static PeasPluginInfo *
ide_application_locate_tool (IdeApplication *self,
                             const gchar    *tool_name)
{
  PeasEngine *engine;
  const GList *list;

  g_assert (IDE_IS_APPLICATION (self));
  g_assert (tool_name != NULL);

  engine = peas_engine_get_default ();
  list = peas_engine_get_plugin_list (engine);

  for (; list != NULL; list = list->next)
    {
      PeasPluginInfo *plugin_info = list->data;
      const gchar *name;

      name = peas_plugin_info_get_external_data (plugin_info, "Tool-Name");
      if (g_strcmp0 (name, tool_name) == 0)
        return plugin_info;
    }

  return NULL;
}
void
ide_application_add_test (IdeApplication               *self,
                          const gchar                  *test_name,
                          IdeApplicationTest            test_func,
                          IdeApplicationTestCompletion  test_completion)
{
  AsyncTest *test;

  IDE_ENTRY;

  g_return_if_fail (IDE_IS_APPLICATION (self));
  g_return_if_fail (test_name != NULL);
  g_return_if_fail (test_func != NULL);

  if (test_completion == NULL)
    test_completion = ide_application_task_completion;

  test = g_slice_new0 (AsyncTest);
  test->name = g_strdup (test_name);
  test->test_func = test_func;
  test->test_completion = test_completion;

  self->test_funcs = g_list_append (self->test_funcs, test);

  IDE_EXIT;
}
Пример #3
0
static void
ide_application_actions_help (GSimpleAction *action,
                              GVariant      *param,
                              gpointer       user_data)
{
  IdeApplication *self = user_data;
  GtkWindow *focused_window= NULL;
  GdkScreen *screen = NULL;
  GError *err = NULL;

  g_assert (IDE_IS_APPLICATION (self));

  focused_window = gtk_application_get_active_window (GTK_APPLICATION (self));

  screen = gtk_window_get_screen (focused_window);
  gtk_show_uri (screen,
                "help:gnome-builder",
                gtk_get_current_event_time (),
                &err);
  if (err)
    {
      g_message ("Unable to open help: %s\n", err->message);
      g_error_free (err);
    }
}
static gboolean
maybe_open_with_existing_workspace (IdeApplication *self,
                                    GFile          *file,
                                    const gchar    *hint,
                                    GCancellable   *cancellable)
{
  GList *windows;
  GList *iter;

  g_assert (IDE_IS_APPLICATION (self));
  g_assert (G_IS_FILE (file));

  windows = gtk_application_get_windows (GTK_APPLICATION (self));

  for (iter = windows; iter != NULL; iter = iter->next)
    {
      GtkWindow *window = iter->data;

      if (IDE_IS_WORKBENCH (window) &&
          workbench_manages_file (IDE_WORKBENCH (window), file))
        {
          ide_workbench_open_files_async (IDE_WORKBENCH (window),
                                          &file,
                                          1,
                                          hint,
                                          0,
                                          cancellable,
                                          NULL,
                                          NULL);
          return TRUE;
        }
    }

  return FALSE;
}
Пример #5
0
void
ide_application_load_addins (IdeApplication *self)
{
  g_return_if_fail (IDE_IS_APPLICATION (self));

  self->addins = peas_extension_set_new (peas_engine_get_default (),
                                         IDE_TYPE_APPLICATION_ADDIN,
                                         NULL);

  g_signal_connect_object (self->addins,
                           "extension-added",
                           G_CALLBACK (ide_application_addin_added),
                           self,
                           0);

  g_signal_connect_object (self->addins,
                           "extension-removed",
                           G_CALLBACK (ide_application_addin_removed),
                           self,
                           0);

  peas_extension_set_foreach (self->addins,
                              ide_application_addin_added,
                              self);
}
Пример #6
0
static void
ide_application_unload_plugin_resources (IdeApplication *self,
                                         PeasPluginInfo *plugin_info,
                                         PeasEngine     *engine)
{
  g_autofree gchar *path = NULL;
  const gchar *data_dir;
  const gchar *module_name;

  g_assert (IDE_IS_APPLICATION (self));
  g_assert (plugin_info != NULL);
  g_assert (PEAS_IS_ENGINE (engine));

  module_name = peas_plugin_info_get_module_name (plugin_info);
  data_dir = peas_plugin_info_get_data_dir (plugin_info);

  /* Remove embedded gresources */
  path = g_strdup_printf ("resource:///org/gnome/builder/plugins/%s/", module_name);
  dzl_application_remove_resources (DZL_APPLICATION (self), path);

  /* Remove on disk resources */
  if (!g_str_has_prefix (data_dir, "resource://"))
    dzl_application_remove_resources (DZL_APPLICATION (self), data_dir);

  ide_application_plugins_unload_plugin_gresources (self, plugin_info, engine);
}
static void
present_greeter_with_surface (GSimpleAction *action,
                              GVariant      *param,
                              gpointer       user_data)
{
  GbpGreeterApplicationAddin *self = user_data;
  g_autoptr(IdeWorkbench) workbench = NULL;
  IdeGreeterWorkspace *workspace;
  const gchar *name;

  g_assert (!action || G_IS_SIMPLE_ACTION (action));
  g_assert (!param || g_variant_is_of_type (param, G_VARIANT_TYPE_STRING));
  g_assert (GBP_IS_GREETER_APPLICATION_ADDIN (self));
  g_assert (IDE_IS_APPLICATION (self->application));

  workbench = ide_workbench_new ();
  ide_application_add_workbench (self->application, workbench);

  workspace = ide_greeter_workspace_new (self->application);
  ide_workbench_add_workspace (workbench, IDE_WORKSPACE (workspace));

  if (param != NULL && (name = g_variant_get_string (param, NULL)) && !ide_str_empty0 (name))
    ide_workspace_set_visible_surface_name (IDE_WORKSPACE (workspace), name);

  ide_workbench_focus_workspace (workbench, IDE_WORKSPACE (workspace));
}
Пример #8
0
static void
ide_application_plugins_enabled_changed (IdeApplication *self,
                                         const gchar    *key,
                                         GSettings      *settings)
{
  PeasPluginInfo *plugin_info;
  PeasEngine *engine;
  gboolean enabled;

  g_assert (IDE_IS_APPLICATION (self));
  g_assert (dzl_str_equal0 (key, "enabled"));
  g_assert (G_IS_SETTINGS (settings));

  enabled = g_settings_get_boolean (settings, key);

  engine = peas_engine_get_default ();

  plugin_info = g_object_get_data (G_OBJECT (settings), "PEAS_PLUGIN_INFO");
  g_assert (plugin_info != NULL);

  if (enabled &&
      ide_application_can_load_plugin (self, plugin_info) &&
      !peas_plugin_info_is_loaded (plugin_info))
    peas_engine_load_plugin (engine, plugin_info);
  else if (!enabled && peas_plugin_info_is_loaded (plugin_info))
    peas_engine_unload_plugin (engine, plugin_info);
}
static PeasPluginInfo *
ide_application_locate_worker (IdeApplication *self,
                               const gchar    *worker_name)
{
  PeasEngine *engine;
  const GList *list;

  g_assert (IDE_IS_APPLICATION (self));
  g_assert (worker_name != NULL);

  engine = peas_engine_get_default ();
  list = peas_engine_get_plugin_list (engine);

  for (; list != NULL; list = list->next)
    {
      PeasPluginInfo *plugin_info = list->data;
      const gchar *name;

      name = peas_plugin_info_get_module_name (plugin_info);
      if (g_strcmp0 (name, worker_name) == 0)
        return plugin_info;
    }

  return NULL;
}
Пример #10
0
void
ide_application_actions_update (IdeApplication *self)
{
  GList *windows;
  GAction *action;
  gboolean enabled;

  g_assert (IDE_IS_APPLICATION (self));

  /*
   * We only enable the preferences action if we have a workbench open
   * that is past the greeter.
   */
  action = g_action_map_lookup_action (G_ACTION_MAP (self), "preferences");
  enabled = FALSE;
  for (windows = gtk_application_get_windows (GTK_APPLICATION (self));
       windows != NULL;
       windows = windows->next)
    {
      GtkWindow *window = windows->data;

      if (IDE_IS_WORKBENCH (window) &&
          !ide_str_equal0 ("greeter",
                           ide_workbench_get_visible_perspective_name (IDE_WORKBENCH (window))))
        {
          enabled = TRUE;
          break;
        }
    }
  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enabled);
}
static void
gbp_greeter_application_addin_handle_command_line (IdeApplicationAddin     *addin,
                                                   IdeApplication          *application,
                                                   GApplicationCommandLine *cmdline)
{
  GbpGreeterApplicationAddin *self = (GbpGreeterApplicationAddin *)addin;
  g_auto(GStrv) argv = NULL;
  GVariantDict *dict;
  const gchar *clone_uri = NULL;
  gint argc;

  g_assert (GBP_IS_GREETER_APPLICATION_ADDIN (self));
  g_assert (IDE_IS_APPLICATION (application));
  g_assert (G_IS_APPLICATION_COMMAND_LINE (cmdline));

  dict = g_application_command_line_get_options_dict (cmdline);
  argv = ide_application_get_argv (IDE_APPLICATION (application), cmdline);
  argc = g_strv_length (argv);

  /*
   * If we are processing the arguments for the startup of the primary
   * instance, then we want to show the greeter if no arguments are
   * provided. (That means argc == 1, the programe executable).
   *
   * Also, if they provided --greeter or -g we'll show a new greeter.
   */
  if ((!g_application_command_line_get_is_remote (cmdline) && argc == 1) ||
      g_variant_dict_contains (dict, "greeter"))
    {
      present_greeter_with_surface (NULL, NULL, addin);
      return;
    }

  /*
   * If the --clone=URI option was provided, switch the greeter to the
   * clone surface and begin cloning.
   */
  if (dict != NULL && g_variant_dict_lookup (dict, "clone", "&s", &clone_uri))
    {
      IdeGreeterWorkspace *workspace;
      IdeWorkbench *workbench;
      IdeSurface *surface;

      workbench = ide_workbench_new ();
      ide_application_add_workbench (self->application, workbench);

      workspace = ide_greeter_workspace_new (self->application);
      ide_workbench_add_workspace (workbench, IDE_WORKSPACE (workspace));

      surface = ide_workspace_get_surface_by_name (IDE_WORKSPACE (workspace), "clone");
      ide_workspace_set_visible_surface (IDE_WORKSPACE (workspace), surface);

      if (IDE_IS_CLONE_SURFACE (surface))
        ide_clone_surface_set_uri (IDE_CLONE_SURFACE (surface), clone_uri);

      ide_workbench_focus_workspace (workbench, IDE_WORKSPACE (workspace));
    }
}
Пример #12
0
gboolean
ide_application_open_finish (IdeApplication  *self,
                             GAsyncResult    *result,
                             GError         **error)
{
  g_return_val_if_fail (IDE_IS_APPLICATION (self), FALSE);

  return g_task_propagate_boolean (G_TASK (result), error);
}
Пример #13
0
/**
 * ide_application_addin_unload:
 * @self: An #IdeApplicationAddin.
 * @application: An #IdeApplication.
 *
 * This inteface method is called when the application is shutting down or the
 * plugin has been unloaded.
 *
 * Use this function to cleanup after anything setup in
 * ide_application_addin_load().
 *
 * Since: 3.32
 */
