Changeset 866


Ignore:
Timestamp:
Sep 18, 2006, 1:26:49 AM (17 years ago)
Author:
joshe
Message:

Improve debug window:

Limit the log to 5000 messages.
Use a monospaced font.
Add timestamps.
Add button to clear the log.
Add button to save the log to a file.
Replace radio buttons with popup menu.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/msgwin.c

    r815 r866  
    2323 *****************************************************************************/
    2424
     25#include <errno.h>
    2526#include <string.h>
    2627
     
    3334#include "util.h"
    3435
     36#define MAX_MSGCOUNT 5000
     37
    3538#define COL_LVL 0
    3639#define COL_MSG 1
    3740
    3841static void
    39 changelevel( GtkToggleButton * button, gpointer data );
     42changelevel( GtkWidget * widget, gpointer data );
     43static void
     44asksave( GtkWidget * widget, gpointer data );
     45static void
     46dosave( GtkWidget * widget, gint resp, gpointer gdata );
     47static void
     48doclear( GtkWidget * widget, gpointer data );
    4049
    4150static GtkTextBuffer * textbuf = NULL;
     51
     52static struct { char * label; char * pref; char * text; int id; } levels[] = {
     53  { N_("Error"), "error", "ERR", TR_MSG_ERR },
     54  { N_("Info"),  "info",  "INF", TR_MSG_INF },
     55  { N_("Debug"), "debug", "DBG", TR_MSG_DBG },
     56};
    4257
    4358GtkWidget *
    4459msgwin_create( void ) {
    4560  GtkWidget * win, * vbox, * scroll, * text;
    46   GtkWidget * frame, * bbox, * err, * inf, * dbg;
     61  GtkWidget * frame, * bbox, * save, * clear, * menu;
     62  PangoFontDescription * desc;
     63  unsigned int ii;
     64  int curlevel;
    4765
    4866  if( NULL == textbuf )
     
    5573  frame = gtk_frame_new( NULL );
    5674  bbox = gtk_hbutton_box_new();
    57   err = gtk_radio_button_new_with_label( NULL, _( "Error" ) );
    58   inf = gtk_radio_button_new_with_label_from_widget(
    59     GTK_RADIO_BUTTON( err ), _( "Info" ) );
    60   dbg = gtk_radio_button_new_with_label_from_widget(
    61     GTK_RADIO_BUTTON( err ), _( "Debug" ) );
     75  save = gtk_button_new_from_stock( GTK_STOCK_SAVE );
     76  clear = gtk_button_new_from_stock( GTK_STOCK_CLEAR );
     77  menu = gtk_combo_box_new_text();
    6278
    6379  gtk_text_view_set_editable( GTK_TEXT_VIEW( text ), FALSE );
     80  desc = pango_font_description_new();
     81  pango_font_description_set_family( desc, "Monospace" );
     82  gtk_widget_modify_font( text, desc );
     83  pango_font_description_free( desc );
    6484
    6585  gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scroll ),
     
    7494  gtk_button_box_set_layout( GTK_BUTTON_BOX( bbox), GTK_BUTTONBOX_SPREAD );
    7595
    76   gtk_container_add( GTK_CONTAINER( bbox ), err );
    77   gtk_container_add( GTK_CONTAINER( bbox ), inf );
    78   gtk_container_add( GTK_CONTAINER( bbox ), dbg );
     96  curlevel = tr_getMessageLevel();
     97  for( ii = 0; ALEN( levels ) > ii; ii++ ) {
     98    gtk_combo_box_append_text( GTK_COMBO_BOX( menu ),
     99                               gettext( levels[ii].label ) );
     100    if( levels[ii].id == curlevel )
     101      gtk_combo_box_set_active( GTK_COMBO_BOX( menu ), ii );
     102  }
     103
     104  gtk_container_add( GTK_CONTAINER( bbox ), clear );
     105  gtk_container_add( GTK_CONTAINER( bbox ), save );
     106  gtk_container_add( GTK_CONTAINER( bbox ), menu );
    79107  gtk_box_pack_start( GTK_BOX( vbox ), bbox, FALSE, FALSE, 0 );
    80108
    81109  gtk_container_add( GTK_CONTAINER( win ), vbox );
    82110
    83   switch( tr_getMessageLevel() ) {
    84     case TR_MSG_ERR:
    85       gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( err ), TRUE );
    86       break;
    87     case TR_MSG_INF:
    88       gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( inf ), TRUE );
    89       break;
    90     case TR_MSG_DBG:
    91       gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dbg ), TRUE );
    92       break;
    93   }
    94 
    95   g_signal_connect( err, "toggled", G_CALLBACK( changelevel ),
    96                     GINT_TO_POINTER( TR_MSG_ERR ) );
    97   g_signal_connect( inf, "toggled", G_CALLBACK( changelevel ),
    98                     GINT_TO_POINTER( TR_MSG_INF ) );
    99   g_signal_connect( dbg, "toggled", G_CALLBACK( changelevel ),
    100                     GINT_TO_POINTER( TR_MSG_DBG ) );
     111  g_signal_connect( save, "clicked", G_CALLBACK( asksave ), win );
     112  g_signal_connect( clear, "clicked", G_CALLBACK( doclear ), NULL );
     113  g_signal_connect( menu, "changed", G_CALLBACK( changelevel ), NULL );
    101114
    102115  gtk_widget_show_all( win );
     
    106119
    107120static void
    108 changelevel( GtkToggleButton * button, gpointer data ) {
    109   int    level;
     121changelevel( GtkWidget * widget, gpointer data SHUTUP ) {
     122  int    index;
    110123  char * ignored;
    111124
    112   if( gtk_toggle_button_get_active( button ) ) {
    113     level = GPOINTER_TO_INT( data );
    114     tr_setMessageLevel( level );
    115     switch( level ) {
    116       case TR_MSG_ERR:
    117         cf_setpref( PREF_MSGLEVEL, "error" );
    118         break;
    119       case TR_MSG_INF:
    120         cf_setpref( PREF_MSGLEVEL, "info" );
    121         break;
    122       case TR_MSG_DBG:
    123         cf_setpref( PREF_MSGLEVEL, "debug" );
    124         break;
    125     }
     125  index = gtk_combo_box_get_active( GTK_COMBO_BOX( widget ) );
     126  if( 0 <= index && (int) ALEN( levels ) > index &&
     127      tr_getMessageLevel() != levels[index].id ) {
     128    tr_setMessageLevel( levels[index].id );
     129    cf_setpref( PREF_MSGLEVEL, levels[index].pref );
    126130    cf_saveprefs( &ignored );
    127131    g_free( ignored );
     
    130134}
    131135
     136static void
     137asksave( GtkWidget * widget SHUTUP, gpointer data ) {
     138  GtkWidget * wind;
     139
     140  wind = gtk_file_chooser_dialog_new( _("Save Log"), GTK_WINDOW( data ),
     141                                      GTK_FILE_CHOOSER_ACTION_SAVE,
     142                                      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
     143                                      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
     144                                      NULL );
     145  g_signal_connect( G_OBJECT( wind ), "response", G_CALLBACK( dosave ), NULL );
     146  gtk_widget_show( wind );
     147}
     148
     149static void
     150dosave( GtkWidget * widget, gint resp, gpointer gdata SHUTUP ) {
     151  char      * path, * buf;
     152  FILE      * fptr;
     153  GtkTextIter front, back;
     154  size_t      len;
     155
     156  if( GTK_RESPONSE_ACCEPT == resp ) {
     157    path = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( widget ) );
     158    if( NULL != path ) {
     159      fptr = fopen( path, "w" );
     160      if( NULL == fptr ) {
     161        errmsg( GTK_WINDOW( widget ),
     162                _("Failed to open the file %s for writing:\n%s"),
     163                path, strerror( errno ) );
     164      }
     165      else {
     166        gtk_text_buffer_get_start_iter( textbuf, &front );
     167        gtk_text_buffer_get_end_iter( textbuf, &back );
     168        buf = gtk_text_buffer_get_text( textbuf, &front, &back, FALSE );
     169        if( NULL != buf ) {
     170          len = strlen( buf );
     171          if( len > fwrite( buf, 1, len, fptr ) ) {
     172            errmsg( GTK_WINDOW( widget ),
     173                    _("Error while writing to the file %s:\n%s"),
     174                    path, strerror( errno ) );
     175          }
     176          g_free( buf );
     177        }
     178        fclose( fptr );
     179      }
     180    }
     181    g_free( path );
     182  }
     183
     184  gtk_widget_destroy( widget );
     185}
     186
     187static void
     188doclear( GtkWidget * widget SHUTUP, gpointer data SHUTUP ) {
     189  GtkTextIter front, back;
     190
     191  gtk_text_buffer_get_start_iter( textbuf, &front );
     192  gtk_text_buffer_get_end_iter( textbuf, &back );
     193  gtk_text_buffer_delete( textbuf, &front, &back );
     194}
     195
    132196void
    133197msgwin_loadpref( void ) {
    134198  const char * pref;
     199  unsigned int ii;
    135200
    136201  tr_setMessageQueuing( 1 );
     
    139204    return;
    140205
    141   if( 0 == strcmp( "error", pref ) )
    142     tr_setMessageLevel( TR_MSG_ERR );
    143   else if( 0 == strcmp( "info", pref ) )
    144     tr_setMessageLevel( TR_MSG_INF );
    145   else if( 0 == strcmp( "debug", pref ) )
    146     tr_setMessageLevel( TR_MSG_DBG );
     206  for( ii = 0; ALEN( levels ) > ii; ii++ ) {
     207    if( 0 == strcmp( pref, levels[ii].pref ) ) {
     208      tr_setMessageLevel( levels[ii].id );
     209      break;
     210    }
     211  }
    147212}
    148213
     
    150215msgwin_update( void ) {
    151216  tr_msg_list_t * msgs, * ii;
    152   GtkTextIter     iter;
    153   char          * label;
     217  GtkTextIter     iter, front;
     218  char          * label, * line;
     219  int             count;
     220  struct tm     * tm;
     221  unsigned int    jj;
    154222
    155223  if( NULL == textbuf )
     
    158226  msgs = tr_getQueuedMessages();
    159227  for( ii = msgs; NULL != ii; ii = ii->next ) {
    160     switch( ii->level )
    161     {
    162       case TR_MSG_ERR:
    163         label = _( "ERR " );
     228    label = _("???");
     229    for( jj = 0; ALEN( levels ) > jj; jj++ ) {
     230      if( levels[jj].id == ii->level ) {
     231        label = levels[jj].text;
    164232        break;
    165       case TR_MSG_INF:
    166         label = _( "INF " );
    167         break;
    168       case TR_MSG_DBG:
    169         label = _( "DBG " );
    170         break;
    171       default:
    172         label = _( "??? " );
    173         break;
     233      }
    174234    }
     235    tm = localtime( &ii->when );
     236    line = g_strdup_printf( "%02i:%02i:%02i %s %s\n", tm->tm_hour, tm->tm_min,
     237                            tm->tm_sec, label, ii->message );
    175238    gtk_text_buffer_get_end_iter( textbuf, &iter );
    176     gtk_text_buffer_insert( textbuf, &iter, label, -1 );
    177     gtk_text_buffer_insert( textbuf, &iter, ii->message, -1 );
    178     gtk_text_buffer_insert( textbuf, &iter, "\n", -1 );
     239    gtk_text_buffer_insert( textbuf, &iter, line, -1 );
     240    g_free( line );
    179241  }
    180242  tr_freeMessageList( msgs );
    181 }
     243
     244  count = gtk_text_buffer_get_line_count( textbuf );
     245  if( MAX_MSGCOUNT < count ) {
     246    gtk_text_buffer_get_iter_at_line( textbuf, &front, 0 );
     247    gtk_text_buffer_get_iter_at_line( textbuf, &iter, count - MAX_MSGCOUNT );
     248    gtk_text_buffer_delete( textbuf, &front, &iter );
     249  }
     250}
Note: See TracChangeset for help on using the changeset viewer.