source: trunk/gtk/msgwin.c @ 1125

Last change on this file since 1125 was 866, checked in by joshe, 15 years ago

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.

  • Property svn:keywords set to Date Rev Author Id
File size: 7.9 KB
Line 
1/******************************************************************************
2 * $Id: msgwin.c 866 2006-09-18 01:26:49Z livings124 $
3 *
4 * Copyright (c) 2006 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#include <errno.h>
26#include <string.h>
27
28#include <gtk/gtk.h>
29#include <glib/gi18n.h>
30
31#include "conf.h"
32#include "msgwin.h"
33#include "transmission.h"
34#include "util.h"
35
36#define MAX_MSGCOUNT 5000
37
38#define COL_LVL 0
39#define COL_MSG 1
40
41static void
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 );
49
50static 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};
57
58GtkWidget *
59msgwin_create( void ) {
60  GtkWidget * win, * vbox, * scroll, * text;
61  GtkWidget * frame, * bbox, * save, * clear, * menu;
62  PangoFontDescription * desc;
63  unsigned int ii;
64  int 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_widget_show_all( win );
116
117  return win;
118}
119
120static void
121changelevel( GtkWidget * widget, gpointer data SHUTUP ) {
122  int    index;
123  char * ignored;
124
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 );
130    cf_saveprefs( &ignored );
131    g_free( ignored );
132    msgwin_update();
133  }
134}
135
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
196void
197msgwin_loadpref( void ) {
198  const char * pref;
199  unsigned int ii;
200
201  tr_setMessageQueuing( 1 );
202  pref = cf_getpref( PREF_MSGLEVEL );
203  if( NULL == pref )
204    return;
205
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  }
212}
213
214void
215msgwin_update( void ) {
216  tr_msg_list_t * msgs, * ii;
217  GtkTextIter     iter, front;
218  char          * label, * line;
219  int             count;
220  struct tm     * tm;
221  unsigned int    jj;
222
223  if( NULL == textbuf )
224    return;
225
226  msgs = tr_getQueuedMessages();
227  for( ii = msgs; NULL != ii; ii = ii->next ) {
228    label = _("???");
229    for( jj = 0; ALEN( levels ) > jj; jj++ ) {
230      if( levels[jj].id == ii->level ) {
231        label = levels[jj].text;
232        break;
233      }
234    }
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 );
238    gtk_text_buffer_get_end_iter( textbuf, &iter );
239    gtk_text_buffer_insert( textbuf, &iter, line, -1 );
240    g_free( line );
241  }
242  tr_freeMessageList( msgs );
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 TracBrowser for help on using the repository browser.