[gnome-builder/wip/chergert/sysprof] sysprof: stub out sysprof perspective
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/sysprof] sysprof: stub out sysprof perspective
- Date: Fri, 19 Aug 2016 23:30:33 +0000 (UTC)
commit ff4a98e91cca65471c8f7f3ac50903cc052dbae0
Author: Christian Hergert <chergert redhat com>
Date: Fri Aug 19 16:30:16 2016 -0700
sysprof: stub out sysprof perspective
configure.ac | 2 +
libide/runner/OVERVIEW.md | 11 +
libide/runner/ide-run-manager.c | 376 +++++++++++++++++++++--
libide/runner/ide-run-manager.h | 47 +++-
plugins/Makefile.am | 1 +
plugins/autotools/ide-makecache.c | 1 +
plugins/run-tools/gbp-run-workbench-addin.c | 100 +------
plugins/sysprof/Makefile.am | 37 +++
plugins/sysprof/configure.ac | 21 ++
plugins/sysprof/gbp-sysprof-perspective.c | 184 +++++++++++
plugins/sysprof/gbp-sysprof-perspective.h | 36 +++
plugins/sysprof/gbp-sysprof-perspective.ui | 15 +
plugins/sysprof/gbp-sysprof-plugin.c | 30 ++
plugins/sysprof/gbp-sysprof-workbench-addin.c | 401 +++++++++++++++++++++++++
plugins/sysprof/gbp-sysprof-workbench-addin.h | 33 ++
plugins/sysprof/gtk/menus.ui | 11 +
plugins/sysprof/sysprof.gresource.xml | 7 +
plugins/sysprof/sysprof.plugin | 7 +
18 files changed, 1184 insertions(+), 136 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index c896021..8f09661 100644
--- a/configure.ac
+++ b/configure.ac
@@ -308,6 +308,7 @@ m4_include([plugins/run-tools/configure.ac])
m4_include([plugins/support/configure.ac])
m4_include([plugins/symbol-tree/configure.ac])
m4_include([plugins/sysmon/configure.ac])
+m4_include([plugins/sysprof/configure.ac])
m4_include([plugins/todo/configure.ac])
m4_include([plugins/terminal/configure.ac])
m4_include([plugins/vala-pack/configure.ac])
@@ -595,6 +596,7 @@ echo " Python Language Pack ................. : ${enable_python_pack_plugin}"
echo " Run Tools ............................ : ${enable_run_tools_plugin}"
echo " Support .............................. : ${enable_support_plugin}"
echo " System Monitor ....................... : ${enable_sysmon_plugin}"
+echo " Sysprof System Profiler .............. : ${enable_sysprof_plugin}"
echo " Symbol Tree .......................... : ${enable_symbol_tree_plugin}"
echo " Todo ................................. : ${enable_todo_plugin}"
echo " Terminal ............................. : ${enable_terminal_plugin}"
diff --git a/libide/runner/OVERVIEW.md b/libide/runner/OVERVIEW.md
index cf5801a..94c4e33 100644
--- a/libide/runner/OVERVIEW.md
+++ b/libide/runner/OVERVIEW.md
@@ -87,3 +87,14 @@ So it might need to do something like:
runner.prepend_argv('sysprof-spawner')
+
+## RunHandlers
+
+Because we want one runner at a time, and different plugins might implement
+different runners (debugger, profiler, basic run support), we register
+a run handler.
+
+When ide_run_manager_run_async() is called, the run handler will be called
+and it can adjust things as necessary.
+
+
diff --git a/libide/runner/ide-run-manager.c b/libide/runner/ide-run-manager.c
index b86d93a..fbbab46 100644
--- a/libide/runner/ide-run-manager.c
+++ b/libide/runner/ide-run-manager.c
@@ -24,6 +24,7 @@
#include "ide-debug.h"
#include "buildsystem/ide-build-manager.h"
+#include "buildsystem/ide-build-system.h"
#include "buildsystem/ide-build-target.h"
#include "buildsystem/ide-configuration.h"
#include "buildsystem/ide-configuration-manager.h"
@@ -31,14 +32,29 @@
#include "runner/ide-runner.h"
#include "runtimes/ide-runtime.h"
+typedef struct
+{
+ gchar *id;
+ gchar *title;
+ gchar *icon_name;
+ gchar *accel;
+ IdeRunHandler handler;
+ gpointer handler_data;
+ GDestroyNotify handler_data_destroy;
+} IdeRunHandlerInfo;
+
struct _IdeRunManager
{
- IdeObject parent_instance;
+ IdeObject parent_instance;
+
+ GCancellable *cancellable;
+ GSimpleActionGroup *actions;
+ IdeBuildTarget *build_target;
- GCancellable *cancellable;
- GSimpleActionGroup *actions;
+ const IdeRunHandlerInfo *handler;
+ GList *handlers;
- guint busy : 1;
+ guint busy : 1;
};
G_DEFINE_TYPE (IdeRunManager, ide_run_manager, IDE_TYPE_OBJECT)
@@ -52,12 +68,32 @@ enum {
static GParamSpec *properties [N_PROPS];
static void
+ide_run_handler_info_free (gpointer data)
+{
+ IdeRunHandlerInfo *info = data;
+
+ g_free (info->id);
+ g_free (info->title);
+ g_free (info->icon_name);
+ g_free (info->accel);
+
+ if (info->handler_data_destroy)
+ info->handler_data_destroy (info->handler_data);
+
+ g_slice_free (IdeRunHandlerInfo, info);
+}
+
+static void
ide_run_manager_finalize (GObject *object)
{
IdeRunManager *self = (IdeRunManager *)object;
g_clear_object (&self->cancellable);
g_clear_object (&self->actions);
+ g_clear_object (&self->build_target);
+
+ g_list_free_full (self->handlers, ide_run_handler_info_free);
+ self->handlers = NULL;
G_OBJECT_CLASS (ide_run_manager_parent_class)->finalize (object);
}
@@ -217,6 +253,9 @@ ide_run_manager_install_cb (GObject *object,
g_assert (IDE_IS_RUNNER (runner));
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+ if (self->handler != NULL)
+ self->handler->handler (self, runner, self->handler->handler_data);
+
ide_runner_run_async (runner,
cancellable,
ide_run_manager_run_cb,
@@ -244,6 +283,66 @@ ide_run_manager_task_completed (IdeRunManager *self,
IDE_EXIT;
}
+static void
+ide_run_manager_do_install_before_run (IdeRunManager *self,
+ GTask *task)
+{
+ IdeBuildManager *build_manager;
+ IdeContext *context;
+
+ g_assert (IDE_IS_RUN_MANAGER (self));
+ g_assert (G_IS_TASK (task));
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ build_manager = ide_context_get_build_manager (context);
+
+ /*
+ * First we need to make sure the target is up to date and installed
+ * so that all the dependent resources are available.
+ */
+
+ self->busy = TRUE;
+
+ g_signal_connect_object (task,
+ "notify::completed",
+ G_CALLBACK (ide_run_manager_task_completed),
+ self,
+ G_CONNECT_SWAPPED);
+
+ ide_build_manager_install_async (build_manager,
+ g_task_get_cancellable (task),
+ ide_run_manager_install_cb,
+ g_object_ref (task));
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_BUSY]);
+}
+
+static void
+ide_run_manager_run_discover_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeRunManager *self = (IdeRunManager *)object;
+ g_autoptr(IdeBuildTarget) build_target = NULL;
+ g_autoptr(GTask) task = user_data;
+ GError *error = NULL;
+
+ g_assert (IDE_IS_RUN_MANAGER (self));
+ g_assert (G_IS_ASYNC_RESULT (result));
+
+ build_target = ide_run_manager_discover_default_target_finish (self, result, &error);
+
+ if (build_target == NULL)
+ {
+ g_task_return_error (task, error);
+ return;
+ }
+
+ g_task_set_task_data (task, g_steal_pointer (&build_target), g_object_unref);
+
+ ide_run_manager_do_install_before_run (self, task);
+}
+
void
ide_run_manager_run_async (IdeRunManager *self,
IdeBuildTarget *build_target,
@@ -253,14 +352,12 @@ ide_run_manager_run_async (IdeRunManager *self,
{
g_autoptr(GTask) task = NULL;
g_autoptr(GCancellable) local_cancellable = NULL;
- IdeBuildManager *build_manager;
- IdeContext *context;
GError *error = NULL;
IDE_ENTRY;
g_return_if_fail (IDE_IS_RUN_MANAGER (self));
- g_return_if_fail (IDE_IS_BUILD_TARGET (build_target));
+ g_return_if_fail (!build_target || IDE_IS_BUILD_TARGET (build_target));
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
if (cancellable == NULL)
@@ -268,40 +365,33 @@ ide_run_manager_run_async (IdeRunManager *self,
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, ide_run_manager_run_async);
- g_task_set_task_data (task, g_object_ref (build_target), g_object_unref);
+
+ g_set_object (&self->cancellable, cancellable);
if (ide_run_manager_check_busy (self, &error))
{
g_task_return_error (task, error);
- IDE_GOTO (failure);
+ IDE_EXIT;
}
- /*
- * First we need to make sure the target is up to date and installed
- * so that all the dependent resources are available.
- */
-
- context = ide_object_get_context (IDE_OBJECT (self));
- build_manager = ide_context_get_build_manager (context);
-
- self->busy = TRUE;
-
- g_set_object (&self->cancellable, cancellable);
-
- g_signal_connect_object (task,
- "notify::completed",
- G_CALLBACK (ide_run_manager_task_completed),
- self,
- G_CONNECT_SWAPPED);
+ if (build_target == NULL)
+ {
+ build_target = ide_run_manager_get_build_target (self);
+
+ if (build_target == NULL)
+ {
+ ide_run_manager_discover_default_target_async (self,
+ cancellable,
+ ide_run_manager_run_discover_cb,
+ g_object_ref (task));
+ IDE_EXIT;
+ }
+ }
- ide_build_manager_install_async (build_manager,
- cancellable,
- ide_run_manager_install_cb,
- g_steal_pointer (&task));
+ g_task_set_task_data (task, g_object_ref (build_target), g_object_unref);
- g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_BUSY]);
+ ide_run_manager_do_install_before_run (self, task);
-failure:
IDE_EXIT;
}
@@ -325,7 +415,7 @@ ide_run_manager_run_finish (IdeRunManager *self,
static gboolean
do_cancel_in_timeout (gpointer user_data)
{
- GCancellable *cancellable = user_data;
+ g_autoptr(GCancellable) cancellable = user_data;
IDE_ENTRY;
@@ -349,3 +439,223 @@ 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);
+ break;
+ }
+ }
+}
+
+void
+ide_run_manager_add_handler (IdeRunManager *self,
+ const gchar *id,
+ const gchar *title,
+ const gchar *icon_name,
+ const gchar *accel,
+ 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_new (IdeRunHandlerInfo);
+ info->id = g_strdup (id);
+ info->title = g_strdup (title);
+ info->icon_name = g_strdup (icon_name);
+ info->accel = g_strdup (accel);
+ 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_remove_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;
+ }
+ }
+}
+
+/**
+ * ide_run_manager_get_build_target:
+ *
+ * Gets the build target that will be executed by the run manager if a
+ * specific build target has not been specified to ide_run_manager_run_async().
+ *
+ * Returns: (transfer none): An #IdeBuildTarget or %NULL if no build target
+ * has been set.
+ */
+IdeBuildTarget *
+ide_run_manager_get_build_target (IdeRunManager *self)
+{
+ g_return_val_if_fail (IDE_IS_RUN_MANAGER (self), NULL);
+
+ return self->build_target;
+}
+
+static IdeBuildTarget *
+find_best_target (GPtrArray *targets)
+{
+ IdeBuildTarget *ret = NULL;
+ guint i;
+
+ g_assert (targets != NULL);
+
+ /* TODO:
+ *
+ * This is just a barebones way to try to discover a target that matters. We
+ * could probably defer this off to the build system. Either way, it's shit
+ * and should be thought through by someone.
+ */
+
+ for (i = 0; i < targets->len; i++)
+ {
+ IdeBuildTarget *target = g_ptr_array_index (targets, i);
+ g_autoptr(GFile) installdir = NULL;
+
+ installdir = ide_build_target_get_install_directory (target);
+
+ if (installdir == NULL)
+ continue;
+
+ if (ret == NULL)
+ ret = target;
+ }
+
+ return ret;
+}
+
+static void
+ide_run_manager_discover_default_target_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeBuildSystem *build_system = (IdeBuildSystem *)object;
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GPtrArray) targets = NULL;
+ IdeBuildTarget *best_match;
+ GError *error = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_BUILD_SYSTEM (build_system));
+ g_assert (G_IS_ASYNC_RESULT (result));
+
+ targets = ide_build_system_get_build_targets_finish (build_system, result, &error);
+
+ if (targets == NULL)
+ {
+ g_task_return_error (task, error);
+ IDE_EXIT;
+ }
+
+ best_match = find_best_target (targets);
+
+ if (best_match == NULL)
+ {
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Failed to locate build target");
+ IDE_EXIT;
+ }
+
+ g_task_return_pointer (task, g_object_ref (best_match), g_object_unref);
+
+ IDE_EXIT;
+}
+
+void
+ide_run_manager_discover_default_target_async (IdeRunManager *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+ IdeBuildSystem *build_system;
+ IdeContext *context;
+
+ IDE_ENTRY;
+
+ g_return_if_fail (IDE_IS_RUN_MANAGER (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_source_tag (task, ide_run_manager_discover_default_target_async);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ build_system = ide_context_get_build_system (context);
+
+ ide_build_system_get_build_targets_async (build_system,
+ cancellable,
+ ide_run_manager_discover_default_target_cb,
+ g_object_ref (task));
+
+ IDE_EXIT;
+}
+
+/**
+ * ide_run_manager_discover_default_target_finish:
+ *
+ * Returns: (transfer none): An #IdeBuildTarget if successful; otherwise %NULL
+ * and @error is set.
+ */
+IdeBuildTarget *
+ide_run_manager_discover_default_target_finish (IdeRunManager *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ IdeBuildTarget *ret;
+
+ IDE_ENTRY;
+
+ g_return_val_if_fail (IDE_IS_RUN_MANAGER (self), NULL);
+ g_return_val_if_fail (G_IS_TASK (result), NULL);
+
+ ret = g_task_propagate_pointer (G_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
diff --git a/libide/runner/ide-run-manager.h b/libide/runner/ide-run-manager.h
index 49a3e3f..358463a 100644
--- a/libide/runner/ide-run-manager.h
+++ b/libide/runner/ide-run-manager.h
@@ -21,22 +21,49 @@
#include "ide-object.h"
+#include "buildsystem/ide-build-target.h"
+#include "runner/ide-runner.h"
+
G_BEGIN_DECLS
#define IDE_TYPE_RUN_MANAGER (ide_run_manager_get_type())
G_DECLARE_FINAL_TYPE (IdeRunManager, ide_run_manager, IDE, RUN_MANAGER, IdeObject)
-void ide_run_manager_cancel (IdeRunManager *self);
-gboolean ide_run_manager_get_busy (IdeRunManager *self);
-void ide_run_manager_run_async (IdeRunManager *self,
- IdeBuildTarget *build_target,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean ide_run_manager_run_finish (IdeRunManager *self,
- GAsyncResult *result,
- GError **error);
+typedef void (*IdeRunHandler) (IdeRunManager *self,
+ IdeRunner *runner,
+ gpointer user_data);
+
+IdeBuildTarget *ide_run_manager_get_build_target (IdeRunManager *self);
+void ide_run_manager_cancel (IdeRunManager *self);
+gboolean ide_run_manager_get_busy (IdeRunManager *self);
+void ide_run_manager_set_handler (IdeRunManager *self,
+ const gchar *id);
+void ide_run_manager_add_handler (IdeRunManager *self,
+ const gchar *id,
+ const gchar *title,
+ const gchar *icon_name,
+ const gchar *accel,
+ IdeRunHandler run_handler,
+ gpointer user_data,
+ GDestroyNotify user_data_destroy);
+void ide_run_manager_remove_handler (IdeRunManager *self,
+ const gchar *id);
+void ide_run_manager_run_async (IdeRunManager *self,
+ IdeBuildTarget *build_target,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ide_run_manager_run_finish (IdeRunManager *self,
+ GAsyncResult *result,
+ GError **error);
+void ide_run_manager_discover_default_target_async (IdeRunManager *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+IdeBuildTarget *ide_run_manager_discover_default_target_finish (IdeRunManager *self,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 0827d68..14b3b4b 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -31,6 +31,7 @@ SUBDIRS = \
support \
symbol-tree \
sysmon \
+ sysprof \
terminal \
todo \
vala-pack \
diff --git a/plugins/autotools/ide-makecache.c b/plugins/autotools/ide-makecache.c
index f06c9a9..765ab08 100644
--- a/plugins/autotools/ide-makecache.c
+++ b/plugins/autotools/ide-makecache.c
@@ -1916,6 +1916,7 @@ ide_makecache_get_build_targets_worker (GTask *task,
ide_subprocess_launcher_push_argv (launcher, "print-bindir");
ide_subprocess_launcher_push_argv (launcher, "print-libexecdir");
ide_subprocess_launcher_push_argv (launcher, "print-bin_PROGRAMS");
+ ide_subprocess_launcher_push_argv (launcher, "print-bin_SCRIPTS");
ide_subprocess_launcher_push_argv (launcher, "print-noinst_PROGRAMS");
ide_subprocess_launcher_push_argv (launcher, "print-libexec_PROGRAMS");
diff --git a/plugins/run-tools/gbp-run-workbench-addin.c b/plugins/run-tools/gbp-run-workbench-addin.c
index 6cf8fd6..a5dcff0 100644
--- a/plugins/run-tools/gbp-run-workbench-addin.c
+++ b/plugins/run-tools/gbp-run-workbench-addin.c
@@ -61,93 +61,6 @@ failure:
IDE_EXIT;
}
-static IdeBuildTarget *
-find_best_target (GPtrArray *targets)
-{
- IdeBuildTarget *ret = NULL;
- guint i;
-
- g_assert (targets != NULL);
-
- for (i = 0; i < targets->len; i++)
- {
- IdeBuildTarget *target = g_ptr_array_index (targets, i);
- g_autoptr(GFile) installdir = NULL;
-
- installdir = ide_build_target_get_install_directory (target);
-
- if (installdir == NULL)
- continue;
-
- if (ret == NULL)
- ret = target;
-
- /* TODO: Compare likelyhood of primary binary */
- }
-
- return ret;
-}
-
-static void
-gbp_run_workbench_addin_get_build_targets_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
-{
- IdeBuildSystem *build_system = (IdeBuildSystem *)object;
- GbpRunWorkbenchAddin *self;
- g_autoptr(GPtrArray) targets = NULL;
- g_autoptr(GTask) task = user_data;
- IdeBuildTarget *best_match;
- IdeRunManager *run_manager;
- GCancellable *cancellable;
- IdeContext *context;
- GError *error = NULL;
-
- IDE_ENTRY;
-
- g_assert (IDE_IS_BUILD_SYSTEM (build_system));
- g_assert (G_IS_ASYNC_RESULT (result));
- g_assert (G_IS_TASK (task));
-
- self = g_task_get_source_object (task);
- cancellable = g_task_get_cancellable (task);
-
- g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
- g_assert (GBP_IS_RUN_WORKBENCH_ADDIN (self));
- g_assert (IDE_IS_WORKBENCH (self->workbench));
-
- targets = ide_build_system_get_build_targets_finish (build_system, result, &error);
-
- if (targets == NULL)
- {
- g_task_return_error (task, error);
- IDE_EXIT;
- }
-
- best_match = find_best_target (targets);
-
- if (best_match == NULL)
- {
- g_task_return_new_error (task,
- G_IO_ERROR,
- G_IO_ERROR_FAILED,
- "%s",
- _("Failed to locate build target"));
- IDE_EXIT;
- }
-
- context = ide_workbench_get_context (self->workbench);
- run_manager = ide_context_get_run_manager (context);
-
- ide_run_manager_run_async (run_manager,
- best_match,
- cancellable,
- gbp_run_workbench_addin_run_cb,
- g_steal_pointer (&task));
-
- IDE_EXIT;
-}
-
static void
gbp_run_workbench_addin_run (GSimpleAction *action,
GVariant *param,
@@ -155,7 +68,7 @@ gbp_run_workbench_addin_run (GSimpleAction *action,
{
GbpRunWorkbenchAddin *self = user_data;
g_autoptr(GTask) task = NULL;
- IdeBuildSystem *build_system;
+ IdeRunManager *run_manager;
IdeContext *context;
IDE_ENTRY;
@@ -164,15 +77,16 @@ gbp_run_workbench_addin_run (GSimpleAction *action,
g_assert (GBP_IS_RUN_WORKBENCH_ADDIN (self));
context = ide_workbench_get_context (self->workbench);
- build_system = ide_context_get_build_system (context);
+ run_manager = ide_context_get_run_manager (context);
task = g_task_new (self, NULL, NULL, NULL);
g_task_set_source_tag (task, gbp_run_workbench_addin_run);
- ide_build_system_get_build_targets_async (build_system,
- NULL,
- gbp_run_workbench_addin_get_build_targets_cb,
- g_steal_pointer (&task));
+ ide_run_manager_run_async (run_manager,
+ NULL,
+ NULL,
+ gbp_run_workbench_addin_run_cb,
+ g_steal_pointer (&task));
IDE_EXIT;
}
diff --git a/plugins/sysprof/Makefile.am b/plugins/sysprof/Makefile.am
new file mode 100644
index 0000000..27bc552
--- /dev/null
+++ b/plugins/sysprof/Makefile.am
@@ -0,0 +1,37 @@
+if ENABLE_SYSPROF_PLUGIN
+
+DISTCLEANFILES =
+BUILT_SOURCES =
+CLEANFILES =
+EXTRA_DIST = $(plugin_DATA)
+
+plugindir = $(libdir)/gnome-builder/plugins
+plugin_LTLIBRARIES = libsysprof-plugin.la
+dist_plugin_DATA = sysprof.plugin
+
+libsysprof_plugin_la_SOURCES = \
+ gbp-sysprof-plugin.c \
+ gbp-sysprof-perspective.c \
+ gbp-sysprof-perspective.h \
+ gbp-sysprof-workbench-addin.c \
+ gbp-sysprof-workbench-addin.h \
+ $(NULL)
+
+nodist_libsysprof_plugin_la_SOURCES = \
+ gbp-sysprof-resources.c \
+ gbp-sysprof-resources.h
+
+libsysprof_plugin_la_CFLAGS = $(PLUGIN_CFLAGS) $(SYSPROF_CFLAGS)
+libsysprof_plugin_la_LIBADD = $(PLUGIN_LIBS) $(SYSPROF_LIBS)
+
+glib_resources_c = gbp-sysprof-resources.c
+glib_resources_h = gbp-sysprof-resources.h
+glib_resources_xml = sysprof.gresource.xml
+glib_resources_namespace = gbp_sysprof
+include $(top_srcdir)/build/autotools/Makefile.am.gresources
+
+include $(top_srcdir)/plugins/Makefile.plugin
+
+endif
+
+-include $(top_srcdir)/git.mk
diff --git a/plugins/sysprof/configure.ac b/plugins/sysprof/configure.ac
new file mode 100644
index 0000000..657d385
--- /dev/null
+++ b/plugins/sysprof/configure.ac
@@ -0,0 +1,21 @@
+m4_define(sysprof_required_version, [3.20.1])
+
+PKG_CHECK_MODULES(SYSPROF, [sysprof-2 >= sysprof_required_version
+ sysprof-ui-2 >= sysprof_required_version])
+
+# --enable-sysprof-plugin=yes/no
+AC_ARG_ENABLE([sysprof-plugin],
+ [AS_HELP_STRING([--enable-sysprof-plugin=@<:@yes/no@:>@],
+ [Build with support for the Sysprof system profiler.])],
+ [enable_sysprof_plugin=$enableval],
+ [enable_sysprof_plugin=yes])
+
+AS_IF([test x$enable_sysprof_plugin = xyes && test x$have_sysprof_ui = xno],[
+ AC_MSG_ERROR([Failed to locate sysprof-ui dependencies. Try installing Sysprof with GTK support.])
+])
+
+# for if ENABLE_SYSPROF_PLUGIN in Makefile.am
+AM_CONDITIONAL(ENABLE_SYSPROF_PLUGIN, test x$enable_sysprof_plugin != xno)
+
+# Ensure our makefile is generated by autoconf
+AC_CONFIG_FILES([plugins/sysprof/Makefile])
diff --git a/plugins/sysprof/gbp-sysprof-perspective.c b/plugins/sysprof/gbp-sysprof-perspective.c
new file mode 100644
index 0000000..3928954
--- /dev/null
+++ b/plugins/sysprof/gbp-sysprof-perspective.c
@@ -0,0 +1,184 @@
+/* gbp-sysprof-perspective.c
+ *
+ * Copyright (C) 2016 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/>.
+ */
+
+#define G_LOG_DOMAIN "gbp-sysprof-perspective"
+
+#include <glib/gi18n.h>
+#include <sysprof.h>
+#include <sysprof-ui.h>
+
+#include "gbp-sysprof-perspective.h"
+
+struct _GbpSysprofPerspective
+{
+ GtkBin parent_instance;
+
+ SpCallgraphView *callgraph_view;
+};
+
+enum {
+ PROP_0,
+ N_PROPS
+};
+
+static void perspective_iface_init (IdePerspectiveInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (GbpSysprofPerspective, gbp_sysprof_perspective, GTK_TYPE_BIN, 0,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_PERSPECTIVE, perspective_iface_init))
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+gbp_sysprof_perspective_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (gbp_sysprof_perspective_parent_class)->finalize (object);
+}
+
+static void
+gbp_sysprof_perspective_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpSysprofPerspective *self = GBP_SYSPROF_PERSPECTIVE (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_sysprof_perspective_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpSysprofPerspective *self = GBP_SYSPROF_PERSPECTIVE (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_sysprof_perspective_class_init (GbpSysprofPerspectiveClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = gbp_sysprof_perspective_finalize;
+ object_class->get_property = gbp_sysprof_perspective_get_property;
+ object_class->set_property = gbp_sysprof_perspective_set_property;
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/builder/plugins/sysprof-plugin/gbp-sysprof-perspective.ui");
+ gtk_widget_class_bind_template_child (widget_class, GbpSysprofPerspective, callgraph_view);
+
+ g_type_ensure (SP_TYPE_CALLGRAPH_VIEW);
+}
+
+static void
+gbp_sysprof_perspective_init (GbpSysprofPerspective *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static gchar *
+gbp_sysprof_perspective_get_icon_name (IdePerspective *perspective)
+{
+ return g_strdup ("utilities-system-monitor-symbolic");
+}
+
+static gchar *
+gbp_sysprof_perspective_get_title (IdePerspective *perspective)
+{
+ return g_strdup (_("Profiler"));
+}
+
+static gchar *
+gbp_sysprof_perspective_get_id (IdePerspective *perspective)
+{
+ return g_strdup ("profiler");
+}
+
+static gint
+gbp_sysprof_perspective_get_priority (IdePerspective *perspective)
+{
+ return 70000;
+}
+
+static gchar *
+gbp_sysprof_perspective_get_accelerator (IdePerspective *perspective)
+{
+ return g_strdup ("<Alt>2");
+}
+
+static void
+perspective_iface_init (IdePerspectiveInterface *iface)
+{
+ iface->get_icon_name = gbp_sysprof_perspective_get_icon_name;
+ iface->get_title = gbp_sysprof_perspective_get_title;
+ iface->get_id = gbp_sysprof_perspective_get_id;
+ iface->get_priority = gbp_sysprof_perspective_get_priority;
+ iface->get_accelerator = gbp_sysprof_perspective_get_accelerator;
+}
+
+static void
+generate_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ SpCallgraphProfile *profile = (SpCallgraphProfile *)object;
+ g_autoptr(GbpSysprofPerspective) self = user_data;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (SP_IS_CALLGRAPH_PROFILE (profile));
+ g_assert (GBP_IS_SYSPROF_PERSPECTIVE (self));
+
+ if (!sp_profile_generate_finish (SP_PROFILE (profile), result, &error))
+ {
+ g_warning ("Failed to generate profile: %s", error->message);
+ return;
+ }
+
+ sp_callgraph_view_set_profile (self->callgraph_view, profile);
+}
+
+void
+gbp_sysprof_perspective_set_reader (GbpSysprofPerspective *self,
+ SpCaptureReader *reader)
+{
+ g_autoptr(SpProfile) profile = NULL;
+
+ g_assert (GBP_IS_SYSPROF_PERSPECTIVE (self));
+
+ if (reader == NULL)
+ {
+ sp_callgraph_view_set_profile (self->callgraph_view, NULL);
+ return;
+ }
+
+ profile = sp_callgraph_profile_new ();
+
+ sp_profile_set_reader (profile, reader);
+
+ sp_profile_generate (profile, NULL, generate_cb, g_object_ref (self));
+}
diff --git a/plugins/sysprof/gbp-sysprof-perspective.h b/plugins/sysprof/gbp-sysprof-perspective.h
new file mode 100644
index 0000000..54355c4
--- /dev/null
+++ b/plugins/sysprof/gbp-sysprof-perspective.h
@@ -0,0 +1,36 @@
+/* gbp-sysprof-perspective.h
+ *
+ * Copyright (C) 2016 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/>.
+ */
+
+#ifndef GBP_SYSPROF_PERSPECTIVE_H
+#define GBP_SYSPROF_PERSPECTIVE_H
+
+#include <ide.h>
+#include <sysprof.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_SYSPROF_PERSPECTIVE (gbp_sysprof_perspective_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpSysprofPerspective, gbp_sysprof_perspective, GBP, SYSPROF_PERSPECTIVE, GtkBin)
+
+void gbp_sysprof_perspective_set_reader (GbpSysprofPerspective *self,
+ SpCaptureReader *reader);
+
+G_END_DECLS
+
+#endif /* GBP_SYSPROF_PERSPECTIVE_H */
diff --git a/plugins/sysprof/gbp-sysprof-perspective.ui b/plugins/sysprof/gbp-sysprof-perspective.ui
new file mode 100644
index 0000000..253f51b
--- /dev/null
+++ b/plugins/sysprof/gbp-sysprof-perspective.ui
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GbpSysprofPerspective" parent="GtkBin">
+ <child>
+ <object class="GtkStack">
+ <property name="visible">true</property>
+ <child>
+ <object class="SpCallgraphView" id="callgraph_view">
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/plugins/sysprof/gbp-sysprof-plugin.c b/plugins/sysprof/gbp-sysprof-plugin.c
new file mode 100644
index 0000000..987ff07
--- /dev/null
+++ b/plugins/sysprof/gbp-sysprof-plugin.c
@@ -0,0 +1,30 @@
+/* gbp-sysprof-plugin.c
+ *
+ * Copyright (C) 2016 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/>.
+ */
+
+#include <libpeas/peas.h>
+#include <ide.h>
+
+#include "gbp-sysprof-workbench-addin.h"
+
+void
+peas_register_types (PeasObjectModule *module)
+{
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_WORKBENCH_ADDIN,
+ GBP_TYPE_SYSPROF_WORKBENCH_ADDIN);
+}
diff --git a/plugins/sysprof/gbp-sysprof-workbench-addin.c b/plugins/sysprof/gbp-sysprof-workbench-addin.c
new file mode 100644
index 0000000..a98518d
--- /dev/null
+++ b/plugins/sysprof/gbp-sysprof-workbench-addin.c
@@ -0,0 +1,401 @@
+/* gbp-sysprof-workbench-addin.c
+ *
+ * Copyright (C) 2016 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/>.
+ */
+
+#include <glib/gi18n.h>
+#include <sysprof.h>
+
+#include "gbp-sysprof-perspective.h"
+#include "gbp-sysprof-workbench-addin.h"
+
+struct _GbpSysprofWorkbenchAddin
+{
+ GObject parent_instance;
+
+ GSimpleActionGroup *actions;
+ SpProfiler *profiler;
+
+ GbpSysprofPerspective *perspective;
+ IdeWorkbench *workbench;
+};
+
+static void workbench_addin_iface_init (IdeWorkbenchAddinInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (GbpSysprofWorkbenchAddin, gbp_sysprof_workbench_addin, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKBENCH_ADDIN, workbench_addin_iface_init))
+
+static void
+set_action_state (GbpSysprofWorkbenchAddin *self,
+ const gchar *action_name,
+ GVariant *state,
+ gboolean enabled)
+{
+ GAction *action;
+
+ g_assert (GBP_IS_SYSPROF_WORKBENCH_ADDIN (self));
+ g_assert (action_name != NULL);
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (self->actions), action_name);
+ g_simple_action_set_state (G_SIMPLE_ACTION (action), state);
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enabled);
+}
+
+static void
+profiler_stopped (GbpSysprofWorkbenchAddin *self,
+ SpProfiler *profiler)
+{
+ IDE_ENTRY;
+
+ g_return_if_fail (GBP_IS_SYSPROF_WORKBENCH_ADDIN (self));
+ g_return_if_fail (SP_IS_PROFILER (profiler));
+
+ if (self->profiler == profiler)
+ {
+ set_action_state (self, "start-profiler", g_variant_new_boolean (FALSE), TRUE);
+ IDE_EXIT;
+ }
+
+ IDE_EXIT;
+}
+
+static void
+profiler_run_handler (IdeRunManager *run_manager,
+ IdeRunner *runner,
+ gpointer user_data)
+{
+ GbpSysprofWorkbenchAddin *self = user_data;
+
+ g_assert (GBP_IS_SYSPROF_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_RUNNER (runner));
+ g_assert (IDE_IS_RUN_MANAGER (run_manager));
+
+ g_printerr ("This is where we would connect to the pid spawn and start profiling.\n");
+}
+
+
+static void
+gbp_sysprof_workbench_addin_start (GbpSysprofWorkbenchAddin *self)
+{
+ IdeContext *context;
+ IdeRunManager *run_manager;
+
+ IDE_ENTRY;
+
+ g_return_if_fail (GBP_IS_SYSPROF_WORKBENCH_ADDIN (self));
+ g_return_if_fail (IDE_IS_PERSPECTIVE (self->perspective));
+ g_return_if_fail (IDE_IS_WORKBENCH (self->workbench));
+
+ if (self->profiler != NULL)
+ {
+ if (sp_profiler_get_is_running (self->profiler))
+ {
+ g_warning ("Profiler is already running, cannot start profiler.");
+ IDE_EXIT;
+ }
+ }
+
+ context = ide_workbench_get_context (self->workbench);
+
+ run_manager = ide_context_get_run_manager (context);
+ ide_run_manager_set_handler (run_manager, "profiler");
+
+ ide_workbench_set_visible_perspective (self->workbench, IDE_PERSPECTIVE (self->perspective));
+
+ set_action_state (self, "start-profiler", g_variant_new_boolean (TRUE), FALSE);
+
+ g_clear_object (&self->profiler);
+ self->profiler = sp_local_profiler_new ();
+
+ g_signal_connect_object (self->profiler,
+ "stopped",
+ G_CALLBACK (profiler_stopped),
+ self,
+ G_CONNECT_SWAPPED);
+
+ ide_run_manager_run_async (run_manager, NULL, NULL, NULL, NULL);
+
+ sp_profiler_start (self->profiler);
+
+ IDE_EXIT;
+}
+
+static void
+start_profiler_action (GSimpleAction *action,
+ GVariant *variant,
+ gpointer user_data)
+{
+ GbpSysprofWorkbenchAddin *self = user_data;
+
+ g_assert (GBP_IS_SYSPROF_WORKBENCH_ADDIN (self));
+
+ gbp_sysprof_workbench_addin_start (self);
+}
+
+static void
+gbp_sysprof_workbench_addin_open_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GbpSysprofWorkbenchAddin *self = (GbpSysprofWorkbenchAddin *)object;
+ g_autoptr(SpCaptureReader) reader = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (GBP_IS_SYSPROF_WORKBENCH_ADDIN (self));
+ g_assert (G_IS_TASK (result));
+
+ reader = g_task_propagate_pointer (G_TASK (result), &error);
+
+ g_assert (reader || error != NULL);
+
+ if (reader == NULL)
+ {
+ g_message ("%s", error->message);
+ return;
+ }
+
+ gbp_sysprof_perspective_set_reader (self->perspective, reader);
+}
+
+static void
+gbp_sysprof_workbench_addin_open_worker (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GbpSysprofWorkbenchAddin *self = source_object;
+ g_autofree gchar *path = NULL;
+ SpCaptureReader *reader;
+ GFile *file = task_data;
+ GError *error = NULL;
+
+ g_assert (G_IS_TASK (task));
+ g_assert (GBP_IS_SYSPROF_WORKBENCH_ADDIN (self));
+ g_assert (G_IS_FILE (file));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ path = g_file_get_path (file);
+
+ if (NULL == (reader = sp_capture_reader_new (path, &error)))
+ {
+ g_assert (error != NULL);
+ g_task_return_error (task, error);
+ return;
+ }
+
+ g_task_return_pointer (task, reader, (GDestroyNotify)sp_capture_reader_unref);
+}
+
+static void
+gbp_sysprof_workbench_addin_open (GbpSysprofWorkbenchAddin *self,
+ GFile *file)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_assert (GBP_IS_SYSPROF_WORKBENCH_ADDIN (self));
+ g_assert (G_IS_FILE (file));
+
+ if (!g_file_is_native (file))
+ {
+ g_warning ("Can only open local sysprof capture files.");
+ return;
+ }
+
+ task = g_task_new (self, NULL, gbp_sysprof_workbench_addin_open_cb, NULL);
+ g_task_set_task_data (task, g_object_ref (file), g_object_unref);
+ g_task_run_in_thread (task, gbp_sysprof_workbench_addin_open_worker);
+}
+
+static void
+open_profile_action (GSimpleAction *action,
+ GVariant *variant,
+ gpointer user_data)
+{
+ GbpSysprofWorkbenchAddin *self = user_data;
+ GtkFileChooserNative *native;
+ GtkFileFilter *filter;
+ gint ret;
+
+ g_assert (GBP_IS_SYSPROF_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_WORKBENCH (self->workbench));
+ g_assert (GBP_IS_SYSPROF_PERSPECTIVE (self->perspective));
+
+ ide_workbench_set_visible_perspective (self->workbench, IDE_PERSPECTIVE (self->perspective));
+
+ native = gtk_file_chooser_native_new (_("Open Profile"),
+ GTK_WINDOW (self->workbench),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ _("Open"),
+ _("Cancel"));
+
+ /* Add our filter for sysprof capture files. */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_set_name (filter, _("Sysprof Capture (*.syscap)"));
+ gtk_file_filter_add_pattern (filter, "*.syscap");
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (native), filter);
+
+ /* And all files now */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_set_name (filter, _("All Files"));
+ gtk_file_filter_add_pattern (filter, "*");
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (native), filter);
+
+ /* Unlike gtk_dialog_run(), this will handle processing
+ * various I/O events and so should be safe to use.
+ */
+ ret = gtk_native_dialog_run (GTK_NATIVE_DIALOG (native));
+
+ if (ret == GTK_RESPONSE_ACCEPT)
+ {
+ g_autoptr(GFile) file = NULL;
+
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (native));
+ if (G_IS_FILE (file))
+ gbp_sysprof_workbench_addin_open (self, file);
+ }
+
+ gtk_native_dialog_hide (GTK_NATIVE_DIALOG (native));
+ gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (native));
+}
+
+static void
+gbp_sysprof_workbench_addin_finalize (GObject *object)
+{
+ GbpSysprofWorkbenchAddin *self = (GbpSysprofWorkbenchAddin *)object;
+
+ g_clear_object (&self->actions);
+
+ G_OBJECT_CLASS (gbp_sysprof_workbench_addin_parent_class)->finalize (object);
+}
+
+static void
+gbp_sysprof_workbench_addin_class_init (GbpSysprofWorkbenchAddinClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gbp_sysprof_workbench_addin_finalize;
+}
+
+static void
+gbp_sysprof_workbench_addin_init (GbpSysprofWorkbenchAddin *self)
+{
+ static const GActionEntry entries[] = {
+ { "start-profiler", start_profiler_action, NULL, "false" },
+ { "open-profile", open_profile_action },
+ };
+
+ self->actions = g_simple_action_group_new ();
+
+ g_action_map_add_action_entries (G_ACTION_MAP (self->actions),
+ entries,
+ G_N_ELEMENTS (entries),
+ self);
+}
+
+static void
+gbp_sysprof_workbench_addin_load (IdeWorkbenchAddin *addin,
+ IdeWorkbench *workbench)
+{
+ GbpSysprofWorkbenchAddin *self = (GbpSysprofWorkbenchAddin *)addin;
+ IdeWorkbenchHeaderBar *headerbar;
+ IdeRunManager *run_manager;
+ IdeContext *context;
+ GtkWidget *button;
+
+ g_assert (GBP_IS_SYSPROF_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_WORKBENCH (workbench));
+
+ self->workbench = workbench;
+
+ context = ide_workbench_get_context (workbench);
+
+ /*
+ * Register our custom run handler to activate the profiler.
+ */
+ run_manager = ide_context_get_run_manager (context);
+ ide_run_manager_add_handler (run_manager,
+ "profiler",
+ _("Profile"),
+ "utilities-system-monitor-symbolic",
+ "<Ctrl>F8",
+ profiler_run_handler,
+ self,
+ NULL);
+
+ /*
+ * Add the perspcetive to the workbench.
+ */
+ self->perspective = g_object_new (GBP_TYPE_SYSPROF_PERSPECTIVE,
+ "visible", TRUE,
+ NULL);
+ ide_workbench_add_perspective (workbench, IDE_PERSPECTIVE (self->perspective));
+
+
+ /*
+ * Add our actions to the workbench so they can be activated via the
+ * headerbar or the perspective.
+ */
+ gtk_widget_insert_action_group (GTK_WIDGET (workbench),
+ "profiler",
+ G_ACTION_GROUP (self->actions));
+
+
+ /*
+ * Add our Profile button next to "Run".
+ */
+ headerbar = ide_workbench_get_headerbar (workbench);
+ button = g_object_new (GTK_TYPE_TOGGLE_BUTTON,
+ "action-name", "profiler.start-profiler",
+ "focus-on-click", FALSE,
+ "child", g_object_new (GTK_TYPE_IMAGE,
+ "icon-name", "media-record-symbolic",
+ "visible", TRUE,
+ NULL),
+ "tooltip-text", _("Profile project"),
+ "visible", TRUE,
+ NULL);
+ ide_widget_add_style_class (button, "image-button");
+ ide_workbench_header_bar_insert_right (headerbar, button, GTK_PACK_START, 10);
+}
+
+static void
+gbp_sysprof_workbench_addin_unload (IdeWorkbenchAddin *addin,
+ IdeWorkbench *workbench)
+{
+ GbpSysprofWorkbenchAddin *self = (GbpSysprofWorkbenchAddin *)addin;
+ IdeRunManager *run_manager;
+ IdeContext *context;
+
+ g_assert (GBP_IS_SYSPROF_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_WORKBENCH (workbench));
+
+ context = ide_workbench_get_context (workbench);
+
+ run_manager = ide_context_get_run_manager (context);
+ ide_run_manager_remove_handler (run_manager, "profiler");
+
+ ide_workbench_remove_perspective (workbench, IDE_PERSPECTIVE (self->perspective));
+
+ self->perspective = NULL;
+ self->workbench = NULL;
+}
+
+static void
+workbench_addin_iface_init (IdeWorkbenchAddinInterface *iface)
+{
+ iface->load = gbp_sysprof_workbench_addin_load;
+ iface->unload = gbp_sysprof_workbench_addin_unload;
+}
diff --git a/plugins/sysprof/gbp-sysprof-workbench-addin.h b/plugins/sysprof/gbp-sysprof-workbench-addin.h
new file mode 100644
index 0000000..3df3d93
--- /dev/null
+++ b/plugins/sysprof/gbp-sysprof-workbench-addin.h
@@ -0,0 +1,33 @@
+/* gbp-sysprof-workbench-addin.h
+ *
+ * Copyright (C) 2016 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/>.
+ */
+
+#ifndef GBP_SYSPROF_WORKBENCH_ADDIN_H
+#define GBP_SYSPROF_WORKBENCH_ADDIN_H
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_SYSPROF_WORKBENCH_ADDIN (gbp_sysprof_workbench_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpSysprofWorkbenchAddin, gbp_sysprof_workbench_addin, GBP, SYSPROF_WORKBENCH_ADDIN,
GObject)
+
+G_END_DECLS
+
+#endif /* GBP_SYSPROF_WORKBENCH_ADDIN_H */
+
diff --git a/plugins/sysprof/gtk/menus.ui b/plugins/sysprof/gtk/menus.ui
new file mode 100644
index 0000000..6004cef
--- /dev/null
+++ b/plugins/sysprof/gtk/menus.ui
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<interface>
+ <menu id="gear-menu">
+ <section id="gear-menu-open-section">
+ <item>
+ <attribute name="label" translatable="yes">Open Profile…</attribute>
+ <attribute name="action">profiler.open-profile</attribute>
+ </item>
+ </section>
+ </menu>
+</interface>
diff --git a/plugins/sysprof/sysprof.gresource.xml b/plugins/sysprof/sysprof.gresource.xml
new file mode 100644
index 0000000..2695fd8
--- /dev/null
+++ b/plugins/sysprof/sysprof.gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/builder/plugins/sysprof-plugin">
+ <file>gtk/menus.ui</file>
+ <file>gbp-sysprof-perspective.ui</file>
+ </gresource>
+</gresources>
diff --git a/plugins/sysprof/sysprof.plugin b/plugins/sysprof/sysprof.plugin
new file mode 100644
index 0000000..784959d
--- /dev/null
+++ b/plugins/sysprof/sysprof.plugin
@@ -0,0 +1,7 @@
+[Plugin]
+Module=sysprof-plugin
+Name=Sysprof
+Description=Integration with the Sysprof system profiler
+Authors=Christian Hergert <christian hergert me>
+Copyright=Copyright © 2016 Christian Hergert
+Builtin=true
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]