Changeset 8174
- Timestamp:
- Apr 7, 2009, 8:13:08 PM (14 years ago)
- Location:
- trunk/gtk
- Files:
-
- 2 deleted
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gtk/Makefile.am
r8152 r8174 38 38 actions.h \ 39 39 add-dialog.h \ 40 blocklist.h \41 40 conf.h \ 42 41 details.h \ … … 72 71 actions.c \ 73 72 add-dialog.c \ 74 blocklist.c \75 73 conf.c \ 76 74 details.c \ -
trunk/gtk/main.c
r8172 r8174 43 43 #include "actions.h" 44 44 #include "add-dialog.h" 45 #include "blocklist.h"46 45 #include "conf.h" 47 46 #include "details.h" … … 447 446 appsetup( win, argfiles, cbdata, startpaused, startminimized ); 448 447 tr_sessionSetRPCCallback( session, onRPCChanged, cbdata ); 449 gtr_blocklist_maybe_autoupdate( cbdata->core ); 448 449 /* on startup, check & see if it's time to update the blocklist */ 450 if( pref_flag_get( PREF_KEY_BLOCKLIST_UPDATES_ENABLED ) 451 && ( time( NULL ) - pref_int_get( "blocklist-date" ) > ( 60 * 60 * 24 * 7 ) ) ) 452 tr_core_blocklist_update( cbdata->core ); 450 453 451 454 gtk_main( ); -
trunk/gtk/tr-core.c
r8122 r8174 35 35 36 36 #include <libtransmission/transmission.h> 37 #include <libtransmission/bencode.h> 38 #include <libtransmission/rpcimpl.h> 39 #include <libtransmission/json.h> 37 40 #include <libtransmission/utils.h> /* tr_free */ 38 41 … … 97 100 } 98 101 99 static void100 tr_core_marshal_blocklist( GClosure * closure,101 GValue * ret UNUSED,102 guint count,103 const GValue * vals,104 gpointer hint UNUSED,105 gpointer marshal )106 {107 typedef void ( *TRMarshalErr )108 ( gpointer, enum tr_core_err, const char *,109 gpointer );110 TRMarshalErr callback;111 GCClosure * cclosure = (GCClosure*) closure;112 gboolean flag;113 const char * str;114 gpointer inst, gdata;115 116 g_return_if_fail( count == 3 );117 118 inst = g_value_peek_pointer( vals );119 flag = g_value_get_boolean( vals + 1 );120 str = g_value_get_string( vals + 2 );121 gdata = closure->data;122 123 callback = (TRMarshalErr)( marshal ? marshal : cclosure->callback );124 callback( inst, flag, str, gdata );125 }126 127 static void128 tr_core_marshal_prompt( GClosure * closure,129 GValue * ret UNUSED,130 guint count,131 const GValue * vals,132 gpointer hint UNUSED,133 gpointer marshal )134 {135 typedef void ( *TRMarshalPrompt )( gpointer, tr_ctor *, gpointer );136 TRMarshalPrompt callback;137 GCClosure * cclosure = (GCClosure*) closure;138 gpointer ctor;139 gpointer inst, gdata;140 141 g_return_if_fail( count == 2 );142 143 inst = g_value_peek_pointer( vals );144 ctor = g_value_peek_pointer( vals + 1 );145 gdata = closure->data;146 147 callback = (TRMarshalPrompt)( marshal ? marshal : cclosure->callback );148 callback( inst, ctor, gdata );149 }150 151 102 static int 152 103 isDisposed( const TrCore * core ) … … 176 127 { 177 128 GObjectClass * gobject_class; 178 TrCoreClass * c ore_class;129 TrCoreClass * cc; 179 130 180 131 g_type_class_add_private( g_class, sizeof( struct TrCorePrivate ) ); … … 183 134 gobject_class->dispose = tr_core_dispose; 184 135 185 186 core_class = TR_CORE_CLASS( g_class ); 187 core_class->blocksig = g_signal_new( "blocklist-status", 188 G_TYPE_FROM_CLASS( 189 g_class ), 190 G_SIGNAL_RUN_LAST, 0, NULL, NULL, 191 tr_core_marshal_blocklist, 192 G_TYPE_NONE, 193 2, G_TYPE_BOOLEAN, G_TYPE_STRING ); 194 core_class->errsig = g_signal_new( "error", G_TYPE_FROM_CLASS( g_class ), 195 G_SIGNAL_RUN_LAST, 0, NULL, NULL, 196 tr_core_marshal_err, G_TYPE_NONE, 197 2, G_TYPE_INT, G_TYPE_STRING ); 198 core_class->promptsig = g_signal_new( "add-torrent-prompt", 199 G_TYPE_FROM_CLASS( 200 g_class ), 201 G_SIGNAL_RUN_LAST, 0, NULL, NULL, 202 tr_core_marshal_prompt, 203 G_TYPE_NONE, 204 1, G_TYPE_POINTER ); 205 core_class->quitsig = g_signal_new( "quit", G_TYPE_FROM_CLASS( g_class ), 206 G_SIGNAL_RUN_LAST, 0, NULL, NULL, 207 g_cclosure_marshal_VOID__VOID, 208 G_TYPE_NONE, 0 ); 209 core_class->prefsig = g_signal_new( "prefs-changed", 210 G_TYPE_FROM_CLASS( g_class ), 211 G_SIGNAL_RUN_LAST, 0, NULL, NULL, 212 g_cclosure_marshal_VOID__STRING, 213 G_TYPE_NONE, 1, G_TYPE_STRING ); 136 cc = TR_CORE_CLASS( g_class ); 137 138 cc->blocklistSignal = g_signal_new( "blocklist-updated", /* name */ 139 G_TYPE_FROM_CLASS( g_class ), /* applies to TrCore */ 140 G_SIGNAL_RUN_FIRST, /* when to invoke */ 141 0, NULL, NULL, /* accumulator */ 142 g_cclosure_marshal_VOID__INT, /* marshaler */ 143 G_TYPE_NONE, /* return type */ 144 1, G_TYPE_INT ); /* signal arguments */ 145 146 cc->portSignal = g_signal_new( "port-tested", 147 G_TYPE_FROM_CLASS( g_class ), 148 G_SIGNAL_RUN_LAST, 149 0, NULL, NULL, 150 g_cclosure_marshal_VOID__BOOLEAN, 151 G_TYPE_NONE, 152 1, G_TYPE_BOOLEAN ); 153 154 cc->errsig = g_signal_new( "error", 155 G_TYPE_FROM_CLASS( g_class ), 156 G_SIGNAL_RUN_LAST, 157 0, NULL, NULL, 158 tr_core_marshal_err, 159 G_TYPE_NONE, 160 2, G_TYPE_INT, G_TYPE_STRING ); 161 162 cc->promptsig = g_signal_new( "add-torrent-prompt", 163 G_TYPE_FROM_CLASS( g_class ), 164 G_SIGNAL_RUN_LAST, 165 0, NULL, NULL, 166 g_cclosure_marshal_VOID__POINTER, 167 G_TYPE_NONE, 168 1, G_TYPE_POINTER ); 169 170 cc->quitsig = g_signal_new( "quit", 171 G_TYPE_FROM_CLASS( g_class ), 172 G_SIGNAL_RUN_LAST, 173 0, NULL, NULL, 174 g_cclosure_marshal_VOID__VOID, 175 G_TYPE_NONE, 176 0 ); 177 178 cc->prefsig = g_signal_new( "prefs-changed", 179 G_TYPE_FROM_CLASS( g_class ), 180 G_SIGNAL_RUN_LAST, 181 0, NULL, NULL, 182 g_cclosure_marshal_VOID__STRING, 183 G_TYPE_NONE, 184 1, G_TYPE_STRING ); 214 185 215 186 #ifdef HAVE_DBUS_GLIB … … 887 858 } 888 859 889 void 890 tr_core_blocksig( TrCore * core, 891 gboolean isDone, 892 const char * status ) 893 { 894 g_signal_emit( core, TR_CORE_GET_CLASS( 895 core )->blocksig, 0, isDone, status ); 860 static void 861 emitBlocklistUpdated( TrCore * core, int ruleCount ) 862 { 863 g_signal_emit( core, TR_CORE_GET_CLASS( core )->blocklistSignal, 0, ruleCount ); 864 } 865 866 static void 867 emitPortTested( TrCore * core, gboolean isOpen ) 868 { 869 g_signal_emit( core, TR_CORE_GET_CLASS( core )->portSignal, 0, isOpen ); 896 870 } 897 871 … … 1040 1014 if( findTorrentInModel( core, id, &iter ) ) 1041 1015 { 1042 TrTorrent * 1016 TrTorrent * gtor; 1043 1017 GtkTreeModel * model = tr_core_model( core ); 1044 1018 gtk_tree_model_get( model, &iter, MC_TORRENT, >or, -1 ); … … 1337 1311 } 1338 1312 1313 /*** 1314 **** 1315 **** RPC Interface 1316 **** 1317 ***/ 1318 1319 /* #define DEBUG_RPC */ 1320 1321 static int nextTag = 1; 1322 1323 typedef void ( server_response_func )( TrCore * core, tr_benc * response, gpointer user_data ); 1324 1325 struct pending_request_data 1326 { 1327 int tag; 1328 TrCore * core; 1329 server_response_func * responseFunc; 1330 gpointer responseFuncUserData; 1331 }; 1332 1333 static GHashTable * pendingRequests = NULL; 1334 1335 static gboolean 1336 readResponseIdle( void * vresponse ) 1337 { 1338 GByteArray * response; 1339 tr_benc top; 1340 int64_t intVal; 1341 int tag; 1342 struct pending_request_data * data; 1343 1344 response = vresponse; 1345 tr_jsonParse( response->data, response->len, &top, NULL ); 1346 tr_bencDictFindInt( &top, "tag", &intVal ); 1347 tag = (int)intVal; 1348 1349 data = g_hash_table_lookup( pendingRequests, &tag ); 1350 if( data ) 1351 (*data->responseFunc)(data->core, &top, data->responseFuncUserData ); 1352 1353 tr_bencFree( &top ); 1354 g_hash_table_remove( pendingRequests, &tag ); 1355 g_byte_array_free( response, TRUE ); 1356 return FALSE; 1357 } 1358 1359 static void 1360 readResponse( tr_session * session UNUSED, 1361 const char * response, 1362 size_t response_len, 1363 void * unused UNUSED ) 1364 { 1365 GByteArray * bytes = g_byte_array_new( ); 1366 #ifdef DEBUG_RPC 1367 g_message( "response: [%*.*s]", (int)response_len, (int)response_len, response ); 1368 #endif 1369 g_byte_array_append( bytes, (const uint8_t*)response, response_len ); 1370 g_idle_add( readResponseIdle, bytes ); 1371 } 1372 1373 static void 1374 sendRequest( TrCore * core, const char * json, int tag, 1375 server_response_func * responseFunc, void * responseFuncUserData ) 1376 { 1377 tr_session * session = tr_core_session( core ); 1378 1379 if( pendingRequests == NULL ) 1380 { 1381 pendingRequests = g_hash_table_new_full( g_int_hash, g_int_equal, NULL, g_free ); 1382 } 1383 1384 if( session == NULL ) 1385 { 1386 g_error( "GTK+ client doesn't support connections to remote servers yet." ); 1387 } 1388 else 1389 { 1390 /* remember this request */ 1391 struct pending_request_data * data; 1392 data = g_new0( struct pending_request_data, 1 ); 1393 data->core = core; 1394 data->tag = tag; 1395 data->responseFunc = responseFunc; 1396 data->responseFuncUserData = responseFuncUserData; 1397 g_hash_table_insert( pendingRequests, &data->tag, data ); 1398 1399 /* make the request */ 1400 #ifdef DEBUG_RPC 1401 g_message( "request: [%s]", json ); 1402 #endif 1403 tr_rpc_request_exec_json( session, json, strlen( json ), readResponse, GINT_TO_POINTER(tag) ); 1404 } 1405 } 1406 1407 /*** 1408 **** Sending a test-port request via RPC 1409 ***/ 1410 1411 static void 1412 portTestResponseFunc( TrCore * core, tr_benc * response, gpointer userData UNUSED ) 1413 { 1414 tr_benc * args; 1415 tr_bool isOpen = FALSE; 1416 1417 if( tr_bencDictFindDict( response, "arguments", &args ) ) 1418 tr_bencDictFindBool( args, "port-is-open", &isOpen ); 1419 1420 emitPortTested( core, isOpen ); 1421 } 1422 1423 void 1424 tr_core_port_test( TrCore * core ) 1425 { 1426 char buf[128]; 1427 const int tag = nextTag++; 1428 g_snprintf( buf, sizeof( buf ), "{ \"method\": \"port-test\", \"tag\": %d }", tag ); 1429 sendRequest( core, buf, tag, portTestResponseFunc, NULL ); 1430 } 1431 1432 /*** 1433 **** Updating a blocklist via RPC 1434 ***/ 1435 1436 static void 1437 blocklistResponseFunc( TrCore * core, tr_benc * response, gpointer userData UNUSED ) 1438 { 1439 tr_benc * args; 1440 int64_t ruleCount = 0; 1441 1442 if( tr_bencDictFindDict( response, "arguments", &args ) ) 1443 tr_bencDictFindInt( args, "blocklist-size", &ruleCount ); 1444 1445 if( ruleCount > 0 ) 1446 pref_int_set( "blocklist-date", time( NULL ) ); 1447 1448 emitBlocklistUpdated( core, ruleCount ); 1449 } 1450 1451 void 1452 tr_core_blocklist_update( TrCore * core ) 1453 { 1454 char buf[128]; 1455 const int tag = nextTag++; 1456 g_snprintf( buf, sizeof( buf ), "{ \"method\": \"blocklist-update\", \"tag\": %d }", tag ); 1457 sendRequest( core, buf, tag, blocklistResponseFunc, NULL ); 1458 } -
trunk/gtk/tr-core.h
r7888 r8174 65 65 GObjectClass parent; 66 66 67 /* "blocklist" signal: 68 void handler( TrCore *, const char *, gpointer userData ); */ 69 int blocksig; 70 71 /* "error" signal: 72 void handler( TrCore *, enum tr_core_err, const char *, gpointer ) */ 73 int errsig; 74 75 /* "add-torrent-prompt" signal: 76 void handler( TrCore *, gpointer ctor, gpointer userData ) 67 /* "blocklist-updated" signal with a callback type of 68 void (*callback )( TrCore*, int ruleCount, gpointer userData ). */ 69 int blocklistSignal; 70 71 /* "port-tested" signal with a callback type of 72 void( *callback )( TrCore*, gboolean isOpen, gpointer userData ). */ 73 int portSignal; 74 75 /* "error" signal with a callback type of 76 void( *callback )( TrCore*, enum tr_core_err, const char * humanReadable, gpointer userData ). */ 77 int errsig; 78 79 /* "add-torrent-prompt" signal with a callback type of 80 void ( *callback)( TrCore *, gpointer ctor, gpointer userData ) 77 81 The handler assumes ownership of ctor and must free when done */ 78 int 82 int promptsig; 79 83 80 84 /* "quit" signal: 81 85 void handler( TrCore *, gpointer ) */ 82 int 86 int quitsig; 83 87 84 88 /* "prefs-changed" signal: 85 89 void handler( TrCore *, int, gpointer ) */ 86 int 90 int prefsig; 87 91 } 88 92 TrCoreClass; … … 138 142 139 143 /** Add a torrent. */ 140 gboolean tr_core_add_file( 141 TrCore*, 142 const char * filename, 143 gboolean * 144 setme_success, 145 GError ** err ); 144 gboolean tr_core_add_file( TrCore*, const char * filename, gboolean * setme_success, GError ** err ); 145 /** Add a torrent. */ 146 void tr_core_add_torrent( TrCore*, TrTorrent* ); 146 147 147 148 /** Present the main window */ 148 gboolean tr_core_present_window( 149 TrCore*, 150 gboolean * 151 setme_success, 152 GError ** err ); 153 154 /** Add a torrent. */ 155 void tr_core_add_torrent( TrCore*, 156 TrTorrent* ); 149 gboolean tr_core_present_window( TrCore*, gboolean * setme_success, GError ** err ); 150 157 151 158 152 /** … … 168 162 /* we've gotten notice from RPC that a torrent has been destroyed; 169 163 update our gui accordingly */ 170 void tr_core_torrent_destroyed( TrCore * self, 171 int id ); 164 void tr_core_torrent_destroyed( TrCore * self, int torrentId ); 172 165 173 166 /* remove a torrent */ 174 void tr_core_remove_torrent( TrCore * self, 175 TrTorrent * gtor, 176 int deleteFiles ); 167 void tr_core_remove_torrent( TrCore * self, TrTorrent * gtor, int deleteFiles ); 177 168 178 169 /* update the model with current torrent status */ 179 void 170 void tr_core_update( TrCore * self ); 180 171 181 172 /* emit the "quit" signal */ 182 void tr_core_quit( TrCore * self ); 183 184 /* emit the "blocklist changed" signal */ 185 void tr_core_blocksig( TrCore * core, 186 gboolean isDone, 187 const char * status ); 188 189 /* Set a preference value, save the prefs file, and emit the 190 "prefs-changed" signal */ 191 void tr_core_set_pref( TrCore * self, 192 const char * key, 193 const char * val ); 194 195 /* Set a boolean preference value, save the prefs file, and emit the 196 "prefs-changed" signal */ 197 void tr_core_set_pref_bool( TrCore * self, 198 const char * key, 199 gboolean val ); 200 201 /* Set an integer preference value, save the prefs file, and emit the 202 "prefs-changed" signal */ 203 void tr_core_set_pref_int( TrCore * self, 204 const char * key, 205 int val ); 206 207 /* Set a double preference value, save the prefs file, and emit the 208 "prefs-changed" signal */ 209 void tr_core_set_pref_double( TrCore * self, 210 const char * key, 211 double val ); 173 void tr_core_quit( TrCore * self ); 174 175 /** 176 *** Set a preference value, save the prefs file, and emit the "prefs-changed" signal 177 **/ 178 179 void tr_core_set_pref ( TrCore * self, const char * key, const char * val ); 180 void tr_core_set_pref_bool( TrCore * self, const char * key, gboolean val ); 181 void tr_core_set_pref_int ( TrCore * self, const char * key, int val ); 182 void tr_core_set_pref_double( TrCore * self, const char * key, double val ); 183 184 /** 185 *** 186 **/ 187 188 void tr_core_port_test( TrCore * core ); 189 190 void tr_core_blocklist_update( TrCore * core ); 212 191 213 192 /** -
trunk/gtk/tr-prefs.c
r8173 r8174 14 14 #include <errno.h> 15 15 #include <stdarg.h> 16 #include <limits.h> /* USHRT_MAX */ 16 17 #include <stdlib.h> /* free() */ 17 18 #include <unistd.h> … … 22 23 #include <libtransmission/version.h> 23 24 #include <libtransmission/web.h> 24 #include "blocklist.h"25 25 #include "conf.h" 26 26 #include "hig.h" … … 357 357 struct blocklist_data 358 358 { 359 GtkWidget * check; 360 GtkWidget * dialog; 361 TrCore * core; 362 gulong id; 363 int abortFlag; 364 char secondary[256]; 359 gulong updateBlocklistTag; 360 GtkWidget * updateBlocklistButton; 361 GtkWidget * updateBlocklistDialog; 362 GtkWidget * check; 363 TrCore * core; 365 364 }; 366 365 367 366 static void 368 updateBlocklistText( GtkWidget * w, 369 TrCore * core ) 367 updateBlocklistText( GtkWidget * w, TrCore * core ) 370 368 { 371 369 const int n = tr_blocklistGetRuleCount( tr_core_session( core ) ); 372 370 char buf[512]; 373 374 371 g_snprintf( buf, sizeof( buf ), 375 372 ngettext( "Enable _blocklist (contains %'d rule)", … … 378 375 } 379 376 380 static void 381 onBlocklistDialogResponse( GtkDialog * d, 382 int response UNUSED, 383 gpointer gdata ) 377 /* prefs dialog is being destroyed, so stop listening to blocklist updates */ 378 static void 379 peerPageDestroyed( gpointer gdata, GObject * dead UNUSED ) 384 380 { 385 381 struct blocklist_data * data = gdata; 386 387 g_signal_handler_disconnect( data->core, data->id ); 388 gtk_widget_destroy( GTK_WIDGET( d ) ); 389 } 390 391 static void 392 onBlocklistStatus( TrCore * core UNUSED, 393 gboolean isDone, 394 const char * status, 395 gpointer gdata ) 382 if( data->updateBlocklistTag > 0 ) 383 g_signal_handler_disconnect( data->core, data->updateBlocklistTag ); 384 g_free( data ); 385 } 386 387 /* user hit "close" in the blocklist-update dialog */ 388 static void 389 onBlocklistUpdateResponse( GtkDialog * dialog, gint response UNUSED, gpointer gdata ) 396 390 { 397 391 struct blocklist_data * data = gdata; 398 399 gdk_threads_enter( ); 400 gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( data-> dialog ), 401 "%s", status ); 402 gtk_dialog_set_response_sensitive( GTK_DIALOG( data->dialog ), 403 GTK_RESPONSE_CANCEL, !isDone ); 404 gtk_dialog_set_response_sensitive( GTK_DIALOG( data->dialog ), 405 GTK_RESPONSE_CLOSE, isDone ); 406 if( isDone ) 407 updateBlocklistText( data->check, core ); 408 gdk_threads_leave( ); 409 } 410 411 static void 412 onUpdateBlocklistCB( GtkButton * w, 413 gpointer gdata ) 414 { 415 GtkWidget * d; 392 gtk_widget_destroy( GTK_WIDGET( dialog ) ); 393 gtk_widget_set_sensitive( data->updateBlocklistButton, TRUE ); 394 data->updateBlocklistDialog = NULL; 395 g_signal_handler_disconnect( data->core, data->updateBlocklistTag ); 396 } 397 398 /* core says the blocklist was updated */ 399 static void 400 onBlocklistUpdated( TrCore * core, int n, gpointer gdata ) 401 { 402 const char * s = ngettext( "Blocklist now has %'d rule.", "Blocklist now has %'d rules.", n ); 416 403 struct blocklist_data * data = gdata; 417 418 d = 419 gtk_message_dialog_new( GTK_WINDOW( gtk_widget_get_toplevel( 420 GTK_WIDGET( 421 w ) ) ), 422 GTK_DIALOG_DESTROY_WITH_PARENT, 423 GTK_MESSAGE_INFO, 424 GTK_BUTTONS_NONE, 425 _( "Updating Blocklist" ) ); 426 427 data->dialog = d; 428 data->id = 429 g_signal_connect( data->core, "blocklist-status", G_CALLBACK( 430 onBlocklistStatus ), data ); 431 432 gtk_dialog_add_buttons( GTK_DIALOG( d ), 433 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 434 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, 435 NULL ); 436 gtk_dialog_set_response_sensitive( GTK_DIALOG( 437 d ), GTK_RESPONSE_CLOSE, FALSE ); 438 439 g_signal_connect( d, "response", G_CALLBACK( 440 onBlocklistDialogResponse ), data ); 404 GtkMessageDialog * d = GTK_MESSAGE_DIALOG( data->updateBlocklistDialog ); 405 gtk_widget_set_sensitive( data->updateBlocklistButton, TRUE ); 406 gtk_message_dialog_set_markup( d, _( "<b>Update succeeded!</b>" ) ); 407 gtk_message_dialog_format_secondary_text( d, s, n ); 408 updateBlocklistText( data->check, core ); 409 } 410 411 /* user pushed a button to update the blocklist */ 412 static void 413 onBlocklistUpdate( GtkButton * w, gpointer gdata ) 414 { 415 GtkWidget * d; 416 struct blocklist_data * data = gdata; 417 d = gtk_message_dialog_new( GTK_WINDOW( gtk_widget_get_toplevel( GTK_WIDGET( w ) ) ), 418 GTK_DIALOG_DESTROY_WITH_PARENT, 419 GTK_MESSAGE_INFO, 420 GTK_BUTTONS_CLOSE, 421 _( "Update Blocklist" ) ); 422 gtk_widget_set_sensitive( data->updateBlocklistButton, FALSE ); 423 gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( d ), _( "Getting new blocklist..." ) ); 424 data->updateBlocklistDialog = d; 425 g_signal_connect( d, "response", G_CALLBACK(onBlocklistUpdateResponse), data ); 441 426 gtk_widget_show( d ); 442 443 gtr_blocklist_update( data->core);427 tr_core_blocklist_update( data->core ); 428 data->updateBlocklistTag = g_signal_connect( data->core, "blocklist-updated", G_CALLBACK( onBlocklistUpdated ), data ); 444 429 } 445 430 … … 449 434 { 450 435 const int val = gtk_toggle_button_get_active( w ) 451 ? TR_ENCRYPTION_REQUIRED 452 : TR_ENCRYPTION_PREFERRED; 453 436 ? TR_ENCRYPTION_REQUIRED 437 : TR_ENCRYPTION_PREFERRED; 454 438 tr_core_set_pref_int( TR_CORE( core ), TR_PREFS_KEY_ENCRYPTION, val ); 455 439 } … … 476 460 h = gtk_hbox_new( FALSE, GUI_PAD_BIG ); 477 461 gtk_box_pack_start( GTK_BOX( h ), w, TRUE, TRUE, 0 ); 478 b = gtr_button_new_from_stock( GTK_STOCK_REFRESH, _( "_Update" ) );462 b = data->updateBlocklistButton = gtr_button_new_from_stock( GTK_STOCK_REFRESH, _( "_Update" ) ); 479 463 data->check = w; 480 464 g_object_set_data( G_OBJECT( b ), "session", 481 465 tr_core_session( TR_CORE( core ) ) ); 482 g_signal_connect( b, "clicked", G_CALLBACK( on UpdateBlocklistCB), data );466 g_signal_connect( b, "clicked", G_CALLBACK( onBlocklistUpdate ), data ); 483 467 gtk_box_pack_start( GTK_BOX( h ), b, FALSE, FALSE, 0 ); 484 468 g_signal_connect( w, "toggled", G_CALLBACK( target_cb ), b ); … … 516 500 517 501 hig_workarea_finish( t, &row ); 502 g_object_weak_ref( G_OBJECT( t ), peerPageDestroyed, data ); 518 503 return t; 519 504 } … … 736 721 737 722 /* port */ 738 w = new_spin_button( TR_PREFS_KEY_RPC_PORT, core, 0, 65535, 1 );723 w = new_spin_button( TR_PREFS_KEY_RPC_PORT, core, 0, USHRT_MAX, 1 ); 739 724 page->widgets = g_slist_append( page->widgets, w ); 740 725 w = hig_workarea_add_row( t, &row, _( "Listening _port:" ), w, NULL ); … … 941 926 page->proxy_widgets = g_slist_append( page->proxy_widgets, w ); 942 927 943 w = new_spin_button( TR_PREFS_KEY_PROXY_PORT, core, 0, 65535, 1 );928 w = new_spin_button( TR_PREFS_KEY_PROXY_PORT, core, 0, USHRT_MAX, 1 ); 944 929 page->proxy_widgets = g_slist_append( page->proxy_widgets, w ); 945 930 w = hig_workarea_add_row( t, &row, _( "Proxy _port:" ), w, NULL ); … … 1231 1216 ****/ 1232 1217 1233 struct test_port_data 1234 { 1235 GtkWidget * label; 1236 gboolean * alive; 1237 char text[128]; 1218 struct network_page_data 1219 { 1220 TrCore * core; 1221 GtkWidget * portLabel; 1222 GtkWidget * portButton; 1223 GtkWidget * portSpin; 1224 gulong portTag; 1225 gulong prefsTag; 1238 1226 }; 1239 1227 1240 /* this is invoked in the gtk main loop's thread */ 1241 static gboolean 1242 testing_port_done_idle( gpointer gdata ) 1243 { 1244 struct test_port_data * data = gdata; 1245 1246 if( *data->alive ) 1247 { 1248 gdk_threads_enter( ); 1249 gtk_label_set_markup( GTK_LABEL( data->label ), data->text ); 1250 gdk_threads_leave( ); 1251 } 1252 1253 return FALSE; 1254 } 1255 1256 /* this is invoked in the libtransmission thread */ 1257 static void 1258 testing_port_done( tr_session * session UNUSED, 1259 long response_code UNUSED, 1260 const void * response, 1261 size_t response_len, 1262 void * gdata ) 1263 { 1264 struct test_port_data * data = gdata; 1265 1266 if( *data->alive ) 1267 { 1268 const int isOpen = response_len && *(char*)response == '1'; 1269 g_snprintf( data->text, sizeof( data->text ), isOpen 1270 ? _( "Port is <b>open</b>" ) 1271 : _( "Port is <b>closed</b>" ) ); 1272 g_idle_add( testing_port_done_idle, data ); 1273 } 1274 } 1275 1276 static gboolean 1277 testing_port_begin( gpointer gdata ) 1278 { 1279 struct test_port_data * data = gdata; 1280 1281 if( *data->alive ) 1282 { 1283 char url[256]; 1284 GObject * o = G_OBJECT( data->label ); 1285 GtkSpinButton * spin = g_object_get_data( o, "tr-port-spin" ); 1286 tr_session * session = g_object_get_data( o, "session" ); 1287 const int port = gtk_spin_button_get_value_as_int( spin ); 1288 g_snprintf( url, sizeof( url ), 1289 "http://portcheck.transmissionbt.com/%d", 1290 port ); 1291 tr_webRun( session, url, NULL, testing_port_done, data ); 1292 } 1293 return FALSE; 1294 } 1295 1296 struct network_page_data 1297 { 1298 gboolean * alive; 1299 GtkWidget * label; 1300 guint id; 1301 TrCore * core; 1302 }; 1303 1304 static void 1305 onCorePrefsChanged( TrCore * core UNUSED, 1306 const char * key, 1307 gpointer gdata ) 1228 static void 1229 onCorePrefsChanged( TrCore * core UNUSED, const char * key, gpointer gdata ) 1308 1230 { 1309 1231 if( !strcmp( key, TR_PREFS_KEY_PEER_PORT ) ) 1310 1232 { 1311 struct network_page_data * ndata = gdata; 1312 struct test_port_data * data; 1313 1314 gtk_label_set_markup( GTK_LABEL( ndata->label ), 1315 _( "<i>Testing port...</i>" ) ); 1316 1317 /* wait three seconds to give the port forwarding time to kick in */ 1318 data = g_new0( struct test_port_data, 1 ); 1319 data->label = ndata->label; 1320 data->alive = ndata->alive; 1321 gtr_timeout_add_seconds( 3, testing_port_begin, data ); 1233 struct network_page_data * data = gdata; 1234 gtk_label_set_text( GTK_LABEL( data->portLabel ), _( "Status unknown" ) ); 1235 gtk_widget_set_sensitive( data->portButton, TRUE ); 1236 gtk_widget_set_sensitive( data->portSpin, TRUE ); 1322 1237 } 1323 1238 } 1324 1239 1325 1240 static void 1326 networkPageDestroyed( gpointer gdata, 1327 GObject * dead UNUSED ) 1241 networkPageDestroyed( gpointer gdata, GObject * dead UNUSED ) 1328 1242 { 1329 1243 struct network_page_data * data = gdata; 1330 1331 *data->alive = FALSE; 1332 g_signal_handler_disconnect( data->core, data->id ); 1244 if( data->prefsTag > 0 ) 1245 g_signal_handler_disconnect( data->core, data->prefsTag ); 1246 if( data->portTag > 0 ) 1247 g_signal_handler_disconnect( data->core, data->portTag ); 1333 1248 g_free( data ); 1249 } 1250 1251 static void 1252 onPortTested( TrCore * core UNUSED, gboolean isOpen, gpointer vdata ) 1253 { 1254 struct network_page_data * data = vdata; 1255 const char * markup = isOpen ? _( "Port is <b>open</b>" ) : _( "Port is <b>closed</b>" ); 1256 gtk_label_set_markup( GTK_LABEL( data->portLabel ), markup ); 1257 gtk_widget_set_sensitive( data->portButton, TRUE ); 1258 gtk_widget_set_sensitive( data->portSpin, TRUE ); 1259 } 1260 1261 static void 1262 onPortTest( GtkButton * button UNUSED, gpointer vdata ) 1263 { 1264 struct network_page_data * data = vdata; 1265 gtk_widget_set_sensitive( data->portButton, FALSE ); 1266 gtk_widget_set_sensitive( data->portSpin, FALSE ); 1267 gtk_label_set_markup( GTK_LABEL( data->portLabel ), _( "<i>Testing...</i>" ) ); 1268 data->portTag = g_signal_connect( data->core, "port-tested", G_CALLBACK(onPortTested), data ); 1269 tr_core_port_test( data->core ); 1334 1270 } 1335 1271 … … 1341 1277 GtkWidget * t; 1342 1278 GtkWidget * w; 1343 GtkWidget * w2;1344 1279 GtkWidget * h; 1345 1280 GtkWidget * l; 1346 1281 struct network_page_data * data; 1347 1282 1348 /* register to stop listening to core prefs changes when the page is 1349 destroyed */ 1283 /* register to stop listening to core prefs changes when the page is destroyed */ 1350 1284 data = g_new0( struct network_page_data, 1 ); 1351 1285 data->core = TR_CORE( core ); 1352 1353 /* we leak this gboolean* s.t. we know it will still be alive when the port1354 check is done, whether the dialog was destroyed or not. kind of1355 clumsy... */1356 data->alive = g_new( gboolean, 1 );1357 *data->alive = TRUE;1358 1286 1359 1287 /* build the page */ … … 1361 1289 hig_workarea_add_section_title( t, &row, _( "Incoming Peers" ) ); 1362 1290 1291 s = _( "_Port for incoming connections:" ); 1292 w = data->portSpin = new_spin_button( TR_PREFS_KEY_PEER_PORT, core, 1, USHRT_MAX, 1 ); 1293 hig_workarea_add_row( t, &row, s, w, NULL ); 1294 1363 1295 h = gtk_hbox_new( FALSE, GUI_PAD_BIG ); 1364 w2 = new_spin_button( TR_PREFS_KEY_PEER_PORT, core, 1, 65535, 1 ); 1365 gtk_box_pack_start( GTK_BOX( h ), w2, FALSE, FALSE, 0 ); 1366 data->label = l = gtk_label_new( NULL ); 1296 l = data->portLabel = gtk_label_new( _( "Status unknown" ) ); 1367 1297 gtk_misc_set_alignment( GTK_MISC( l ), 0.0f, 0.5f ); 1368 gtk_box_pack_start( GTK_BOX( h ), l, FALSE, FALSE, 0 ); 1369 hig_workarea_add_row( t, &row, _( "Listening _port:" ), h, w2 ); 1370 1371 g_object_set_data( G_OBJECT( l ), "tr-port-spin", w2 ); 1372 g_object_set_data( G_OBJECT( l ), "session", 1373 tr_core_session( TR_CORE( core ) ) ); 1374 data->id = g_signal_connect( TR_CORE( core ), "prefs-changed", 1375 G_CALLBACK( onCorePrefsChanged ), data ); 1376 onCorePrefsChanged( NULL, TR_PREFS_KEY_PEER_PORT, data ); 1298 gtk_box_pack_start_defaults( GTK_BOX( h ), l ); 1299 w = data->portButton = gtk_button_new_with_mnemonic( _( "_Test Port" ) ); 1300 gtk_box_pack_end( GTK_BOX( h ), w, FALSE, FALSE, 0 ); 1301 g_signal_connect( w, "clicked", G_CALLBACK(onPortTest), data ); 1302 hig_workarea_add_row( t, &row, NULL, h, NULL ); 1303 data->prefsTag = g_signal_connect( TR_CORE( core ), "prefs-changed", G_CALLBACK( onCorePrefsChanged ), data ); 1304 g_object_weak_ref( G_OBJECT( t ), networkPageDestroyed, data ); 1377 1305 1378 1306 s = _( "Randomize the port every launch" ); … … 1385 1313 1386 1314 hig_workarea_finish( t, &row ); 1387 g_object_weak_ref( G_OBJECT( t ), networkPageDestroyed, data );1388 1389 1315 return t; 1390 1316 } … … 1422 1348 gtk_label_new ( _( "Peers" ) ) ); 1423 1349 gtk_notebook_append_page( GTK_NOTEBOOK( n ), 1350 bandwidthPage( core ), 1351 gtk_label_new ( _( "Speed" ) ) ); 1352 gtk_notebook_append_page( GTK_NOTEBOOK( n ), 1424 1353 networkPage( core ), 1425 1354 gtk_label_new ( _( "Network" ) ) ); 1426 gtk_notebook_append_page( GTK_NOTEBOOK( n ),1427 bandwidthPage( core ),1428 gtk_label_new ( _( "Speed" ) ) );1429 1355 gtk_notebook_append_page( GTK_NOTEBOOK( n ), 1430 1356 desktopPage( core ),
Note: See TracChangeset
for help on using the changeset viewer.