~ubuntu-branches/ubuntu/maverick/nautilus-actions/maverick

« back to all changes in this revision

Viewing changes to src/nact/nact-assistant.c

  • Committer: Bazaar Package Importer
  • Author(s): Christine Spang
  • Date: 2009-10-25 14:04:13 UTC
  • mfrom: (1.1.7 upstream) (3.1.5 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091025140413-okqdth1kvcx8ko3o
Tags: 2.29.1-1
* New upstream version.
  - implements full API as defined for use by Nautilus menu
    extensions : this let the user define items which will be
    available when there is no selection, and will apply to
    current folder, either in the 'File' menu or in the
    toolbar ;
  - the ability for the user to define a full hierarchy of
    actions with menus, submenus, and so on ;
  - drag and drop ;
  - full cut/copy/paste clipboard support.
  - Gnome bugs fixed:
    - #325528 reported by Frederic Ruaudel
              (bloated  contextual menu)
    - #325587 reported by Frederic Ruaudel
              (drag & drop support)
    - #326699 reported by Frederic Ruaudel
              (action items do not remain in user defined order)
    - #353353 reported by Frederic Ruaudel
              (check if command exist and if not warn user)
    - #588482 reported by Sean
            (ordering in actions list)
    - #326699 reported by Frederic Ruaudel
            (action items do not remain in user defined order)
    - #353353 reported by Frederic Ruaudel
              (check if command exist and if not warn user)
    - #588482 reported by Sean
              (ordering in actions list)
    - #590400 reported by Pierre Wieser
              (have some sort of warnings in the ui)
    - #599520 reported by António Lima
              (do not mark authors names and emails for translating)

Show diffs side-by-side

added added

removed removed

Lines of Context:
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, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
7
 
 * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
8
 
 *
9
 
 * This Program 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
 
 * This Program 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
17
 
 * GNU General Public License for more details.
18
 
 *
19
 
 * You should have received a copy of the GNU General Public
20
 
 * License along with this Library; see the file COPYING.  If not,
21
 
 * write to the Free Software Foundation, Inc., 59 Temple Place,
22
 
 * Suite 330, Boston, MA 02111-1307, USA.
23
 
 *
24
 
 * Authors:
25
 
 *   Frederic Ruaudel <grumz@grumz.net>
26
 
 *   Rodrigo Moya <rodrigo@gnome-db.org>
27
 
 *   Pierre Wieser <pwieser@trychlos.org>
28
 
 *   ... and many others (see AUTHORS)
29
 
 */
30
 
 
31
 
#ifdef HAVE_CONFIG_H
32
 
#include <config.h>
33
 
#endif
34
 
 
35
 
#include <gdk/gdkkeysyms.h>
36
 
#include <glib.h>
37
 
#include <glib/gi18n.h>
38
 
 
39
 
#include "base-application.h"
40
 
#include "nact-assistant.h"
41
 
 
42
 
/* private class data
43
 
 */
44
 
struct NactAssistantClassPrivate {
45
 
};
46
 
 
47
 
/* private instance data
48
 
 */
49
 
struct NactAssistantPrivate {
50
 
        gboolean dispose_has_run;
51
 
        gboolean warn_on_cancel;
52
 
};
53
 
 
54
 
/* instance properties
55
 
 */
56
 
enum {
57
 
        PROP_ASSIST_WARN_ON_CANCEL = 1
58
 
};
59
 
 
60
 
#define PROP_ASSIST_WARN_ON_CANCEL_STR          "nact-assist-warn-on-cancel"
61
 
 
62
 
static GObjectClass *st_parent_class = NULL;
63
 
 
64
 
static GType    register_type( void );
65
 
static void     class_init( NactAssistantClass *klass );
66
 
static void     instance_init( GTypeInstance *instance, gpointer klass );
67
 
static void     instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
68
 
static void     instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
69
 
static void     instance_dispose( GObject *application );
70
 
static void     instance_finalize( GObject *application );
71
 
 
72
 
static GtkWindow * get_dialog( BaseWindow *window, const gchar *name );
73
 
 
74
 
static void     v_assistant_apply( GtkAssistant *assistant, gpointer user_data );
75
 
static void     v_assistant_cancel( GtkAssistant *assistant, gpointer user_data );
76
 
static void     v_assistant_close( GtkAssistant *assistant, gpointer user_data );
77
 
static void     v_assistant_prepare( GtkAssistant *assistant, GtkWidget *page, gpointer user_data );
78
 
 
79
 
static void     on_runtime_init_toplevel( BaseWindow *window );
80
 
static gboolean on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, gpointer user_data );
81
 
