README: add deprecation notice
[nautilus-actions.git] / src / ui / fma-application.c
bloba8d9ec393bd96da7f0a6365a7e4bfa9a1d103612
1 /*
2 * FileManager-Actions
3 * A file-manager extension which offers configurable context menu actions.
5 * Copyright (C) 2005 The GNOME Foundation
6 * Copyright (C) 2006-2008 Frederic Ruaudel and others (see AUTHORS)
7 * Copyright (C) 2009-2015 Pierre Wieser and others (see AUTHORS)
9 * FileManager-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.
14 * FileManager-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.
19 * You should have received a copy of the GNU General Public License
20 * along with FileManager-Actions; see the file COPYING. If not, see
21 * <http://www.gnu.org/licenses/>.
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)
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
34 #include <glib/gi18n.h>
35 #include <libintl.h>
37 #include "api/fma-core-utils.h"
39 #include "core/fma-about.h"
41 #include "fma-application.h"
42 #include "fma-main-window.h"
43 #include "fma-menu.h"
45 /* private instance data
47 struct _FMAApplicationPrivate {
48 gboolean dispose_has_run;
50 const gchar *application_name; /* new: st_application_name localized version */
51 const gchar *description; /* new: st_description localized version */
52 const gchar *icon_name; /* new: icon name */
53 int argc;
54 GStrv argv;
55 int code;
57 FMAUpdater *updater;
58 FMAMainWindow *main_window;
61 static const gchar *st_application_name = N_( "FileManager-Actions Configuration Tool" );
62 static const gchar *st_description = N_( "A user interface to edit your own contextual actions" );
63 static const gchar *st_application_id = "org.gnome.filemanager-actions.ConfigurationTool";
65 static gboolean st_non_unique_opt = FALSE;
66 static gboolean st_version_opt = FALSE;
68 static GOptionEntry st_option_entries[] = {
69 { "non-unique", 'n', 0, G_OPTION_ARG_NONE, &st_non_unique_opt,
70 N_( "Set it to run multiple instances of the program [unique]" ), NULL },
71 { "version" , 'v', 0, G_OPTION_ARG_NONE, &st_version_opt,
72 N_( "Output the version number, and exit gracefully [no]" ), NULL },
73 { NULL }
76 static GtkApplicationClass *st_parent_class = NULL;
78 static GType register_type( void );
79 static void class_init( FMAApplicationClass *klass );
80 static void instance_init( GTypeInstance *instance, gpointer klass );
81 static void instance_dispose( GObject *application );
82 static void instance_finalize( GObject *application );
83 static void init_i18n( FMAApplication *application );
84 static gboolean init_gtk_args( FMAApplication *application );
85 static gboolean manage_options( FMAApplication *application );
86 static void application_startup( GApplication *application );
87 static void application_activate( GApplication *application );
88 static void application_open( GApplication *application, GFile **files, gint n_files, const gchar *hint );
90 GType
91 fma_application_get_type( void )
93 static GType application_type = 0;
95 if( !application_type ){
96 application_type = register_type();
99 return( application_type );
102 static GType
103 register_type( void )
105 static const gchar *thisfn = "fma_application_register_type";
106 GType type;
108 static GTypeInfo info = {
109 sizeof( FMAApplicationClass ),
110 ( GBaseInitFunc ) NULL,
111 ( GBaseFinalizeFunc ) NULL,
112 ( GClassInitFunc ) class_init,
113 NULL,
114 NULL,
115 sizeof( FMAApplication ),
117 ( GInstanceInitFunc ) instance_init
120 g_debug( "%s", thisfn );
122 type = g_type_register_static( GTK_TYPE_APPLICATION, "FMAApplication", &info, 0 );
124 return( type );
127 static void
128 class_init( FMAApplicationClass *klass )
130 static const gchar *thisfn = "fma_application_class_init";
132 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
134 st_parent_class = GTK_APPLICATION_CLASS( g_type_class_peek_parent( klass ));
136 G_OBJECT_CLASS( klass )->dispose = instance_dispose;
137 G_OBJECT_CLASS( klass )->finalize = instance_finalize;
139 G_APPLICATION_CLASS( klass )->startup = application_startup;
140 G_APPLICATION_CLASS( klass )->activate = application_activate;
141 G_APPLICATION_CLASS( klass )->open = application_open;
144 static void
145 instance_init( GTypeInstance *application, gpointer klass )
147 static const gchar *thisfn = "fma_application_instance_init";
148 FMAApplication *self;
150 g_return_if_fail( FMA_IS_APPLICATION( application ));
152 g_debug( "%s: application=%p (%s), klass=%p",
153 thisfn, ( void * ) application, G_OBJECT_TYPE_NAME( application ), ( void * ) klass );
155 self = FMA_APPLICATION( application );
157 self->private = g_new0( FMAApplicationPrivate, 1 );
159 self->private->dispose_has_run = FALSE;
162 static void
163 instance_dispose( GObject *application )
165 static const gchar *thisfn = "fma_application_instance_dispose";
166 FMAApplicationPrivate *priv;
168 g_return_if_fail( application && FMA_IS_APPLICATION( application ));
170 priv = FMA_APPLICATION( application )->private;
172 if( !priv->dispose_has_run ){
174 g_debug( "%s: application=%p (%s)", thisfn, ( void * ) application, G_OBJECT_TYPE_NAME( application ));
176 priv->dispose_has_run = TRUE;
178 if( priv->updater ){
179 g_clear_object( &priv->updater );
183 /* chain up to the parent class */
184 G_OBJECT_CLASS( st_parent_class )->dispose( application );
187 static void
188 instance_finalize( GObject *application )
190 static const gchar *thisfn = "fma_application_instance_finalize";
191 FMAApplication *self;
193 g_return_if_fail( FMA_IS_APPLICATION( application ));
195 g_debug( "%s: application=%p (%s)", thisfn, ( void * ) application, G_OBJECT_TYPE_NAME( application ));
197 self = FMA_APPLICATION( application );
199 g_free( self->private );
201 /* chain call to the parent class */
202 G_OBJECT_CLASS( st_parent_class )->finalize( application );
206 * fma_application_new:
208 * Returns: a newly allocated FMAApplication object.
210 FMAApplication *
211 fma_application_new( void )
213 FMAApplication *application;
214 FMAApplicationPrivate *priv;
216 application = g_object_new( FMA_TYPE_APPLICATION,
217 "application-id", st_application_id,
218 NULL );
220 priv = application->private;
221 priv->application_name = gettext( st_application_name );
222 priv->description = gettext( st_description );
223 priv->icon_name = fma_about_get_icon_name();
225 return( application );
229 * fma_application_run_with_args:
230 * @application: this #GtkApplication -derived instance.
231 * @argc:
232 * @argv:
234 * Starts and runs the application.
235 * Takes care of creating, initializing, and running the main window.
237 * All steps are implemented as virtual functions which provide some
238 * suitable defaults, and may be overriden by a derived class.
240 * Returns: an %int code suitable as an exit code for the program.
242 * Though it is defined as a virtual function itself, it should be very
243 * seldomly needed to override this in a derived class.
246 fma_application_run_with_args( FMAApplication *application, int argc, GStrv argv )
248 static const gchar *thisfn = "fma_application_run_with_args";
249 FMAApplicationPrivate *priv;
251 g_debug( "%s: application=%p (%s), argc=%d",
252 thisfn,
253 ( void * ) application, G_OBJECT_TYPE_NAME( application ),
254 argc );
256 g_return_val_if_fail( application && FMA_IS_APPLICATION( application ), FMA_EXIT_CODE_PROGRAM );
258 priv = application->private;
260 if( !priv->dispose_has_run ){
262 priv->argc = argc;
263 priv->argv = g_strdupv( argv );
264 priv->code = FMA_EXIT_CODE_OK;
266 init_i18n( application );
267 g_set_application_name( priv->application_name );
268 gtk_window_set_default_icon_name( priv->icon_name );
270 if( init_gtk_args( application ) &&
271 manage_options( application )){
273 g_debug( "%s: entering g_application_run", thisfn );
274 priv->code = g_application_run( G_APPLICATION( application ), 0, NULL );
278 return( priv->code );
282 * i18n initialization
284 * Returns: %TRUE to continue the execution, %FALSE to terminate the program.
285 * The program exit code will be taken from @code.
287 static void
288 init_i18n( FMAApplication *application )
290 static const gchar *thisfn = "fma_application_init_i18n";
292 g_debug( "%s: application=%p", thisfn, ( void * ) application );
294 #ifdef ENABLE_NLS
295 bindtextdomain( GETTEXT_PACKAGE, GNOMELOCALEDIR );
296 # ifdef HAVE_BIND_TEXTDOMAIN_CODESET
297 bind_textdomain_codeset( GETTEXT_PACKAGE, "UTF-8" );
298 # endif
299 textdomain( GETTEXT_PACKAGE );
300 #endif
304 * Pre-Gtk+ initialization
306 * Though GApplication has its own infrastructure to handle command-line
307 * arguments, it appears that it does not deal with Gtk+-specific arguments.
308 * We so have to explicitely call gtk_init_with_args() in order to let Gtk+
309 * "eat" its own arguments, and only have to handle our owns...
311 static gboolean
312 init_gtk_args( FMAApplication *application )
314 static const gchar *thisfn = "fma_application_init_gtk_args";
315 FMAApplicationPrivate *priv;
316 gboolean ret;
317 char *parameter_string;
318 GError *error;
320 g_debug( "%s: application=%p", thisfn, ( void * ) application );
322 priv = application->private;
324 parameter_string = g_strdup( g_get_application_name());
325 error = NULL;
326 ret = gtk_init_with_args(
327 &priv->argc,
328 ( char *** ) &priv->argv,
329 parameter_string,
330 st_option_entries,
331 GETTEXT_PACKAGE,
332 &error );
333 if( !ret ){
334 g_warning( "%s: %s", thisfn, error->message );
335 g_error_free( error );
336 ret = FALSE;
337 priv->code = FMA_EXIT_CODE_ARGS;
339 g_free( parameter_string );
341 return( ret );
344 static gboolean
345 manage_options( FMAApplication *application )
347 static const gchar *thisfn = "fma_application_manage_options";
348 gboolean ret;
350 g_debug( "%s: application=%p", thisfn, ( void * ) application );
352 ret = TRUE;
354 /* display the program version ?
355 * if yes, then stops here, exiting with code ok
357 if( st_version_opt ){
358 fma_core_utils_print_version();
359 ret = FALSE;
362 /* run the application as non-unique ?
364 if( ret && st_non_unique_opt ){
365 g_application_set_flags( G_APPLICATION( application ), G_APPLICATION_NON_UNIQUE );
368 return( ret );
372 * https://wiki.gnome.org/HowDoI/GtkApplication
374 * Invoked on the primary instance immediately after registration.
376 * When your application starts, the startup signal will be fired. This
377 * gives you a chance to perform initialisation tasks that are not
378 * directly related to showing a new window. After this, depending on
379 * how the application is started, either activate or open will be called
380 * next.
382 * GtkApplication defaults to applications being single-instance. If the
383 * user attempts to start a second instance of a single-instance
384 * application then GtkApplication will signal the first instance and
385 * you will receive additional activate or open signals. In this case,
386 * the second instance will exit immediately, without calling startup
387 * or shutdown.
389 * For this reason, you should do essentially no work at all from main().
390 * All startup initialisation should be done in startup. This avoids
391 * wasting work in the second-instance case where the program just exits
392 * immediately.
394 static void
395 application_startup( GApplication *application )
397 static const gchar *thisfn = "fma_application_startup";
398 FMAApplicationPrivate *priv;
400 g_debug( "%s: application=%p", thisfn, ( void * ) application );
402 g_return_if_fail( application && FMA_IS_APPLICATION( application ));
403 priv = FMA_APPLICATION( application )->private;
405 /* chain up to the parent class */
406 if( G_APPLICATION_CLASS( st_parent_class )->startup ){
407 G_APPLICATION_CLASS( st_parent_class )->startup( application );
410 /* create the FMAPivot object (loading the plugins and so on)
411 * after having dealt with command-line arguments
413 priv->updater = fma_updater_new();
414 fma_pivot_set_loadable( FMA_PIVOT( priv->updater ), PIVOT_LOAD_ALL );
416 /* define the application menu */
417 fma_menu_app( FMA_APPLICATION( application ));
421 * https://wiki.gnome.org/Projects/GLib/GApplication/Introduction
422 * https://wiki.gnome.org/HowDoI/GtkApplication
424 * activate is executed by GApplication when the application is "activated".
425 * This corresponds to the program being run from the command line, or when
426 * its icon is clicked on in an application launcher.
427 * From a semantic standpoint, activate should usually do one of two things,
428 * depending on the type of application.
430 * If your application is the type of application that deals with several
431 * documents at a time, in separate windows (and/or tabs) then activate
432 * should involve showing a window or creating a tab for a new document.
434 * If your application is more like the type of application with one primary
435 * main window then activate should usually involve raising this window with
436 * gtk_window_present(). It is the choice of the application in this case if
437 * the window itself is constructed in startup or on the first execution of
438 * activate.
440 * activate is potentially called many times in a process or maybe never.
441 * If the process is started without files to open then activate will be run
442 * after startup. It may also be run again if a second instance of the
443 * process is started.
445 static void
446 application_activate( GApplication *application )
448 static const gchar *thisfn = "fma_application_activate";
449 FMAApplicationPrivate *priv;
450 GList *windows_list;
451 FMAMainWindow *main_window;
453 g_debug( "%s: application=%p", thisfn, ( void * ) application );
455 g_return_if_fail( application && FMA_IS_APPLICATION( application ));
457 priv = FMA_APPLICATION( application )->private;
458 windows_list = gtk_application_get_windows( GTK_APPLICATION( application ));
460 /* if the application is unique, have only one main window */
461 if( !st_non_unique_opt ){
462 if( !g_list_length( windows_list )){
463 main_window = fma_main_window_new( FMA_APPLICATION( application ));
464 g_debug( "%s: main window instanciated at %p", thisfn, main_window );
465 } else {
466 main_window = ( FMAMainWindow * ) windows_list->data;
469 /* have as many main windows we want */
470 } else {
471 main_window = fma_main_window_new( FMA_APPLICATION( application ));
474 g_return_if_fail( main_window && FMA_IS_MAIN_WINDOW( main_window ));
476 priv->main_window = main_window;
478 gtk_window_present( GTK_WINDOW( main_window ));
482 * https://wiki.gnome.org/Projects/GLib/GApplication/Introduction
484 * open is similar to activate, but it is used when some files have been
485 * passed to the application to open.
486 * In fact, you could think of activate as a special case of open: the
487 * one with zero files.
488 * Similar to activate, open should create a window or tab. It should
489 * open the file in this window. If multiple files are given, possibly
490 * several windows should be opened.
491 * open will only be invoked in the case that your application declares
492 * that it supports opening files with the G_APPLICATION_HANDLES_OPEN
493 * GApplicationFlag.
495 * Openbook: as the G_APPLICATION_HANDLES_OPEN flag is not set, then
496 * this function should never be called.
498 static void
499 application_open( GApplication *application, GFile **files, gint n_files, const gchar *hint )
501 static const gchar *thisfn = "fma_application_open";
503 g_warning( "%s: application=%p, n_files=%d, hint=%s: unexpected run here",
504 thisfn, ( void * ) application, n_files, hint );
508 * fma_application_get_application_name:
509 * @application: this #FMAApplication instance.
511 * Returns: the application name as a newly allocated string which should
512 * be be g_free() by the caller.
514 gchar *
515 fma_application_get_application_name( const FMAApplication *application )
517 FMAApplicationPrivate *priv;
518 gchar *name = NULL;
520 g_return_val_if_fail( application && FMA_IS_APPLICATION( application ), NULL );
522 priv = application->private;
524 if( !priv->dispose_has_run ){
526 name = g_strdup( priv->application_name );
529 return( name );
533 * fma_application_get_updater:
534 * @application: this FMAApplication object.
536 * Returns a pointer on the #FMAUpdater object.
538 * The returned pointer is owned by the #FMAApplication object.
539 * It should not be g_free() not g_object_unref() by the caller.
541 FMAUpdater *
542 fma_application_get_updater( const FMAApplication *application )
544 FMAApplicationPrivate *priv;
545 FMAUpdater *updater = NULL;
547 g_return_val_if_fail( application && FMA_IS_APPLICATION( application ), NULL );
549 priv = application->private;
551 if( !priv->dispose_has_run ){
553 updater = priv->updater;
556 return( updater );
560 * fma_application_get_main_window:
561 * @application: this FMAApplication object.
563 * Returns: the main window.
565 GtkWindow *
566 fma_application_get_main_window( FMAApplication *application )
568 FMAApplicationPrivate *priv;
570 g_return_val_if_fail( application && FMA_IS_APPLICATION( application ), NULL );
572 priv = application->private;
574 if( !priv->dispose_has_run ){
576 return( GTK_WINDOW( priv->main_window ));
579 return( NULL );