]> hydra-www.ietfng.org Git - gtetrinet/commitdiff
added the channel list widget
authorDaniel Carbonell Fraj <bocata@src.gnome.org>
Fri, 14 Feb 2003 19:05:43 +0000 (19:05 +0000)
committerDaniel Carbonell Fraj <bocata@src.gnome.org>
Fri, 14 Feb 2003 19:05:43 +0000 (19:05 +0000)
ChangeLog
src/client.c
src/gtetrinet.h
src/partyline.c
src/partyline.h
src/tetrinet.c
src/tetrinet.h

index 39f609a20840bc07e2801c261beb9e45c9ddb9aa..b7f7921e3f754e3abc3124c874b68db1d1f1c840 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+2003-02-14  Dani Carbonell  <bocata@panete.net>
+
+       * src/client.c: a few fixes in error handling.
+       
+       * src/gtetrinet.h: fixed a couple of function declarations.
+       
+       * src/partyline.c: added the channel_list widget.
+       (partyline_page_new): added the new widget.
+       (partyline_add_channel): new function that will add a channel to the
+       list of available channels.
+       (copy_item): function that will copy a item of the work_model to the
+       actual model of the tree_view.
+       (stop_list): new function that will be called then all the markers
+       are sended back to us.
+       (partyline_update_list): function to be called if you want to update
+       the channel list.
+       (partyline_more_channel_lines): new function that will be called if
+       there are more channels waiting to be listed.
+       (partyline_clear_list_channel): new function that will clear the
+       list channel.
+       
+       * src/partyline.h: added the new function declarations.
+       
+       * src/tetrinet.c: install the channel list refresh signal, and parse
+       the incoming messages when appropiate.
+       (tetrinet_inmessage): install the signal when connecting. Refresh
+       the channel list when the user completes the connection protocol.
+       Parse the system messages if appropiate.
+       
+       * src/tetrinet.h: added new variable declaration.
+
 2003-02-11  Dani Carbonell  <bocata@panete.net>
 
        * src/gtetrinet.c (main): fixed a bug when quitting GTetrinet when
index 996bdaad1b92d0b34dd69202febf9f1e9426d66b..f8bb672399d3a71102ad4010b45d7d280c821dcb 100644 (file)
@@ -397,17 +397,21 @@ io_channel_cb (GIOChannel *source, GIOCondition condition)
     case G_IO_IN :
     {
       if (client_readmsg (&buf) < 0)
-        g_warning ("client_readmsg returned -1\n");
-      
-      if (strlen (buf)) client_inmessage (buf);
-        
-      if (strncmp ("noconnecting", buf, 12) == 0)
       {
-        connected = 1; /* so we can disconnect :) */
+        g_warning ("client_readmsg failed, aborting connection\n");
         client_disconnect ();
       }
-      
-      g_free (buf);
+      else
+      {
+        if (strlen (buf)) client_inmessage (buf);
+        
+        if (strncmp ("noconnecting", buf, 12) == 0)
+        {
+          connected = 1; /* so we can disconnect :) */
+          client_disconnect ();
+        }
+        g_free (buf);
+      }
     }; break;
     default : break;
   }