static gboolean on_escape_key_pressed( GtkWidget *widget, GdkEventKey *event, gpointer user_data );
82
 
static void     do_assistant_apply( NactAssistant *window, GtkAssistant *assistant );
83
 
static void     do_assistant_cancel( NactAssistant *window, GtkAssistant *assistant );
84
 
static void     do_assistant_close( NactAssistant *window, GtkAssistant *assistant );
85
 
static void     do_assistant_prepare( NactAssistant *window, GtkAssistant *assistant, GtkWidget *page );
86
 
 
87
 
GType
88
 
nact_assistant_get_type( void )
89
 
{
90
 
        static GType window_type = 0;
91
 
 
92
 
        if( !window_type ){
93
 
                window_type = register_type();
94
 
        }
95
 
 
96
 
        return( window_type );
97
 
}
98
 
 
99
 
static GType
100
 
register_type( void )
101
 
{
102
 
        static const gchar *thisfn = "nact_assistant_register_type";
103
 
        g_debug( "%s", thisfn );
104
 
 
105
 
        g_type_init();
106
 
 
107
 
        static GTypeInfo info = {
108
 
                sizeof( NactAssistantClass ),
109
 
                ( GBaseInitFunc ) NULL,
110
 
                ( GBaseFinalizeFunc ) NULL,
111
 
                ( GClassInitFunc ) class_init,
112
 
                NULL,
113
 
                NULL,
114
 
                sizeof( NactAssistant ),
115
 
                0,
116
 
                ( GInstanceInitFunc ) instance_init
117
 
        };
118
 
 
119
 
        GType type = g_type_register_static( NACT_WINDOW_TYPE, "NactAssistant", &info, 0 );
120
 
 
121
 
        return( type );
122
 
}
123
 
 
124
 
static void
125
 
class_init( NactAssistantClass *klass )
126
 
{
127
 
        static const gchar *thisfn = "nact_assistant_class_init";
128
 
        g_debug( "%s: klass=%p", thisfn, klass );
129
 
 
130
 
        st_parent_class = g_type_class_peek_parent( klass );
131
 
 
132
 
        GObjectClass *object_class = G_OBJECT_CLASS( klass );
133
 
        object_class->dispose = instance_dispose;
134
 
        object_class->finalize = instance_finalize;
135
 
        object_class->get_property = instance_get_property;
136
 
        object_class->set_property = instance_set_property;
137
 
 
138
 
        GParamSpec *spec;
139
 
        spec = g_param_spec_boolean(
140
 
                        PROP_ASSIST_WARN_ON_CANCEL_STR,
141
 
                        PROP_ASSIST_WARN_ON_CANCEL_STR,
142
 
                        "Does the user should confirm when exiting the assistant ?", FALSE,
143
 
                        G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
144
 
        g_object_class_install_property( object_class, PROP_ASSIST_WARN_ON_CANCEL, spec );
145
 
 
146
 
        klass->private = g_new0( NactAssistantClassPrivate, 1 );
147
 
 
148
 
        BaseWindowClass *base_class = BASE_WINDOW_CLASS( klass );
149
 
        base_class->get_dialog = get_dialog;
150
 
        base_class->runtime_init_toplevel = on_runtime_init_toplevel;
151
 
 
152
 
        klass->on_escape_key_pressed = on_escape_key_pressed;
153
 
        klass->on_assistant_apply = do_assistant_apply;
154
 
        klass->on_assistant_close = do_assistant_close;
155
 
        klass->on_assistant_cancel = do_assistant_cancel;
156
 
        klass->on_assistant_prepare = do_assistant_prepare;
157
 
}
158
 
 
159
 
static void
160
 
instance_init( GTypeInstance *instance, gpointer klass )
161
 
{
162
 
        static const gchar *thisfn = "nact_assistant_instance_init";
163
 
        g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );
164
 
 
165
 
        g_assert( NACT_IS_ASSISTANT( instance ));
166
 
        NactAssistant *self = NACT_ASSISTANT( instance );
167
 
 
168
 
        self->private = g_new0( NactAssistantPrivate, 1 );
169
 
 
170
 
        self->private->dispose_has_run = FALSE;
171
 
}
172
 
 
173
 
