Changeset 11628


Ignore:
Timestamp:
Jan 5, 2011, 7:08:34 AM (11 years ago)
Author:
jordan
Message:

(trunk gtk) #3866 "Popup menu for file list manipulation" -- patch by ijuxda + random bugs by me

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/file-list.c

    r11599 r11628  
    2424#include "icons.h"
    2525#include "tr-prefs.h"
     26
     27#define TR_DOWNLOAD_KEY  "tr-download-key"
     28#define TR_COLUMN_ID_KEY "tr-model-column-id-key"
     29#define TR_PRIORITY_KEY  "tr-priority-key"
    2630
    2731enum
     
    323327}
    324328
    325 static void
    326 getSelectedFilesAndDescendants( GtkTreeView * view, GArray * indices )
     329static GArray*
     330getSelectedFilesAndDescendants( GtkTreeView * view )
    327331{
    328332    struct ActiveData data;
    329333
    330334    data.sel = gtk_tree_view_get_selection( view );
    331     data.array  = indices;
     335    data.array = g_array_new( FALSE, FALSE, sizeof( tr_file_index_t ) );
    332336    gtk_tree_model_foreach( gtk_tree_view_get_model( view ),
    333337                            getSelectedFilesForeach, &data );
     338    return data.array;
    334339}
    335340
     
    379384getActiveFilesForPath( GtkTreeView * view, GtkTreePath * path )
    380385{
     386    GArray * indices;
    381387    GtkTreeSelection * sel = gtk_tree_view_get_selection( view );
    382     GArray * indices = g_array_new( FALSE, FALSE, sizeof( tr_file_index_t ) );
    383388
    384389    if( gtk_tree_selection_path_is_selected( sel, path ) )
    385390    {
    386391        /* clicked in a selected row... use the current selection */
    387         getSelectedFilesAndDescendants( view, indices );
     392        indices = getSelectedFilesAndDescendants( view );
    388393    }
    389394    else
    390395    {
    391396        /* clicked OUTSIDE of the selected row... just use the clicked row */
     397        indices = g_array_new( FALSE, FALSE, sizeof( tr_file_index_t ) );
    392398        getSubtree( view, path, indices );
    393399    }
     
    684690}
    685691
     692static void
     693fileMenuSetDownload( GtkWidget * item, gpointer gdata )
     694{
     695    tr_torrent * tor;
     696    FileData * data = gdata;
     697
     698    if(( tor = tr_torrentFindFromId( tr_core_session( data->core ), data->torrentId )))
     699    {
     700        const tr_bool download_flag = g_object_get_data( G_OBJECT( item ), TR_DOWNLOAD_KEY ) != NULL;
     701        GArray * indices = getSelectedFilesAndDescendants( GTK_TREE_VIEW( data->view ) );
     702
     703        tr_torrentSetFileDLs( tor,
     704                              (tr_file_index_t *) indices->data,
     705                              (tr_file_index_t) indices->len,
     706                              download_flag );
     707
     708        refresh( data );
     709        g_array_free( indices, TRUE );
     710    }
     711}
     712
     713static void
     714fileMenuSetPriority( GtkWidget * item, gpointer gdata )
     715{
     716    tr_torrent * tor;
     717    FileData * data = gdata;
     718
     719    if(( tor = tr_torrentFindFromId( tr_core_session( data->core ), data->torrentId )))
     720    {
     721        const int priority = GPOINTER_TO_INT( g_object_get_data( G_OBJECT( item ), TR_PRIORITY_KEY ) );
     722        GArray * indices = getSelectedFilesAndDescendants( GTK_TREE_VIEW( data->view ) );
     723        tr_torrentSetFilePriorities( tor,
     724                                     (tr_file_index_t *) indices->data,
     725                                     (tr_file_index_t) indices->len,
     726                                     priority );
     727        refresh( data );
     728        g_array_free( indices, TRUE );
     729    }
     730}
     731
     732static void
     733fileMenuPopup( GtkWidget * w, GdkEventButton * event, gpointer filedata )
     734{
     735    GtkWidget * item;
     736    GtkWidget * menu;
     737
     738    menu = gtk_menu_new( );
     739    item = gtk_menu_item_new_with_label( _( "Set Priority High" ) );
     740    g_object_set_data( G_OBJECT( item ), TR_PRIORITY_KEY,
     741                       GINT_TO_POINTER( TR_PRI_HIGH ) );
     742    g_signal_connect( item, "activate",
     743                      G_CALLBACK( fileMenuSetPriority ), filedata );
     744    gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
     745
     746    item = gtk_menu_item_new_with_label( _( "Set Priority Normal" ) );
     747    g_object_set_data( G_OBJECT( item ), TR_PRIORITY_KEY,
     748                       GINT_TO_POINTER( TR_PRI_NORMAL ) );
     749    g_signal_connect( item, "activate",
     750                      G_CALLBACK( fileMenuSetPriority ), filedata );
     751    gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
     752
     753    item = gtk_menu_item_new_with_label( _( "Set Priority Low" ) );
     754    g_object_set_data( G_OBJECT( item ), TR_PRIORITY_KEY,
     755                       GINT_TO_POINTER( TR_PRI_LOW ) );
     756    g_signal_connect( item, "activate",
     757                      G_CALLBACK( fileMenuSetPriority ), filedata );
     758    gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
     759
     760    item = gtk_separator_menu_item_new( );
     761    gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
     762
     763    item = gtk_menu_item_new_with_label( _( "Download" ) );
     764    g_object_set_data( G_OBJECT( item ), TR_DOWNLOAD_KEY,
     765                       GINT_TO_POINTER( TRUE ) );
     766    g_signal_connect( item, "activate",
     767                      G_CALLBACK( fileMenuSetDownload ), filedata );
     768    gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
     769
     770    item = gtk_menu_item_new_with_label( _( "Do Not Download" ) );
     771    g_object_set_data( G_OBJECT( item ), TR_DOWNLOAD_KEY,
     772                       GINT_TO_POINTER( FALSE ) );
     773    g_signal_connect( item, "activate",
     774                      G_CALLBACK( fileMenuSetDownload ), filedata );
     775    gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
     776
     777    gtk_widget_show_all( menu );
     778    gtk_menu_attach_to_widget( GTK_MENU( menu ), w, NULL );
     779    gtk_menu_popup( GTK_MENU( menu ), NULL, NULL, NULL, NULL,
     780                    event ? event->button : 0,
     781                    event ? event->time : gtk_get_current_event_time( ) );
     782}
     783
     784static gboolean
     785onViewPathToggled( GtkTreeView       * view,
     786                   GtkTreeViewColumn * col,
     787                   GtkTreePath       * path,
     788                   FileData          * data )
     789{
     790    int cid;
     791    tr_torrent * tor;
     792    gboolean handled = FALSE;
     793
     794    if( !col || !path )
     795        return FALSE;
     796
     797    cid = GPOINTER_TO_INT( g_object_get_data( G_OBJECT( col ), TR_COLUMN_ID_KEY ) );
     798    tor = tr_torrentFindFromId( tr_core_session( data->core ), data->torrentId );
     799    if( ( tor != NULL ) && ( ( cid == FC_PRIORITY ) || ( cid == FC_ENABLED ) ) )
     800    {
     801        GtkTreeIter iter;
     802        GArray * indices = getActiveFilesForPath( view, path );
     803        GtkTreeModel * model = data->model;
     804
     805        gtk_tree_model_get_iter( model, &iter, path );
     806
     807        if( cid == FC_PRIORITY )
     808        {
     809            int priority;
     810            gtk_tree_model_get( model, &iter, FC_PRIORITY, &priority, -1 );
     811            switch( priority ) {
     812                case TR_PRI_NORMAL: priority = TR_PRI_HIGH; break;
     813                case TR_PRI_HIGH:   priority = TR_PRI_LOW; break;
     814                default:            priority = TR_PRI_NORMAL; break;
     815            }
     816            tr_torrentSetFilePriorities( tor,
     817                                         (tr_file_index_t *) indices->data,
     818                                         (tr_file_index_t) indices->len,
     819                                         priority );
     820        }
     821        else
     822        {
     823            int enabled;
     824            gtk_tree_model_get( model, &iter, FC_ENABLED, &enabled, -1 );
     825            enabled = !enabled;
     826
     827            tr_torrentSetFileDLs( tor,
     828                                  (tr_file_index_t *) indices->data,
     829                                  (tr_file_index_t) indices->len,
     830                                  enabled );
     831        }
     832
     833        refresh( data );
     834        g_array_free( indices, TRUE );
     835        handled = TRUE;
     836    }
     837
     838    return handled;
     839}
     840
     841/**
     842 * @note 'col' and 'path' are assumed not to be NULL.
     843 */
     844static gboolean
     845getAndSelectEventPath( GtkTreeView        * treeview,
     846                       GdkEventButton     * event,
     847                       GtkTreeViewColumn ** col,
     848                       GtkTreePath       ** path )
     849{
     850    GtkTreeSelection * sel;
     851
     852    if( gtk_tree_view_get_path_at_pos( treeview,
     853                                       event->x, event->y,
     854                                       path, col, NULL, NULL ) )
     855    {
     856        sel = gtk_tree_view_get_selection( treeview );
     857        if( !gtk_tree_selection_path_is_selected( sel, *path ) )
     858        {
     859            gtk_tree_selection_unselect_all( sel );
     860            gtk_tree_selection_select_path( sel, *path );
     861        }
     862        return TRUE;
     863    }
     864
     865    return FALSE;
     866}
    686867
    687868static gboolean
    688869onViewButtonPressed( GtkWidget * w, GdkEventButton * event, gpointer gdata )
    689870{
    690     FileData * data = gdata;
    691     gboolean   handled = FALSE;
    692     tr_torrent * tor = tr_torrentFindFromId( tr_core_session( data->core ), data->torrentId );
    693 
     871    tr_torrent        * tor;
     872    GtkTreeViewColumn * col = NULL;
     873    GtkTreePath       * path = NULL;
     874    FileData          * data = gdata;
     875    gboolean            handled = FALSE;
     876    GtkTreeView       * treeview = GTK_TREE_VIEW( w );
     877
     878    tor = tr_torrentFindFromId( tr_core_session( data->core ),
     879                                data->torrentId );
    694880    if( tor == NULL )
    695         return handled;
    696 
    697     if( ( event->type == GDK_BUTTON_PRESS ) && ( event->button == 1 )
    698       && !( event->state & ( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) )
    699     {
    700         GtkTreeView *       view = GTK_TREE_VIEW( w );
    701         GtkTreePath *       path;
    702         GtkTreeViewColumn * column;
    703         int                 cell_x;
    704         int                 cell_y;
    705         if( gtk_tree_view_get_path_at_pos( view, event->x, event->y,
    706                                            &path, &column, &cell_x, &cell_y ) )
     881        return FALSE;
     882
     883    if( event->type == GDK_BUTTON_PRESS && event->button == 1
     884        && !( event->state & ( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) )
     885        && getAndSelectEventPath( treeview, event, &col, &path ) )
     886    {
     887        handled = onViewPathToggled( treeview, col, path, data );
     888    }
     889    else if( event->type == GDK_BUTTON_PRESS && event->button == 3
     890             && getAndSelectEventPath( treeview, event, &col, &path ) )
     891    {
     892        GtkTreeSelection * sel = gtk_tree_view_get_selection( treeview );
     893        if( gtk_tree_selection_count_selected_rows( sel ) > 0 )
    707894        {
    708             const char * column_title = gtk_tree_view_column_get_title( column );
    709             const gboolean downloadColumn = !strcmp( column_title, _( "Download" ) );
    710             const gboolean priorityColumn = !strcmp( column_title, _( "Priority" ) );
    711             if( downloadColumn || priorityColumn )
    712             {
    713                 GArray * a = getActiveFilesForPath( view, path );
    714                 GtkTreeSelection * sel = gtk_tree_view_get_selection( view );
    715                 const gboolean isSelected = gtk_tree_selection_path_is_selected( sel, path );
    716                 GtkTreeModel * model = data->model;
    717                 GtkTreeIter iter;
    718 
    719                 gtk_tree_model_get_iter( model, &iter, path );
    720 
    721                 if( priorityColumn )
    722                 {
    723                     int priority;
    724 
    725                     /* get the `priority' state of the clicked row */
    726                     gtk_tree_model_get( model, &iter, FC_PRIORITY, &priority, -1 );
    727 
    728                     /* twiddle it to the next state */
    729                     switch( priority ) {
    730                         case TR_PRI_NORMAL: priority = TR_PRI_HIGH; break;
    731                         case TR_PRI_HIGH:   priority = TR_PRI_LOW; break;
    732                         default:            priority = TR_PRI_NORMAL; break;
    733                     }
    734 
    735                     /* apply that new state to the active files */
    736                     tr_torrentSetFilePriorities( tor,
    737                                                  (tr_file_index_t*)a->data,
    738                                                  (tr_file_index_t)a->len,
    739                                                  priority );
    740                 }
    741                 else if( downloadColumn )
    742                 {
    743                     int enabled;
    744 
    745                     /* get the `enabled' state of the clicked row */
    746                     gtk_tree_model_get( model, &iter, FC_ENABLED, &enabled, -1 );
    747 
    748                     /* twiddle it to the next state */
    749                     enabled = !enabled;
    750 
    751                     /* apply that new state to the active files */
    752                     tr_torrentSetFileDLs( tor,
    753                                           (tr_file_index_t*)a->data,
    754                                           (tr_file_index_t)a->len,
    755                                           enabled );
    756                 }
    757 
    758                 refresh( data );
    759 
    760                 /* the click was meant to change the priority or enabled state,
    761                    not to alter which rows were selected, so don't pass this
    762                    event on to the other handlers. */
    763                 handled = isSelected;
    764 
    765                 /* cleanup */
    766                 g_array_free( a, TRUE );
    767             }
    768 
    769             gtk_tree_path_free( path );
     895            fileMenuPopup( w, event, data );
     896            handled = TRUE;
    770897        }
    771898    }
    772899
     900    gtk_tree_path_free( path );
    773901    return handled;
     902}
     903
     904static gboolean
     905onViewPopupMenu( GtkWidget * w, gpointer gdata )
     906{
     907    fileMenuPopup( w, NULL, gdata );
     908    return TRUE;
    774909}
    775910
     
    798933    g_signal_connect( view, "button-press-event",
    799934                      G_CALLBACK( onViewButtonPressed ), data );
     935    g_signal_connect( view, "popup-menu",
     936                      G_CALLBACK( onViewPopupMenu ), data );
    800937    g_signal_connect( view, "row_activated",
    801938                      G_CALLBACK( onRowActivated ), data );
     
    849986    rend = gtk_cell_renderer_toggle_new( );
    850987    col = gtk_tree_view_column_new_with_attributes( title, rend, NULL );
     988    g_object_set_data( G_OBJECT( col ), TR_COLUMN_ID_KEY,
     989                       GINT_TO_POINTER( FC_ENABLED ) );
    851990    gtk_tree_view_column_set_fixed_width( col, width );
    852991    gtk_tree_view_column_set_sizing( col, GTK_TREE_VIEW_COLUMN_FIXED );
     
    8641003    g_object_set( rend, "xalign", (gfloat)0.5, "yalign", (gfloat)0.5, NULL );
    8651004    col = gtk_tree_view_column_new_with_attributes( title, rend, NULL );
     1005    g_object_set_data( G_OBJECT( col ), TR_COLUMN_ID_KEY,
     1006                       GINT_TO_POINTER( FC_PRIORITY ) );
    8661007    gtk_tree_view_column_set_fixed_width( col, width );
    8671008    gtk_tree_view_column_set_sizing( col, GTK_TREE_VIEW_COLUMN_FIXED );
Note: See TracChangeset for help on using the changeset viewer.