@@ -443,13 +447,19 @@ int client_readmsg (gchar **str)
       switch (g_io_channel_read_chars (io_channel, &buf[i], 1, &bytes, &error))
       {
         case G_IO_STATUS_EOF :
-          g_warning ("End of file."); break;
+          g_warning ("End of file.");
+          return -1;
+          break;
         
         case G_IO_STATUS_AGAIN :
-          g_warning ("Resource temporarily unavailable."); break;
+          g_warning ("Resource temporarily unavailable.");
+          return -1;
+          break;
         
         case G_IO_STATUS_ERROR :
-          g_warning ("Error"); break;
+          g_warning ("Error");
+          return -1;
+          break;
         
         case G_IO_STATUS_NORMAL :
           if (error != NULL)
index 581a8f1fbaee621dbfb81045fd6d814b50f90072..32897c43547807f45131c9bec8ad24da3ec2929f 100644 (file)
@@ -15,5 +15,5 @@ extern gint keyrelease (GtkWidget *widget, GdkEventKey *key);
 extern void move_current_page_to_window (void);
 extern void show_fields_page (void);
 extern void show_partyline_page (void);
-void unblock_keyboard_signal (void);
-gint get_current_notebook_page (void);
+extern void unblock_keyboard_signal (void);
+extern gint get_current_notebook_page (void);
index b059ff1f45b101badf2ff5f318d76ee312b77103..fb4176243987701a7575d389c6cf6d8e6b37ce68 100644 (file)
 
 /* widgets that we have to do stuff with */
 static GtkWidget *playerlist, *textbox, *entrybox,
-    *namelabel, *teamlabel, *infolabel, *textboxscroll, *playerlist_scroll;
+    *namelabel, *teamlabel, *infolabel, *textboxscroll, 
+    *playerlist_scroll, *playerlist_vpaned, *channel_box,
+    *playerlist_channel_scroll;
 
 /* some more widgets for layout */
 static GtkWidget *table, *leftbox, *rightbox;
 
+static GtkListStore *work_model, *playerlist_channels;
+
 /* stuff for pline history */
 #define PLHSIZE 64
 char plhistory[PLHSIZE][256];
@@ -56,6 +60,9 @@ GtkWidget *partyline_page_new (void)
     GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
     GList *focus_list = NULL;
 
+    playerlist_channels = gtk_list_store_new (5, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+    work_model = gtk_list_store_new (5, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+  
     /* left box */
     leftbox = gtk_vbox_new (FALSE, 4);
     /* chat thingy */
@@ -64,14 +71,36 @@ GtkWidget *partyline_page_new (void)
     gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW(textbox), GTK_WRAP_WORD);
     gtk_text_view_set_editable (GTK_TEXT_VIEW (textbox), FALSE);
     gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (textbox), FALSE);
-    gtk_widget_show (textbox);
     textboxscroll = gtk_scrolled_window_new (NULL, NULL);
     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(textboxscroll),
                                    GTK_POLICY_AUTOMATIC,
                                    GTK_POLICY_ALWAYS);
     gtk_container_add (GTK_CONTAINER(textboxscroll), textbox);
-    gtk_widget_show(textboxscroll);
-    gtk_box_pack_start (GTK_BOX(leftbox), textboxscroll, TRUE, TRUE, 0);
+    
+    /* channel list */
+    channel_box = GTK_WIDGET (gtk_tree_view_new_with_model (GTK_TREE_MODEL (playerlist_channels)));
+    gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (channel_box), -1, _("Name"), renderer,
+                                                 "text", 1, NULL);
+    gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (channel_box), -1, _("Players"), renderer,
+                                                 "text", 2, NULL);
+    gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (channel_box), -1, _("State"), renderer,
+                                                 "text", 3, NULL);
+    gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (channel_box), -1, _("Description"), renderer,
+                                                 "text", 4, NULL);
+    playerlist_channel_scroll = gtk_scrolled_window_new (NULL, NULL);
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (playerlist_channel_scroll),
+                                   GTK_POLICY_AUTOMATIC,
+                                   GTK_POLICY_AUTOMATIC);
+    gtk_container_add (GTK_CONTAINER(playerlist_channel_scroll), channel_box);
+    gtk_widget_set_size_request (playerlist_channel_scroll, -1, 100);
+
+    /* vpaned widget */
+    playerlist_vpaned = gtk_vpaned_new ();
+    
+    gtk_paned_add1 (GTK_PANED (playerlist_vpaned), playerlist_channel_scroll);
+    gtk_paned_add2 (GTK_PANED (playerlist_vpaned), textboxscroll);
+    gtk_box_pack_start (GTK_BOX(leftbox), playerlist_vpaned, TRUE, TRUE, 0);
+    
     /* entry box */
     entrybox = gtk_entry_new ();
     gtk_entry_set_max_length (GTK_ENTRY (entrybox), 200);
@@ -79,9 +108,8 @@ GtkWidget *partyline_page_new (void)
                       GTK_SIGNAL_FUNC(textentry), NULL);
     g_signal_connect (G_OBJECT(entrybox), "key-press-event",
                       GTK_SIGNAL_FUNC(entrykey), NULL);
-    gtk_widget_show (entrybox);
     gtk_box_pack_start (GTK_BOX(leftbox), entrybox, FALSE, FALSE, 0);
-    gtk_widget_show (leftbox);
+    gtk_widget_show_all (leftbox);
 
     /* player list with scrollbar */
     playerlist = GTK_WIDGET (gtk_tree_view_new_with_model (GTK_TREE_MODEL (playerlist_model)));