static void
174
 
instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
175
 
{
176
 
        g_assert( NACT_IS_ASSISTANT( object ));
177
 
        NactAssistant *self = NACT_ASSISTANT( object );
178
 
 
179
 
        switch( property_id ){
180
 
                case PROP_ASSIST_WARN_ON_CANCEL:
181
 
                        g_value_set_boolean( value, self->private->warn_on_cancel );
182
 
                        break;
183
 
 
184
 
                default:
185
 
                        G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
186
 
                        break;
187
 
        }
188
 
}
189
 
 
190
 
static void
191
 
instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
192
 
{
193
 
        g_assert( NACT_IS_ASSISTANT( object ));
194
 
        NactAssistant *self = NACT_ASSISTANT( object );
195
 
 
196
 
        switch( property_id ){
197
 
                case PROP_ASSIST_WARN_ON_CANCEL:
198
 
                        self->private->warn_on_cancel = g_value_get_boolean( value );
199
 
                        break;
200
 
 
201
 
                default:
202
 
                        G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
203
 
                        break;
204
 
        }
205
 
}
206
 
 
207
 
static void
208
 
instance_dispose( GObject *window )
209
 
{
210
 
        static const gchar *thisfn = "nact_assistant_instance_dispose";
211
 
        g_debug( "%s: window=%p", thisfn, window );
212
 
 
213
 
        g_assert( NACT_IS_ASSISTANT( window ));
214
 
        NactAssistant *self = NACT_ASSISTANT( window );
215
 
 
216
 
        if( !self->private->dispose_has_run ){
217
 
 
218
 
                self->private->dispose_has_run = TRUE;
219
 
 
220
 
                /* chain up to the parent class */
221
 
                G_OBJECT_CLASS( st_parent_class )->dispose( window );
222
 
        }
223
 
}
224
 
 
225
 
static void
226
 
instance_finalize( GObject *window )
227
 
{
228
 
        static const gchar *thisfn = "nact_assistant_instance_finalize";
229
 
        g_debug( "%s: window=%p", thisfn, window );
230
 
 
231
 
        g_assert( NACT_IS_ASSISTANT( window ));
232
 
        NactAssistant *self = ( NactAssistant * ) window;
233
 
 
234
 
        g_free( self->private );
235
 
 
236
 
        /* chain call to parent class */
237
 
        if( st_parent_class->finalize ){
238
 
                G_OBJECT_CLASS( st_parent_class )->finalize( window );
239
 
        }
240
 
}
241
 
 
242
 
/*
243
 
 * cf. http://bugzilla.gnome.org/show_bug.cgi?id=589746 against Gtk+ 2.16
244
 
 * a GtkFileChooseWidget embedded in a GtkAssistant is not displayed
245
 
 * when run more than once
246
 
 *
247
 
 * as a work-around, reload the XML ui each time we run an assistant !
248
 
 */
249
 
static GtkWindow *
250
 
