Logo Search packages:      
Sourcecode: pan version File versions  Download package

server-menu-ui.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Pan - A Newsreader for Gtk+
 * Copyright (C) 2002  Charles Kerr <charles@rebelbase.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <config.h>

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <glib.h>
#include <gtk/gtk.h>

#include <pan/base/pan-i18n.h>
#include <pan/base/debug.h>
#include <pan/base/pan-glib-extensions.h>
#include <pan/base/server.h>
#include <pan/base/serverlist.h>

#include <pan/globals.h>
#include <pan/gui.h>
#include <pan/prefs.h>
#include <pan/server-menu-ui.h>
#include <pan/util.h>

/**
***  MENU
**/

extern GtkItemFactory * _main_menu_factory;

static gboolean server_activate_registered = FALSE;
static GHashTable * server_to_menubutton = NULL;

static int
sort_servers_by_name (gconstpointer va, gconstpointer vb, gpointer unused)
{
      const Server * a = *(const Server **)va;
      const Server * b = *(const Server **)vb;
      return g_strcasecmp (a->name.str, b->name.str);
}

static void
server_selected_cb (gpointer user_data, int unused, GtkWidget * w)
{
      Server * cur_server;
      Server * sel_server;
      const PString sel_name = pstring_shallow ((char*) g_object_get_data (G_OBJECT(w), "server_name"), -1);

      /* get the selected server */
      sel_server = serverlist_get_named_server (&sel_name);

      /* get the cur server */
      cur_server = serverlist_get_active_server ();

      /* set the server */
      if (sel_server!=cur_server && GTK_CHECK_MENU_ITEM(w)->active)
            serverlist_set_active_server (sel_server);
}

static void
server_activated_cb (gpointer server_gp, gpointer foo, gpointer bar)
{
      char * path = NULL;
      GtkWidget * w = NULL;
      Server * server = (Server*) server_gp;

      if (server != NULL) {
            path = g_strdup_printf ("/Servers/%s", server_get_name (server));
            g_strdelimit (path, "_", ' ');
      }
      if (path != NULL)
            w = gtk_item_factory_get_widget (_main_menu_factory, path);
      if (w != NULL)
            gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(w), TRUE);

      g_free (path);
}


void
server_menu_update (void)
{
      int i;
      Server * active_server;
      GPtrArray * servers;

      static GStaticMutex entries_mutex = G_STATIC_MUTEX_INIT;
      static GtkItemFactoryEntry * entries = NULL;
      static int qty = 0;

      g_static_mutex_lock (&entries_mutex);

      /* make sure we update the menu when a server is activated */
      if (!server_activate_registered) {
            server_activate_registered = TRUE;
            pan_callback_add (serverlist_get_server_activated_callback(),
                              server_activated_cb,
                              NULL);
      }

      /* remove any old server buttons */
      if (entries != NULL) {
            gtk_item_factory_delete_entries (_main_menu_factory, qty, entries);
            for (i=0; i<qty; ++i)
                  g_free (entries[i].path);
            g_free (entries);
            entries = NULL;
            qty = 0;
      }

      /* build the new menu */
      if (server_to_menubutton != NULL)
            g_hash_table_destroy (server_to_menubutton);
      server_to_menubutton = g_hash_table_new (g_direct_hash, g_direct_equal);

      /* get a list of servers, sorted alphabetically */
      servers = g_ptr_array_new ();
      serverlist_get_servers (servers);
      active_server = serverlist_get_active_server ();
      if (servers->len)
      {
            const int alloc_qty = servers->len;
            char * active_path = NULL;
            char * radio_path = NULL;

            /* sort the array of servers with case-insensitive alphabetically
             * to be pretty in the menu, and remove the `Folders' server
             * because that's an implementation wart that users shouldn't see. */
            g_ptr_array_sort_with_data (servers, sort_servers_by_name, NULL);
            for (i=0; i<servers->len; ) {
                  const Server * server = SERVER(g_ptr_array_index(servers,i));
                  if (pstring_equal (&INTERNAL_SERVER_NAME, &server->name))
                        g_ptr_array_remove_index (servers, i);
                  else
                        ++i;
            }

            /* build the ItemFactoryEntries for adding to the main menu */
            entries = g_new0 (GtkItemFactoryEntry, alloc_qty);
            for (qty=0; qty<servers->len; ++qty)
            {
                  /* build an entry: the callback arg is the index into the servers array */
                  const Server * server = SERVER(g_ptr_array_index(servers,qty));
                  char * path = g_strdup_printf ("/Servers/%s", server_get_name (server));
                  g_strdelimit (path, "_", ' ');
                  entries[qty].path = path;
                  entries[qty].item_type = qty==0 ? "<RadioItem>" : radio_path;
                  entries[qty].callback = server_selected_cb;
                  if (qty==0)
                        radio_path = entries[qty].path;
                  if (server == active_server)
                        active_path = entries[qty].path;
            }

            /* add the servers to the menu */
            gtk_item_factory_create_items (_main_menu_factory, qty, entries, NULL);

            /* add the server name as data item in the menu buttons.
             * This is used by the server_selected_cb() callback to
             * get a Server* from the GtkMenuRadioButton */
            for (i=0; i<qty; ++i) {
                  Server * server = SERVER(g_ptr_array_index(servers,i));
                  GtkWidget * w = gtk_item_factory_get_widget (_main_menu_factory, entries[i].path);
                  g_object_set_data_full (G_OBJECT(w), "server_name", g_strdup(server_get_name(server)), g_free);
            }

            /* activate the menu button which corresponds to the current server */
            if (active_path != NULL) {
                  GtkWidget * w = gtk_item_factory_get_widget (_main_menu_factory, active_path);
                  gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(w), TRUE);
            }

      }

      /* cleanup */
      g_ptr_array_free (servers, TRUE);
      g_static_mutex_unlock (&entries_mutex);
}

Generated by  Doxygen 1.6.0   Back to index