mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 18:37:35 +00:00
IRCClient: Hacking on IRCClient bringup.
This commit is contained in:
parent
aa19735c5a
commit
850c7504a2
11 changed files with 210 additions and 12 deletions
|
@ -44,11 +44,22 @@ void IRCAppWindow::setup_widgets()
|
||||||
auto* subwindow_list = new GListBox(widget);
|
auto* subwindow_list = new GListBox(widget);
|
||||||
subwindow_list->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill);
|
subwindow_list->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill);
|
||||||
subwindow_list->set_preferred_size({ 120, 0 });
|
subwindow_list->set_preferred_size({ 120, 0 });
|
||||||
subwindow_list->add_item("test1");
|
subwindow_list->add_item("Server");
|
||||||
subwindow_list->add_item("test2");
|
subwindow_list->add_item("#test");
|
||||||
subwindow_list->add_item("test3");
|
|
||||||
|
|
||||||
auto* container = new GWidget(widget);
|
m_subwindow_container = new GWidget(widget);
|
||||||
|
m_subwindow_container->set_layout(make<GBoxLayout>(Orientation::Vertical));
|
||||||
|
m_subwindow_container->set_fill_with_background_color(true);
|
||||||
|
m_subwindow_container->set_background_color(Color::Yellow);
|
||||||
|
m_subwindow_container->set_size_policy(SizePolicy::Fill, SizePolicy::Fill);
|
||||||
|
|
||||||
auto* subwindow = new IRCSubWindow("Server", container);
|
create_subwindow(IRCSubWindow::Server, "Server");
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRCAppWindow::create_subwindow(IRCSubWindow::Type type, const String& name)
|
||||||
|
{
|
||||||
|
auto* subwindow = new IRCSubWindow(m_client, type, name, m_subwindow_container);
|
||||||
|
subwindow->set_fill_with_background_color(true);
|
||||||
|
subwindow->set_background_color(Color::Magenta);
|
||||||
|
m_subwindows.append(subwindow);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <LibGUI/GWindow.h>
|
#include <LibGUI/GWindow.h>
|
||||||
#include <LibGUI/GWidget.h>
|
#include <LibGUI/GWidget.h>
|
||||||
#include "IRCClient.h"
|
#include "IRCClient.h"
|
||||||
|
#include "IRCSubWindow.h"
|
||||||
|
|
||||||
class IRCAppWindow : public GWindow {
|
class IRCAppWindow : public GWindow {
|
||||||
public:
|
public:
|
||||||
|
@ -13,5 +14,10 @@ private:
|
||||||
void setup_client();
|
void setup_client();
|
||||||
void setup_widgets();
|
void setup_widgets();
|
||||||
|
|
||||||
|
void create_subwindow(IRCSubWindow::Type, const String& name);
|
||||||
|
|
||||||
IRCClient m_client;
|
IRCClient m_client;
|
||||||
|
|
||||||
|
GWidget* m_subwindow_container { nullptr };
|
||||||
|
Vector<IRCSubWindow*> m_subwindows;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "IRCClient.h"
|
#include "IRCClient.h"
|
||||||
#include "IRCChannel.h"
|
#include "IRCChannel.h"
|
||||||
#include "IRCQuery.h"
|
#include "IRCQuery.h"
|
||||||
|
#include "IRCLogBuffer.h"
|
||||||
|
#include "IRCSubWindow.h"
|
||||||
#include <LibGUI/GNotifier.h>
|
#include <LibGUI/GNotifier.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
@ -17,6 +19,7 @@ IRCClient::IRCClient(const String& address, int port)
|
||||||
: m_hostname(address)
|
: m_hostname(address)
|
||||||
, m_port(port)
|
, m_port(port)
|
||||||
, m_nickname("anon")
|
, m_nickname("anon")
|
||||||
|
, m_log(IRCLogBuffer::create())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +168,7 @@ void IRCClient::process_line()
|
||||||
msg.arguments.append(String(current_parameter.data(), current_parameter.size()));
|
msg.arguments.append(String(current_parameter.data(), current_parameter.size()));
|
||||||
msg.prefix = String(prefix.data(), prefix.size());
|
msg.prefix = String(prefix.data(), prefix.size());
|
||||||
msg.command = String(command.data(), command.size());
|
msg.command = String(command.data(), command.size());
|
||||||
handle(msg);
|
handle(msg, String(m_line_buffer.data(), m_line_buffer.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRCClient::send(const String& text)
|
void IRCClient::send(const String& text)
|
||||||
|
@ -198,7 +201,7 @@ void IRCClient::join_channel(const String& channel_name)
|
||||||
send(String::format("JOIN %s\r\n", channel_name.characters()));
|
send(String::format("JOIN %s\r\n", channel_name.characters()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRCClient::handle(const Message& msg)
|
void IRCClient::handle(const Message& msg, const String& verbatim)
|
||||||
{
|
{
|
||||||
printf("IRCClient::execute: prefix='%s', command='%s', arguments=%d\n",
|
printf("IRCClient::execute: prefix='%s', command='%s', arguments=%d\n",
|
||||||
msg.prefix.characters(),
|
msg.prefix.characters(),
|
||||||
|
@ -231,6 +234,8 @@ void IRCClient::handle(const Message& msg)
|
||||||
|
|
||||||
if (msg.command == "PRIVMSG")
|
if (msg.command == "PRIVMSG")
|
||||||
return handle_privmsg(msg);
|
return handle_privmsg(msg);
|
||||||
|
|
||||||
|
m_log->add_message(0, "Server", verbatim);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IRCClient::is_nick_prefix(char ch) const
|
bool IRCClient::is_nick_prefix(char ch) const
|
||||||
|
@ -297,7 +302,7 @@ void IRCClient::handle_ping(const Message& msg)
|
||||||
{
|
{
|
||||||
if (msg.arguments.size() < 0)
|
if (msg.arguments.size() < 0)
|
||||||
return;
|
return;
|
||||||
m_server_messages.enqueue(String::format("Ping? Pong! %s\n", msg.arguments[0].characters()));
|
m_log->add_message(0, "", String::format("Ping? Pong! %s\n", msg.arguments[0].characters()));
|
||||||
send_pong(msg.arguments[0]);
|
send_pong(msg.arguments[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,3 +344,30 @@ void IRCClient::handle_namreply(const Message& msg)
|
||||||
|
|
||||||
channel.dump();
|
channel.dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IRCClient::register_subwindow(IRCSubWindow& subwindow)
|
||||||
|
{
|
||||||
|
if (subwindow.type() == IRCSubWindow::Server) {
|
||||||
|
m_server_subwindow = &subwindow;
|
||||||
|
subwindow.set_log_buffer(*m_log);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (subwindow.type() == IRCSubWindow::Channel) {
|
||||||
|
auto it = m_channels.find(subwindow.name());
|
||||||
|
ASSERT(it != m_channels.end());
|
||||||
|
auto& channel = *(*it).value;
|
||||||
|
subwindow.set_log_buffer(channel.log());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (subwindow.type() == IRCSubWindow::Query) {
|
||||||
|
subwindow.set_log_buffer(ensure_query(subwindow.name()).log());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRCClient::unregister_subwindow(IRCSubWindow& subwindow)
|
||||||
|
{
|
||||||
|
if (subwindow.type() == IRCSubWindow::Server) {
|
||||||
|
m_server_subwindow = &subwindow;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
#include <AK/CircularQueue.h>
|
#include <AK/CircularQueue.h>
|
||||||
#include <AK/Function.h>
|
#include <AK/Function.h>
|
||||||
|
#include "IRCLogBuffer.h"
|
||||||
|
|
||||||
class IRCChannel;
|
class IRCChannel;
|
||||||
class IRCQuery;
|
class IRCQuery;
|
||||||
|
class IRCSubWindow;
|
||||||
class GNotifier;
|
class GNotifier;
|
||||||
|
|
||||||
class IRCClient {
|
class IRCClient {
|
||||||
|
@ -31,6 +33,9 @@ public:
|
||||||
Function<void(const String& name)> on_query_message;
|
Function<void(const String& name)> on_query_message;
|
||||||
Function<void()> on_server_message;
|
Function<void()> on_server_message;
|
||||||
|
|
||||||
|
void register_subwindow(IRCSubWindow&);
|
||||||
|
void unregister_subwindow(IRCSubWindow&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Message {
|
struct Message {
|
||||||
String prefix;
|
String prefix;
|
||||||
|
@ -48,7 +53,7 @@ private:
|
||||||
void handle_ping(const Message&);
|
void handle_ping(const Message&);
|
||||||
void handle_namreply(const Message&);
|
void handle_namreply(const Message&);
|
||||||
void handle_privmsg(const Message&);
|
void handle_privmsg(const Message&);
|
||||||
void handle(const Message&);
|
void handle(const Message&, const String& verbatim);
|
||||||
IRCQuery& ensure_query(const String& name);
|
IRCQuery& ensure_query(const String& name);
|
||||||
|
|
||||||
String m_hostname;
|
String m_hostname;
|
||||||
|
@ -61,5 +66,7 @@ private:
|
||||||
HashMap<String, RetainPtr<IRCChannel>> m_channels;
|
HashMap<String, RetainPtr<IRCChannel>> m_channels;
|
||||||
HashMap<String, RetainPtr<IRCQuery>> m_queries;
|
HashMap<String, RetainPtr<IRCQuery>> m_queries;
|
||||||
|
|
||||||
CircularQueue<String, 1024> m_server_messages;
|
IRCSubWindow* m_server_subwindow { nullptr };
|
||||||
|
|
||||||
|
Retained<IRCLogBuffer> m_log;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "IRCLogBuffer.h"
|
#include "IRCLogBuffer.h"
|
||||||
|
#include "IRCLogBufferModel.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
@ -9,6 +10,7 @@ Retained<IRCLogBuffer> IRCLogBuffer::create()
|
||||||
|
|
||||||
IRCLogBuffer::IRCLogBuffer()
|
IRCLogBuffer::IRCLogBuffer()
|
||||||
{
|
{
|
||||||
|
m_model = new IRCLogBufferModel(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
IRCLogBuffer::~IRCLogBuffer()
|
IRCLogBuffer::~IRCLogBuffer()
|
||||||
|
@ -18,6 +20,7 @@ IRCLogBuffer::~IRCLogBuffer()
|
||||||
void IRCLogBuffer::add_message(char prefix, const String& name, const String& text)
|
void IRCLogBuffer::add_message(char prefix, const String& name, const String& text)
|
||||||
{
|
{
|
||||||
m_messages.enqueue({ time(nullptr), prefix, name, text });
|
m_messages.enqueue({ time(nullptr), prefix, name, text });
|
||||||
|
m_model->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRCLogBuffer::dump() const
|
void IRCLogBuffer::dump() const
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include <AK/Retainable.h>
|
#include <AK/Retainable.h>
|
||||||
#include <AK/RetainPtr.h>
|
#include <AK/RetainPtr.h>
|
||||||
|
|
||||||
|
class IRCLogBufferModel;
|
||||||
|
|
||||||
class IRCLogBuffer : public Retainable<IRCLogBuffer> {
|
class IRCLogBuffer : public Retainable<IRCLogBuffer> {
|
||||||
public:
|
public:
|
||||||
static Retained<IRCLogBuffer> create();
|
static Retained<IRCLogBuffer> create();
|
||||||
|
@ -24,8 +26,13 @@ public:
|
||||||
|
|
||||||
void dump() const;
|
void dump() const;
|
||||||
|
|
||||||
|
const IRCLogBufferModel* model() const { return m_model; }
|
||||||
|
IRCLogBufferModel* model() { return m_model; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IRCLogBuffer();
|
IRCLogBuffer();
|
||||||
|
|
||||||
|
IRCLogBufferModel* m_model { nullptr };
|
||||||
|
|
||||||
CircularQueue<Message, 1000> m_messages;
|
CircularQueue<Message, 1000> m_messages;
|
||||||
};
|
};
|
||||||
|
|
65
Applications/IRCClient/IRCLogBufferModel.cpp
Normal file
65
Applications/IRCClient/IRCLogBufferModel.cpp
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#include "IRCLogBufferModel.h"
|
||||||
|
#include "IRCLogBuffer.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
IRCLogBufferModel::IRCLogBufferModel(Retained<IRCLogBuffer>&& log_buffer)
|
||||||
|
: m_log_buffer(move(log_buffer))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IRCLogBufferModel::~IRCLogBufferModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int IRCLogBufferModel::row_count() const
|
||||||
|
{
|
||||||
|
return m_log_buffer->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int IRCLogBufferModel::column_count() const
|
||||||
|
{
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
String IRCLogBufferModel::column_name(int column) const
|
||||||
|
{
|
||||||
|
switch (column) {
|
||||||
|
case Column::Timestamp: return "Time";
|
||||||
|
case Column::Prefix: return "@";
|
||||||
|
case Column::Name: return "Name";
|
||||||
|
case Column::Text: return "Text";
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
GTableModel::ColumnMetadata IRCLogBufferModel::column_metadata(int column) const
|
||||||
|
{
|
||||||
|
switch (column) {
|
||||||
|
case Column::Timestamp: return { 90, TextAlignment::CenterLeft };
|
||||||
|
case Column::Prefix: return { 10, TextAlignment::CenterLeft };
|
||||||
|
case Column::Name: return { 70, TextAlignment::CenterRight };
|
||||||
|
case Column::Text: return { 400, TextAlignment::CenterLeft };
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
GVariant IRCLogBufferModel::data(const GModelIndex& index, Role role) const
|
||||||
|
{
|
||||||
|
auto& entry = m_log_buffer->at(index.row());
|
||||||
|
switch (index.column()) {
|
||||||
|
case Column::Timestamp: return String::format("%u", entry.timestamp);
|
||||||
|
case Column::Prefix: return entry.prefix;
|
||||||
|
case Column::Name: return entry.sender;
|
||||||
|
case Column::Text: return entry.text;
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRCLogBufferModel::update()
|
||||||
|
{
|
||||||
|
did_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRCLogBufferModel::activate(const GModelIndex&)
|
||||||
|
{
|
||||||
|
}
|
29
Applications/IRCClient/IRCLogBufferModel.h
Normal file
29
Applications/IRCClient/IRCLogBufferModel.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibGUI/GTableModel.h>
|
||||||
|
|
||||||
|
class IRCLogBuffer;
|
||||||
|
|
||||||
|
class IRCLogBufferModel final : public GTableModel {
|
||||||
|
public:
|
||||||
|
enum Column {
|
||||||
|
Timestamp = 0,
|
||||||
|
Prefix,
|
||||||
|
Name,
|
||||||
|
Text,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit IRCLogBufferModel(Retained<IRCLogBuffer>&&);
|
||||||
|
virtual ~IRCLogBufferModel() 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;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Retained<IRCLogBuffer> m_log_buffer;
|
||||||
|
};
|
|
@ -1,11 +1,30 @@
|
||||||
#include "IRCSubWindow.h"
|
#include "IRCSubWindow.h"
|
||||||
|
#include "IRCClient.h"
|
||||||
|
#include "IRCLogBufferModel.h"
|
||||||
|
#include <LibGUI/GBoxLayout.h>
|
||||||
|
#include <LibGUI/GTableView.h>
|
||||||
|
#include <LibGUI/GTextBox.h>
|
||||||
|
|
||||||
IRCSubWindow::IRCSubWindow(const String& name, GWidget* parent)
|
IRCSubWindow::IRCSubWindow(IRCClient& client, Type type, const String& name, GWidget* parent)
|
||||||
: GWidget(parent)
|
: GWidget(parent)
|
||||||
|
, m_client(client)
|
||||||
|
, m_type(type)
|
||||||
, m_name(name)
|
, m_name(name)
|
||||||
{
|
{
|
||||||
|
set_layout(make<GBoxLayout>(Orientation::Vertical));
|
||||||
|
m_table_view = new GTableView(this);
|
||||||
|
m_table_view->set_font(Font::default_fixed_width_font());
|
||||||
|
|
||||||
|
m_client.register_subwindow(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
IRCSubWindow::~IRCSubWindow()
|
IRCSubWindow::~IRCSubWindow()
|
||||||
{
|
{
|
||||||
|
m_client.unregister_subwindow(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRCSubWindow::set_log_buffer(const IRCLogBuffer& log_buffer)
|
||||||
|
{
|
||||||
|
m_log_buffer = &log_buffer;
|
||||||
|
m_table_view->set_model(OwnPtr<IRCLogBufferModel>((IRCLogBufferModel*)log_buffer.model()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,32 @@
|
||||||
|
|
||||||
#include <LibGUI/GWidget.h>
|
#include <LibGUI/GWidget.h>
|
||||||
|
|
||||||
|
class IRCClient;
|
||||||
|
class IRCLogBuffer;
|
||||||
|
class GTableView;
|
||||||
|
|
||||||
class IRCSubWindow : public GWidget {
|
class IRCSubWindow : public GWidget {
|
||||||
public:
|
public:
|
||||||
explicit IRCSubWindow(const String& name, GWidget* parent);
|
enum Type {
|
||||||
|
Server,
|
||||||
|
Channel,
|
||||||
|
Query,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit IRCSubWindow(IRCClient&, Type, const String& name, GWidget* parent);
|
||||||
virtual ~IRCSubWindow() override;
|
virtual ~IRCSubWindow() override;
|
||||||
|
|
||||||
String name() const { return m_name; }
|
String name() const { return m_name; }
|
||||||
void set_name(const String& name) { m_name = name; }
|
void set_name(const String& name) { m_name = name; }
|
||||||
|
|
||||||
|
Type type() const { return m_type; }
|
||||||
|
|
||||||
|
void set_log_buffer(const IRCLogBuffer&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
IRCClient& m_client;
|
||||||
|
Type m_type;
|
||||||
String m_name;
|
String m_name;
|
||||||
|
GTableView* m_table_view { nullptr };
|
||||||
|
RetainPtr<IRCLogBuffer> m_log_buffer;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@ OBJS = \
|
||||||
IRCChannel.o \
|
IRCChannel.o \
|
||||||
IRCQuery.o \
|
IRCQuery.o \
|
||||||
IRCLogBuffer.o \
|
IRCLogBuffer.o \
|
||||||
|
IRCLogBufferModel.o \
|
||||||
IRCAppWindow.o \
|
IRCAppWindow.o \
|
||||||
IRCSubWindow.o \
|
IRCSubWindow.o \
|
||||||
main.o
|
main.o
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue