forked from OpenGamers/abaddon
add ability to reorder roles
- some other small tweaks
This commit is contained in:
141
components/draglistbox.cpp
Normal file
141
components/draglistbox.cpp
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
#include "draglistbox.hpp"
|
||||||
|
|
||||||
|
DragListBox::DragListBox() {
|
||||||
|
drag_dest_set(m_entries, Gtk::DEST_DEFAULT_MOTION | Gtk::DEST_DEFAULT_DROP, Gdk::ACTION_MOVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragListBox::row_drag_begin(Gtk::Widget *widget, const Glib::RefPtr<Gdk::DragContext> &context) {
|
||||||
|
m_drag_row = dynamic_cast<Gtk::ListBoxRow *>(widget->get_ancestor(GTK_TYPE_LIST_BOX_ROW));
|
||||||
|
|
||||||
|
auto alloc = m_drag_row->get_allocation();
|
||||||
|
auto surface = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, alloc.get_width(), alloc.get_height());
|
||||||
|
auto cr = Cairo::Context::create(surface);
|
||||||
|
|
||||||
|
m_drag_row->get_style_context()->add_class("drag-icon");
|
||||||
|
gtk_widget_draw(reinterpret_cast<GtkWidget *>(m_drag_row->gobj()), cr->cobj());
|
||||||
|
m_drag_row->get_style_context()->remove_class("drag-icon");
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
widget->translate_coordinates(*m_drag_row, 0, 0, x, y);
|
||||||
|
surface->set_device_offset(-x, -y);
|
||||||
|
context->set_icon(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DragListBox::on_drag_motion(const Glib::RefPtr<Gdk::DragContext> &context, gint x, gint y, guint time) {
|
||||||
|
if (y > m_hover_top || y < m_hover_bottom) {
|
||||||
|
auto *row = get_row_at_y(y);
|
||||||
|
if (row == nullptr) return true;
|
||||||
|
const bool old_top = m_top;
|
||||||
|
const auto alloc = row->get_allocation();
|
||||||
|
|
||||||
|
const int hover_row_y = alloc.get_y();
|
||||||
|
const int hover_row_height = alloc.get_height();
|
||||||
|
if (row != m_drag_row) {
|
||||||
|
if (y < hover_row_y + hover_row_height / 2) {
|
||||||
|
m_hover_top = hover_row_y;
|
||||||
|
m_hover_bottom = m_hover_top + hover_row_height / 2;
|
||||||
|
row->get_style_context()->add_class("drag-hover-top");
|
||||||
|
row->get_style_context()->remove_class("drag-hover-bottom");
|
||||||
|
m_top = true;
|
||||||
|
} else {
|
||||||
|
m_hover_top = hover_row_y + hover_row_height / 2;
|
||||||
|
m_hover_bottom = hover_row_y + hover_row_height;
|
||||||
|
row->get_style_context()->add_class("drag-hover-bottom");
|
||||||
|
row->get_style_context()->remove_class("drag-hover-top");
|
||||||
|
m_top = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_hover_row != nullptr && m_hover_row != row) {
|
||||||
|
if (old_top)
|
||||||
|
m_hover_row->get_style_context()->remove_class("drag-hover-top");
|
||||||
|
else
|
||||||
|
m_hover_row->get_style_context()->remove_class("drag-hover-bottom");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_hover_row = row;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_scroll(y);
|
||||||
|
if (m_should_scroll && !m_scrolling) {
|
||||||
|
m_scrolling = true;
|
||||||
|
Glib::signal_timeout().connect(sigc::mem_fun(*this, &DragListBox::scroll), SCROLL_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragListBox::on_drag_leave(const Glib::RefPtr<Gdk::DragContext> &context, guint time) {
|
||||||
|
m_should_scroll = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragListBox::check_scroll(gint y) {
|
||||||
|
if (!get_focus_vadjustment())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const double vadjustment_min = get_focus_vadjustment()->get_value();
|
||||||
|
const double vadjustment_max = get_focus_vadjustment()->get_page_size() + vadjustment_min;
|
||||||
|
const double show_min = std::max(0, y - SCROLL_DISTANCE);
|
||||||
|
const double show_max = std::min(get_focus_vadjustment()->get_upper(), static_cast<double>(y) + SCROLL_DISTANCE);
|
||||||
|
if (vadjustment_min > show_min) {
|
||||||
|
m_should_scroll = true;
|
||||||
|
m_scroll_up = true;
|
||||||
|
} else if (vadjustment_max < show_max) {
|
||||||
|
m_should_scroll = true;
|
||||||
|
m_scroll_up = false;
|
||||||
|
} else {
|
||||||
|
m_should_scroll = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DragListBox::scroll() {
|
||||||
|
if (m_should_scroll) {
|
||||||
|
if (m_scroll_up) {
|
||||||
|
get_focus_vadjustment()->set_value(get_focus_vadjustment()->get_value() - SCROLL_STEP_SIZE);
|
||||||
|
} else {
|
||||||
|
get_focus_vadjustment()->set_value(get_focus_vadjustment()->get_value() + SCROLL_STEP_SIZE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_scrolling = false;
|
||||||
|
}
|
||||||
|
return m_should_scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragListBox::on_drag_data_received(const Glib::RefPtr<Gdk::DragContext> &context, int x, int y, const Gtk::SelectionData &selection_data, guint info, guint time) {
|
||||||
|
int index = 0;
|
||||||
|
if (m_hover_row != nullptr) {
|
||||||
|
if (m_top) {
|
||||||
|
index = m_hover_row->get_index() - 1;
|
||||||
|
m_hover_row->get_style_context()->remove_class("drag-hover-top");
|
||||||
|
} else {
|
||||||
|
index = m_hover_row->get_index();
|
||||||
|
m_hover_row->get_style_context()->remove_class("drag-hover-bottom");
|
||||||
|
}
|
||||||
|
|
||||||
|
Gtk::Widget *handle = *reinterpret_cast<Gtk::Widget *const *>(selection_data.get_data());
|
||||||
|
auto *row = dynamic_cast<Gtk::ListBoxRow *>(handle->get_ancestor(GTK_TYPE_LIST_BOX_ROW));
|
||||||
|
|
||||||
|
if (row != nullptr && row != m_hover_row) {
|
||||||
|
if (row->get_index() > index)
|
||||||
|
index += 1;
|
||||||
|
if (m_signal_on_drop.emit(row, index)) return;
|
||||||
|
row->get_parent()->remove(*row);
|
||||||
|
insert(*row, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_drag_row = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragListBox::add_draggable(Gtk::ListBoxRow *widget) {
|
||||||
|
widget->drag_source_set(m_entries, Gdk::BUTTON1_MASK, Gdk::ACTION_MOVE);
|
||||||
|
widget->signal_drag_begin().connect(sigc::bind<0>(sigc::mem_fun(*this, &DragListBox::row_drag_begin), widget));
|
||||||
|
widget->signal_drag_data_get().connect([this, widget](const Glib::RefPtr<Gdk::DragContext> &context, Gtk::SelectionData &selection_data, guint info, guint time) {
|
||||||
|
selection_data.set("GTK_LIST_BOX_ROW", 32, reinterpret_cast<const guint8 *>(&widget), sizeof(&widget));
|
||||||
|
});
|
||||||
|
add(*widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
DragListBox::type_signal_on_drop DragListBox::signal_on_drop() {
|
||||||
|
return m_signal_on_drop;
|
||||||
|
}
|
||||||
45
components/draglistbox.hpp
Normal file
45
components/draglistbox.hpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <gtkmm.h>
|
||||||
|
|
||||||
|
class DragListBox : public Gtk::ListBox {
|
||||||
|
public:
|
||||||
|
DragListBox();
|
||||||
|
|
||||||
|
void row_drag_begin(Gtk::Widget *widget, const Glib::RefPtr<Gdk::DragContext> &context);
|
||||||
|
|
||||||
|
bool on_drag_motion(const Glib::RefPtr<Gdk::DragContext> &context, gint x, gint y, guint time) override;
|
||||||
|
|
||||||
|
void on_drag_leave(const Glib::RefPtr<Gdk::DragContext> &context, guint time) override;
|
||||||
|
|
||||||
|
void check_scroll(gint y);
|
||||||
|
|
||||||
|
bool scroll();
|
||||||
|
|
||||||
|
void on_drag_data_received(const Glib::RefPtr<Gdk::DragContext> &context, int x, int y, const Gtk::SelectionData &selection_data, guint info, guint time) override;
|
||||||
|
|
||||||
|
void add_draggable(Gtk::ListBoxRow *widget);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Gtk::ListBoxRow *m_hover_row = nullptr;
|
||||||
|
Gtk::ListBoxRow *m_drag_row = nullptr;
|
||||||
|
bool m_top = false;
|
||||||
|
int m_hover_top = 0;
|
||||||
|
int m_hover_bottom = 0;
|
||||||
|
bool m_should_scroll = false;
|
||||||
|
bool m_scrolling = false;
|
||||||
|
bool m_scroll_up = false;
|
||||||
|
|
||||||
|
constexpr static int SCROLL_STEP_SIZE = 8;
|
||||||
|
constexpr static int SCROLL_DISTANCE = 30;
|
||||||
|
constexpr static int SCROLL_DELAY = 50;
|
||||||
|
|
||||||
|
const std::vector<Gtk::TargetEntry> m_entries = {
|
||||||
|
Gtk::TargetEntry("GTK_LIST_BOX_ROW", Gtk::TARGET_SAME_APP, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
using type_signal_on_drop = sigc::signal<bool, Gtk::ListBoxRow *, int /* new index */>;
|
||||||
|
type_signal_on_drop m_signal_on_drop;
|
||||||
|
|
||||||
|
public:
|
||||||
|
type_signal_on_drop signal_on_drop(); // return true to prevent drop
|
||||||
|
};
|
||||||
@@ -321,3 +321,11 @@
|
|||||||
.app-window colorswatch {
|
.app-window colorswatch {
|
||||||
box-shadow: 0 1px rgba(0, 0, 0, 0);
|
box-shadow: 0 1px rgba(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.drag-hover-top {
|
||||||
|
background: linear-gradient(to bottom, rgba(255, 66, 66, 0.65) 0%, rgba(0, 0, 0, 0) 35%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.drag-hover-bottom {
|
||||||
|
background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 65%, rgba(255, 66, 66, 0.65) 100%);
|
||||||
|
}
|
||||||
|
|||||||
@@ -571,6 +571,58 @@ void DiscordClient::ModifyRoleColor(Snowflake guild_id, Snowflake role_id, Gdk::
|
|||||||
ModifyRoleColor(guild_id, role_id, int_color, callback);
|
ModifyRoleColor(guild_id, role_id, int_color, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiscordClient::ModifyRolePosition(Snowflake guild_id, Snowflake role_id, int position, sigc::slot<void(bool success)> callback) {
|
||||||
|
const auto roles = GetGuild(guild_id)->FetchRoles();
|
||||||
|
if (position > roles.size()) return;
|
||||||
|
// gay and makes you send every role in between new and old position
|
||||||
|
size_t index_from = -1, index_to = -1;
|
||||||
|
for (size_t i = 0; i < roles.size(); i++) {
|
||||||
|
const auto &role = roles[i];
|
||||||
|
if (role.ID == role_id)
|
||||||
|
index_from = i;
|
||||||
|
else if (role.Position == position)
|
||||||
|
index_to = i;
|
||||||
|
if (index_from != -1 && index_to != -1) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index_from == -1 || index_to == -1) return;
|
||||||
|
|
||||||
|
int dir;
|
||||||
|
size_t range_from, range_to;
|
||||||
|
if (index_to > index_from) {
|
||||||
|
dir = 1;
|
||||||
|
range_from = index_from + 1;
|
||||||
|
range_to = index_to + 1;
|
||||||
|
} else {
|
||||||
|
dir = -1;
|
||||||
|
range_from = index_to;
|
||||||
|
range_to = index_from;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModifyGuildRolePositionsObject obj;
|
||||||
|
|
||||||
|
obj.Positions.push_back({ roles[index_from].ID, position });
|
||||||
|
for (size_t i = range_from; i < range_to; i++)
|
||||||
|
obj.Positions.push_back({ roles[i].ID, roles[i].Position + dir });
|
||||||
|
|
||||||
|
m_http.MakePATCH("/guilds/" + std::to_string(guild_id) + "/roles", nlohmann::json(obj).dump(), [this, callback](const http::response_type &response) {
|
||||||
|
callback(CheckCode(response));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiscordClient::CanModifyRole(Snowflake guild_id, Snowflake role_id, Snowflake user_id) const {
|
||||||
|
const auto guild = *GetGuild(guild_id);
|
||||||
|
if (guild.OwnerID == user_id) return true;
|
||||||
|
const auto role = *GetRole(role_id);
|
||||||
|
const auto has_modify = HasGuildPermission(user_id, guild_id, Permission::MANAGE_CHANNELS);
|
||||||
|
const auto highest = GetMemberHighestRole(guild_id, user_id);
|
||||||
|
return has_modify && highest.has_value() && highest->Position > role.Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiscordClient::CanModifyRole(Snowflake guild_id, Snowflake role_id) const {
|
||||||
|
return CanModifyRole(guild_id, role_id, GetUserData().ID);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<BanData> DiscordClient::GetBansInGuild(Snowflake guild_id) {
|
std::vector<BanData> DiscordClient::GetBansInGuild(Snowflake guild_id) {
|
||||||
return m_store.GetBans(guild_id);
|
return m_store.GetBans(guild_id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,10 @@ public:
|
|||||||
void ModifyRoleName(Snowflake guild_id, Snowflake role_id, const Glib::ustring &name, sigc::slot<void(bool success)> callback);
|
void ModifyRoleName(Snowflake guild_id, Snowflake role_id, const Glib::ustring &name, sigc::slot<void(bool success)> callback);
|
||||||
void ModifyRoleColor(Snowflake guild_id, Snowflake role_id, uint32_t color, sigc::slot<void(bool success)> callback);
|
void ModifyRoleColor(Snowflake guild_id, Snowflake role_id, uint32_t color, sigc::slot<void(bool success)> callback);
|
||||||
void ModifyRoleColor(Snowflake guild_id, Snowflake role_id, Gdk::RGBA color, sigc::slot<void(bool success)> callback);
|
void ModifyRoleColor(Snowflake guild_id, Snowflake role_id, Gdk::RGBA color, sigc::slot<void(bool success)> callback);
|
||||||
|
void ModifyRolePosition(Snowflake guild_id, Snowflake role_id, int position, sigc::slot<void(bool success)> callback);
|
||||||
|
|
||||||
|
bool CanModifyRole(Snowflake guild_id, Snowflake role_id) const;
|
||||||
|
bool CanModifyRole(Snowflake guild_id, Snowflake role_id, Snowflake user_id) const;
|
||||||
|
|
||||||
// real client doesn't seem to use the single role endpoints so neither do we
|
// real client doesn't seem to use the single role endpoints so neither do we
|
||||||
template<typename Iter>
|
template<typename Iter>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "httpclient.hpp"
|
#include "httpclient.hpp"
|
||||||
#include "httpclient.hpp"
|
|
||||||
|
|
||||||
//#define USE_LOCAL_PROXY
|
//#define USE_LOCAL_PROXY
|
||||||
HTTPClient::HTTPClient(std::string api_base)
|
HTTPClient::HTTPClient(std::string api_base)
|
||||||
|
|||||||
@@ -376,3 +376,12 @@ void to_json(nlohmann::json &j, const ModifyGuildRoleObject &m) {
|
|||||||
if (m.Permissions.has_value())
|
if (m.Permissions.has_value())
|
||||||
j["permissions"] = std::to_string(static_cast<uint64_t>(*m.Permissions));
|
j["permissions"] = std::to_string(static_cast<uint64_t>(*m.Permissions));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void to_json(nlohmann::json &j, const ModifyGuildRolePositionsObject::PositionParam &m) {
|
||||||
|
j["id"] = m.ID;
|
||||||
|
JS_IF("position", m.Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_json(nlohmann::json &j, const ModifyGuildRolePositionsObject &m) {
|
||||||
|
j = m.Positions;
|
||||||
|
}
|
||||||
|
|||||||
@@ -526,3 +526,15 @@ struct ModifyGuildRoleObject {
|
|||||||
|
|
||||||
friend void to_json(nlohmann::json &j, const ModifyGuildRoleObject &m);
|
friend void to_json(nlohmann::json &j, const ModifyGuildRoleObject &m);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ModifyGuildRolePositionsObject {
|
||||||
|
struct PositionParam {
|
||||||
|
Snowflake ID;
|
||||||
|
std::optional<int> Position; // no idea why this can be optional
|
||||||
|
|
||||||
|
friend void to_json(nlohmann::json &j, const PositionParam &m);
|
||||||
|
};
|
||||||
|
std::vector<PositionParam> Positions;
|
||||||
|
|
||||||
|
friend void to_json(nlohmann::json &j, const ModifyGuildRolePositionsObject &m);
|
||||||
|
};
|
||||||
|
|||||||
@@ -28,23 +28,13 @@ void GuildSettingsRolesPane::OnRoleSelect(Snowflake role_id) {
|
|||||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||||
const auto role = *discord.GetRole(role_id);
|
const auto role = *discord.GetRole(role_id);
|
||||||
m_roles_perms.SetRole(role);
|
m_roles_perms.SetRole(role);
|
||||||
|
m_roles_perms.set_sensitive(discord.CanModifyRole(GuildID, role_id));
|
||||||
const auto self_id = discord.GetUserData().ID;
|
|
||||||
|
|
||||||
const auto is_owner = discord.GetGuild(GuildID)->OwnerID == self_id;
|
|
||||||
if (is_owner)
|
|
||||||
m_roles_perms.set_sensitive(true);
|
|
||||||
else {
|
|
||||||
const bool can_modify = discord.HasGuildPermission(self_id, GuildID, Permission::MANAGE_ROLES);
|
|
||||||
if (!can_modify) {
|
|
||||||
m_roles_perms.set_sensitive(false);
|
|
||||||
} else {
|
|
||||||
const auto highest = discord.GetMemberHighestRole(GuildID, self_id);
|
|
||||||
m_roles_perms.set_sensitive(highest.has_value() && highest->Position > role.Position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::vector<Gtk::TargetEntry> g_target_entries = {
|
||||||
|
Gtk::TargetEntry("GTK_LIST_ROLES_ROW", Gtk::TARGET_SAME_APP, 0)
|
||||||
|
};
|
||||||
|
|
||||||
GuildSettingsRolesPaneRoles::GuildSettingsRolesPaneRoles(Snowflake guild_id)
|
GuildSettingsRolesPaneRoles::GuildSettingsRolesPaneRoles(Snowflake guild_id)
|
||||||
: Gtk::Box(Gtk::ORIENTATION_VERTICAL)
|
: Gtk::Box(Gtk::ORIENTATION_VERTICAL)
|
||||||
, GuildID(guild_id) {
|
, GuildID(guild_id) {
|
||||||
@@ -61,19 +51,47 @@ GuildSettingsRolesPaneRoles::GuildSettingsRolesPaneRoles(Snowflake guild_id)
|
|||||||
m_signal_role_select.emit(selected->RoleID);
|
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<GuildSettingsRolesPaneRolesListItem *>(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 (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](bool success) {
|
||||||
|
if (!success) {
|
||||||
|
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();
|
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||||
discord.signal_role_create().connect(sigc::mem_fun(*this, &GuildSettingsRolesPaneRoles::OnRoleCreate));
|
discord.signal_role_create().connect(sigc::mem_fun(*this, &GuildSettingsRolesPaneRoles::OnRoleCreate));
|
||||||
discord.signal_role_delete().connect(sigc::mem_fun(*this, &GuildSettingsRolesPaneRoles::OnRoleDelete));
|
discord.signal_role_delete().connect(sigc::mem_fun(*this, &GuildSettingsRolesPaneRoles::OnRoleDelete));
|
||||||
|
|
||||||
const auto guild = *discord.GetGuild(GuildID);
|
const auto guild = *discord.GetGuild(GuildID);
|
||||||
const auto roles = guild.FetchRoles();
|
const auto roles = guild.FetchRoles();
|
||||||
|
const bool can_modify = discord.HasGuildPermission(discord.GetUserData().ID, GuildID, Permission::MANAGE_ROLES);
|
||||||
for (const auto &role : roles) {
|
for (const auto &role : roles) {
|
||||||
auto *row = Gtk::manage(new GuildSettingsRolesPaneRolesListItem(guild, role));
|
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_margin_start(5);
|
||||||
row->set_halign(Gtk::ALIGN_FILL);
|
row->set_halign(Gtk::ALIGN_FILL);
|
||||||
row->show();
|
row->show();
|
||||||
m_rows[role.ID] = row;
|
m_rows[role.ID] = row;
|
||||||
m_list.add(*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 {
|
m_list.set_sort_func([this](Gtk::ListBoxRow *rowa_, Gtk::ListBoxRow *rowb_) -> int {
|
||||||
@@ -108,12 +126,16 @@ GuildSettingsRolesPaneRoles::GuildSettingsRolesPaneRoles(Snowflake guild_id)
|
|||||||
void GuildSettingsRolesPaneRoles::OnRoleCreate(Snowflake guild_id, Snowflake role_id) {
|
void GuildSettingsRolesPaneRoles::OnRoleCreate(Snowflake guild_id, Snowflake role_id) {
|
||||||
if (guild_id != GuildID) return;
|
if (guild_id != GuildID) return;
|
||||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
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 guild = *discord.GetGuild(guild_id);
|
||||||
const auto role = *discord.GetRole(role_id);
|
const auto role = *discord.GetRole(role_id);
|
||||||
auto *row = Gtk::manage(new GuildSettingsRolesPaneRolesListItem(guild, role));
|
auto *row = Gtk::manage(new GuildSettingsRolesPaneRolesListItem(guild, role));
|
||||||
row->show();
|
row->show();
|
||||||
m_rows[role_id] = row;
|
m_rows[role_id] = row;
|
||||||
m_list.add(*row);
|
if (can_modify)
|
||||||
|
m_list.add_draggable(row);
|
||||||
|
else
|
||||||
|
m_list.add(*row);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuildSettingsRolesPaneRoles::OnRoleDelete(Snowflake guild_id, Snowflake role_id) {
|
void GuildSettingsRolesPaneRoles::OnRoleDelete(Snowflake guild_id, Snowflake role_id) {
|
||||||
@@ -205,6 +227,7 @@ GuildSettingsRolesPaneInfo::GuildSettingsRolesPaneInfo(Snowflake guild_id)
|
|||||||
if (!success) {
|
if (!success) {
|
||||||
m_color_button.set_rgba(IntToRGBA(discord.GetRole(RoleID)->Color));
|
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);
|
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();
|
dlg.run();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -364,6 +387,7 @@ void GuildSettingsRolesPaneInfo::UpdateRoleName() {
|
|||||||
if (!success) {
|
if (!success) {
|
||||||
m_role_name.set_text(discord.GetRole(RoleID)->Name);
|
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);
|
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();
|
dlg.run();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <gtkmm.h>
|
#include <gtkmm.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "../../discord/guild.hpp"
|
#include "../../discord/guild.hpp"
|
||||||
|
#include "../../components/draglistbox.hpp"
|
||||||
|
|
||||||
class GuildSettingsRolesPaneRolesListItem : public Gtk::ListBoxRow {
|
class GuildSettingsRolesPaneRolesListItem : public Gtk::ListBoxRow {
|
||||||
public:
|
public:
|
||||||
@@ -32,7 +33,7 @@ private:
|
|||||||
|
|
||||||
Gtk::Entry m_search;
|
Gtk::Entry m_search;
|
||||||
Gtk::ScrolledWindow m_list_scroll;
|
Gtk::ScrolledWindow m_list_scroll;
|
||||||
Gtk::ListBox m_list;
|
DragListBox m_list;
|
||||||
|
|
||||||
typedef sigc::signal<void, Snowflake /* role_id */> type_signal_role_select;
|
typedef sigc::signal<void, Snowflake /* role_id */> type_signal_role_select;
|
||||||
type_signal_role_select m_signal_role_select;
|
type_signal_role_select m_signal_role_select;
|
||||||
|
|||||||
Reference in New Issue
Block a user