Changeset 11673


Ignore:
Timestamp:
Jan 14, 2011, 9:57:20 PM (11 years ago)
Author:
jordan
Message:

(trunk libT) #3898 "Add 'Add' and 'Remove' buttons to the tracker list" -- done.

Location:
trunk/gtk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/add-dialog.c

    r11599 r11673  
    492492}
    493493
    494 static void
    495 paste_clipboard_url_into_entry( GtkWidget * e )
    496 {
    497   size_t i;
    498 
    499   char * text[] = {
    500     gtk_clipboard_wait_for_text( gtk_clipboard_get( GDK_SELECTION_PRIMARY ) ),
    501     gtk_clipboard_wait_for_text( gtk_clipboard_get( GDK_SELECTION_CLIPBOARD ) )
    502   };
    503 
    504   for( i=0; i<G_N_ELEMENTS(text); ++i ) {
    505       char * s = text[i];
    506       if( s && ( gtr_is_supported_url( s ) || gtr_is_magnet_link( s ) ) ) {
    507           gtk_entry_set_text( GTK_ENTRY( e ), s );
    508           break;
    509       }
    510   }
    511 
    512   for( i=0; i<G_N_ELEMENTS(text); ++i )
    513     g_free( text[i] );
    514 }
    515 
    516494GtkWidget*
    517495gtr_torrent_add_from_url_dialog_new( GtkWindow * parent, TrCore * core )
     
    538516    e = gtk_entry_new( );
    539517    gtk_widget_set_size_request( e, 400, -1 );
    540     paste_clipboard_url_into_entry( e );
     518    gtr_paste_clipboard_url_into_entry( e );
    541519    g_object_set_data( G_OBJECT( w ), "url-entry", e );
    542520    hig_workarea_add_row( t, &row, _( "_URL" ), e, NULL );
  • trunk/gtk/details.c

    r11599 r11673  
    8585    GtkWidget * more_peer_details_check;
    8686
    87     GtkListStore * trackers;
    88     GtkTreeModel * trackers_filtered;
    89     GtkWidget * edit_trackers_button;
    90     GtkWidget * tracker_view;
    91     GtkWidget * scrape_check;
    92     GtkWidget * all_check;
    93     GtkTextBuffer * tracker_buffer;
     87    GtkListStore  * tracker_store;
     88    GHashTable    * tracker_hash;
     89    GtkTreeModel  * trackers_filtered;
     90    GtkWidget     * add_tracker_button;
     91    GtkWidget     * edit_trackers_button;
     92    GtkWidget     * remove_tracker_button;
     93    GtkWidget     * tracker_view;
     94    GtkWidget     * scrape_check;
     95    GtkWidget     * all_check;
    9496
    9597    GtkWidget * file_list;
     
    17631765
    17641766/****
     1767*****
    17651768*****  TRACKER
     1769*****
    17661770****/
    17671771
     
    18851889{
    18861890  TRACKER_COL_TORRENT_ID,
    1887   TRACKER_COL_TRACKER_INDEX,
    18881891  TRACKER_COL_TEXT,
    1889   TRACKER_COL_BACKUP,
    1890   TRACKER_COL_TORRENT_NAME,
    1891   TRACKER_COL_TRACKER_NAME,
     1892  TRACKER_COL_IS_BACKUP,
     1893  TRACKER_COL_TRACKER_ID,
    18921894  TRACKER_COL_FAVICON,
     1895  TRACKER_COL_WAS_UPDATED,
     1896  TRACKER_COL_KEY,
    18931897  TRACKER_N_COLS
    18941898};
     
    19051909
    19061910     /* don't show the backups... */
    1907      gtk_tree_model_get( model, iter, TRACKER_COL_BACKUP, &isBackup, -1 );
     1911     gtk_tree_model_get( model, iter, TRACKER_COL_IS_BACKUP, &isBackup, -1 );
    19081912     return !isBackup;
    19091913}
    19101914
    1911 static void
    1912 populate_tracker_buffer( GtkTextBuffer * buffer, const tr_torrent * tor )
     1915static int
     1916tracker_list_get_current_torrent_id( struct DetailsImpl * di )
     1917{
     1918    int torrent_id = -1;
     1919
     1920    /* if there's only one torrent in the dialog, always use it */
     1921    if( torrent_id < 0 )
     1922        if( g_slist_length( di->ids ) == 1 )
     1923            torrent_id = GPOINTER_TO_INT( di->ids->data );
     1924
     1925    /* otherwise, use the selected tracker's torrent */
     1926    if( torrent_id < 0 ) {
     1927        GtkTreeIter iter;
     1928        GtkTreeModel * model;
     1929        GtkTreeSelection * sel = gtk_tree_view_get_selection( GTK_TREE_VIEW( di->tracker_view ) );
     1930        if( gtk_tree_selection_get_selected( sel, &model, &iter ) )
     1931            gtk_tree_model_get( model, &iter, TRACKER_COL_TORRENT_ID, &torrent_id, -1 );
     1932    }
     1933
     1934    return torrent_id;
     1935}
     1936
     1937static tr_torrent*
     1938tracker_list_get_current_torrent( struct DetailsImpl * di )
     1939{
     1940    const int torrent_id = tracker_list_get_current_torrent_id( di );
     1941    tr_session * session = tr_core_session( di->core );
     1942    return tr_torrentFindFromId( session, torrent_id );
     1943}
     1944
     1945static void
     1946favicon_ready_cb( gpointer pixbuf, gpointer vreference )
     1947{
     1948    GtkTreeIter iter;
     1949    GtkTreeRowReference * reference = vreference;
     1950
     1951    if( pixbuf != NULL )
     1952    {
     1953        GtkTreePath * path = gtk_tree_row_reference_get_path( reference );
     1954        GtkTreeModel * model = gtk_tree_row_reference_get_model( reference );
     1955
     1956        if( gtk_tree_model_get_iter( model, &iter, path ) )
     1957            gtk_list_store_set( GTK_LIST_STORE( model ), &iter,
     1958                                TRACKER_COL_FAVICON, pixbuf,
     1959                                -1 );
     1960
     1961        gtk_tree_path_free( path );
     1962
     1963        g_object_unref( pixbuf );
     1964    }
     1965
     1966    gtk_tree_row_reference_free( reference );
     1967}
     1968
     1969static void
     1970refreshTracker( struct DetailsImpl * di, tr_torrent ** torrents, int n )
     1971{
     1972    int i;
     1973    int * statCount;
     1974    tr_tracker_stat ** stats;
     1975    GtkTreeIter iter;
     1976    GtkTreeModel * model;
     1977    GHashTable * hash = di->tracker_hash;
     1978    GtkListStore * store = di->tracker_store;
     1979    tr_session * session = tr_core_session( di->core );
     1980    const gboolean showScrape = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( di->scrape_check ) );
     1981
     1982    /* step 1: get all the trackers */
     1983    statCount = g_new0( int, n );
     1984    stats = g_new0( tr_tracker_stat *, n );
     1985    for( i=0; i<n; ++i )
     1986        stats[i] = tr_torrentTrackers( torrents[i], &statCount[i] );
     1987
     1988    /* step 2: mark all the trackers in the list as not-updated */
     1989    model = GTK_TREE_MODEL( store );
     1990    if( gtk_tree_model_get_iter_first( model, &iter ) ) do
     1991        gtk_list_store_set( store, &iter, TRACKER_COL_WAS_UPDATED, FALSE, -1 );
     1992    while( gtk_tree_model_iter_next( model, &iter ) );
     1993
     1994    /* step 3: add any new trackers */
     1995    for( i=0; i<n; ++i ) {
     1996        int j;
     1997        const int jn = statCount[i];
     1998        for( j=0; j<jn; ++j ) {
     1999            const tr_torrent * tor = torrents[i];
     2000            const tr_tracker_stat * st = &stats[i][j];
     2001            const int torrent_id = tr_torrentId( tor );
     2002            char * key = g_strdup_printf( "%d\t%d\t%s", torrent_id, st->tier, st->announce );
     2003
     2004            if( g_hash_table_lookup( hash, key ) == NULL ) {
     2005                GtkTreePath * p;
     2006                GtkTreeIter iter;
     2007                GtkTreeRowReference * ref;
     2008
     2009                gtk_list_store_insert_with_values( store, &iter, -1,
     2010                    TRACKER_COL_TORRENT_ID, torrent_id,
     2011                    TRACKER_COL_TRACKER_ID, st->id,
     2012                    TRACKER_COL_KEY, key,
     2013                    -1 );
     2014
     2015                p = gtk_tree_model_get_path( model, &iter );
     2016                ref = gtk_tree_row_reference_new( model, p );
     2017                g_hash_table_insert( hash, g_strdup( key ), ref );
     2018                ref = gtk_tree_row_reference_new( model, p );
     2019                gtr_get_favicon_from_url( session, st->announce, favicon_ready_cb, ref );
     2020                gtk_tree_path_free( p );
     2021            }
     2022
     2023            g_free( key );
     2024        }
     2025    }
     2026
     2027    /* step 4: update the peers */
     2028    for( i=0; i<n; ++i ) {
     2029        int j;
     2030        const tr_torrent * tor = torrents[i];
     2031        const char * summary_name = n>1 ? tr_torrentInfo( tor )->name : NULL;
     2032        for( j=0; j<statCount[i]; ++j ) {
     2033            const tr_tracker_stat * st = &stats[i][j];
     2034            char * summary = buildTrackerSummary( summary_name, st, showScrape );
     2035            char * key = g_strdup_printf( "%d\t%d\t%s", tr_torrentId( tor ), st->tier, st->announce );
     2036            GtkTreeRowReference * ref = g_hash_table_lookup( hash, key );
     2037            GtkTreePath * p = gtk_tree_row_reference_get_path( ref );
     2038            gtk_tree_model_get_iter( model, &iter, p );
     2039            gtk_list_store_set( store, &iter, TRACKER_COL_TEXT, summary,
     2040                                              TRACKER_COL_IS_BACKUP, st->isBackup,
     2041                                              TRACKER_COL_TRACKER_ID, st->id,
     2042                                              TRACKER_COL_WAS_UPDATED, TRUE,
     2043                                              -1 );
     2044            gtk_tree_path_free( p );
     2045            g_free( key );
     2046            g_free( summary );
     2047        }
     2048    }
     2049
     2050    /* step 5: remove trackers that have disappeared */
     2051    if( gtk_tree_model_get_iter_first( model, &iter ) ) {
     2052        gboolean more = TRUE;
     2053        while( more ) {
     2054            gboolean b;
     2055            gtk_tree_model_get( model, &iter, TRACKER_COL_WAS_UPDATED, &b, -1 );
     2056            if( b )
     2057                more = gtk_tree_model_iter_next( model, &iter );
     2058            else {
     2059                char * key;
     2060                gtk_tree_model_get( model, &iter, TRACKER_COL_KEY, &key, -1 );
     2061                g_hash_table_remove( hash, key );
     2062                more = gtk_list_store_remove( store, &iter );
     2063                g_free( key );
     2064            }
     2065        }
     2066    }
     2067
     2068    gtk_widget_set_sensitive( di->edit_trackers_button,
     2069                              tracker_list_get_current_torrent_id( di ) >= 0 );
     2070
     2071    /* cleanup */
     2072    for( i=0; i<n; ++i )
     2073        tr_torrentTrackersFree( stats[i], statCount[i] );
     2074    g_free( stats );
     2075    g_free( statCount );
     2076}
     2077
     2078static void
     2079onScrapeToggled( GtkToggleButton * button, struct DetailsImpl * di )
     2080{
     2081    const char * key = PREF_KEY_SHOW_MORE_TRACKER_INFO;
     2082    const gboolean value = gtk_toggle_button_get_active( button );
     2083    tr_core_set_pref_bool( di->core, key, value );
     2084    refresh( di );
     2085}
     2086
     2087static void
     2088onBackupToggled( GtkToggleButton * button, struct DetailsImpl * di )
     2089{
     2090    const char * key = PREF_KEY_SHOW_BACKUP_TRACKERS;
     2091    const gboolean value = gtk_toggle_button_get_active( button );
     2092    tr_core_set_pref_bool( di->core, key, value );
     2093    refresh( di );
     2094}
     2095
     2096static void
     2097on_edit_trackers_response( GtkDialog * dialog, int response, gpointer data )
     2098{
     2099    gboolean do_destroy = TRUE;
     2100    struct DetailsImpl * di = data;
     2101
     2102    if( response == GTK_RESPONSE_ACCEPT )
     2103    {
     2104        int i, n;
     2105        int tier;
     2106        GtkTextIter start, end;
     2107        const int torrent_id = GPOINTER_TO_INT( g_object_get_data( G_OBJECT( dialog ), "torrent-id" ) );
     2108        GtkTextBuffer * text_buffer = g_object_get_data( G_OBJECT( dialog ), "text-buffer" );
     2109        tr_session * session = tr_core_session( di->core );
     2110        tr_torrent * tor = tr_torrentFindFromId( session, torrent_id );
     2111
     2112        if( tor != NULL )
     2113        {
     2114            tr_tracker_info * trackers;
     2115            char ** tracker_strings;
     2116            char * tracker_text;
     2117
     2118            /* build the array of trackers */
     2119            gtk_text_buffer_get_bounds( text_buffer, &start, &end );
     2120            tracker_text = gtk_text_buffer_get_text( text_buffer, &start, &end, FALSE );
     2121            tracker_strings = g_strsplit( tracker_text, "\n", 0 );
     2122            for( i=0; tracker_strings[i]; )
     2123                ++i;
     2124            trackers = g_new0( tr_tracker_info, i );
     2125            for( i=n=tier=0; tracker_strings[i]; ++i ) {
     2126                const char * str = tracker_strings[i];
     2127                if( !*str )
     2128                    ++tier;
     2129                else {
     2130                    trackers[n].tier = tier;
     2131                    trackers[n].announce = tracker_strings[i];
     2132                    ++n;
     2133                }
     2134            }
     2135
     2136            /* update the torrent */
     2137            if( tr_torrentSetAnnounceList( tor, trackers, n ) )
     2138                refresh( di );
     2139            else {
     2140                GtkWidget * w;
     2141                const char * text = _( "List contains invalid URLs" );
     2142                w = gtk_message_dialog_new( GTK_WINDOW( dialog ),
     2143                                            GTK_DIALOG_MODAL,
     2144                                            GTK_MESSAGE_ERROR,
     2145                                            GTK_BUTTONS_CLOSE, "%s", text );
     2146                gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( w ), "%s", _( "Please correct the errors and try again." ) );
     2147                gtk_dialog_run( GTK_DIALOG( w ) );
     2148                gtk_widget_destroy( w );
     2149                do_destroy = FALSE;
     2150            }
     2151
     2152            /* cleanup */
     2153            g_free( trackers );
     2154            g_strfreev( tracker_strings );
     2155            g_free( tracker_text );
     2156        }
     2157    }
     2158
     2159    if( do_destroy )
     2160        gtk_widget_destroy( GTK_WIDGET( dialog ) );
     2161}
     2162
     2163static char*
     2164get_editable_tracker_list( const tr_torrent * tor )
    19132165{
    19142166    int i;
     
    19262178    if( gstr->len > 0 )
    19272179        g_string_truncate( gstr, gstr->len-1 );
    1928     gtk_text_buffer_set_text( buffer, gstr->str, -1 );
    1929     g_string_free( gstr, TRUE );
    1930 }
    1931 
    1932 #define TORRENT_PTR_KEY "torrent-pointer"
    1933 
    1934 static void
    1935 favicon_ready_cb( gpointer pixbuf, gpointer vreference )
    1936 {
    1937     GtkTreeIter iter;
    1938     GtkTreeRowReference * reference = vreference;
    1939 
    1940     if( pixbuf != NULL )
     2180    return g_string_free( gstr, FALSE );
     2181}
     2182
     2183static void
     2184on_edit_trackers( GtkButton * button, gpointer data )
     2185{
     2186    struct DetailsImpl * di = data;
     2187    tr_torrent * tor = tracker_list_get_current_torrent( di );
     2188
     2189    if( tor != NULL )
    19412190    {
    1942         GtkTreePath * path = gtk_tree_row_reference_get_path( reference );
    1943         GtkTreeModel * model = gtk_tree_row_reference_get_model( reference );
    1944 
    1945         if( gtk_tree_model_get_iter( model, &iter, path ) )
    1946             gtk_list_store_set( GTK_LIST_STORE( model ), &iter,
    1947                                 TRACKER_COL_FAVICON, pixbuf,
    1948                                 -1 );
    1949 
    1950         gtk_tree_path_free( path );
    1951 
    1952         g_object_unref( pixbuf );
    1953     }
    1954 
    1955     gtk_tree_row_reference_free( reference );
    1956 }
    1957 
    1958 static void
    1959 refreshTracker( struct DetailsImpl * di, tr_torrent ** torrents, int n )
    1960 {
    1961     int i;
    1962     int * statCount;
    1963     tr_tracker_stat ** stats;
    1964     GtkTreeIter iter;
    1965     GtkListStore * store = di->trackers;
    1966     GtkTreeModel * model;
    1967     const gboolean showScrape = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( di->scrape_check ) );
    1968 
    1969     statCount = g_new0( int, n );
    1970     stats = g_new0( tr_tracker_stat *, n );
    1971     for( i=0; i<n; ++i )
    1972         stats[i] = tr_torrentTrackers( torrents[i], &statCount[i] );
    1973 
    1974     /* "edit trackers" button */
    1975     gtk_widget_set_sensitive( di->edit_trackers_button, n==1 );
    1976     if( n==1 )
    1977         g_object_set_data( G_OBJECT( di->edit_trackers_button ), TORRENT_PTR_KEY, torrents[0] );
    1978 
    1979     /* build the store if we don't already have it */
    1980     if( store == NULL )
    1981     {
    1982         GtkTreeModel * filter;
    1983 
    1984         store = gtk_list_store_new( TRACKER_N_COLS, G_TYPE_INT,
    1985                                                     G_TYPE_INT,
    1986                                                     G_TYPE_STRING,
    1987                                                     G_TYPE_BOOLEAN,
    1988                                                     G_TYPE_STRING,
    1989                                                     G_TYPE_STRING,
    1990                                                     GDK_TYPE_PIXBUF );
    1991 
    1992         filter = gtk_tree_model_filter_new( GTK_TREE_MODEL( store ), NULL );
    1993         gtk_tree_model_filter_set_visible_func( GTK_TREE_MODEL_FILTER( filter ),
    1994                                                 trackerVisibleFunc, di, NULL );
    1995 
    1996         di->trackers = store;
    1997         di->trackers_filtered = filter;
    1998 
    1999         gtk_tree_view_set_model( GTK_TREE_VIEW( di->tracker_view ), filter );
    2000 
    2001         g_object_unref( filter );
    2002         g_object_unref( store );
    2003     }
    2004 
    2005     if( ( di->tracker_buffer == NULL ) && ( n == 1 ) )
    2006     {
    2007         di->tracker_buffer = gtk_text_buffer_new( NULL );
    2008         populate_tracker_buffer( di->tracker_buffer, torrents[0] );
    2009     }
    2010 
    2011     /* add any missing rows (FIXME: doesn't handle edited trackers) */
    2012     model = GTK_TREE_MODEL( store );
    2013     if( n && !gtk_tree_model_get_iter_first( model, &iter ) )
    2014     {
    2015         tr_session * session = tr_core_session( di->core );
    2016 
    2017         for( i=0; i<n; ++i )
    2018         {
    2019             int j;
    2020             const tr_torrent * tor = torrents[i];
    2021             const int torrentId = tr_torrentId( tor );
    2022             const tr_info * inf = tr_torrentInfo( tor );
    2023 
    2024             for( j=0; j<statCount[i]; ++j )
    2025             {
    2026                 GtkTreePath * path;
    2027                 GtkTreeRowReference * reference;
    2028                 const tr_tracker_stat * st = &stats[i][j];
    2029 
    2030                 gtk_list_store_insert_with_values( store, &iter, -1,
    2031                     TRACKER_COL_TORRENT_ID, torrentId,
    2032                     TRACKER_COL_TRACKER_INDEX, j,
    2033                     TRACKER_COL_TORRENT_NAME, inf->name,
    2034                     TRACKER_COL_TRACKER_NAME, st->host,
    2035                     -1 );
    2036 
    2037                 path = gtk_tree_model_get_path( model, &iter );
    2038                 reference = gtk_tree_row_reference_new( model, path );
    2039                 gtr_get_favicon_from_url( session, st->announce, favicon_ready_cb, reference );
    2040                 gtk_tree_path_free( path );
    2041             }
    2042         }
    2043     }
    2044 
    2045     /* update the store */
    2046     if( gtk_tree_model_get_iter_first( model, &iter ) ) do
    2047     {
    2048         int torrentId;
    2049         int trackerIndex;
    2050 
    2051         gtk_tree_model_get( model, &iter, TRACKER_COL_TORRENT_ID, &torrentId,
    2052                                           TRACKER_COL_TRACKER_INDEX, &trackerIndex,
    2053                                           -1 );
    2054 
    2055         for( i=0; i<n; ++i )
    2056             if( tr_torrentId( torrents[i] ) == torrentId )
    2057                 break;
    2058 
    2059         if( i<n && trackerIndex<statCount[i] )
    2060         {
    2061             const tr_tracker_stat * st = &stats[i][trackerIndex];
    2062             const char * key = n>1 ? tr_torrentInfo( torrents[i] )->name : NULL;
    2063             char * text = buildTrackerSummary( key, st, showScrape );
    2064             gtk_list_store_set( store, &iter, TRACKER_COL_TEXT, text,
    2065                                               TRACKER_COL_BACKUP, st->isBackup,
    2066                                               -1 );
    2067             g_free( text );
    2068         }
    2069     }
    2070     while( gtk_tree_model_iter_next( model, &iter ) );
    2071 
    2072     /* cleanup */
    2073     for( i=0; i<n; ++i )
    2074         tr_torrentTrackersFree( stats[i], statCount[i] );
    2075     g_free( stats );
    2076     g_free( statCount );
    2077 }
    2078 
    2079 static void
    2080 onScrapeToggled( GtkToggleButton * button, struct DetailsImpl * di )
    2081 {
    2082     const char * key = PREF_KEY_SHOW_MORE_TRACKER_INFO;
    2083     const gboolean value = gtk_toggle_button_get_active( button );
    2084     tr_core_set_pref_bool( di->core, key, value );
    2085     refresh( di );
    2086 }
    2087 
    2088 static void
    2089 onBackupToggled( GtkToggleButton * button, struct DetailsImpl * di )
    2090 {
    2091     const char * key = PREF_KEY_SHOW_BACKUP_TRACKERS;
    2092     const gboolean value = gtk_toggle_button_get_active( button );
    2093     tr_core_set_pref_bool( di->core, key, value );
    2094     refresh( di );
    2095 }
    2096 
    2097 static void
    2098 onEditTrackersResponse( GtkDialog * dialog, int response, gpointer data )
    2099 {
    2100     gboolean do_destroy = TRUE;
    2101     struct DetailsImpl * di = data;
    2102 
    2103     if( response == GTK_RESPONSE_ACCEPT )
    2104     {
    2105         int i, n;
    2106         int tier;
    2107         GtkTextIter start, end;
    2108         char * tracker_text;
    2109         char ** tracker_strings;
    2110         tr_tracker_info * trackers;
    2111         tr_torrent * tor = g_object_get_data( G_OBJECT( dialog ), TORRENT_PTR_KEY );
    2112 
    2113         /* build the array of trackers */
    2114         gtk_text_buffer_get_bounds( di->tracker_buffer, &start, &end );
    2115         tracker_text = gtk_text_buffer_get_text( di->tracker_buffer, &start, &end, FALSE );
    2116         tracker_strings = g_strsplit( tracker_text, "\n", 0 );
    2117         for( i=0; tracker_strings[i]; )
    2118             ++i;
    2119         trackers = g_new0( tr_tracker_info, i );
    2120         for( i=n=tier=0; tracker_strings[i]; ++i ) {
    2121             const char * str = tracker_strings[i];
    2122             if( !*str )
    2123                 ++tier;
    2124             else {
    2125                 trackers[n].tier = tier;
    2126                 trackers[n].announce = tracker_strings[i];
    2127                 ++n;
    2128             }
    2129         }
    2130 
    2131         /* update the torrent */
    2132         if( !tr_torrentSetAnnounceList( tor, trackers, n ) )
    2133         {
    2134             GtkWidget * w;
    2135             const char * text = _( "List contains invalid URLs" );
    2136             w = gtk_message_dialog_new( GTK_WINDOW( dialog ),
    2137                                         GTK_DIALOG_MODAL,
    2138                                         GTK_MESSAGE_ERROR,
    2139                                         GTK_BUTTONS_CLOSE, "%s", text );
    2140             gtk_dialog_run( GTK_DIALOG( w ) );
    2141             gtk_widget_destroy( w );
    2142             do_destroy = FALSE;
    2143         }
    2144         else
    2145         {
    2146             di->trackers = NULL;
    2147             di->tracker_buffer = NULL;
    2148         }
    2149 
    2150         /* cleanup */
    2151         g_free( trackers );
    2152         g_strfreev( tracker_strings );
    2153         g_free( tracker_text );
    2154     }
    2155 
    2156     if( response == GTK_RESPONSE_CANCEL )
    2157     {
    2158         tr_torrent * tor = g_object_get_data( G_OBJECT( dialog ), TORRENT_PTR_KEY );
    2159         populate_tracker_buffer( di->tracker_buffer, tor );
    2160     }
    2161 
    2162     if( do_destroy )
    2163         gtk_widget_destroy( GTK_WIDGET( dialog ) );
    2164 }
    2165 
    2166 static void
    2167 onEditTrackers( GtkButton * button, gpointer data )
    2168 {
    2169     int row;
    2170     GtkWidget *w, *d, *fr, *t, *l, *sw;
    2171     GtkWindow * win = GTK_WINDOW( gtk_widget_get_toplevel( GTK_WIDGET( button ) ) );
    2172     struct DetailsImpl * di = data;
    2173 
    2174     d = gtk_dialog_new_with_buttons( _( "Edit Trackers" ), win,
    2175                                      GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
    2176                                      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
    2177                                      GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
    2178                                      NULL );
    2179     g_object_set_data( G_OBJECT( d ), TORRENT_PTR_KEY,
    2180                        g_object_get_data( G_OBJECT( button ), TORRENT_PTR_KEY ) );
    2181     g_signal_connect( d, "response",
    2182                       G_CALLBACK( onEditTrackersResponse ), data );
    2183 
    2184     row = 0;
    2185     t = hig_workarea_create( );
    2186     hig_workarea_add_section_title( t, &row, _( "Tracker Announce URLs" ) );
     2191        int row;
     2192        GtkWidget *w, *d, *fr, *t, *l, *sw;
     2193        GtkWindow * win = GTK_WINDOW( gtk_widget_get_toplevel( GTK_WIDGET( button ) ) );
     2194        char * text = get_editable_tracker_list( tor );
     2195        const int torrent_id = tr_torrentId( tor );
     2196        char * title = g_strdup_printf( _( "%s - Edit Trackers" ), tr_torrentInfo( tor )->name );
     2197
     2198        d = gtk_dialog_new_with_buttons( title, win,
     2199                                         GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
     2200                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
     2201                                         GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
     2202                                         NULL );
     2203        g_signal_connect( d, "response", G_CALLBACK( on_edit_trackers_response ), data );
     2204
     2205        row = 0;
     2206        t = hig_workarea_create( );
     2207        hig_workarea_add_section_title( t, &row, _( "Tracker Announce URLs" ) );
    21872208
    21882209        l = gtk_label_new( NULL );
     
    21932214        hig_workarea_add_wide_control( t, &row, l );
    21942215
    2195         w = gtk_text_view_new_with_buffer( di->tracker_buffer );
     2216        w = gtk_text_view_new( );
     2217        gtk_text_buffer_set_text( gtk_text_view_get_buffer( GTK_TEXT_VIEW( w ) ), text, -1 );
    21962218        gtk_widget_set_size_request( w, 500u, 166u );
    21972219        fr = gtk_frame_new( NULL );
     
    22052227        hig_workarea_add_wide_tall_control( t, &row, fr );
    22062228
    2207     hig_workarea_finish( t, &row );
    2208     gtr_dialog_set_content( GTK_DIALOG( d ), t );
    2209     gtk_widget_show( d );
     2229        hig_workarea_finish( t, &row );
     2230        gtr_dialog_set_content( GTK_DIALOG( d ), t );
     2231
     2232        g_object_set_data( G_OBJECT( d ), "torrent-id", GINT_TO_POINTER( torrent_id ) );
     2233        g_object_set_data( G_OBJECT( d ), "text-buffer", gtk_text_view_get_buffer( GTK_TEXT_VIEW( w ) ) );
     2234        gtk_widget_show( d );
     2235
     2236        g_free( title );
     2237        g_free( text );
     2238    }
     2239}
     2240
     2241static void
     2242on_tracker_list_selection_changed( GtkTreeSelection * sel, gpointer gdi )
     2243{
     2244    struct DetailsImpl * di = gdi;
     2245    const int n = gtk_tree_selection_count_selected_rows( sel );
     2246    tr_torrent * tor = tracker_list_get_current_torrent( di );
     2247
     2248    gtk_widget_set_sensitive( di->remove_tracker_button, n>0 );
     2249    gtk_widget_set_sensitive( di->add_tracker_button, tor!=NULL );
     2250    gtk_widget_set_sensitive( di->edit_trackers_button, tor!=NULL );
     2251}
     2252
     2253static void
     2254on_add_tracker_response( GtkDialog * dialog, int response, gpointer gdi )
     2255{
     2256    gboolean destroy = TRUE;
     2257
     2258    if( response == GTK_RESPONSE_ACCEPT )
     2259    {
     2260        struct DetailsImpl * di = gdi;
     2261        GtkWidget * e = GTK_WIDGET( g_object_get_data( G_OBJECT( dialog ), "url-entry" ) );
     2262        const int torrent_id = GPOINTER_TO_INT( g_object_get_data( G_OBJECT( dialog ), "torrent-id" ) );
     2263        char * url = g_strdup( gtk_entry_get_text( GTK_ENTRY( e ) ) );
     2264        g_strstrip( url );
     2265
     2266        if( url && *url )
     2267        {
     2268            if( gtr_is_supported_url( url ) )
     2269            {
     2270                char * json = g_strdup_printf(
     2271                    "{\n"
     2272                    "  \"method\": \"torrent-set\",\n"
     2273                    "  \"arguments\": { \"id\": %d, \"trackerAdd\": [ \"%s\" ] }\n"
     2274                    "}\n",
     2275                    torrent_id, url );
     2276                tr_core_exec_json( di->core, json );
     2277                refresh( di );
     2278                g_free( json );
     2279            }
     2280            else
     2281            {
     2282                gtr_unrecognized_url_dialog( GTK_WIDGET( dialog ), url );
     2283                destroy = FALSE;
     2284            }
     2285        }
     2286
     2287        g_free( url );
     2288    }
     2289
     2290    if( destroy )
     2291        gtk_widget_destroy( GTK_WIDGET( dialog ) );
     2292}
     2293
     2294static void
     2295on_tracker_list_add_button_clicked( GtkButton * button UNUSED, gpointer gdi )
     2296{
     2297    struct DetailsImpl * di = gdi;
     2298    tr_torrent * tor = tracker_list_get_current_torrent( di );
     2299
     2300    if( tor != NULL )
     2301    {
     2302        int row;
     2303        GtkWidget * e;
     2304        GtkWidget * t;
     2305        GtkWidget * w;
     2306        char * title = g_strdup_printf( _( "%s - Add Tracker" ), tr_torrentInfo( tor )->name );
     2307
     2308        w = gtk_dialog_new_with_buttons( title, GTK_WINDOW( di->dialog ),
     2309                                         GTK_DIALOG_DESTROY_WITH_PARENT,
     2310                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
     2311                                         GTK_STOCK_ADD, GTK_RESPONSE_ACCEPT,
     2312                                         NULL );
     2313        gtk_dialog_set_alternative_button_order( GTK_DIALOG( w ),
     2314                                                 GTK_RESPONSE_ACCEPT,
     2315                                                 GTK_RESPONSE_CANCEL,
     2316                                                 -1 );
     2317        g_signal_connect( w, "response", G_CALLBACK( on_add_tracker_response ), gdi );
     2318
     2319        row = 0;
     2320        t = hig_workarea_create( );
     2321        hig_workarea_add_section_title( t, &row, _( "Tracker" ) );
     2322        e = gtk_entry_new( );
     2323        gtk_widget_set_size_request( e, 400, -1 );
     2324        gtr_paste_clipboard_url_into_entry( e );
     2325        g_object_set_data( G_OBJECT( w ), "url-entry", e );
     2326        g_object_set_data( G_OBJECT( w ), "torrent-id", GINT_TO_POINTER( tr_torrentId( tor ) ) );
     2327        hig_workarea_add_row( t, &row, _( "_Announce URL:" ), e, NULL );
     2328        gtr_dialog_set_content( GTK_DIALOG( w ), t );
     2329        gtk_widget_show_all( w );
     2330
     2331        g_free( title );
     2332    }
     2333}
     2334
     2335static void
     2336on_tracker_list_remove_button_clicked( GtkButton * button UNUSED, gpointer gdi )
     2337{
     2338    GtkTreeIter iter;
     2339    GtkTreeModel * model;
     2340    struct DetailsImpl * di = gdi;
     2341    GtkTreeView * v = GTK_TREE_VIEW( di->tracker_view );
     2342    GtkTreeSelection * sel = gtk_tree_view_get_selection( v );
     2343
     2344    if( gtk_tree_selection_get_selected( sel, &model, &iter ) )
     2345    {
     2346        char * json;
     2347        int torrent_id;
     2348        int tracker_id;
     2349        gtk_tree_model_get( model, &iter, TRACKER_COL_TRACKER_ID, &tracker_id,
     2350                                          TRACKER_COL_TORRENT_ID, &torrent_id,
     2351                                          -1 );
     2352        json = g_strdup_printf( "{\n"
     2353                                "  \"method\": \"torrent-set\",\n"
     2354                                "  \"arguments\": { \"id\": %d, \"trackerRemove\": [ %d ] }\n"
     2355                                "}\n",
     2356                                torrent_id, tracker_id );
     2357        tr_core_exec_json( di->core, json );
     2358        refresh( di );
     2359        g_free( json );
     2360    }
    22102361}
    22112362
     
    22142365{
    22152366    gboolean b;
    2216     GtkCellRenderer *r;
    2217     GtkTreeViewColumn *c;
     2367    GtkCellRenderer * r;
     2368    GtkTreeViewColumn * c;
     2369    GtkTreeSelection * sel;
    22182370    GtkWidget *vbox, *sw, *w, *v, *hbox;
    22192371    const int pad = ( GUI_PAD + GUI_PAD_BIG ) / 2;
     
    22222374    gtk_container_set_border_width( GTK_CONTAINER( vbox ), GUI_PAD_BIG );
    22232375
    2224     v = di->tracker_view = gtk_tree_view_new( );
    2225     gtk_tree_view_set_headers_visible( GTK_TREE_VIEW( v ), FALSE );
    2226     g_signal_connect( v, "button-press-event",
    2227                       G_CALLBACK( on_tree_view_button_pressed ), NULL );
    2228     g_signal_connect( v, "button-release-event",
    2229                       G_CALLBACK( on_tree_view_button_released ), NULL );
    2230     gtk_tree_view_set_rules_hint( GTK_TREE_VIEW( v ), TRUE );
    2231 
    2232     c = gtk_tree_view_column_new( );
    2233     gtk_tree_view_column_set_title( c, _( "Trackers" ) );
    2234     gtk_tree_view_append_column( GTK_TREE_VIEW( v ), c );
    2235 
    2236     r = gtk_cell_renderer_pixbuf_new( );
    2237     g_object_set( r, "width", 20 + (GUI_PAD_SMALL*2), "xpad", GUI_PAD_SMALL, "ypad", pad, "yalign", 0.0f, NULL );
    2238     gtk_tree_view_column_pack_start( c, r, FALSE );
    2239     gtk_tree_view_column_add_attribute( c, r, "pixbuf", TRACKER_COL_FAVICON );
    2240 
    2241     r = gtk_cell_renderer_text_new( );
    2242     g_object_set( G_OBJECT( r ), "ellipsize", PANGO_ELLIPSIZE_END, "xpad", GUI_PAD_SMALL, "ypad", pad, NULL );
    2243     gtk_tree_view_column_pack_start( c, r, TRUE );
    2244     gtk_tree_view_column_add_attribute( c, r, "markup", TRACKER_COL_TEXT );
    2245 
    2246     sw = gtk_scrolled_window_new( NULL, NULL );
    2247     gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( sw ),
    2248                                     GTK_POLICY_AUTOMATIC,
    2249                                     GTK_POLICY_AUTOMATIC );
    2250     gtk_container_add( GTK_CONTAINER( sw ), v );
    2251     w = gtk_frame_new( NULL );
    2252     gtk_frame_set_shadow_type( GTK_FRAME( w ), GTK_SHADOW_IN );
    2253     gtk_container_add( GTK_CONTAINER( w ), sw );
    2254     gtk_box_pack_start( GTK_BOX( vbox ), w, TRUE, TRUE, 0 );
    2255 
    2256     hbox = gtk_hbox_new( FALSE, 0 );
    2257 
    2258       w = gtk_check_button_new_with_mnemonic( _( "Show _more details" ) );
    2259       di->scrape_check = w;
    2260       b = gtr_pref_flag_get( PREF_KEY_SHOW_MORE_TRACKER_INFO );
    2261       gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), b );
    2262       g_signal_connect( w, "toggled", G_CALLBACK( onScrapeToggled ), di );
    2263       gtk_box_pack_start( GTK_BOX( hbox ), w, FALSE, FALSE, 0 );
    2264 
    2265       w = gtk_button_new_with_mnemonic( _( "_Edit Trackers" ) );
    2266       gtk_button_set_image( GTK_BUTTON( w ), gtk_image_new_from_stock( GTK_STOCK_EDIT, GTK_ICON_SIZE_BUTTON ) );
    2267       g_signal_connect( w, "clicked", G_CALLBACK( onEditTrackers ), di );
    2268       gtk_box_pack_end( GTK_BOX( hbox ), w, FALSE, FALSE, 0 );
    2269       di->edit_trackers_button = w;
    2270 
    2271     gtk_box_pack_start( GTK_BOX( vbox ), hbox, FALSE, FALSE, 0 );
     2376    di->tracker_store = gtk_list_store_new( TRACKER_N_COLS, G_TYPE_INT,
     2377                                                            G_TYPE_STRING,
     2378                                                            G_TYPE_BOOLEAN,
     2379                                                            G_TYPE_INT,
     2380                                                            GDK_TYPE_PIXBUF,
     2381                                                            G_TYPE_BOOLEAN,
     2382                                                            G_TYPE_STRING );
     2383    di->tracker_hash = g_hash_table_new_full( g_str_hash,
     2384                                              g_str_equal,
     2385                                              (GDestroyNotify)g_free,
     2386                                              (GDestroyNotify)gtk_tree_row_reference_free );
     2387    di->trackers_filtered = gtk_tree_model_filter_new( GTK_TREE_MODEL( di->tracker_store ), NULL );
     2388    gtk_tree_model_filter_set_visible_func( GTK_TREE_MODEL_FILTER( di->trackers_filtered ),
     2389                                            trackerVisibleFunc, di, NULL );
     2390
     2391    hbox = gtk_hbox_new( FALSE, GUI_PAD_BIG );
     2392
     2393        v = di->tracker_view = gtk_tree_view_new_with_model( GTK_TREE_MODEL( di->trackers_filtered ) );
     2394        gtk_tree_view_set_headers_visible( GTK_TREE_VIEW( v ), FALSE );
     2395        g_signal_connect( v, "button-press-event", G_CALLBACK( on_tree_view_button_pressed ), NULL );
     2396        g_signal_connect( v, "button-release-event", G_CALLBACK( on_tree_view_button_released ), NULL );
     2397        gtk_tree_view_set_rules_hint( GTK_TREE_VIEW( v ), TRUE );
     2398
     2399        sel = gtk_tree_view_get_selection( GTK_TREE_VIEW( v ) );
     2400        g_signal_connect( sel, "changed", G_CALLBACK( on_tracker_list_selection_changed ), di );
     2401       
     2402        c = gtk_tree_view_column_new( );
     2403        gtk_tree_view_column_set_title( c, _( "Trackers" ) );
     2404        gtk_tree_view_append_column( GTK_TREE_VIEW( v ), c );
     2405
     2406        r = gtk_cell_renderer_pixbuf_new( );
     2407        g_object_set( r, "width", 20 + (GUI_PAD_SMALL*2), "xpad", GUI_PAD_SMALL, "ypad", pad, "yalign", 0.0f, NULL );
     2408        gtk_tree_view_column_pack_start( c, r, FALSE );
     2409        gtk_tree_view_column_add_attribute( c, r, "pixbuf", TRACKER_COL_FAVICON );
     2410
     2411        r = gtk_cell_renderer_text_new( );
     2412        g_object_set( G_OBJECT( r ), "ellipsize", PANGO_ELLIPSIZE_END, "xpad", GUI_PAD_SMALL, "ypad", pad, NULL );
     2413        gtk_tree_view_column_pack_start( c, r, TRUE );
     2414        gtk_tree_view_column_add_attribute( c, r, "markup", TRACKER_COL_TEXT );
     2415
     2416        sw = gtk_scrolled_window_new( NULL, NULL );
     2417        gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( sw ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
     2418        gtk_container_add( GTK_CONTAINER( sw ), v );
     2419        w = gtk_frame_new( NULL );
     2420        gtk_frame_set_shadow_type( GTK_FRAME( w ), GTK_SHADOW_IN );
     2421        gtk_container_add( GTK_CONTAINER( w ), sw );
     2422
     2423    gtk_box_pack_start( GTK_BOX( hbox ), w, TRUE, TRUE, 0 );
     2424
     2425        v = gtk_vbox_new( FALSE, GUI_PAD );
     2426
     2427        w = gtk_button_new_with_mnemonic( _( "_Add" ) );
     2428        di->add_tracker_button = w;
     2429        g_signal_connect( w, "clicked", G_CALLBACK( on_tracker_list_add_button_clicked ), di );
     2430        gtk_box_pack_start( GTK_BOX( v ), w, FALSE, FALSE, 0 );
     2431
     2432        w = gtk_button_new_with_mnemonic( _( "_Edit" ) );
     2433        gtk_button_set_image( GTK_BUTTON( w ), gtk_image_new_from_stock( GTK_STOCK_EDIT, GTK_ICON_SIZE_BUTTON ) );
     2434        g_signal_connect( w, "clicked", G_CALLBACK( on_edit_trackers ), di );
     2435        di->edit_trackers_button = w;
     2436        gtk_box_pack_start( GTK_BOX( v ), w, FALSE, FALSE, 0 );
     2437
     2438        w = gtk_button_new_with_mnemonic( _( "_Remove" ) );
     2439        di->remove_tracker_button = w;
     2440        g_signal_connect( w, "clicked", G_CALLBACK( on_tracker_list_remove_button_clicked ), di );
     2441        gtk_box_pack_start( GTK_BOX( v ), w, FALSE, FALSE, 0 );
     2442
     2443        gtk_box_pack_start( GTK_BOX( hbox ), v, FALSE, FALSE, 0 );
     2444
     2445    gtk_box_pack_start( GTK_BOX( vbox ), hbox, TRUE, TRUE, 0 );
     2446
     2447    w = gtk_check_button_new_with_mnemonic( _( "Show _more details" ) );
     2448    di->scrape_check = w;
     2449    b = gtr_pref_flag_get( PREF_KEY_SHOW_MORE_TRACKER_INFO );
     2450    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), b );
     2451    g_signal_connect( w, "toggled", G_CALLBACK( onScrapeToggled ), di );
     2452    gtk_box_pack_start( GTK_BOX( vbox ), w, FALSE, FALSE, 0 );
    22722453
    22732454    w = gtk_check_button_new_with_mnemonic( _( "Show _backup trackers" ) );
     
    23152496    struct DetailsImpl * data = gdata;
    23162497    g_source_remove( data->periodic_refresh_tag );
     2498    g_hash_table_destroy( data->tracker_hash );
    23172499    g_hash_table_destroy( data->webseed_hash );
    23182500    g_hash_table_destroy( data->peer_hash );
  • trunk/gtk/util.c

    r11599 r11673  
    914914    g_string_free( gstr, TRUE );
    915915}
     916
     917/***
     918****
     919***/
     920
     921void
     922gtr_paste_clipboard_url_into_entry( GtkWidget * e )
     923{
     924  size_t i;
     925
     926  char * text[] = {
     927    gtk_clipboard_wait_for_text( gtk_clipboard_get( GDK_SELECTION_PRIMARY ) ),
     928    gtk_clipboard_wait_for_text( gtk_clipboard_get( GDK_SELECTION_CLIPBOARD ) )
     929  };
     930
     931  for( i=0; i<G_N_ELEMENTS(text); ++i ) {
     932      char * s = text[i];
     933      if( s && ( gtr_is_supported_url( s ) || gtr_is_magnet_link( s ) ) ) {
     934          gtk_entry_set_text( GTK_ENTRY( e ), s );
     935          break;
     936      }
     937  }
     938
     939  for( i=0; i<G_N_ELEMENTS(text); ++i )
     940    g_free( text[i] );
     941}
     942
  • trunk/gtk/util.h

    r11599 r11673  
    199199int gtr_file_trash_or_remove( const char * filename );
    200200
     201void gtr_paste_clipboard_url_into_entry( GtkWidget * entry );
     202
     203
    201204#endif /* GTR_UTIL_H */
Note: See TracChangeset for help on using the changeset viewer.