/* * Copyright (C) 2007 OpenedHand Ltd. * Authored by: Rob Bradford * * This is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, version 2 of the License. * * This software is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include #include #include #include "plugin.h" #define PREFS_PROP_SDK_ROOT "sdk.root" #define PREFS_PROP_TRIPLET "sdk.triplet" static gpointer anjuta_plugin_sdk_parent_class; static gchar * file_chooser_property_get_cb (AnjutaProperty *prop) { GtkWidget *chooser = NULL; gchar *filename = NULL; chooser = anjuta_property_get_widget (prop); filename = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (chooser)); return filename; } static void file_chooser_property_set_cb (AnjutaProperty *prop, const gchar *value) { GtkWidget *chooser = NULL; chooser = anjuta_property_get_widget (prop); if (value != NULL && chooser != NULL) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser), value); } static void sdk_root_file_chooser_changed_cb (GtkFileChooserButton *button, gpointer userdata) { AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; gchar *filename = NULL; filename = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button)); anjuta_preferences_set (ANJUTA_PREFERENCES (sp->prefs), PREFS_PROP_SDK_ROOT, filename); g_free (filename); } static void update_path (AnjutaPluginSdk *sp) { char *path = NULL; gchar **pathv = NULL; gchar **new_pathv = NULL; gchar **path_it = NULL; gchar **new_path_it = NULL; gchar *new_path_component = NULL; if (sp->triplet != NULL && sp->sdk_root != NULL) { new_path_component = g_build_filename (sp->sdk_root, "bin", NULL); } g_debug ("New path component: %s", new_path_component); /* get current path. do not free */ path = getenv ("PATH"); g_debug ("Current path: %s", path); /* split old path up */ pathv = g_strsplit (path, ":", -1); /* allocate memory for new pathv */ new_pathv = g_malloc0 ((g_strv_length (pathv) + 2) * (sizeof (gchar *))); /* new pathv iterator */ new_path_it = new_pathv; /* insert at the front if we have something to insert */ if (new_path_component) { *new_path_it = new_path_component; new_path_it++; } /* iterate through */ for (path_it = pathv; *path_it != NULL; path_it++) { /* Check for the old component */ if (sp->path_component && g_str_equal (*path_it, sp->path_component)) { path_it++; /* skip over */ } *new_path_it = *path_it; new_path_it++; } /* Create our new path */ path = g_strjoinv (":", new_pathv); setenv ("PATH", path, 1); g_debug ("New path: %s", path); /* Save the component */ g_free (sp->path_component); sp->path_component = new_path_component; } static void update_environment (AnjutaPluginSdk *sp) { gchar *tmp = NULL; g_free (sp->sdk_root); g_free (sp->triplet); sp->sdk_root = anjuta_preferences_get (ANJUTA_PREFERENCES (sp->prefs), PREFS_PROP_SDK_ROOT); sp->triplet = anjuta_preferences_get (ANJUTA_PREFERENCES (sp->prefs), PREFS_PROP_TRIPLET); if (sp->triplet == NULL || sp->sdk_root == NULL) { /* unset environment keys */ unsetenv ("PKG_CONFIG_SYSROOT_DIR"); unsetenv ("PKG_CONFIG_PATH"); unsetenv ("CONFIG_SITE"); } update_path (sp); tmp = g_build_filename (sp->sdk_root, sp->triplet, NULL); setenv ("PKG_CONFIG_SYSROOT_DIR", tmp, 1); g_free (tmp); tmp = g_build_filename (sp->sdk_root, sp->triplet, "lib", "pkgconfig", NULL); setenv ("PKG_CONFIG_PATH", tmp, 1); g_free (tmp); tmp = g_build_filename (sp->sdk_root, "site-config", NULL); setenv ("CONFIG_SITE", tmp, 1); g_free (tmp); } static void cleanup_environment (AnjutaPluginSdk *sp) { g_free (sp->triplet); g_free (sp->sdk_root); sp->triplet = NULL; sp->sdk_root = NULL; update_path (sp); } static void update_configure_opts (AnjutaPluginSdk *sp) { /* * can't do anything to update the option. must instead do it in the * session-load signal */ } /* idle callback used to aggregate updates */ static gboolean update_environment_idle_cb (gpointer userdata) { update_environment ((AnjutaPluginSdk *)userdata); return FALSE; } static void sdk_root_preference_notify_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer userdata) { AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; if (!sp->update_environment_idle) g_idle_add (update_environment_idle_cb, sp); } static void triplet_preference_notify_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer userdata) { AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; if (!sp->update_environment_idle) g_idle_add (update_environment_idle_cb, sp); update_configure_opts (sp); } /* * cb that gets fired when the session is loaded up, we use this fiddle with * the configure option to add our --host option for cross compiling */ static void load_session_cb (AnjutaShell *shell, AnjutaSessionPhase phase, AnjutaSession *session, gpointer userdata) { AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; gchar *tmp = NULL; gchar *configure_opts = NULL; tmp = anjuta_session_get_string (session, "Build", "Configure parameters"); if (sp->triplet) { if (tmp != NULL) { /* check if already present */ if (strstr (tmp, "--host=") == NULL) { configure_opts = g_strdup_printf ("%s --host=%s", tmp, sp->triplet); } } else { configure_opts = g_strdup_printf ("--host=%s", sp->triplet); } anjuta_session_set_string (session, "Build", "Configure parameters", configure_opts); } g_free (configure_opts); g_free (tmp); } static void anjuta_plugin_sdk_setup_preferences (AnjutaPluginSdk *sp) { GtkWidget *vbox; GtkSizeGroup *opts_labels_group; GtkSizeGroup *opts_fields_group; GtkWidget *frame; GtkWidget *inner_vbox; GtkWidget *hbox; GtkWidget *label; GtkWidget *chooser; GtkWidget *entry; GtkWidget *inner_alignment; gboolean res; sp->prefs = anjuta_preferences_new (); /* Create main vbox */ vbox = gtk_vbox_new (FALSE, 6); gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); /* Frame for options */ frame = gtk_frame_new (_("SDK options")); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 2); label = gtk_frame_get_label_widget (GTK_FRAME (frame)); gtk_label_set_use_markup (GTK_LABEL (label), TRUE); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE); /* size groups for files */ opts_labels_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); opts_fields_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); /* Pack inner vbox */ inner_vbox = gtk_vbox_new (FALSE, 6); inner_alignment = gtk_alignment_new (0, 0.5, 1, 1); g_object_set (inner_alignment, "left-padding", 12, "top-padding", 6, NULL); gtk_container_add (GTK_CONTAINER (inner_alignment), inner_vbox); gtk_container_add (GTK_CONTAINER (frame), inner_alignment); /* Widgets for sdk root */ hbox = gtk_hbox_new (FALSE, 6); gtk_box_pack_start (GTK_BOX (inner_vbox), hbox, TRUE, FALSE, 0); /* label */ label = gtk_label_new (_("SDK root: ")); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); gtk_size_group_add_widget (opts_labels_group, label); gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); /* chooser */ chooser = gtk_file_chooser_button_new (_("Select SDK root"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); sp->sdk_root_chooser = chooser; gtk_box_pack_start (GTK_BOX (hbox), chooser, TRUE, TRUE, 0); gtk_size_group_add_widget (opts_fields_group, label); /* register prop */ res = anjuta_preferences_register_property_custom (ANJUTA_PREFERENCES (sp->prefs), chooser, PREFS_PROP_SDK_ROOT, NULL, ANJUTA_PROPERTY_DATA_TYPE_TEXT, 0, file_chooser_property_set_cb, file_chooser_property_get_cb); if (!res) g_warning ("Error adding preference for SDK root"); /* signal for file changed */ g_signal_connect (chooser, "current-folder-changed", (GCallback)sdk_root_file_chooser_changed_cb, sp); /* Widgets for toolchain triplet */ hbox = gtk_hbox_new (FALSE, 6); gtk_box_pack_start (GTK_BOX (inner_vbox), hbox, TRUE, FALSE, 0); /* label */ label = gtk_label_new (_("Toolchain triplet: ")); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); gtk_size_group_add_widget (opts_labels_group, label); gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); /* entry */ entry = gtk_entry_new (); sp->triplet_entry = entry; gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0); gtk_size_group_add_widget (opts_fields_group, label); /* register prop */ res = anjuta_preferences_register_property_raw (ANJUTA_PREFERENCES (sp->prefs), entry, PREFS_PROP_TRIPLET, NULL, 0, ANJUTA_PROPERTY_OBJECT_TYPE_ENTRY, ANJUTA_PROPERTY_DATA_TYPE_TEXT); if (!res) g_warning ("Error adding preference for triplet"); /* Add a label requesting restart */ label = gtk_label_new (_("Anjuta must be restarted for these changes to take effect")); gtk_label_set_use_markup (GTK_LABEL (label), TRUE); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 2); gtk_widget_show_all (vbox); /* add page */ anjuta_preferences_dialog_add_page (ANJUTA_PREFERENCES_DIALOG (sp->prefs), _("SDK"), "SDK", NULL, vbox); /* callbacks for when the preferences are changed */ sp->sdk_root_notifyid = anjuta_preferences_notify_add (ANJUTA_PREFERENCES (sp->prefs), PREFS_PROP_SDK_ROOT, sdk_root_preference_notify_cb, sp, NULL); sp->triplet_notifyid = anjuta_preferences_notify_add (ANJUTA_PREFERENCES (sp->prefs), PREFS_PROP_TRIPLET, triplet_preference_notify_cb, sp, NULL); } static void anjuta_plugin_sdk_unsetup_preferences (AnjutaPluginSdk *sp) { /* remove page */ anjuta_preferences_dialog_remove_page (ANJUTA_PREFERENCES_DIALOG (sp->prefs), "SDK"); /* remove callbacks */ anjuta_preferences_notify_remove (ANJUTA_PREFERENCES (sp->prefs), sp->sdk_root_notifyid); anjuta_preferences_notify_remove (ANJUTA_PREFERENCES (sp->prefs), sp->triplet_notifyid); } static gboolean anjuta_plugin_sdk_activate (AnjutaPlugin *plugin) { AnjutaUI *ui; AnjutaPluginSdk *sp = (AnjutaPluginSdk *)plugin; ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (plugin)->shell, NULL); anjuta_plugin_sdk_setup_preferences (sp); update_environment (sp); /* hook up a signal for session loading */ g_signal_connect (ANJUTA_PLUGIN (plugin)->shell, "load-session", (GCallback)load_session_cb, sp); return TRUE; } static gboolean anjuta_plugin_sdk_deactivate (AnjutaPlugin *plugin) { AnjutaPluginSdk *sp = (AnjutaPluginSdk *)plugin; anjuta_plugin_sdk_unsetup_preferences (sp); cleanup_environment (sp); g_signal_handlers_disconnect_by_func (ANJUTA_PLUGIN (plugin)->shell, load_session_cb, sp); g_free (sp->sdk_root); g_free (sp->triplet); g_free (sp->path_component); return TRUE; } static void anjuta_plugin_sdk_finalize (GObject *obj) { if (G_OBJECT_CLASS (anjuta_plugin_sdk_parent_class)->finalize) G_OBJECT_CLASS (anjuta_plugin_sdk_parent_class)->finalize (obj); } static void anjuta_plugin_sdk_dispose (GObject *obj) { AnjutaPluginSdk *sp = (AnjutaPluginSdk *)obj; if (sp->prefs) { gtk_widget_destroy (sp->prefs); sp->prefs = NULL; } if (G_OBJECT_CLASS (anjuta_plugin_sdk_parent_class)->dispose) G_OBJECT_CLASS (anjuta_plugin_sdk_parent_class)->dispose (obj); } static void anjuta_plugin_sdk_instance_init (GObject *obj) { } static void anjuta_plugin_sdk_class_init (GObjectClass *klass) { AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass); anjuta_plugin_sdk_parent_class = g_type_class_peek_parent (klass); plugin_class->activate = anjuta_plugin_sdk_activate; plugin_class->deactivate = anjuta_plugin_sdk_deactivate; klass->finalize = anjuta_plugin_sdk_finalize; klass->dispose = anjuta_plugin_sdk_dispose; } ANJUTA_PLUGIN_BOILERPLATE (AnjutaPluginSdk, anjuta_plugin_sdk); ANJUTA_SIMPLE_PLUGIN (AnjutaPluginSdk, anjuta_plugin_sdk);