@@ -91,44 +119,37 @@ GtkWidget *partyline_page_new (void)
                                                  "text", 1, NULL);
     gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (playerlist), -1, _("Team"), renderer,
                                                  "text", 2, NULL);
-    gtk_widget_show (playerlist);
     playerlist_scroll = gtk_scrolled_window_new (NULL, NULL);
     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (playerlist_scroll),
                                    GTK_POLICY_AUTOMATIC,
                                    GTK_POLICY_NEVER);
     gtk_container_add (GTK_CONTAINER(playerlist_scroll), playerlist);
     gtk_widget_set_size_request (playerlist_scroll, 150, 200);
-    gtk_widget_show (playerlist_scroll);
+    gtk_widget_show_all (playerlist_scroll);
     
     /* right box */
     box = gtk_vbox_new (FALSE, 2);
 
     widget = leftlabel_new (_("Your name:"));
-    gtk_widget_show (widget);
     gtk_box_pack_start (GTK_BOX(box), widget, FALSE, FALSE, 0);
     namelabel = gtk_label_new ("");
     gtk_widget_show (namelabel);
     gtk_box_pack_start (GTK_BOX(box), namelabel, FALSE, FALSE, 0);
     widget = gtk_vseparator_new (); /* invisible... just needed some space */
-    gtk_widget_show (widget);
     gtk_box_pack_start (GTK_BOX(box), widget, FALSE, FALSE, 2);
     widget = leftlabel_new (_("Your team:"));
-    gtk_widget_show (widget);
     gtk_box_pack_start (GTK_BOX(box), widget, FALSE, FALSE, 0);
     teamlabel = gtk_label_new ("");
-    gtk_widget_show (teamlabel);
     gtk_box_pack_start (GTK_BOX(box), teamlabel, FALSE, FALSE, 0);
     infolabel = gtk_label_new ("");
     gtk_label_set_line_wrap (GTK_LABEL(teamlabel), TRUE);
-    gtk_widget_show (infolabel);
     gtk_box_pack_start (GTK_BOX(box), infolabel, TRUE, FALSE, 0);
 
     gtk_container_set_border_width (GTK_CONTAINER(box), 4);
-    gtk_widget_show (box);
     rightbox = gtk_frame_new (NULL);
     gtk_frame_set_shadow_type (GTK_FRAME(rightbox), GTK_SHADOW_IN);
     gtk_container_add (GTK_CONTAINER(rightbox), box);
-    gtk_widget_show (rightbox);
+    gtk_widget_show_all (rightbox);
 
     /* stuff all the boxes into the table */
     table = gtk_table_new (2, 2, FALSE);
@@ -332,3 +353,150 @@ static gint entrykey (GtkWidget *widget, GdkEventKey *key)
         return FALSE;
     }
 }
