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

log-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 <glib.h>
#include <gtk/gtk.h>

#include <pan/base/argset.h>
#include <pan/base/debug.h>
#include <pan/base/log.h>
#include <pan/base/pan-i18n.h>

#include <pan/gui.h>
#include <pan/util.h>
#include <pan/log-ui.h>
#include <pan/xpm/pan-pixbufs.h>


/*********************
**********************  Structures / Typedefs
**********************/

typedef struct
{
      GdkPixbuf   * error_pixbuf;
      GdkPixmap   * error_pixmap;
      GdkBitmap   * error_bitmask;

      GtkWidget * window;        /* main window */
      GtkWidget * log;           /* GtkCList of log contents */
      GtkWidget * menubar;
      GtkWidget * toolbar;
      GtkWidget * file_entry;
}
LogViewer;

/*********************
**********************  Variables
**********************/

#define DATE_FORMAT "%a, %d %b %Y %H:%M:%S"
#define DIMENSIONS_KEY "log_dialog_3"

/*********************
**********************  BEGINNING OF SOURCE
**********************/

/************
*************  PRIVATE ROUTINES
*************/

static void
log_close_cb (GtkWidget * widget, LogViewer * view)
{
      gtk_widget_destroy (view->window);
}

static void
log_clear_cb (GtkWidget * widget, LogViewer * view)
{
      log_clear ();
}

static void
log_save_ok_clicked (GtkWidget * widget, LogViewer * view)
{
      const char *filename;
      FILE * fp = NULL;

      filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (view->file_entry));
      if (is_nonempty_string (filename))
            fp = fopen (filename, "w");

      if (fp != NULL)
      {
            guint i;
            GPtrArray * entries = log_get_entries ();
            for (i=0; i!=entries->len; ++i) {
                  const LogEntry * entry = (const LogEntry*) g_ptr_array_index (entries, i);
                  char *date = get_date_display_string (entry->date, DATE_FORMAT);
                  fprintf (fp, "%s - %s\n", date, entry->message);
            }
            fclose (fp);
      }

      gtk_widget_destroy (GTK_WIDGET(view->file_entry));
      view->file_entry = NULL;
}

static void
log_save_cb (GtkWidget * widget, LogViewer * view)
{
      view->file_entry = gtk_file_selection_new (_("Save the log to a file"));

      gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (view->file_entry));

      gtk_signal_connect_object (GTK_OBJECT (view->file_entry), "destroy",
                           GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (view->file_entry));
      gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (view->file_entry)->cancel_button), "clicked",
                           GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (view->file_entry));
      gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (view->file_entry)->ok_button),
                      "clicked",
                      GTK_SIGNAL_FUNC (log_save_ok_clicked),
                      view);

      gtk_widget_show_all (view->file_entry);
}

static void
menu_button_mediator (gpointer user_data, int action, GtkWidget * w)
{
      switch (action) {
            case 1: log_save_cb (w, user_data); break;
            case 2: log_clear_cb (w, user_data); break;
            case 3: log_close_cb (w, user_data); break;
            default: pan_warn_if_reached ();
      }
}


static GtkItemFactoryEntry log_entries[] =
{
      {N_("/_File"),            NULL, NULL, 0, "<Branch>"},
      {N_("/_File/_Save..."),   NULL, menu_button_mediator, 1, NULL},
      {N_("/_File/Clea_r"),     NULL, menu_button_mediator, 2, NULL},
      {N_("/_File/---"),        NULL, NULL, 0, "<Separator>"},
      {N_("/_File/_Close"),     NULL, menu_button_mediator, 3, NULL}
};





static void
log_viewer_add_entry_nolock (LogViewer * view, LogEntry * entry)
{
      int row;
      char * data [3];
      char * freeme1 = NULL;
      char * freeme2 = NULL;

      g_return_if_fail (entry != NULL);
      g_return_if_fail (view != NULL);

      data[0] = "";
      data[1] = freeme1 = get_date_display_string (entry->date, DATE_FORMAT);
      data[2] = (char *) pan_utf8ize (entry->message, -1, &freeme2);
      row = gtk_clist_prepend (GTK_CLIST(view->log), data);

      if (entry->severity & LOG_ERROR)
            gtk_clist_set_pixmap (GTK_CLIST(view->log), row, 0,
                                  view->error_pixmap,
                                  view->error_bitmask);

      g_free (freeme1);
      g_free (freeme2);
}

static void
log_list_appended_cb (gpointer obj, gpointer arg, gpointer window_gpointer)
{
      LogEntry * entry = (LogEntry*) obj;
      GtkWindow * window = GTK_WINDOW (window_gpointer);
      LogViewer * view = (LogViewer*) g_object_get_data (G_OBJECT(window), "view");

      pan_lock ();
      log_viewer_add_entry_nolock (view, entry);
      pan_unlock ();
}

static void
log_viewer_rebuild_ui (GtkWindow * window)
{
      LogViewer * view = (LogViewer*) g_object_get_data (G_OBJECT(window), "view");

      if (view != NULL)
      {
            int i;
            GPtrArray * entries = log_get_entries ();
            GtkCList * clist = GTK_CLIST(view->log);

            pan_lock ();
            gtk_clist_freeze (clist);
            gtk_clist_clear (clist);
            for (i=0; i!=entries->len; ++i)
                  log_viewer_add_entry_nolock (view, (LogEntry*)g_ptr_array_index(entries,i));
            gtk_clist_thaw (clist);
            pan_unlock ();
      }
}

