source: branches/1.9x/gtk/actions.c @ 10563

Last change on this file since 10563 was 10563, checked in by charles, 12 years ago

(1.93 gtk) backport #3179 "gtk+ client should use the 24-pixel-wide icon in the system tray"

  • Property svn:keywords set to Date Rev Author Id
File size: 12.0 KB
Line 
1/*
2 * This file Copyright (C) 2007-2010 Mnemosyne LLC
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: actions.c 10563 2010-05-01 03:32:54Z charles $
11 */
12
13#include <string.h>
14
15#include <glib/gi18n.h>
16#include <gtk/gtk.h>
17
18#include <libtransmission/transmission.h>
19
20#include "actions.h"
21#include "conf.h"
22#include "tr-core.h"
23#include "tr-prefs.h"
24#include "lock.h"
25
26#include "logo-24.h"
27#include "logo-48.h"
28#include "ratio-icon.h"
29#include "options-icon.h"
30#include "turtles.h"
31
32#define UNUSED G_GNUC_UNUSED
33
34static TrCore *         myCore = NULL;
35
36static GtkActionGroup * myGroup = NULL;
37
38static void
39action_cb( GtkAction * a,
40           gpointer    user_data )
41{
42    doAction ( gtk_action_get_name( a ), user_data );
43}
44
45#if !GTK_CHECK_VERSION( 2, 8, 0 )
46 #define GTK_STOCK_INFO GTK_STOCK_PROPERTIES
47#endif
48
49#if !GTK_CHECK_VERSION( 2, 10, 0 )
50 #define GTK_STOCK_SELECT_ALL NULL
51#endif
52
53static GtkRadioActionEntry sort_radio_entries[] =
54{
55    { "sort-by-activity",  NULL, N_( "Sort by _Activity" ),  NULL, NULL, 0 },
56    { "sort-by-name",      NULL, N_( "Sort by _Name" ),      NULL, NULL, 1 },
57    { "sort-by-progress",  NULL, N_( "Sort by _Progress" ),  NULL, NULL, 2 },
58    { "sort-by-ratio",     NULL, N_( "Sort by Rati_o" ),     NULL, NULL, 3 },
59    { "sort-by-state",     NULL, N_( "Sort by Stat_e" ),     NULL, NULL, 4 },
60    { "sort-by-tracker",   NULL, N_( "Sort by T_racker" ),   NULL, NULL, 5 },
61    { "sort-by-age",       NULL, N_( "Sort by A_ge" ),       NULL, NULL, 6 },
62    { "sort-by-time-left", NULL, N_( "Sort by Time _Left" ), NULL, NULL, 7 },
63    { "sort-by-size",      NULL, N_( "Sort by Si_ze" ),      NULL, NULL, 8 }
64};
65
66static void
67sort_changed_cb( GtkAction            * action UNUSED,
68                 GtkRadioAction *              current,
69                 gpointer user_data            UNUSED )
70{
71    const char * key = PREF_KEY_SORT_MODE;
72    const int    i = gtk_radio_action_get_current_value( current );
73    const char * val = sort_radio_entries[i].name;
74
75    tr_core_set_pref( myCore, key, val );
76}
77
78static GtkToggleActionEntry show_toggle_entries[] =
79{
80    { "toggle-main-window", NULL, N_( "_Show Transmission" ), NULL, NULL, G_CALLBACK( action_cb ), TRUE },
81    { "toggle-message-log", NULL, N_( "Message _Log" ), NULL, NULL, G_CALLBACK( action_cb ), FALSE }
82};
83
84static void
85toggle_pref_cb( GtkToggleAction *  action,
86                gpointer user_data UNUSED )
87{
88    const char *   key = gtk_action_get_name( GTK_ACTION( action ) );
89    const gboolean val = gtk_toggle_action_get_active( action );
90
91    tr_core_set_pref_bool( myCore, key, val );
92}
93
94static GtkToggleActionEntry  pref_toggle_entries[] =
95{
96    { "alt-speed-enabled", NULL, N_( "Enable Temporary Speed _Limits" ), NULL, NULL, G_CALLBACK( toggle_pref_cb ), FALSE },
97    { "minimal-view",      NULL, N_( "_Minimal View" ), "<alt>M", NULL, G_CALLBACK( toggle_pref_cb ), FALSE },
98    { "sort-reversed",     NULL, N_( "Re_verse Sort Order" ), NULL, NULL, G_CALLBACK( toggle_pref_cb ), FALSE },
99    { "show-filterbar",    NULL, N_( "_Filterbar" ), NULL, NULL, G_CALLBACK( toggle_pref_cb ), FALSE },
100    { "show-statusbar",    NULL, N_( "_Statusbar" ), NULL, NULL, G_CALLBACK( toggle_pref_cb ), FALSE },
101    { "show-toolbar",      NULL, N_( "_Toolbar" ), NULL, NULL, G_CALLBACK( toggle_pref_cb ), FALSE }
102};
103
104static GtkActionEntry entries[] =
105{
106    { "file-menu", NULL, N_( "_File" ), NULL, NULL, NULL  },
107    { "torrent-menu", NULL, N_( "_Torrent" ), NULL, NULL, NULL  },
108    { "view-menu", NULL, N_( "_View" ), NULL, NULL, NULL  },
109    { "sort-menu", NULL, N_( "_Sort Torrents By" ), NULL, NULL, NULL },
110    { "edit-menu", NULL, N_( "_Edit" ), NULL, NULL, NULL },
111    { "help-menu", NULL, N_( "_Help" ), NULL, NULL, NULL },
112    { "copy-magnet-link-to-clipboard",  GTK_STOCK_COPY, N_("Copy _Magnet Link to Clipboard" ), "<control>M", NULL,  G_CALLBACK( action_cb ) },
113    { "add-torrent-from-url",  GTK_STOCK_ADD, N_("Add _URL..." ), NULL, N_( "Add URL..." ),  G_CALLBACK( action_cb ) },
114    { "add-torrent-toolbar",  GTK_STOCK_ADD, NULL, NULL, N_( "Add a torrent" ),  G_CALLBACK( action_cb ) },
115    { "add-torrent-menu", GTK_STOCK_ADD, N_( "_Add File..." ), "<control>D", N_( "Add a torrent" ), G_CALLBACK( action_cb ) },
116    { "start-torrent", GTK_STOCK_MEDIA_PLAY, N_( "_Start" ), "<control>S", N_( "Start torrent" ), G_CALLBACK( action_cb ) },
117    { "show-stats", NULL, N_( "_Statistics" ), NULL, NULL, G_CALLBACK( action_cb ) },
118    { "donate", NULL, N_( "_Donate" ), NULL, NULL, G_CALLBACK( action_cb ) },
119    { "verify-torrent", NULL, N_( "_Verify Local Data" ), "<control>V", NULL, G_CALLBACK( action_cb ) },
120    { "pause-torrent", GTK_STOCK_MEDIA_PAUSE, N_( "_Pause" ), "<control>P", N_( "Pause torrent" ), G_CALLBACK( action_cb ) },
121    { "pause-all-torrents", GTK_STOCK_MEDIA_PAUSE, N_( "_Pause All" ), NULL, N_( "Pause all torrents" ), G_CALLBACK( action_cb ) },
122    { "start-all-torrents", GTK_STOCK_MEDIA_PLAY, N_( "_Start All" ), NULL, N_( "Start all torrents" ), G_CALLBACK( action_cb ) },
123    { "relocate-torrent", NULL, N_("Set _Location" ), NULL, NULL, G_CALLBACK( action_cb ) },
124    { "remove-torrent", GTK_STOCK_REMOVE, NULL, "Delete", N_( "Remove torrent" ), G_CALLBACK( action_cb ) },
125    { "delete-torrent", GTK_STOCK_DELETE, N_( "_Delete Files and Remove" ), "<shift>Delete", NULL, G_CALLBACK( action_cb ) },
126    { "new-torrent", GTK_STOCK_NEW, N_( "_New..." ), NULL, N_( "Create a torrent" ), G_CALLBACK( action_cb ) },
127    { "quit", GTK_STOCK_QUIT, N_( "_Quit" ), NULL, NULL, G_CALLBACK( action_cb ) },
128    { "select-all", GTK_STOCK_SELECT_ALL, N_( "Select _All" ), "<control>A", NULL, G_CALLBACK( action_cb ) },
129    { "deselect-all", NULL, N_( "Dese_lect All" ), "<shift><control>A", NULL, G_CALLBACK( action_cb ) },
130    { "edit-preferences", GTK_STOCK_PREFERENCES, NULL, NULL, NULL, G_CALLBACK( action_cb ) },
131    { "show-torrent-properties", GTK_STOCK_PROPERTIES, NULL, "<alt>Return", N_( "Torrent properties" ), G_CALLBACK( action_cb ) },
132    { "open-torrent-folder",  GTK_STOCK_OPEN, N_( "_Open Folder" ), NULL, NULL, G_CALLBACK( action_cb ) },
133    { "show-about-dialog", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK( action_cb ) },
134    { "help", GTK_STOCK_HELP, N_( "_Contents" ), "F1", NULL, G_CALLBACK( action_cb ) },
135    { "update-tracker", GTK_STOCK_NETWORK, N_( "Ask Tracker for _More Peers" ), NULL, NULL, G_CALLBACK( action_cb ) },
136    { "present-main-window", NULL, NULL, NULL, NULL, G_CALLBACK( action_cb ) },
137};
138
139typedef struct
140{
141    const guint8*   raw;
142    const char *    name;
143}
144BuiltinIconInfo;
145
146static const BuiltinIconInfo my_fallback_icons[] =
147{
148    { tr_icon_logo_48, WINDOW_ICON         },
149    { tr_icon_logo_24, TRAY_ICON           },
150    { tr_icon_logo_48, NOTIFICATION_ICON   },
151    { tr_icon_lock,   "transmission-lock" },
152    { options_icon,   "options"           },
153    { blue_turtle,    "alt-speed-on"      },
154    { grey_turtle,    "alt-speed-off"     },
155    { ratio_icon,     "ratio"             }
156};
157
158static void
159register_my_icons( void )
160{
161    int              i;
162    const int        n = G_N_ELEMENTS( my_fallback_icons );
163    GtkIconFactory * factory = gtk_icon_factory_new( );
164    GtkIconTheme *   theme = gtk_icon_theme_get_default( );
165
166    gtk_icon_factory_add_default( factory );
167
168    for( i = 0; i < n; ++i )
169    {
170        const char * name = my_fallback_icons[i].name;
171
172        if( !gtk_icon_theme_has_icon( theme, name ) )
173        {
174            int          width;
175            GdkPixbuf *  p;
176            GtkIconSet * icon_set;
177
178            p =
179                gdk_pixbuf_new_from_inline( -1, my_fallback_icons[i].raw,
180                                            FALSE,
181                                            NULL );
182            width = gdk_pixbuf_get_width( p );
183            icon_set = gtk_icon_set_new_from_pixbuf( p );
184            gtk_icon_theme_add_builtin_icon( name, width, p );
185            gtk_icon_factory_add( factory, name, icon_set );
186
187            g_object_unref( p );
188            gtk_icon_set_unref( icon_set );
189        }
190    }
191
192    g_object_unref ( G_OBJECT ( factory ) );
193}
194
195static GtkUIManager * myUIManager = NULL;
196
197void
198actions_set_core( TrCore * core )
199{
200    myCore = core;
201}
202
203void
204actions_init( GtkUIManager * ui_manager,
205              gpointer       callback_user_data )
206{
207    int              i, n;
208    int              active;
209    const char *     match;
210    const int        n_entries = G_N_ELEMENTS( entries );
211    GtkActionGroup * action_group;
212
213    myUIManager = ui_manager;
214
215    register_my_icons( );
216
217    action_group = myGroup = gtk_action_group_new( "Actions" );
218    gtk_action_group_set_translation_domain( action_group, NULL );
219
220
221    match = pref_string_get( PREF_KEY_SORT_MODE );
222    for( i = 0, n = G_N_ELEMENTS( sort_radio_entries ), active = -1;
223         active == -1 && i < n; ++i )
224        if( !strcmp( sort_radio_entries[i].name, match ) )
225            active = i;
226
227    gtk_action_group_add_radio_actions( action_group,
228                                        sort_radio_entries,
229                                        G_N_ELEMENTS( sort_radio_entries ),
230                                        active,
231                                        G_CALLBACK( sort_changed_cb ),
232                                        NULL );
233
234    gtk_action_group_add_toggle_actions( action_group,
235                                         show_toggle_entries,
236                                         G_N_ELEMENTS( show_toggle_entries ),
237                                         callback_user_data );
238
239    for( i = 0, n = G_N_ELEMENTS( pref_toggle_entries ); i < n; ++i )
240        pref_toggle_entries[i].is_active =
241            pref_flag_get( pref_toggle_entries[i].name );
242
243    gtk_action_group_add_toggle_actions( action_group,
244                                         pref_toggle_entries,
245                                         G_N_ELEMENTS( pref_toggle_entries ),
246                                         callback_user_data );
247
248    gtk_action_group_add_actions( action_group,
249                                  entries, n_entries,
250                                  callback_user_data );
251
252    gtk_ui_manager_insert_action_group( ui_manager, action_group, 0 );
253    g_object_unref ( G_OBJECT( action_group ) );
254}
255
256/****
257*****
258****/
259
260static GHashTable * key_to_action = NULL;
261
262static void
263ensure_action_map_loaded( GtkUIManager * uim )
264{
265    GList * l;
266
267    if( key_to_action != NULL )
268        return;
269
270    key_to_action =
271        g_hash_table_new_full( g_str_hash, g_str_equal, g_free, NULL );
272
273    for( l = gtk_ui_manager_get_action_groups( uim ); l != NULL;
274         l = l->next )
275    {
276        GtkActionGroup * action_group = GTK_ACTION_GROUP( l->data );
277        GList *          ait, *actions = gtk_action_group_list_actions(
278            action_group );
279        for( ait = actions; ait != NULL; ait = ait->next )
280        {
281            GtkAction *  action = GTK_ACTION( ait->data );
282            const char * name = gtk_action_get_name( action );
283            g_hash_table_insert( key_to_action, g_strdup( name ), action );
284        }
285        g_list_free( actions );
286    }
287}
288
289static GtkAction*
290get_action( const char* name )
291{
292    ensure_action_map_loaded( myUIManager );
293    return ( GtkAction* ) g_hash_table_lookup( key_to_action, name );
294}
295
296void
297action_activate( const char * name )
298{
299    GtkAction * action = get_action( name );
300
301    g_assert( action != NULL );
302    gtk_action_activate( action );
303}
304
305void
306action_sensitize( const char * name,
307                  gboolean     b )
308{
309    GtkAction * action = get_action( name );
310
311    g_assert( action != NULL );
312    g_object_set( action, "sensitive", b, NULL );
313}
314
315void
316action_set_important( const char * name, gboolean b )
317{
318    GtkAction * action = get_action( name );
319
320    g_assert( action != NULL );
321    g_object_set( action, "is-important", b, NULL );
322}
323
324void
325action_toggle( const char * name,
326               gboolean     b )
327{
328    GtkAction * action = get_action( name );
329
330    gtk_toggle_action_set_active( GTK_TOGGLE_ACTION( action ), b );
331}
332
333GtkWidget*
334action_get_widget( const char * path )
335{
336    return gtk_ui_manager_get_widget( myUIManager, path );
337}
338
Note: See TracBrowser for help on using the repository browser.