Added keywords in desktop file.
[anjuta.git] / src / anjuta-application.c
bloba7566955641bd66e76a7a74fe55d8b991ed305d7
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 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 {
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 = 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 */
78 remembered_plugins =
79 anjuta_plugin_manager_get_remembered_plugins (plugin_manager);
80 g_settings_set_string (win->settings,
81 ANJUTA_REMEMBERED_PLUGINS,
82 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));
96 /* Do not exit now */
97 return TRUE;
98 case ANJUTA_SAVE_PROMPT_RESPONSE_DISCARD:
99 case ANJUTA_SAVE_PROMPT_RESPONSE_SAVE_CLOSE:
100 /* exit now */
101 break;
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
115 * default session
117 current_profile = anjuta_profile_manager_get_current (profile_manager);
118 if (strcmp (anjuta_profile_get_name (current_profile), "user") == 0)
120 gchar *session_dir;
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));
130 /* Shutdown */
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));
138 return FALSE;
141 static void
142 on_profile_scoped (AnjutaProfileManager *profile_manager,
143 AnjutaProfile *profile, AnjutaWindow *win)
145 gchar *session_dir;
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)
150 return;
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;
160 else
162 session_dir = USER_SESSION_PATH_NEW;
165 if (first_time)
167 first_time = FALSE;
169 else
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",
175 "Files", NULL);
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);
185 static void
186 on_profile_descoped (AnjutaProfileManager *profile_manager,
187 AnjutaProfile *profile, AnjutaWindow *win)
189 gchar *session_dir;
191 DEBUG_PRINT ("Profile descoped: %s", anjuta_profile_get_name (profile));
192 if (strcmp (anjuta_profile_get_name (profile), USER_PROFILE_NAME) != 0)
193 return;
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 */
207 static gchar *
208 create_anjuta_application_hint (const gchar *geometry,
209 gboolean no_splash,
210 gboolean no_session,
211 gboolean no_files)
213 GString *hint;
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 */
230 static void
231 anjuta_application_parse_hint (AnjutaApplication *app,
232 const gchar* hint)
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, "-");
243 if (end != NULL)
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;
254 static void
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 *---------------------------------------------------------------------------*/
268 static gboolean
269 anjuta_application_local_command_line (GApplication *application,
270 gchar ***arguments,
271 gint *exit_status)
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,
285 &geometry,
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,
293 &no_splash,
294 N_("Do not show the splash screen"),
295 NULL
298 "no-client", 'c', 0, G_OPTION_ARG_NONE,
299 &no_client,
300 N_("Start a new instance and do not open the file in an existing instance"),
301 NULL
304 "no-session", 'n', 0, G_OPTION_ARG_NONE,
305 &no_session,
306 N_("Do not open last session on startup"),
307 NULL
310 "no-files", 'f', 0, G_OPTION_ARG_NONE,
311 &no_files,
312 N_("Do not open last project and files on startup"),
313 NULL
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)"),
319 NULL
322 "version", 'v', 0, G_OPTION_ARG_NONE,
323 &version,
324 N_("Display program version"),
325 NULL
328 G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY,
329 &filenames,
330 NULL,
331 NULL
333 {NULL}
335 GOptionContext *context;
336 gint argc = 0;
337 gchar **argv = NULL;
338 GError *error = NULL;
339 gchar *hint = NULL;
340 GPtrArray *files;
342 context = g_option_context_new (_("- Integrated Development Environment"));
343 #ifdef ENABLE_NLS
344 g_option_context_add_main_entries (context, anjuta_options, GETTEXT_PACKAGE);
345 #else
346 g_option_context_add_main_entries (context, anjuta_options, NULL);
347 #endif
348 g_option_context_add_group (context, gtk_get_option_group (TRUE));
350 /* Parse arguments */
351 argv = *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;
360 return TRUE;
362 *exit_status = EXIT_SUCCESS;
363 g_option_context_free (context);
366 /* Display version */
367 if (version)
369 g_print ("%s\n", PACKAGE_STRING);
370 return TRUE;
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 ();
380 if (filenames)
382 gchar** filename;
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);
394 /* Open 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);
398 g_free (hint);
400 return TRUE;
403 static void
404 anjuta_application_open (GApplication *application,
405 GFile **files,
406 gint n_files,
407 const gchar* hint)
409 GList *windows;
410 AnjutaShell *win;
411 IAnjutaFileLoader* loader = NULL;
412 gint i;
414 anjuta_application_parse_hint (ANJUTA_APPLICATION (application), hint);
416 windows = gtk_application_get_windows (GTK_APPLICATION (application));
417 if (windows == NULL)
419 if (n_files == 0)
421 win = ANJUTA_SHELL (anjuta_application_create_window (ANJUTA_APPLICATION (application)));
423 else
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;
431 else
433 if (n_files == 0)
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;
440 else
442 win = ANJUTA_SHELL (windows->data);
446 if (win != NULL)
448 loader = anjuta_shell_get_interface(win, IAnjutaFileLoader, NULL);
450 if (!loader)
451 return;
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 *---------------------------------------------------------------------------*/
466 static void
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);
479 static void
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;
492 static void
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));
508 /* Public functions
509 *---------------------------------------------------------------------------*/
511 AnjutaApplication*
512 anjuta_application_new (void)
514 g_type_init ();
516 return g_object_new (anjuta_application_get_type (),
517 "application-id", "org.gnome.anjuta",
518 "flags", G_APPLICATION_HANDLES_OPEN,
519 NULL);
522 gboolean
523 anjuta_application_get_proper_shutdown (AnjutaApplication *app)
525 return app->priv->proper_shutdown;
528 gboolean
529 anjuta_application_get_no_files (AnjutaApplication *app)
531 return app->priv->no_files;
534 gboolean
535 anjuta_application_get_no_session (AnjutaApplication *app)
537 return app->priv->no_session;
540 const gchar *
541 anjuta_application_get_geometry (AnjutaApplication *app)
543 return app->priv->geometry;
546 AnjutaWindow*
547 anjuta_application_create_window (AnjutaApplication *app)
549 AnjutaPluginManager *plugin_manager;
550 AnjutaProfileManager *profile_manager;
551 AnjutaWindow *win;
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);
574 else
576 gchar *im_file = NULL;
577 im_file = anjuta_res_get_pixmap_file (ANJUTA_PIXMAP_SPLASH_SCREEN);
578 if (im_file)
580 anjuta_status_set_splash (status, im_file, 100);
581 g_free (im_file);
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),
590 NULL);
591 profile_manager = anjuta_shell_get_profile_manager (ANJUTA_SHELL (win),
592 NULL);
594 /* Restore remembered plugins */
595 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,
599 remembered_plugins);
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,
606 TRUE, &error);
607 if (error)
609 anjuta_util_dialog_error (GTK_WINDOW (win), "%s", error->message);
610 g_error_free (error);
611 error = NULL;
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,
621 FALSE, &error);
622 if (error)
624 anjuta_util_dialog_error (GTK_WINDOW (win), "%s", error->message);
625 g_error_free (error);
626 error = NULL;
629 anjuta_profile_set_sync_file (profile, session_profile);
630 g_object_unref (session_profile);
631 g_free (profile_name);
633 /* Load profile */
634 anjuta_profile_manager_freeze (profile_manager);
635 anjuta_profile_manager_push (profile_manager, profile, &error);
636 if (error)
638 anjuta_util_dialog_error (GTK_WINDOW (win), "%s", error->message);
639 g_error_free (error);
640 error = NULL;
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);
648 if (error)
650 anjuta_util_dialog_error (GTK_WINDOW (win), "%s", error->message);
651 g_error_free (error);
652 error = NULL;
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);
660 return win;