void
ide_application_addin_unload (IdeApplicationAddin *self,
                              IdeApplication      *application)
{
  g_return_if_fail (IDE_IS_APPLICATION_ADDIN (self));
  g_return_if_fail (IDE_IS_APPLICATION (application));

  IDE_APPLICATION_ADDIN_GET_IFACE (self)->unload (self, application);
}
Пример #14
0
static gboolean
ide_application_can_load_plugin (IdeApplication *self,
                                 PeasPluginInfo *plugin_info)
{
  const gchar *module_name;

  g_assert (IDE_IS_APPLICATION (self));
  g_assert (plugin_info != NULL);

  module_name = peas_plugin_info_get_module_name (plugin_info);

  for (guint i = 0; i < G_N_ELEMENTS (blacklisted_plugins); i++)
    {
      if (g_strcmp0 (module_name, blacklisted_plugins[i]) == 0)
        return FALSE;
    }

  if (self->mode == IDE_APPLICATION_MODE_WORKER)
    {
      if (self->worker != plugin_info)
        return FALSE;
    }

  if (self->mode == IDE_APPLICATION_MODE_TOOL)
    {
      /*
       * Plugins might provide critical features needed
       * to load a project (build system, vcs, etc).
       */
      return TRUE;
    }

  /*
   * TODO: Do ABI check on external data.
   *
   * Right now, we don't have any way to check that the plugin is implementing
   * the same version of the API/ABI that the application exports. There are a
   * couple ways we could go about doing this.
   *
   * One approach might be to generate UUIDs for each plugin structure,
   * and update it every time the structure changes. However, plenty of changes
   * can be safe for existing modules. So perhaps we need something that has
   * a revision since last break. Then plugins would specify which version
   * and revision of an interface they require.
   *
   * Imagine the scenario that FooIface added the method frobnicate(). Previous
   * extensions for FooIface are perfectly happy to keep on working, but a new
   * addin that requires FooIface may require frobnicate()'s existance. So while
   * the ABI hasn't broken, some plugins will require a newer revision.
   *
   * This is not entirely different from libtool's interface age. Presumably,
   * Gedit's IAge is similar here, but we would need it per-structure.
   */

  return TRUE;
}
Пример #15
0
/**
 * ide_application_addin_add_option_entries:
 * @self: a #IdeApplicationAddin
 * @application: an #IdeApplication
 *
 * This function is called to allow the application a chance to add various
 * command-line options to the #GOptionContext. See
 * g_application_add_main_option_entries() for more information on how to
 * add arguments.
 *
 * See ide_application_addin_handle_command_line() for how to handle arguments
 * once command line argument processing begins.
 *
 * Make sure you set `X-At-Startup=true` in your `.plugin` file so that the
 * plugin is loaded early during startup or this virtual function will not
 * be called.
 *
 * Since: 3.32
 */
