1 /*
2 * Nautilus-Actions
3 * A Nautilus extension which offers configurable context menu actions.
4 *
5 * Copyright (C) 2005 The GNOME Foundation
6 * Copyright (C) 2006-2008 Frederic Ruaudel and others (see AUTHORS)
7 * Copyright (C) 2009-2014 Pierre Wieser and others (see AUTHORS)
8 *
9 * Nautilus-Actions is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * Nautilus-Actions is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Nautilus-Actions; see the file COPYING. If not, see
21 * <http://www.gnu.org/licenses/>.
22 *
23 * Authors:
24 * Frederic Ruaudel <grumz@grumz.net>
25 * Rodrigo Moya <rodrigo@gnome-db.org>
26 * Pierre Wieser <pwieser@trychlos.org>
27 * ... and many others (see AUTHORS)
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <string.h>
35
36 #include <api/na-object-api.h>
37
38 #include "base-gtk-utils.h"
39 #include "nact-main-tab.h"
40 #include "nact-iexecution-tab.h"
41
42 /* private interface data
43 */
44 struct _NactIExecutionTabInterfacePrivate {
45 void *empty; /* so that gcc -pedantic is happy */
46 };
47
48 /* data set against the instance
49 */
50 typedef struct {
51 gboolean on_selection_change;
52 }
53 IExecutionData;
54
55 #define IEXECUTION_TAB_PROP_DATA "nact-iexecution-tab-data"
56
57 static guint st_initializations = 0; /* interface initialization count */
58
59 static GType register_type( void );
60 static void interface_base_init( NactIExecutionTabInterface *klass );
61 static void interface_base_finalize( NactIExecutionTabInterface *klass );
62
63 static void on_base_initialize_window( NactIExecutionTab *instance, gpointer user_data );
64
65 static void on_main_selection_changed( NactIExecutionTab *instance, GList *selected_items, gpointer user_data );
66
67 static void on_normal_mode_toggled( GtkToggleButton *togglebutton, NactIExecutionTab *instance );
68 static void on_terminal_mode_toggled( GtkToggleButton *togglebutton, NactIExecutionTab *instance );
69 static void on_embedded_mode_toggled( GtkToggleButton *togglebutton, NactIExecutionTab *instance );
70 static void on_display_mode_toggled( GtkToggleButton *togglebutton, NactIExecutionTab *instance );
71 static void execution_mode_toggle( NactIExecutionTab *instance, GtkToggleButton *togglebutton, GCallback cb, const gchar *mode );
72 static void on_startup_notify_toggled( GtkToggleButton *togglebutton, NactIExecutionTab *instance );
73 static void on_startup_class_changed( GtkEntry *entry, NactIExecutionTab *instance );
74 static void on_execute_as_changed( GtkEntry *entry, NactIExecutionTab *instance );
75
76 static IExecutionData *get_iexecution_data( NactIExecutionTab *instance );
77 static void on_instance_finalized( gpointer user_data, NactIExecutionTab *instance );
78
79 GType
nact_iexecution_tab_get_type(void)80 nact_iexecution_tab_get_type( void )
81 {
82 static GType iface_type = 0;
83
84 if( !iface_type ){
85 iface_type = register_type();
86 }
87
88 return( iface_type );
89 }
90
91 static GType
register_type(void)92 register_type( void )
93 {
94 static const gchar *thisfn = "nact_iexecution_tab_register_type";
95 GType type;
96
97 static const GTypeInfo info = {
98 sizeof( NactIExecutionTabInterface ),
99 ( GBaseInitFunc ) interface_base_init,
100 ( GBaseFinalizeFunc ) interface_base_finalize,
101 NULL,
102 NULL,
103 NULL,
104 0,
105 0,
106 NULL
107 };
108
109 g_debug( "%s", thisfn );
110
111 type = g_type_register_static( G_TYPE_INTERFACE, "NactIExecutionTab", &info, 0 );
112
113 g_type_interface_add_prerequisite( type, BASE_TYPE_WINDOW );
114
115 return( type );
116 }
117
118 static void
interface_base_init(NactIExecutionTabInterface * klass)119 interface_base_init( NactIExecutionTabInterface *klass )
120 {
121 static const gchar *thisfn = "nact_iexecution_tab_interface_base_init";
122
123 if( !st_initializations ){
124
125 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
126
127 klass->private = g_new0( NactIExecutionTabInterfacePrivate, 1 );
128 }
129
130 st_initializations += 1;
131 }
132
133 static void
interface_base_finalize(NactIExecutionTabInterface * klass)134 interface_base_finalize( NactIExecutionTabInterface *klass )
135 {
136 static const gchar *thisfn = "nact_iexecution_tab_interface_base_finalize";
137
138 st_initializations -= 1;
139
140 if( !st_initializations ){
141
142 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
143
144 g_free( klass->private );
145 }
146 }
147
148 /**
149 * nact_iexecution_tab_init:
150 * @instance: this #NactIExecutionTab instance.
151 *
152 * Initialize the interface
153 * Connect to #BaseWindow signals
154 */
155 void
nact_iexecution_tab_init(NactIExecutionTab * instance)156 nact_iexecution_tab_init( NactIExecutionTab *instance )
157 {
158 static const gchar *thisfn = "nact_iexecution_tab_init";
159 IExecutionData *data;
160
161 g_return_if_fail( NACT_IS_IEXECUTION_TAB( instance ));
162
163 g_debug( "%s: instance=%p (%s)",
164 thisfn,
165 ( void * ) instance, G_OBJECT_TYPE_NAME( instance ));
166
167 base_window_signal_connect(
168 BASE_WINDOW( instance ),
169 G_OBJECT( instance ),
170 BASE_SIGNAL_INITIALIZE_WINDOW,
171 G_CALLBACK( on_base_initialize_window ));
172
173 nact_main_tab_init( NACT_MAIN_WINDOW( instance ), TAB_EXECUTION );
174
175 data = get_iexecution_data( instance );
176 data->on_selection_change = FALSE;
177
178 g_object_weak_ref( G_OBJECT( instance ), ( GWeakNotify ) on_instance_finalized, NULL );
179 }
180
181 /*
182 * on_base_initialize_window:
183 * @window: this #NactIExecutionTab instance.
184 *
185 * Initializes the tab widget at each time the widget will be displayed.
186 * Connect signals and setup runtime values.
187 */
188 static void
on_base_initialize_window(NactIExecutionTab * instance,void * user_data)189 on_base_initialize_window( NactIExecutionTab *instance, void *user_data )
190 {
191 static const gchar *thisfn = "nact_iexecution_tab_on_base_initialize_window";
192
193 g_return_if_fail( NACT_IS_IEXECUTION_TAB( instance ));
194
195 g_debug( "%s: instance=%p (%s), user_data=%p",
196 thisfn,
197 ( void * ) instance, G_OBJECT_TYPE_NAME( instance ),
198 ( void * ) user_data );
199
200 base_window_signal_connect(
201 BASE_WINDOW( instance ),
202 G_OBJECT( instance ),
203 MAIN_SIGNAL_SELECTION_CHANGED,
204 G_CALLBACK( on_main_selection_changed ));
205
206 base_window_signal_connect_by_name(
207 BASE_WINDOW( instance ),
208 "ExecutionModeNormal",
209 "toggled",
210 G_CALLBACK( on_normal_mode_toggled ));
211
212 base_window_signal_connect_by_name(
213 BASE_WINDOW( instance ),
214 "ExecutionModeTerminal",
215 "toggled",
216 G_CALLBACK( on_terminal_mode_toggled ));
217
218 base_window_signal_connect_by_name(
219 BASE_WINDOW( instance ),
220 "ExecutionModeEmbedded",
221 "toggled",
222 G_CALLBACK( on_embedded_mode_toggled ));
223
224 base_window_signal_connect_by_name(
225 BASE_WINDOW( instance ),
226 "ExecutionModeDisplayOutput",
227 "toggled",
228 G_CALLBACK( on_display_mode_toggled ));
229
230 base_window_signal_connect_by_name(
231 BASE_WINDOW( instance ),
232 "StartupNotifyButton",
233 "toggled",
234 G_CALLBACK( on_startup_notify_toggled ));
235
236 base_window_signal_connect_by_name(
237 BASE_WINDOW( instance ),
238 "StartupWMClassEntry",
239 "changed",
240 G_CALLBACK( on_startup_class_changed ));
241
242 base_window_signal_connect_by_name(
243 BASE_WINDOW( instance ),
244 "ExecuteAsEntry",
245 "changed",
246 G_CALLBACK( on_execute_as_changed ));
247 }
248
249 static void
on_main_selection_changed(NactIExecutionTab * instance,GList * selected_items,gpointer user_data)250 on_main_selection_changed( NactIExecutionTab *instance, GList *selected_items, gpointer user_data )
251 {
252 static const gchar *thisfn = "nact_iexecution_tab_on_main_selection_changed";
253 NAObjectProfile *profile;
254 gboolean editable;
255 gboolean enable_tab;
256 gchar *mode;
257 GtkWidget *normal_toggle, *terminal_toggle, *embedded_toggle, *display_toggle;
258 gboolean notify;
259 GtkWidget *notify_check, *frame;
260 gchar *class, *user;
261 GtkWidget *entry;
262 IExecutionData *data;
263
264 g_return_if_fail( NACT_IS_IEXECUTION_TAB( instance ));
265
266 g_debug( "%s: instance=%p (%s), selected_items=%p (count=%d)",
267 thisfn,
268 ( void * ) instance, G_OBJECT_TYPE_NAME( instance ),
269 ( void * ) selected_items, g_list_length( selected_items ));
270
271 g_object_get(
272 G_OBJECT( instance ),
273 MAIN_PROP_PROFILE, &profile,
274 MAIN_PROP_EDITABLE, &editable,
275 NULL );
276
277 enable_tab = ( profile != NULL );
278 nact_main_tab_enable_page( NACT_MAIN_WINDOW( instance ), TAB_EXECUTION, enable_tab );
279
280 data = get_iexecution_data( instance );
281 data->on_selection_change = TRUE;
282
283 normal_toggle = base_window_get_widget( BASE_WINDOW( instance ), "ExecutionModeNormal" );
284 terminal_toggle = base_window_get_widget( BASE_WINDOW( instance ), "ExecutionModeTerminal" );
285 embedded_toggle = base_window_get_widget( BASE_WINDOW( instance ), "ExecutionModeEmbedded" );
286 display_toggle = base_window_get_widget( BASE_WINDOW( instance ), "ExecutionModeDisplayOutput" );
287
288 mode = profile ? na_object_get_execution_mode( profile ) : g_strdup( "Normal" );
289 gtk_toggle_button_set_inconsistent( GTK_TOGGLE_BUTTON( normal_toggle ), profile == NULL );
290
291 if( !strcmp( mode, "Normal" )){
292 base_gtk_utils_radio_set_initial_state(
293 GTK_RADIO_BUTTON( normal_toggle ),
294 G_CALLBACK( on_normal_mode_toggled ), instance, editable, ( profile != NULL ));
295
296 } else if( !strcmp( mode, "Terminal" )){
297 base_gtk_utils_radio_set_initial_state(
298 GTK_RADIO_BUTTON( terminal_toggle ),
299 G_CALLBACK( on_terminal_mode_toggled ), instance, editable, ( profile != NULL ));
300
301 } else if( !strcmp( mode, "Embedded" )){
302 base_gtk_utils_radio_set_initial_state(
303 GTK_RADIO_BUTTON( embedded_toggle ),
304 G_CALLBACK( on_embedded_mode_toggled ), instance, editable, ( profile != NULL ));
305
306 } else if( !strcmp( mode, "DisplayOutput" )){
307 base_gtk_utils_radio_set_initial_state(
308 GTK_RADIO_BUTTON( display_toggle ),
309 G_CALLBACK( on_display_mode_toggled ), instance, editable, ( profile != NULL ));
310
311 } else {
312 g_warning( "%s: unable to setup execution mode '%s'", thisfn, mode );
313 }
314
315 g_free( mode );
316
317 frame = base_window_get_widget( BASE_WINDOW( instance ), "StartupModeFrame" );
318 gtk_widget_set_sensitive( frame, FALSE );
319
320 notify = profile ? na_object_get_startup_notify( profile ) : FALSE;
321 notify_check = base_window_get_widget( BASE_WINDOW( instance ), "StartupNotifyButton" );
322 base_gtk_utils_set_editable( G_OBJECT( notify_check ), editable );
323 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( notify_check ), notify );
324
325 class = profile ? na_object_get_startup_class( profile ) : g_strdup( "" );
326 entry = base_window_get_widget( BASE_WINDOW( instance ), "StartupWMClassEntry" );
327 gtk_entry_set_text( GTK_ENTRY( entry ), class );
328 base_gtk_utils_set_editable( G_OBJECT( entry ), editable );
329 g_free( class );
330
331 frame = base_window_get_widget( BASE_WINDOW( instance ), "UserFrame" );
332 gtk_widget_set_sensitive( frame, FALSE );
333
334 user = profile ? na_object_get_execute_as( profile ) : g_strdup( "" );
335 entry = base_window_get_widget( BASE_WINDOW( instance ), "ExecuteAsEntry" );
336 gtk_entry_set_text( GTK_ENTRY( entry ), user );
337 base_gtk_utils_set_editable( G_OBJECT( entry ), editable );
338 g_free( user );
339
340 data->on_selection_change = FALSE;
341 }
342
343 static void
on_normal_mode_toggled(GtkToggleButton * togglebutton,NactIExecutionTab * instance)344 on_normal_mode_toggled( GtkToggleButton *togglebutton, NactIExecutionTab *instance )
345 {
346 execution_mode_toggle( instance, togglebutton, G_CALLBACK( on_normal_mode_toggled ), "Normal" );
347 }
348
349 static void
on_terminal_mode_toggled(GtkToggleButton * togglebutton,NactIExecutionTab * instance)350 on_terminal_mode_toggled( GtkToggleButton *togglebutton, NactIExecutionTab *instance )
351 {
352 execution_mode_toggle( instance, togglebutton, G_CALLBACK( on_terminal_mode_toggled ), "Terminal" );
353 }
354
355 static void
on_embedded_mode_toggled(GtkToggleButton * togglebutton,NactIExecutionTab * instance)356 on_embedded_mode_toggled( GtkToggleButton *togglebutton, NactIExecutionTab *instance )
357 {
358 execution_mode_toggle( instance, togglebutton, G_CALLBACK( on_embedded_mode_toggled ), "Embedded" );
359 }
360
361 static void
on_display_mode_toggled(GtkToggleButton * togglebutton,NactIExecutionTab * instance)362 on_display_mode_toggled( GtkToggleButton *togglebutton, NactIExecutionTab *instance )
363 {
364 execution_mode_toggle( instance, togglebutton, G_CALLBACK( on_display_mode_toggled ), "DisplayOutput" );
365 }
366
367 static void
execution_mode_toggle(NactIExecutionTab * instance,GtkToggleButton * toggle_button,GCallback cb,const gchar * mode)368 execution_mode_toggle( NactIExecutionTab *instance, GtkToggleButton *toggle_button, GCallback cb, const gchar *mode )
369 {
370 NAObjectProfile *profile;
371 gboolean editable;
372 gboolean active;
373 gboolean is_normal;
374 GtkWidget *widget;
375
376 g_object_get(
377 G_OBJECT( instance ),
378 MAIN_PROP_PROFILE, &profile,
379 MAIN_PROP_EDITABLE, &editable,
380 NULL );
381
382 if( profile ){
383 active = gtk_toggle_button_get_active( toggle_button );
384
385 if( editable ){
386 if( active ){
387 na_object_set_execution_mode( profile, mode );
388
389 is_normal = ( strcmp( mode, "Normal" ) == 0 );
390 widget = base_window_get_widget( BASE_WINDOW( instance ), "StartupNotifyButton" );
391 gtk_widget_set_sensitive( widget, is_normal );
392 widget = base_window_get_widget( BASE_WINDOW( instance ), "StartupWMClassEntry" );
393 gtk_widget_set_sensitive( widget, is_normal );
394
395 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, profile, 0 );
396 }
397
398 } else {
399 base_gtk_utils_radio_reset_initial_state( GTK_RADIO_BUTTON( toggle_button ), cb );
400 }
401 }
402 }
403
404 static void
on_startup_notify_toggled(GtkToggleButton * toggle_button,NactIExecutionTab * instance)405 on_startup_notify_toggled( GtkToggleButton *toggle_button, NactIExecutionTab *instance )
406 {
407 NAObjectProfile *profile;
408 gboolean editable;
409 gboolean active;
410
411 g_object_get(
412 G_OBJECT( instance ),
413 MAIN_PROP_PROFILE, &profile,
414 MAIN_PROP_EDITABLE, &editable,
415 NULL );
416
417 if( profile ){
418 active = gtk_toggle_button_get_active( toggle_button );
419
420 if( editable ){
421 na_object_set_startup_notify( profile, active );
422 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, profile, 0 );
423
424 } else {
425 g_signal_handlers_block_by_func(( gpointer ) toggle_button, on_startup_notify_toggled, instance );
426 gtk_toggle_button_set_active( toggle_button, !active );
427 g_signal_handlers_unblock_by_func(( gpointer ) toggle_button, on_startup_notify_toggled, instance );
428 }
429 }
430 }
431
432 static void
on_startup_class_changed(GtkEntry * entry,NactIExecutionTab * instance)433 on_startup_class_changed( GtkEntry *entry, NactIExecutionTab *instance )
434 {
435 NAObjectProfile *profile;
436 const gchar *text;
437
438 g_object_get(
439 G_OBJECT( instance ),
440 MAIN_PROP_PROFILE, &profile,
441 NULL );
442
443 if( profile ){
444 text = gtk_entry_get_text( entry );
445 na_object_set_startup_class( profile, text );
446 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, profile, 0 );
447 }
448 }
449
450 static void
on_execute_as_changed(GtkEntry * entry,NactIExecutionTab * instance)451 on_execute_as_changed( GtkEntry *entry, NactIExecutionTab *instance )
452 {
453 NAObjectProfile *profile;
454 const gchar *text;
455
456 g_object_get(
457 G_OBJECT( instance ),
458 MAIN_PROP_PROFILE, &profile,
459 NULL );
460
461 if( profile ){
462 text = gtk_entry_get_text( entry );
463 na_object_set_execute_as( profile, text );
464 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, profile, 0 );
465 }
466 }
467
468 static IExecutionData *
get_iexecution_data(NactIExecutionTab * instance)469 get_iexecution_data( NactIExecutionTab *instance )
470 {
471 IExecutionData *data;
472
473 data = ( IExecutionData * ) g_object_get_data( G_OBJECT( instance ), IEXECUTION_TAB_PROP_DATA );
474
475 if( !data ){
476 data = g_new0( IExecutionData, 1 );
477 g_object_set_data( G_OBJECT( instance ), IEXECUTION_TAB_PROP_DATA, data );
478 }
479
480 return( data );
481 }
482
483 static void
on_instance_finalized(gpointer user_data,NactIExecutionTab * instance)484 on_instance_finalized( gpointer user_data, NactIExecutionTab *instance )
485 {
486 static const gchar *thisfn = "nact_iexecution_tab_on_instance_finalized";
487 IExecutionData *data;
488
489 g_debug( "%s: instance=%p, user_data=%p", thisfn, ( void * ) instance, ( void * ) user_data );
490
491 data = get_iexecution_data( instance );
492
493 g_free( data );
494 }
495