static void
log_list_changed_cb (gpointer obj, gpointer arg, gpointer data)
{
      if (GTK_IS_WIDGET (data))
      {
            log_viewer_rebuild_ui (GTK_WINDOW(data));
      }
}

static int
log_delete_cb (GtkWidget * w, GdkEvent * e, gpointer data)
{
      LogViewer * view = (LogViewer*) data;
      gui_save_window_size (view->window, DIMENSIONS_KEY);
      gui_save_column_widths (view->log, DIMENSIONS_KEY);
      return FALSE;
}

static void
view_info_free (gpointer view_gpointer)
{
      LogViewer * view = (LogViewer*) view_gpointer;

      g_object_unref (view->error_pixbuf);
      g_object_unref (view->error_pixmap);
      g_object_unref (view->error_bitmask);
      g_free (view);
}

static void
log_destroy_cb (GtkWidget * widget, gpointer unused)
{
      pan_callback_remove (log_get_entry_list_changed_callback(),
                           log_list_changed_cb, widget);
      pan_callback_remove (log_get_entry_added_callback(),
                           log_list_appended_cb, widget);
}



static LogViewer *
dialog_log_viewer_create (GtkWidget * window)
{
      char * titles[3];
      GtkWidget * w;
      GtkWidget * vbox;
      GtkWidget * scrolled_window;
      LogViewer * view = g_new0 (LogViewer, 1);

      /* create the log window */
      w = view->window = window;
      gtk_window_set_title (GTK_WINDOW(w), _("Pan: Status Log"));
      gtk_window_set_role (GTK_WINDOW(w), "pan-status-log");
      vbox = gtk_vbox_new (FALSE, 0);
      gtk_container_add (GTK_CONTAINER(view->window), vbox);

      /* add the menubar */
      view->menubar = menubar_create (view->window,
                                      log_entries,
                                      sizeof (log_entries) / sizeof(log_entries[0]),
                                      "<Log>",
                              view);
      gtk_box_pack_start (GTK_BOX(vbox), view->menubar, FALSE, FALSE, 0);

      /* add the toolbar */
      w = view->toolbar = gtk_toolbar_new ();
      gtk_toolbar_insert_stock (GTK_TOOLBAR(w), GTK_STOCK_SAVE,
                                _("Save the log to a file"), NULL,
                                G_CALLBACK(log_save_cb), view,
                          -1);
      gtk_toolbar_insert_stock (GTK_TOOLBAR(w), GTK_STOCK_CLEAR,
                                _("Clear the log window"), NULL,
                                G_CALLBACK(log_clear_cb), view,
                          -1);
      gtk_toolbar_insert_stock (GTK_TOOLBAR(w), GTK_STOCK_CLOSE,
                                _("Close the log window"), NULL,
                                G_CALLBACK(log_close_cb), view,
                          -1);
      gtk_box_pack_start (GTK_BOX(vbox), view->toolbar, FALSE, FALSE, 0);

      /* create the clist */
      view->error_pixbuf = gdk_pixbuf_new_from_inline (-1, icon_caution, FALSE, NULL);
      gdk_pixbuf_render_pixmap_and_mask_for_colormap (view->error_pixbuf,
                                                      gdk_colormap_get_system (),
                                                      &view->error_pixmap,
                                                      &view->error_bitmask, 128);
      titles[0] = "";
      titles[1] = _("Time");
      titles[2] = _("Log Entry");
      view->log = gtk_clist_new_with_titles (3, titles);
      gtk_clist_set_column_width (GTK_CLIST(view->log), 0, 20);
      gtk_clist_set_column_width (GTK_CLIST(view->log), 1, 150);
      gtk_clist_set_column_width (GTK_CLIST(view->log), 2, 1500);
      gui_restore_column_widths (view->log, DIMENSIONS_KEY);
      scrolled_window = gtk_scrolled_window_new (NULL, NULL);
      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
                              GTK_POLICY_AUTOMATIC,
                              GTK_POLICY_AUTOMATIC);
      gtk_container_add (GTK_CONTAINER (scrolled_window), view->log);
      gtk_box_pack_start (GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0);

      g_signal_connect (view->window, "delete_event", G_CALLBACK(log_delete_cb), view);
      g_signal_connect (view->window, "destroy", G_CALLBACK(log_destroy_cb), view);

      return view;
}

/************
*************  PUBLIC ROUTINES
*************/

GtkWidget*
log_dialog_new (GtkWindow * window)
{
      GtkWidget * dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL);
      LogViewer * view = dialog_log_viewer_create (dialog);

      g_object_set_data_full (G_OBJECT(dialog), "view", view, view_info_free);
      pan_callback_add (log_get_entry_list_changed_callback(), log_list_changed_cb, dialog);
      pan_callback_add (log_get_entry_added_callback(), log_list_appended_cb, dialog);
      log_viewer_rebuild_ui (GTK_WINDOW(dialog));

      gtk_window_set_default_size (GTK_WINDOW (view->window), 500, 336);
      gui_restore_window_size (view->window, DIMENSIONS_KEY);

      return view->window;
}

Generated by  Doxygen 1.6.0   Back to index