From a51a54bc5979a2491f152abc47ad54e6b63f27c8 Mon Sep 17 00:00:00 2001 From: Dylam De La Torre Date: Tue, 23 Nov 2021 05:21:56 +0100 Subject: Restructure source and resource files (#46) importantly, res is now res/res and css is now res/css --- windows/guildsettings/auditlogpane.cpp | 636 --------------------------------- windows/guildsettings/auditlogpane.hpp | 19 - windows/guildsettings/banspane.cpp | 161 --------- windows/guildsettings/banspane.hpp | 45 --- windows/guildsettings/emojispane.cpp | 257 ------------- windows/guildsettings/emojispane.hpp | 53 --- windows/guildsettings/infopane.cpp | 220 ------------ windows/guildsettings/infopane.hpp | 26 -- windows/guildsettings/invitespane.cpp | 136 ------- windows/guildsettings/invitespane.hpp | 43 --- windows/guildsettings/memberspane.cpp | 410 --------------------- windows/guildsettings/memberspane.hpp | 135 ------- windows/guildsettings/rolespane.cpp | 419 ---------------------- windows/guildsettings/rolespane.hpp | 102 ------ 14 files changed, 2662 deletions(-) delete mode 100644 windows/guildsettings/auditlogpane.cpp delete mode 100644 windows/guildsettings/auditlogpane.hpp delete mode 100644 windows/guildsettings/banspane.cpp delete mode 100644 windows/guildsettings/banspane.hpp delete mode 100644 windows/guildsettings/emojispane.cpp delete mode 100644 windows/guildsettings/emojispane.hpp delete mode 100644 windows/guildsettings/infopane.cpp delete mode 100644 windows/guildsettings/infopane.hpp delete mode 100644 windows/guildsettings/invitespane.cpp delete mode 100644 windows/guildsettings/invitespane.hpp delete mode 100644 windows/guildsettings/memberspane.cpp delete mode 100644 windows/guildsettings/memberspane.hpp delete mode 100644 windows/guildsettings/rolespane.cpp delete mode 100644 windows/guildsettings/rolespane.hpp (limited to 'windows/guildsettings') diff --git a/windows/guildsettings/auditlogpane.cpp b/windows/guildsettings/auditlogpane.cpp deleted file mode 100644 index 08f99da..0000000 --- a/windows/guildsettings/auditlogpane.cpp +++ /dev/null @@ -1,636 +0,0 @@ -#include "auditlogpane.hpp" -#include "abaddon.hpp" - -using namespace std::string_literals; - -GuildSettingsAuditLogPane::GuildSettingsAuditLogPane(Snowflake id) - : GuildID(id) { - signal_map().connect(sigc::mem_fun(*this, &GuildSettingsAuditLogPane::OnMap)); - set_name("guild-audit-log-pane"); - set_hexpand(true); - set_vexpand(true); - - m_list.set_selection_mode(Gtk::SELECTION_NONE); - m_list.show(); - add(m_list); -} - -void GuildSettingsAuditLogPane::OnMap() { - if (m_requested) return; - m_requested = true; - - auto &discord = Abaddon::Get().GetDiscordClient(); - const auto self_id = discord.GetUserData().ID; - - if (discord.HasGuildPermission(self_id, GuildID, Permission::VIEW_AUDIT_LOG)) - discord.FetchAuditLog(GuildID, sigc::mem_fun(*this, &GuildSettingsAuditLogPane::OnAuditLogFetch)); -} - -void GuildSettingsAuditLogPane::OnAuditLogFetch(const AuditLogData &data) { - auto &discord = Abaddon::Get().GetDiscordClient(); - auto guild = *discord.GetGuild(GuildID); - for (const auto &entry : data.Entries) { - if (entry.TargetID == "") continue; - - auto expander = Gtk::manage(new Gtk::Expander); - auto label = Gtk::manage(new Gtk::Label); - label->set_ellipsize(Pango::ELLIPSIZE_END); - - Glib::ustring user_markup = "Unknown User"; - if (entry.UserID.has_value()) { - if (auto user = discord.GetUser(*entry.UserID); user.has_value()) - user_markup = discord.GetUser(*entry.UserID)->GetEscapedBoldString(); - } - - // spaghetti moment - Glib::ustring markup; - std::vector extra_markup; - switch (entry.Type) { - case AuditLogActionType::GUILD_UPDATE: { - markup = - user_markup + - " made changes to " + - Glib::Markup::escape_text(guild.Name) + - ""; - - if (entry.Changes.has_value()) - for (const auto &change : *entry.Changes) { - if (change.Key == "icon_hash") { - extra_markup.push_back("Set the server icon"); - } else if (change.Key == "name") { - auto new_name = change.NewValue; - if (new_name.has_value()) - extra_markup.push_back("Set the server name to " + - Glib::Markup::escape_text(new_name->get()) + - ""); - else - extra_markup.push_back("Set the server name"); - } - } - } break; - case AuditLogActionType::CHANNEL_CREATE: { - const auto type = *entry.GetNewFromKey("type"); - markup = user_markup + - " created a " + (type == ChannelType::GUILD_VOICE ? "voice" : "text") + - " channel #" + - Glib::Markup::escape_text(*entry.GetNewFromKey("name")) + - ""; - if (entry.Changes.has_value()) - for (const auto &change : *entry.Changes) { - if (change.Key == "name" && change.NewValue.has_value()) - extra_markup.push_back("Set the name to " + - Glib::Markup::escape_text(change.NewValue->get()) + - ""); - else if (change.Key == "nsfw" && change.NewValue.has_value()) - extra_markup.push_back((*change.NewValue ? "Marked" : "Unmarked") + - " the channel as NSFW"s); - } - - } break; - case AuditLogActionType::CHANNEL_UPDATE: { - const auto target_channel = discord.GetChannel(entry.TargetID); - if (target_channel.has_value()) { - markup = user_markup + - " made changes to #" + - Glib::Markup::escape_text(*target_channel->Name) + - ""; - } else { - markup = user_markup + - " made changes to <#" + - entry.TargetID + - ">"; - } - if (entry.Changes.has_value()) - for (const auto &change : *entry.Changes) { - if (change.Key == "name" && change.NewValue.has_value()) { - if (change.OldValue.has_value()) - extra_markup.push_back("Changed the name from " + - Glib::Markup::escape_text(change.OldValue->get()) + - " to " + - Glib::Markup::escape_text(change.NewValue->get()) + - ""); - else - extra_markup.push_back("Changed the name to " + - Glib::Markup::escape_text(change.NewValue->get()) + - ""); - } else if (change.Key == "topic") { - if (change.NewValue.has_value()) - extra_markup.push_back("Changed the topic to " + - Glib::Markup::escape_text(change.NewValue->get()) + - ""); - else - extra_markup.push_back("Cleared the topic"); - } else if (change.Key == "nsfw" && change.NewValue.has_value()) { - extra_markup.push_back((*change.NewValue ? "Marked" : "Unmarked") + " the channel as NSFW"s); - } else if (change.Key == "rate_limit_per_user" && change.NewValue.has_value()) { - const int secs = change.NewValue->get(); - if (secs == 0) - extra_markup.push_back("Disabled slowmode"); - else - extra_markup.push_back("Set slowmode to " + - std::to_string(secs) + " seconds"); - } - } - } break; - case AuditLogActionType::CHANNEL_DELETE: { - markup = user_markup + - " removed #" + - Glib::Markup::escape_text(*entry.GetOldFromKey("name")) + - ""; - } break; - case AuditLogActionType::CHANNEL_OVERWRITE_CREATE: { - const auto channel = discord.GetChannel(entry.TargetID); - if (channel.has_value()) { - markup = user_markup + - " created channel overrides for #" + - Glib::Markup::escape_text(*channel->Name) + ""; - } else { - markup = user_markup + - " created channel overrides for <#" + - entry.TargetID + ">"; - } - } break; - case AuditLogActionType::CHANNEL_OVERWRITE_UPDATE: { - const auto channel = discord.GetChannel(entry.TargetID); - if (channel.has_value()) { - markup = user_markup + - " updated channel overrides for #" + - Glib::Markup::escape_text(*channel->Name) + ""; - } else { - markup = user_markup + - " updated channel overrides for <#" + - entry.TargetID + ">"; - } - } break; - case AuditLogActionType::CHANNEL_OVERWRITE_DELETE: { - const auto channel = discord.GetChannel(entry.TargetID); - if (channel.has_value()) { - markup = user_markup + - " removed channel overrides for #" + - Glib::Markup::escape_text(*channel->Name) + ""; - } else { - markup = user_markup + - " removed channel overrides for <#" + - entry.TargetID + ">"; - } - } break; - case AuditLogActionType::MEMBER_KICK: { - const auto target_user = discord.GetUser(entry.TargetID); - markup = user_markup + - " kicked " + - target_user->GetEscapedString() + - ""; - } break; - case AuditLogActionType::MEMBER_PRUNE: { - markup = user_markup + - " pruned " + - *entry.Options->MembersRemoved + - " members"; - extra_markup.push_back("For " + - *entry.Options->DeleteMemberDays + - " days of inactivity"); - } break; - case AuditLogActionType::MEMBER_BAN_ADD: { - const auto target_user = discord.GetUser(entry.TargetID); - markup = user_markup + - " banned " + - target_user->GetEscapedString() + - ""; - } break; - case AuditLogActionType::MEMBER_BAN_REMOVE: { - const auto target_user = discord.GetUser(entry.TargetID); - markup = user_markup + - " removed the ban for " + - target_user->GetEscapedString() + - ""; - } break; - case AuditLogActionType::MEMBER_UPDATE: { - const auto target_user = discord.GetUser(entry.TargetID); - markup = user_markup + - " updated " + - target_user->GetEscapedString() + - ""; - if (entry.Changes.has_value()) - for (const auto &change : *entry.Changes) { - if (change.Key == "deaf" && change.NewValue.has_value()) - extra_markup.push_back( - (change.NewValue->get() ? "Deafened"s : "Undeafened"s) + - " them"); - else if (change.Key == "mute" && change.NewValue.has_value()) - extra_markup.push_back( - (change.NewValue->get() ? "Muted"s : "Unmuted"s) + - " them"); - else if (change.Key == "nick" && change.NewValue.has_value()) - extra_markup.push_back("Set their nickname to " + - Glib::Markup::escape_text(change.NewValue->get()) + - ""); - } - } break; - case AuditLogActionType::MEMBER_ROLE_UPDATE: { - const auto target_user = discord.GetUser(entry.TargetID); - markup = user_markup + - " updated roles for " + - target_user->GetEscapedString() + ""; - if (entry.Changes.has_value()) - for (const auto &change : *entry.Changes) { - if (change.Key == "$remove" && change.NewValue.has_value()) { - extra_markup.push_back("Removed a role " + - Glib::Markup::escape_text(change.NewValue.value()[0].at("name").get()) + - ""); - } else if (change.Key == "$add" && change.NewValue.has_value()) { - extra_markup.push_back("Added a role " + - Glib::Markup::escape_text(change.NewValue.value()[0].at("name").get()) + - ""); - } - } - } break; - case AuditLogActionType::MEMBER_MOVE: { - const auto channel = discord.GetChannel(*entry.Options->ChannelID); - markup = user_markup + - " moved " + - *entry.Options->Count + - " user" + - (*entry.Options->Count == "1" ? ""s : "s"s) + - " to " + - Glib::Markup::escape_text(*channel->Name) + - ""; - } break; - case AuditLogActionType::MEMBER_DISCONNECT: { - markup = user_markup + - " disconnected " + - *entry.Options->Count + - " users from voice"; - } break; - case AuditLogActionType::BOT_ADD: { - const auto target_user = discord.GetUser(entry.TargetID); - markup = user_markup + - " added " + - target_user->GetEscapedString() + - " to the server"; - } break; - case AuditLogActionType::ROLE_CREATE: { - markup = user_markup + - " created the role " + - *entry.GetNewFromKey("name") + - ""; - } break; - case AuditLogActionType::ROLE_UPDATE: { - const auto role = discord.GetRole(entry.TargetID); - markup = user_markup + - " updated the role " + - (role.has_value() ? Glib::Markup::escape_text(role->Name) : Glib::ustring(entry.TargetID)) + - ""; - if (entry.Changes.has_value()) - for (const auto &change : *entry.Changes) { - if (change.Key == "name" && change.NewValue.has_value()) { - extra_markup.push_back("Changed the name to " + - Glib::Markup::escape_text(change.NewValue->get()) + - ""); - } else if (change.Key == "color" && change.NewValue.has_value()) { - const auto col = change.NewValue->get(); - if (col == 0) - extra_markup.push_back("Removed the color"); - else - extra_markup.push_back("Set the color to " + - IntToCSSColor(col) + - ""); - } else if (change.Key == "permissions") { - extra_markup.push_back("Updated the permissions"); - } else if (change.Key == "mentionable" && change.NewValue.has_value()) { - extra_markup.push_back(change.NewValue->get() ? "Mentionable" : "Not mentionable"); - } else if (change.Key == "hoist" && change.NewValue.has_value()) { - extra_markup.push_back(change.NewValue->get() ? "Not hoisted" : "Hoisted"); - } - } - } break; - case AuditLogActionType::ROLE_DELETE: { - markup = user_markup + - " deleted the role " + - *entry.GetOldFromKey("name") + - ""; - } break; - case AuditLogActionType::INVITE_CREATE: { - const auto code = *entry.GetNewFromKey("code"); - markup = user_markup + - " created an invite " + code + ""; - if (entry.Changes.has_value()) - for (const auto &change : *entry.Changes) { - if (change.Key == "channel_id" && change.NewValue.has_value()) { - const auto channel = discord.GetChannel(change.NewValue->get()); - if (!channel.has_value()) continue; - extra_markup.push_back("For channel #" + - Glib::Markup::escape_text(*channel->Name) + - ""); - } else if (change.Key == "max_uses" && change.NewValue.has_value()) { - const auto uses = change.NewValue->get(); - if (uses == 0) - extra_markup.push_back("Which has unlimited uses"); - else - extra_markup.push_back("Which has " + std::to_string(uses) + " uses"); - } else if (change.Key == "temporary" && change.NewValue.has_value()) { - extra_markup.push_back("With temporary "s + - (change.NewValue->get() ? "on" : "off") + - ""); - } // no max_age cuz fuck time - } - } break; - case AuditLogActionType::INVITE_DELETE: { - markup = user_markup + - " deleted an invite " + - *entry.GetOldFromKey("code") + - ""; - } break; - case AuditLogActionType::WEBHOOK_CREATE: { - markup = user_markup + - " created the webhook " + - Glib::Markup::escape_text(*entry.GetNewFromKey("name")) + - ""; - for (const auto &change : *entry.Changes) { - if (change.Key == "channel_id" && change.NewValue.has_value()) { - const auto channel = discord.GetChannel(change.NewValue->get()); - if (channel.has_value()) { - extra_markup.push_back("With channel #" + - Glib::Markup::escape_text(*channel->Name) + - ""); - } - } - } - } break; - case AuditLogActionType::WEBHOOK_UPDATE: { - const WebhookData *webhookptr = nullptr; - for (const auto &webhook : data.Webhooks) { - if (webhook.ID == entry.TargetID) - webhookptr = &webhook; - } - if (webhookptr != nullptr) { - markup = user_markup + - " updated the webhook " + - Glib::Markup::escape_text(webhookptr->Name) + - ""; - } else { - markup = user_markup + - " updated a webhook"; - } - if (entry.Changes.has_value()) - for (const auto &change : *entry.Changes) { - if (change.Key == "name" && change.NewValue.has_value()) { - extra_markup.push_back("Changed the name to " + - Glib::Markup::escape_text(change.NewValue->get()) + - ""); - } else if (change.Key == "avatar_hash") { - extra_markup.push_back("Changed the avatar"); - } else if (change.Key == "channel_id" && change.NewValue.has_value()) { - const auto channel = discord.GetChannel(change.NewValue->get()); - if (channel.has_value()) { - extra_markup.push_back("Changed the channel to #" + - Glib::Markup::escape_text(*channel->Name) + - ""); - } else { - extra_markup.push_back("Changed the channel"); - } - } - } - } break; - case AuditLogActionType::WEBHOOK_DELETE: { - markup = user_markup + - " deleted the webhook " + - Glib::Markup::escape_text(*entry.GetOldFromKey("name")) + - ""; - } break; - case AuditLogActionType::EMOJI_CREATE: { - markup = user_markup + - " created the emoji " + - Glib::Markup::escape_text(*entry.GetNewFromKey("name")) + - ""; - } break; - case AuditLogActionType::EMOJI_UPDATE: { - markup = user_markup + - " updated the emoji " + - Glib::Markup::escape_text(*entry.GetOldFromKey("name")) + - ""; - extra_markup.push_back("Changed the name from " + - Glib::Markup::escape_text(*entry.GetOldFromKey("name")) + - " to " + - Glib::Markup::escape_text(*entry.GetNewFromKey("name")) + - ""); - } break; - case AuditLogActionType::EMOJI_DELETE: { - markup = user_markup + - " deleted the emoji " + - Glib::Markup::escape_text(*entry.GetOldFromKey("name")) + - ""; - } break; - case AuditLogActionType::MESSAGE_DELETE: { - const auto channel = discord.GetChannel(*entry.Options->ChannelID); - const auto count = *entry.Options->Count; - if (channel.has_value()) { - markup = user_markup + - " deleted " + count + " messages in #" + - Glib::Markup::escape_text(*channel->Name) + - ""; - } else { - markup = user_markup + - " deleted " + count + " messages"; - } - } break; - case AuditLogActionType::MESSAGE_BULK_DELETE: { - const auto channel = discord.GetChannel(entry.TargetID); - if (channel.has_value()) { - markup = user_markup + - " deleted " + - *entry.Options->Count + - " messages in #" + - Glib::Markup::escape_text(*channel->Name) + - ""; - } else { - markup = user_markup + - " deleted " + - *entry.Options->Count + - " messages"; - } - } break; - case AuditLogActionType::MESSAGE_PIN: { - const auto target_user = discord.GetUser(entry.TargetID); - markup = user_markup + - " pinned a message by " + - target_user->GetEscapedString() + - ""; - } break; - case AuditLogActionType::MESSAGE_UNPIN: { - const auto target_user = discord.GetUser(entry.TargetID); - markup = user_markup + - " unpinned a message by " + - target_user->GetEscapedString() + - ""; - } break; - case AuditLogActionType::STAGE_INSTANCE_CREATE: { - const auto channel = discord.GetChannel(*entry.Options->ChannelID); - if (channel.has_value()) { - markup = user_markup + - " started the stage for " + - Glib::Markup::escape_text(*channel->Name) + - ""; - } else { - markup = user_markup + - " started the stage for " + - std::to_string(*entry.Options->ChannelID) + - ""; - } - - if (entry.Changes.has_value()) { - for (const auto &change : *entry.Changes) { - if (change.Key == "topic" && change.NewValue.has_value()) { - extra_markup.push_back( - "Set the topic to " + - Glib::Markup::escape_text(change.NewValue->get()) + - ""); - } else if (change.Key == "privacy_level" && change.NewValue.has_value()) { - Glib::ustring str = Glib::Markup::escape_text(GetStagePrivacyDisplayString(change.NewValue->get())); - extra_markup.push_back( - "Set the privacy level to " + - str + - ""); - } - } - } - } break; - case AuditLogActionType::STAGE_INSTANCE_UPDATE: { - const auto channel = discord.GetChannel(*entry.Options->ChannelID); - if (channel.has_value()) { - markup = user_markup + - " updated the stage for " + - Glib::Markup::escape_text(*channel->Name) + - ""; - } else { - markup = user_markup + - " updated the stage for " + - std::to_string(*entry.Options->ChannelID) + - ""; - } - - if (entry.Changes.has_value()) { - for (const auto &change : *entry.Changes) { - if (change.Key == "topic" && change.NewValue.has_value()) { - extra_markup.push_back( - "Set the topic to " + - Glib::Markup::escape_text(change.NewValue->get()) + - ""); - } else if (change.Key == "privacy_level" && change.NewValue.has_value()) { - Glib::ustring str = Glib::Markup::escape_text(GetStagePrivacyDisplayString(change.NewValue->get())); - extra_markup.push_back( - "Set the privacy level to " + - str + - ""); - } - } - } - } break; - case AuditLogActionType::STAGE_INSTANCE_DELETE: { - const auto channel = discord.GetChannel(*entry.Options->ChannelID); - if (channel.has_value()) { - markup = user_markup + - " ended the stage for " + - Glib::Markup::escape_text(*channel->Name) + - ""; - } else { - markup = user_markup + - " ended the stage for " + - std::to_string(*entry.Options->ChannelID) + - ""; - } - } break; - case AuditLogActionType::THREAD_CREATE: { - const auto channel = discord.GetChannel(entry.TargetID); - markup = user_markup + - " created a thread " + - (channel.has_value() - ? Glib::Markup::escape_text(*channel->Name) - : Glib::ustring(*entry.GetNewFromKey("name"))) + - ""; - if (entry.Changes.has_value()) { - for (const auto &change : *entry.Changes) { - if (change.Key == "name") - extra_markup.push_back("Set the name to " + Glib::Markup::escape_text(change.NewValue->get()) + ""); - else if (change.Key == "archived") - extra_markup.push_back(change.NewValue->get() ? "Archived the thread" : "Unarchived the thread"); - else if (change.Key == "auto_archive_duration") - extra_markup.push_back("Set auto archive duration to "s + std::to_string(change.NewValue->get()) + " minutes"s); - else if (change.Key == "rate_limit_per_user" && change.NewValue.has_value()) { - const int secs = change.NewValue->get(); - if (secs == 0) - extra_markup.push_back("Disabled slowmode"); - else - extra_markup.push_back("Set slowmode to " + - std::to_string(secs) + " seconds"); - } else if (change.Key == "locked") - extra_markup.push_back(change.NewValue->get() ? "Locked the thread, restricting it to only be unarchived by moderators" : "Unlocked the thread, allowing it to be unarchived by non-moderators"); - } - } - } break; - case AuditLogActionType::THREAD_UPDATE: { - const auto channel = discord.GetChannel(entry.TargetID); - markup = user_markup + - " made changes to the thread " + - (channel.has_value() - ? Glib::Markup::escape_text(*channel->Name) - : Glib::ustring(entry.TargetID)) + - ""; - for (const auto &change : *entry.Changes) { - if (change.Key == "name") - extra_markup.push_back( - "Changed the name from " + - Glib::Markup::escape_text(change.OldValue->get()) + - " to " + - Glib::Markup::escape_text(change.NewValue->get()) + - ""); - else if (change.Key == "auto_archive_duration") - extra_markup.push_back("Set auto archive duration to "s + std::to_string(change.NewValue->get()) + " minutes"s); - else if (change.Key == "rate_limit_per_user" && change.NewValue.has_value()) { - const int secs = change.NewValue->get(); - if (secs == 0) - extra_markup.push_back("Disabled slowmode"); - else - extra_markup.push_back("Set slowmode to " + - std::to_string(secs) + - " seconds"); - } else if (change.Key == "locked") - extra_markup.push_back(change.NewValue->get() ? "Locked the thread, restricting it to only be unarchived by moderators" : "Unlocked the thread, allowing it to be unarchived by non-moderators"); - else if (change.Key == "archived") - extra_markup.push_back(change.NewValue->get() ? "Archived the thread" : "Unarchived the thread"); - } - } break; - case AuditLogActionType::THREAD_DELETE: { - markup = user_markup + - " deleted the thread " + Glib::Markup::escape_text(*entry.GetOldFromKey("name")) + ""; - } break; - default: - markup = "Unknown action"; - break; - } - - label->set_markup(markup); - expander->set_label_widget(*label); - - if (entry.Reason.has_value()) { - extra_markup.push_back("With reason " + - Glib::Markup::escape_text(*entry.Reason) + - ""); - } - - expander->set_expanded(true); - - auto contents = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL)); - for (const auto &extra : extra_markup) { - auto extra_label = Gtk::manage(new Gtk::Label); - extra_label->set_markup(extra); - extra_label->set_halign(Gtk::ALIGN_START); - extra_label->set_margin_start(25); - extra_label->set_ellipsize(Pango::ELLIPSIZE_END); - contents->add(*extra_label); - } - expander->add(*contents); - expander->set_margin_bottom(5); - expander->show_all(); - m_list.add(*expander); - } -} diff --git a/windows/guildsettings/auditlogpane.hpp b/windows/guildsettings/auditlogpane.hpp deleted file mode 100644 index ac12321..0000000 --- a/windows/guildsettings/auditlogpane.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include -#include "discord/objects.hpp" - -class GuildSettingsAuditLogPane : public Gtk::ScrolledWindow { -public: - GuildSettingsAuditLogPane(Snowflake id); - -private: - void OnMap(); - - bool m_requested = false; - - Gtk::ListBox m_list; - - void OnAuditLogFetch(const AuditLogData &data); - - Snowflake GuildID; -}; diff --git a/windows/guildsettings/banspane.cpp b/windows/guildsettings/banspane.cpp deleted file mode 100644 index 97a70c4..0000000 --- a/windows/guildsettings/banspane.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "banspane.hpp" -#include "abaddon.hpp" - -// gtk_list_store_set_value: assertion 'column >= 0 && column < priv->n_columns' failed -// dont care to figure out why this happens cuz it doesnt seem to break anything - -GuildSettingsBansPane::GuildSettingsBansPane(Snowflake id) - : Gtk::Box(Gtk::ORIENTATION_VERTICAL) - , GuildID(id) - , m_model(Gtk::ListStore::create(m_columns)) - , m_menu_unban("Unban") - , m_menu_copy_id("Copy ID") { - signal_map().connect(sigc::mem_fun(*this, &GuildSettingsBansPane::OnMap)); - set_name("guild-bans-pane"); - set_hexpand(true); - set_vexpand(true); - - auto &discord = Abaddon::Get().GetDiscordClient(); - - discord.signal_guild_ban_add().connect(sigc::mem_fun(*this, &GuildSettingsBansPane::OnBanAdd)); - discord.signal_guild_ban_remove().connect(sigc::mem_fun(*this, &GuildSettingsBansPane::OnBanRemove)); - - const auto self_id = discord.GetUserData().ID; - const auto can_ban = discord.HasGuildPermission(self_id, GuildID, Permission::BAN_MEMBERS); - - if (!can_ban) { - for (const auto &ban : discord.GetBansInGuild(id)) - OnGuildBanFetch(ban); - - m_no_perms_note = Gtk::manage(new Gtk::Label("You do not have permission to see bans. However, bans made while you are connected will appear here")); - m_no_perms_note->set_single_line_mode(true); - m_no_perms_note->set_ellipsize(Pango::ELLIPSIZE_END); - m_no_perms_note->set_halign(Gtk::ALIGN_START); - add(*m_no_perms_note); - } - - m_menu_unban.signal_activate().connect(sigc::mem_fun(*this, &GuildSettingsBansPane::OnMenuUnban)); - m_menu_copy_id.signal_activate().connect(sigc::mem_fun(*this, &GuildSettingsBansPane::OnMenuCopyID)); - m_menu_unban.show(); - m_menu_copy_id.show(); - m_menu.append(m_menu_unban); - m_menu.append(m_menu_copy_id); - - m_view.signal_button_press_event().connect(sigc::mem_fun(*this, &GuildSettingsBansPane::OnTreeButtonPress), false); - m_view.show(); - - m_scroll.set_propagate_natural_height(true); - m_scroll.add(m_view); - add(m_scroll); - show_all_children(); - - m_view.set_enable_search(false); - m_view.set_model(m_model); - m_view.append_column("User", m_columns.m_col_user); - m_view.append_column("Reason", m_columns.m_col_reason); -} - -void GuildSettingsBansPane::OnMap() { - if (m_requested) return; - m_requested = true; - - auto &discord = Abaddon::Get().GetDiscordClient(); - - const auto self_id = discord.GetUserData().ID; - const auto can_ban = discord.HasGuildPermission(self_id, GuildID, Permission::BAN_MEMBERS); - - if (can_ban) - discord.FetchGuildBans(GuildID, sigc::mem_fun(*this, &GuildSettingsBansPane::OnGuildBansFetch)); -} - -void GuildSettingsBansPane::OnGuildBanFetch(const BanData &ban) { - const auto user = Abaddon::Get().GetDiscordClient().GetUser(ban.User.ID); - auto row = *m_model->append(); - row[m_columns.m_col_id] = ban.User.ID; - if (user.has_value()) - row[m_columns.m_col_user] = user->Username + "#" + user->Discriminator; - else - row[m_columns.m_col_user] = "<@" + std::to_string(ban.User.ID) + ">"; - - row[m_columns.m_col_reason] = ban.Reason; -} - -void GuildSettingsBansPane::OnGuildBansFetch(const std::vector &bans) { - for (const auto &ban : bans) { - const auto user = Abaddon::Get().GetDiscordClient().GetUser(ban.User.ID); - auto row = *m_model->append(); - row[m_columns.m_col_id] = user->ID; - row[m_columns.m_col_user] = user->Username + "#" + user->Discriminator; - row[m_columns.m_col_reason] = ban.Reason; - } -} - -void GuildSettingsBansPane::OnMenuUnban() { - auto selected_row = *m_view.get_selection()->get_selected(); - if (selected_row) { - Snowflake id = selected_row[m_columns.m_col_id]; - auto cb = [this](DiscordError code) { - if (code != DiscordError::NONE) { - Gtk::MessageDialog dlg("Failed to unban user", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - dlg.set_position(Gtk::WIN_POS_CENTER); - dlg.run(); - } - }; - Abaddon::Get().GetDiscordClient().UnbanUser(GuildID, id, sigc::track_obj(cb, *this)); - } -} - -void GuildSettingsBansPane::OnMenuCopyID() { - auto selected_row = *m_view.get_selection()->get_selected(); - if (selected_row) - Gtk::Clipboard::get()->set_text(std::to_string(static_cast(selected_row[m_columns.m_col_id]))); -} - -bool GuildSettingsBansPane::OnTreeButtonPress(GdkEventButton *event) { - if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_SECONDARY) { - auto &discord = Abaddon::Get().GetDiscordClient(); - const auto self_id = discord.GetUserData().ID; - const auto can_ban = discord.HasGuildPermission(self_id, GuildID, Permission::BAN_MEMBERS); - m_menu_unban.set_sensitive(can_ban); - auto selection = m_view.get_selection(); - Gtk::TreeModel::Path path; - if (m_view.get_path_at_pos(event->x, event->y, path)) { - m_view.get_selection()->select(path); - m_menu.popup_at_pointer(reinterpret_cast(event)); - } - - return true; - } - - return false; -} - -void GuildSettingsBansPane::OnBanRemove(Snowflake guild_id, Snowflake user_id) { - if (guild_id != GuildID) return; - for (auto &child : m_model->children()) { - if (static_cast(child[m_columns.m_col_id]) == user_id) { - m_model->erase(child); - break; - } - } -} - -void GuildSettingsBansPane::OnBanAdd(Snowflake guild_id, Snowflake user_id) { - if (guild_id != GuildID) return; - auto &discord = Abaddon::Get().GetDiscordClient(); - if (discord.HasGuildPermission(discord.GetUserData().ID, guild_id, Permission::BAN_MEMBERS)) { - discord.FetchGuildBan(guild_id, user_id, sigc::mem_fun(*this, &GuildSettingsBansPane::OnGuildBanFetch)); - } else { - auto user = *discord.GetUser(user_id); - auto row = *m_model->append(); - row[m_columns.m_col_id] = user_id; - row[m_columns.m_col_user] = user.Username + "#" + user.Discriminator; - row[m_columns.m_col_reason] = ""; - } -} - -GuildSettingsBansPane::ModelColumns::ModelColumns() { - add(m_col_id); - add(m_col_user); - add(m_col_reason); -} diff --git a/windows/guildsettings/banspane.hpp b/windows/guildsettings/banspane.hpp deleted file mode 100644 index b2420a9..0000000 --- a/windows/guildsettings/banspane.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once -#include -#include "discord/snowflake.hpp" -#include "discord/ban.hpp" - -class GuildSettingsBansPane : public Gtk::Box { -public: - GuildSettingsBansPane(Snowflake id); - -private: - void OnMap(); - - bool m_requested = false; - - void OnGuildBanFetch(const BanData &ban); - void OnGuildBansFetch(const std::vector &bans); - void OnMenuUnban(); - void OnMenuCopyID(); - bool OnTreeButtonPress(GdkEventButton *event); - void OnBanRemove(Snowflake guild_id, Snowflake user_id); - void OnBanAdd(Snowflake guild_id, Snowflake user_id); - - Gtk::Label *m_no_perms_note = nullptr; - - Gtk::ScrolledWindow m_scroll; - Gtk::TreeView m_view; - - Snowflake GuildID; - - class ModelColumns : public Gtk::TreeModel::ColumnRecord { - public: - ModelColumns(); - - Gtk::TreeModelColumn m_col_user; - Gtk::TreeModelColumn m_col_reason; - Gtk::TreeModelColumn m_col_id; - }; - - ModelColumns m_columns; - Glib::RefPtr m_model; - - Gtk::Menu m_menu; - Gtk::MenuItem m_menu_unban; - Gtk::MenuItem m_menu_copy_id; -}; diff --git a/windows/guildsettings/emojispane.cpp b/windows/guildsettings/emojispane.cpp deleted file mode 100644 index 1f4bfa9..0000000 --- a/windows/guildsettings/emojispane.cpp +++ /dev/null @@ -1,257 +0,0 @@ -#include "emojispane.hpp" -#include "abaddon.hpp" -#include "components/cellrendererpixbufanimation.hpp" - -GuildSettingsEmojisPane::GuildSettingsEmojisPane(Snowflake guild_id) - : Gtk::Box(Gtk::ORIENTATION_VERTICAL) - , GuildID(guild_id) - , m_model(Gtk::ListStore::create(m_columns)) - , m_filter(Gtk::TreeModelFilter::create(m_model)) - , m_menu_delete("Delete") - , m_menu_copy_id("Copy ID") - , m_menu_copy_emoji_url("Copy Emoji URL") - , m_menu_show_emoji("Open in Browser") { - signal_map().connect(sigc::mem_fun(*this, &GuildSettingsEmojisPane::OnMap)); - set_name("guild-emojis-pane"); - - m_view_scroll.set_hexpand(true); - m_view_scroll.set_vexpand(true); - - m_view.signal_button_press_event().connect(sigc::mem_fun(*this, &GuildSettingsEmojisPane::OnTreeButtonPress), false); - - m_menu_copy_id.signal_activate().connect(sigc::mem_fun(*this, &GuildSettingsEmojisPane::OnMenuCopyID)); - m_menu_delete.signal_activate().connect(sigc::mem_fun(*this, &GuildSettingsEmojisPane::OnMenuDelete)); - m_menu_copy_emoji_url.signal_activate().connect(sigc::mem_fun(*this, &GuildSettingsEmojisPane::OnMenuCopyEmojiURL)); - m_menu_show_emoji.signal_activate().connect(sigc::mem_fun(*this, &GuildSettingsEmojisPane::OnMenuShowEmoji)); - - m_menu.append(m_menu_delete); - m_menu.append(m_menu_copy_id); - m_menu.append(m_menu_copy_emoji_url); - m_menu.append(m_menu_show_emoji); - m_menu.show_all(); - - auto &discord = Abaddon::Get().GetDiscordClient(); - - discord.signal_guild_emojis_update().connect(sigc::hide<0>(sigc::mem_fun(*this, &GuildSettingsEmojisPane::OnFetchEmojis))); - - const auto self_id = discord.GetUserData().ID; - const bool can_manage = discord.HasGuildPermission(self_id, GuildID, Permission::MANAGE_EMOJIS); - m_menu_delete.set_sensitive(can_manage); - - m_search.set_placeholder_text("Filter"); - m_search.signal_changed().connect([this]() { - m_filter->refilter(); - }); - - m_view_scroll.add(m_view); - add(m_search); - add(m_view_scroll); - m_search.show(); - m_view.show(); - m_view_scroll.show(); - - m_filter->set_visible_func([this](const Gtk::TreeModel::const_iterator &iter) -> bool { - const auto text = m_search.get_text(); - if (text == "") return true; - return StringContainsCaseless((*iter)[m_columns.m_col_name], text); - }); - m_view.set_enable_search(false); - m_view.set_model(m_filter); - - auto *column = Gtk::manage(new Gtk::TreeView::Column("Emoji")); - auto *renderer = Gtk::manage(new CellRendererPixbufAnimation); - column->pack_start(*renderer); - column->add_attribute(renderer->property_pixbuf(), m_columns.m_col_pixbuf); - column->add_attribute(renderer->property_pixbuf_animation(), m_columns.m_col_pixbuf_animation); - m_view.append_column(*column); - - if (can_manage) { - auto *column = Gtk::manage(new Gtk::TreeView::Column("Name")); - auto *renderer = Gtk::manage(new Gtk::CellRendererText); - column->pack_start(*renderer); - column->add_attribute(renderer->property_text(), m_columns.m_col_name); - renderer->property_editable() = true; - renderer->signal_edited().connect([this, renderer, column](const Glib::ustring &path, const Glib::ustring &text) { - std::string new_str; - int size = 0; - for (const auto ch : text) { - if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_') - new_str += ch; - else if (ch == ' ') - new_str += '_'; - if (++size == 32) break; - } - if (auto row = *m_model->get_iter(path)) { - row[m_columns.m_col_name] = new_str; - OnEditName(row[m_columns.m_col_id], new_str); - } - }); - m_view.append_column(*column); - } else - m_view.append_column("Name", m_columns.m_col_name); - if (can_manage) - m_view.append_column("Creator", m_columns.m_col_creator); - m_view.append_column("Is Animated?", m_columns.m_col_animated); - - for (const auto column : m_view.get_columns()) - column->set_resizable(true); -} - -void GuildSettingsEmojisPane::OnMap() { - m_view.grab_focus(); - - if (m_requested) return; - m_requested = true; - - auto &discord = Abaddon::Get().GetDiscordClient(); - const auto self_id = discord.GetUserData().ID; - const bool can_manage = discord.HasGuildPermission(self_id, GuildID, Permission::MANAGE_EMOJIS); - m_menu_delete.set_sensitive(can_manage); - - discord.FetchGuildEmojis(GuildID, sigc::mem_fun(*this, &GuildSettingsEmojisPane::OnFetchEmojis)); -} - -void GuildSettingsEmojisPane::AddEmojiRow(const EmojiData &emoji) { - auto &img = Abaddon::Get().GetImageManager(); - - auto row = *m_model->append(); - - row[m_columns.m_col_id] = emoji.ID; - row[m_columns.m_col_pixbuf] = img.GetPlaceholder(32); - row[m_columns.m_col_name] = emoji.Name; - if (emoji.Creator.has_value()) - row[m_columns.m_col_creator] = emoji.Creator->Username + "#" + emoji.Creator->Discriminator; - if (emoji.IsAnimated.has_value()) - row[m_columns.m_col_animated] = *emoji.IsAnimated ? "Yes" : "No"; - else - row[m_columns.m_col_animated] = "No"; - if (emoji.IsAvailable.has_value()) - row[m_columns.m_col_available] = *emoji.IsAvailable ? "Yes" : "No"; - else - row[m_columns.m_col_available] = "Yes"; - - static bool show_animations = Abaddon::Get().GetSettings().GetShowAnimations(); - if (show_animations && emoji.IsAnimated.has_value() && *emoji.IsAnimated) { - const auto cb = [this, id = emoji.ID](const Glib::RefPtr &pb) { - for (auto &row : m_model->children()) { - if (static_cast(row[m_columns.m_col_id]) == id) { - row[m_columns.m_col_pixbuf_animation] = pb; - return; - } - } - }; - img.LoadAnimationFromURL(emoji.GetURL("gif"), 32, 32, sigc::track_obj(cb, *this)); - } else { - const auto cb = [this, id = emoji.ID](const Glib::RefPtr &pb) { - for (auto &row : m_model->children()) { - if (static_cast(row[m_columns.m_col_id]) == id) { - row[m_columns.m_col_pixbuf] = pb->scale_simple(32, 32, Gdk::INTERP_BILINEAR); - return; - } - } - }; - img.LoadFromURL(emoji.GetURL(), sigc::track_obj(cb, *this)); - } -} - -void GuildSettingsEmojisPane::OnFetchEmojis(std::vector emojis) { - m_model->clear(); - - // put animated emojis at the end then sort alphabetically - std::sort(emojis.begin(), emojis.end(), [&](const EmojiData &a, const EmojiData &b) { - const bool a_is_animated = a.IsAnimated.has_value() && *a.IsAnimated; - const bool b_is_animated = b.IsAnimated.has_value() && *b.IsAnimated; - if (a_is_animated == b_is_animated) - return a.Name < b.Name; - else if (a_is_animated && !b_is_animated) - return false; - else if (!a_is_animated && b_is_animated) - return true; - return false; // this wont happen please be quiet compiler - }); - - for (const auto &emoji : emojis) - AddEmojiRow(emoji); -} - -void GuildSettingsEmojisPane::OnEditName(Snowflake id, const std::string &name) { - const auto cb = [this](DiscordError code) { - if (code != DiscordError::NONE) { - Gtk::MessageDialog dlg("Failed to set emoji name", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK); - dlg.set_position(Gtk::WIN_POS_CENTER); - dlg.run(); - } - }; - Abaddon::Get().GetDiscordClient().ModifyEmojiName(GuildID, id, name, cb); -} - -void GuildSettingsEmojisPane::OnMenuCopyID() { - if (auto selected_row = *m_view.get_selection()->get_selected()) { - const auto id = static_cast(selected_row[m_columns.m_col_id]); - Gtk::Clipboard::get()->set_text(std::to_string(id)); - } -} - -void GuildSettingsEmojisPane::OnMenuDelete() { - if (auto selected_row = *m_view.get_selection()->get_selected()) { - const auto name = static_cast(selected_row[m_columns.m_col_name]); - const auto id = static_cast(selected_row[m_columns.m_col_id]); - if (auto *window = dynamic_cast(get_toplevel())) - if (Abaddon::Get().ShowConfirm("Are you sure you want to delete " + name + "?", window)) { - const auto cb = [this](DiscordError code) { - if (code != DiscordError::NONE) { - Gtk::MessageDialog dlg("Failed to delete emoji", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK); - dlg.set_position(Gtk::WIN_POS_CENTER); - dlg.run(); - } - }; - Abaddon::Get().GetDiscordClient().DeleteEmoji(GuildID, id, cb); - } - } -} - -void GuildSettingsEmojisPane::OnMenuCopyEmojiURL() { - if (auto selected_row = *m_view.get_selection()->get_selected()) { - const auto id = static_cast(selected_row[m_columns.m_col_id]); - const bool is_animated = static_cast(selected_row[m_columns.m_col_animated]) == "Yes"; - Gtk::Clipboard::get()->set_text(EmojiData::URLFromID(id, is_animated ? "gif" : "png", "256")); - } -} - -void GuildSettingsEmojisPane::OnMenuShowEmoji() { - if (auto selected_row = *m_view.get_selection()->get_selected()) { - const auto id = static_cast(selected_row[m_columns.m_col_id]); - const bool is_animated = static_cast(selected_row[m_columns.m_col_animated]) == "Yes"; - LaunchBrowser(EmojiData::URLFromID(id, is_animated ? "gif" : "png", "256")); - } -} - -bool GuildSettingsEmojisPane::OnTreeButtonPress(GdkEventButton *event) { - if (event->button == GDK_BUTTON_SECONDARY) { - auto &discord = Abaddon::Get().GetDiscordClient(); - const auto self_id = discord.GetUserData().ID; - const bool can_manage = discord.HasGuildPermission(self_id, GuildID, Permission::MANAGE_EMOJIS); - m_menu_delete.set_sensitive(can_manage); - - auto selection = m_view.get_selection(); - Gtk::TreeModel::Path path; - if (m_view.get_path_at_pos(event->x, event->y, path)) { - m_view.get_selection()->select(path); - m_menu.popup_at_pointer(reinterpret_cast(event)); - } - - return true; - } - - return false; -} - -GuildSettingsEmojisPane::ModelColumns::ModelColumns() { - add(m_col_id); - add(m_col_pixbuf); - add(m_col_pixbuf_animation); - add(m_col_name); - add(m_col_creator); - add(m_col_animated); - add(m_col_available); -} diff --git a/windows/guildsettings/emojispane.hpp b/windows/guildsettings/emojispane.hpp deleted file mode 100644 index 1c0edd1..0000000 --- a/windows/guildsettings/emojispane.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once -#include -#include "discord/emoji.hpp" - -class GuildSettingsEmojisPane : public Gtk::Box { -public: - GuildSettingsEmojisPane(Snowflake guild_id); - -private: - void OnMap(); - - bool m_requested = false; - - void AddEmojiRow(const EmojiData &emoji); - - void OnFetchEmojis(std::vector emojis); - - void OnEditName(Snowflake id, const std::string &name); - void OnMenuCopyID(); - void OnMenuDelete(); - void OnMenuCopyEmojiURL(); - void OnMenuShowEmoji(); - bool OnTreeButtonPress(GdkEventButton *event); - - Snowflake GuildID; - - Gtk::Entry m_search; - Gtk::ScrolledWindow m_view_scroll; - Gtk::TreeView m_view; - - class ModelColumns : public Gtk::TreeModel::ColumnRecord { - public: - ModelColumns(); - - Gtk::TreeModelColumn> m_col_pixbuf; - Gtk::TreeModelColumn> m_col_pixbuf_animation; - Gtk::TreeModelColumn m_col_name; - Gtk::TreeModelColumn m_col_creator; - Gtk::TreeModelColumn m_col_animated; - Gtk::TreeModelColumn m_col_available; - Gtk::TreeModelColumn m_col_id; - }; - - ModelColumns m_columns; - Glib::RefPtr m_model; - Glib::RefPtr m_filter; - - Gtk::Menu m_menu; - Gtk::MenuItem m_menu_delete; - Gtk::MenuItem m_menu_copy_id; - Gtk::MenuItem m_menu_copy_emoji_url; - Gtk::MenuItem m_menu_show_emoji; -}; diff --git a/windows/guildsettings/infopane.cpp b/windows/guildsettings/infopane.cpp deleted file mode 100644 index b4f75f3..0000000 --- a/windows/guildsettings/infopane.cpp +++ /dev/null @@ -1,220 +0,0 @@ -#include "infopane.hpp" -#include "abaddon.hpp" -#include - -GuildSettingsInfoPane::GuildSettingsInfoPane(Snowflake id) - : m_guild_icon_label("Guild icon") - , m_guild_name_label("Guild name") - , GuildID(id) { - auto &discord = Abaddon::Get().GetDiscordClient(); - const auto guild = *discord.GetGuild(id); - const auto self_id = discord.GetUserData().ID; - const auto can_modify = discord.HasGuildPermission(self_id, id, Permission::MANAGE_GUILD); - - set_name("guild-info-pane"); - - m_guild_name.set_sensitive(can_modify); - m_guild_name.set_text(guild.Name); - m_guild_name.signal_focus_out_event().connect([this](GdkEventFocus *e) -> bool { - UpdateGuildName(); - return false; - }); - m_guild_name.signal_key_press_event().connect([this](GdkEventKey *e) -> bool { - if (e->keyval == GDK_KEY_Return) - UpdateGuildName(); - return false; - // clang-format off - }, false); - // clang-format on - m_guild_name.set_tooltip_text("Press enter or lose focus to submit"); - m_guild_name.show(); - m_guild_name_label.show(); - - auto guild_update_cb = [this](Snowflake id) { - if (id != GuildID) return; - const auto guild = *Abaddon::Get().GetDiscordClient().GetGuild(id); - FetchGuildIcon(guild); - }; - discord.signal_guild_update().connect(sigc::track_obj(guild_update_cb, *this)); - FetchGuildIcon(guild); - - AddPointerCursor(m_guild_icon_ev); - - m_guild_icon.set_margin_bottom(10); - if (can_modify) { - m_guild_icon_ev.set_tooltip_text("Click to choose a file, right click to paste"); - - m_guild_icon_ev.signal_button_press_event().connect([this](GdkEventButton *event) -> bool { - if (event->type == GDK_BUTTON_PRESS) { - if (event->button == GDK_BUTTON_PRIMARY) - UpdateGuildIconPicker(); - else if (event->button == GDK_BUTTON_SECONDARY) - UpdateGuildIconClipboard(); - } - - return false; - }); - } else if (guild.HasIcon()) { - std::string guild_icon_url; - if (guild.HasAnimatedIcon()) - guild_icon_url = guild.GetIconURL("gif", "512"); - else - guild_icon_url = guild.GetIconURL("png", "512"); - m_guild_icon_ev.signal_button_press_event().connect([this, guild_icon_url](GdkEventButton *event) -> bool { - if (event->type == GDK_BUTTON_PRESS) - if (event->button == GDK_BUTTON_PRIMARY) - LaunchBrowser(guild_icon_url); - - return false; - }); - } - - m_guild_icon.show(); - m_guild_icon_ev.show(); - - m_guild_icon_ev.add(m_guild_icon); - attach(m_guild_icon_ev, 0, 0, 1, 1); - attach(m_guild_name_label, 0, 1, 1, 1); - attach_next_to(m_guild_name, m_guild_name_label, Gtk::POS_RIGHT, 1, 1); -} - -void GuildSettingsInfoPane::FetchGuildIcon(const GuildData &guild) { - m_guild_icon.property_pixbuf() = Abaddon::Get().GetImageManager().GetPlaceholder(32); - if (guild.HasIcon()) { - if (Abaddon::Get().GetSettings().GetShowAnimations() && guild.HasAnimatedIcon()) { - auto cb = [this](const Glib::RefPtr &pixbuf) { - m_guild_icon.property_pixbuf_animation() = pixbuf; - }; - Abaddon::Get().GetImageManager().LoadAnimationFromURL(guild.GetIconURL("gif", "64"), 64, 64, sigc::track_obj(cb, *this)); - } - - auto cb = [this](const Glib::RefPtr &pixbuf) { - m_guild_icon.property_pixbuf() = pixbuf->scale_simple(64, 64, Gdk::INTERP_BILINEAR); - }; - Abaddon::Get().GetImageManager().LoadFromURL(guild.GetIconURL("png", "64"), sigc::track_obj(cb, *this)); - } -} - -void GuildSettingsInfoPane::UpdateGuildName() { - auto &discord = Abaddon::Get().GetDiscordClient(); - if (discord.GetGuild(GuildID)->Name == m_guild_name.get_text()) return; - - auto cb = [this](DiscordError code) { - if (code != DiscordError::NONE) { - m_guild_name.set_text(Abaddon::Get().GetDiscordClient().GetGuild(GuildID)->Name); - Gtk::MessageDialog dlg("Failed to set guild name", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - dlg.set_position(Gtk::WIN_POS_CENTER); - dlg.run(); - } - }; - discord.SetGuildName(GuildID, m_guild_name.get_text(), sigc::track_obj(cb, *this)); -} - -void GuildSettingsInfoPane::UpdateGuildIconFromData(const std::vector &data, const std::string &mime) { - auto encoded = "data:" + mime + ";base64," + Glib::Base64::encode(std::string(data.begin(), data.end())); - auto &discord = Abaddon::Get().GetDiscordClient(); - - auto cb = [this](DiscordError code) { - if (code != DiscordError::NONE) { - Gtk::MessageDialog dlg("Failed to set guild icon", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - dlg.set_position(Gtk::WIN_POS_CENTER); - dlg.run(); - } - }; - discord.SetGuildIcon(GuildID, encoded, sigc::track_obj(cb, *this)); -} - -void GuildSettingsInfoPane::UpdateGuildIconFromPixbuf(Glib::RefPtr pixbuf) { - int w = pixbuf->get_width(); - int h = pixbuf->get_height(); - if (w > 1024 || h > 1024) { - GetImageDimensions(w, h, w, h, 1024, 1024); - pixbuf = pixbuf->scale_simple(w, h, Gdk::INTERP_BILINEAR); - } - gchar *buffer; - gsize buffer_size; - pixbuf->save_to_buffer(buffer, buffer_size, "png"); - std::vector data(buffer_size); - std::memcpy(data.data(), buffer, buffer_size); - UpdateGuildIconFromData(data, "image/png"); -} - -void GuildSettingsInfoPane::UpdateGuildIconPicker() { - // this picker fucking sucks - Gtk::FileChooserDialog dlg("Choose new guild icon", Gtk::FILE_CHOOSER_ACTION_OPEN); - dlg.get_style_context()->remove_provider(Abaddon::Get().GetStyleProvider()); - dlg.set_modal(true); - dlg.signal_response().connect([this, &dlg](int response) { - if (response == Gtk::RESPONSE_OK) { - auto data = ReadWholeFile(dlg.get_filename()); - if (GetExtension(dlg.get_filename()) == ".gif") - UpdateGuildIconFromData(data, "image/gif"); - else - try { - auto loader = Gdk::PixbufLoader::create(); - loader->signal_size_prepared().connect([&loader](int inw, int inh) { - int w, h; - GetImageDimensions(inw, inh, w, h, 1024, 1024); - loader->set_size(w, h); - }); - loader->write(data.data(), data.size()); - loader->close(); - UpdateGuildIconFromPixbuf(loader->get_pixbuf()); - } catch (const std::exception &) {}; - } - }); - - dlg.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK); - dlg.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); - - auto filter_images = Gtk::FileFilter::create(); - if (Abaddon::Get().GetDiscordClient().GetGuild(GuildID)->HasFeature("ANIMATED_ICON")) { - filter_images->set_name("Supported images (*.jpg, *.jpeg, *.png, *.gif)"); - filter_images->add_pattern("*.gif"); - } else { - filter_images->set_name("Supported images (*.jpg, *.jpeg, *.png)"); - } - filter_images->add_pattern("*.jpg"); - filter_images->add_pattern("*.jpeg"); - filter_images->add_pattern("*.png"); - dlg.add_filter(filter_images); - - auto filter_all = Gtk::FileFilter::create(); - filter_all->set_name("All files (*.*)"); - filter_all->add_pattern("*.*"); - dlg.add_filter(filter_all); - - dlg.run(); -} - -void GuildSettingsInfoPane::UpdateGuildIconClipboard() { - std::vector icon_data; - - auto cb = Gtk::Clipboard::get(); - // query for file path then for actual image - if (cb->wait_is_text_available()) { - auto path = cb->wait_for_text(); - if (!std::filesystem::exists(path.c_str())) return; - auto data = ReadWholeFile(path); - try { - auto loader = Gdk::PixbufLoader::create(); - loader->signal_size_prepared().connect([&loader](int inw, int inh) { - int w, h; - GetImageDimensions(inw, inh, w, h, 1024, 1024); - loader->set_size(w, h); - }); - loader->write(data.data(), data.size()); - loader->close(); - auto pb = loader->get_pixbuf(); - UpdateGuildIconFromPixbuf(pb); - - return; - } catch (const std::exception &) {}; - } - - if (cb->wait_is_image_available()) { - auto pb = cb->wait_for_image(); - UpdateGuildIconFromPixbuf(pb); - return; - } -} diff --git a/windows/guildsettings/infopane.hpp b/windows/guildsettings/infopane.hpp deleted file mode 100644 index 8a7e6a2..0000000 --- a/windows/guildsettings/infopane.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include -#include "discord/guild.hpp" - -class GuildSettingsInfoPane : public Gtk::Grid { -public: - GuildSettingsInfoPane(Snowflake id); - -private: - void FetchGuildIcon(const GuildData &guild); - - void UpdateGuildName(); - void UpdateGuildIconFromData(const std::vector &data, const std::string &mime); - void UpdateGuildIconFromPixbuf(Glib::RefPtr pixbuf); - void UpdateGuildIconPicker(); - void UpdateGuildIconClipboard(); - - Gtk::Label m_guild_icon_label; - Gtk::EventBox m_guild_icon_ev; // necessary to make custom cursor behave properly - Gtk::Image m_guild_icon; - - Gtk::Label m_guild_name_label; - Gtk::Entry m_guild_name; - - Snowflake GuildID; -}; diff --git a/windows/guildsettings/invitespane.cpp b/windows/guildsettings/invitespane.cpp deleted file mode 100644 index bec4784..0000000 --- a/windows/guildsettings/invitespane.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "invitespane.hpp" -#include "abaddon.hpp" - -GuildSettingsInvitesPane::GuildSettingsInvitesPane(Snowflake id) - : GuildID(id) - , m_model(Gtk::ListStore::create(m_columns)) - , m_menu_delete("Delete") { - signal_map().connect(sigc::mem_fun(*this, &GuildSettingsInvitesPane::OnMap)); - set_name("guild-invites-pane"); - set_hexpand(true); - set_vexpand(true); - - m_view.signal_button_press_event().connect(sigc::mem_fun(*this, &GuildSettingsInvitesPane::OnTreeButtonPress), false); - - m_menu_delete.signal_activate().connect(sigc::mem_fun(*this, &GuildSettingsInvitesPane::OnMenuDelete)); - m_menu.append(m_menu_delete); - m_menu.show_all(); - - auto &discord = Abaddon::Get().GetDiscordClient(); - - discord.signal_invite_create().connect(sigc::mem_fun(*this, &GuildSettingsInvitesPane::OnInviteCreate)); - discord.signal_invite_delete().connect(sigc::mem_fun(*this, &GuildSettingsInvitesPane::OnInviteDelete)); - - m_view.show(); - add(m_view); - - m_view.set_enable_search(false); - m_view.set_model(m_model); - m_view.append_column("Code", m_columns.m_col_code); - m_view.append_column("Expires", m_columns.m_col_expires); - m_view.append_column("Created by", m_columns.m_col_inviter); - m_view.append_column("Uses", m_columns.m_col_uses); - m_view.append_column("Max uses", m_columns.m_col_max_uses); - m_view.append_column("Grants temporary membership", m_columns.m_col_temporary); - - for (const auto column : m_view.get_columns()) - column->set_resizable(true); -} - -void GuildSettingsInvitesPane::OnMap() { - if (m_requested) return; - m_requested = true; - - auto &discord = Abaddon::Get().GetDiscordClient(); - const auto self_id = discord.GetUserData().ID; - - if (discord.HasGuildPermission(self_id, GuildID, Permission::MANAGE_GUILD)) - discord.FetchGuildInvites(GuildID, sigc::mem_fun(*this, &GuildSettingsInvitesPane::OnInvitesFetch)); -} - -void GuildSettingsInvitesPane::AppendInvite(const InviteData &invite) { - auto row = *m_model->append(); - row[m_columns.m_col_code] = invite.Code; - if (invite.Inviter.has_value()) - row[m_columns.m_col_inviter] = invite.Inviter->Username + "#" + invite.Inviter->Discriminator; - - if (invite.MaxAge.has_value()) { - if (*invite.MaxAge == 0) - row[m_columns.m_col_expires] = "Never"; - else - row[m_columns.m_col_expires] = FormatISO8601(*invite.CreatedAt, *invite.MaxAge); - } - - row[m_columns.m_col_uses] = *invite.Uses; - if (*invite.MaxUses == 0) - row[m_columns.m_col_max_uses] = "Unlimited"; - else - row[m_columns.m_col_max_uses] = std::to_string(*invite.MaxUses); - - row[m_columns.m_col_temporary] = *invite.IsTemporary ? "Yes" : "No"; -} - -void GuildSettingsInvitesPane::OnInviteFetch(const std::optional &invite) { - if (!invite.has_value()) return; - AppendInvite(*invite); -} - -void GuildSettingsInvitesPane::OnInvitesFetch(const std::vector &invites) { - for (const auto &invite : invites) - AppendInvite(invite); -} - -void GuildSettingsInvitesPane::OnInviteCreate(const InviteData &invite) { - if (invite.Guild->ID == GuildID) - OnInviteFetch(std::make_optional(invite)); -} - -void GuildSettingsInvitesPane::OnInviteDelete(const InviteDeleteObject &data) { - if (*data.GuildID == GuildID) - for (auto &row : m_model->children()) - if (row[m_columns.m_col_code] == data.Code) - m_model->erase(row); -} - -void GuildSettingsInvitesPane::OnMenuDelete() { - auto selected_row = *m_view.get_selection()->get_selected(); - if (selected_row) { - auto code = static_cast(selected_row[m_columns.m_col_code]); - auto cb = [this](DiscordError code) { - if (code != DiscordError::NONE) { - Gtk::MessageDialog dlg("Failed to delete invite", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - dlg.set_position(Gtk::WIN_POS_CENTER); - dlg.run(); - } - }; - Abaddon::Get().GetDiscordClient().DeleteInvite(code, sigc::track_obj(cb, *this)); - } -} - -bool GuildSettingsInvitesPane::OnTreeButtonPress(GdkEventButton *event) { - if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_SECONDARY) { - auto &discord = Abaddon::Get().GetDiscordClient(); - const auto self_id = discord.GetUserData().ID; - const auto can_manage = discord.HasGuildPermission(self_id, GuildID, Permission::MANAGE_GUILD); - m_menu_delete.set_sensitive(can_manage); - auto selection = m_view.get_selection(); - Gtk::TreeModel::Path path; - if (m_view.get_path_at_pos(event->x, event->y, path)) { - m_view.get_selection()->select(path); - m_menu.popup_at_pointer(reinterpret_cast(event)); - } - - return true; - } - - return false; -} - -GuildSettingsInvitesPane::ModelColumns::ModelColumns() { - add(m_col_code); - add(m_col_expires); - add(m_col_inviter); - add(m_col_temporary); - add(m_col_uses); - add(m_col_max_uses); -} diff --git a/windows/guildsettings/invitespane.hpp b/windows/guildsettings/invitespane.hpp deleted file mode 100644 index 5268d68..0000000 --- a/windows/guildsettings/invitespane.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -#include -#include "discord/objects.hpp" - -class GuildSettingsInvitesPane : public Gtk::ScrolledWindow { -public: - GuildSettingsInvitesPane(Snowflake id); - -private: - void OnMap(); - - bool m_requested = false; - - void AppendInvite(const InviteData &invite); - void OnInviteFetch(const std::optional &invite); - void OnInvitesFetch(const std::vector &invites); - void OnInviteCreate(const InviteData &invite); - void OnInviteDelete(const InviteDeleteObject &data); - void OnMenuDelete(); - bool OnTreeButtonPress(GdkEventButton *event); - - Gtk::TreeView m_view; - - Snowflake GuildID; - - class ModelColumns : public Gtk::TreeModel::ColumnRecord { - public: - ModelColumns(); - - Gtk::TreeModelColumn m_col_code; - Gtk::TreeModelColumn m_col_expires; - Gtk::TreeModelColumn m_col_inviter; - Gtk::TreeModelColumn m_col_temporary; - Gtk::TreeModelColumn m_col_uses; - Gtk::TreeModelColumn m_col_max_uses; - }; - - ModelColumns m_columns; - Glib::RefPtr m_model; - - Gtk::Menu m_menu; - Gtk::MenuItem m_menu_delete; -}; diff --git a/windows/guildsettings/memberspane.cpp b/windows/guildsettings/memberspane.cpp deleted file mode 100644 index 36c5c0b..0000000 --- a/windows/guildsettings/memberspane.cpp +++ /dev/null @@ -1,410 +0,0 @@ -#include "memberspane.hpp" -#include "abaddon.hpp" - -GuildSettingsMembersPane::GuildSettingsMembersPane(Snowflake id) - : Gtk::Box(Gtk::ORIENTATION_VERTICAL) - , GuildID(id) - , m_layout(Gtk::ORIENTATION_HORIZONTAL) - , m_member_list(id) - , m_member_info(id) { - set_name("guild-members-pane"); - set_hexpand(true); - set_vexpand(true); - - m_member_list.signal_member_select().connect(sigc::mem_fun(m_member_info, &GuildSettingsMembersPaneInfo::SetUser)); - - m_note.set_label("Some members may not be shown if the client is not aware of them"); - m_note.set_single_line_mode(true); - m_note.set_ellipsize(Pango::ELLIPSIZE_END); - - m_layout.set_homogeneous(true); - m_layout.add(m_member_list); - m_layout.add(m_member_info); - add(m_note); - add(m_layout); - - m_member_list.show(); - m_member_info.show(); - m_note.show(); - m_layout.show(); -} - -GuildSettingsMembersPaneMembers::GuildSettingsMembersPaneMembers(Snowflake id) - : Gtk::Box(Gtk::ORIENTATION_VERTICAL) - , GuildID(id) { - m_list_scroll.get_style_context()->add_class("guild-members-pane-list"); - - m_list_scroll.set_hexpand(true); - m_list_scroll.set_vexpand(true); - m_list_scroll.set_propagate_natural_height(true); - - auto &discord = Abaddon::Get().GetDiscordClient(); - auto members = discord.GetUsersInGuild(id); - const auto guild = *discord.GetGuild(GuildID); - for (const auto member_id : members) { - auto member = discord.GetMember(member_id, GuildID); - if (!member.has_value()) continue; // fixme this should not be necessary - member->User = discord.GetUser(member_id); - if (member->User->IsDeleted()) continue; - auto *row = Gtk::manage(new GuildSettingsMembersListItem(guild, *member)); - row->show(); - m_list.add(*row); - } - - m_list.set_selection_mode(Gtk::SELECTION_SINGLE); - m_list.signal_row_selected().connect([this](Gtk::ListBoxRow *selected_) { - if (auto *selected = dynamic_cast(selected_)) - m_signal_member_select.emit(selected->UserID); - }); - - m_search.set_placeholder_text("Filter"); - m_search.signal_changed().connect([this] { - m_list.invalidate_filter(); - }); - - m_list.set_filter_func([this](Gtk::ListBoxRow *row_) -> bool { - const auto search_term = m_search.get_text(); - if (search_term.size() == 0) return true; - if (auto *row = dynamic_cast(row_)) - return StringContainsCaseless(row->DisplayTerm, m_search.get_text()); - return true; - }); - - m_list_scroll.add(m_list); - add(m_search); - add(m_list_scroll); - - m_search.show(); - m_list.show(); - m_list_scroll.show(); -} - -GuildSettingsMembersPaneMembers::type_signal_member_select GuildSettingsMembersPaneMembers::signal_member_select() { - return m_signal_member_select; -} - -GuildSettingsMembersListItem::GuildSettingsMembersListItem(const GuildData &guild, const GuildMember &member) - : UserID(member.User->ID) - , GuildID(guild.ID) - , m_avatar(32, 32) { - m_avatar.SetAnimated(true); - - m_ev.signal_button_press_event().connect([this](GdkEventButton *event) -> bool { - if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_SECONDARY) { - Abaddon::Get().ShowUserMenu(reinterpret_cast(event), UserID, GuildID); - return true; - } - return false; - }); - - auto &discord = Abaddon::Get().GetDiscordClient(); - - if (member.User->HasAnimatedAvatar() && Abaddon::Get().GetSettings().GetShowAnimations()) - m_avatar.SetURL(member.User->GetAvatarURL("gif", "32")); - else - m_avatar.SetURL(member.User->GetAvatarURL("png", "32")); - - DisplayTerm = member.User->Username + "#" + member.User->Discriminator; - - const auto member_update_cb = [this](Snowflake guild_id, Snowflake user_id) { - if (user_id == UserID) - UpdateColor(); - }; - discord.signal_guild_member_update().connect(sigc::track_obj(member_update_cb, *this)); - UpdateColor(); - - static bool crown = Abaddon::Get().GetSettings().GetShowOwnerCrown(); - if (crown && guild.OwnerID == member.User->ID) { - try { - const static auto crown_path = Abaddon::GetResPath("/crown.png"); - auto pixbuf = Gdk::Pixbuf::create_from_file(crown_path, 12, 12); - m_crown = Gtk::manage(new Gtk::Image(pixbuf)); - m_crown->set_valign(Gtk::ALIGN_CENTER); - m_crown->set_margin_start(10); - m_crown->show(); - } catch (...) {} - } - - m_avatar.set_margin_end(5); - m_avatar.set_halign(Gtk::ALIGN_START); - m_avatar.set_valign(Gtk::ALIGN_CENTER); - m_name.set_halign(Gtk::ALIGN_START); - m_name.set_valign(Gtk::ALIGN_CENTER); - - m_main.set_hexpand(true); - - m_main.add(m_avatar); - m_main.add(m_name); - if (m_crown != nullptr) - m_main.add(*m_crown); - - m_ev.add(m_main); - add(m_ev); - - m_avatar.show(); - m_name.show(); - m_main.show(); - m_ev.show(); -} - -void GuildSettingsMembersListItem::UpdateColor() { - auto &discord = Abaddon::Get().GetDiscordClient(); - const auto user = *discord.GetUser(UserID); - if (auto color_id = discord.GetMemberHoistedRole(GuildID, UserID, true); color_id.IsValid()) { - auto role = *discord.GetRole(color_id); - m_name.set_markup("" + user.GetEscapedBoldString() + ""); - } else - m_name.set_markup(user.GetEscapedBoldString()); -} - -GuildSettingsMembersPaneInfo::GuildSettingsMembersPaneInfo(Snowflake guild_id) - : GuildID(guild_id) - , m_roles(guild_id) - , m_box(Gtk::ORIENTATION_VERTICAL) { - get_style_context()->add_class("guild-members-pane-info"); - - const auto label = [](Gtk::Label &lbl) { - lbl.set_single_line_mode(true); - lbl.set_halign(Gtk::ALIGN_START); - lbl.set_valign(Gtk::ALIGN_START); - lbl.set_ellipsize(Pango::ELLIPSIZE_END); - lbl.set_margin_bottom(5); - lbl.show(); - }; - - m_bot.set_text("User is a bot"); - - label(m_bot); - label(m_id); - label(m_created); - label(m_joined); - label(m_nickname); - label(m_boosting); - - m_box.set_halign(Gtk::ALIGN_FILL); - m_box.set_valign(Gtk::ALIGN_START); - m_box.set_hexpand(true); - m_box.set_vexpand(true); - m_box.add(m_bot); - m_box.add(m_id); - m_box.add(m_created); - m_box.add(m_joined); - m_box.add(m_nickname); - m_box.add(m_boosting); - m_box.add(m_roles); - - m_bot.hide(); - m_box.show(); - - add(m_box); -} - -void GuildSettingsMembersPaneInfo::SetUser(Snowflake user_id) { - auto &discord = Abaddon::Get().GetDiscordClient(); - const auto guild = *discord.GetGuild(GuildID); - auto member = *discord.GetMember(user_id, GuildID); - member.User = discord.GetUser(user_id); - - m_bot.set_visible(member.User->IsBot.has_value() && *member.User->IsBot); - - m_id.set_text("User ID: " + std::to_string(user_id)); - m_created.set_text("Account created: " + user_id.GetLocalTimestamp()); - if (member.JoinedAt != "") - m_joined.set_text("Joined server: " + FormatISO8601(member.JoinedAt)); - else - m_joined.set_text("Joined server: Unknown"); - m_nickname.set_text("Nickname: " + member.Nickname); - m_nickname.set_visible(member.Nickname != ""); - if (member.PremiumSince.has_value()) { - m_boosting.set_text("Boosting since " + FormatISO8601(*member.PremiumSince)); - m_boosting.show(); - } else - m_boosting.hide(); - - m_roles.show(); - m_roles.SetRoles(user_id, member.Roles, guild.OwnerID == discord.GetUserData().ID); -} - -GuildSettingsMembersPaneRoles::GuildSettingsMembersPaneRoles(Snowflake guild_id) - : GuildID(guild_id) { - auto &discord = Abaddon::Get().GetDiscordClient(); - const auto self_id = discord.GetUserData().ID; - const bool can_modify = discord.HasGuildPermission(self_id, guild_id, Permission::MANAGE_ROLES); - const auto highest = discord.GetMemberHighestRole(GuildID, self_id); - if (highest.has_value()) - m_hoisted_position = highest->Position; - - discord.signal_role_create().connect(sigc::mem_fun(*this, &GuildSettingsMembersPaneRoles::OnRoleCreate)); - discord.signal_role_update().connect(sigc::mem_fun(*this, &GuildSettingsMembersPaneRoles::OnRoleUpdate)); - discord.signal_role_delete().connect(sigc::mem_fun(*this, &GuildSettingsMembersPaneRoles::OnRoleDelete)); - - const auto guild = *discord.GetGuild(guild_id); - const auto roles = guild.FetchRoles(); - for (const auto &role : roles) { - CreateRow(can_modify, role, guild.OwnerID == self_id); - } - - m_list.set_sort_func([this](Gtk::ListBoxRow *a, Gtk::ListBoxRow *b) -> int { - auto *rowa = dynamic_cast(a); - auto *rowb = dynamic_cast(b); - return rowb->Position - rowa->Position; - }); - - set_propagate_natural_height(true); - set_propagate_natural_width(true); - set_hexpand(true); - set_vexpand(true); - set_halign(Gtk::ALIGN_FILL); - set_valign(Gtk::ALIGN_START); - - m_list.show(); - - add(m_list); -} - -void GuildSettingsMembersPaneRoles::SetRoles(Snowflake user_id, const std::vector &roles, bool is_owner) { - UserID = user_id; - - for (auto it = m_update_connection.begin(); it != m_update_connection.end();) { - it->disconnect(); - it = m_update_connection.erase(it); - } - - m_set_role_ids = { roles.begin(), roles.end() }; - for (const auto &[role_id, row] : m_rows) { - auto role = *Abaddon::Get().GetDiscordClient().GetRole(role_id); - if (role.ID == GuildID) { - row->SetChecked(true); - row->SetToggleable(false); - } else { - row->SetToggleable(role.Position < m_hoisted_position || is_owner); - row->SetChecked(m_set_role_ids.find(role_id) != m_set_role_ids.end()); - } - } -} - -void GuildSettingsMembersPaneRoles::CreateRow(bool has_manage_roles, const RoleData &role, bool is_owner) { - auto *row = Gtk::manage(new GuildSettingsMembersPaneRolesItem(has_manage_roles, role)); - if (role.ID == GuildID) { - row->SetChecked(true); - row->SetToggleable(false); - } else - row->SetToggleable(role.Position < m_hoisted_position || is_owner); - row->signal_role_click().connect(sigc::mem_fun(*this, &GuildSettingsMembersPaneRoles::OnRoleToggle)); - row->show(); - m_rows[role.ID] = row; - m_list.add(*row); -} - -void GuildSettingsMembersPaneRoles::OnRoleToggle(Snowflake role_id, bool new_set) { - auto row = m_rows.at(role_id); - row->SetToggleable(false); - auto &discord = Abaddon::Get().GetDiscordClient(); - auto cb = [this, new_set, role_id, row](bool success) { - if (!success) { // undo - if (new_set) - m_set_role_ids.erase(role_id); - else - m_set_role_ids.insert(role_id); - } else - row->SetChecked(new_set); - - row->SetToggleable(true); - }; - - if (new_set) - m_set_role_ids.insert(role_id); - else - m_set_role_ids.erase(role_id); - - // hack to prevent cb from being called if SetRoles is called before callback completion - sigc::signal tmp; - m_update_connection.push_back(tmp.connect(std::move(cb))); - const auto tmp_cb = [this, tmp = std::move(tmp)](DiscordError code) { tmp.emit(code == DiscordError::NONE); }; - discord.SetMemberRoles(GuildID, UserID, m_set_role_ids.begin(), m_set_role_ids.end(), sigc::track_obj(tmp_cb, *this)); -} - -void GuildSettingsMembersPaneRoles::OnRoleCreate(Snowflake guild_id, Snowflake role_id) { - if (guild_id != GuildID) return; - auto &discord = Abaddon::Get().GetDiscordClient(); - const auto self_id = discord.GetUserData().ID; - const bool can_modify = discord.HasGuildPermission(self_id, GuildID, Permission::MANAGE_ROLES); - const auto role = *discord.GetRole(role_id); - CreateRow(can_modify, role, discord.GetGuild(guild_id)->OwnerID == self_id); -} - -void GuildSettingsMembersPaneRoles::OnRoleUpdate(Snowflake guild_id, Snowflake role_id) { - if (guild_id != GuildID) return; - auto role = *Abaddon::Get().GetDiscordClient().GetRole(role_id); - m_rows.at(role_id)->UpdateRoleData(role); - m_list.invalidate_sort(); -} - -void GuildSettingsMembersPaneRoles::OnRoleDelete(Snowflake guild_id, Snowflake role_id) { - if (guild_id != GuildID) return; - delete m_rows.at(role_id); -} - -GuildSettingsMembersPaneRolesItem::GuildSettingsMembersPaneRolesItem(bool sensitive, const RoleData &role) - : RoleID(role.ID) { - UpdateRoleData(role); - - m_main.set_hexpand(true); - m_main.set_vexpand(true); - - const auto cb = [this](GdkEventButton *event) -> bool { - if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY) { - m_signal_role_click.emit(RoleID, !m_check.get_active()); - return true; - } - return false; - }; - m_check.signal_button_press_event().connect(cb, false); - - m_desired_sensitivity = sensitive; - ComputeSensitivity(); - - m_check.set_margin_start(5); - m_label.set_margin_start(5); - - m_main.add(m_check); - m_main.add(m_label); - add(m_main); - m_check.show(); - m_label.show(); - m_main.show(); -} - -void GuildSettingsMembersPaneRolesItem::SetChecked(bool checked) { - m_check.set_active(checked); -} - -void GuildSettingsMembersPaneRolesItem::SetToggleable(bool toggleable) { - m_desired_sensitivity = toggleable; - ComputeSensitivity(); -} - -void GuildSettingsMembersPaneRolesItem::UpdateRoleData(const RoleData &role) { - m_role = role; - Position = role.Position; - UpdateLabel(); -} - -void GuildSettingsMembersPaneRolesItem::UpdateLabel() { - if (m_role.Color) - m_label.set_markup("" + Glib::Markup::escape_text(m_role.Name) + ""); - else - m_label.set_text(m_role.Name); -} - -void GuildSettingsMembersPaneRolesItem::ComputeSensitivity() { - if (m_role.IsManaged) { - m_check.set_sensitive(false); - return; - } - m_check.set_sensitive(m_desired_sensitivity); -} - -GuildSettingsMembersPaneRolesItem::type_signal_role_click GuildSettingsMembersPaneRolesItem::signal_role_click() { - return m_signal_role_click; -} diff --git a/windows/guildsettings/memberspane.hpp b/windows/guildsettings/memberspane.hpp deleted file mode 100644 index 01398da..0000000 --- a/windows/guildsettings/memberspane.hpp +++ /dev/null @@ -1,135 +0,0 @@ -#pragma once -#include -#include -#include "discord/member.hpp" -#include "discord/guild.hpp" -#include "components/lazyimage.hpp" - -class GuildSettingsMembersPaneRolesItem : public Gtk::ListBoxRow { -public: - GuildSettingsMembersPaneRolesItem(bool sensitive, const RoleData &role); - void SetChecked(bool checked); - void SetToggleable(bool toggleable); - void UpdateRoleData(const RoleData &role); - - Snowflake RoleID; - int Position; - -private: - void UpdateLabel(); - void ComputeSensitivity(); - bool m_desired_sensitivity = true; - - RoleData m_role; - - Gtk::Box m_main; - Gtk::CheckButton m_check; - Gtk::Label m_label; - - // own thing so we can stop it from actually changing - typedef sigc::signal type_signal_role_click; - - type_signal_role_click m_signal_role_click; - -public: - type_signal_role_click signal_role_click(); -}; - -class GuildSettingsMembersPaneRoles : public Gtk::ScrolledWindow { -public: - GuildSettingsMembersPaneRoles(Snowflake guild_id); - - void SetRoles(Snowflake user_id, const std::vector &roles, bool is_owner); - -private: - void CreateRow(bool has_manage_roles, const RoleData &role, bool is_owner); - - void OnRoleToggle(Snowflake role_id, bool new_set); - - void OnRoleCreate(Snowflake guild_id, Snowflake role_id); - void OnRoleUpdate(Snowflake guild_id, Snowflake role_id); - void OnRoleDelete(Snowflake guild_id, Snowflake role_id); - - int m_hoisted_position = 0; - - std::vector m_update_connection; - - std::unordered_set m_set_role_ids; - - Snowflake GuildID; - Snowflake UserID; - - Gtk::ListBox m_list; - - std::unordered_map m_rows; -}; - -class GuildSettingsMembersPaneInfo : public Gtk::ScrolledWindow { -public: - GuildSettingsMembersPaneInfo(Snowflake guild_id); - - void SetUser(Snowflake user_id); - -private: - Snowflake GuildID; - Snowflake UserID; - - Gtk::Label m_bot; - Gtk::Label m_id; - Gtk::Label m_created; - Gtk::Label m_joined; - Gtk::Label m_nickname; - Gtk::Label m_boosting; - GuildSettingsMembersPaneRoles m_roles; - Gtk::Box m_box; -}; - -class GuildSettingsMembersPaneMembers : public Gtk::Box { -public: - GuildSettingsMembersPaneMembers(Snowflake id); - -private: - Snowflake GuildID; - - Gtk::Entry m_search; - Gtk::ScrolledWindow m_list_scroll; - Gtk::ListBox m_list; - - typedef sigc::signal type_signal_member_select; - type_signal_member_select m_signal_member_select; - -public: - type_signal_member_select signal_member_select(); -}; - -class GuildSettingsMembersListItem : public Gtk::ListBoxRow { -public: - GuildSettingsMembersListItem(const GuildData &guild, const GuildMember &member); - - Glib::ustring DisplayTerm; - - Snowflake UserID; - Snowflake GuildID; - -private: - void UpdateColor(); - - Gtk::EventBox m_ev; - LazyImage m_avatar; - Gtk::Label m_name; - Gtk::Box m_main; - Gtk::Image *m_crown = nullptr; -}; - -class GuildSettingsMembersPane : public Gtk::Box { -public: - GuildSettingsMembersPane(Snowflake id); - -private: - Snowflake GuildID; - - Gtk::Box m_layout; - Gtk::Label m_note; - GuildSettingsMembersPaneMembers m_member_list; - GuildSettingsMembersPaneInfo m_member_info; -}; diff --git a/windows/guildsettings/rolespane.cpp b/windows/guildsettings/rolespane.cpp deleted file mode 100644 index 8d355ee..0000000 --- a/windows/guildsettings/rolespane.cpp +++ /dev/null @@ -1,419 +0,0 @@ -#include "rolespane.hpp" -#include "abaddon.hpp" - -GuildSettingsRolesPane::GuildSettingsRolesPane(Snowflake id) - : Gtk::Box(Gtk::ORIENTATION_HORIZONTAL) - , GuildID(id) - , m_roles_list(id) - , m_roles_perms(id) { - set_name("guild-roles-pane"); - set_hexpand(true); - set_vexpand(true); - - m_roles_list.signal_role_select().connect(sigc::mem_fun(*this, &GuildSettingsRolesPane::OnRoleSelect)); - - m_roles_perms.set_sensitive(false); - - m_layout.set_homogeneous(true); - m_layout.add(m_roles_list); - m_layout.add(m_roles_perms); - add(m_layout); - - m_roles_list.show(); - m_roles_perms.show(); - m_layout.show(); -} - -void GuildSettingsRolesPane::OnRoleSelect(Snowflake role_id) { - auto &discord = Abaddon::Get().GetDiscordClient(); - const auto role = *discord.GetRole(role_id); - m_roles_perms.SetRole(role); - m_roles_perms.set_sensitive(discord.CanModifyRole(GuildID, role_id)); -} - -static std::vector g_target_entries = { - Gtk::TargetEntry("GTK_LIST_ROLES_ROW", Gtk::TARGET_SAME_APP, 0) -}; - -GuildSettingsRolesPaneRoles::GuildSettingsRolesPaneRoles(Snowflake guild_id) - : Gtk::Box(Gtk::ORIENTATION_VERTICAL) - , GuildID(guild_id) { - m_list.get_style_context()->add_class("guild-roles-pane-list"); - - m_list_scroll.set_hexpand(true); - m_list_scroll.set_vexpand(true); - m_list_scroll.set_propagate_natural_height(true); - m_list_scroll.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); - - m_list.set_selection_mode(Gtk::SELECTION_SINGLE); - m_list.signal_row_selected().connect([this](Gtk::ListBoxRow *selected_) { - if (auto *selected = dynamic_cast(selected_)) - m_signal_role_select.emit(selected->RoleID); - }); - - m_list.set_focus_vadjustment(m_list_scroll.get_vadjustment()); - m_list.signal_on_drop().connect([this](Gtk::ListBoxRow *row_, int new_index) -> bool { - if (auto *row = dynamic_cast(row_)) { - auto &discord = Abaddon::Get().GetDiscordClient(); - const auto num_rows = m_list.get_children().size(); - const auto new_pos = num_rows - new_index - 1; - if (row->RoleID == GuildID) return true; // moving role @everyone - if (static_cast(new_index) == num_rows) return true; // trying to move row below @everyone - // make sure it wont modify a neighbor role u dont have perms to modify - if (!discord.CanModifyRole(GuildID, row->RoleID)) return false; - const auto cb = [this](DiscordError code) { - if (code != DiscordError::NONE) { - Gtk::MessageDialog dlg("Failed to set role position", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - dlg.set_position(Gtk::WIN_POS_CENTER_ON_PARENT); - dlg.run(); - } - }; - discord.ModifyRolePosition(GuildID, row->RoleID, new_pos, sigc::track_obj(cb, *this)); - return true; - } - return false; - }); - - auto &discord = Abaddon::Get().GetDiscordClient(); - discord.signal_role_create().connect(sigc::mem_fun(*this, &GuildSettingsRolesPaneRoles::OnRoleCreate)); - discord.signal_role_delete().connect(sigc::mem_fun(*this, &GuildSettingsRolesPaneRoles::OnRoleDelete)); - - const auto guild = *discord.GetGuild(GuildID); - const auto roles = guild.FetchRoles(); - const bool can_modify = discord.HasGuildPermission(discord.GetUserData().ID, GuildID, Permission::MANAGE_ROLES); - for (const auto &role : roles) { - auto *row = Gtk::manage(new GuildSettingsRolesPaneRolesListItem(guild, role)); - row->drag_source_set(g_target_entries, Gdk::BUTTON1_MASK, Gdk::ACTION_MOVE); - row->set_margin_start(5); - row->set_halign(Gtk::ALIGN_FILL); - row->show(); - m_rows[role.ID] = row; - if (can_modify) - m_list.add_draggable(row); - else - m_list.add(*row); - } - - m_list.set_sort_func([this](Gtk::ListBoxRow *rowa_, Gtk::ListBoxRow *rowb_) -> int { - auto *rowa = dynamic_cast(rowa_); - auto *rowb = dynamic_cast(rowb_); - return rowb->Position - rowa->Position; - }); - m_list.invalidate_sort(); - - m_list.set_filter_func([this](Gtk::ListBoxRow *row_) -> bool { - const auto search_term = m_search.get_text(); - if (search_term.size() == 0) return true; - if (auto *row = dynamic_cast(row_)) - return StringContainsCaseless(row->DisplayTerm, m_search.get_text()); - return true; - }); - - m_search.set_placeholder_text("Filter"); - m_search.signal_changed().connect([this] { - m_list.invalidate_filter(); - }); - - m_list_scroll.add(m_list); - add(m_search); - add(m_list_scroll); - - m_search.show(); - m_list.show(); - m_list_scroll.show(); -} - -void GuildSettingsRolesPaneRoles::OnRoleCreate(Snowflake guild_id, Snowflake role_id) { - if (guild_id != GuildID) return; - auto &discord = Abaddon::Get().GetDiscordClient(); - const bool can_modify = discord.HasGuildPermission(discord.GetUserData().ID, guild_id, Permission::MANAGE_ROLES); - const auto guild = *discord.GetGuild(guild_id); - const auto role = *discord.GetRole(role_id); - auto *row = Gtk::manage(new GuildSettingsRolesPaneRolesListItem(guild, role)); - row->show(); - m_rows[role_id] = row; - if (can_modify) - m_list.add_draggable(row); - else - m_list.add(*row); -} - -void GuildSettingsRolesPaneRoles::OnRoleDelete(Snowflake guild_id, Snowflake role_id) { - if (guild_id != GuildID) return; - auto it = m_rows.find(role_id); - delete it->second; - m_rows.erase(it); -} - -GuildSettingsRolesPaneRoles::type_signal_role_select GuildSettingsRolesPaneRoles::signal_role_select() { - return m_signal_role_select; -} - -GuildSettingsRolesPaneRolesListItem::GuildSettingsRolesPaneRolesListItem(const GuildData &guild, const RoleData &role) - : GuildID(guild.ID) - , RoleID(role.ID) - , Position(role.Position) { - auto &discord = Abaddon::Get().GetDiscordClient(); - - set_hexpand(true); - - UpdateItem(role); - - discord.signal_role_update().connect(sigc::mem_fun(*this, &GuildSettingsRolesPaneRolesListItem::OnRoleUpdate)); - - m_name.set_ellipsize(Pango::ELLIPSIZE_END); - - m_ev.set_halign(Gtk::ALIGN_START); - m_ev.add(m_name); - add(m_ev); - - m_name.show(); - m_ev.show(); -} - -void GuildSettingsRolesPaneRolesListItem::UpdateItem(const RoleData &role) { - DisplayTerm = role.Name; - - if (role.Color != 0) - m_name.set_markup("" + - Glib::Markup::escape_text(role.Name) + - ""); - else - m_name.set_text(role.Name); -} - -void GuildSettingsRolesPaneRolesListItem::OnRoleUpdate(Snowflake guild_id, Snowflake role_id) { - if (guild_id != GuildID || role_id != RoleID) return; - const auto role = Abaddon::Get().GetDiscordClient().GetRole(RoleID); - if (!role.has_value()) return; - Position = role->Position; - UpdateItem(*role); - changed(); -} - -GuildSettingsRolesPaneInfo::GuildSettingsRolesPaneInfo(Snowflake guild_id) - : GuildID(guild_id) - , m_layout(Gtk::ORIENTATION_VERTICAL) - , m_meta(Gtk::ORIENTATION_HORIZONTAL) { - set_propagate_natural_height(true); - set_propagate_natural_width(true); - - auto &discord = Abaddon::Get().GetDiscordClient(); - discord.signal_role_update().connect(sigc::mem_fun(*this, &GuildSettingsRolesPaneInfo::OnRoleUpdate)); - - const auto cb = [this](GdkEventKey *e) -> bool { - if (e->keyval == GDK_KEY_Return) - UpdateRoleName(); - return false; - }; - m_role_name.signal_key_press_event().connect(cb, false); - - m_role_name.set_tooltip_text("Press enter to submit"); - - m_role_name.set_max_length(100); - - m_role_name.set_margin_top(5); - m_role_name.set_margin_bottom(5); - m_role_name.set_margin_start(5); - m_role_name.set_margin_end(5); - - m_color_button.set_margin_top(5); - m_color_button.set_margin_bottom(5); - m_color_button.set_margin_start(5); - m_color_button.set_margin_end(5); - - m_color_button.signal_color_set().connect([this, &discord]() { - const auto color = m_color_button.get_rgba(); - const auto cb = [this, &discord](DiscordError code) { - if (code != DiscordError::NONE) { - m_color_button.set_rgba(IntToRGBA(discord.GetRole(RoleID)->Color)); - Gtk::MessageDialog dlg("Failed to set role color", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - dlg.set_position(Gtk::WIN_POS_CENTER_ON_PARENT); - dlg.run(); - } - }; - discord.ModifyRoleColor(GuildID, RoleID, color, cb); - }); - - int left_ypos = 0; - int right_ypos = 0; - - const int LEFT = 0; - const int RIGHT = 1; - - auto add_perms = [&](const std::string &label, int side, const std::initializer_list &perms) { - int &pos = side == LEFT ? left_ypos : right_ypos; - auto *header = Gtk::manage(new Gtk::Label(label)); - header->show(); - m_grid.attach(*header, side, pos++, 1, 1); - for (const auto perm : perms) { - auto *btn = Gtk::manage(new GuildSettingsRolesPanePermItem(perm)); - btn->signal_permission_click().connect(sigc::mem_fun(*this, &GuildSettingsRolesPaneInfo::OnPermissionToggle)); - m_perm_items[perm] = btn; - btn->show(); - m_grid.attach(*btn, side, pos++, 1, 1); - } - pos++; - }; - - // fuck you clang-format you suck - // clang-format off - add_perms("General", LEFT, { - Permission::VIEW_CHANNEL, - Permission::MANAGE_CHANNELS, - Permission::MANAGE_ROLES, - Permission::MANAGE_EMOJIS, - Permission::VIEW_AUDIT_LOG, - Permission::VIEW_GUILD_INSIGHTS, - Permission::MANAGE_WEBHOOKS, - Permission::MANAGE_GUILD }); - - add_perms("Membership", LEFT, { - Permission::CREATE_INSTANT_INVITE, - Permission::CHANGE_NICKNAME, - Permission::MANAGE_NICKNAMES, - Permission::KICK_MEMBERS, - Permission::BAN_MEMBERS }); - - add_perms("Text Channels", RIGHT, { - Permission::SEND_MESSAGES, - Permission::USE_PUBLIC_THREADS, - Permission::USE_PRIVATE_THREADS, - Permission::EMBED_LINKS, - Permission::ATTACH_FILES, - Permission::ADD_REACTIONS, - Permission::USE_EXTERNAL_EMOJIS, - Permission::MENTION_EVERYONE, - Permission::MANAGE_MESSAGES, - Permission::MANAGE_THREADS, - Permission::READ_MESSAGE_HISTORY, - Permission::SEND_TTS_MESSAGES, - Permission::USE_SLASH_COMMANDS }); - - add_perms("Voice Channels", RIGHT, { - Permission::CONNECT, - Permission::SPEAK, - Permission::STREAM, - Permission::USE_VAD, - Permission::PRIORITY_SPEAKER, - Permission::MUTE_MEMBERS, - Permission::DEAFEN_MEMBERS, - Permission::MOVE_MEMBERS }); - - add_perms("Advanced", LEFT, { Permission::ADMINISTRATOR }); - - // clang-format on - - m_meta.add(m_role_name); - m_meta.add(m_color_button); - m_layout.add(m_meta); - m_layout.add(m_grid); - add(m_layout); - m_meta.show(); - m_color_button.show(); - m_role_name.show(); - m_layout.show(); - m_grid.show(); -} - -void GuildSettingsRolesPaneInfo::SetRole(const RoleData &role) { - for (auto it = m_update_connections.begin(); it != m_update_connections.end();) { - it->disconnect(); - it = m_update_connections.erase(it); - } - - if (role.Color != 0) { - m_color_button.set_rgba(IntToRGBA(role.Color)); - } else { - static Gdk::RGBA trans; - trans.set_alpha(0.0); - m_color_button.set_rgba(trans); - } - - m_role_name.set_text(role.Name); - - RoleID = role.ID; - m_perms = role.Permissions; - for (const auto [perm, btn] : m_perm_items) { - btn->set_sensitive(true); - btn->set_active((role.Permissions & perm) == perm); - } -} - -void GuildSettingsRolesPaneInfo::OnRoleUpdate(Snowflake guild_id, Snowflake role_id) { - if (guild_id != GuildID || role_id != RoleID) return; - const auto role = *Abaddon::Get().GetDiscordClient().GetRole(RoleID); - m_role_name.set_text(role.Name); - - if (role.Color != 0) { - m_color_button.set_rgba(IntToRGBA(role.Color)); - } else { - static Gdk::RGBA trans; - trans.set_alpha(0.0); - m_color_button.set_rgba(trans); - } - - m_perms = role.Permissions; - for (const auto [perm, btn] : m_perm_items) - btn->set_active((role.Permissions & perm) == perm); -} - -void GuildSettingsRolesPaneInfo::OnPermissionToggle(Permission perm, bool new_set) { - auto btn = m_perm_items.at(perm); - btn->set_sensitive(false); - auto &discord = Abaddon::Get().GetDiscordClient(); - auto cb = [this, new_set, perm, btn](bool success) { - if (!success) { // undo - if (new_set) - m_perms &= ~perm; - else - m_perms |= perm; - } else - btn->set_active(new_set); - btn->set_sensitive(true); - }; - - if (new_set) - m_perms |= perm; - else - m_perms &= ~perm; - - sigc::signal tmp; - m_update_connections.push_back(tmp.connect(std::move(cb))); - const auto tmp_cb = [this, tmp = std::move(tmp)](DiscordError code) { tmp.emit(code == DiscordError::NONE); }; - discord.ModifyRolePermissions(GuildID, RoleID, m_perms, sigc::track_obj(tmp_cb, *this)); -} - -void GuildSettingsRolesPaneInfo::UpdateRoleName() { - auto &discord = Abaddon::Get().GetDiscordClient(); - if (discord.GetRole(RoleID)->Name == m_role_name.get_text()) return; - - const auto cb = [this, &discord](DiscordError code) { - if (code != DiscordError::NONE) { - m_role_name.set_text(discord.GetRole(RoleID)->Name); - Gtk::MessageDialog dlg("Failed to set role name", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - dlg.set_position(Gtk::WIN_POS_CENTER_ON_PARENT); - dlg.run(); - } - }; - discord.ModifyRoleName(GuildID, RoleID, m_role_name.get_text(), cb); -} - -GuildSettingsRolesPanePermItem::GuildSettingsRolesPanePermItem(Permission perm) - : Gtk::CheckButton(GetPermissionString(perm)) - , m_permission(perm) { - set_tooltip_text(GetPermissionDescription(m_permission)); - - const auto cb = [this](GdkEventButton *event) -> bool { - if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY) { - m_signal_permission.emit(m_permission, !get_active()); - return true; - } - return false; - }; - signal_button_press_event().connect(cb, false); -} - -GuildSettingsRolesPanePermItem::type_signal_permission_click GuildSettingsRolesPanePermItem::signal_permission_click() { - return m_signal_permission; -} diff --git a/windows/guildsettings/rolespane.hpp b/windows/guildsettings/rolespane.hpp deleted file mode 100644 index 2999f32..0000000 --- a/windows/guildsettings/rolespane.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once -#include -#include -#include "discord/guild.hpp" -#include "components/draglistbox.hpp" - -class GuildSettingsRolesPaneRolesListItem : public Gtk::ListBoxRow { -public: - GuildSettingsRolesPaneRolesListItem(const GuildData &guild, const RoleData &role); - - Glib::ustring DisplayTerm; - - Snowflake GuildID; - Snowflake RoleID; - int Position; - -private: - void UpdateItem(const RoleData &role); - void OnRoleUpdate(Snowflake guild_id, Snowflake role_id); - - Gtk::EventBox m_ev; - Gtk::Label m_name; -}; - -class GuildSettingsRolesPaneRoles : public Gtk::Box { -public: - GuildSettingsRolesPaneRoles(Snowflake guild_id); - -private: - void OnRoleCreate(Snowflake guild_id, Snowflake role_id); - void OnRoleDelete(Snowflake guild_id, Snowflake role_id); - - Snowflake GuildID; - - Gtk::Entry m_search; - Gtk::ScrolledWindow m_list_scroll; - DragListBox m_list; - - typedef sigc::signal type_signal_role_select; - type_signal_role_select m_signal_role_select; - -public: - std::unordered_map m_rows; - type_signal_role_select signal_role_select(); -}; - -class GuildSettingsRolesPanePermItem : public Gtk::CheckButton { -public: - GuildSettingsRolesPanePermItem(Permission perm); - -private: - Permission m_permission; - - typedef sigc::signal type_signal_permission_click; - - type_signal_permission_click m_signal_permission; - -public: - type_signal_permission_click signal_permission_click(); -}; - -class GuildSettingsRolesPaneInfo : public Gtk::ScrolledWindow { -public: - GuildSettingsRolesPaneInfo(Snowflake guild_id); - - void SetRole(const RoleData &role); - -private: - void OnRoleUpdate(Snowflake guild_id, Snowflake role_id); - void OnPermissionToggle(Permission perm, bool new_set); - - void UpdateRoleName(); - - Snowflake GuildID; - Snowflake RoleID; - - Permission m_perms; - - std::vector m_update_connections; - - Gtk::Box m_layout; - Gtk::Box m_meta; - Gtk::Entry m_role_name; - Gtk::ColorButton m_color_button; - Gtk::Grid m_grid; - - std::unordered_map m_perm_items; -}; - -class GuildSettingsRolesPane : public Gtk::Box { -public: - GuildSettingsRolesPane(Snowflake id); - -private: - void OnRoleSelect(Snowflake role_id); - - Snowflake GuildID; - - Gtk::Box m_layout; - GuildSettingsRolesPaneRoles m_roles_list; - GuildSettingsRolesPaneInfo m_roles_perms; -}; -- cgit v1.2.3