void
ide_application_addin_add_option_entries (IdeApplicationAddin *self,
                                          IdeApplication      *application)
{
  g_return_if_fail (IDE_IS_APPLICATION_ADDIN (self));
  g_return_if_fail (IDE_IS_APPLICATION (application));

  if (IDE_APPLICATION_ADDIN_GET_IFACE (self)->add_option_entries)
    IDE_APPLICATION_ADDIN_GET_IFACE (self)->add_option_entries (self, application);
}
Пример #16
0
/**
 * ide_application_addin_activate:
 * @self: a #IdeApplicationAddin
 * @application: an #ideApplication
 *
 * This function is activated when the GApplication::activate signal is
 * emitted.
 *
 * Since: 3.32
 */
void
ide_application_addin_activate (IdeApplicationAddin *self,
                                IdeApplication      *application)
{
  g_return_if_fail (IDE_IS_APPLICATION_ADDIN (self));
  g_return_if_fail (IDE_IS_APPLICATION (application));

  if (IDE_APPLICATION_ADDIN_GET_IFACE (self)->activate)
    IDE_APPLICATION_ADDIN_GET_IFACE (self)->activate (self, application);
}
Пример #17
0
static void
ide_application_actions_open_project (GSimpleAction *action,
                                      GVariant      *variant,
                                      gpointer       user_data)
{
  IdeApplication *self = user_data;

  g_assert (IDE_IS_APPLICATION (self));

  ide_application_show_projects_window (self);
}
Пример #18
0
static void
ide_application_actions_new_project (GSimpleAction *action,
                                     GVariant      *variant,
                                     gpointer       user_data)
{
  IdeApplication *self = user_data;

  g_assert (IDE_IS_APPLICATION (self));

  ide_application_actions_load_workbench_view (self, "GbpCreateProjectGenesisAddin", NULL);
}
Пример #19
0
/**
 * ide_application_addin_handle_command_line:
 * @self: a #IdeApplicationAddin
 * @application: an #IdeApplication
 * @cmdline: a #GApplicationCommandLine
 *
 * This function is called to allow the addin to procses command line arguments
 * that were parsed based on options added in
 * ide_application_addin_add_option_entries().
 *
 * See g_application_command_line_get_option_dict() for more information.
 *
 * Since: 3.32
 */
