From 491aa112ab817af2ce8107b449c92636d4e0f049 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 15 Mar 2019 18:25:51 +0100 Subject: [PATCH] IRClient: Add a member list to channel views. --- Applications/IRCClient/IRCChannel.cpp | 2 + Applications/IRCClient/IRCChannel.h | 8 +++ .../IRCClient/IRCChannelMemberListModel.cpp | 59 +++++++++++++++++++ .../IRCClient/IRCChannelMemberListModel.h | 26 ++++++++ Applications/IRCClient/IRCClient.h | 5 +- Applications/IRCClient/IRCClientWindow.cpp | 17 +++++- Applications/IRCClient/Makefile | 1 + 7 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 Applications/IRCClient/IRCChannelMemberListModel.cpp create mode 100644 Applications/IRCClient/IRCChannelMemberListModel.h diff --git a/Applications/IRCClient/IRCChannel.cpp b/Applications/IRCClient/IRCChannel.cpp index 45e7acb0b7..a96ae54404 100644 --- a/Applications/IRCClient/IRCChannel.cpp +++ b/Applications/IRCClient/IRCChannel.cpp @@ -1,5 +1,6 @@ #include "IRCChannel.h" #include "IRCClient.h" +#include "IRCChannelMemberListModel.h" #include #include @@ -8,6 +9,7 @@ IRCChannel::IRCChannel(IRCClient& client, const String& name) , m_name(name) , m_log(IRCLogBuffer::create()) { + m_member_model = new IRCChannelMemberListModel(*this); } IRCChannel::~IRCChannel() diff --git a/Applications/IRCClient/IRCChannel.h b/Applications/IRCClient/IRCChannel.h index b0c85bd132..6e5e846dc3 100644 --- a/Applications/IRCClient/IRCChannel.h +++ b/Applications/IRCClient/IRCChannel.h @@ -8,6 +8,7 @@ #include "IRCLogBuffer.h" class IRCClient; +class IRCChannelMemberListModel; class IRCChannel : public Retainable { public: @@ -31,6 +32,12 @@ public: const IRCLogBuffer& log() const { return *m_log; } IRCLogBuffer& log() { return *m_log; } + IRCChannelMemberListModel* member_model() { return m_member_model; } + const IRCChannelMemberListModel* member_model() const { return m_member_model; } + + int member_count() const { return m_members.size(); } + String member_at(int i) { return m_members[i].name; } + private: IRCChannel(IRCClient&, const String&); @@ -44,4 +51,5 @@ private: bool m_open { false }; Retained m_log; + IRCChannelMemberListModel* m_member_model { nullptr }; }; diff --git a/Applications/IRCClient/IRCChannelMemberListModel.cpp b/Applications/IRCClient/IRCChannelMemberListModel.cpp new file mode 100644 index 0000000000..21830ec4a9 --- /dev/null +++ b/Applications/IRCClient/IRCChannelMemberListModel.cpp @@ -0,0 +1,59 @@ +#include "IRCChannelMemberListModel.h" +#include "IRCChannel.h" +#include +#include + +IRCChannelMemberListModel::IRCChannelMemberListModel(IRCChannel& channel) + : m_channel(channel) +{ + set_activates_on_selection(true); +} + +IRCChannelMemberListModel::~IRCChannelMemberListModel() +{ +} + +int IRCChannelMemberListModel::row_count() const +{ + return m_channel.member_count(); +} + +int IRCChannelMemberListModel::column_count() const +{ + return 1; +} + +String IRCChannelMemberListModel::column_name(int column) const +{ + switch (column) { + case Column::Name: return "Name"; + } + ASSERT_NOT_REACHED(); +} + +GTableModel::ColumnMetadata IRCChannelMemberListModel::column_metadata(int column) const +{ + switch (column) { + case Column::Name: return { 70, TextAlignment::CenterLeft }; + } + ASSERT_NOT_REACHED(); +} + +GVariant IRCChannelMemberListModel::data(const GModelIndex& index, Role) const +{ + switch (index.column()) { + case Column::Name: return m_channel.member_at(index.row()); + } + ASSERT_NOT_REACHED(); +} + +void IRCChannelMemberListModel::update() +{ + did_update(); +} + +void IRCChannelMemberListModel::activate(const GModelIndex& index) +{ + if (on_activation) + on_activation(m_channel.member_at(index.row())); +} diff --git a/Applications/IRCClient/IRCChannelMemberListModel.h b/Applications/IRCClient/IRCChannelMemberListModel.h new file mode 100644 index 0000000000..89aaf5b4cc --- /dev/null +++ b/Applications/IRCClient/IRCChannelMemberListModel.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +class IRCChannel; + +class IRCChannelMemberListModel final : public GTableModel { +public: + enum Column { Name }; + explicit IRCChannelMemberListModel(IRCChannel&); + virtual ~IRCChannelMemberListModel() override; + + virtual int row_count() const override; + virtual int column_count() const override; + virtual String column_name(int column) const override; + virtual ColumnMetadata column_metadata(int column) const override; + virtual GVariant data(const GModelIndex&, Role = Role::Display) const override; + virtual void update() override; + virtual void activate(const GModelIndex&) override; + + Function on_activation; + +private: + IRCChannel& m_channel; +}; diff --git a/Applications/IRCClient/IRCClient.h b/Applications/IRCClient/IRCClient.h index 7c341db494..e391ecb7bc 100644 --- a/Applications/IRCClient/IRCClient.h +++ b/Applications/IRCClient/IRCClient.h @@ -51,6 +51,9 @@ public: void handle_user_input_in_query(const String& query_name, const String&); void handle_user_input_in_server(const String&); + IRCQuery& ensure_query(const String& name); + IRCChannel& ensure_channel(const String& name); + private: struct Message { String prefix; @@ -70,8 +73,6 @@ private: void handle_namreply(const Message&); void handle_privmsg(const Message&); void handle(const Message&, const String& verbatim); - IRCQuery& ensure_query(const String& name); - IRCChannel& ensure_channel(const String& name); String m_hostname; int m_port { 0 }; diff --git a/Applications/IRCClient/IRCClientWindow.cpp b/Applications/IRCClient/IRCClientWindow.cpp index c4eb12ae80..d2d35630fe 100644 --- a/Applications/IRCClient/IRCClientWindow.cpp +++ b/Applications/IRCClient/IRCClientWindow.cpp @@ -1,5 +1,7 @@ #include "IRCClientWindow.h" #include "IRCClient.h" +#include "IRCChannel.h" +#include "IRCChannelMemberListModel.h" #include "IRCLogBufferModel.h" #include #include @@ -13,10 +15,23 @@ IRCClientWindow::IRCClientWindow(IRCClient& client, Type type, const String& nam , m_name(name) { set_layout(make(Orientation::Vertical)); - m_table_view = new GTableView(this); + + // Make a container for the log buffer view + optional member list. + GWidget* container = new GWidget(this); + container->set_layout(make(Orientation::Horizontal)); + + m_table_view = new GTableView(container); m_table_view->set_headers_visible(false); m_table_view->set_font(Font::default_fixed_width_font()); + if (m_type == Channel) { + auto* member_view = new GTableView(container); + member_view->set_headers_visible(false); + member_view->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill); + member_view->set_preferred_size({ 100, 0 }); + member_view->set_model(OwnPtr(m_client.ensure_channel(m_name).member_model())); + } + m_text_editor = new GTextEditor(GTextEditor::SingleLine, this); m_text_editor->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed); m_text_editor->set_preferred_size({ 0, 18 }); diff --git a/Applications/IRCClient/Makefile b/Applications/IRCClient/Makefile index deb9ba1130..d627be9e5c 100644 --- a/Applications/IRCClient/Makefile +++ b/Applications/IRCClient/Makefile @@ -7,6 +7,7 @@ OBJS = \ IRCAppWindow.o \ IRCClientWindow.o \ IRCClientWindowListModel.o \ + IRCChannelMemberListModel.o \ main.o APP = IRCClient