diff --git a/gtk/main.c b/gtk/main.c index e78ddabb6..03aeb7361 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -63,7 +63,7 @@ #include /* interval in milliseconds to update the torrent list display */ -#define UPDATE_INTERVAL 1000 +#define UPDATE_INTERVAL 1666 /* interval in milliseconds to check for stopped torrents and update display */ #define EXIT_CHECK_INTERVAL 500 @@ -320,9 +320,6 @@ main( int argc, char ** argv ) GtkWindow * mainwind = GTK_WINDOW( tr_window_new( myUIManager, cbdata->core ) ); g_signal_connect( mainwind, "window-state-event", G_CALLBACK(windowStateChanged), cbdata ); - /* set message level here before tr_init() */ - msgwin_loadpref( ); - appsetup( mainwind, argfiles, cbdata, startpaused, startminimized ); } else @@ -880,9 +877,6 @@ updatemodel(gpointer gdata) { if( data->wind ) tr_window_update( data->wind ); - /* update the message window */ - msgwin_update(); - return TRUE; } @@ -1123,7 +1117,7 @@ doAction ( const char * action_name, gpointer user_data ) { if( !data->msgwin ) { - GtkWidget * win = msgwin_create( data->core ); + GtkWidget * win = msgwin_new( data->core ); g_signal_connect( win, "destroy", G_CALLBACK( msgwinclosed ), NULL ); data->msgwin = win; diff --git a/gtk/msgwin.c b/gtk/msgwin.c index f3b63dcad..3db5494e7 100644 --- a/gtk/msgwin.c +++ b/gtk/msgwin.c @@ -1,26 +1,14 @@ -/****************************************************************************** - * $Id$ +/* + * This file Copyright (C) 2008 Charles Kerr * - * Copyright (c) 2006-2008 Transmission authors and contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - *****************************************************************************/ + * This file is licensed by the GPL version 2. Works owned by the + * Transmission project are granted a special exemption to clause 2(b) + * so that the bulk of its code can remain under the MIT license. + * This exemption does not extend to derived works not owned by + * the Transmission project. + * + * $Id:$ + */ #include #include @@ -34,6 +22,7 @@ #include "conf.h" #include "hig.h" #include "msgwin.h" +#include "tr-core.h" #include "tr-prefs.h" #include "util.h" @@ -57,9 +46,11 @@ struct MsgData GtkTreeModel * filter; GtkTreeModel * sort; int maxLevel; + guint refresh_tag; }; -static struct MsgData myData; +static struct tr_msg_list * myTail = NULL; +static struct tr_msg_list * myHead = NULL; /*** **** @@ -164,10 +155,12 @@ onSaveRequest( GtkWidget * w, gpointer data ) } static void -onClearRequest( GtkWidget * w UNUSED, gpointer unused UNUSED ) +onClearRequest( GtkWidget * w UNUSED, gpointer gdata ) { - struct MsgData * data = &myData; + struct MsgData * data = gdata; gtk_list_store_clear( data->store ); + tr_freeMessageList( myHead ); + myHead = myTail = NULL; } static struct { @@ -304,128 +297,155 @@ isRowVisible( GtkTreeModel * model, GtkTreeIter * iter, gpointer gdata ) return level <= data->maxLevel; } +static void +onWindowDestroyed( gpointer gdata, GObject * deadWindow UNUSED ) +{ + struct MsgData * data = gdata; + g_source_remove( data->refresh_tag ); + g_free( data ); +} + +static tr_msg_list * +addMessages( GtkListStore * store, struct tr_msg_list * head ) +{ + const char * default_category = g_get_application_name( ); + static int sequence = 1; + tr_msg_list * i; + + for( i=head; i; i=i->next ) + { + GtkTreeIter unused; + + gtk_list_store_insert_with_values( store, &unused, 0, + COL_LEVEL, (int)i->level, + COL_LINE, i->line, + COL_FILE, i->file, + COL_TIME, (uint64_t)i->when, + COL_CATEGORY, ( i->name ? i->name : default_category ), + COL_MESSAGE, i->message, + COL_SEQUENCE, sequence++, + -1 ); + + if( !i->next ) + break; + } + + return i; /* tail */ +} + +static gboolean +onRefresh( gpointer gdata ) +{ + tr_msg_list * msgs = tr_getQueuedMessages( ); + if( msgs ) + { + /* add the new messages and append them to the end of + * our persistent list */ + struct MsgData * data = gdata; + tr_msg_list * tail = addMessages( data->store, msgs ); + if( myTail ) + myTail->next = msgs; + else + myHead = msgs; + myTail = tail; + } + return TRUE; +} + /** *** Public Functions **/ GtkWidget * -msgwin_create( TrCore * core ) +msgwin_new( TrCore * core ) { - unsigned int i; - GtkListStore * store; - GtkWidget * win; - GtkWidget * vbox; - GtkWidget * levels; - GtkWidget * toolbar; - GtkWidget * w; - GtkWidget * view; - GtkWidget * l; - GtkCellRenderer * renderer; - int ii, curlevel; - struct MsgData * data; + unsigned int i; + GtkListStore * store; + GtkWidget * win; + GtkWidget * vbox; + GtkWidget * levels; + GtkWidget * toolbar; + GtkWidget * w; + GtkWidget * view; + GtkWidget * l; + GtkCellRenderer * renderer; + int ii, curlevel; + struct MsgData * data; - data = &myData; - data->core = core; + data = g_new0( struct MsgData, 1 ); + data->core = core; - win = gtk_window_new( GTK_WINDOW_TOPLEVEL ); - gtk_window_set_title( GTK_WINDOW( win ), _( "Message Log" ) ); - gtk_window_set_default_size( GTK_WINDOW( win ), 600, 400 ); - gtk_window_set_role( GTK_WINDOW( win ), "message-log" ); - vbox = gtk_vbox_new( FALSE, 0 ); + win = gtk_window_new( GTK_WINDOW_TOPLEVEL ); + gtk_window_set_title( GTK_WINDOW( win ), _( "Message Log" ) ); + gtk_window_set_default_size( GTK_WINDOW( win ), 600, 400 ); + gtk_window_set_role( GTK_WINDOW( win ), "message-log" ); + vbox = gtk_vbox_new( FALSE, 0 ); - /** - *** toolbar - **/ + /** + *** toolbar + **/ - toolbar = gtk_toolbar_new( ); - gtk_toolbar_set_style( GTK_TOOLBAR( toolbar), GTK_TOOLBAR_BOTH_HORIZ ); + toolbar = gtk_toolbar_new( ); - gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_SAVE, - NULL, NULL, - G_CALLBACK(onSaveRequest), data, -1); + gtk_toolbar_insert_stock( GTK_TOOLBAR(toolbar), GTK_STOCK_SAVE, + NULL, NULL, + G_CALLBACK(onSaveRequest), data, -1); - gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_CLEAR, - NULL, NULL, - G_CALLBACK(onClearRequest), data, -1); + gtk_toolbar_insert_stock( GTK_TOOLBAR(toolbar), GTK_STOCK_CLEAR, + NULL, NULL, + G_CALLBACK(onClearRequest), data, -1); - gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1); + gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1); - l = gtk_label_new( _( "Level" ) ); - gtk_misc_set_padding( GTK_MISC( l ), GUI_PAD, 0 ); - gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_CHILD_WIDGET, l, - NULL, _("Set the verbosity level"), - NULL, NULL, NULL, NULL); + l = gtk_label_new( _( "Level" ) ); + gtk_misc_set_padding( GTK_MISC( l ), GUI_PAD, 0 ); + gtk_toolbar_append_element( GTK_TOOLBAR(toolbar), + GTK_TOOLBAR_CHILD_WIDGET, l, + NULL, _("Set the verbosity level"), + NULL, NULL, NULL, NULL); - w = gtk_alignment_new( 0.0f, 0.0f, 0.0f, 0.0f ); - gtk_widget_set_size_request( w, GUI_PAD_SMALL, GUI_PAD_SMALL ); - gtk_toolbar_append_element( GTK_TOOLBAR(toolbar), - GTK_TOOLBAR_CHILD_WIDGET, w, - NULL, NULL, NULL, NULL, NULL, NULL); + w = gtk_alignment_new( 0.0f, 0.0f, 0.0f, 0.0f ); + gtk_widget_set_size_request( w, GUI_PAD_SMALL, GUI_PAD_SMALL ); + gtk_toolbar_append_element( GTK_TOOLBAR(toolbar), + GTK_TOOLBAR_CHILD_WIDGET, w, + NULL, NULL, NULL, NULL, NULL, NULL); - store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); + store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); - curlevel = pref_int_get( PREF_KEY_MSGLEVEL ); - for( i=ii=0; isort ); - data->view = GTK_TREE_VIEW( view ); - gtk_tree_view_set_rules_hint( data->view, TRUE ); - appendColumn( data->view, COL_TIME ); - appendColumn( data->view, COL_CATEGORY ); - appendColumn( data->view, COL_MESSAGE ); - w = gtk_scrolled_window_new( NULL, NULL ); - gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( w ), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC ); - gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( w ), - GTK_SHADOW_IN); - gtk_container_add( GTK_CONTAINER( w ), view ); - gtk_box_pack_start( GTK_BOX( vbox ), w, TRUE, TRUE, 0 ); - gtk_container_add( GTK_CONTAINER( win ), vbox ); - - - msgwin_update( ); - gtk_widget_show_all( win ); - return win; -} - -void -msgwin_loadpref( void ) -{ - struct MsgData * data = &myData; + /** + *** messages + **/ data->store = gtk_list_store_new( N_COLUMNS, G_TYPE_INT, /* level */ @@ -435,37 +455,35 @@ msgwin_loadpref( void ) G_TYPE_STRING, /* category */ G_TYPE_STRING, /* message */ G_TYPE_INT ); /* sequence */ + addMessages( data->store, myHead ); + onRefresh( data ); /* much faster to populate *before* it has listeners */ data->filter = gtk_tree_model_filter_new( GTK_TREE_MODEL( data->store ), NULL ); data->sort = gtk_tree_model_sort_new_with_model( data->filter ); data->maxLevel = pref_int_get( PREF_KEY_MSGLEVEL ); gtk_tree_model_filter_set_visible_func( GTK_TREE_MODEL_FILTER( data->filter ), isRowVisible, data, NULL ); -} - -void -msgwin_update( void ) -{ - tr_msg_list * i; - tr_msg_list * msgs; - struct MsgData * data = &myData; - static int sequence = 1; - const char * default_category = g_get_application_name( ); - - msgs = tr_getQueuedMessages(); - for( i=msgs; i; i=i->next ) - { - GtkTreeIter unused; - - gtk_list_store_insert_with_values( data->store, &unused, -1, - COL_LEVEL, (int)i->level, - COL_LINE, i->line, - COL_FILE, i->file, - COL_TIME, (uint64_t)i->when, - COL_CATEGORY, ( i->name ? i->name : default_category ), - COL_MESSAGE, i->message, - COL_SEQUENCE, sequence++, - -1 ); - } - tr_freeMessageList( msgs ); + + + view = gtk_tree_view_new_with_model( data->sort ); + data->view = GTK_TREE_VIEW( view ); + gtk_tree_view_set_rules_hint( data->view, TRUE ); + appendColumn( data->view, COL_TIME ); + appendColumn( data->view, COL_CATEGORY ); + appendColumn( data->view, COL_MESSAGE ); + w = gtk_scrolled_window_new( NULL, NULL ); + gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( w ), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC ); + gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( w ), + GTK_SHADOW_IN); + gtk_container_add( GTK_CONTAINER( w ), view ); + gtk_box_pack_start( GTK_BOX( vbox ), w, TRUE, TRUE, 0 ); + gtk_container_add( GTK_CONTAINER( win ), vbox ); + + data->refresh_tag = g_timeout_add( 1000, onRefresh, data ); + g_object_weak_ref( G_OBJECT( win ), onWindowDestroyed, data ); + + gtk_widget_show_all( win ); + return win; } diff --git a/gtk/msgwin.h b/gtk/msgwin.h index de4ee68de..c20827bfb 100644 --- a/gtk/msgwin.h +++ b/gtk/msgwin.h @@ -1,42 +1,20 @@ -/****************************************************************************** - * $Id$ +/* + * This file Copyright (C) 2008 Charles Kerr * - * Copyright (c) 2005-2008 Transmission authors and contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - *****************************************************************************/ + * This file is licensed by the GPL version 2. Works owned by the + * Transmission project are granted a special exemption to clause 2(b) + * so that the bulk of its code can remain under the MIT license. + * This exemption does not extend to derived works not owned by + * the Transmission project. + * + * $Id:$ + */ #ifndef TG_MSGWIN_H #define TG_MSGWIN_H -#include "tr-core.h" +struct TrCore; -void -msgwin_init( void ); +GtkWidget * msgwin_new( struct TrCore * core ); -GtkWidget * -msgwin_create( TrCore* core ); - -void -msgwin_update( void ); - -void -msgwin_loadpref( void ); - -#endif /* TG_MSGWIN_H */ +#endif diff --git a/gtk/torrent-cell-renderer.c b/gtk/torrent-cell-renderer.c index aa44fc21e..12afbbe49 100644 --- a/gtk/torrent-cell-renderer.c +++ b/gtk/torrent-cell-renderer.c @@ -77,7 +77,7 @@ getProgressString( const tr_info * info, const tr_stat * torStat ) tr_strlsize( buf2, torStat->uploadedEver, sizeof(buf2) ), tr_strlratio( buf3, torStat->ratio, sizeof( buf3 ) ) ); - // add time when downloading + /* add time when downloading */ if( torStat->status == TR_STATUS_DOWNLOAD ) { const int eta = torStat->eta; diff --git a/gtk/tr-core.c b/gtk/tr-core.c index edea68532..de97a0639 100644 --- a/gtk/tr-core.c +++ b/gtk/tr-core.c @@ -554,7 +554,7 @@ doCollate( const char * in ) while( in < end ) { const gunichar ch = g_utf8_get_char( in ); - if (!g_unichar_isalnum (ch)) // eat everything before the first alnum + if (!g_unichar_isalnum (ch)) /* eat everything before the first alnum */ in += g_unichar_to_utf8( ch, NULL ); else break;