+
+void partyline_add_channel (gchar *line)
+{
+  GScanner *scan;
+  gint num, actual, max;
+  gchar *name, *players, *state, final[1024], *desc, *utf8;
+  GtkTreeIter iter;
+  
+  scan = g_scanner_new (NULL);
+  g_scanner_input_text (scan, line, strlen (line));
+  
+  /* we'll use single line comments to parse the channel name */
+  scan->config->cpair_comment_single = "#[";
+  scan->config->skip_comment_single = FALSE;
+  
+  while ((g_scanner_get_next_token (scan) != G_TOKEN_INT) && !g_scanner_eof (scan));
+  num = scan->value.v_int;
+  
+  while ((g_scanner_get_next_token (scan) != G_TOKEN_COMMENT_SINGLE) && !g_scanner_eof (scan));
+  utf8 = g_locale_to_utf8 (scan->value.v_comment, -1, NULL, NULL, NULL);
+  name = g_strconcat ("#", utf8, NULL);
+  
+  while ((g_scanner_get_next_token (scan) != G_TOKEN_IDENTIFIER) && !g_scanner_eof (scan));
+  players = g_strdup (scan->value.v_identifier);
+
+  if (strncmp (players, "FULL", 4))
+  {
+    while ((g_scanner_get_next_token (scan) != G_TOKEN_INT) && !g_scanner_eof (scan));
+    actual = scan->value.v_int;
+
+    while ((g_scanner_get_next_token (scan) != G_TOKEN_INT) && !g_scanner_eof (scan));
+    max = scan->value.v_int;
+
+    g_snprintf (final, 1024, "%d/%d %s", actual, max, players);
+  }
+  else
+    g_snprintf (final, 1024, "6/6 %s", players);
+  
+  g_scanner_get_next_token (scan); /* dump the ')' */
+  
+  if (g_scanner_get_next_token (scan) == G_TOKEN_LEFT_CURLY)
+  {
+    g_scanner_get_next_token (scan);
+    state = g_strdup (scan->value.v_identifier);
+  }
+  else
+    state = g_strdup ("IDLE");
+  
+  while ((g_scanner_get_next_token (scan) != G_TOKEN_RIGHT_PAREN) && !g_scanner_eof (scan));
+  if (line[scan->position] != 0)
+    desc = g_strstrip (g_locale_to_utf8 (&line[scan->position], -1, NULL, NULL, NULL));
+  else
+    desc = g_strdup ("");
+  
+  
+  gtk_list_store_append (work_model, &iter);
+  gtk_list_store_set (work_model, &iter,
+                      0, num,
+                      1, name,
+                      2, final,
+                      3, state,
+                      4, desc,
+                      -1);
+
+  g_scanner_destroy (scan);
+  g_free (name);
+  g_free (state);
+  g_free (players);
+  g_free (desc);
+  g_free (utf8);
+}
+
+gboolean copy_item (GtkTreeModel *model,
+                    GtkTreePath *path,
+                    GtkTreeIter *iter)
+{
+  gint num;
+  gchar *name, *players, *state, *desc;
+  GtkTreeIter iter2;
+
+  path = path;
+  
+  gtk_tree_model_get (model, iter,
+                      0, &num,
+                      1, &name,
+                      2, &players,
+                      3, &state,
+                      4, &desc, -1);
+  
+  gtk_list_store_append (playerlist_channels, &iter2);
+  gtk_list_store_set (playerlist_channels, &iter2,
+                      0, num,
+                      1, name,
+                      2, players,
+                      3, state,
+                      4, desc,
+                      -1);
+  
+  g_free (players);
+  g_free (name);
+  g_free (state);
+  g_free (desc);
+  
+  return FALSE;
+}
+
+void stop_list (void)
+{
+  list_issued = FALSE;
+  
+  /* update the channel list widget, with some sort of "double buffering" */
+  gtk_tree_view_set_model (GTK_TREE_VIEW (channel_box), GTK_TREE_MODEL (work_model));
+  gtk_list_store_clear (playerlist_channels);
+  gtk_tree_model_foreach (GTK_TREE_MODEL (work_model), (GtkTreeModelForeachFunc) copy_item, NULL);
+  gtk_tree_view_set_model (GTK_TREE_VIEW (channel_box), GTK_TREE_MODEL (playerlist_channels));
+}
+
+gboolean partyline_update_channel_list (void)
+{
+  gchar cad[1024];
+  
+  list_issued++;
+  gtk_list_store_clear (work_model);
+  tetrinet_playerline ("/list");
+  
+  /* send the mark */
+  g_snprintf (cad, 1024, "/msg %d --- MARK ---", playernum);
+  tetrinet_playerline (cad);
+  
+  return TRUE;
+}
+
+void partyline_more_channel_lines (void)
+{
+  gchar cad[1024];
+
+  list_issued ++;
+  tetrinet_playerline ("/list+");
+  g_snprintf (cad, 1024, "/msg %d --- MARK ---", playernum);
+  tetrinet_playerline (cad);
+}
+
+void partyline_clear_list_channel (void)
+{
+  gtk_list_store_clear (playerlist_channels);
+  gtk_list_store_clear (work_model);
+}
index 1f14ef32434821c81c26f85cfba65a8c0cbbce24..6e41fff56717ea519fde7f5e9a4747e57b145b24 100644 (file)
@@ -7,4 +7,9 @@ extern void partyline_text (char *text);
 extern void partyline_fmt (const char *text, ...) G_GNUC_PRINTF (1, 2);
 extern void partyline_playerlist (int *numbers, char **names, char **teams, int n, char **specs, int sn);
 extern void partyline_entryfocus (void);