void
ide_application_addin_handle_command_line (IdeApplicationAddin     *self,
                                           IdeApplication          *application,
                                           GApplicationCommandLine *cmdline)
{
  g_return_if_fail (IDE_IS_APPLICATION_ADDIN (self));
  g_return_if_fail (IDE_IS_APPLICATION (application));
  g_return_if_fail (G_IS_APPLICATION_COMMAND_LINE (cmdline));

  if (IDE_APPLICATION_ADDIN_GET_IFACE (self)->handle_command_line)
    IDE_APPLICATION_ADDIN_GET_IFACE (self)->handle_command_line (self, application, cmdline);
}
static void
new_window (GSimpleAction *action,
            GVariant      *param,
            gpointer       user_data)
{
  GbpGreeterApplicationAddin *self = user_data;

  g_assert (!action || G_IS_SIMPLE_ACTION (action));
  g_assert (GBP_IS_GREETER_APPLICATION_ADDIN (self));
  g_assert (IDE_IS_APPLICATION (self->application));

  present_greeter_with_surface (NULL, NULL, self);
}
Пример #21
0
/**
 * ide_application_addin_open:
 * @self: a #IdeApplicationAddin
 * @application: an #ideApplication
 * @files: (array length=n_files) (element-type GFile): an array of #GFiles
 * @n_files: the length of @files
 * @hint: a hint provided by the calling instance
 *
 * This function is activated when the #GApplication::open signal is emitted.
 *
 * Since: 3.32
 */