get_dialog( BaseWindow *window, const gchar *name )
251
 
{
252
 
        GtkBuilder *builder = gtk_builder_new();
253
 
 
254
 
        BaseApplication *appli = base_window_get_application( window );
255
 
 
256
 
        gchar *fname = base_application_get_ui_filename( appli );
257
 
 
258
 
        gtk_builder_add_from_file( builder, fname, NULL );
259
 
 
260
 
        g_free( fname );
261
 
 
262
 
        GtkWindow *dialog = GTK_WINDOW( gtk_builder_get_object( builder, name ));
263
 
 
264
 
        return( dialog );
265
 
}
266
 
 
267
 
/**
268
 
 * Set 'warn on close' property.
269
 
 */
270
 
 
271
 
void
272
 
nact_assistant_set_warn_on_cancel( NactAssistant *window, gboolean warn )
273
 
{
274
 
        g_assert( NACT_IS_ASSISTANT( window ));
275
 
        g_object_set( G_OBJECT( window ), PROP_ASSIST_WARN_ON_CANCEL_STR, warn, NULL );
276
 
}
277
 
 
278
 
static void
279
 
v_assistant_apply( GtkAssistant *assistant, gpointer user_data )
280
 
{
281
 
        g_assert( NACT_IS_ASSISTANT( user_data ));
282
 
 
283
 
        if( NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_apply ){
284
 
                NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_apply( NACT_ASSISTANT( user_data ), assistant );
285
 
        } else {
286
 
                do_assistant_apply( NACT_ASSISTANT( user_data ), assistant );
287
 
        }
288
 
}
289
 
 
290
 
static void
291
 
v_assistant_cancel( GtkAssistant *assistant, gpointer user_data )
292
 
{
293
 
        g_assert( NACT_IS_ASSISTANT( user_data ));
294
 
 
295
 
        if( NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_cancel ){
296
 
                NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_cancel( NACT_ASSISTANT( user_data ), assistant );
297
 
        } else {
298
 
                do_assistant_cancel( NACT_ASSISTANT( user_data ), assistant );
299
 
        }
300
 
}
301
 
 
302
 
static void
303
 
v_assistant_close( GtkAssistant *assistant, gpointer user_data )
304
 
{
305
 
        g_assert( NACT_IS_ASSISTANT( user_data ));
306
 
 
307
 
        if( NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_close ){
308
 
                NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_close( NACT_ASSISTANT( user_data ), assistant );
309
 
        } else {
310
 
                do_assistant_close( NACT_ASSISTANT( user_data ), assistant );
311
 
        }
312
 
}
313
 
 
314
 
static void
315
 
v_assistant_prepare( GtkAssistant *assistant, GtkWidget *page, gpointer user_data )
316
 
{
317
 
        g_assert( NACT_IS_ASSISTANT( user_data ));
318
 
 
319
 
        if( NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_prepare ){
320
 
                NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_prepare( NACT_ASSISTANT( user_data ), assistant, page );
321
 
        } else {
322
 
                do_assistant_prepare( NACT_ASSISTANT( user_data ), assistant, page );
323
 
        }
324
 
}
325
 
 
326
 
static void
327
 
on_runtime_init_toplevel( BaseWindow *window )
328
 
{
329
 
        static const gchar *thisfn = "nact_assistant_on_runtime_init_toplevel";
330
 
 
331
 
        /* call parent class at the very beginning */
332
 
        if( BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel ){
333
 
                BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel( window );
334
 
        }
335
 
 
336
 
        g_debug( "%s: window=%p", thisfn, window );
337
 
        g_assert( NACT_IS_ASSISTANT( window ));
338
 
 
339
 
        GtkWindow *toplevel = base_window_get_toplevel_dialog( window );
340
 
        g_assert( GTK_IS_ASSISTANT( toplevel ));
341
 
 
342
 
        nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( toplevel ), "key-press-event", G_CALLBACK( on_key_pressed_event ));