-void partyline_switch_entryfocus (void);
+extern void partyline_add_channel (gchar *line);
+extern gboolean partyline_update_channel_list (void);
+extern void partyline_more_channel_lines (void);
+extern void partyline_switch_entryfocus (void);
+extern void partyline_clear_list_channel (void);
+extern void stop_list (void);
index cd46e5d9184d35a27d83f226593ac89e0c72d51a..23a02c5d4d01d2d74bd272eb55e50abc25189572 100644 (file)
@@ -68,6 +68,11 @@ int spectatorcount = 0;
 char specialblocks[256];
 int specialblocknum = 0;
 
+/*
+ * this will have the number of /list commands sended and waiting for answer
+ */
+gint list_issued;
+
 FIELD fields[7];
 
 int moderator; /* are we the moderator ? TRUE : FALSE */
@@ -133,6 +138,8 @@ struct sb sbinfo[] = {
     {0, 0, 0}
 };
 
+static guint up_chan_list_source;
+
 static void tetrinet_updatelevels (void);
 static void tetrinet_setspeciallabel (int sb);
 static void tetrinet_dospecial (int from, int to, int type);
@@ -175,7 +182,8 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data)
     /* process the message */
     switch (msgtype) {
     case IN_CONNECT:
-        /* do nothing - setup is done with the playernum message */
+        list_issued = 0;
+        up_chan_list_source = g_timeout_add (30000, (GSourceFunc) partyline_update_channel_list, NULL);
         break;
     case IN_DISCONNECT:
         if (!connected) {
@@ -195,11 +203,13 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data)
                 playernames[i][0] = teamnames[i][0] = 0;
             fieldslabelupdate ();
         }
+        g_source_remove (up_chan_list_source);
         winlist_clear ();
         fields_attdefclear ();
         fields_gmsgclear ();
         partyline_fmt (_("%c%c*** Disconnected from server"),
                        TETRI_TB_C_DARK_GREEN, TETRI_TB_BOLD);
+        partyline_clear_list_channel ();
         break;
     case IN_CONNECTERROR:
     connecterror:
@@ -265,6 +275,7 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data)
                 checkmoderatorstatus ();
                 partylineupdate_join (nick);
                 partylineupdate_team (nick, team);
+                partyline_update_channel_list ();
             }
         }
         /* show partyline on successful connect */
@@ -391,13 +402,60 @@ void tetrinet_inmessage (enum inmsg_type msgtype, char *data)
                     tetrix = TRUE;
                 }
                 else if (tetrix) {
+                    if (list_issued)
+                    {
+                      gchar *line = nocolor (token);
+                      
+                      if (*line == '(')
+                      {
+                        partyline_add_channel (line);
+                        break;
+                      }
+                      
+                      if (!strncmp ("List", line, 4))
+                      {
+                        partyline_more_channel_lines ();
+                        break;
+                      }
+                      
+                      if (!strncmp ("TetriNET", line, 8))
+                        break;
+                      
+                      if (!strncmp ("You", line, 3))
+                      {
+                        /* we will use the error message as list stopper */
+                        list_issued--;
+                        if (list_issued <= 0)
+                          stop_list();
+                        break;
+                      }
+                      
+                      //if (line != NULL) g_free (line);
+                    }
+
                     g_snprintf (buf, sizeof(buf), "*** %s", token);
                     partyline_text (buf);
                     break;
                 }
-                else plinemsg ("Server", token);
+                else
+                  plinemsg ("Server", token);
+            }
+            else
+            {
+              if (pnum == playernum)
+              {
+                gchar *line = nocolor (token);
+                if (!strncmp (line, "(msg) --- MARK ---", 18))
+                {
+                  list_issued--;
+                  if (list_issued <= 0)
+                    stop_list();
+                }
+                //g_free (line);
+              }
+              else
+                plinemsg (playernames[pnum], token);
             }
-            else plinemsg (playernames[pnum], token);
         }
         break;
     case IN_PLINEACT:
index 991fbe14cddce5d2aaf662c74c07b00e6dbc3fde..5faa5fad282a608f5ad68935f13f12132064fe1f 100644 (file)
@@ -1,3 +1,5 @@
+#include <gnome.h>
+
 #define FIELDWIDTH 12
 #define FIELDHEIGHT 22
 
@@ -13,6 +15,7 @@ extern int gmsgstate;
 
 extern char specialblocks[256];
 extern int specialblocknum;
+extern gint list_issued;
 
 extern void tetrinet_inmessage (enum inmsg_type msgtype, char *data);
 extern void tetrinet_playerline (const char *text);