mirror of
https://github.com/uowuo/abaddon.git
synced 2024-09-20 06:51:51 +00:00
start channel list refactor for server list
This commit is contained in:
parent
1895a8f133
commit
3e0cd83dd6
|
@ -1,4 +1,4 @@
|
|||
#include "channelscellrenderer.hpp"
|
||||
#include "cellrendererchannels.hpp"
|
||||
|
||||
constexpr static int MentionsRightPad = 7;
|
||||
#ifndef M_PI
|
|
@ -1,6 +1,6 @@
|
|||
#include "channels.hpp"
|
||||
#include "channellist.hpp"
|
||||
#include "imgmanager.hpp"
|
||||
#include "statusindicator.hpp"
|
||||
#include "components/statusindicator.hpp"
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
@ -8,6 +8,7 @@
|
|||
ChannelList::ChannelList()
|
||||
: Glib::ObjectBase(typeid(ChannelList))
|
||||
, m_model(Gtk::TreeStore::create(m_columns))
|
||||
, m_filter_model(Gtk::TreeModelFilter::create(m_model))
|
||||
, m_menu_guild_copy_id("_Copy ID", true)
|
||||
, m_menu_guild_settings("View _Settings", true)
|
||||
, m_menu_guild_leave("_Leave", true)
|
||||
|
@ -36,9 +37,9 @@ ChannelList::ChannelList()
|
|||
, m_menu_thread_mark_as_read("Mark as _Read", true) {
|
||||
get_style_context()->add_class("channel-list");
|
||||
|
||||
// todo: move to method
|
||||
// Filter iters
|
||||
const auto cb = [this](const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn *column) {
|
||||
auto row = *m_model->get_iter(path);
|
||||
auto row = *m_filter_model->get_iter(path);
|
||||
const auto type = row[m_columns.m_type];
|
||||
// text channels should not be allowed to be collapsed
|
||||
// maybe they should be but it seems a little difficult to handle expansion to permit this
|
||||
|
@ -72,13 +73,22 @@ ChannelList::ChannelList()
|
|||
m_view.set_show_expanders(false);
|
||||
m_view.set_enable_search(false);
|
||||
m_view.set_headers_visible(false);
|
||||
m_view.set_model(m_model);
|
||||
m_view.set_model(m_filter_model);
|
||||
m_model->set_sort_column(m_columns.m_sort, Gtk::SORT_ASCENDING);
|
||||
|
||||
m_model->signal_row_inserted().connect([this](const Gtk::TreeModel::Path &path, const Gtk::TreeModel::iterator &iter) {
|
||||
if (m_updating_listing) return;
|
||||
if (auto parent = iter->parent(); parent && (*parent)[m_columns.m_expanded])
|
||||
m_view.expand_row(m_model->get_path(parent), false);
|
||||
if (auto parent = iter->parent(); parent && (*parent)[m_columns.m_expanded]) {
|
||||
const auto filter_path = m_filter_model->convert_child_path_to_path(m_model->get_path(parent));
|
||||
m_view.expand_row(filter_path, false);
|
||||
}
|
||||
});
|
||||
|
||||
m_filter_model->set_visible_func([this](const Gtk::TreeModel::const_iterator &iter) -> bool {
|
||||
if ((*iter)[m_columns.m_type] == RenderType::Guild) {
|
||||
return (*iter)[m_columns.m_id] == 754921263616753776ULL;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
m_view.show();
|
||||
|
@ -594,9 +604,9 @@ void ChannelList::SetActiveChannel(Snowflake id, bool expand_to) {
|
|||
const auto channel_iter = GetIteratorForRowFromID(id);
|
||||
if (channel_iter) {
|
||||
if (expand_to) {
|
||||
m_view.expand_to_path(m_model->get_path(channel_iter));
|
||||
m_view.expand_to_path(m_filter_model->convert_child_path_to_path(m_model->get_path(channel_iter)));
|
||||
}
|
||||
m_view.get_selection()->select(channel_iter);
|
||||
m_view.get_selection()->select(m_filter_model->convert_child_iter_to_iter(channel_iter));
|
||||
} else {
|
||||
m_view.get_selection()->unselect_all();
|
||||
const auto channel = Abaddon::Get().GetDiscordClient().GetChannel(id);
|
||||
|
@ -604,64 +614,17 @@ void ChannelList::SetActiveChannel(Snowflake id, bool expand_to) {
|
|||
auto parent_iter = GetIteratorForRowFromID(*channel->ParentID);
|
||||
if (!parent_iter) return;
|
||||
m_temporary_thread_row = CreateThreadRow(parent_iter->children(), *channel);
|
||||
m_view.get_selection()->select(m_temporary_thread_row);
|
||||
m_view.get_selection()->select(m_filter_model->convert_child_iter_to_iter(m_temporary_thread_row));
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelList::UseExpansionState(const ExpansionStateRoot &root) {
|
||||
auto recurse = [this](auto &self, const ExpansionStateRoot &root) -> void {
|
||||
for (const auto &[id, state] : root.Children) {
|
||||
Gtk::TreeModel::iterator row_iter;
|
||||
if (const auto map_iter = m_tmp_row_map.find(id); map_iter != m_tmp_row_map.end()) {
|
||||
row_iter = map_iter->second;
|
||||
} else if (const auto map_iter = m_tmp_guild_row_map.find(id); map_iter != m_tmp_guild_row_map.end()) {
|
||||
row_iter = map_iter->second;
|
||||
}
|
||||
|
||||
if (row_iter) {
|
||||
if (state.IsExpanded)
|
||||
m_view.expand_row(m_model->get_path(row_iter), false);
|
||||
else
|
||||
m_view.collapse_row(m_model->get_path(row_iter));
|
||||
}
|
||||
|
||||
self(self, state.Children);
|
||||
}
|
||||
};
|
||||
|
||||
for (const auto &[id, state] : root.Children) {
|
||||
if (const auto iter = GetIteratorForTopLevelFromID(id)) {
|
||||
if (state.IsExpanded)
|
||||
m_view.expand_row(m_model->get_path(iter), false);
|
||||
else
|
||||
m_view.collapse_row(m_model->get_path(iter));
|
||||
}
|
||||
|
||||
recurse(recurse, state.Children);
|
||||
}
|
||||
|
||||
m_tmp_row_map.clear();
|
||||
}
|
||||
|
||||
ExpansionStateRoot ChannelList::GetExpansionState() const {
|
||||
ExpansionStateRoot r;
|
||||
|
||||
auto recurse = [this](auto &self, const Gtk::TreeRow &row) -> ExpansionState {
|
||||
ExpansionState r;
|
||||
|
||||
r.IsExpanded = row[m_columns.m_expanded];
|
||||
for (const auto &child : row.children())
|
||||
r.Children.Children[static_cast<Snowflake>(child[m_columns.m_id])] = self(self, child);
|
||||
|
||||
return r;
|
||||
};
|
||||
|
||||
for (const auto &child : m_model->children()) {
|
||||
const auto id = static_cast<Snowflake>(child[m_columns.m_id]);
|
||||
if (static_cast<uint64_t>(id) == 0ULL) continue; // dont save DM header
|
||||
r.Children[id] = recurse(recurse, child);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -969,7 +932,7 @@ void ChannelList::OnRowExpanded(const Gtk::TreeModel::iterator &iter, const Gtk:
|
|||
// restore previous expansion
|
||||
for (auto it = iter->children().begin(); it != iter->children().end(); it++) {
|
||||
if ((*it)[m_columns.m_expanded])
|
||||
m_view.expand_row(m_model->get_path(it), false);
|
||||
m_view.expand_row(m_filter_model->get_path(it), false);
|
||||
}
|
||||
|
||||
// try and restore selection if previous collapsed
|
||||
|
@ -981,11 +944,13 @@ void ChannelList::OnRowExpanded(const Gtk::TreeModel::iterator &iter, const Gtk:
|
|||
}
|
||||
|
||||
bool ChannelList::SelectionFunc(const Glib::RefPtr<Gtk::TreeModel> &model, const Gtk::TreeModel::Path &path, bool is_currently_selected) {
|
||||
if (auto selection = m_view.get_selection())
|
||||
if (auto row = selection->get_selected())
|
||||
m_last_selected = m_model->get_path(row);
|
||||
if (auto selection = m_view.get_selection()) {
|
||||
if (auto row = selection->get_selected()) {
|
||||
m_last_selected = m_filter_model->get_path(row);
|
||||
}
|
||||
}
|
||||
|
||||
auto type = (*m_model->get_iter(path))[m_columns.m_type];
|
||||
auto type = (*model->get_iter(path))[m_columns.m_type];
|
||||
return type == RenderType::TextChannel || type == RenderType::DM || type == RenderType::Thread;
|
||||
}
|
||||
|
||||
|
@ -1139,7 +1104,7 @@ void ChannelList::OnMessageCreate(const Message &msg) {
|
|||
bool ChannelList::OnButtonPressEvent(GdkEventButton *ev) {
|
||||
if (ev->button == GDK_BUTTON_SECONDARY && ev->type == GDK_BUTTON_PRESS) {
|
||||
if (m_view.get_path_at_pos(static_cast<int>(ev->x), static_cast<int>(ev->y), m_path_for_menu)) {
|
||||
auto row = (*m_model->get_iter(m_path_for_menu));
|
||||
auto row = (*m_filter_model->get_iter(m_path_for_menu));
|
||||
switch (static_cast<RenderType>(row[m_columns.m_type])) {
|
||||
case RenderType::Guild:
|
||||
OnGuildSubmenuPopup();
|
|
@ -8,11 +8,12 @@
|
|||
#include <gtkmm/scrolledwindow.h>
|
||||
#include <gtkmm/treemodel.h>
|
||||
#include <gtkmm/treestore.h>
|
||||
#include <gtkmm/treemodelfilter.h>
|
||||
#include <gtkmm/treeview.h>
|
||||
#include <sigc++/sigc++.h>
|
||||
#include "discord/discord.hpp"
|
||||
#include "state.hpp"
|
||||
#include "channelscellrenderer.hpp"
|
||||
#include "cellrendererchannels.hpp"
|
||||
|
||||
constexpr static int GuildIconSize = 24;
|
||||
constexpr static int DMIconSize = 20;
|
||||
|
@ -82,6 +83,7 @@ protected:
|
|||
|
||||
ModelColumns m_columns;
|
||||
Glib::RefPtr<Gtk::TreeStore> m_model;
|
||||
Glib::RefPtr<Gtk::TreeModelFilter> m_filter_model;
|
||||
|
||||
Gtk::TreeModel::iterator AddFolder(const UserSettingsGuildFoldersEntry &folder);
|
||||
Gtk::TreeModel::iterator AddGuild(const GuildData &guild, const Gtk::TreeNodeChildren &root);
|
||||
|
@ -116,7 +118,7 @@ protected:
|
|||
void UpdateCreateDMChannel(const ChannelData &channel);
|
||||
void SetDMChannelIcon(Gtk::TreeIter iter, const ChannelData &dm);
|
||||
|
||||
void RedrawUnreadIndicatorsForChannel(const ChannelData& channel);
|
||||
void RedrawUnreadIndicatorsForChannel(const ChannelData &channel);
|
||||
void OnMessageAck(const MessageAckData &data);
|
||||
void OnMessageCreate(const Message &msg);
|
||||
|
23
src/components/channellist/classic/guildlist.cpp
Normal file
23
src/components/channellist/classic/guildlist.cpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include "guildlist.hpp"
|
||||
#include "guildlistfolderitem.hpp"
|
||||
|
||||
GuildList::GuildList() {
|
||||
set_selection_mode(Gtk::SELECTION_NONE);
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
void GuildList::AddGuild(Snowflake id) {
|
||||
const auto guild = Abaddon::Get().GetDiscordClient().GetGuild(id);
|
||||
if (!guild.has_value()) return;
|
||||
|
||||
auto *item = Gtk::make_managed<GuildListGuildItem>(*guild);
|
||||
item->show();
|
||||
add(*item);
|
||||
}
|
||||
|
||||
void GuildList::Clear() {
|
||||
const auto children = get_children();
|
||||
for (auto child : children) {
|
||||
delete child;
|
||||
}
|
||||
}
|
12
src/components/channellist/classic/guildlist.hpp
Normal file
12
src/components/channellist/classic/guildlist.hpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
#include <gtkmm/listbox.h>
|
||||
#include "discord/snowflake.hpp"
|
||||
|
||||
class GuildList : public Gtk::ListBox {
|
||||
public:
|
||||
GuildList();
|
||||
|
||||
void AddGuild(Snowflake id);
|
||||
|
||||
void Clear();
|
||||
};
|
18
src/components/channellist/classic/guildlistfolderitem.cpp
Normal file
18
src/components/channellist/classic/guildlistfolderitem.cpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include "guildlistfolderitem.hpp"
|
||||
|
||||
GuildListFolderItem::GuildListFolderItem() {
|
||||
m_revealer.add(m_box);
|
||||
m_revealer.set_reveal_child(true);
|
||||
|
||||
m_ev.signal_button_press_event().connect([this](GdkEventButton *event) -> bool {
|
||||
if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY) {
|
||||
m_revealer.set_reveal_child(!m_revealer.get_reveal_child());
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
m_ev.add(m_image);
|
||||
add(m_ev);
|
||||
add(m_revealer);
|
||||
show_all_children();
|
||||
}
|
18
src/components/channellist/classic/guildlistfolderitem.hpp
Normal file
18
src/components/channellist/classic/guildlistfolderitem.hpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
#include <gtkmm/box.h>
|
||||
#include <gtkmm/eventbox.h>
|
||||
#include <gtkmm/image.h>
|
||||
#include <gtkmm/revealer.h>
|
||||
|
||||
#include "guildlistguilditem.hpp"
|
||||
|
||||
class GuildListFolderItem : public Gtk::VBox {
|
||||
public:
|
||||
GuildListFolderItem();
|
||||
|
||||
private:
|
||||
Gtk::EventBox m_ev;
|
||||
Gtk::Image m_image;
|
||||
Gtk::Revealer m_revealer;
|
||||
Gtk::VBox m_box;
|
||||
};
|
29
src/components/channellist/classic/guildlistguilditem.cpp
Normal file
29
src/components/channellist/classic/guildlistguilditem.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include "guildlistguilditem.hpp"
|
||||
|
||||
GuildListGuildItem::GuildListGuildItem(const GuildData &guild)
|
||||
: ID(guild.ID) {
|
||||
m_image.property_pixbuf() = Abaddon::Get().GetImageManager().GetPlaceholder(48);
|
||||
add(m_image);
|
||||
show_all_children();
|
||||
|
||||
signal_button_press_event().connect([this](GdkEventButton *event) -> bool {
|
||||
if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY) {
|
||||
printf("Click %llu\n", (uint64_t)ID);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
set_tooltip_text(guild.Name);
|
||||
|
||||
UpdateIcon();
|
||||
}
|
||||
|
||||
void GuildListGuildItem::UpdateIcon() {
|
||||
const auto guild = Abaddon::Get().GetDiscordClient().GetGuild(ID);
|
||||
if (!guild.has_value()) return;
|
||||
Abaddon::Get().GetImageManager().LoadFromURL(guild->GetIconURL("png", "64"), sigc::mem_fun(*this, &GuildListGuildItem::OnIconFetched));
|
||||
}
|
||||
|
||||
void GuildListGuildItem::OnIconFetched(const Glib::RefPtr<Gdk::Pixbuf> &pb) {
|
||||
m_image.property_pixbuf() = pb->scale_simple(48, 48, Gdk::INTERP_BILINEAR);
|
||||
}
|
17
src/components/channellist/classic/guildlistguilditem.hpp
Normal file
17
src/components/channellist/classic/guildlistguilditem.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
#include <gtkmm/box.h>
|
||||
#include <gtkmm/image.h>
|
||||
#include "discord/guild.hpp"
|
||||
|
||||
class GuildListGuildItem : public Gtk::EventBox {
|
||||
public:
|
||||
GuildListGuildItem(const GuildData &guild);
|
||||
|
||||
Snowflake ID;
|
||||
|
||||
private:
|
||||
void UpdateIcon();
|
||||
void OnIconFetched(const Glib::RefPtr<Gdk::Pixbuf> &pb);
|
||||
|
||||
Gtk::Image m_image;
|
||||
};
|
|
@ -1,4 +1,5 @@
|
|||
#include "mainwindow.hpp"
|
||||
#include "components/channellist/channellist.hpp"
|
||||
|
||||
MainWindow::MainWindow()
|
||||
: m_main_box(Gtk::ORIENTATION_VERTICAL)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#pragma once
|
||||
#include "components/channels.hpp"
|
||||
#include "components/channellist/channellist.hpp"
|
||||
#include "components/chatwindow.hpp"
|
||||
#include "components/memberlist.hpp"
|
||||
#include "components/friendslist.hpp"
|
||||
|
|
Loading…
Reference in New Issue
Block a user