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 ANJUTA_SESSION_SKIP_LAST "session-skip-last"
40 #define ANJUTA_SESSION_SKIP_LAST_FILES "session-skip-last-files"
42 #define DEFAULT_PROFILE "file://"PACKAGE_DATA_DIR"/profiles/default.profile"
43 #define USER_PROFILE_NAME "user"
45 #define ANJUTA_PIXMAP_SPLASH_SCREEN "anjuta_splash.png"
47 #define ANJUTA_GEOMETRY_HINT "-g="
48 #define ANJUTA_NO_SPLASH_HINT "-s"
49 #define ANJUTA_NO_SESSION_HINT "-n"
50 #define ANJUTA_NO_FILES_HINT "-f"
52 G_DEFINE_TYPE (AnjutaApplication
, anjuta_application
, GTK_TYPE_APPLICATION
)
54 struct _AnjutaApplicationPrivate
{
56 gboolean proper_shutdown
;
63 on_anjuta_delete_event (AnjutaWindow
*win
, GdkEvent
*event
, gpointer user_data
)
65 AnjutaApplication
*app
= user_data
;
66 AnjutaApplicationPrivate
*priv
= app
->priv
;
68 AnjutaPluginManager
*plugin_manager
;
69 AnjutaProfileManager
*profile_manager
;
70 AnjutaSavePrompt
*save_prompt
;
71 gchar
*remembered_plugins
;
73 DEBUG_PRINT ("%s", "AnjutaWindow delete event");
75 plugin_manager
= anjuta_shell_get_plugin_manager (ANJUTA_SHELL (win
), NULL
);
76 profile_manager
= anjuta_shell_get_profile_manager (ANJUTA_SHELL (win
), NULL
);
78 /* Save remembered plugins */
80 anjuta_plugin_manager_get_remembered_plugins (plugin_manager
);
81 g_settings_set_string (win
->settings
,
82 ANJUTA_REMEMBERED_PLUGINS
,
84 g_free (remembered_plugins
);
86 /* Check for unsaved data */
87 save_prompt
= anjuta_save_prompt_new (GTK_WINDOW (win
));
88 anjuta_shell_save_prompt (ANJUTA_SHELL (win
), save_prompt
, NULL
);
90 if (anjuta_save_prompt_get_items_count (save_prompt
) > 0)
92 switch (gtk_dialog_run (GTK_DIALOG (save_prompt
)))
94 case GTK_RESPONSE_DELETE_EVENT
:
95 case ANJUTA_SAVE_PROMPT_RESPONSE_CANCEL
:
96 gtk_widget_destroy (GTK_WIDGET (save_prompt
));
99 case ANJUTA_SAVE_PROMPT_RESPONSE_DISCARD
:
100 case ANJUTA_SAVE_PROMPT_RESPONSE_SAVE_CLOSE
:
105 gtk_widget_destroy (GTK_WIDGET (save_prompt
));
107 /* Wait for files to be really saved (asyncronous operation) */
108 if (win
->save_count
> 0)
110 g_message ("Waiting for %d file(s) to be saved!", win
->save_count
);
111 while (win
->save_count
> 0)
113 g_main_context_iteration (NULL
, TRUE
);
117 /* Close the profile manager which will emit "profile-descoped" and release
118 * all previous profiles. */
119 anjuta_profile_manager_close (profile_manager
);
121 /* If this is the last window we can just quit the application and skip
122 * deactivating plugins and other cleanup. */
123 if (!priv
->proper_shutdown
&&
124 g_list_length (gtk_application_get_windows (GTK_APPLICATION (app
))) == 1)
126 g_application_quit (G_APPLICATION (app
));
130 /* Hide the window while unloading all the plugins. */
131 gtk_widget_hide (GTK_WIDGET (win
));
132 anjuta_plugin_manager_unload_all_plugins (plugin_manager
);
138 on_profile_scoped (AnjutaProfileManager
*profile_manager
,
139 AnjutaProfile
*profile
, AnjutaWindow
*win
)
142 static gboolean first_time
= TRUE
;
143 AnjutaSession
*session
;
145 DEBUG_PRINT ("Profile scoped: %s", anjuta_profile_get_name (profile
));
146 if (strcmp (anjuta_profile_get_name (profile
), USER_PROFILE_NAME
) != 0)
149 DEBUG_PRINT ("%s", "User profile loaded; Restoring user session");
151 /* If profile scoped to "user", restore user session */
152 session_dir
= USER_SESSION_PATH_NEW
;
154 session
= anjuta_session_new (session_dir
);
157 if (g_settings_get_boolean (win
->settings
, ANJUTA_SESSION_SKIP_LAST
))
160 anjuta_session_clear (session
);
162 else if (g_settings_get_boolean (win
->settings
, ANJUTA_SESSION_SKIP_LAST_FILES
))
164 /* Clear files from session */
165 anjuta_session_set_string_list (session
, "File Loader",
172 /* Clear the files list since we don't want to load them later */
173 anjuta_session_set_string_list (session
, "File Loader",
176 anjuta_session_sync (session
);
177 g_object_unref (session
);
179 /* Restore session */
180 anjuta_shell_session_load (ANJUTA_SHELL (win
), session_dir
, NULL
);
181 g_free (session_dir
);
185 on_profile_descoped (AnjutaProfileManager
*profile_manager
,
186 AnjutaProfile
*profile
, AnjutaWindow
*win
)
190 DEBUG_PRINT ("Profile descoped: %s", anjuta_profile_get_name (profile
));
191 if (strcmp (anjuta_profile_get_name (profile
), USER_PROFILE_NAME
) != 0)
194 DEBUG_PRINT ("%s", "User profile descoped; Saving user session");
196 /* If profile descoped from is "user", save user session */
197 session_dir
= USER_SESSION_PATH_NEW
;
199 /* Save current session */
200 anjuta_shell_session_save (ANJUTA_SHELL (win
), session_dir
, NULL
);
201 g_free (session_dir
);
204 /* Create hint string.
205 * Pass command line options to primary instance if needed */
207 create_anjuta_application_hint (const gchar
*geometry
,
214 hint
= g_string_new (NULL
);
215 if (geometry
!= NULL
)
217 g_string_append (hint
, ANJUTA_GEOMETRY_HINT
);
218 g_string_append (hint
, geometry
);
220 if (no_splash
) g_string_append (hint
,ANJUTA_NO_SPLASH_HINT
);
221 if (no_session
) g_string_append (hint
,ANJUTA_NO_SESSION_HINT
);
222 if (no_files
) g_string_append (hint
,ANJUTA_NO_FILES_HINT
);
223 g_string_append_c(hint
, '-');
225 return g_string_free (hint
, FALSE
);
228 /* Parse hint string to set flag in primary application */
230 anjuta_application_parse_hint (AnjutaApplication
*app
,
233 const gchar
*geometry
;
235 g_free (app
->priv
->geometry
);
236 app
->priv
->geometry
= NULL
;
237 geometry
= strstr(hint
, ANJUTA_GEOMETRY_HINT
);
238 if (geometry
!= NULL
)
240 const gchar
*end
= strstr(geometry
+ 1, "-");
244 geometry
+= strlen (ANJUTA_GEOMETRY_HINT
);
245 app
->priv
->geometry
= g_strndup (geometry
, end
- geometry
);
248 app
->priv
->no_splash
= strstr(hint
, ANJUTA_NO_SPLASH_HINT
"-") != NULL
? TRUE
: FALSE
;
249 app
->priv
->no_session
= strstr(hint
, ANJUTA_NO_SESSION_HINT
"-") != NULL
? TRUE
: FALSE
;
250 app
->priv
->no_files
= strstr(hint
, ANJUTA_NO_FILES_HINT
"-") != NULL
? TRUE
: FALSE
;
254 anjuta_application_reset_hint (AnjutaApplication
*app
)
256 g_free (app
->priv
->geometry
);
257 app
->priv
->geometry
= NULL
;
258 app
->priv
->no_splash
= FALSE
;
259 app
->priv
->no_session
= FALSE
;
260 app
->priv
->no_files
= FALSE
;
264 /* GApplication implementation
265 *---------------------------------------------------------------------------*/
268 anjuta_application_local_command_line (GApplication
*application
,
272 /* Command line options */
273 gboolean no_splash
= FALSE
;
274 gboolean no_client
= FALSE
;
275 gboolean no_session
= FALSE
;
276 gboolean no_files
= FALSE
;
277 gboolean version
= FALSE
;
278 gchar
*geometry
= NULL
;
279 gchar
**filenames
= NULL
;
281 const GOptionEntry anjuta_options
[] = {
283 "geometry", 'g', 0, G_OPTION_ARG_STRING
,
285 N_("Specify the size and location of the main window"),
286 /* This is the format you can specify the size andposition
287 * of the window on command line */
288 N_("WIDTHxHEIGHT+XOFF+YOFF")
291 "no-splash", 's', 0, G_OPTION_ARG_NONE
,
293 N_("Do not show the splash screen"),
297 "no-client", 'c', 0, G_OPTION_ARG_NONE
,
299 N_("Start a new instance and do not open the file in an existing instance"),
303 "no-session", 'n', 0, G_OPTION_ARG_NONE
,
305 N_("Do not open last session on startup"),
309 "no-files", 'f', 0, G_OPTION_ARG_NONE
,
311 N_("Do not open last project and files on startup"),
315 "proper-shutdown", 'p', 0, G_OPTION_ARG_NONE
,
316 &((ANJUTA_APPLICATION (application
))->priv
->proper_shutdown
),
317 N_("Shut down Anjuta properly, releasing all resources (for debugging)"),
321 "version", 'v', 0, G_OPTION_ARG_NONE
,
323 N_("Display program version"),
327 G_OPTION_REMAINING
, 0, 0, G_OPTION_ARG_FILENAME_ARRAY
,
334 GOptionContext
*context
;
337 GError
*error
= NULL
;
341 context
= g_option_context_new (_("- Integrated Development Environment"));
343 g_option_context_add_main_entries (context
, anjuta_options
, GETTEXT_PACKAGE
);
345 g_option_context_add_main_entries (context
, anjuta_options
, NULL
);
347 g_option_context_add_group (context
, gtk_get_option_group (TRUE
));
349 /* Parse arguments */
351 argc
= g_strv_length (argv
);
352 if (!g_option_context_parse (context
, &argc
, &argv
, &error
))
354 g_printerr ("Could not parse arguments: %s\n", error
->message
);
355 g_error_free (error
);
356 g_option_context_free (context
);
358 *exit_status
= EXIT_FAILURE
;
361 *exit_status
= EXIT_SUCCESS
;
362 g_option_context_free (context
);
365 /* Display version */
368 g_print ("%s\n", PACKAGE_STRING
);
372 /* Register application */
373 if (no_client
) g_application_set_flags (application
, G_APPLICATION_NON_UNIQUE
| g_application_get_flags (application
));
374 g_application_register (G_APPLICATION (application
), NULL
, NULL
);
376 /* Convert all file names to GFile, so an already existing instance of
377 * Anjuta having another current directory can still open the files */
378 files
= g_ptr_array_new ();
383 for (filename
= filenames
; *filename
!= NULL
; filename
++)
385 GFile
* file
= g_file_new_for_commandline_arg(*filename
);
386 if (file
!= NULL
) g_ptr_array_add (files
, file
);
390 /* Create hint string */
391 hint
= create_anjuta_application_hint (geometry
, no_splash
, no_session
, no_files
);
394 g_application_open (application
, (GFile
**)files
->pdata
, files
->len
, hint
);
395 g_ptr_array_foreach (files
, (GFunc
)g_object_unref
, NULL
);
396 g_ptr_array_free (files
, TRUE
);
403 anjuta_application_open (GApplication
*application
,
410 IAnjutaFileLoader
* loader
= NULL
;
413 anjuta_application_parse_hint (ANJUTA_APPLICATION (application
), hint
);
415 windows
= gtk_application_get_windows (GTK_APPLICATION (application
));
420 win
= ANJUTA_SHELL (anjuta_application_create_window (ANJUTA_APPLICATION (application
)));
424 gboolean no_files
= ANJUTA_APPLICATION (application
)->priv
->no_files
;
425 ANJUTA_APPLICATION (application
)->priv
->no_files
= TRUE
;
426 win
= ANJUTA_SHELL (anjuta_application_create_window (ANJUTA_APPLICATION (application
)));
427 ANJUTA_APPLICATION (application
)->priv
->no_files
= no_files
;
434 gboolean no_files
= ANJUTA_APPLICATION (application
)->priv
->no_files
;
435 ANJUTA_APPLICATION (application
)->priv
->no_files
= TRUE
;
436 win
= ANJUTA_SHELL (anjuta_application_create_window (ANJUTA_APPLICATION (application
)));
437 ANJUTA_APPLICATION (application
)->priv
->no_files
= no_files
;
441 win
= ANJUTA_SHELL (windows
->data
);
447 loader
= anjuta_shell_get_interface(win
, IAnjutaFileLoader
, NULL
);
452 for (i
= 0; i
< n_files
; i
++)
454 ianjuta_file_loader_load(loader
, files
[i
], FALSE
, NULL
);
457 anjuta_application_reset_hint (ANJUTA_APPLICATION (application
));
462 /* GObject implementation
463 *---------------------------------------------------------------------------*/
466 anjuta_application_finalize (GObject
*object
)
468 AnjutaApplication
*app
= ANJUTA_APPLICATION (object
);
470 if (app
->priv
->geometry
!= NULL
)
472 g_free (app
->priv
->geometry
);
473 app
->priv
->geometry
= NULL
;
475 G_OBJECT_CLASS (anjuta_application_parent_class
)->finalize (object
);
479 anjuta_application_init (AnjutaApplication
*application
)
481 application
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (application
,
482 ANJUTA_TYPE_APPLICATION
,
483 AnjutaApplicationPrivate
);
484 application
->priv
->proper_shutdown
= FALSE
;
485 application
->priv
->no_files
= FALSE
;
486 application
->priv
->no_session
= FALSE
;
487 application
->priv
->no_splash
= FALSE
;
488 application
->priv
->geometry
= NULL
;
492 anjuta_application_class_init (AnjutaApplicationClass
*klass
)
494 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
495 GApplicationClass
* app_class
= G_APPLICATION_CLASS (klass
);
497 object_class
->finalize
= anjuta_application_finalize
;
499 app_class
->open
= anjuta_application_open
;
500 app_class
->local_command_line
= anjuta_application_local_command_line
;
502 g_type_class_add_private (klass
, sizeof (AnjutaApplicationPrivate
));
508 *---------------------------------------------------------------------------*/
511 anjuta_application_new (void)
515 return g_object_new (anjuta_application_get_type (),
516 "application-id", "org.gnome.anjuta",
517 "flags", G_APPLICATION_HANDLES_OPEN
,
522 anjuta_application_get_proper_shutdown (AnjutaApplication
*app
)
524 return app
->priv
->proper_shutdown
;
528 anjuta_application_get_no_files (AnjutaApplication
*app
)
530 return app
->priv
->no_files
;
534 anjuta_application_get_no_session (AnjutaApplication
*app
)
536 return app
->priv
->no_session
;
540 anjuta_application_get_geometry (AnjutaApplication
*app
)
542 return app
->priv
->geometry
;
546 anjuta_application_create_window (AnjutaApplication
*app
)
548 AnjutaPluginManager
*plugin_manager
;
549 AnjutaProfileManager
*profile_manager
;
551 AnjutaStatus
*status
;
552 AnjutaProfile
*profile
;
553 GFile
*session_profile
;
554 gchar
*remembered_plugins
;
555 gchar
*profile_name
= NULL
;
556 GError
*error
= NULL
;
558 /* Initialize application */
559 win
= ANJUTA_WINDOW (anjuta_window_new ());
560 gtk_application_add_window (GTK_APPLICATION (app
), GTK_WINDOW (win
));
561 status
= anjuta_shell_get_status (ANJUTA_SHELL (win
), NULL
);
562 anjuta_status_progress_add_ticks (status
, 1);
564 gtk_window_set_role (GTK_WINDOW (win
), "anjuta-app");
565 gtk_window_set_auto_startup_notification(TRUE
);
566 gtk_window_set_default_icon_name ("anjuta");
567 gtk_window_set_auto_startup_notification(FALSE
);
569 if (app
->priv
->no_splash
)
571 anjuta_status_disable_splash (status
, TRUE
);
575 gchar
*im_file
= NULL
;
576 im_file
= anjuta_res_get_pixmap_file (ANJUTA_PIXMAP_SPLASH_SCREEN
);
579 anjuta_status_set_splash (status
, im_file
, 100);
584 g_signal_connect (G_OBJECT (win
), "delete_event",
585 G_CALLBACK (on_anjuta_delete_event
), app
);
587 /* Setup application framework */
588 plugin_manager
= anjuta_shell_get_plugin_manager (ANJUTA_SHELL (win
),
590 profile_manager
= anjuta_shell_get_profile_manager (ANJUTA_SHELL (win
),
593 /* Restore remembered plugins */
595 g_settings_get_string (win
->settings
, ANJUTA_REMEMBERED_PLUGINS
);
596 if (remembered_plugins
)
597 anjuta_plugin_manager_set_remembered_plugins (plugin_manager
,
599 g_free (remembered_plugins
);
601 /* Prepare profile */
602 profile
= anjuta_profile_new (USER_PROFILE_NAME
, plugin_manager
);
603 session_profile
= g_file_new_for_uri (DEFAULT_PROFILE
);
604 anjuta_profile_add_plugins_from_xml (profile
, session_profile
,
608 anjuta_util_dialog_error (GTK_WINDOW (win
), "%s", error
->message
);
609 g_error_free (error
);
612 g_object_unref (session_profile
);
614 /* Load user session profile */
615 profile_name
= g_path_get_basename (DEFAULT_PROFILE
);
616 session_profile
= anjuta_util_get_user_cache_file (profile_name
, NULL
);
617 if (g_file_query_exists (session_profile
, NULL
))
619 anjuta_profile_add_plugins_from_xml (profile
, session_profile
,
623 anjuta_util_dialog_error (GTK_WINDOW (win
), "%s", error
->message
);
624 g_error_free (error
);
628 anjuta_profile_set_sync_file (profile
, session_profile
);
629 g_object_unref (session_profile
);
630 g_free (profile_name
);
633 anjuta_profile_manager_freeze (profile_manager
);
634 anjuta_profile_manager_push (profile_manager
, profile
, &error
);
637 anjuta_util_dialog_error (GTK_WINDOW (win
), "%s", error
->message
);
638 g_error_free (error
);
642 /* Prepare for session save and load on profile change */
643 g_signal_connect (profile_manager
, "profile-scoped",
644 G_CALLBACK (on_profile_scoped
), win
);
645 anjuta_profile_manager_thaw (profile_manager
, &error
);
649 anjuta_util_dialog_error (GTK_WINDOW (win
), "%s", error
->message
);
650 g_error_free (error
);
653 g_signal_connect (profile_manager
, "profile-descoped",
654 G_CALLBACK (on_profile_descoped
), win
);
656 anjuta_status_progress_tick (status
, NULL
, _("Loaded Session…"));
657 anjuta_status_disable_splash (status
, TRUE
);