343
 
        nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( toplevel ), "cancel", G_CALLBACK( v_assistant_cancel ));
344
 
        nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( toplevel ), "close", G_CALLBACK( v_assistant_close ));
345
 
        nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( toplevel ), "prepare", G_CALLBACK( v_assistant_prepare ));
346
 
        nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( toplevel ), "apply", G_CALLBACK( v_assistant_apply ));
347
 
 
348
 
        nact_assistant_set_warn_on_cancel( NACT_ASSISTANT( window ), TRUE );
349
 
}
350
 
 
351
 
static gboolean
352
 
on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
353
 
{
354
 
        /*static const gchar *thisfn = "nact_assistant_on_key_pressed_event";
355
 
        g_debug( "%s: widget=%p, event=%p, user_data=%p", thisfn, widget, event, user_data );*/
356
 
 
357
 
        gboolean stop = FALSE;
358
 
 
359
 
        if( event->keyval == GDK_Escape ){
360
 
                if( NACT_ASSISTANT_GET_CLASS( user_data )->on_escape_key_pressed ){
361
 
                        stop = NACT_ASSISTANT_GET_CLASS( user_data )->on_escape_key_pressed( widget, event, user_data );
362
 
                }
363
 
        }
364
 
 
365
 
        return( stop );
366
 
}
367
 
 
368
 
static gboolean
369
 
on_escape_key_pressed( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
370
 
{
371
 
        static const gchar *thisfn = "nact_assistant_on_escape_key_pressed";
372
 
        g_debug( "%s: widget=%p, event=%p, user_data=%p", thisfn, widget, event, user_data );
373
 
 
374
 
        GtkWindow *toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( user_data ));
375
 
        v_assistant_cancel( GTK_ASSISTANT( toplevel ), user_data );
376
 
 
377
 
        return( TRUE );
378
 
}
379
 
 
380
 
static void
381
 
do_assistant_apply( NactAssistant *window, GtkAssistant *assistant )
382
 
{
383
 
        static const gchar *thisfn = "nact_assistant_do_assistant_apply";
384
 
        g_debug( "%s: window=%p, assistant=%p", thisfn, window, assistant );
385
 
}
386
 
 
387
 
/*
388
 
 * the 'Cancel' button is clicked
389
 
 */
390
 
static void
391
 
do_assistant_cancel( NactAssistant *window, GtkAssistant *assistant )
392
 
{
393
 
        static const gchar *thisfn = "nact_assistant_do_assistant_cancel";
394
 
        g_debug( "%s: window=%p, assistant=%p", thisfn, window, assistant );
395
 
 
396
 
        gboolean ok = TRUE;
397
 
 
398
 
        if( window->private->warn_on_cancel ){
399
 
                gchar *first = g_strdup( _( "Are you sure you want to quit this assistant ?" ));
400
 
                ok = base_window_yesno_dlg( BASE_WINDOW( window ), GTK_MESSAGE_QUESTION, first, NULL );
401
 
                g_free( first );
402
 
        }
403
 
 
404
 
        if( ok ){
405
 
                do_assistant_close( window, assistant );
406
 
        }
407
 
}
408
 
 
409
 
static void
410
 
do_assistant_close( NactAssistant *window, GtkAssistant *assistant )
411
 
{
412
 
        static const gchar *thisfn = "nact_assistant_do_assistant_close";
413
 
        g_debug( "%s: window=%p, assistant=%p", thisfn, window, assistant );
414
 
 
415
 
        g_object_unref( window );
416
 
}
417
 
 
418
 
static void
419
 
do_assistant_prepare( NactAssistant *window, GtkAssistant *assistant, GtkWidget *page )
420
 
{
421
 
        static const gchar *thisfn = "nact_assistant_do_assistant_prepare";
422
 
        g_debug( "%s: window=%p, assistant=%p, page=%p", thisfn, window, assistant, page );
423
 
}