Changeset 2185 for trunk/gtk/msgwin.c


Ignore:
Timestamp:
Jun 22, 2007, 8:59:23 PM (15 years ago)
Author:
charles
Message:

add color-coded lines to the gtk debug window -- info is black, debug is grey, errors are red...

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/msgwin.c

    r1587 r2185  
    4040#define COL_MSG 1
    4141
    42 static void
    43 changelevel( GtkWidget * widget, gpointer data );
    44 static void
    45 asksave( GtkWidget * widget, gpointer data );
    46 static void
    47 dosave( GtkWidget * widget, gint resp, gpointer gdata );
    48 static void
    49 doclear( GtkWidget * widget, gpointer data );
    50 
    5142static GtkTextBuffer * textbuf = NULL;
    5243
    53 static struct { char * label; char * pref; char * text; int id; } levels[] = {
    54   { N_("Error"), "error", "ERR", TR_MSG_ERR },
    55   { N_("Info"),  "info",  "INF", TR_MSG_INF },
    56   { N_("Debug"), "debug", "DBG", TR_MSG_DBG },
    57 };
    58 
    59 GtkWidget *
    60 msgwin_create( void ) {
    61   GtkWidget * win, * vbox, * scroll, * text;
    62   GtkWidget * frame, * bbox, * save, * clear, * menu;
    63   PangoFontDescription * desc;
    64   int ii, curlevel;
    65 
    66   if( NULL == textbuf )
    67     textbuf = gtk_text_buffer_new( NULL );
    68 
    69   win = gtk_window_new( GTK_WINDOW_TOPLEVEL );
    70   vbox = gtk_vbox_new( FALSE, 0 );
    71   scroll = gtk_scrolled_window_new( NULL, NULL );
    72   text = gtk_text_view_new_with_buffer( textbuf );
    73   frame = gtk_frame_new( NULL );
    74   bbox = gtk_hbutton_box_new();
    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();
    78 
    79   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 );
    84 
    85   gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scroll ),
    86                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
    87 
    88   gtk_container_add( GTK_CONTAINER( scroll ), text );
    89   gtk_container_add( GTK_CONTAINER( frame ), scroll );
    90 
    91   gtk_frame_set_shadow_type( GTK_FRAME( frame ), GTK_SHADOW_IN );
    92   gtk_box_pack_start( GTK_BOX( vbox ), frame, TRUE, TRUE, 0 );
    93 
    94   gtk_button_box_set_layout( GTK_BUTTON_BOX( bbox), GTK_BUTTONBOX_SPREAD );
    95 
    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 );
    107   gtk_box_pack_start( GTK_BOX( vbox ), bbox, FALSE, FALSE, 0 );
    108 
    109   gtk_container_add( GTK_CONTAINER( win ), vbox );
    110 
    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 );
    114 
    115   gtk_window_set_role( GTK_WINDOW( win ), "tr-messages" );
    116 
    117   gtk_widget_show_all( win );
    118 
    119   return win;
    120 }
    121 
    122 static void
    123 changelevel( GtkWidget * widget, gpointer data SHUTUP ) {
    124   int    index;
    125   char * ignored;
    126 
    127   index = gtk_combo_box_get_active( GTK_COMBO_BOX( widget ) );
    128   if( 0 <= index && (int) ALEN( levels ) > index &&
    129       tr_getMessageLevel() != levels[index].id ) {
    130     tr_setMessageLevel( levels[index].id );
    131     cf_setpref( tr_prefs_name( PREF_ID_MSGLEVEL ), levels[index].pref );
    132     cf_saveprefs( &ignored );
    133     g_free( ignored );
    134     msgwin_update();
    135   }
    136 }
    137 
    138 static void
    139 asksave( GtkWidget * widget SHUTUP, gpointer data ) {
    140   GtkWidget * wind;
    141 
    142   wind = gtk_file_chooser_dialog_new( _("Save Log"), GTK_WINDOW( data ),
    143                                       GTK_FILE_CHOOSER_ACTION_SAVE,
    144                                       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
    145                                       GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
    146                                       NULL );
    147   g_signal_connect( G_OBJECT( wind ), "response", G_CALLBACK( dosave ), NULL );
    148   gtk_widget_show( wind );
    149 }
    150 
    151 static void
    152 dosave( GtkWidget * widget, gint resp, gpointer gdata SHUTUP ) {
    153   char      * path, * buf;
    154   FILE      * fptr;
    155   GtkTextIter front, back;
    156   size_t      len;
    157 
    158   if( GTK_RESPONSE_ACCEPT == resp ) {
    159     path = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( widget ) );
    160     if( NULL != path ) {
    161       fptr = fopen( path, "w" );
    162       if( NULL == fptr ) {
    163         errmsg( GTK_WINDOW( widget ),
    164                 _("Failed to open the file %s for writing:\n%s"),
    165                 path, strerror( errno ) );
    166       }
    167       else {
    168         gtk_text_buffer_get_start_iter( textbuf, &front );
    169         gtk_text_buffer_get_end_iter( textbuf, &back );
    170         buf = gtk_text_buffer_get_text( textbuf, &front, &back, FALSE );
    171         if( NULL != buf ) {
    172           len = strlen( buf );
    173           if( len > fwrite( buf, 1, len, fptr ) ) {
    174             errmsg( GTK_WINDOW( widget ),
    175                     _("Error while writing to the file %s:\n%s"),
    176                     path, strerror( errno ) );
    177           }
    178           g_free( buf );
    179         }
    180         fclose( fptr );
    181       }
     44static GtkTextTag*
     45get_or_create_tag (GtkTextTagTable * table, const char * key)
     46{
     47  g_assert (table);
     48  g_assert (key && *key);
     49
     50  GtkTextTag * tag = gtk_text_tag_table_lookup (table, key);
     51  if (!tag) {
     52    tag = gtk_text_tag_new (key);
     53    gtk_text_tag_table_add (table, tag);
     54    g_object_unref (tag); // table refs it
     55  }
     56
     57  return tag;
     58}
     59
     60static GtkTextBuffer*
     61debug_window_text_buffer_new ( void )
     62{
     63  GtkTextBuffer * buffer = gtk_text_buffer_new ( NULL );
     64
     65  GtkTextTagTable * table = gtk_text_buffer_get_tag_table (buffer);
     66
     67  g_object_set (get_or_create_tag(table,"bold"),
     68      "weight", PANGO_WEIGHT_BOLD,
     69      NULL);
     70 
     71  g_object_set (get_or_create_tag (table, "info"),
     72      "foreground", "black",
     73      NULL);
     74 
     75  g_object_set (get_or_create_tag (table, "error"),
     76      "foreground", "red",
     77      NULL);
     78
     79  g_object_set (get_or_create_tag (table, "debug"),
     80      "foreground", "gray",
     81      NULL);
     82
     83  return buffer;
     84}
     85
     86void
     87msgwin_update( void )
     88{
     89  tr_msg_list_t * msgs, * ii;
     90
     91  g_assert( textbuf != NULL );
     92
     93  msgs = tr_getQueuedMessages();
     94  for( ii = msgs; NULL != ii; ii = ii->next )
     95  {
     96    int len;
     97    char * line;
     98    const char * tag = NULL;
     99    struct tm * tm = localtime( &ii->when );
     100    GtkTextIter mark_start, mark_end;
     101
     102    switch( ii->level ) {
     103      case TR_MSG_ERR: tag = "error"; break;
     104      case TR_MSG_INF: tag = "info"; break;
     105      case TR_MSG_DBG: tag = "debug"; break;
    182106    }
    183     g_free( path );
    184   }
    185 
    186   gtk_widget_destroy( widget );
    187 }
    188 
    189 static void
    190 doclear( GtkWidget * widget SHUTUP, gpointer data SHUTUP ) {
    191   GtkTextIter front, back;
    192 
    193   gtk_text_buffer_get_start_iter( textbuf, &front );
    194   gtk_text_buffer_get_end_iter( textbuf, &back );
    195   gtk_text_buffer_delete( textbuf, &front, &back );
    196 }
    197 
    198 void
    199 msgwin_loadpref( void ) {
    200   const char * pref;
    201   int ii;
    202 
    203   tr_setMessageQueuing( 1 );
    204   pref = tr_prefs_get( PREF_ID_MSGLEVEL );
    205   if( NULL == pref )
    206     return;
    207 
    208   for( ii = 0; ALEN( levels ) > ii; ii++ ) {
    209     if( 0 == strcmp( pref, levels[ii].pref ) ) {
    210       tr_setMessageLevel( levels[ii].id );
    211       break;
    212     }
    213   }
    214 }
    215 
    216 void
    217 msgwin_update( void ) {
    218   tr_msg_list_t * msgs, * ii;
    219   GtkTextIter     iter, front;
    220   char          * label, * line;
    221   int             count, jj;
    222   struct tm     * tm;
    223 
    224   if( NULL == textbuf )
    225     return;
    226 
    227   msgs = tr_getQueuedMessages();
    228   for( ii = msgs; NULL != ii; ii = ii->next ) {
    229     label = _("???");
    230     for( jj = 0; ALEN( levels ) > jj; jj++ ) {
    231       if( levels[jj].id == ii->level ) {
    232         label = levels[jj].text;
    233         break;
    234       }
    235     }
    236     tm = localtime( &ii->when );
    237     line = g_strdup_printf( "%02i:%02i:%02i %s %s\n", tm->tm_hour, tm->tm_min,
    238                             tm->tm_sec, label, ii->message );
    239     gtk_text_buffer_get_end_iter( textbuf, &iter );
    240     gtk_text_buffer_insert( textbuf, &iter, line, -1 );
     107
     108    line = g_strdup_printf( "%02i:%02i:%02i %s\n", tm->tm_hour, tm->tm_min, tm->tm_sec, ii->message );
     109    len = strlen( line );
     110
     111    gtk_text_buffer_get_end_iter( textbuf, &mark_end );
     112    gtk_text_buffer_insert( textbuf, &mark_end, line, len );
     113    mark_start = mark_end;
     114    gtk_text_iter_backward_chars( &mark_start, len );
     115    gtk_text_buffer_apply_tag_by_name (textbuf, tag, &mark_start, &mark_end);
     116
    241117    g_free( line );
    242118  }
    243119  tr_freeMessageList( msgs );
    244120
     121#if 0
    245122  count = gtk_text_buffer_get_line_count( textbuf );
    246123  if( MAX_MSGCOUNT < count ) {
     
    249126    gtk_text_buffer_delete( textbuf, &front, &iter );
    250127  }
    251 }
     128#endif
     129}
     130
     131static void
     132level_combo_changed_cb( GtkWidget * w, TrCore * core )
     133{
     134    GtkTreeIter iter;
     135    if( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(w), &iter ) ) {
     136        int id = 0;
     137        GtkTreeModel * m = gtk_combo_box_get_model( GTK_COMBO_BOX(w) );
     138        gtk_tree_model_get( m, &iter, 1, &id, -1 );
     139        tr_setMessageLevel( id );
     140        tr_core_set_pref_int( core, PREF_ID_MSGLEVEL, id );
     141        msgwin_update( );
     142    }
     143}
     144
     145static void
     146save_dialog_response_cb( GtkWidget * d, int response, GtkTextBuffer * textbuf )
     147{
     148  if( response == GTK_RESPONSE_ACCEPT )
     149  {
     150      char * filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( d ) );
     151      FILE * fp = fopen( filename, "w+" );
     152      if( !fp )
     153      {
     154          errmsg( GTK_WINDOW(d),
     155                  _("Unable to open \"%s\" for writing: %s"),
     156                  filename, g_strerror( errno ) );
     157      }
     158      else
     159      {
     160          char * buf;
     161          GtkTextIter front, back;
     162          gtk_text_buffer_get_start_iter( textbuf, &front );
     163          gtk_text_buffer_get_end_iter( textbuf, &back );
     164          buf = gtk_text_buffer_get_text( textbuf, &front, &back, FALSE );
     165          if( buf ) {
     166              const size_t len = strlen( buf );
     167              if( len > fwrite( buf, 1, len, fp ) ) {
     168                  errmsg( GTK_WINDOW( d ),
     169                          _("Error writing to \"%s\": %s"),
     170                          filename, strerror( errno ) );
     171              }
     172              g_free( buf );
     173          }
     174          fclose( fp );
     175      }
     176      g_free( filename );
     177  }
     178
     179  gtk_widget_destroy( d );
     180}
     181
     182static void
     183save_cb( GtkWidget * w, GtkTextBuffer * textbuf )
     184{
     185  GtkWindow * window = GTK_WINDOW( gtk_widget_get_toplevel( w ) );
     186  GtkWidget * d = gtk_file_chooser_dialog_new( _("Save Debug Log"), window,
     187                                               GTK_FILE_CHOOSER_ACTION_SAVE,
     188                                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
     189                                               GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
     190                                               NULL );
     191  g_signal_connect( d, "response",
     192                    G_CALLBACK( save_dialog_response_cb ), textbuf );
     193  gtk_widget_show( d );
     194}
     195
     196static void
     197clear_cb( GtkWidget * w UNUSED, GtkTextBuffer * textbuf )
     198{
     199  GtkTextIter front, back;
     200  gtk_text_buffer_get_start_iter( textbuf, &front );
     201  gtk_text_buffer_get_end_iter( textbuf, &back );
     202  gtk_text_buffer_delete( textbuf, &front, &back );
     203}
     204
     205static struct {
     206  const char * label;
     207  const char * pref;
     208  const char * text;
     209  int id;
     210} trLevels[] = {
     211  { N_("Error"), "error", "ERR", TR_MSG_ERR },
     212  { N_("Info"),  "info",  "INF", TR_MSG_INF },
     213  { N_("Debug"), "debug", "DBG", TR_MSG_DBG },
     214};
     215
     216GtkWidget *
     217msgwin_create( TrCore * core )
     218{
     219  unsigned int i;
     220  GtkListStore * store;
     221  GtkWidget * win, * vbox, * scroll, * text;
     222  GtkWidget * levels;
     223  GtkWidget * toolbar;
     224  GtkCellRenderer * renderer;
     225  int ii, curlevel;
     226
     227  win = gtk_window_new( GTK_WINDOW_TOPLEVEL );
     228  gtk_window_set_role( GTK_WINDOW( win ), "debug-window" );
     229  vbox = gtk_vbox_new( FALSE, 0 );
     230
     231  /**
     232  ***  toolbar
     233  **/
     234
     235  toolbar = gtk_toolbar_new ();
     236  gtk_toolbar_set_style( GTK_TOOLBAR( toolbar), GTK_TOOLBAR_BOTH_HORIZ );
     237
     238  gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_SAVE,
     239                           _("Save"), NULL,
     240                           G_CALLBACK(save_cb), textbuf, -1);
     241
     242  gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_CLEAR,
     243                           _("Clear"), NULL,
     244                           G_CALLBACK(clear_cb), textbuf, -1);
     245
     246  gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1);
     247
     248
     249  gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
     250                             GTK_TOOLBAR_CHILD_WIDGET, gtk_label_new(_("Level ")),
     251                             NULL, _("Select the debug filter level."),
     252                             NULL, NULL, NULL, NULL);
     253
     254  store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
     255
     256  curlevel = TR_MSG_INF;
     257  tr_prefs_get_int( PREF_ID_MSGLEVEL, &curlevel );
     258  for( i=ii=0; i<G_N_ELEMENTS(trLevels); ++i ) {
     259      GtkTreeIter iter;
     260      gtk_list_store_append (store, &iter);
     261      gtk_list_store_set (store, &iter, 0, _(trLevels[i].label),
     262                                        1, trLevels[i].id,
     263                                       -1);
     264      if( trLevels[i].id == curlevel )
     265          ii = i;
     266  }
     267  levels = gtk_combo_box_new_with_model (GTK_TREE_MODEL(store));
     268  g_object_unref (G_OBJECT(store));
     269  renderer = gtk_cell_renderer_text_new ();
     270  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(levels), renderer, TRUE);
     271  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT(levels), renderer, "text", 0, NULL);
     272  gtk_combo_box_set_active( GTK_COMBO_BOX( levels ), ii );
     273  g_signal_connect( levels, "changed", G_CALLBACK(level_combo_changed_cb), core );
     274
     275  gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
     276                             GTK_TOOLBAR_CHILD_WIDGET, levels,
     277                             NULL, _("Select the debug filter level."),
     278                             NULL, NULL, NULL, NULL);
     279
     280  gtk_box_pack_start( GTK_BOX( vbox ), toolbar, FALSE, FALSE, 0 );
     281
     282  /**
     283  ***  text area
     284  **/
     285
     286  text = gtk_text_view_new_with_buffer( textbuf );
     287  gtk_text_view_set_editable( GTK_TEXT_VIEW( text ), FALSE );
     288
     289  scroll = gtk_scrolled_window_new( NULL, NULL );
     290  gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scroll ),
     291                                  GTK_POLICY_AUTOMATIC,
     292                                  GTK_POLICY_AUTOMATIC );
     293  gtk_container_add( GTK_CONTAINER( scroll ), text );
     294
     295  gtk_box_pack_start( GTK_BOX( vbox ), scroll, TRUE, TRUE, 0 );
     296
     297
     298  msgwin_update( );
     299  gtk_container_add( GTK_CONTAINER( win ), vbox );
     300  gtk_widget_show_all( win );
     301  return win;
     302}
     303
     304void
     305msgwin_loadpref( void )
     306{
     307    int level = TR_MSG_INF;
     308    textbuf = debug_window_text_buffer_new ( );
     309    gboolean b = tr_prefs_get_int( PREF_ID_MSGLEVEL, &level );
     310g_message ("level from prefs: %d (b==%d)", level, (int)b );
     311    tr_setMessageLevel( level );
     312    tr_setMessageQueuing( TRUE );
     313}
Note: See TracChangeset for help on using the changeset viewer.