Sfoglia il codice sorgente

IRCClient: Add a little "(n)" indicator to window list for unread messages.

Andreas Kling 6 anni fa
parent
commit
b4f787090c

+ 15 - 9
Applications/IRCClient/IRCAppWindow.cpp

@@ -12,8 +12,7 @@
 #include <stdio.h>
 
 IRCAppWindow::IRCAppWindow()
-    : GWindow()
-    , m_client("127.0.0.1", 6667)
+    : m_client("127.0.0.1", 6667)
 {
     set_title(String::format("IRC Client: %s@%s:%d", m_client.nickname().characters(), m_client.hostname().characters(), m_client.port()));
     set_rect(200, 200, 600, 400);
@@ -30,9 +29,15 @@ IRCAppWindow::~IRCAppWindow()
 
 void IRCAppWindow::setup_client()
 {
-    m_client.aid_create_window = [this] (void* owner, IRCWindow::Type type, const String& name) -> IRCWindow* {
+    m_client.aid_create_window = [this] (void* owner, IRCWindow::Type type, const String& name) {
         return &create_window(owner, type, name);
     };
+    m_client.aid_get_active_window = [this] {
+        return static_cast<IRCWindow*>(m_container->active_widget());
+    };
+    m_client.aid_update_window_list = [this] {
+        m_window_list->model()->update();
+    };
 
     m_client.on_connect = [this] {
         m_client.join_channel("#test");
@@ -110,14 +115,15 @@ void IRCAppWindow::setup_widgets()
     auto* horizontal_container = new GWidget(widget);
     horizontal_container->set_layout(make<GBoxLayout>(Orientation::Horizontal));
 
-    auto* window_list = new GTableView(horizontal_container);
-    window_list->set_headers_visible(false);
-    window_list->set_alternating_row_colors(false);
-    window_list->set_model(OwnPtr<IRCWindowListModel>(m_client.client_window_list_model()));
-    window_list->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill);
-    window_list->set_preferred_size({ 120, 0 });
+    m_window_list = new GTableView(horizontal_container);
+    m_window_list->set_headers_visible(false);
+    m_window_list->set_alternating_row_colors(false);
+    m_window_list->set_model(OwnPtr<IRCWindowListModel>(m_client.client_window_list_model()));
+    m_window_list->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill);
+    m_window_list->set_preferred_size({ 120, 0 });
     m_client.client_window_list_model()->on_activation = [this] (IRCWindow& window) {
         m_container->set_active_widget(&window);
+        window.clear_unread_count();
     };
 
     m_container = new GStackWidget(horizontal_container);

+ 1 - 3
Applications/IRCClient/IRCAppWindow.h

@@ -20,11 +20,9 @@ private:
     void setup_widgets();
 
     IRCWindow& create_window(void* owner, IRCWindow::Type, const String& name);
-
     IRCClient m_client;
-
     GStackWidget* m_container { nullptr };
-
+    GTableView* m_window_list { nullptr };
     RetainPtr<GAction> m_join_action;
     RetainPtr<GAction> m_part_action;
     RetainPtr<GAction> m_whois_action;

+ 1 - 0
Applications/IRCClient/IRCChannel.cpp

@@ -37,6 +37,7 @@ void IRCChannel::add_member(const String& name, char prefix)
 
 void IRCChannel::add_message(char prefix, const String& name, const String& text)
 {
+    window().did_add_message();
     log().add_message(prefix, name, text);
     dump();
 }

+ 3 - 1
Applications/IRCClient/IRCClient.cpp

@@ -237,8 +237,10 @@ void IRCClient::handle(const Message& msg, const String&)
     if (msg.command == "PRIVMSG")
         return handle_privmsg(msg);
 
-    if (msg.arguments.size() >= 2)
+    if (msg.arguments.size() >= 2) {
         m_log->add_message(0, "Server", String::format("[%s] %s", msg.command.characters(), msg.arguments[1].characters()));
+        m_server_subwindow->did_add_message();
+    }
 }
 
 void IRCClient::send_privmsg(const String& target, const String& text)

+ 5 - 0
Applications/IRCClient/IRCClient.h

@@ -30,11 +30,16 @@ public:
 
     bool is_nick_prefix(char) const;
 
+    IRCWindow* current_window() { return aid_get_active_window(); }
+    const IRCWindow* current_window() const { return aid_get_active_window(); }
+
     Function<void()> on_connect;
     Function<void()> on_disconnect;
     Function<void()> on_server_message;
 
     Function<IRCWindow*(void*, IRCWindow::Type, const String&)> aid_create_window;
+    Function<IRCWindow*()> aid_get_active_window;
+    Function<void()> aid_update_window_list;
 
     void register_subwindow(IRCWindow&);
     void unregister_subwindow(IRCWindow&);

+ 1 - 0
Applications/IRCClient/IRCQuery.cpp

@@ -29,6 +29,7 @@ void IRCQuery::dump() const
 
 void IRCQuery::add_message(char prefix, const String& name, const String& text)
 {
+    window().did_add_message();
     log().add_message(prefix, name, text);
     dump();
 }

+ 26 - 0
Applications/IRCClient/IRCWindow.cpp

@@ -61,3 +61,29 @@ void IRCWindow::set_log_buffer(const IRCLogBuffer& log_buffer)
     m_log_buffer = &log_buffer;
     m_table_view->set_model(OwnPtr<IRCLogBufferModel>((IRCLogBufferModel*)log_buffer.model()));
 }
+
+bool IRCWindow::is_active() const
+{
+    return m_client.current_window() == this;
+}
+
+void IRCWindow::did_add_message()
+{
+    if (!is_active()) {
+        ++m_unread_count;
+        m_client.aid_update_window_list();
+    }
+}
+
+void IRCWindow::clear_unread_count()
+{
+    if (!m_unread_count)
+        return;
+    m_unread_count = 0;
+    m_client.aid_update_window_list();
+}
+
+int IRCWindow::unread_count() const
+{
+    return m_unread_count;
+}

+ 10 - 0
Applications/IRCClient/IRCWindow.h

@@ -27,6 +27,13 @@ public:
 
     void set_log_buffer(const IRCLogBuffer&);
 
+    bool is_active() const;
+
+    int unread_count() const;
+    void clear_unread_count();
+
+    void did_add_message();
+
     IRCChannel& channel() { return *(IRCChannel*)m_owner; }
     const IRCChannel& channel() const { return *(const IRCChannel*)m_owner; }
 
@@ -34,6 +41,8 @@ public:
     const IRCQuery& query() const { return *(const IRCQuery*)m_owner; }
 
 private:
+    const char* class_name() const override { return "IRCWindow"; }
+
     IRCClient& m_client;
     void* m_owner { nullptr };
     Type m_type;
@@ -41,4 +50,5 @@ private:
     GTableView* m_table_view { nullptr };
     GTextEditor* m_text_editor { nullptr };
     RetainPtr<IRCLogBuffer> m_log_buffer;
+    int m_unread_count { 0 };
 };

+ 6 - 1
Applications/IRCClient/IRCWindowListModel.cpp

@@ -43,7 +43,12 @@ GTableModel::ColumnMetadata IRCWindowListModel::column_metadata(int column) cons
 GVariant IRCWindowListModel::data(const GModelIndex& index, Role) const
 {
     switch (index.column()) {
-    case Column::Name: return m_client.window_at(index.row()).name();
+    case Column::Name: {
+        auto& window = m_client.window_at(index.row());
+        if (!window.unread_count())
+            return window.name();
+        return String::format("%s (%d)\n", window.name().characters(), window.unread_count());
+    }
     }
     ASSERT_NOT_REACHED();
 }