1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) 2000 Naba Kumar <naba@gnome.org>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <libanjuta/anjuta-shell.h>
26 #include <libanjuta/anjuta-debug.h>
27 #include <libanjuta/anjuta-utils.h>
28 #include <libanjuta/anjuta-save-prompt.h>
29 #include <libanjuta/anjuta-plugin-manager.h>
30 #include <libanjuta/resources.h>
31 #include <libanjuta/interfaces/ianjuta-file-loader.h>
32 #include <libanjuta/interfaces/ianjuta-file.h>
34 #include "anjuta-application.h"
36 #define ANJUTA_REMEMBERED_PLUGINS "remembered-plugins"
37 #define USER_SESSION_PATH_NEW (anjuta_util_get_user_cache_file_path ("session/", NULL))
39 #define DEFAULT_PROFILE "file://"PACKAGE_DATA_DIR"/profiles/default.profile"
40 #define USER_PROFILE_NAME "user"
42 #define ANJUTA_PIXMAP_SPLASH_SCREEN "anjuta_splash.png"
45 #define ANJUTA_GEOMETRY_HINT "-g="
46 #define ANJUTA_NO_SPLASH_HINT "-s"
47 #define ANJUTA_NO_SESSION_HINT "-n"
48 #define ANJUTA_NO_FILES_HINT "-f"
50 G_DEFINE_TYPE (AnjutaApplication
, anjuta_application
, GTK_TYPE_APPLICATION
)
52 static gchar
*system_restore_session
= NULL
;
54 struct _AnjutaApplicationPrivate
{
56 gboolean proper_shutdown
;
63 on_anjuta_delete_event (AnjutaWindow
*win
, GdkEvent
*event
, gpointer user_data
)
65 AnjutaApplication
*app
= ANJUTA_APPLICATION (user_data
);
66 AnjutaPluginManager
*plugin_manager
;
67 AnjutaProfileManager
*profile_manager
;
68 AnjutaProfile
*current_profile
;
69 AnjutaSavePrompt
*save_prompt
;
70 gchar
*remembered_plugins
;
72 DEBUG_PRINT ("%s", "AnjutaWindow delete event");
74 plugin_manager
= anjuta_shell_get_plugin_manager (ANJUTA_SHELL (win
), NULL
);
75 profile_manager
= anjuta_shell_get_profile_manager (ANJUTA_SHELL (win
), NULL
);
77 /* Save remembered plugins */
79 anjuta_plugin_manager_get_remembered_plugins (plugin_manager
);
80 g_settings_set_string (win
->settings
,
81 ANJUTA_REMEMBERED_PLUGINS
,
83 g_free (remembered_plugins
);
85 /* Check for unsaved data */
86 save_prompt
= anjuta_save_prompt_new (GTK_WINDOW (win
));
87 anjuta_shell_save_prompt (ANJUTA_SHELL (win
), save_prompt
, NULL
);
89 if (anjuta_save_prompt_get_items_count (save_prompt
) > 0)
91 switch (gtk_dialog_run (GTK_DIALOG (save_prompt
)))
93 case GTK_RESPONSE_DELETE_EVENT
:
94 case ANJUTA_SAVE_PROMPT_RESPONSE_CANCEL
:
95 gtk_widget_destroy (GTK_WIDGET (save_prompt
));
98 case ANJUTA_SAVE_PROMPT_RESPONSE_DISCARD
:
99 case ANJUTA_SAVE_PROMPT_RESPONSE_SAVE_CLOSE
:
104 /* Wait for files to be really saved (asyncronous operation) */
105 if (win
->save_count
> 0)
107 g_message ("Waiting for %d file(s) to be saved!", win
->save_count
);
108 while (win
->save_count
> 0)
110 g_main_context_iteration (NULL
, TRUE
);
114 /* If current active profile is "user", save current session as
117 current_profile
= anjuta_profile_manager_get_current (profile_manager
);
118 if (strcmp (anjuta_profile_get_name (current_profile
), "user") == 0)
121 session_dir
= USER_SESSION_PATH_NEW
;
122 anjuta_shell_session_save (ANJUTA_SHELL (win
), session_dir
, NULL
);
123 g_free (session_dir
);
126 anjuta_shell_notify_exit (ANJUTA_SHELL (win
), NULL
);
128 gtk_widget_destroy (GTK_WIDGET (save_prompt
));
131 if (anjuta_application_get_proper_shutdown (app
))
133 gtk_widget_hide (GTK_WIDGET (win
));
134 anjuta_plugin_manager_unload_all_plugins
135 (anjuta_shell_get_plugin_manager (ANJUTA_SHELL (win
), NULL
));
142 on_profile_scoped (AnjutaProfileManager
*profile_manager
,
143 AnjutaProfile
*profile
, AnjutaWindow
*win
)
146 static gboolean first_time
= TRUE
;
148 DEBUG_PRINT ("Profile scoped: %s", anjuta_profile_get_name (profile
));
149 if (strcmp (anjuta_profile_get_name (profile
), USER_PROFILE_NAME
) != 0)
152 DEBUG_PRINT ("%s", "User profile loaded; Restoring user session");
154 /* If profile scoped to "user", restore user session */
155 if (system_restore_session
)
157 session_dir
= system_restore_session
;
158 system_restore_session
= NULL
;
162 session_dir
= USER_SESSION_PATH_NEW
;
171 /* Clear the files list since we don't want to load them later */
172 AnjutaSession
*session
;
173 session
= anjuta_session_new (session_dir
);
174 anjuta_session_set_string_list (session
, "File Loader",
176 anjuta_session_sync (session
);
177 g_object_unref (session
);
180 /* Restore session */
181 anjuta_shell_session_load (ANJUTA_SHELL (win
), session_dir
, NULL
);
182 g_free (session_dir
);
186 on_profile_descoped (AnjutaProfileManager
*profile_manager
,
187 AnjutaProfile
*profile
, AnjutaWindow
*win
)
191 DEBUG_PRINT ("Profile descoped: %s", anjuta_profile_get_name (profile
));
192 if (strcmp (anjuta_profile_get_name (profile
), USER_PROFILE_NAME
) != 0)
195 DEBUG_PRINT ("%s", "User profile descoped; Saving user session");
197 /* If profile descoped from is "user", save user session */
198 session_dir
= USER_SESSION_PATH_NEW
;
200 /* Save current session */
201 anjuta_shell_session_save (ANJUTA_SHELL (win
), session_dir
, NULL
);
202 g_free (session_dir
);
205 /* Create hint string.
206 * Pass command line options to primary instance if needed */
208 create_anjuta_application_hint (const gchar
*geometry
,
215 hint
= g_string_new (NULL
);
216 if (geometry
!= NULL
)
218 g_string_append (hint
, ANJUTA_GEOMETRY_HINT
);
219 g_string_append (hint
, geometry
);
221 if (no_splash
) g_string_append (hint
,ANJUTA_NO_SPLASH_HINT
);
222 if (no_session
) g_string_append (hint
,ANJUTA_NO_SESSION_HINT
);
223 if (no_files
) g_string_append (hint
,ANJUTA_NO_FILES_HINT
);
224 g_string_append_c(hint
, '-');
226 return g_string_free (hint
, FALSE
);
229 /* Parse hint string to set flag in primary application */
231 anjuta_application_parse_hint (AnjutaApplication
*app
,
234 const gchar
*geometry
;
236 g_free (app
->priv
->geometry
);
237 app
->priv
->geometry
= NULL
;
238 geometry
= strstr(hint
, ANJUTA_GEOMETRY_HINT
);
239 if (geometry
!= NULL
)
241 const gchar
*end
= strstr(geometry
+ 1, "-");
245 geometry
+= strlen (ANJUTA_GEOMETRY_HINT
);
246 app
->priv
->geometry
= g_strndup (geometry
, end
- geometry
);
249 app
->priv
->no_splash
= strstr(hint
, ANJUTA_NO_SPLASH_HINT
"-") != NULL
? TRUE
: FALSE
;
250 app
->priv
->no_session
= strstr(hint
, ANJUTA_NO_SESSION_HINT
"-") != NULL
? TRUE
: FALSE
;
251 app
->priv
->no_files
= strstr(hint
, ANJUTA_NO_FILES_HINT
"-") != NULL
? TRUE
: FALSE
;
255 anjuta_application_reset_hint (AnjutaApplication
*app
)
257 g_free (app
->priv
->geometry
);
258 app
->priv
->geometry
= NULL
;
259 app
->priv
->no_splash
= FALSE
;
260 app
->priv
->no_session
= FALSE
;
261 app
->priv
->no_files
= FALSE
;
265 /* GApplication implementation
266 *---------------------------------------------------------------------------*/
269 anjuta_application_local_command_line (GApplication
*application
,
273 /* Command line options */
274 gboolean no_splash
= FALSE
;
275 gboolean no_client
= FALSE
;
276 gboolean no_session
= FALSE
;
277 gboolean no_files
= FALSE
;
278 gboolean version
= FALSE
;
279 gchar
*geometry
= NULL
;
280 gchar
**filenames
= NULL
;
282 const GOptionEntry anjuta_options
[] = {
284 "geometry", 'g', 0, G_OPTION_ARG_STRING
,
286 N_("Specify the size and location of the main window"),
287 /* This is the format you can specify the size andposition
288 * of the window on command line */
289 N_("WIDTHxHEIGHT+XOFF+YOFF")
292 "no-splash", 's', 0, G_OPTION_ARG_NONE
,
294 N_("Do not show the splash screen"),
298 "no-client", 'c', 0, G_OPTION_ARG_NONE
,
300 N_("Start a new instance and do not open the file in an existing instance"),
304 "no-session", 'n', 0, G_OPTION_ARG_NONE
,
306 N_("Do not open last session on startup"),
310 "no-files", 'f', 0, G_OPTION_ARG_NONE
,
312 N_("Do not open last project and files on startup"),
316 "proper-shutdown", 'p', 0, G_OPTION_ARG_NONE
,
317 &((ANJUTA_APPLICATION (application
))->priv
->proper_shutdown
),
318 N_("Shut down Anjuta properly, releasing all resources (for debugging)"),
322 "version", 'v', 0, G_OPTION_ARG_NONE
,
324 N_("Display program version"),
328 G_OPTION_REMAINING
, 0, 0, G_OPTION_ARG_FILENAME_ARRAY
,
335 GOptionContext
*context
;
338 GError
*error
= NULL
;
342 context
= g_option_context_new (_("- Integrated Development Environment"));
344 g_option_context_add_main_entries (context
, anjuta_options
, GETTEXT_PACKAGE
);
346 g_option_context_add_main_entries (context
, anjuta_options
, NULL
);
348 g_option_context_add_group (context
, gtk_get_option_group (TRUE
));
350 /* Parse arguments */
352 argc
= g_strv_length (argv
);
353 if (!g_option_context_parse (context
, &argc
, &argv
, &error
))
355 g_printerr ("Could not parse arguments: %s\n", error
->message
);
356 g_error_free (error
);
357 g_option_context_free (context
);
359 *exit_status
= EXIT_FAILURE
;
362 *exit_status
= EXIT_SUCCESS
;
363 g_option_context_free (context
);
366 /* Display version */
369 g_print ("%s\n", PACKAGE_STRING
);
373 /* Register application */
374 if (no_client
) g_application_set_flags (application
, G_APPLICATION_NON_UNIQUE
| g_application_get_flags (application
));
375 g_application_register (G_APPLICATION (application
), NULL
, NULL
);
377 /* Convert all file names to GFile, so an already existing instance of
378 * Anjuta having another current directory can still open the files */
379 files
= g_ptr_array_new ();
384 for (filename
= filenames
; *filename
!= NULL
; filename
++)
386 GFile
* file
= g_file_new_for_commandline_arg(*filename
);
387 if (file
!= NULL
) g_ptr_array_add (files
, file
);
391 /* Create hint string */
392 hint
= create_anjuta_application_hint (geometry
, no_splash
, no_session
, no_files
);
395 g_application_open (application
, (GFile
**)files
->pdata
, files
->len
, hint
);
396 g_ptr_array_foreach (files
, (GFunc
)g_object_unref
, NULL
);
397 g_ptr_array_free (files
, TRUE
);
404 anjuta_application_open (GApplication
*application
,
411 IAnjutaFileLoader
* loader
= NULL
;
414 anjuta_application_parse_hint (ANJUTA_APPLICATION (application
), hint
);
416 windows
= gtk_application_get_windows (GTK_APPLICATION (application
));
421 win
= ANJUTA_SHELL (anjuta_application_create_window (ANJUTA_APPLICATION (application
)));
425 gboolean no_files
= ANJUTA_APPLICATION (application
)->priv
->no_files
;
426 ANJUTA_APPLICATION (application
)->priv
->no_files
= TRUE
;
427 win
= ANJUTA_SHELL (anjuta_application_create_window (ANJUTA_APPLICATION (application
)));
428 ANJUTA_APPLICATION (application
)->priv
->no_files
= no_files
;
435 gboolean no_files
= ANJUTA_APPLICATION (application
)->priv
->no_files
;
436 ANJUTA_APPLICATION (application
)->priv
->no_files
= TRUE
;
437 win
= ANJUTA_SHELL (anjuta_application_create_window (ANJUTA_APPLICATION (application
)));
438 ANJUTA_APPLICATION (application
)->priv
->no_files
= no_files
;
442 win
= ANJUTA_SHELL (windows
->data
);
448 loader
= anjuta_shell_get_interface(win
, IAnjutaFileLoader
, NULL
);
453 for (i
= 0; i
< n_files
; i
++)
455 ianjuta_file_loader_load(loader
, files
[i
], FALSE
, NULL
);
458 anjuta_application_reset_hint (ANJUTA_APPLICATION (application
));
463 /* GObject implementation
464 *---------------------------------------------------------------------------*/
467 anjuta_application_finalize (GObject
*object
)
469 AnjutaApplication
*app
= ANJUTA_APPLICATION (object
);
471 if (app
->priv
->geometry
!= NULL
)
473 g_free (app
->priv
->geometry
);
474 app
->priv
->geometry
= NULL
;
476 G_OBJECT_CLASS (anjuta_application_parent_class
)->finalize (object
);
480 anjuta_application_init (AnjutaApplication
*application
)
482 application
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (application
,
483 ANJUTA_TYPE_APPLICATION
,
484 AnjutaApplicationPrivate
);
485 application
->priv
->proper_shutdown
= FALSE
;
486 application
->priv
->no_files
= FALSE
;
487 application
->priv
->no_session
= FALSE
;
488 application
->priv
->no_splash
= FALSE
;
489 application
->priv
->geometry
= NULL
;
493 anjuta_application_class_init (AnjutaApplicationClass
*klass
)
495 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
496 GApplicationClass
* app_class
= G_APPLICATION_CLASS (klass
);
498 object_class
->finalize
= anjuta_application_finalize
;
500 app_class
->open
= anjuta_application_open
;
501 app_class
->local_command_line
= anjuta_application_local_command_line
;
503 g_type_class_add_private (klass
, sizeof (AnjutaApplicationPrivate
));
509 *---------------------------------------------------------------------------*/
512 anjuta_application_new (void)
516 return g_object_new (anjuta_application_get_type (),
517 "application-id", "org.gnome.anjuta",
518 "flags", G_APPLICATION_HANDLES_OPEN
,
523 anjuta_application_get_proper_shutdown (AnjutaApplication
*app
)
525 return app
->priv
->proper_shutdown
;
529 anjuta_application_get_no_files (AnjutaApplication
*app
)
531 return app
->priv
->no_files
;
535 anjuta_application_get_no_session (AnjutaApplication
*app
)
537 return app
->priv
->no_session
;
541 anjuta_application_get_geometry (AnjutaApplication
*app
)
543 return app
->priv
->geometry
;
547 anjuta_application_create_window (AnjutaApplication
*app
)
549 AnjutaPluginManager
*plugin_manager
;
550 AnjutaProfileManager
*profile_manager
;
552 AnjutaStatus
*status
;
553 AnjutaProfile
*profile
;
554 GFile
*session_profile
;
555 gchar
*remembered_plugins
;
556 gchar
*profile_name
= NULL
;
557 GError
*error
= NULL
;
559 /* Initialize application */
560 win
= ANJUTA_WINDOW (anjuta_window_new ());
561 gtk_application_add_window (GTK_APPLICATION (app
), GTK_WINDOW (win
));
562 status
= anjuta_shell_get_status (ANJUTA_SHELL (win
), NULL
);
563 anjuta_status_progress_add_ticks (status
, 1);
565 gtk_window_set_role (GTK_WINDOW (win
), "anjuta-app");
566 gtk_window_set_auto_startup_notification(TRUE
);
567 gtk_window_set_default_icon_name ("anjuta");
568 gtk_window_set_auto_startup_notification(FALSE
);
570 if (app
->priv
->no_splash
)
572 anjuta_status_disable_splash (status
, TRUE
);
576 gchar
*im_file
= NULL
;
577 im_file
= anjuta_res_get_pixmap_file (ANJUTA_PIXMAP_SPLASH_SCREEN
);
580 anjuta_status_set_splash (status
, im_file
, 100);
585 g_signal_connect (G_OBJECT (win
), "delete_event",
586 G_CALLBACK (on_anjuta_delete_event
), app
);
588 /* Setup application framework */
589 plugin_manager
= anjuta_shell_get_plugin_manager (ANJUTA_SHELL (win
),
591 profile_manager
= anjuta_shell_get_profile_manager (ANJUTA_SHELL (win
),
594 /* Restore remembered plugins */
596 g_settings_get_string (win
->settings
, ANJUTA_REMEMBERED_PLUGINS
);
597 if (remembered_plugins
)
598 anjuta_plugin_manager_set_remembered_plugins (plugin_manager
,
600 g_free (remembered_plugins
);
602 /* Prepare profile */
603 profile
= anjuta_profile_new (USER_PROFILE_NAME
, plugin_manager
);
604 session_profile
= g_file_new_for_uri (DEFAULT_PROFILE
);
605 anjuta_profile_add_plugins_from_xml (profile
, session_profile
,
609 anjuta_util_dialog_error (GTK_WINDOW (win
), "%s", error
->message
);
610 g_error_free (error
);
613 g_object_unref (session_profile
);
615 /* Load user session profile */
616 profile_name
= g_path_get_basename (DEFAULT_PROFILE
);
617 session_profile
= anjuta_util_get_user_cache_file (profile_name
, NULL
);
618 if (g_file_query_exists (session_profile
, NULL
))
620 anjuta_profile_add_plugins_from_xml (profile
, session_profile
,
624 anjuta_util_dialog_error (GTK_WINDOW (win
), "%s", error
->message
);
625 g_error_free (error
);
629 anjuta_profile_set_sync_file (profile
, session_profile
);
630 g_object_unref (session_profile
);
631 g_free (profile_name
);
634 anjuta_profile_manager_freeze (profile_manager
);
635 anjuta_profile_manager_push (profile_manager
, profile
, &error
);
638 anjuta_util_dialog_error (GTK_WINDOW (win
), "%s", error
->message
);
639 g_error_free (error
);
643 /* Prepare for session save and load on profile change */
644 g_signal_connect (profile_manager
, "profile-scoped",
645 G_CALLBACK (on_profile_scoped
), win
);
646 anjuta_profile_manager_thaw (profile_manager
, &error
);
650 anjuta_util_dialog_error (GTK_WINDOW (win
), "%s", error
->message
);
651 g_error_free (error
);
654 g_signal_connect (profile_manager
, "profile-descoped",
655 G_CALLBACK (on_profile_descoped
), win
);
657 anjuta_status_progress_tick (status
, NULL
, _("Loaded Session…"));
658 anjuta_status_disable_splash (status
, TRUE
);