/* * This file Copyright (C) Mnemosyne LLC * * 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: relocate.c 13188 2012-02-03 15:51:36Z jordan $ */ #include #include #include #include "conf.h" /* gtr_pref_string_get */ #include "hig.h" #include "relocate.h" #include "util.h" #define DATA_KEY "gtr-relocate-data" static char * previousLocation = NULL; struct relocate_dialog_data { int done; bool do_move; TrCore * core; GSList * torrent_ids; GtkWidget * message_dialog; GtkWidget * chooser_dialog; }; static void data_free( gpointer gdata ) { struct relocate_dialog_data * data = gdata; g_slist_free( data->torrent_ids ); g_free( data ); } /*** **** ***/ static void startMovingNextTorrent( struct relocate_dialog_data * data ) { char * str; const int id = GPOINTER_TO_INT( data->torrent_ids->data ); tr_torrent * tor = gtr_core_find_torrent( data->core, id ); if( tor != NULL ) tr_torrentSetLocation( tor, previousLocation, data->do_move, NULL, &data->done ); data->torrent_ids = g_slist_delete_link( data->torrent_ids, data->torrent_ids ); str = g_strdup_printf( _( "Moving \"%s\"" ), tr_torrentName( tor ) ); gtk_message_dialog_set_markup( GTK_MESSAGE_DIALOG( data->message_dialog ), str ); g_free( str ); } /* every once in awhile, check to see if the move is done. * if so, delete the dialog */ static gboolean onTimer( gpointer gdata ) { struct relocate_dialog_data * data = gdata; const int done = data->done; if( done == TR_LOC_ERROR ) { const int flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT; GtkWidget * w = gtk_message_dialog_new( GTK_WINDOW( data->message_dialog ), flags, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", _( "Couldn't move torrent" ) ); gtk_dialog_run( GTK_DIALOG( w ) ); gtk_widget_destroy( GTK_WIDGET( data->message_dialog ) ); return FALSE; } else if( done == TR_LOC_DONE ) { if( data->torrent_ids != NULL ) { startMovingNextTorrent( data ); } else { gtk_widget_destroy( GTK_WIDGET( data->chooser_dialog ) ); return FALSE; } } return TRUE; /* keep looping */ } static void onResponse( GtkDialog * dialog, int response, gpointer unused UNUSED ) { if( response == GTK_RESPONSE_APPLY ) { GtkWidget * w; GObject * d = G_OBJECT( dialog ); struct relocate_dialog_data * data = g_object_get_data( d, DATA_KEY ); GtkFileChooser * chooser = g_object_get_data( d, "chooser" ); GtkToggleButton * move_tb = g_object_get_data( d, "move_rb" ); char * location = gtk_file_chooser_get_filename( chooser ); data->do_move = gtk_toggle_button_get_active( move_tb ); /* pop up a dialog saying that the work is in progress */ w = gtk_message_dialog_new( GTK_WINDOW( dialog ), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, NULL ); gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( w ), _( "This may take a moment…" ) ); gtk_dialog_set_response_sensitive( GTK_DIALOG( w ), GTK_RESPONSE_CLOSE, FALSE ); gtk_widget_show( w ); /* remember this location so that it can be the default next time */ g_free( previousLocation ); previousLocation = location; /* start the move and periodically check its status */ data->message_dialog = w; data->done = TR_LOC_DONE; onTimer( data ); gdk_threads_add_timeout_seconds( 1, onTimer, data ); } else { gtk_widget_destroy( GTK_WIDGET( dialog ) ); } } GtkWidget* gtr_relocate_dialog_new( GtkWindow * parent, TrCore * core, GSList * torrent_ids ) { guint row; GtkWidget * w; GtkWidget * d; GtkWidget * t; struct relocate_dialog_data * data; d = gtk_dialog_new_with_buttons( _( "Set Torrent Location" ), parent, GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, NULL ); gtk_dialog_set_default_response( GTK_DIALOG( d ), GTK_RESPONSE_CANCEL ); gtk_dialog_set_alternative_button_order( GTK_DIALOG( d ), GTK_RESPONSE_APPLY, GTK_RESPONSE_CANCEL, -1 ); g_signal_connect( d, "response", G_CALLBACK( onResponse ), NULL ); row = 0; t = hig_workarea_create( ); hig_workarea_add_section_title( t, &row, _( "Location" ) ); if( previousLocation == NULL ) previousLocation = g_strdup( gtr_pref_string_get( TR_PREFS_KEY_DOWNLOAD_DIR ) ); w = gtk_file_chooser_button_new( _( "Set Torrent Location" ), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ); gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER( w ), previousLocation ); g_object_set_data( G_OBJECT( d ), "chooser", w ); hig_workarea_add_row( t, &row, _( "Torrent _location:" ), w, NULL ); w = gtk_radio_button_new_with_mnemonic( NULL, _( "_Move from the current folder" ) ); g_object_set_data( G_OBJECT( d ), "move_rb", w ); hig_workarea_add_wide_control( t, &row, w ); w = gtk_radio_button_new_with_mnemonic_from_widget( GTK_RADIO_BUTTON( w ), _( "Local data is _already there" ) ); hig_workarea_add_wide_control( t, &row, w ); hig_workarea_finish( t, &row ); gtr_dialog_set_content( GTK_DIALOG( d ), t ); data = g_new0( struct relocate_dialog_data, 1 ); data->core = core; data->torrent_ids = torrent_ids; data->chooser_dialog = d; g_object_set_data_full( G_OBJECT( d ), DATA_KEY, data, data_free ); return d; }