void
ide_application_addin_open (IdeApplicationAddin  *self,
                            IdeApplication       *application,
                            GFile               **files,
                            gint                  n_files,
                            const gchar          *hint)
{
  g_return_if_fail (IDE_IS_APPLICATION_ADDIN (self));
  g_return_if_fail (IDE_IS_APPLICATION (application));

  if (IDE_APPLICATION_ADDIN_GET_IFACE (self)->open)
    IDE_APPLICATION_ADDIN_GET_IFACE (self)->open (self, application, files, n_files, hint);
}
static void
gbp_greeter_application_addin_activate (IdeApplicationAddin *addin,
                                        IdeApplication      *app)
{
  GtkWindow *window;

  g_assert (IDE_IS_MAIN_THREAD ());
  g_assert (GBP_IS_GREETER_APPLICATION_ADDIN (addin));
  g_assert (IDE_IS_APPLICATION (app));

  if (!(window = gtk_application_get_active_window (GTK_APPLICATION (app))))
    present_greeter_with_surface (NULL, NULL, addin);
}
Пример #23
0
static void
ide_application_actions_load_flatpak (GSimpleAction *action,
                                      GVariant      *args,
                                      gpointer       user_data)
{
  IdeApplication *self = user_data;
  const gchar *manifest = NULL;

  g_assert (IDE_IS_APPLICATION (self));

  manifest = g_variant_get_string (args, NULL);
  ide_application_actions_load_workbench_view (self, "GbpFlatpakGenesisAddin", manifest);
}
static void
gbp_greeter_application_addin_unload (IdeApplicationAddin *addin,
                                      IdeApplication      *application)
{
  GbpGreeterApplicationAddin *self = (GbpGreeterApplicationAddin *)addin;

  g_assert (GBP_IS_GREETER_APPLICATION_ADDIN (self));
  g_assert (IDE_IS_APPLICATION (application));

  for (guint i = 0; i < G_N_ELEMENTS (actions); i++)
    g_action_map_remove_action (G_ACTION_MAP (application), actions[i].name);

  self->application = NULL;
}
Пример #25
0
static void
ide_application_actions_quit (GSimpleAction *action,
                              GVariant      *param,
                              gpointer       user_data)
{
  IdeApplication *self = user_data;

  IDE_ENTRY;

  g_assert (IDE_IS_APPLICATION (self));

  g_application_quit (G_APPLICATION (self));

  IDE_EXIT;
}
Пример #26
0
void
ide_application_load_plugins (IdeApplication *self)
{
  PeasEngine *engine;
  const GList *list;

  g_return_if_fail (IDE_IS_APPLICATION (self));

  engine = peas_engine_get_default ();

  list = peas_engine_get_plugin_list (engine);

  for (; list; list = list->next)
    {
      PeasPluginInfo *plugin_info = list->data;
      GSettings *settings;
      const gchar *module_name;

      module_name = peas_plugin_info_get_module_name (plugin_info);
      settings = _ide_application_plugin_get_settings (self, module_name);

      g_object_set_data (G_OBJECT (settings), "PEAS_PLUGIN_INFO", plugin_info);

      g_signal_connect_object (settings,
                               "changed::enabled",
                               G_CALLBACK (ide_application_plugins_enabled_changed),
                               self,
                               G_CONNECT_SWAPPED);

      if (!g_settings_get_boolean (settings, "enabled"))
        continue;

      /*
       * If we are running the unit tests, we don't want to load plugins here,
       * but defer until the test is loading to perform the loading.  However,
       * we do want all of the other machinery above to be setup.
       */
      if (self->mode == IDE_APPLICATION_MODE_TESTS)
        continue;

      if (ide_application_can_load_plugin (self, plugin_info))
        {
          g_debug ("Loading plugin \"%s\"",
                   peas_plugin_info_get_module_name (plugin_info));
          peas_engine_load_plugin (engine, plugin_info);
        }
    }
}
Пример #27
0
void
ide_application_run_tests (IdeApplication *self)
{
  IDE_ENTRY;

  g_assert (IDE_IS_APPLICATION (self));

  if (self->test_funcs != NULL)
    {
      g_test_log_set_fatal_handler (fatal_log_handler, NULL);
      g_application_hold (G_APPLICATION (self));
      ide_application_run_next_test (self);
    }

  IDE_EXIT;
}
static void
gbp_greeter_application_addin_load (IdeApplicationAddin *addin,
                                    IdeApplication      *application)
{
  GbpGreeterApplicationAddin *self = (GbpGreeterApplicationAddin *)addin;

  g_assert (GBP_IS_GREETER_APPLICATION_ADDIN (self));
  g_assert (IDE_IS_APPLICATION (application));

  self->application = application;

  g_action_map_add_action_entries (G_ACTION_MAP (application),
                                   actions,
                                   G_N_ELEMENTS (actions),
                                   self);
}
static gchar *
ide_application_get_command_help (IdeApplication *self,
                                  gboolean        long_form)
{
  PeasEngine *engine;
  const GList *list;
  GString *str;
  gint count = 0;

  g_assert (IDE_IS_APPLICATION (self));

  engine = peas_engine_get_default ();
  list = peas_engine_get_plugin_list (engine);

  str = g_string_new (NULL);

  if (long_form)
    g_string_append_printf (str, "%s\n", _("Commands:"));

  for (; list != NULL; list = list->next)
    {
      PeasPluginInfo *plugin_info = list->data;
      const gchar *name;
      const gchar *desc;

      name = peas_plugin_info_get_external_data (plugin_info, "Tool-Name");
      desc = peas_plugin_info_get_external_data (plugin_info, "Tool-Description");

      if (name != NULL)
        {
          if (long_form)
            g_string_append_printf (str, "  %-25s %s\n", name, desc);
          else
            g_string_append_printf (str, "%s\n", name);

          count++;
        }
    }

  if (count == 0)
    {
      g_string_free (str, TRUE);
      return NULL;
    }

  return g_strstrip (g_string_free (str, FALSE));
}
Пример #30
0
static void
ide_application_actions_about (GSimpleAction *action,
                               GVariant      *param,
                               gpointer       user_data)
{
  IdeApplication *self = user_data;
  GtkDialog *dialog;
  GtkWindow *parent = NULL;
  GList *iter;
  GList *windows;

  g_assert (IDE_IS_APPLICATION (self));

  windows = gtk_application_get_windows (GTK_APPLICATION (self));

  for (iter = windows; iter; iter = iter->next)
    {
      if (IDE_IS_WORKBENCH (iter->data))
        {
          parent = iter->data;
          break;
        }
    }

  dialog = g_object_new (GTK_TYPE_ABOUT_DIALOG,
                         "artists", ide_application_credits_artists,
                         "authors", ide_application_credits_authors,
                         "comments", _("An IDE for GNOME"),
                         "copyright", "Copyright © 2014—2016 Christian Hergert, et al.",
                         "documenters", ide_application_credits_documenters,
                         "license-type", GTK_LICENSE_GPL_3_0,
                         "logo-icon-name", "org.gnome.Builder",
                         "modal", TRUE,
                         "program-name", _("GNOME Builder"),
                         "transient-for", parent,
                         "translator-credits", _("translator-credits"),
                         "version", PACKAGE_VERSION,
                         "website", "https://wiki.gnome.org/Apps/Builder",
                         "website-label", _("Learn more about GNOME Builder"),
                         NULL);
  gtk_about_dialog_add_credit_section (GTK_ABOUT_DIALOG (dialog),
                                       _("Funded By"),
                                       ide_application_credits_funders);

  g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
  gtk_window_present (GTK_WINDOW (dialog));
}