mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 09:02:43 +00:00 
			
		
		
		
	IRCClient: Use a model for the window list.
This commit is contained in:
		
							parent
							
								
									eba5fd3f46
								
							
						
					
					
						commit
						a23dddc56f
					
				
					 7 changed files with 138 additions and 24 deletions
				
			
		|  | @ -1,6 +1,7 @@ | ||||||
| #include "IRCAppWindow.h" | #include "IRCAppWindow.h" | ||||||
| #include "IRCClientWindow.h" | #include "IRCClientWindow.h" | ||||||
| #include <LibGUI/GListBox.h> | #include "IRCClientWindowListModel.h" | ||||||
|  | #include <LibGUI/GTableView.h> | ||||||
| #include <LibGUI/GBoxLayout.h> | #include <LibGUI/GBoxLayout.h> | ||||||
| 
 | 
 | ||||||
| IRCAppWindow::IRCAppWindow() | IRCAppWindow::IRCAppWindow() | ||||||
|  | @ -23,6 +24,10 @@ void IRCAppWindow::setup_client() | ||||||
|         m_client.join_channel("#test"); |         m_client.join_channel("#test"); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |     m_client.on_join = [this] (const String& channel_name) { | ||||||
|  |         ensure_window(IRCClientWindow::Channel, channel_name); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|     m_client.on_query_message = [this] (const String& name) { |     m_client.on_query_message = [this] (const String& name) { | ||||||
|         // FIXME: Update query view.
 |         // FIXME: Update query view.
 | ||||||
|     }; |     }; | ||||||
|  | @ -41,11 +46,10 @@ void IRCAppWindow::setup_widgets() | ||||||
|     set_main_widget(widget); |     set_main_widget(widget); | ||||||
|     widget->set_layout(make<GBoxLayout>(Orientation::Horizontal)); |     widget->set_layout(make<GBoxLayout>(Orientation::Horizontal)); | ||||||
| 
 | 
 | ||||||
|     auto* subwindow_list = new GListBox(widget); |     auto* subwindow_list = new GTableView(widget); | ||||||
|  |     subwindow_list->set_model(OwnPtr<IRCClientWindowListModel>(m_client.client_window_list_model())); | ||||||
|     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("Server"); |  | ||||||
|     subwindow_list->add_item("#test"); |  | ||||||
| 
 | 
 | ||||||
|     m_subwindow_container = new GWidget(widget); |     m_subwindow_container = new GWidget(widget); | ||||||
|     m_subwindow_container->set_layout(make<GBoxLayout>(Orientation::Vertical)); |     m_subwindow_container->set_layout(make<GBoxLayout>(Orientation::Vertical)); | ||||||
|  | @ -54,8 +58,17 @@ void IRCAppWindow::setup_widgets() | ||||||
|     create_subwindow(IRCClientWindow::Server, "Server"); |     create_subwindow(IRCClientWindow::Server, "Server"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void IRCAppWindow::create_subwindow(IRCClientWindow::Type type, const String& name) | IRCClientWindow& IRCAppWindow::create_subwindow(IRCClientWindow::Type type, const String& name) | ||||||
| { | { | ||||||
|     auto* subwindow = new IRCClientWindow(m_client, type, name, m_subwindow_container); |     return *new IRCClientWindow(m_client, type, name, m_subwindow_container); | ||||||
|     m_subwindows.append(subwindow); | } | ||||||
|  | 
 | ||||||
|  | IRCClientWindow& IRCAppWindow::ensure_window(IRCClientWindow::Type type, const String& name) | ||||||
|  | { | ||||||
|  |     for (int i = 0; i < m_client.window_count(); ++i) { | ||||||
|  |         auto& window = m_client.window_at(i); | ||||||
|  |         if (window.name() == name) | ||||||
|  |             return window; | ||||||
|  |     } | ||||||
|  |     return create_subwindow(type, name); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -14,10 +14,10 @@ private: | ||||||
|     void setup_client(); |     void setup_client(); | ||||||
|     void setup_widgets(); |     void setup_widgets(); | ||||||
| 
 | 
 | ||||||
|     void create_subwindow(IRCClientWindow::Type, const String& name); |     IRCClientWindow& create_subwindow(IRCClientWindow::Type, const String& name); | ||||||
|  |     IRCClientWindow& ensure_window(IRCClientWindow::Type, const String& name); | ||||||
| 
 | 
 | ||||||
|     IRCClient m_client; |     IRCClient m_client; | ||||||
| 
 | 
 | ||||||
|     GWidget* m_subwindow_container { nullptr }; |     GWidget* m_subwindow_container { nullptr }; | ||||||
|     Vector<IRCClientWindow*> m_subwindows; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| #include "IRCQuery.h" | #include "IRCQuery.h" | ||||||
| #include "IRCLogBuffer.h" | #include "IRCLogBuffer.h" | ||||||
| #include "IRCClientWindow.h" | #include "IRCClientWindow.h" | ||||||
|  | #include "IRCClientWindowListModel.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> | ||||||
|  | @ -21,6 +22,7 @@ IRCClient::IRCClient(const String& address, int port) | ||||||
|     , m_nickname("anon") |     , m_nickname("anon") | ||||||
|     , m_log(IRCLogBuffer::create()) |     , m_log(IRCLogBuffer::create()) | ||||||
| { | { | ||||||
|  |     m_client_window_list_model = new IRCClientWindowListModel(*this); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| IRCClient::~IRCClient() | IRCClient::~IRCClient() | ||||||
|  | @ -62,11 +64,11 @@ bool IRCClient::connect() | ||||||
|     m_notifier = make<GNotifier>(m_socket_fd, GNotifier::Read); |     m_notifier = make<GNotifier>(m_socket_fd, GNotifier::Read); | ||||||
|     m_notifier->on_ready_to_read = [this] (GNotifier&) { receive_from_server(); }; |     m_notifier->on_ready_to_read = [this] (GNotifier&) { receive_from_server(); }; | ||||||
| 
 | 
 | ||||||
|     if (on_connect) |  | ||||||
|         on_connect(); |  | ||||||
| 
 |  | ||||||
|     send_user(); |     send_user(); | ||||||
|     send_nick(); |     send_nick(); | ||||||
|  | 
 | ||||||
|  |     if (on_connect) | ||||||
|  |         on_connect(); | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -102,9 +104,6 @@ void IRCClient::receive_from_server() | ||||||
| 
 | 
 | ||||||
| void IRCClient::process_line() | void IRCClient::process_line() | ||||||
| { | { | ||||||
| #if 0 |  | ||||||
|     printf("Process line: '%s'\n", line.characters()); |  | ||||||
| #endif |  | ||||||
|     Message msg; |     Message msg; | ||||||
|     Vector<char> prefix; |     Vector<char> prefix; | ||||||
|     Vector<char> command; |     Vector<char> command; | ||||||
|  | @ -118,8 +117,7 @@ void IRCClient::process_line() | ||||||
|         InTrailingParameter, |         InTrailingParameter, | ||||||
|     } state = Start; |     } state = Start; | ||||||
| 
 | 
 | ||||||
|     for (int i = 0; i < m_line_buffer.size(); ++i) { |     for (char ch : m_line_buffer) { | ||||||
|         char ch = m_line_buffer[i]; |  | ||||||
|         switch (state) { |         switch (state) { | ||||||
|         case Start: |         case Start: | ||||||
|             if (ch == ':') { |             if (ch == ':') { | ||||||
|  | @ -316,6 +314,8 @@ void IRCClient::handle_join(const Message& msg) | ||||||
|     ASSERT(it == m_channels.end()); |     ASSERT(it == m_channels.end()); | ||||||
|     auto channel = IRCChannel::create(*this, channel_name); |     auto channel = IRCChannel::create(*this, channel_name); | ||||||
|     m_channels.set(channel_name, move(channel)); |     m_channels.set(channel_name, move(channel)); | ||||||
|  |     if (on_join) | ||||||
|  |         on_join(channel_name); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void IRCClient::handle_namreply(const Message& msg) | void IRCClient::handle_namreply(const Message& msg) | ||||||
|  | @ -351,24 +351,28 @@ void IRCClient::register_subwindow(IRCClientWindow& subwindow) | ||||||
|     if (subwindow.type() == IRCClientWindow::Server) { |     if (subwindow.type() == IRCClientWindow::Server) { | ||||||
|         m_server_subwindow = &subwindow; |         m_server_subwindow = &subwindow; | ||||||
|         subwindow.set_log_buffer(*m_log); |         subwindow.set_log_buffer(*m_log); | ||||||
|         return; |     } else if (subwindow.type() == IRCClientWindow::Channel) { | ||||||
|     } |  | ||||||
|     if (subwindow.type() == IRCClientWindow::Channel) { |  | ||||||
|         auto it = m_channels.find(subwindow.name()); |         auto it = m_channels.find(subwindow.name()); | ||||||
|         ASSERT(it != m_channels.end()); |         ASSERT(it != m_channels.end()); | ||||||
|         auto& channel = *(*it).value; |         auto& channel = *(*it).value; | ||||||
|         subwindow.set_log_buffer(channel.log()); |         subwindow.set_log_buffer(channel.log()); | ||||||
|         return; |     } else if (subwindow.type() == IRCClientWindow::Query) { | ||||||
|     } |  | ||||||
|     if (subwindow.type() == IRCClientWindow::Query) { |  | ||||||
|         subwindow.set_log_buffer(ensure_query(subwindow.name()).log()); |         subwindow.set_log_buffer(ensure_query(subwindow.name()).log()); | ||||||
|     } |     } | ||||||
|  |     m_windows.append(&subwindow); | ||||||
|  |     m_client_window_list_model->update(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void IRCClient::unregister_subwindow(IRCClientWindow& subwindow) | void IRCClient::unregister_subwindow(IRCClientWindow& subwindow) | ||||||
| { | { | ||||||
|     if (subwindow.type() == IRCClientWindow::Server) { |     if (subwindow.type() == IRCClientWindow::Server) { | ||||||
|         m_server_subwindow = &subwindow; |         m_server_subwindow = &subwindow; | ||||||
|         return; |  | ||||||
|     } |     } | ||||||
|  |     for (int i = 0; i < m_windows.size(); ++i) { | ||||||
|  |         if (m_windows.at(i) == &subwindow) { | ||||||
|  |             m_windows.remove(i); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     m_client_window_list_model->update(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
| class IRCChannel; | class IRCChannel; | ||||||
| class IRCQuery; | class IRCQuery; | ||||||
| class IRCClientWindow; | class IRCClientWindow; | ||||||
|  | class IRCClientWindowListModel; | ||||||
| class GNotifier; | class GNotifier; | ||||||
| 
 | 
 | ||||||
| class IRCClient { | class IRCClient { | ||||||
|  | @ -31,11 +32,19 @@ public: | ||||||
|     Function<void()> on_disconnect; |     Function<void()> on_disconnect; | ||||||
|     Function<void(const String& channel)> on_channel_message; |     Function<void(const String& channel)> on_channel_message; | ||||||
|     Function<void(const String& name)> on_query_message; |     Function<void(const String& name)> on_query_message; | ||||||
|  |     Function<void(const String& channel)> on_join; | ||||||
|     Function<void()> on_server_message; |     Function<void()> on_server_message; | ||||||
| 
 | 
 | ||||||
|     void register_subwindow(IRCClientWindow&); |     void register_subwindow(IRCClientWindow&); | ||||||
|     void unregister_subwindow(IRCClientWindow&); |     void unregister_subwindow(IRCClientWindow&); | ||||||
| 
 | 
 | ||||||
|  |     IRCClientWindowListModel* client_window_list_model() { return m_client_window_list_model; } | ||||||
|  |     const IRCClientWindowListModel* client_window_list_model() const { return m_client_window_list_model; } | ||||||
|  | 
 | ||||||
|  |     int window_count() const { return m_windows.size(); } | ||||||
|  |     const IRCClientWindow& window_at(int index) const { return *m_windows.at(index); } | ||||||
|  |     IRCClientWindow& window_at(int index) { return *m_windows.at(index); } | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     struct Message { |     struct Message { | ||||||
|         String prefix; |         String prefix; | ||||||
|  | @ -66,7 +75,11 @@ 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; | ||||||
| 
 | 
 | ||||||
|  |     Vector<IRCClientWindow*> m_windows; | ||||||
|  | 
 | ||||||
|     IRCClientWindow* m_server_subwindow { nullptr }; |     IRCClientWindow* m_server_subwindow { nullptr }; | ||||||
| 
 | 
 | ||||||
|  |     IRCClientWindowListModel* m_client_window_list_model { nullptr }; | ||||||
|  | 
 | ||||||
|     Retained<IRCLogBuffer> m_log; |     Retained<IRCLogBuffer> m_log; | ||||||
| }; | }; | ||||||
|  |  | ||||||
							
								
								
									
										57
									
								
								Applications/IRCClient/IRCClientWindowListModel.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								Applications/IRCClient/IRCClientWindowListModel.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,57 @@ | ||||||
|  | #include "IRCClientWindowListModel.h" | ||||||
|  | #include "IRCClientWindow.h" | ||||||
|  | #include "IRCClient.h" | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <time.h> | ||||||
|  | 
 | ||||||
|  | IRCClientWindowListModel::IRCClientWindowListModel(IRCClient& client) | ||||||
|  |     : m_client(client) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IRCClientWindowListModel::~IRCClientWindowListModel() | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int IRCClientWindowListModel::row_count() const | ||||||
|  | { | ||||||
|  |     return m_client.window_count(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int IRCClientWindowListModel::column_count() const | ||||||
|  | { | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | String IRCClientWindowListModel::column_name(int column) const | ||||||
|  | { | ||||||
|  |     switch (column) { | ||||||
|  |     case Column::Name: return "Name"; | ||||||
|  |     } | ||||||
|  |     ASSERT_NOT_REACHED(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | GTableModel::ColumnMetadata IRCClientWindowListModel::column_metadata(int column) const | ||||||
|  | { | ||||||
|  |     switch (column) { | ||||||
|  |     case Column::Name: return { 70, TextAlignment::CenterLeft }; | ||||||
|  |     } | ||||||
|  |     ASSERT_NOT_REACHED(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | GVariant IRCClientWindowListModel::data(const GModelIndex& index, Role) const | ||||||
|  | { | ||||||
|  |     switch (index.column()) { | ||||||
|  |     case Column::Name: return m_client.window_at(index.row()).name(); | ||||||
|  |     } | ||||||
|  |     ASSERT_NOT_REACHED(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IRCClientWindowListModel::update() | ||||||
|  | { | ||||||
|  |     did_update(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IRCClientWindowListModel::activate(const GModelIndex&) | ||||||
|  | { | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								Applications/IRCClient/IRCClientWindowListModel.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								Applications/IRCClient/IRCClientWindowListModel.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <LibGUI/GTableModel.h> | ||||||
|  | 
 | ||||||
|  | class IRCClient; | ||||||
|  | 
 | ||||||
|  | class IRCClientWindowListModel final : public GTableModel { | ||||||
|  | public: | ||||||
|  |     enum Column { | ||||||
|  |         Name, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     explicit IRCClientWindowListModel(IRCClient&); | ||||||
|  |     virtual ~IRCClientWindowListModel() 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: | ||||||
|  |     IRCClient& m_client; | ||||||
|  | }; | ||||||
|  | @ -6,6 +6,7 @@ OBJS = \ | ||||||
|     IRCLogBufferModel.o \
 |     IRCLogBufferModel.o \
 | ||||||
|     IRCAppWindow.o \
 |     IRCAppWindow.o \
 | ||||||
|     IRCClientWindow.o \
 |     IRCClientWindow.o \
 | ||||||
|  |     IRCClientWindowListModel.o \
 | ||||||
|     main.o |     main.o | ||||||
| 
 | 
 | ||||||
| APP = IRCClient | APP = IRCClient | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling