[gnome-builder/wip/gtk4-port: 1641/1774] libide/foundry: port plugins to IdeRunTool
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/gtk4-port: 1641/1774] libide/foundry: port plugins to IdeRunTool
- Date: Mon, 11 Jul 2022 22:31:52 +0000 (UTC)
commit 16971ae1840012c201ab457a97a212e07bd6d0ed
Author: Christian Hergert <chergert redhat com>
Date: Fri Jun 24 03:35:41 2022 -0700
libide/foundry: port plugins to IdeRunTool
This is the first step in moving away from the IdeRunHandler, and another
step towards removing IdeRunner. I notice some things still wrong with
regular running, debugging and what-not seems to work.
Sysprof is still unported, but this moves us in a direction that is much
nicer for handling that too.
src/libide/foundry/ide-run-manager-private.h | 14 +-
src/libide/foundry/ide-run-manager.c | 273 +++++++----------
src/libide/foundry/ide-run-manager.h | 26 +-
src/libide/gui/ide-run-button.c | 101 ++-----
src/plugins/debuggerui/debuggerui-plugin.c | 4 +
src/plugins/debuggerui/gbp-debugger-tool.c | 146 +++++++++
src/plugins/debuggerui/gbp-debugger-tool.h | 31 ++
src/plugins/debuggerui/gtk/menus.ui | 4 +-
.../debuggerui/ide-debugger-workspace-addin.c | 122 --------
src/plugins/debuggerui/meson.build | 1 +
src/plugins/sysprof/gbp-sysprof-tool.c | 104 +++++++
src/plugins/sysprof/gbp-sysprof-tool.h | 31 ++
src/plugins/sysprof/gbp-sysprof-workspace-addin.c | 278 +----------------
src/plugins/sysprof/meson.build | 3 +
.../sysprof/org.gnome.builder.sysprof.gschema.xml | 16 +
src/plugins/sysprof/sysprof-plugin.c | 4 +
src/plugins/valgrind/gbp-valgrind-tool.c | 204 +++++++++++++
src/plugins/valgrind/gbp-valgrind-tool.h | 31 ++
.../valgrind/gbp-valgrind-workbench-addin.c | 335 ++-------------------
src/plugins/valgrind/meson.build | 3 +
.../org.gnome.builder.valgrind.gschema.xml | 28 ++
src/plugins/valgrind/valgrind-plugin.c | 4 +
22 files changed, 781 insertions(+), 982 deletions(-)
---
diff --git a/src/libide/foundry/ide-run-manager-private.h b/src/libide/foundry/ide-run-manager-private.h
index 847a27a85..8b2e7c762 100644
--- a/src/libide/foundry/ide-run-manager-private.h
+++ b/src/libide/foundry/ide-run-manager-private.h
@@ -24,18 +24,6 @@
G_BEGIN_DECLS
-typedef struct
-{
- char *id;
- char *title;
- char *icon_name;
- int priority;
- IdeRunHandler handler;
- gpointer handler_data;
- GDestroyNotify handler_data_destroy;
-} IdeRunHandlerInfo;
-
-const GList *_ide_run_manager_get_handlers (IdeRunManager *self);
-void _ide_run_manager_drop_caches (IdeRunManager *self);
+void _ide_run_manager_drop_caches (IdeRunManager *self);
G_END_DECLS
diff --git a/src/libide/foundry/ide-run-manager.c b/src/libide/foundry/ide-run-manager.c
index 303c00695..06c78e2ea 100644
--- a/src/libide/foundry/ide-run-manager.c
+++ b/src/libide/foundry/ide-run-manager.c
@@ -41,11 +41,13 @@
#include "ide-deploy-strategy.h"
#include "ide-device-manager.h"
#include "ide-foundry-compat.h"
+#include "ide-no-tool-private.h"
#include "ide-run-command.h"
#include "ide-run-command-provider.h"
#include "ide-run-context.h"
#include "ide-run-manager-private.h"
#include "ide-run-manager.h"
+#include "ide-run-tool-private.h"
#include "ide-runner.h"
#include "ide-runtime.h"
@@ -56,9 +58,8 @@ struct _IdeRunManager
GCancellable *cancellable;
IdeNotification *notif;
IdeExtensionSetAdapter *run_command_providers;
-
- const IdeRunHandlerInfo *handler;
- GList *handlers;
+ IdeExtensionSetAdapter *run_tools;
+ IdeRunTool *run_tool;
IdeSubprocess *current_subprocess;
IdeRunCommand *current_run_command;
@@ -115,7 +116,8 @@ G_DEFINE_TYPE_EXTENDED (IdeRunManager, ide_run_manager, IDE_TYPE_OBJECT, G_TYPE_
enum {
PROP_0,
PROP_BUSY,
- PROP_HANDLER,
+ PROP_ICON_NAME,
+ PROP_RUN_TOOL,
N_PROPS
};
@@ -129,6 +131,57 @@ enum {
static GParamSpec *properties [N_PROPS];
static guint signals [N_SIGNALS];
+static IdeRunTool *
+ide_run_manager_get_run_tool (IdeRunManager *self)
+{
+ g_assert (IDE_IS_RUN_MANAGER (self));
+ g_assert (IDE_IS_RUN_TOOL (self->run_tool));
+
+ return self->run_tool;
+}
+
+void
+ide_run_manager_set_run_tool_from_plugin_info (IdeRunManager *self,
+ PeasPluginInfo *plugin_info)
+{
+ g_autoptr(IdeRunTool) no_tool = NULL;
+ PeasExtension *exten = NULL;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_RUN_MANAGER (self));
+
+ if (plugin_info != NULL)
+ exten = ide_extension_set_adapter_get_extension (self->run_tools, plugin_info);
+
+ if (exten == NULL)
+ {
+ if (IDE_IS_NO_TOOL (self->run_tool))
+ return;
+ no_tool = ide_no_tool_new ();
+ exten = (PeasExtension *)no_tool;
+ }
+
+ if (g_set_object (&self->run_tool, IDE_RUN_TOOL (exten)))
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_RUN_TOOL]);
+}
+
+static void
+ide_run_manager_set_run_tool_from_module_name (IdeRunManager *self,
+ const char *name)
+{
+ PeasPluginInfo *plugin_info = NULL;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_RUN_MANAGER (self));
+
+ g_debug ("Looking for run-tool from module %s", name);
+
+ if (!ide_str_empty0 (name))
+ plugin_info = peas_engine_get_plugin_info (peas_engine_get_default (), name);
+
+ ide_run_manager_set_run_tool_from_plugin_info (self, plugin_info);
+}
+
static void
ide_run_manager_actions_high_contrast (IdeRunManager *self,
GVariant *param)
@@ -203,26 +256,6 @@ ide_run_manager_actions_default_run_command (IdeRunManager *self,
}
}
-static void
-ide_run_handler_info_free (gpointer data)
-{
- IdeRunHandlerInfo *info = data;
-
- g_clear_pointer (&info->id, g_free);
- g_clear_pointer (&info->title, g_free);
- g_clear_pointer (&info->icon_name, g_free);
-
- if (info->handler_data_destroy)
- {
- GDestroyNotify notify = g_steal_pointer (&info->handler_data_destroy);
- gpointer notify_data = g_steal_pointer (&info->handler_data);
-
- notify (notify_data);
- }
-
- g_slice_free (IdeRunHandlerInfo, info);
-}
-
static void
ide_run_manager_update_action_enabled (IdeRunManager *self)
{
@@ -285,18 +318,15 @@ ide_run_manager_dispose (GObject *object)
{
IdeRunManager *self = (IdeRunManager *)object;
- self->handler = NULL;
-
g_clear_pointer (&self->default_run_command, g_free);
g_clear_object (&self->cancellable);
g_clear_object (&self->current_run_command);
g_clear_object (&self->current_subprocess);
+ g_clear_object (&self->run_tool);
ide_clear_and_destroy_object (&self->run_command_providers);
-
- g_list_free_full (self->handlers, ide_run_handler_info_free);
- self->handlers = NULL;
+ ide_clear_and_destroy_object (&self->run_tools);
G_OBJECT_CLASS (ide_run_manager_parent_class)->dispose (object);
}
@@ -317,6 +347,17 @@ ide_run_manager_notify_can_build (IdeRunManager *self,
IDE_EXIT;
}
+const char *
+ide_run_manager_get_icon_name (IdeRunManager *self)
+{
+ g_assert (IDE_IS_RUN_MANAGER (self));
+
+ if (self->run_tool == NULL)
+ return NULL;
+
+ return ide_run_tool_get_icon_name (self->run_tool);
+}
+
static gboolean
initable_init (GInitable *initable,
GCancellable *cancellable,
@@ -347,6 +388,11 @@ initable_init (GInitable *initable,
IDE_TYPE_RUN_COMMAND_PROVIDER,
NULL, NULL);
+ self->run_tools = ide_extension_set_adapter_new (IDE_OBJECT (self),
+ peas_engine_get_default (),
+ IDE_TYPE_RUN_TOOL,
+ NULL, NULL);
+
IDE_RETURN (TRUE);
}
@@ -370,8 +416,12 @@ ide_run_manager_get_property (GObject *object,
g_value_set_boolean (value, ide_run_manager_get_busy (self));
break;
- case PROP_HANDLER:
- g_value_set_string (value, ide_run_manager_get_handler (self));
+ case PROP_ICON_NAME:
+ g_value_set_string (value, ide_run_manager_get_icon_name (self));
+ break;
+
+ case PROP_RUN_TOOL:
+ g_value_set_object (value, ide_run_manager_get_run_tool (self));
break;
default:
@@ -388,17 +438,18 @@ ide_run_manager_class_init (IdeRunManagerClass *klass)
object_class->get_property = ide_run_manager_get_property;
properties [PROP_BUSY] =
- g_param_spec_boolean ("busy",
- "Busy",
- "Busy",
+ g_param_spec_boolean ("busy", NULL, NULL,
FALSE,
(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
- properties [PROP_HANDLER] =
- g_param_spec_string ("handler",
- "Handler",
- "Handler",
- "run",
+ properties [PROP_ICON_NAME] =
+ g_param_spec_string ("icon-name", NULL, NULL,
+ NULL,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_RUN_TOOL] =
+ g_param_spec_object ("run-tool", NULL, NULL,
+ IDE_TYPE_RUN_TOOL,
(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties);
@@ -745,6 +796,7 @@ ide_run_manager_run_subprocess_wait_check_cb (GObject *object,
IDE_ENTRY;
+ g_assert (IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_SUBPROCESS (subprocess));
g_assert (G_IS_ASYNC_RESULT (result));
g_assert (IDE_IS_TASK (task));
@@ -763,6 +815,8 @@ ide_run_manager_run_subprocess_wait_check_cb (GObject *object,
else
ide_task_return_boolean (task, TRUE);
+ _ide_run_tool_emit_stopped (self->run_tool);
+
g_signal_emit (self, signals[STOPPED], 0);
IDE_EXIT;
@@ -782,17 +836,16 @@ ide_run_manager_prepare_run_context (IdeRunManager *self,
g_assert (IDE_IS_RUN_CONTEXT (run_context));
g_assert (IDE_IS_RUN_COMMAND (run_command));
g_assert (IDE_IS_PIPELINE (pipeline));
+ g_assert (IDE_IS_RUN_TOOL (self->run_tool));
+
+ g_debug ("Preparing run context using run tool %s",
+ G_OBJECT_TYPE_NAME (self->run_tool));
- /* The very first thing we need to do is allow the current run handler
+ /* The very first thing we need to do is allow the current run tool
* to inject any command wrapper it needs. This might be something like
* gdb, or valgrind, etc.
*/
- if (self->handler != NULL && self->handler->handler != NULL)
- self->handler->handler (self,
- pipeline,
- run_command,
- run_context,
- self->handler->handler_data);
+ ide_run_tool_prepare_to_run (self->run_tool, pipeline, run_command, run_context);
/* Now push a new layer so that we can keep those values separate from
* what is configured in the run command. We use an expansion layer so
@@ -937,6 +990,8 @@ ide_run_manager_run_deploy_cb (GObject *object,
ide_notification_attach (self->notif, IDE_OBJECT (self));
}
+ _ide_run_tool_emit_started (self->run_tool, subprocess);
+
g_signal_emit (self, signals[STARTED], 0);
/* Wait for the application to finish running */
@@ -1182,9 +1237,9 @@ ide_run_manager_cancel (IdeRunManager *self)
int exit_signal = ide_run_manager_get_exit_signal (self);
if (!self->sent_signal)
- ide_subprocess_send_signal (self->current_subprocess, exit_signal);
+ ide_run_tool_send_signal (self->run_tool, exit_signal);
else
- ide_subprocess_force_exit (self->current_subprocess);
+ ide_run_tool_force_exit (self->run_tool);
self->sent_signal = TRUE;
}
@@ -1197,103 +1252,6 @@ ide_run_manager_cancel (IdeRunManager *self)
IDE_EXIT;
}
-void
-ide_run_manager_set_handler (IdeRunManager *self,
- const gchar *id)
-{
- g_return_if_fail (IDE_IS_RUN_MANAGER (self));
-
- self->handler = NULL;
-
- for (GList *iter = self->handlers; iter; iter = iter->next)
- {
- const IdeRunHandlerInfo *info = iter->data;
-
- if (g_strcmp0 (info->id, id) == 0)
- {
- self->handler = info;
- IDE_TRACE_MSG ("run handler set to %s", info->title);
- g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_HANDLER]);
- break;
- }
- }
-}
-
-void
-ide_run_manager_add_handler (IdeRunManager *self,
- const gchar *id,
- const gchar *title,
- const gchar *icon_name,
- IdeRunHandler run_handler,
- gpointer user_data,
- GDestroyNotify user_data_destroy)
-{
- IdeRunHandlerInfo *info;
-
- g_return_if_fail (IDE_IS_RUN_MANAGER (self));
- g_return_if_fail (id != NULL);
- g_return_if_fail (title != NULL);
-
- info = g_slice_new0 (IdeRunHandlerInfo);
- info->id = g_strdup (id);
- info->title = g_strdup (title);
- info->icon_name = g_strdup (icon_name);
- info->handler = run_handler;
- info->handler_data = user_data;
- info->handler_data_destroy = user_data_destroy;
-
- self->handlers = g_list_append (self->handlers, info);
-
- if (self->handler == NULL)
- self->handler = info;
-}
-
-void
-ide_run_manager_remove_handler (IdeRunManager *self,
- const gchar *id)
-{
- g_return_if_fail (IDE_IS_RUN_MANAGER (self));
- g_return_if_fail (id != NULL);
-
- for (GList *iter = self->handlers; iter; iter = iter->next)
- {
- IdeRunHandlerInfo *info = iter->data;
-
- if (g_strcmp0 (info->id, id) == 0)
- {
- self->handlers = g_list_delete_link (self->handlers, iter);
-
- if (self->handler == info && self->handlers != NULL)
- self->handler = self->handlers->data;
- else
- self->handler = NULL;
-
- ide_run_handler_info_free (info);
-
- break;
- }
- }
-}
-
-const GList *
-_ide_run_manager_get_handlers (IdeRunManager *self)
-{
- g_return_val_if_fail (IDE_IS_RUN_MANAGER (self), NULL);
-
- return self->handlers;
-}
-
-const gchar *
-ide_run_manager_get_handler (IdeRunManager *self)
-{
- g_return_val_if_fail (IDE_IS_RUN_MANAGER (self), NULL);
-
- if (self->handler != NULL)
- return self->handler->id;
-
- return NULL;
-}
-
static void
ide_run_manager_run_action_cb (GObject *object,
GAsyncResult *result,
@@ -1333,23 +1291,13 @@ static void
ide_run_manager_actions_run_with_handler (IdeRunManager *self,
GVariant *param)
{
- const gchar *handler = NULL;
- g_autoptr(GVariant) sunk = NULL;
-
IDE_ENTRY;
+ g_assert (IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_RUN_MANAGER (self));
+ g_assert (g_variant_is_of_type (param, G_VARIANT_TYPE_STRING));
- if (param != NULL)
- {
- handler = g_variant_get_string (param, NULL);
- if (g_variant_is_floating (param))
- sunk = g_variant_ref_sink (param);
- }
-
- /* Use specified handler, if provided */
- if (!ide_str_empty0 (handler))
- ide_run_manager_set_handler (self, handler);
+ ide_run_manager_set_run_tool_from_module_name (self, g_variant_get_string (param, NULL));
ide_run_manager_run_async (self,
NULL,
@@ -1378,6 +1326,7 @@ ide_run_manager_init (IdeRunManager *self)
GtkTextDirection text_dir;
self->cancellable = g_cancellable_new ();
+ self->run_tool = ide_no_tool_new ();
/* Setup initial text direction state */
text_dir = gtk_widget_get_default_direction ();
@@ -1387,14 +1336,6 @@ ide_run_manager_init (IdeRunManager *self)
text_dir == GTK_TEXT_DIR_LTR ?
g_variant_new_string ("ltr") :
g_variant_new_string ("rtl"));
-
- ide_run_manager_add_handler (self,
- "run",
- _("Run"),
- "builder-run-start-symbolic",
- NULL,
- NULL,
- NULL);
}
void
diff --git a/src/libide/foundry/ide-run-manager.h b/src/libide/foundry/ide-run-manager.h
index eeba81a0b..23f08cf72 100644
--- a/src/libide/foundry/ide-run-manager.h
+++ b/src/libide/foundry/ide-run-manager.h
@@ -25,6 +25,7 @@
#endif
#include <libide-core.h>
+#include <libide-plugins.h>
#include "ide-foundry-types.h"
@@ -35,34 +36,17 @@ G_BEGIN_DECLS
IDE_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (IdeRunManager, ide_run_manager, IDE, RUN_MANAGER, IdeObject)
-typedef void (*IdeRunHandler) (IdeRunManager *self,
- IdePipeline *pipeline,
- IdeRunCommand *run_command,
- IdeRunContext *run_context,
- gpointer user_data);
-
IDE_AVAILABLE_IN_ALL
IdeRunManager *ide_run_manager_from_context (IdeContext *context);
IDE_AVAILABLE_IN_ALL
void ide_run_manager_cancel (IdeRunManager *self);
IDE_AVAILABLE_IN_ALL
-gboolean ide_run_manager_get_busy (IdeRunManager *self);
-IDE_AVAILABLE_IN_ALL
-const gchar *ide_run_manager_get_handler (IdeRunManager *self);
+const char *ide_run_manager_get_icon_name (IdeRunManager *self);
IDE_AVAILABLE_IN_ALL
-void ide_run_manager_set_handler (IdeRunManager *self,
- const gchar *id);
-IDE_AVAILABLE_IN_ALL
-void ide_run_manager_add_handler (IdeRunManager *self,
- const char *id,
- const char *title,
- const char *icon_name,
- IdeRunHandler run_handler,
- gpointer user_data,
- GDestroyNotify user_data_destroy);
+gboolean ide_run_manager_get_busy (IdeRunManager *self);
IDE_AVAILABLE_IN_ALL
-void ide_run_manager_remove_handler (IdeRunManager *self,
- const gchar *id);
+void ide_run_manager_set_run_tool_from_plugin_info (IdeRunManager *self,
+ PeasPluginInfo *plugin_info);
IDE_AVAILABLE_IN_ALL
void ide_run_manager_run_async (IdeRunManager *self,
GCancellable *cancellable,
diff --git a/src/libide/gui/ide-run-button.c b/src/libide/gui/ide-run-button.c
index a942f34d2..f44f35f5e 100644
--- a/src/libide/gui/ide-run-button.c
+++ b/src/libide/gui/ide-run-button.c
@@ -38,44 +38,15 @@ struct _IdeRunButton
{
GtkWidget parent_instance;
AdwSplitButton *split_button;
- char *run_handler_icon_name;
IdeJoinedMenu *joined_menu;
};
G_DEFINE_FINAL_TYPE (IdeRunButton, ide_run_button, GTK_TYPE_WIDGET)
static void
-ide_run_button_handler_set (IdeRunButton *self,
- GParamSpec *pspec,
- IdeRunManager *run_manager)
-{
- const GList *list;
- const GList *iter;
- const gchar *handler;
-
- g_assert (IDE_IS_RUN_BUTTON (self));
- g_assert (IDE_IS_RUN_MANAGER (run_manager));
-
- handler = ide_run_manager_get_handler (run_manager);
- list = _ide_run_manager_get_handlers (run_manager);
-
- for (iter = list; iter; iter = iter->next)
- {
- const IdeRunHandlerInfo *info = iter->data;
-
- if (g_strcmp0 (info->id, handler) == 0)
- {
- self->run_handler_icon_name = g_strdup (info->icon_name);
- g_object_set (self->split_button, "icon-name", info->icon_name, NULL);
- break;
- }
- }
-}
-
-static void
-on_run_busy_state_changed_cb (IdeRunButton *self,
- GParamSpec *pspec,
- IdeRunManager *run_manager)
+on_icon_state_changed_cb (IdeRunButton *self,
+ GParamSpec *pspec,
+ IdeRunManager *run_manager)
{
const char *icon_name;
const char *action_name;
@@ -85,7 +56,7 @@ on_run_busy_state_changed_cb (IdeRunButton *self,
if (!ide_run_manager_get_busy (run_manager))
{
- icon_name = self->run_handler_icon_name;
+ icon_name = ide_run_manager_get_icon_name (run_manager);
action_name = "run-manager.run";
}
else
@@ -94,8 +65,10 @@ on_run_busy_state_changed_cb (IdeRunButton *self,
action_name = "run-manager.stop";
}
- g_object_set (self->split_button, "icon-name", icon_name, NULL);
- gtk_actionable_set_action_name (GTK_ACTIONABLE (self->split_button), action_name);
+ g_object_set (self->split_button,
+ "action-name", action_name,
+ "icon-name", icon_name,
+ NULL);
}
static void
@@ -114,27 +87,25 @@ ide_run_button_load (IdeRunButton *self,
if (!ide_context_has_project (context))
IDE_EXIT;
- device_manager = ide_device_manager_from_context (context);
+ /* Setup button action/icon */
run_manager = ide_run_manager_from_context (context);
-
g_signal_connect_object (run_manager,
"notify::busy",
- G_CALLBACK (on_run_busy_state_changed_cb),
+ G_CALLBACK (on_icon_state_changed_cb),
self,
G_CONNECT_SWAPPED);
-
g_signal_connect_object (run_manager,
- "notify::handler",
- G_CALLBACK (ide_run_button_handler_set),
+ "notify::icon-name",
+ G_CALLBACK (on_icon_state_changed_cb),
self,
G_CONNECT_SWAPPED);
+ on_icon_state_changed_cb (self, NULL, run_manager);
/* Add devices section */
+ device_manager = ide_device_manager_from_context (context);
menu = _ide_device_manager_get_menu (device_manager);
ide_joined_menu_prepend_menu (self->joined_menu, G_MENU_MODEL (menu));
- ide_run_button_handler_set (self, NULL, run_manager);
-
IDE_EXIT;
}
@@ -160,9 +131,6 @@ ide_run_button_query_tooltip (IdeRunButton *self,
GtkButton *button)
{
IdeRunManager *run_manager;
- const GList *list;
- const GList *iter;
- const gchar *handler;
IdeContext *context;
g_assert (IDE_IS_RUN_BUTTON (self));
@@ -171,46 +139,13 @@ ide_run_button_query_tooltip (IdeRunButton *self,
context = ide_widget_get_context (GTK_WIDGET (self));
run_manager = ide_run_manager_from_context (context);
- handler = ide_run_manager_get_handler (run_manager);
- list = _ide_run_manager_get_handlers (run_manager);
if (ide_run_manager_get_busy (run_manager))
- {
- gtk_tooltip_set_text (tooltip, _("Stop running"));
- return TRUE;
- }
-
- for (iter = list; iter; iter = iter->next)
- {
- const IdeRunHandlerInfo *info = iter->data;
-
- if (g_strcmp0 (info->id, handler) == 0)
- {
- gboolean enabled;
-
- /* Figure out if the run action is enabled. If it
- * is not, then we should inform the user that
- * the project cannot be run yet because the
- * build pipeline is not yet configured. */
- g_action_group_query_action (G_ACTION_GROUP (run_manager),
- "run",
- &enabled,
- NULL,
- NULL,
- NULL,
- NULL);
-
- if (!enabled)
- {
- gtk_tooltip_set_text (tooltip, _("Invalid project configuration"));
- return TRUE;
- }
-
- gtk_tooltip_set_text (tooltip, info->title);
- }
- }
+ gtk_tooltip_set_text (tooltip, _("Stop running"));
+ else
+ gtk_tooltip_set_text (tooltip, _("Run project"));
- return FALSE;
+ return TRUE;
}
static void
diff --git a/src/plugins/debuggerui/debuggerui-plugin.c b/src/plugins/debuggerui/debuggerui-plugin.c
index 6412c2a37..ddcc054d7 100644
--- a/src/plugins/debuggerui/debuggerui-plugin.c
+++ b/src/plugins/debuggerui/debuggerui-plugin.c
@@ -27,12 +27,16 @@
#include <libide-debugger.h>
#include <libide-gui.h>
+#include "gbp-debugger-tool.h"
#include "ide-debugger-hover-provider.h"
#include "ide-debugger-workspace-addin.h"
void
_gbp_debuggerui_register_types (PeasObjectModule *module)
{
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_RUN_TOOL,
+ GBP_TYPE_DEBUGGER_TOOL);
peas_object_module_register_extension_type (module,
GTK_SOURCE_TYPE_HOVER_PROVIDER,
IDE_TYPE_DEBUGGER_HOVER_PROVIDER);
diff --git a/src/plugins/debuggerui/gbp-debugger-tool.c b/src/plugins/debuggerui/gbp-debugger-tool.c
new file mode 100644
index 000000000..cce27695e
--- /dev/null
+++ b/src/plugins/debuggerui/gbp-debugger-tool.c
@@ -0,0 +1,146 @@
+/* gbp-debugger-tool.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-debugger-tool"
+
+#include "config.h"
+
+#include <libide-debugger.h>
+
+#include "ide-debug-manager-private.h"
+
+#include "gbp-debugger-tool.h"
+
+struct _GbpDebuggerTool
+{
+ IdeRunTool parent_instance;
+};
+
+G_DEFINE_FINAL_TYPE (GbpDebuggerTool, gbp_debugger_tool, IDE_TYPE_RUN_TOOL)
+
+static void
+gbp_debugger_tool_send_signal (IdeRunTool *run_tool,
+ int signum)
+{
+ GbpDebuggerTool *self = (GbpDebuggerTool *)run_tool;
+ IdeDebugManager *debug_manager;
+ IdeDebugger *debugger;
+ IdeContext *context;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_DEBUGGER_TOOL (self));
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ debug_manager = ide_debug_manager_from_context (context);
+ debugger = ide_debug_manager_get_debugger (debug_manager);
+
+ if (debugger != NULL)
+ ide_debugger_send_signal_async (debugger, signum, NULL, NULL, NULL);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_debugger_tool_prepare_to_run (IdeRunTool *run_tool,
+ IdePipeline *pipeline,
+ IdeRunCommand *run_command,
+ IdeRunContext *run_context)
+{
+ GbpDebuggerTool *self = (GbpDebuggerTool *)run_tool;
+ IdeDebugManager *debug_manager;
+ IdeContext *context;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_DEBUGGER_TOOL (self));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+ g_assert (IDE_IS_RUN_COMMAND (run_command));
+ g_assert (IDE_IS_RUN_CONTEXT (run_context));
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ debug_manager = ide_debug_manager_from_context (context);
+
+ _ide_debug_manager_prepare (debug_manager, pipeline, run_command, run_context, NULL);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_debugger_tool_started (IdeRunTool *run_tool,
+ IdeSubprocess *subprocess)
+{
+ GbpDebuggerTool *self = (GbpDebuggerTool *)run_tool;
+ IdeDebugManager *debug_manager;
+ IdeContext *context;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_DEBUGGER_TOOL (self));
+ g_assert (IDE_IS_SUBPROCESS (subprocess));
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ debug_manager = ide_debug_manager_from_context (context);
+
+ _ide_debug_manager_started (debug_manager);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_debugger_tool_stopped (IdeRunTool *run_tool)
+{
+ GbpDebuggerTool *self = (GbpDebuggerTool *)run_tool;
+ IdeDebugManager *debug_manager;
+ IdeContext *context;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_DEBUGGER_TOOL (self));
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ debug_manager = ide_debug_manager_from_context (context);
+
+ _ide_debug_manager_stopped (debug_manager);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_debugger_tool_class_init (GbpDebuggerToolClass *klass)
+{
+ IdeRunToolClass *run_tool_class = IDE_RUN_TOOL_CLASS (klass);
+
+ run_tool_class->prepare_to_run = gbp_debugger_tool_prepare_to_run;
+ run_tool_class->send_signal = gbp_debugger_tool_send_signal;
+ run_tool_class->started = gbp_debugger_tool_started;
+ run_tool_class->stopped = gbp_debugger_tool_stopped;
+}
+
+static void
+gbp_debugger_tool_init (GbpDebuggerTool *self)
+{
+ ide_run_tool_set_icon_name (IDE_RUN_TOOL (self),
+ "builder-debugger-symbolic");
+}
diff --git a/src/plugins/debuggerui/gbp-debugger-tool.h b/src/plugins/debuggerui/gbp-debugger-tool.h
new file mode 100644
index 000000000..fb876f3c2
--- /dev/null
+++ b/src/plugins/debuggerui/gbp-debugger-tool.h
@@ -0,0 +1,31 @@
+/* gbp-debugger-tool.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-foundry.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_DEBUGGER_TOOL (gbp_debugger_tool_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpDebuggerTool, gbp_debugger_tool, GBP, DEBUGGER_TOOL, IdeRunTool)
+
+G_END_DECLS
diff --git a/src/plugins/debuggerui/gtk/menus.ui b/src/plugins/debuggerui/gtk/menus.ui
index 27d3e8b54..655f7d73a 100644
--- a/src/plugins/debuggerui/gtk/menus.ui
+++ b/src/plugins/debuggerui/gtk/menus.ui
@@ -6,7 +6,7 @@
<attribute name="id">debugger-run-handler</attribute>
<attribute name="after">default-run-handler</attribute>
<attribute name="action">run-manager.run-with-handler</attribute>
- <attribute name="target">debugger</attribute>
+ <attribute name="target" type="s">'debuggerui'</attribute>
<attribute name="label" translatable="yes">Run with Debugger</attribute>
<attribute name="verb-icon-name">builder-debugger-symbolic</attribute>
<attribute name="accel"><control><shift><alt>d</attribute>
@@ -42,7 +42,7 @@
<attribute name="id">project-tree-menu-debug</attribute>
<attribute name="label" translatable="yes">Run with _Debugger</attribute>
<attribute name="action">buildui.run-with-handler</attribute>
- <attribute name="target" type="s">'debugger'</attribute>
+ <attribute name="target" type="s">'debuggerui'</attribute>
</item>
</section>
</submenu>
diff --git a/src/plugins/debuggerui/ide-debugger-workspace-addin.c
b/src/plugins/debuggerui/ide-debugger-workspace-addin.c
index d3cadaa90..86c7f46bc 100644
--- a/src/plugins/debuggerui/ide-debugger-workspace-addin.c
+++ b/src/plugins/debuggerui/ide-debugger-workspace-addin.c
@@ -65,8 +65,6 @@ struct _IdeDebuggerWorkspaceAddin
IdeWorkspace *workspace;
IdeWorkbench *workbench;
- IdeRunManager *run_manager;
-
IdeDebuggerDisassemblyView *disassembly_view;
IdeDebuggerControls *controls;
IdeDebuggerBreakpointsView *breakpoints_view;
@@ -99,72 +97,6 @@ debugger_stopped (IdeDebuggerWorkspaceAddin *self,
IDE_EXIT;
}
-static void
-send_notification (IdeDebuggerWorkspaceAddin *self,
- const gchar *title,
- const gchar *body,
- const gchar *icon_name,
- gboolean urgent)
-{
- g_autoptr(IdeNotification) notif = NULL;
- g_autoptr(GIcon) icon = NULL;
- IdeContext *context;
-
- g_assert (IDE_IS_DEBUGGER_WORKSPACE_ADDIN (self));
-
- context = ide_workbench_get_context (self->workbench);
-
- if (icon_name)
- icon = g_themed_icon_new (icon_name);
-
- notif = g_object_new (IDE_TYPE_NOTIFICATION,
- "has-progress", FALSE,
- "icon", icon,
- "title", title,
- "body", body,
- "urgent", TRUE,
- NULL);
- ide_notification_attach (notif, IDE_OBJECT (context));
- ide_notification_withdraw_in_seconds (notif, 30);
-}
-
-static void
-debugger_run_handler (IdeRunManager *run_manager,
- IdePipeline *pipeline,
- IdeRunCommand *run_command,
- IdeRunContext *run_context,
- gpointer user_data)
-{
- IdeDebuggerWorkspaceAddin *self = user_data;
- g_autoptr(GError) error = NULL;
- IdeDebugManager *debug_manager;
- IdeContext *context;
-
- IDE_ENTRY;
-
- g_assert (IDE_IS_RUN_MANAGER (run_manager));
- g_assert (IDE_IS_PIPELINE (pipeline));
- g_assert (IDE_IS_RUN_COMMAND (run_command));
- g_assert (IDE_IS_RUN_CONTEXT (run_context));
- g_assert (IDE_IS_DEBUGGER_WORKSPACE_ADDIN (self));
-
- /*
- * Get the currently configured debugger and attach it to our runner.
- * It might need to prepend arguments like `gdb', `pdb', `mdb', etc.
- */
- context = ide_object_get_context (IDE_OBJECT (run_manager));
- debug_manager = ide_debug_manager_from_context (context);
-
- if (!_ide_debug_manager_prepare (debug_manager, pipeline, run_command, run_context, &error))
- send_notification (self,
- _("Failed to start the debugger"),
- error->message,
- "computer-fail-symbolic",
- TRUE);
-
- IDE_EXIT;
-}
-
static void
debug_manager_notify_debugger (IdeDebuggerWorkspaceAddin *self,
GParamSpec *pspec,
@@ -339,41 +271,12 @@ ide_debugger_workspace_addin_add_ui (IdeDebuggerWorkspaceAddin *self)
ide_workspace_add_pane (self->workspace, IDE_PANE (self->panel), position);
}
-static void
-ide_debugger_workspace_addin_started_cb (IdeDebugManager *debug_manager,
- IdeRunManager *run_manager)
-{
- IDE_ENTRY;
-
- g_assert (IDE_IS_DEBUG_MANAGER (debug_manager));
- g_assert (IDE_IS_RUN_MANAGER (run_manager));
-
- _ide_debug_manager_started (debug_manager);
-
- IDE_EXIT;
-}
-
-static void
-ide_debugger_workspace_addin_stopped_cb (IdeDebugManager *debug_manager,
- IdeRunManager *run_manager)
-{
- IDE_ENTRY;
-
- g_assert (IDE_IS_DEBUG_MANAGER (debug_manager));
- g_assert (IDE_IS_RUN_MANAGER (run_manager));
-
- _ide_debug_manager_stopped (debug_manager);
-
- IDE_EXIT;
-}
-
static void
ide_debugger_workspace_addin_load (IdeWorkspaceAddin *addin,
IdeWorkspace *workspace)
{
IdeDebuggerWorkspaceAddin *self = (IdeDebuggerWorkspaceAddin *)addin;
IdeDebugManager *debug_manager;
- IdeRunManager *run_manager;
IdeContext *context;
IDE_ENTRY;
@@ -388,33 +291,10 @@ ide_debugger_workspace_addin_load (IdeWorkspaceAddin *addin,
return;
context = ide_widget_get_context (GTK_WIDGET (workspace));
- run_manager = ide_run_manager_from_context (context);
debug_manager = ide_debug_manager_from_context (context);
- self->run_manager = g_object_ref (run_manager);
-
ide_debugger_workspace_addin_add_ui (self);
- ide_run_manager_add_handler (run_manager,
- "debugger",
- _("Run with Debugger"),
- "builder-debugger-symbolic",
- debugger_run_handler,
- g_object_ref (self),
- g_object_unref);
-
- g_signal_connect_object (run_manager,
- "started",
- G_CALLBACK (ide_debugger_workspace_addin_started_cb),
- debug_manager,
- G_CONNECT_SWAPPED);
-
- g_signal_connect_object (run_manager,
- "stopped",
- G_CALLBACK (ide_debugger_workspace_addin_stopped_cb),
- debug_manager,
- G_CONNECT_SWAPPED);
-
self->debugger_signals = ide_signal_group_new (IDE_TYPE_DEBUGGER);
ide_signal_group_connect_swapped (self->debugger_signals,
@@ -459,13 +339,11 @@ ide_debugger_workspace_addin_unload (IdeWorkspaceAddin *addin,
return;
gtk_widget_insert_action_group (GTK_WIDGET (self->workspace), "debugger", NULL);
- ide_run_manager_remove_handler (self->run_manager, "debugger");
self->controls = NULL;
g_clear_object (&self->debugger_signals);
g_clear_object (&self->debug_manager_signals);
- g_clear_object (&self->run_manager);
ide_clear_pane ((IdePane **)&self->panel);
ide_clear_page ((IdePage **)&self->disassembly_view);
diff --git a/src/plugins/debuggerui/meson.build b/src/plugins/debuggerui/meson.build
index 1a7aa48fe..eadaf71ef 100644
--- a/src/plugins/debuggerui/meson.build
+++ b/src/plugins/debuggerui/meson.build
@@ -1,5 +1,6 @@
plugins_sources += files([
'debuggerui-plugin.c',
+ 'gbp-debugger-tool.c',
'ide-debugger-breakpoints-view.c',
'ide-debugger-controls.c',
'ide-debugger-disassembly-view.c',
diff --git a/src/plugins/sysprof/gbp-sysprof-tool.c b/src/plugins/sysprof/gbp-sysprof-tool.c
new file mode 100644
index 000000000..8f469aaf3
--- /dev/null
+++ b/src/plugins/sysprof/gbp-sysprof-tool.c
@@ -0,0 +1,104 @@
+/* gbp-sysprof-tool.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-sysprof-tool"
+
+#include "config.h"
+
+#include "gbp-sysprof-tool.h"
+
+struct _GbpSysprofTool
+{
+ IdeRunTool parent_instance;
+};
+
+G_DEFINE_FINAL_TYPE (GbpSysprofTool, gbp_sysprof_tool, IDE_TYPE_RUN_TOOL)
+
+static void
+gbp_sysprof_tool_prepare_to_run (IdeRunTool *run_tool,
+ IdePipeline *pipeline,
+ IdeRunCommand *run_command,
+ IdeRunContext *run_context)
+{
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_SYSPROF_TOOL (run_tool));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+ g_assert (IDE_IS_RUN_COMMAND (run_command));
+ g_assert (IDE_IS_RUN_CONTEXT (run_context));
+
+ g_printerr ("TODO: Port sysprof tool\n");
+
+ IDE_EXIT;
+}
+
+static void
+gbp_sysprof_tool_send_signal (IdeRunTool *run_tool,
+ int signum)
+{
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_SYSPROF_TOOL (run_tool));
+
+ IDE_EXIT;
+}
+
+static void
+gbp_sysprof_tool_started (IdeRunTool *run_tool,
+ IdeSubprocess *subprocess)
+{
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_SYSPROF_TOOL (run_tool));
+ g_assert (IDE_IS_SUBPROCESS (subprocess));
+
+ IDE_EXIT;
+}
+
+static void
+gbp_sysprof_tool_stopped (IdeRunTool *run_tool)
+{
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_SYSPROF_TOOL (run_tool));
+
+ IDE_EXIT;
+}
+
+static void
+gbp_sysprof_tool_class_init (GbpSysprofToolClass *klass)
+{
+ IdeRunToolClass *run_tool_class = IDE_RUN_TOOL_CLASS (klass);
+
+ run_tool_class->prepare_to_run = gbp_sysprof_tool_prepare_to_run;
+ run_tool_class->send_signal = gbp_sysprof_tool_send_signal;
+ run_tool_class->started = gbp_sysprof_tool_started;
+ run_tool_class->stopped = gbp_sysprof_tool_stopped;
+}
+
+static void
+gbp_sysprof_tool_init (GbpSysprofTool *self)
+{
+ ide_run_tool_set_icon_name (IDE_RUN_TOOL (self), "builder-profiler-symbolic");
+}
diff --git a/src/plugins/sysprof/gbp-sysprof-tool.h b/src/plugins/sysprof/gbp-sysprof-tool.h
new file mode 100644
index 000000000..1ca0b4afb
--- /dev/null
+++ b/src/plugins/sysprof/gbp-sysprof-tool.h
@@ -0,0 +1,31 @@
+/* gbp-sysprof-tool.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-foundry.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_SYSPROF_TOOL (gbp_sysprof_tool_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpSysprofTool, gbp_sysprof_tool, GBP, SYSPROF_TOOL, IdeRunTool)
+
+G_END_DECLS
diff --git a/src/plugins/sysprof/gbp-sysprof-workspace-addin.c
b/src/plugins/sysprof/gbp-sysprof-workspace-addin.c
index 295d28611..5e88639ed 100644
--- a/src/plugins/sysprof/gbp-sysprof-workspace-addin.c
+++ b/src/plugins/sysprof/gbp-sysprof-workspace-addin.c
@@ -39,248 +39,6 @@ struct _GbpSysprofWorkspaceAddin
IdeRunManager *run_manager;
};
-static void
-set_state (GSimpleAction *action,
- GVariant *param,
- gpointer user_data)
-{
- g_simple_action_set_state (action, param);
-}
-
-static gboolean
-get_state (GbpSysprofWorkspaceAddin *self,
- const char *action_name)
-{
- g_autoptr(GVariant) state = NULL;
- GAction *action;
-
- g_assert (GBP_IS_SYSPROF_WORKSPACE_ADDIN (self));
- g_assert (action_name != NULL);
-
- if (!(action = g_action_map_lookup_action (G_ACTION_MAP (self->actions), action_name)))
- g_return_val_if_reached (FALSE);
-
- if (!(state = g_action_get_state (action)))
- g_return_val_if_reached (FALSE);
-
- if (!g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN))
- g_return_val_if_reached (FALSE);
-
- return g_variant_get_boolean (state);
-}
-
-static void
-profiler_child_spawned (IdeRunner *runner,
- const gchar *identifier,
- SysprofProfiler *profiler)
-{
-#ifdef G_OS_UNIX
- GPid pid = 0;
-
- g_assert (IDE_IS_MAIN_THREAD ());
- g_assert (SYSPROF_IS_PROFILER (profiler));
- g_assert (identifier != NULL);
- g_assert (IDE_IS_RUNNER (runner));
-
- pid = g_ascii_strtoll (identifier, NULL, 10);
-
- if (pid == 0)
- {
- g_warning ("Failed to parse integer value from %s", identifier);
- return;
- }
-
- IDE_TRACE_MSG ("Adding pid %s to profiler", identifier);
-
- sysprof_profiler_add_pid (profiler, pid);
- sysprof_profiler_start (profiler);
-#endif
-}
-
-static void
-runner_exited_cb (IdeRunner *runner,
- SysprofProfiler *profiler)
-{
- g_assert (IDE_IS_MAIN_THREAD ());
- g_assert (IDE_IS_RUNNER (runner));
- g_assert (SYSPROF_IS_PROFILER (profiler));
-
- if (sysprof_profiler_get_is_running (profiler))
- sysprof_profiler_stop (profiler);
-}
-
-static void
-foreach_fd (gint dest_fd,
- gint fd,
- gpointer user_data)
-{
- IdeRunner *runner = user_data;
-
- g_assert (IDE_IS_RUNNER (runner));
- g_assert (dest_fd >= 0);
- g_assert (fd >= 0);
-
- ide_runner_take_fd (runner, dup (fd), dest_fd);
-}
-
-static void
-profiler_run_handler (IdeRunManager *run_manager,
- IdePipeline *pipeline,
- IdeRunCommand *run_command,
- IdeRunContext *run_context,
- gpointer user_data)
-{
- g_printerr ("TODO: sysprof not ported to run context yet!\n");
-
-#if 0
- GbpSysprofWorkspaceAddin *self = user_data;
- g_autoptr(SysprofProfiler) profiler = NULL;
- g_autoptr(SysprofSpawnable) spawnable = NULL;
- g_autoptr(IdePanelPosition) position = NULL;
- g_autoptr(GPtrArray) sources = NULL;
- g_auto(GStrv) argv = NULL;
- const gchar * const *env;
- GbpSysprofPage *page;
- IdeEnvironment *ienv;
-
- g_assert (IDE_IS_MAIN_THREAD ());
- g_assert (GBP_IS_SYSPROF_WORKSPACE_ADDIN (self));
- g_assert (IDE_IS_RUN_CONTEXT (run_context));
- g_assert (IDE_IS_RUN_MANAGER (run_manager));
-
- sources = g_ptr_array_new_with_free_func (g_object_unref);
-
- profiler = sysprof_local_profiler_new ();
-
- /*
- * Currently we require whole-system because otherwise we can get a situation
- * where we only watch the spawning process (say jhbuild, flatpak, etc).
- * Longer term we either need a way to follow-children and/or limit to a
- * cgroup/process-group.
- */
- sysprof_profiler_set_whole_system (profiler, TRUE);
-
-#ifdef __linux__
- {
- g_ptr_array_add (sources, sysprof_proc_source_new ());
-
- if (get_state (self, "cpu-aid"))
- g_ptr_array_add (sources, sysprof_hostinfo_source_new ());
-
- if (get_state (self, "perf-aid"))
- g_ptr_array_add (sources, sysprof_perf_source_new ());
-
- if (get_state (self, "memory-aid"))
- g_ptr_array_add (sources, sysprof_memory_source_new ());
-
- if (get_state (self, "energy-aid"))
- g_ptr_array_add (sources, sysprof_proxy_source_new (G_BUS_TYPE_SYSTEM,
- "org.gnome.Sysprof3",
- "/org/gnome/Sysprof3/RAPL"));
-
- if (get_state (self, "battery-aid"))
- g_ptr_array_add (sources, sysprof_battery_source_new ());
-
- if (get_state (self, "netstat-aid"))
- g_ptr_array_add (sources, sysprof_netdev_source_new ());
-
- if (get_state (self, "diskstat-aid"))
- g_ptr_array_add (sources, sysprof_diskstat_source_new ());
-
- if (!get_state (self, "allow-throttle"))
- {
- SysprofSource *governor = sysprof_governor_source_new ();
- sysprof_governor_source_set_disable_governor (SYSPROF_GOVERNOR_SOURCE (governor), TRUE);
- g_ptr_array_add (sources, governor);
- }
- }
-#endif
-
- if (get_state (self, "memprof-aid"))
- g_ptr_array_add (sources, sysprof_memprof_source_new ());
-
- g_ptr_array_add (sources, sysprof_gjs_source_new ());
- g_ptr_array_add (sources, sysprof_symbols_source_new ());
-
- /* Allow the app to submit us data if it supports "SYSPROF_TRACE_FD" */
- if (get_state (self, "allow-tracefd"))
- {
- SysprofSource *app_source = sysprof_tracefd_source_new ();
- sysprof_tracefd_source_set_envvar (SYSPROF_TRACEFD_SOURCE (app_source), "SYSPROF_TRACE_FD");
- g_ptr_array_add (sources, app_source);
- }
-
- /*
- * TODO:
- *
- * We need to synchronize the inferior with the parent here. Ideally, we would
- * prepend the application launch (to some degree) with the application we want
- * to execute. In this case, we might want to add a "gnome-builder-sysprof"
- * helper that will synchronize with the parent, and then block until we start
- * the process (with the appropriate pid) before exec() otherwise we could
- * miss the exit of the app and race to add the pid to the profiler.
- */
-
- g_signal_connect_object (runner,
- "spawned",
- G_CALLBACK (profiler_child_spawned),
- profiler,
- 0);
-
- g_signal_connect_object (runner,
- "exited",
- G_CALLBACK (runner_exited_cb),
- profiler,
- 0);
-
- /*
- * We need to allow the sources to modify the execution environment, so copy
- * the environment into the spawnable, modify it, and the propagate back.
- */
- argv = ide_runner_get_argv (runner);
- ienv = ide_runner_get_environment (runner);
-
- spawnable = sysprof_spawnable_new ();
- sysprof_spawnable_append_args (spawnable, (const gchar * const *)argv);
- sysprof_spawnable_set_starting_fd (spawnable, ide_runner_get_max_fd (runner) + 1);
-
- for (guint i = 0; i < sources->len; i++)
- {
- SysprofSource *source = g_ptr_array_index (sources, i);
-
- if (source != NULL)
- {
- sysprof_profiler_add_source (profiler, source);
- sysprof_source_modify_spawn (source, spawnable);
- }
- }
-
- /* TODO: Propagate argv back to runner.
- *
- * Currently this is a non-issue because none of our sources modify argv.
- * So doing it now is just brittle for no benefit.
- */
-
- if ((env = sysprof_spawnable_get_environ (spawnable)))
- {
- for (guint i = 0; env[i] != NULL; i++)
- {
- g_autofree gchar *key = NULL;
- g_autofree gchar *value = NULL;
-
- if (ide_environ_parse (env[i], &key, &value))
- ide_environment_setenv (ienv, key, value);
- }
- }
-
- sysprof_spawnable_foreach_fd (spawnable, foreach_fd, runner);
-
- page = gbp_sysprof_page_new_for_profiler (profiler);
- position = ide_panel_position_new ();
- ide_workspace_add_page (self->workspace, IDE_PAGE (page), position);
-#endif
-}
-
static void
gbp_sysprof_workspace_addin_open (GbpSysprofWorkspaceAddin *self,
GFile *file)
@@ -383,12 +141,14 @@ run_cb (GSimpleAction *action,
gpointer user_data)
{
GbpSysprofWorkspaceAddin *self = user_data;
+ PeasPluginInfo *plugin_info;
g_assert (GBP_IS_SYSPROF_WORKSPACE_ADDIN (self));
g_assert (IDE_IS_WORKSPACE (self->workspace));
g_assert (IDE_IS_RUN_MANAGER (self->run_manager));
- ide_run_manager_set_handler (self->run_manager, "sysprof");
+ plugin_info = peas_engine_get_plugin_info (peas_engine_get_default (), "sysprof");
+ ide_run_manager_set_run_tool_from_plugin_info (self->run_manager, plugin_info);
ide_run_manager_run_async (self->run_manager, NULL, NULL, NULL);
}
@@ -422,13 +182,6 @@ gbp_sysprof_workspace_addin_check_supported_cb (GObject *object,
gtk_widget_insert_action_group (GTK_WIDGET (self->workspace),
"sysprof",
G_ACTION_GROUP (self->actions));
- ide_run_manager_add_handler (self->run_manager,
- "sysprof",
- _("Run with Profiler"),
- "builder-profiler-symbolic",
- profiler_run_handler,
- self,
- NULL);
IDE_EXIT;
}
@@ -436,17 +189,6 @@ gbp_sysprof_workspace_addin_check_supported_cb (GObject *object,
static const GActionEntry entries[] = {
{ "open-capture", open_capture_action },
{ "run", run_cb },
- { "cpu-aid", NULL, NULL, "true", set_state },
- { "perf-aid", NULL, NULL, "true", set_state },
- { "memory-aid", NULL, NULL, "true", set_state },
- { "memprof-aid", NULL, NULL, "false", set_state },
- { "diskstat-aid", NULL, NULL, "true", set_state },
- { "netstat-aid", NULL, NULL, "true", set_state },
- { "energy-aid", NULL, NULL, "false", set_state },
- { "battery-aid", NULL, NULL, "false", set_state },
- { "compositor-aid", NULL, NULL, "false", set_state },
- { "allow-throttle", NULL, NULL, "true", set_state },
- { "allow-tracefd", NULL, NULL, "true", set_state },
};
static void
@@ -454,6 +196,9 @@ gbp_sysprof_workspace_addin_load (IdeWorkspaceAddin *addin,
IdeWorkspace *workspace)
{
GbpSysprofWorkspaceAddin *self = (GbpSysprofWorkspaceAddin *)addin;
+ g_autoptr(GSettingsSchema) schema = NULL;
+ g_autoptr(GSettings) settings = NULL;
+ g_auto(GStrv) keys = NULL;
IdeRunManager *run_manager;
IdeContext *context;
@@ -476,6 +221,16 @@ gbp_sysprof_workspace_addin_load (IdeWorkspaceAddin *addin,
G_N_ELEMENTS (entries),
self);
+ settings = g_settings_new ("org.gnome.builder.sysprof");
+ g_object_get (settings, "settings-schema", &schema, NULL);
+ keys = g_settings_schema_list_keys (schema);
+
+ for (guint i = 0; keys[i]; i++)
+ {
+ g_autoptr(GAction) action = g_settings_create_action (settings, keys[i]);
+ g_action_map_add_action (G_ACTION_MAP (self->actions), action);
+ }
+
g_object_bind_property (self->run_manager,
"busy",
g_action_map_lookup_action (G_ACTION_MAP (self->actions), "run"),
@@ -501,7 +256,6 @@ gbp_sysprof_workspace_addin_unload (IdeWorkspaceAddin *addin,
g_assert (IDE_IS_WORKSPACE (workspace));
gtk_widget_insert_action_group (GTK_WIDGET (workspace), "sysprof", NULL);
- ide_run_manager_remove_handler (self->run_manager, "sysprof");
g_clear_object (&self->actions);
g_clear_object (&self->run_manager);
diff --git a/src/plugins/sysprof/meson.build b/src/plugins/sysprof/meson.build
index 6b240b0a5..b19174f80 100644
--- a/src/plugins/sysprof/meson.build
+++ b/src/plugins/sysprof/meson.build
@@ -8,6 +8,7 @@ plugins_deps += [
plugins_sources += files([
'sysprof-plugin.c',
'gbp-sysprof-page.c',
+ 'gbp-sysprof-tool.c',
'gbp-sysprof-workbench-addin.c',
'gbp-sysprof-workspace-addin.c',
])
@@ -20,4 +21,6 @@ plugin_sysprof_resources = gnome.compile_resources(
plugins_sources += plugin_sysprof_resources
+install_data(['org.gnome.builder.sysprof.gschema.xml'], install_dir: schema_dir)
+
endif
diff --git a/src/plugins/sysprof/org.gnome.builder.sysprof.gschema.xml
b/src/plugins/sysprof/org.gnome.builder.sysprof.gschema.xml
new file mode 100644
index 000000000..b88e84c6e
--- /dev/null
+++ b/src/plugins/sysprof/org.gnome.builder.sysprof.gschema.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schemalist>
+ <schema id="org.gnome.builder.sysprof" path="/org/gnome/builder/sysprof/" gettext-domain="gnome-builder">
+ <key type="b" name="cpu-aid"><default>true</default></key>
+ <key type="b" name="perf-aid"><default>true</default></key>
+ <key type="b" name="memory-aid"><default>true</default></key>
+ <key type="b" name="memprof-aid"><default>false</default></key>
+ <key type="b" name="diskstat-aid"><default>true</default></key>
+ <key type="b" name="netstat-aid"><default>true</default></key>
+ <key type="b" name="energy-aid"><default>false</default></key>
+ <key type="b" name="battery-aid"><default>false</default></key>
+ <key type="b" name="compositor-aid"><default>false</default></key>
+ <key type="b" name="allow-throttle"><default>true</default></key>
+ <key type="b" name="allow-tracefd"><default>true</default></key>
+ </schema>
+</schemalist>
diff --git a/src/plugins/sysprof/sysprof-plugin.c b/src/plugins/sysprof/sysprof-plugin.c
index f2e721a6f..6d6c97db3 100644
--- a/src/plugins/sysprof/sysprof-plugin.c
+++ b/src/plugins/sysprof/sysprof-plugin.c
@@ -27,6 +27,7 @@
#include <libide-gui.h>
+#include "gbp-sysprof-tool.h"
#include "gbp-sysprof-workbench-addin.h"
#include "gbp-sysprof-workspace-addin.h"
@@ -35,6 +36,9 @@ _gbp_sysprof_register_types (PeasObjectModule *module)
{
sysprof_clock_init ();
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_RUN_TOOL,
+ GBP_TYPE_SYSPROF_TOOL);
peas_object_module_register_extension_type (module,
IDE_TYPE_WORKBENCH_ADDIN,
GBP_TYPE_SYSPROF_WORKBENCH_ADDIN);
diff --git a/src/plugins/valgrind/gbp-valgrind-tool.c b/src/plugins/valgrind/gbp-valgrind-tool.c
new file mode 100644
index 000000000..62c48ae97
--- /dev/null
+++ b/src/plugins/valgrind/gbp-valgrind-tool.c
@@ -0,0 +1,204 @@
+/* gbp-valgrind-tool.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-valgrind-tool"
+
+#include "config.h"
+
+#include <libide-gui.h>
+
+#include "gbp-valgrind-tool.h"
+
+struct _GbpValgrindTool
+{
+ IdeRunTool parent_instance;
+ char *log_name;
+};
+
+G_DEFINE_FINAL_TYPE (GbpValgrindTool, gbp_valgrind_tool, IDE_TYPE_RUN_TOOL)
+
+static gboolean
+gbp_valgrind_tool_handler_cb (IdeRunContext *run_context,
+ const char * const *argv,
+ const char * const *env,
+ const char *cwd,
+ IdeUnixFDMap *unix_fd_map,
+ gpointer user_data,
+ GError **error)
+{
+ GbpValgrindTool *self = user_data;
+ g_autoptr(GSettings) settings = NULL;
+ g_autoptr(GString) leak_kinds = NULL;
+ g_autofree char *name = NULL;
+ g_autofree char *leak_check = NULL;
+ gboolean track_origins;
+ int source_fd;
+ int dest_fd;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_RUN_CONTEXT (run_context));
+ g_assert (IDE_IS_UNIX_FD_MAP (unix_fd_map));
+ g_assert (argv != NULL);
+ g_assert (env != NULL);
+ g_assert (GBP_IS_VALGRIND_TOOL (self));
+
+ settings = g_settings_new ("org.gnome.builder.valgrind");
+
+ if (cwd != NULL)
+ ide_run_context_set_cwd (run_context, cwd);
+
+ dest_fd = ide_unix_fd_map_get_max_dest_fd (unix_fd_map) + 1;
+ if (!ide_run_context_merge_unix_fd_map (run_context, unix_fd_map, error))
+ IDE_RETURN (FALSE);
+
+ /* Create a temp file to write to and an FD to access it */
+ if (-1 == (source_fd = g_file_open_tmp ("gnome-builder-valgrind-XXXXXX.txt", &name, error)))
+ IDE_RETURN (FALSE);
+
+ /* Set our FD for valgrind to log to */
+ ide_run_context_take_fd (run_context, source_fd, dest_fd);
+
+ /* Save the filename so we can open it after exiting */
+ ide_set_string (&self->log_name, name);
+ g_debug ("Using %s for valgrind log", name);
+
+ track_origins = g_settings_get_boolean (settings, "track-origins");
+ leak_check = g_settings_get_string (settings, "leak-check");
+
+ leak_kinds = g_string_new (NULL);
+ if (g_settings_get_boolean (settings, "leak-kind-definite"))
+ g_string_append (leak_kinds, "definite,");
+ if (g_settings_get_boolean (settings, "leak-kind-possible"))
+ g_string_append (leak_kinds, "possible,");
+ if (g_settings_get_boolean (settings, "leak-kind-indirect"))
+ g_string_append (leak_kinds, "indirect,");
+ if (g_settings_get_boolean (settings, "leak-kind-reachable"))
+ g_string_append (leak_kinds, "reachable,");
+
+ ide_run_context_append_argv (run_context, "valgrind");
+ ide_run_context_append_formatted (run_context, "--log-fd=%d", dest_fd);
+ ide_run_context_append_formatted (run_context, "--leak-check=%s", leak_check);
+ ide_run_context_append_formatted (run_context, "--track-origins=%s", track_origins ? "yes" : "no");
+
+ if (leak_kinds->len > 0)
+ {
+ g_string_truncate (leak_kinds, leak_kinds->len-1);
+ ide_run_context_append_formatted (run_context, "--show-leak-kinds=%s", leak_kinds->str);
+ }
+
+ if (env[0] != NULL)
+ {
+ /* If we have to exec "env" to pass environment variables, then we
+ * must follow children to get to our target executable.
+ */
+ ide_run_context_append_argv (run_context, "--trace-children=yes");
+ ide_run_context_append_argv (run_context, "env");
+ ide_run_context_append_args (run_context, env);
+ }
+
+ ide_run_context_append_args (run_context, argv);
+
+ IDE_RETURN (TRUE);
+}
+
+static void
+gbp_valgrind_tool_prepare_to_run (IdeRunTool *run_tool,
+ IdePipeline *pipeline,
+ IdeRunCommand *run_command,
+ IdeRunContext *run_context)
+{
+ GbpValgrindTool *self = (GbpValgrindTool *)run_tool;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_VALGRIND_TOOL (self));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+ g_assert (IDE_IS_RUN_COMMAND (run_command));
+ g_assert (IDE_IS_RUN_CONTEXT (run_context));
+
+ ide_run_context_push (run_context,
+ gbp_valgrind_tool_handler_cb,
+ g_object_ref (self),
+ g_object_unref);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_valgrind_tool_stopped (IdeRunTool *run_tool)
+{
+ GbpValgrindTool *self = (GbpValgrindTool *)run_tool;
+ g_autoptr(GFile) file = NULL;
+ IdeWorkbench *workbench;
+ IdeContext *context;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_VALGRIND_TOOL (self));
+
+ if (self->log_name == NULL)
+ IDE_EXIT;
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ workbench = ide_workbench_from_context (context);
+ file = g_file_new_for_path (self->log_name);
+
+ ide_workbench_open_async (workbench,
+ file,
+ "editorui",
+ IDE_BUFFER_OPEN_FLAGS_NONE,
+ NULL, NULL, NULL, NULL);
+
+ g_clear_pointer (&self->log_name, g_free);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_valgrind_tool_finalize (GObject *object)
+{
+ GbpValgrindTool *self = (GbpValgrindTool *)object;
+
+ g_clear_pointer (&self->log_name, g_free);
+
+ G_OBJECT_CLASS (gbp_valgrind_tool_parent_class)->finalize (object);
+}
+
+static void
+gbp_valgrind_tool_class_init (GbpValgrindToolClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ IdeRunToolClass *run_tool_class = IDE_RUN_TOOL_CLASS (klass);
+
+ object_class->finalize = gbp_valgrind_tool_finalize;
+
+ run_tool_class->prepare_to_run = gbp_valgrind_tool_prepare_to_run;
+ run_tool_class->stopped = gbp_valgrind_tool_stopped;
+}
+
+static void
+gbp_valgrind_tool_init (GbpValgrindTool *self)
+{
+ ide_run_tool_set_icon_name (IDE_RUN_TOOL (self), "system-run-symbolic");
+}
diff --git a/src/plugins/valgrind/gbp-valgrind-tool.h b/src/plugins/valgrind/gbp-valgrind-tool.h
new file mode 100644
index 000000000..be8f5abaf
--- /dev/null
+++ b/src/plugins/valgrind/gbp-valgrind-tool.h
@@ -0,0 +1,31 @@
+/* gbp-valgrind-tool.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-foundry.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_VALGRIND_TOOL (gbp_valgrind_tool_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpValgrindTool, gbp_valgrind_tool, GBP, VALGRIND_TOOL, IdeRunTool)
+
+G_END_DECLS
diff --git a/src/plugins/valgrind/gbp-valgrind-workbench-addin.c
b/src/plugins/valgrind/gbp-valgrind-workbench-addin.c
index a0ea1b367..173dab00a 100644
--- a/src/plugins/valgrind/gbp-valgrind-workbench-addin.c
+++ b/src/plugins/valgrind/gbp-valgrind-workbench-addin.c
@@ -34,289 +34,8 @@
struct _GbpValgrindWorkbenchAddin
{
- GObject parent_instance;
-
- IdeWorkbench *workbench;
- IdeRunManager *run_manager;
- IdeBuildManager *build_manager;
- char *log_name;
- GSimpleActionGroup *actions;
-
- gulong notify_pipeline_handler;
- gulong stopped_handler;
-
- guint has_handler : 1;
-};
-
-static void
-set_state (GSimpleAction *action,
- GVariant *param,
- gpointer user_data)
-{
- g_simple_action_set_state (action, param);
-}
-
-static gboolean
-get_bool (GbpValgrindWorkbenchAddin *self,
- const char *action_name)
-{
- g_autoptr(GVariant) state = NULL;
- GAction *action;
-
- g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
- g_assert (action_name != NULL);
-
- if (!(action = g_action_map_lookup_action (G_ACTION_MAP (self->actions), action_name)))
- g_return_val_if_reached (FALSE);
-
- if (!(state = g_action_get_state (action)))
- g_return_val_if_reached (FALSE);
-
- if (!g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN))
- g_return_val_if_reached (FALSE);
-
- return g_variant_get_boolean (state);
-}
-
-static const char *
-get_string (GbpValgrindWorkbenchAddin *self,
- const char *action_name)
-{
- g_autoptr(GVariant) state = NULL;
- GAction *action;
-
- g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
- g_assert (action_name != NULL);
-
- if (!(action = g_action_map_lookup_action (G_ACTION_MAP (self->actions), action_name)))
- g_return_val_if_reached (NULL);
-
- if (!(state = g_action_get_state (action)))
- g_return_val_if_reached (NULL);
-
- if (!g_variant_is_of_type (state, G_VARIANT_TYPE_STRING))
- g_return_val_if_reached (NULL);
-
- return g_variant_get_string (state, NULL);
-}
-
-static void
-gbp_valgrind_workbench_addin_stop_cb (GbpValgrindWorkbenchAddin *self,
- IdeRunManager *run_manager)
-{
- g_autoptr(GFile) file = NULL;
-
- IDE_ENTRY;
-
- g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
- g_assert (IDE_IS_RUN_MANAGER (run_manager));
-
- if (self->workbench == NULL || self->log_name == NULL)
- IDE_EXIT;
-
- file = g_file_new_for_path (self->log_name);
- ide_workbench_open_async (self->workbench,
- file,
- "editorui",
- IDE_BUFFER_OPEN_FLAGS_NONE,
- NULL, NULL, NULL, NULL);
- g_clear_pointer (&self->log_name, g_free);
-
- IDE_EXIT;
-}
-
-static gboolean
-gbp_valgrind_workbench_addin_run_handler_cb (IdeRunContext *run_context,
- const char * const *argv,
- const char * const *env,
- const char *cwd,
- IdeUnixFDMap *unix_fd_map,
- gpointer user_data,
- GError **error)
-{
- GbpValgrindWorkbenchAddin *self = user_data;
- g_autofree char *name = NULL;
- g_autofree char *track_origins = NULL;
- g_autofree char *leak_check = NULL;
- g_autoptr(GString) leak_kinds = NULL;
- int source_fd;
- int dest_fd;
-
- IDE_ENTRY;
-
- g_assert (IDE_IS_RUN_CONTEXT (run_context));
- g_assert (IDE_IS_UNIX_FD_MAP (unix_fd_map));
- g_assert (argv != NULL);
- g_assert (env != NULL);
- g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
-
- if (cwd != NULL)
- ide_run_context_set_cwd (run_context, cwd);
-
- dest_fd = ide_unix_fd_map_get_max_dest_fd (unix_fd_map) + 1;
- if (!ide_run_context_merge_unix_fd_map (run_context, unix_fd_map, error))
- IDE_RETURN (FALSE);
-
- /* Create a temp file to write to and an FD to access it */
- if (-1 == (source_fd = g_file_open_tmp ("gnome-builder-valgrind-XXXXXX.txt", &name, error)))
- IDE_RETURN (FALSE);
-
- /* Set our FD for valgrind to log to */
- ide_run_context_take_fd (run_context, source_fd, dest_fd);
-
- /* Save the filename so we can open it after exiting */
- g_clear_pointer (&self->log_name, g_free);
- self->log_name = g_steal_pointer (&name);
-
- /* Convert action state to command-line arguments */
- track_origins = g_strdup_printf ("--track-origins=%s", get_bool (self, "track-origins") ? "yes" : "no");
- leak_check = g_strdup_printf ("--leak-check=%s", get_string (self, "leak-check"));
-
- leak_kinds = g_string_new (NULL);
- if (get_bool (self, "leak-kind-definite")) g_string_append (leak_kinds, "definite,");
- if (get_bool (self, "leak-kind-possible")) g_string_append (leak_kinds, "possible,");
- if (get_bool (self, "leak-kind-indirect")) g_string_append (leak_kinds, "indirect,");
- if (get_bool (self, "leak-kind-reachable")) g_string_append (leak_kinds, "reachable,");
-
- ide_run_context_append_argv (run_context, "valgrind");
- ide_run_context_append_formatted (run_context, "--log-fd=%d", dest_fd);
- ide_run_context_append_argv (run_context, leak_check);
- ide_run_context_append_argv (run_context, track_origins);
-
- if (leak_kinds->len > 0)
- {
- g_string_truncate (leak_kinds, leak_kinds->len-1);
- ide_run_context_append_formatted (run_context, "--show-leak-kinds=%s", leak_kinds->str);
- }
-
- if (env[0] != NULL)
- {
- /* If we have to exec "env" to pass environment variables, then we
- * must follow children to get to our target executable.
- */
- ide_run_context_append_argv (run_context, "--trace-children=yes");
- ide_run_context_append_argv (run_context, "env");
- ide_run_context_append_args (run_context, env);
- }
-
- ide_run_context_append_args (run_context, argv);
-
- IDE_RETURN (TRUE);
-}
-
-static void
-gbp_valgrind_workbench_addin_run_handler (IdeRunManager *run_manager,
- IdePipeline *pipeline,
- IdeRunCommand *run_command,
- IdeRunContext *run_context,
- gpointer user_data)
-{
- GbpValgrindWorkbenchAddin *self = user_data;
-
- IDE_ENTRY;
-
- g_assert (IDE_IS_RUN_MANAGER (run_manager));
- g_assert (IDE_IS_RUN_CONTEXT (run_context));
- g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
-
- ide_run_context_push (run_context,
- gbp_valgrind_workbench_addin_run_handler_cb,
- g_object_ref (self),
- g_object_unref);
-
- IDE_EXIT;
-}
-
-static void
-gbp_valgrind_workbench_addin_notify_pipeline_cb (GbpValgrindWorkbenchAddin *self,
- GParamSpec *pspec,
- IdeBuildManager *build_manager)
-{
- IdePipeline *pipeline;
- IdeRuntime *runtime;
- gboolean can_handle = FALSE;
-
- IDE_ENTRY;
-
- g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
- g_assert (IDE_IS_BUILD_MANAGER (build_manager));
- g_assert (IDE_IS_RUN_MANAGER (self->run_manager));
-
- if (!(pipeline = ide_build_manager_get_pipeline (build_manager)) ||
- !(runtime = ide_pipeline_get_runtime (pipeline)) ||
- !ide_runtime_contains_program_in_path (runtime, "valgrind", NULL))
- IDE_GOTO (not_found);
-
- can_handle = TRUE;
-
-not_found:
- if (can_handle != self->has_handler)
- {
- self->has_handler = can_handle;
-
- if (can_handle)
- ide_run_manager_add_handler (self->run_manager,
- "valgrind",
- _("Run with Valgrind"),
- "system-run-symbolic",
- gbp_valgrind_workbench_addin_run_handler,
- g_object_ref (self),
- g_object_unref);
- else
- ide_run_manager_remove_handler (self->run_manager, "valgrind");
- }
-
- IDE_EXIT;
-}
-
-static void
-gbp_valgrind_workbench_addin_project_loaded (IdeWorkbenchAddin *addin,
- IdeProjectInfo *project_info)
-{
- GbpValgrindWorkbenchAddin *self = (GbpValgrindWorkbenchAddin *)addin;
- IdeBuildManager *build_manager;
- IdeRunManager *run_manager;
- IdeContext *context;
-
- IDE_ENTRY;
-
- g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
- g_assert (IDE_IS_PROJECT_INFO (project_info));
- g_assert (IDE_IS_WORKBENCH (self->workbench));
-
- context = ide_workbench_get_context (self->workbench);
- build_manager = ide_build_manager_from_context (context);
- run_manager = ide_run_manager_from_context (context);
-
- g_set_object (&self->build_manager, build_manager);
- g_set_object (&self->run_manager, run_manager);
-
- self->notify_pipeline_handler =
- g_signal_connect_object (build_manager,
- "notify::pipeline",
- G_CALLBACK (gbp_valgrind_workbench_addin_notify_pipeline_cb),
- self,
- G_CONNECT_SWAPPED);
-
- self->stopped_handler =
- g_signal_connect_object (run_manager,
- "stopped",
- G_CALLBACK (gbp_valgrind_workbench_addin_stop_cb),
- self,
- G_CONNECT_SWAPPED);
-
- gbp_valgrind_workbench_addin_notify_pipeline_cb (self, NULL, build_manager);
-
- IDE_EXIT;
-}
-
-static const GActionEntry actions[] = {
- { "track-origins", NULL, NULL, "true", set_state },
- { "leak-check", NULL, "s", "'summary'", set_state },
- { "leak-kind-definite", NULL, NULL, "true", set_state },
- { "leak-kind-possible", NULL, NULL, "true", set_state },
- { "leak-kind-indirect", NULL, NULL, "false", set_state },
- { "leak-kind-reachable", NULL, NULL, "false", set_state },
+ GObject parent_instance;
+ GActionGroup *actions;
};
static void
@@ -324,19 +43,29 @@ gbp_valgrind_workbench_addin_load (IdeWorkbenchAddin *addin,
IdeWorkbench *workbench)
{
GbpValgrindWorkbenchAddin *self = (GbpValgrindWorkbenchAddin *)addin;
+ g_autoptr(GSettings) settings = NULL;
+ static const char *keys[] = {
+ "leak-check",
+ "leak-kind-definite",
+ "leak-kind-indirect",
+ "leak-kind-possible",
+ "leak-kind-reachable",
+ "track-origins",
+ };
IDE_ENTRY;
g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
g_assert (IDE_IS_WORKBENCH (workbench));
- self->workbench = workbench;
+ settings = g_settings_new ("org.gnome.builder.valgrind");
+ self->actions = G_ACTION_GROUP (g_simple_action_group_new ());
- self->actions = g_simple_action_group_new ();
- g_action_map_add_action_entries (G_ACTION_MAP (self->actions),
- actions,
- G_N_ELEMENTS (actions),
- self);
+ for (guint i = 0; i < G_N_ELEMENTS (keys); i++)
+ {
+ g_autoptr(GAction) action = g_settings_create_action (settings, keys[i]);
+ g_action_map_add_action (G_ACTION_MAP (self->actions), action);
+ }
IDE_EXIT;
}
@@ -352,28 +81,8 @@ gbp_valgrind_workbench_addin_unload (IdeWorkbenchAddin *addin,
g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
g_assert (IDE_IS_WORKBENCH (workbench));
- if (self->build_manager != NULL)
- {
- g_clear_signal_handler (&self->notify_pipeline_handler, self->build_manager);
- g_clear_object (&self->build_manager);
- }
-
- if (self->run_manager != NULL)
- {
- g_clear_signal_handler (&self->stopped_handler, self->run_manager);
-
- if (self->has_handler)
- ide_run_manager_remove_handler (self->run_manager, "valgrind");
-
- g_clear_object (&self->run_manager);
- }
-
- g_clear_pointer (&self->log_name, g_free);
-
g_clear_object (&self->actions);
- self->workbench = NULL;
-
IDE_EXIT;
}
@@ -388,9 +97,10 @@ gbp_valgrind_workbench_addin_workspace_added (IdeWorkbenchAddin *addin,
g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
g_assert (IDE_IS_WORKSPACE (workspace));
- gtk_widget_insert_action_group (GTK_WIDGET (workspace),
- "valgrind",
- G_ACTION_GROUP (self->actions));
+ if (IDE_IS_PRIMARY_WORKSPACE (workspace))
+ gtk_widget_insert_action_group (GTK_WIDGET (workspace),
+ "valgrind",
+ self->actions);
IDE_EXIT;
}
@@ -416,7 +126,6 @@ workbench_addin_iface_init (IdeWorkbenchAddinInterface *iface)
{
iface->load = gbp_valgrind_workbench_addin_load;
iface->unload = gbp_valgrind_workbench_addin_unload;
- iface->project_loaded = gbp_valgrind_workbench_addin_project_loaded;
iface->workspace_added = gbp_valgrind_workbench_addin_workspace_added;
iface->workspace_removed = gbp_valgrind_workbench_addin_workspace_removed;
}
diff --git a/src/plugins/valgrind/meson.build b/src/plugins/valgrind/meson.build
index 72bb792f9..132ba5616 100644
--- a/src/plugins/valgrind/meson.build
+++ b/src/plugins/valgrind/meson.build
@@ -2,6 +2,7 @@ if get_option('plugin_valgrind')
plugins_sources += files([
'valgrind-plugin.c',
+ 'gbp-valgrind-tool.c',
'gbp-valgrind-workbench-addin.c',
])
@@ -13,4 +14,6 @@ plugin_valgrind_resources = gnome.compile_resources(
plugins_sources += plugin_valgrind_resources
+install_data(['org.gnome.builder.valgrind.gschema.xml'], install_dir: schema_dir)
+
endif
diff --git a/src/plugins/valgrind/org.gnome.builder.valgrind.gschema.xml
b/src/plugins/valgrind/org.gnome.builder.valgrind.gschema.xml
new file mode 100644
index 000000000..fe9eb0387
--- /dev/null
+++ b/src/plugins/valgrind/org.gnome.builder.valgrind.gschema.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schemalist>
+ <schema id="org.gnome.builder.valgrind" path="/org/gnome/builder/valgrind/" gettext-domain="gnome-builder">
+ <key name="leak-kind-definite" type="b">
+ <default>true</default>
+ </key>
+ <key name="leak-kind-possible" type="b">
+ <default>true</default>
+ </key>
+ <key name="leak-kind-indirect" type="b">
+ <default>false</default>
+ </key>
+ <key name="leak-kind-reachable" type="b">
+ <default>false</default>
+ </key>
+ <key name="track-origins" type="b">
+ <default>true</default>
+ </key>
+ <key name="leak-check" type="s">
+ <choices>
+ <choice value="no"/>
+ <choice value="summary"/>
+ <choice value="full"/>
+ </choices>
+ <default>'summary'</default>
+ </key>
+ </schema>
+</schemalist>
diff --git a/src/plugins/valgrind/valgrind-plugin.c b/src/plugins/valgrind/valgrind-plugin.c
index d6d0a5715..b3df73279 100644
--- a/src/plugins/valgrind/valgrind-plugin.c
+++ b/src/plugins/valgrind/valgrind-plugin.c
@@ -26,11 +26,15 @@
#include <libide-gui.h>
+#include "gbp-valgrind-tool.h"
#include "gbp-valgrind-workbench-addin.h"
_IDE_EXTERN void
_gbp_valgrind_register_types (PeasObjectModule *module)
{
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_RUN_TOOL,
+ GBP_TYPE_VALGRIND_TOOL);
peas_object_module_register_extension_type (module,
IDE_TYPE_WORKBENCH_ADDIN,
GBP_TYPE_VALGRIND_WORKBENCH_ADDIN);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]