source: trunk/gtk/msgwin.c @ 3867

Last change on this file since 3867 was 3867, checked in by charles, 15 years ago

Rename "Debug Window" as "Message Log", which is the terminology the OS X client uses too

  • Property svn:keywords set to Date Rev Author Id
File size: 9.6 KB
Line 
1/******************************************************************************
2 * $Id: msgwin.c 3867 2007-11-18 02:32:46Z charles $
3 *
4 * Copyright (c) 2006-2007 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 <stdio.h>
27#include <string.h>
28
29#include <gtk/gtk.h>
30#include <glib/gi18n.h>
31
32#include <libtransmission/transmission.h>
33
34#include "conf.h"
35#include "msgwin.h"
36#include "tr_prefs.h"
37#include "util.h"
38
39#define MAX_MSGCOUNT 5000
40
41#define COL_LVL 0
42#define COL_MSG 1
43
44static GtkTextBuffer * textbuf = NULL;
45
46static GtkTextTag*
47get_or_create_tag (GtkTextTagTable * table, const char * key)
48{
49  GtkTextTag * tag;
50
51  g_assert (table);
52  g_assert (key && *key);
53
54  tag = gtk_text_tag_table_lookup (table, key);
55  if (!tag) {
56    tag = gtk_text_tag_new (key);
57    gtk_text_tag_table_add (table, tag);
58    g_object_unref (tag); /* table refs it */
59  }
60
61  return tag;
62}
63
64static GtkTextBuffer*
65debug_window_text_buffer_new ( void )
66{
67  GtkTextBuffer * buffer = gtk_text_buffer_new ( NULL );
68
69  GtkTextTagTable * table = gtk_text_buffer_get_tag_table (buffer);
70
71  g_object_set (get_or_create_tag(table,"bold"),
72      "weight", PANGO_WEIGHT_BOLD,
73      NULL);
74 
75  g_object_set (get_or_create_tag (table, "info"),
76      "foreground", "black",
77      NULL);
78 
79  g_object_set (get_or_create_tag (table, "error"),
80      "foreground", "red",
81      NULL);
82
83  g_object_set (get_or_create_tag (table, "debug"),
84      "foreground", "gray",
85      NULL);
86
87  return buffer;
88}
89
90void
91msgwin_update( void )
92{
93  tr_msg_list * msgs, * ii;
94
95  g_assert( textbuf != NULL );
96
97  msgs = tr_getQueuedMessages();
98  for( ii = msgs; NULL != ii; ii = ii->next )
99  {
100    int len;
101    char * line;
102    const char * tag = NULL;
103    struct tm * tm = localtime( &ii->when );
104    GtkTextIter mark_start, mark_end;
105
106    switch( ii->level ) {
107      case TR_MSG_ERR: tag = "error"; break;
108      case TR_MSG_INF: tag = "info"; break;
109      case TR_MSG_DBG: tag = "debug"; break;
110    }
111
112    line = g_strdup_printf( "%02i:%02i:%02i %s\n", tm->tm_hour, tm->tm_min, tm->tm_sec, ii->message );
113    len = strlen( line );
114
115    gtk_text_buffer_get_end_iter( textbuf, &mark_end );
116    gtk_text_buffer_insert( textbuf, &mark_end, line, len );
117    mark_start = mark_end;
118    gtk_text_iter_backward_chars( &mark_start, len );
119    gtk_text_buffer_apply_tag_by_name (textbuf, tag, &mark_start, &mark_end);
120
121    g_free( line );
122  }
123  tr_freeMessageList( msgs );
124
125#if 0
126  count = gtk_text_buffer_get_line_count( textbuf );
127  if( MAX_MSGCOUNT < count ) {
128    gtk_text_buffer_get_iter_at_line( textbuf, &front, 0 );
129    gtk_text_buffer_get_iter_at_line( textbuf, &iter, count - MAX_MSGCOUNT );
130    gtk_text_buffer_delete( textbuf, &front, &iter );
131  }
132#endif
133}
134
135static void
136level_combo_changed_cb( GtkWidget * w, TrCore * core )
137{
138    GtkTreeIter iter;
139    if( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(w), &iter ) ) {
140        int id = 0;
141        GtkTreeModel * m = gtk_combo_box_get_model( GTK_COMBO_BOX(w) );
142        gtk_tree_model_get( m, &iter, 1, &id, -1 );
143        tr_setMessageLevel( id );
144        tr_core_set_pref_int( core, PREF_KEY_MSGLEVEL, id );
145        msgwin_update( );
146    }
147}
148
149static void
150save_dialog_response_cb( GtkWidget * d, int response, GtkTextBuffer * textbuf )
151{
152  if( response == GTK_RESPONSE_ACCEPT )
153  {
154      char * filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( d ) );
155      FILE * fp = fopen( filename, "w+" );
156      if( !fp )
157      {
158          errmsg( GTK_WINDOW(d),
159                  _("Error writing to \"%s\": %s"),
160                  filename, g_strerror( errno ) );
161      }
162      else
163      {
164          char * buf;
165          GtkTextIter front, back;
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( buf ) {
170              const size_t len = strlen( buf );
171              if( len > fwrite( buf, 1, len, fp ) ) {
172                  errmsg( GTK_WINDOW( d ),
173                          _("Error writing to \"%s\": %s"),
174                          filename, g_strerror( errno ) );
175              }
176              g_free( buf );
177          }
178          fclose( fp );
179      }
180      g_free( filename );
181  }
182
183  gtk_widget_destroy( d );
184}
185
186static void
187save_cb( GtkWidget * w, GtkTextBuffer * textbuf )
188{
189  GtkWindow * window = GTK_WINDOW( gtk_widget_get_toplevel( w ) );
190  GtkWidget * d = gtk_file_chooser_dialog_new( _("Save Log"), window,
191                                               GTK_FILE_CHOOSER_ACTION_SAVE,
192                                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
193                                               GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
194                                               NULL );
195  g_signal_connect( d, "response",
196                    G_CALLBACK( save_dialog_response_cb ), textbuf );
197  gtk_widget_show( d );
198}
199
200static void
201clear_cb( GtkWidget * w UNUSED, GtkTextBuffer * textbuf )
202{
203  GtkTextIter front, back;
204  gtk_text_buffer_get_start_iter( textbuf, &front );
205  gtk_text_buffer_get_end_iter( textbuf, &back );
206  gtk_text_buffer_delete( textbuf, &front, &back );
207}
208
209static struct {
210  const char * label;
211  const char * pref;
212  const char * text;
213  int id;
214} trLevels[] = {
215  { N_("Error"), "error", "ERR", TR_MSG_ERR },
216  { N_("Info"),  "info",  "INF", TR_MSG_INF },
217  { N_("Debug"), "debug", "DBG", TR_MSG_DBG },
218};
219
220GtkWidget *
221msgwin_create( TrCore * core )
222{
223  unsigned int i;
224  GtkListStore * store;
225  GtkWidget * win, * vbox, * scroll, * text;
226  GtkWidget * levels;
227  GtkWidget * toolbar;
228  GtkCellRenderer * renderer;
229  int ii, curlevel;
230
231  win = gtk_window_new( GTK_WINDOW_TOPLEVEL );
232  gtk_window_set_title( GTK_WINDOW( win ), _( "Message Log" ) );
233  gtk_window_set_default_size( GTK_WINDOW( win ), 600, 400 );
234  gtk_window_set_role( GTK_WINDOW( win ), "message-log" );
235  vbox = gtk_vbox_new( FALSE, 0 );
236
237  /**
238  ***  toolbar
239  **/
240
241  toolbar = gtk_toolbar_new ();
242  gtk_toolbar_set_style( GTK_TOOLBAR( toolbar), GTK_TOOLBAR_BOTH_HORIZ );
243
244  gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_SAVE,
245                           NULL, NULL,
246                           G_CALLBACK(save_cb), textbuf, -1);
247
248  gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_CLEAR,
249                           NULL, NULL,
250                           G_CALLBACK(clear_cb), textbuf, -1);
251
252  gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1);
253
254
255  gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
256                             GTK_TOOLBAR_CHILD_WIDGET, gtk_label_new(_("Level ")),
257                             NULL, _("Select the debug filter level."),
258                             NULL, NULL, NULL, NULL);
259
260  store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
261
262  curlevel = pref_int_get( PREF_KEY_MSGLEVEL );
263  for( i=ii=0; i<G_N_ELEMENTS(trLevels); ++i ) {
264      GtkTreeIter iter;
265      gtk_list_store_append (store, &iter);
266      gtk_list_store_set (store, &iter, 0, _(trLevels[i].label),
267                                        1, trLevels[i].id,
268                                       -1);
269      if( trLevels[i].id == curlevel )
270          ii = i;
271  }
272  levels = gtk_combo_box_new_with_model (GTK_TREE_MODEL(store));
273  g_object_unref (G_OBJECT(store));
274  renderer = gtk_cell_renderer_text_new ();
275  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(levels), renderer, TRUE);
276  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT(levels), renderer, "text", 0, NULL);
277  gtk_combo_box_set_active( GTK_COMBO_BOX( levels ), ii );
278  g_signal_connect( levels, "changed", G_CALLBACK(level_combo_changed_cb), core );
279
280  gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
281                             GTK_TOOLBAR_CHILD_WIDGET, levels,
282                             NULL, _("Select the debug filter level."),
283                             NULL, NULL, NULL, NULL);
284
285  gtk_box_pack_start( GTK_BOX( vbox ), toolbar, FALSE, FALSE, 0 );
286
287  /**
288  ***  text area
289  **/
290
291  text = gtk_text_view_new_with_buffer( textbuf );
292  gtk_text_view_set_editable( GTK_TEXT_VIEW( text ), FALSE );
293
294  scroll = gtk_scrolled_window_new( NULL, NULL );
295  gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scroll ),
296                                  GTK_POLICY_AUTOMATIC,
297                                  GTK_POLICY_AUTOMATIC );
298  gtk_container_add( GTK_CONTAINER( scroll ), text );
299
300  gtk_box_pack_start( GTK_BOX( vbox ), scroll, TRUE, TRUE, 0 );
301
302  msgwin_update( );
303  gtk_container_add( GTK_CONTAINER( win ), vbox );
304  gtk_widget_show_all( win );
305  return win;
306}
307
308void
309msgwin_loadpref( void )
310{
311    textbuf = debug_window_text_buffer_new ( );
312    tr_setMessageLevel( pref_int_get( PREF_KEY_MSGLEVEL ) );
313    tr_setMessageQueuing( TRUE );
314}
Note: See TracBrowser for help on using the repository browser.