source: trunk/gtk/msgwin.c @ 3401

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

janitorial work for the freeze: (1) finish replacing "transmission-gtk" with "transmission". (2) add Charles to authors lists in man pages. (3) standardize the summary as "A fast and easy BitTorrent? client" in the rpm spec, gtk about dialog, and man pages. (4) fold together similar translation strings in the gtk client. (5) use g_strerror instead of strerror in the gtk client.

  • Property svn:keywords set to Date Rev Author Id
File size: 9.6 KB
Line 
1/******************************************************************************
2 * $Id: msgwin.c 3401 2007-10-13 17:33:53Z 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 Debug 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 ), _( "Debug Window" ) );
233  gtk_window_set_default_size( GTK_WINDOW( win ), 600, 400 );
234  gtk_window_set_role( GTK_WINDOW( win ), "debug-window" );
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.