libanjuta: bgo #696984 - Fix a signal name typo in documentation comments
[anjuta.git] / src / anjuta-application.c
blob4e41eb4900f9953d94655b1817359e2da21685cd
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta-application.c
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)
9 * any later version.
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
14 * for more details.
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
21 #include <config.h>
23 #include <string.h>
24 #include <stdlib.h>
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 {
55 gboolean no_splash;
56 gboolean proper_shutdown;
57 gboolean no_files;
58 gboolean no_session;
59 gchar *geometry;
62 static gboolean
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 */
79 remembered_plugins =
80 anjuta_plugin_manager_get_remembered_plugins (plugin_manager);
81 g_settings_set_string (win->settings,
82 ANJUTA_REMEMBERED_PLUGINS,
83 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));
97 /* Do not exit now */
98 return TRUE;
99 case ANJUTA_SAVE_PROMPT_RESPONSE_DISCARD:
100 case ANJUTA_SAVE_PROMPT_RESPONSE_SAVE_CLOSE:
101 /* exit now */
102 break;
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));
127 return TRUE;
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);
134 return FALSE;
137 static void
138 on_profile_scoped (AnjutaProfileManager *profile_manager,
139 AnjutaProfile *profile, AnjutaWindow *win)
141 gchar *session_dir;
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)
147 return;
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);
155 if (first_time)
157 if (g_settings_get_boolean (win->settings, ANJUTA_SESSION_SKIP_LAST))
159 /* Clear session */
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",
166 "Files", NULL);
168 first_time = FALSE;
170 else
172 /* Clear the files list since we don't want to load them later */
173 anjuta_session_set_string_list (session, "File Loader",
174 "Files", NULL);
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);
184 static void
185 on_profile_descoped (AnjutaProfileManager *profile_manager,
186 AnjutaProfile *profile, AnjutaWindow *win)
188 gchar *session_dir;
190 DEBUG_PRINT ("Profile descoped: %s", anjuta_profile_get_name (profile));
191 if (strcmp (anjuta_profile_get_name (profile), USER_PROFILE_NAME) != 0)
192 return;
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 */
206 static gchar *
207 create_anjuta_application_hint (const gchar *geometry,
208 gboolean no_splash,
209 gboolean no_session,
210 gboolean no_files)
212 GString *hint;
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 */
229 static void
230 anjuta_application_parse_hint (AnjutaApplication *app,
231 const gchar* hint)
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, "-");
242 if (end != NULL)
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;
253 static void
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 *---------------------------------------------------------------------------*/
267 static gboolean
268 anjuta_application_local_command_line (GApplication *application,
269 gchar ***arguments,
270 gint *exit_status)
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,
284 &geometry,
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,
292 &no_splash,
293 N_("Do not show the splash screen"),
294 NULL
297 "no-client", 'c', 0, G_OPTION_ARG_NONE,
298 &no_client,
299 N_("Start a new instance and do not open the file in an existing instance"),
300 NULL
303 "no-session", 'n', 0, G_OPTION_ARG_NONE,
304 &no_session,
305 N_("Do not open last session on startup"),
306 NULL
309 "no-files", 'f', 0, G_OPTION_ARG_NONE,
310 &no_files,
311 N_("Do not open last project and files on startup"),
312 NULL
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)"),
318 NULL
321 "version", 'v', 0, G_OPTION_ARG_NONE,
322 &version,
323 N_("Display program version"),
324 NULL
327 G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY,
328 &filenames,
329 NULL,
330 NULL
332 {NULL}
334 GOptionContext *context;
335 gint argc = 0;
336 gchar **argv = NULL;
337 GError *error = NULL;
338 gchar *hint = NULL;
339 GPtrArray *files;
341 context = g_option_context_new (_("- Integrated Development Environment"));
342 #ifdef ENABLE_NLS
343 g_option_context_add_main_entries (context, anjuta_options, GETTEXT_PACKAGE);
344 #else
345 g_option_context_add_main_entries (context, anjuta_options, NULL);
346 #endif
347 g_option_context_add_group (context, gtk_get_option_group (TRUE));
349 /* Parse arguments */
350 argv = *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;
359 return TRUE;
361 *exit_status = EXIT_SUCCESS;
362 g_option_context_free (context);
365 /* Display version */
366 if (version)
368 g_print ("%s\n", PACKAGE_STRING);
369 return TRUE;
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 ();
379 if (filenames)
381 gchar** filename;
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);
393 /* Open 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);
397 g_free (hint);
399 return TRUE;
402 static void
403 anjuta_application_open (GApplication *application,
404 GFile **files,
405 gint n_files,
406 const gchar* hint)
408 GList *windows;
409 AnjutaShell *win;
410 IAnjutaFileLoader* loader = NULL;
411 gint i;
413 anjuta_application_parse_hint (ANJUTA_APPLICATION (application), hint);
415 windows = gtk_application_get_windows (GTK_APPLICATION (application));
416 if (windows == NULL)
418 if (n_files == 0)
420 win = ANJUTA_SHELL (anjuta_application_create_window (ANJUTA_APPLICATION (application)));
422 else
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;
430 else
432 if (n_files == 0)
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;
439 else
441 win = ANJUTA_SHELL (windows->data);
445 if (win != NULL)
447 loader = anjuta_shell_get_interface(win, IAnjutaFileLoader, NULL);
449 if (!loader)
450 return;
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 *---------------------------------------------------------------------------*/
465 static void
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);
478 static void
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;
491 static void
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));
507 /* Public functions
508 *---------------------------------------------------------------------------*/
510 AnjutaApplication*
511 anjuta_application_new (void)
513 g_type_init ();
515 return g_object_new (anjuta_application_get_type (),
516 "application-id", "org.gnome.anjuta",
517 "flags", G_APPLICATION_HANDLES_OPEN,
518 NULL);
521 gboolean
522 anjuta_application_get_proper_shutdown (AnjutaApplication *app)
524 return app->priv->proper_shutdown;
527 gboolean
528 anjuta_application_get_no_files (AnjutaApplication *app)
530 return app->priv->no_files;
533 gboolean
534 anjuta_application_get_no_session (AnjutaApplication *app)
536 return app->priv->no_session;
539 const gchar *
540 anjuta_application_get_geometry (AnjutaApplication *app)
542 return app->priv->geometry;
545 AnjutaWindow*
546 anjuta_application_create_window (AnjutaApplication *app)
548 AnjutaPluginManager *plugin_manager;
549 AnjutaProfileManager *profile_manager;
550 AnjutaWindow *win;
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);
573 else
575 gchar *im_file = NULL;
576 im_file = anjuta_res_get_pixmap_file (ANJUTA_PIXMAP_SPLASH_SCREEN);
577 if (im_file)
579 anjuta_status_set_splash (status, im_file, 100);
580 g_free (im_file);
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),
589 NULL);
590 profile_manager = anjuta_shell_get_profile_manager (ANJUTA_SHELL (win),
591 NULL);
593 /* Restore remembered plugins */
594 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,
598 remembered_plugins);
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,
605 TRUE, &error);
606 if (error)
608 anjuta_util_dialog_error (GTK_WINDOW (win), "%s", error->message);
609 g_error_free (error);
610 error = NULL;
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,
620 FALSE, &error);
621 if (error)
623 anjuta_util_dialog_error (GTK_WINDOW (win), "%s", error->message);
624 g_error_free (error);
625 error = NULL;
628 anjuta_profile_set_sync_file (profile, session_profile);
629 g_object_unref (session_profile);
630 g_free (profile_name);
632 /* Load profile */
633 anjuta_profile_manager_freeze (profile_manager);
634 anjuta_profile_manager_push (profile_manager, profile, &error);
635 if (error)
637 anjuta_util_dialog_error (GTK_WINDOW (win), "%s", error->message);
638 g_error_free (error);
639 error = NULL;
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);
647 if (error)
649 anjuta_util_dialog_error (GTK_WINDOW (win), "%s", error->message);
650 g_error_free (error);
651 error = NULL;
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);
659 return win;