[gnome-builder/wip/chergert/debugger: 4/5] debugger: stub out debugger API
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/debugger: 4/5] debugger: stub out debugger API
- Date: Fri, 2 Sep 2016 21:05:52 +0000 (UTC)
commit b781886b6aee1f0d86b4ab68b22ff8ff754a7fd1
Author: Christian Hergert <chergert redhat com>
Date: Thu Sep 1 17:51:58 2016 -0700
debugger: stub out debugger API
configure.ac | 2 +
plugins/Makefile.am | 1 +
plugins/debugger/Makefile.am | 46 ++++
plugins/debugger/OVERVIEW.md | 63 +++++
plugins/debugger/configure.ac | 12 +
plugins/debugger/debugger.gresource.xml | 7 +
plugins/debugger/debugger.plugin | 9 +
plugins/debugger/gbp-debugger-breakpoints.c | 293 ++++++++++++++++++++
plugins/debugger/gbp-debugger-breakpoints.h | 49 ++++
plugins/debugger/gbp-debugger-editor-view-addin.c | 161 +++++++++++
plugins/debugger/gbp-debugger-editor-view-addin.h | 32 +++
plugins/debugger/gbp-debugger-gutter-renderer.c | 281 ++++++++++++++++++++
plugins/debugger/gbp-debugger-gutter-renderer.h | 35 +++
plugins/debugger/gbp-debugger-perspective.c | 126 +++++++++
plugins/debugger/gbp-debugger-perspective.h | 32 +++
plugins/debugger/gbp-debugger-perspective.ui | 5 +
plugins/debugger/gbp-debugger-plugin.c | 36 +++
plugins/debugger/gbp-debugger-service.c | 153 +++++++++++
plugins/debugger/gbp-debugger-service.h | 37 +++
plugins/debugger/gbp-debugger-workbench-addin.c | 295 +++++++++++++++++++++
plugins/debugger/gbp-debugger-workbench-addin.h | 32 +++
plugins/debugger/gtk/menus.ui | 3 +
po/POTFILES.in | 4 +
23 files changed, 1714 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index d862d57..c539a5a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -287,6 +287,7 @@ m4_include([plugins/comment-code/configure.ac])
m4_include([plugins/contributing/configure.ac])
m4_include([plugins/create-project/configure.ac])
m4_include([plugins/ctags/configure.ac])
+m4_include([plugins/debugger/configure.ac])
m4_include([plugins/devhelp/configure.ac])
m4_include([plugins/file-search/configure.ac])
m4_include([plugins/flatpak/configure.ac])
@@ -576,6 +577,7 @@ echo " Command Bar .......................... : ${enable_command_bar_plugin}"
echo " Comment Code.......................... : ${enable_comment_code_plugin}"
echo " Contribute ........................... : ${enable_contributing_plugin}"
echo " Ctags ................................ : ${enable_ctags_plugin}"
+echo " Debugger ............................. : ${enable_debugger_plugin}"
echo " Devhelp .............................. : ${enable_devhelp_plugin}"
echo " Editorconfig ......................... : ${enable_editorconfig}"
echo " Fpaste.org ........................... : ${enable_fpaste_plugin}"
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 21ed04b..2a80e6b 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -10,6 +10,7 @@ SUBDIRS = \
contributing \
create-project \
ctags \
+ debugger \
devhelp \
file-search \
flatpak \
diff --git a/plugins/debugger/Makefile.am b/plugins/debugger/Makefile.am
new file mode 100644
index 0000000..9ccf523
--- /dev/null
+++ b/plugins/debugger/Makefile.am
@@ -0,0 +1,46 @@
+if ENABLE_SYSPROF_PLUGIN
+
+DISTCLEANFILES =
+BUILT_SOURCES =
+CLEANFILES =
+EXTRA_DIST = $(plugin_DATA)
+
+plugindir = $(libdir)/gnome-builder/plugins
+plugin_LTLIBRARIES = libdebugger-plugin.la
+dist_plugin_DATA = debugger.plugin
+
+libdebugger_plugin_la_SOURCES = \
+ gbp-debugger-breakpoints.c \
+ gbp-debugger-breakpoints.h \
+ gbp-debugger-editor-view-addin.c \
+ gbp-debugger-editor-view-addin.h \
+ gbp-debugger-gutter-renderer.c \
+ gbp-debugger-gutter-renderer.h \
+ gbp-debugger-perspective.c \
+ gbp-debugger-perspective.h \
+ gbp-debugger-plugin.c \
+ gbp-debugger-service.c \
+ gbp-debugger-service.h \
+ gbp-debugger-workbench-addin.c \
+ gbp-debugger-workbench-addin.h \
+ $(NULL)
+
+nodist_libdebugger_plugin_la_SOURCES = \
+ gbp-debugger-resources.c \
+ gbp-debugger-resources.h
+
+libdebugger_plugin_la_CFLAGS = $(PLUGIN_CFLAGS) $(SYSPROF_CFLAGS)
+libdebugger_plugin_la_LIBADD = $(PLUGIN_LIBS) $(SYSPROF_LIBS)
+libdebugger_plugin_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(SYSPROF_LDFLAGS)
+
+glib_resources_c = gbp-debugger-resources.c
+glib_resources_h = gbp-debugger-resources.h
+glib_resources_xml = debugger.gresource.xml
+glib_resources_namespace = gbp_debugger
+include $(top_srcdir)/build/autotools/Makefile.am.gresources
+
+include $(top_srcdir)/plugins/Makefile.plugin
+
+endif
+
+-include $(top_srcdir)/git.mk
diff --git a/plugins/debugger/OVERVIEW.md b/plugins/debugger/OVERVIEW.md
new file mode 100644
index 0000000..9b36250
--- /dev/null
+++ b/plugins/debugger/OVERVIEW.md
@@ -0,0 +1,63 @@
+# Debugger Overview
+
+The goal of this plugin is to reuse as much of the Nemiver codebase as we can
+to implement a debugger in Builder. Rather than abstract debugger
+implementations in Builder, we will rely on Nemiver's debugger abstraction.
+That means to add a new debugger to Builder, you need to add a new debugger
+module to Nemiver. This is completely a reasonable request as it allows for
+Nemiver to be more generally useful as a standalone debugger for those that
+prefer standalone tools.
+
+## Debugger Service
+
+This `IService` implementation bridges the Nemiver IDebugger implementation
+with Builder. It provides the API calls necessary to make progress on the
+debugger as well register breakpoints, watchpoints, countpoints, etc. These API
+calls are used by the `EditorViewAddin` (and associated GutterRenderer) to
+toggle breakpoints on a given line. Additionally, the service provides
+information on the current position of the debug cycle, so that we can show an
+arrow for the current position in the gutter.
+
+To simplify interaction with UI elements, the Debugger service also exposes
+a `GActionGroup` with actions that can be activated from Gtk widgetry. The
+enabled-state of the actions are automatically updated based on the bridged
+`IDebugger`s ability to perform the action.
+
+## Debugger Perspective
+
+The debugger perspective imports the widgetry from Nemiver into a layout
+suitable for debugging in Builder. It includes a location for read-only
+editors (of the file for the current debugged line) as well as the panels
+such as memory, threads, breakpoints, etc.
+
+## Debugger EditorViewAddin
+
+This addin hooks into the `IdeEditorView` to add the debugger gutter to sources
+that can have breakpoints added to them. Such an example would be C and C++
+files. As additional debugger backends are added, this will need to be
+extended to enable other language ids.
+
+## Debugger GutterRenderer
+
+This is a `GtkSourceGutterRenderer` that allows toggling breakpoints (as well
+as countpoints) for a given line in a source file.
+
+## Debugger WorkbenchAddin
+
+The `IdeWorkbenchAddin` is used to add the perspective to the workbench. Also,
+it adds the Debugger service to the toplevel as an action group so that buttons
+can be attached to the actions. The debugger controls are added to the UI here
+as well, and this class manages their visibility (based on the debugger service
+actively debugging).
+
+This also registers the `IdeRunHandler` for the debugger. When activated, it
+requests the debugger service to start the debugger using the `IdeRunner` for
+the run operation.
+
+## Debugger Breakpoints
+
+Because GtkSourceGutterRenderers do not have their contents cached, we need a
+*very* fast way to determine if a breakpoint is on a given source line. The
+`GbpDebuggerBreakpoints` provides that feature by caching what lines have
+breakpoints. This allows the gutter renderer to quickly check for every line
+rendered as well as invalidating the window when breakpoints change.
diff --git a/plugins/debugger/configure.ac b/plugins/debugger/configure.ac
new file mode 100644
index 0000000..fcc26cb
--- /dev/null
+++ b/plugins/debugger/configure.ac
@@ -0,0 +1,12 @@
+# --enable-debugger-plugin=yes/no
+AC_ARG_ENABLE([debugger-plugin],
+ [AS_HELP_STRING([--enable-debugger-plugin=@<:@yes/no@:>@],
+ [Build with support for the integrated debugger.])],
+ [enable_debugger_plugin=$enableval],
+ [enable_debugger_plugin=yes])
+
+# for if ENABLE_DEBUGGER_PLUGIN in Makefile.am
+AM_CONDITIONAL(ENABLE_DEBUGGER_PLUGIN, [test x$enable_debugger_plugin = xyes])
+
+# Ensure our makefile is generated by autoconf
+AC_CONFIG_FILES([plugins/debugger/Makefile])
diff --git a/plugins/debugger/debugger.gresource.xml b/plugins/debugger/debugger.gresource.xml
new file mode 100644
index 0000000..9787f0c
--- /dev/null
+++ b/plugins/debugger/debugger.gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/builder/plugins/debugger-plugin">
+ <file>gtk/menus.ui</file>
+ <file>gbp-debugger-perspective.ui</file>
+ </gresource>
+</gresources>
diff --git a/plugins/debugger/debugger.plugin b/plugins/debugger/debugger.plugin
new file mode 100644
index 0000000..2b7bac4
--- /dev/null
+++ b/plugins/debugger/debugger.plugin
@@ -0,0 +1,9 @@
+[Plugin]
+Module=debugger-plugin
+Name=Debugger
+Description=Integrates the Nemiver debugger
+Authors=Christian Hergert <christian hergert me>
+Copyright=Copyright © 2016 Christian Hergert
+Depends=editor
+Builtin=true
+Hidden=true
diff --git a/plugins/debugger/gbp-debugger-breakpoints.c b/plugins/debugger/gbp-debugger-breakpoints.c
new file mode 100644
index 0000000..75bf47f
--- /dev/null
+++ b/plugins/debugger/gbp-debugger-breakpoints.c
@@ -0,0 +1,293 @@
+/* gbp-debugger-breakpoints.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-debugger-breakpoints"
+
+#include "gbp-debugger-breakpoints.h"
+#include "gbp-debugger-service.h"
+
+/**
+ * SECTION:gbp-debugger-breakpoints
+ * @title: GbpDebuggerBreakpoints
+ *
+ * This object is used to track breakpoints within a certain file.
+ * This is necessary so that we can draw the gutter for breakpoints
+ * very fast by reducing our breakpoint lookup cost to simply a line
+ * number in a hashtable.
+ *
+ * To do this, the #GbpDebuggerBreakpoints object will track changes
+ * to breakpoints (and watchpoints) in the GbpDebuggerService. If the
+ * breakpoint is part to the current #GbpDebuggerBreakpoints:file, then
+ * it will cache the value. The #GbpDebuggerGutterRenderer is assigned
+ * a #GbpDebuggerBreakpoints which it will use to determine what icon
+ * to render on the gutter.
+ */
+
+struct _GbpDebuggerBreakpoints
+{
+ IdeObject parent_instance;
+ GHashTable *cache;
+ GFile *file;
+};
+
+enum {
+ PROP_0,
+ PROP_FILE,
+ N_PROPS
+};
+
+enum {
+ CHANGED,
+ N_SIGNALS
+};
+
+G_DEFINE_TYPE (GbpDebuggerBreakpoints, gbp_debugger_breakpoints, IDE_TYPE_OBJECT)
+
+static GParamSpec *properties [N_PROPS];
+static guint signals [N_SIGNALS];
+
+static void
+on_breakpoint_added (GbpDebuggerBreakpoints *self,
+ GFile *file,
+ guint line,
+ GbpDebuggerBreakType break_type,
+ GbpDebuggerService *service)
+{
+ GbpDebuggerBreakType type;
+ gpointer key = GUINT_TO_POINTER (line);
+
+ g_assert (GBP_IS_DEBUGGER_BREAKPOINTS (self));
+ g_assert (G_IS_FILE (file));
+
+ if (!g_file_equal (file, self->file))
+ return;
+
+ type = GPOINTER_TO_UINT (g_hash_table_lookup (self->cache, key)) | break_type;
+ g_hash_table_insert (self->cache, key, GUINT_TO_POINTER (type));
+
+ g_signal_emit (self, signals [CHANGED], 0);
+}
+
+static void
+on_breakpoint_removed (GbpDebuggerBreakpoints *self,
+ GFile *file,
+ guint line,
+ GbpDebuggerBreakType break_type,
+ GbpDebuggerService *service)
+{
+ GbpDebuggerBreakType type;
+ gpointer key = GUINT_TO_POINTER (line);
+
+ g_assert (GBP_IS_DEBUGGER_BREAKPOINTS (self));
+ g_assert (G_IS_FILE (file));
+
+ if (!g_file_equal (file, self->file))
+ return;
+
+ type = GPOINTER_TO_UINT (g_hash_table_lookup (self->cache, key));
+ type = type & ~break_type;
+
+ if (type == 0)
+ g_hash_table_remove (self->cache, key);
+ else
+ g_hash_table_replace (self->cache, key, GUINT_TO_POINTER (type));
+
+ g_signal_emit (self, signals [CHANGED], 0);
+}
+
+static void
+gbp_debugger_breakpoints_constructed (GObject *object)
+{
+ GbpDebuggerBreakpoints *self = (GbpDebuggerBreakpoints *)object;
+ GbpDebuggerService *service;
+ IdeContext *context;
+
+ g_assert (GBP_IS_DEBUGGER_BREAKPOINTS (self));
+
+ G_OBJECT_CLASS (gbp_debugger_breakpoints_parent_class)->constructed (object);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ service = ide_context_get_service_typed (context, GBP_TYPE_DEBUGGER_SERVICE);
+
+ g_signal_connect_object (service,
+ "breakpoint-added",
+ G_CALLBACK (on_breakpoint_added),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (service,
+ "breakpoint-removed",
+ G_CALLBACK (on_breakpoint_removed),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+static void
+gbp_debugger_breakpoints_finalize (GObject *object)
+{
+ GbpDebuggerBreakpoints *self = (GbpDebuggerBreakpoints *)object;
+
+ g_clear_object (&self->file);
+ g_clear_pointer (&self->cache, g_hash_table_unref);
+
+ G_OBJECT_CLASS (gbp_debugger_breakpoints_parent_class)->finalize (object);
+}
+
+static void
+gbp_debugger_breakpoints_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpDebuggerBreakpoints *self = GBP_DEBUGGER_BREAKPOINTS (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILE:
+ g_value_set_object (value, self->file);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_debugger_breakpoints_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpDebuggerBreakpoints *self = GBP_DEBUGGER_BREAKPOINTS (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILE:
+ self->file = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_debugger_breakpoints_class_init (GbpDebuggerBreakpointsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = gbp_debugger_breakpoints_constructed;
+ object_class->finalize = gbp_debugger_breakpoints_finalize;
+ object_class->get_property = gbp_debugger_breakpoints_get_property;
+ object_class->set_property = gbp_debugger_breakpoints_set_property;
+
+ properties [PROP_FILE] =
+ g_param_spec_object ("file",
+ "File",
+ "File",
+ G_TYPE_FILE,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ /**
+ * GbpDebuggerBreakpoints::changed:
+ *
+ * This signal is emitted when a breakpoint has changed with in the file
+ * indicated by GbpDebuggerBreakpoints:file.
+ */
+ signals [CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
+}
+
+static void
+gbp_debugger_breakpoints_init (GbpDebuggerBreakpoints *self)
+{
+ self->cache = g_hash_table_new (NULL, NULL);
+}
+
+/**
+ * gbp_debugger_breakpoints_get_file:
+ *
+ * Returns: (transfer none): A #GFile.
+ */
+GFile *
+gbp_debugger_breakpoints_get_file (GbpDebuggerBreakpoints *self)
+{
+ g_return_val_if_fail (GBP_IS_DEBUGGER_BREAKPOINTS (self), NULL);
+
+ return self->file;
+}
+
+void
+gbp_debugger_breakpoints_add (GbpDebuggerBreakpoints *self,
+ guint line,
+ GbpDebuggerBreakType break_type)
+{
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_DEBUGGER_BREAKPOINTS (self));
+ g_assert (line > 0);
+ g_assert (break_type > GBP_DEBUGGER_BREAK_NONE);
+
+ /*
+ * TODO: Propagate request for breakpoint via debugger service.
+ * Instead, for testing, we will just add the breakpoint
+ * locally to our cache. However, a real implementation
+ * should possibly set a pending bit on the entry and the
+ * remove the pending bit once it has been added by the
+ * debugger (since that could involve a round trip over
+ * IPC and we don't want to show a full breakpoint before
+ * its actually available).
+ */
+
+ g_hash_table_insert (self->cache, GUINT_TO_POINTER (line), GUINT_TO_POINTER (break_type));
+ g_signal_emit (self, signals [CHANGED], 0);
+
+ IDE_EXIT;
+}
+
+void
+gbp_debugger_breakpoints_remove (GbpDebuggerBreakpoints *self,
+ guint line)
+{
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_DEBUGGER_BREAKPOINTS (self));
+ g_assert (line > 0);
+
+ /*
+ * TODO: Propagate request to remove breakpoint via debugger service.
+ * For testing, we can just remove the debugger from cache.
+ */
+
+ g_hash_table_remove (self->cache, GUINT_TO_POINTER (line));
+ g_signal_emit (self, signals [CHANGED], 0);
+
+ IDE_EXIT;
+}
+
+GbpDebuggerBreakType
+gbp_debugger_breakpoints_lookup (GbpDebuggerBreakpoints *self,
+ guint line)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (self->cache, GUINT_TO_POINTER (line)));
+}
diff --git a/plugins/debugger/gbp-debugger-breakpoints.h b/plugins/debugger/gbp-debugger-breakpoints.h
new file mode 100644
index 0000000..c5a481a
--- /dev/null
+++ b/plugins/debugger/gbp-debugger-breakpoints.h
@@ -0,0 +1,49 @@
+/* gbp-debugger-breakpoints.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_DEBUGGER_BREAKPOINTS_H
+#define GBP_DEBUGGER_BREAKPOINTS_H
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_DEBUGGER_BREAKPOINTS (gbp_debugger_breakpoints_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpDebuggerBreakpoints, gbp_debugger_breakpoints, GBP, DEBUGGER_BREAKPOINTS, IdeObject)
+
+typedef enum
+{
+ GBP_DEBUGGER_BREAK_NONE = 0,
+ GBP_DEBUGGER_BREAK_BREAKPOINT = 1 << 0,
+ GBP_DEBUGGER_BREAK_COUNTPOINT = 1 << 1,
+ GBP_DEBUGGER_BREAK_WATCHPOINT = 1 << 2,
+} GbpDebuggerBreakType;
+
+GFile *gbp_debugger_breakpoints_get_file (GbpDebuggerBreakpoints *self);
+void gbp_debugger_breakpoints_add (GbpDebuggerBreakpoints *self,
+ guint line,
+ GbpDebuggerBreakType break_type);
+void gbp_debugger_breakpoints_remove (GbpDebuggerBreakpoints *self,
+ guint line);
+GbpDebuggerBreakType gbp_debugger_breakpoints_lookup (GbpDebuggerBreakpoints *self,
+ guint line);
+
+G_END_DECLS
+
+#endif /* GBP_DEBUGGER_BREAKPOINTS_H */
diff --git a/plugins/debugger/gbp-debugger-editor-view-addin.c
b/plugins/debugger/gbp-debugger-editor-view-addin.c
new file mode 100644
index 0000000..0ccb836
--- /dev/null
+++ b/plugins/debugger/gbp-debugger-editor-view-addin.c
@@ -0,0 +1,161 @@
+/* gbp-debugger-editor-view-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/>.
+ */
+
+#define G_LOG_DOMAIN "gbp-debugger-editor-view-addin"
+
+#include "gbp-debugger-breakpoints.h"
+#include "gbp-debugger-editor-view-addin.h"
+#include "gbp-debugger-gutter-renderer.h"
+
+static GHashTable *supported_languages;
+
+struct _GbpDebuggerEditorViewAddin
+{
+ GObject parent_instance;
+ GPtrArray *renderers;
+};
+
+static void
+gbp_debugger_editor_view_addin_load_source_view (IdeEditorViewAddin *addin,
+ IdeSourceView *source_view)
+{
+ GbpDebuggerEditorViewAddin *self = (GbpDebuggerEditorViewAddin *)addin;
+ g_autoptr(GbpDebuggerBreakpoints) breakpoints = NULL;
+ GtkSourceGutterRenderer *renderer;
+ GtkSourceGutter *gutter;
+ IdeContext *context;
+ IdeBuffer *buffer;
+ IdeFile *file;
+ GFile *gfile;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_DEBUGGER_EDITOR_VIEW_ADDIN (addin));
+ g_assert (IDE_IS_SOURCE_VIEW (source_view));
+
+ context = ide_widget_get_context (GTK_WIDGET (source_view));
+ buffer = IDE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view)));
+ file = ide_buffer_get_file (buffer);
+ gfile = ide_file_get_file (file);
+
+ breakpoints = g_object_new (GBP_TYPE_DEBUGGER_BREAKPOINTS,
+ "context", context,
+ "file", gfile,
+ NULL);
+
+ gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (source_view), GTK_TEXT_WINDOW_LEFT);
+ renderer = g_object_new (GBP_TYPE_DEBUGGER_GUTTER_RENDERER,
+ "alignment-mode", GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST,
+ "breakpoints", breakpoints,
+ "size", 16,
+ "visible", TRUE,
+ "xalign", 0.5f,
+ NULL);
+ g_ptr_array_add (self->renderers, g_object_ref (renderer));
+ gtk_source_gutter_insert (gutter, renderer, -1000);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_debugger_editor_view_addin_unload_source_view (IdeEditorViewAddin *addin,
+ IdeSourceView *source_view)
+{
+ GbpDebuggerEditorViewAddin *self = (GbpDebuggerEditorViewAddin *)addin;
+ GtkSourceGutter *gutter;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_DEBUGGER_EDITOR_VIEW_ADDIN (addin));
+ g_assert (IDE_IS_SOURCE_VIEW (source_view));
+
+ gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (source_view), GTK_TEXT_WINDOW_LEFT);
+
+ for (guint i = self->renderers->len; i > 0; i--)
+ {
+ GtkSourceGutterRenderer *renderer = g_ptr_array_index (self->renderers, i - 1);
+
+ if ((gpointer)source_view == (gpointer)gtk_source_gutter_renderer_get_view (renderer))
+ {
+ gtk_source_gutter_remove (gutter, renderer);
+ g_ptr_array_remove_index (self->renderers, i - 1);
+ }
+ }
+
+ IDE_EXIT;
+}
+
+static void
+gbp_debugger_editor_view_addin_language_changed (IdeEditorViewAddin *addin,
+ const gchar *lang_id)
+{
+ GbpDebuggerEditorViewAddin *self = (GbpDebuggerEditorViewAddin *)addin;
+ gboolean visible = FALSE;
+
+ g_assert (GBP_IS_DEBUGGER_EDITOR_VIEW_ADDIN (self));
+
+ visible = lang_id && g_hash_table_contains (supported_languages, lang_id);
+
+ for (guint i = 0; i < self->renderers->len; i++)
+ {
+ GtkSourceGutterRenderer *renderer = g_ptr_array_index (self->renderers, i);
+
+ gtk_source_gutter_renderer_set_visible (renderer, visible);
+ }
+}
+
+static void
+editor_view_addin_iface_init (IdeEditorViewAddinInterface *iface)
+{
+ iface->load_source_view = gbp_debugger_editor_view_addin_load_source_view;
+ iface->unload_source_view = gbp_debugger_editor_view_addin_unload_source_view;
+ iface->language_changed = gbp_debugger_editor_view_addin_language_changed;
+}
+
+G_DEFINE_TYPE_EXTENDED (GbpDebuggerEditorViewAddin, gbp_debugger_editor_view_addin, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_EDITOR_VIEW_ADDIN, editor_view_addin_iface_init))
+
+static void
+gbp_debugger_editor_view_addin_finalize (GObject *object)
+{
+ GbpDebuggerEditorViewAddin *self = (GbpDebuggerEditorViewAddin *)object;
+
+ g_clear_pointer (&self->renderers, g_ptr_array_unref);
+
+ G_OBJECT_CLASS (gbp_debugger_editor_view_addin_parent_class)->finalize (object);
+}
+
+static void
+gbp_debugger_editor_view_addin_class_init (GbpDebuggerEditorViewAddinClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gbp_debugger_editor_view_addin_finalize;
+
+ supported_languages = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (supported_languages, (gchar *)"c", NULL);
+ g_hash_table_insert (supported_languages, (gchar *)"chdr", NULL);
+ g_hash_table_insert (supported_languages, (gchar *)"cpp", NULL);
+ g_hash_table_insert (supported_languages, (gchar *)"cpphdr", NULL);
+}
+
+static void
+gbp_debugger_editor_view_addin_init (GbpDebuggerEditorViewAddin *self)
+{
+ self->renderers = g_ptr_array_new_with_free_func (g_object_unref);
+}
diff --git a/plugins/debugger/gbp-debugger-editor-view-addin.h
b/plugins/debugger/gbp-debugger-editor-view-addin.h
new file mode 100644
index 0000000..8626f88
--- /dev/null
+++ b/plugins/debugger/gbp-debugger-editor-view-addin.h
@@ -0,0 +1,32 @@
+/* gbp-debugger-editor-view-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_DEBUGGER_EDITOR_VIEW_ADDIN_H
+#define GBP_DEBUGGER_EDITOR_VIEW_ADDIN_H
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_DEBUGGER_EDITOR_VIEW_ADDIN (gbp_debugger_editor_view_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpDebuggerEditorViewAddin, gbp_debugger_editor_view_addin, GBP,
DEBUGGER_EDITOR_VIEW_ADDIN, GObject)
+
+G_END_DECLS
+
+#endif /* GBP_DEBUGGER_EDITOR_VIEW_ADDIN_H */
diff --git a/plugins/debugger/gbp-debugger-gutter-renderer.c b/plugins/debugger/gbp-debugger-gutter-renderer.c
new file mode 100644
index 0000000..855d22d
--- /dev/null
+++ b/plugins/debugger/gbp-debugger-gutter-renderer.c
@@ -0,0 +1,281 @@
+/* gbp-debugger-gutter-renderer.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-debugger-gutter-renderer"
+
+#include <glib/gi18n.h>
+
+#include "gbp-debugger-gutter-renderer.h"
+#include "gbp-debugger-breakpoints.h"
+#include "gbp-debugger-service.h"
+
+struct _GbpDebuggerGutterRenderer
+{
+ GtkSourceGutterRendererPixbuf parent_instance;
+ GbpDebuggerBreakpoints *breakpoints;
+ gulong breakpoints_changed_handler;
+};
+
+G_DEFINE_TYPE (GbpDebuggerGutterRenderer, gbp_debugger_gutter_renderer,
GTK_SOURCE_TYPE_GUTTER_RENDERER_PIXBUF)
+
+enum {
+ PROP_0,
+ PROP_BREAKPOINTS,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+gbp_debugger_gutter_renderer_activate (GbpDebuggerGutterRenderer *self,
+ const GtkTextIter *iter,
+ GdkRectangle *area,
+ GdkEvent *event)
+{
+ GbpDebuggerBreakType break_type;
+ guint line;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_DEBUGGER_GUTTER_RENDERER (self));
+ g_assert (iter != NULL);
+ g_assert (area != NULL);
+ g_assert (event != NULL);
+
+ line = gtk_text_iter_get_line (iter) + 1;
+
+ IDE_TRACE_MSG ("Toggle breakpoint on line %u", line);
+
+ break_type = gbp_debugger_breakpoints_lookup (self->breakpoints, line);
+
+ switch (break_type)
+ {
+ case GBP_DEBUGGER_BREAK_NONE:
+ gbp_debugger_breakpoints_add (self->breakpoints, line, GBP_DEBUGGER_BREAK_BREAKPOINT);
+ break;
+
+ case GBP_DEBUGGER_BREAK_BREAKPOINT:
+ case GBP_DEBUGGER_BREAK_COUNTPOINT:
+ case GBP_DEBUGGER_BREAK_WATCHPOINT:
+ gbp_debugger_breakpoints_remove (self->breakpoints, line);
+ break;
+
+ default:
+ break;
+ }
+
+ IDE_EXIT;
+}
+
+static gboolean
+gbp_debugger_gutter_renderer_query_activatable (GbpDebuggerGutterRenderer *self,
+ const GtkTextIter *begin,
+ const GdkRectangle *area,
+ GdkEvent *event)
+{
+ g_assert (GBP_IS_DEBUGGER_GUTTER_RENDERER (self));
+ g_assert (begin != NULL);
+ g_assert (area != NULL);
+ g_assert (event != NULL);
+
+ return TRUE;
+}
+
+static void
+gbp_debugger_gutter_renderer_query_data (GbpDebuggerGutterRenderer *self,
+ const GtkTextIter *begin,
+ const GtkTextIter *end,
+ GtkSourceGutterRendererState state)
+{
+ GbpDebuggerBreakType break_type;
+ guint line;
+
+ g_assert (GBP_IS_DEBUGGER_GUTTER_RENDERER (self));
+ g_assert (begin != NULL);
+ g_assert (end != NULL);
+
+ if (self->breakpoints == NULL)
+ return;
+
+ line = gtk_text_iter_get_line (begin) + 1;
+ break_type = gbp_debugger_breakpoints_lookup (self->breakpoints, line);
+
+ /*
+ * These are very much a miss-appropriation of the icon, but it works
+ * well enough for now until we get real symbolic icons for these.
+ */
+#define BREAKPOINT_ICON_NAME "edit-clear-symbolic-rtl"
+#define COUNTPOINT_ICON_NAME "edit-clear-symbolic-rtl"
+#define WATCHPOINT_ICON_NAME "edit-clear-symbolic-rtl"
+
+ switch (break_type)
+ {
+ case GBP_DEBUGGER_BREAK_BREAKPOINT:
+ gtk_source_gutter_renderer_pixbuf_set_icon_name (GTK_SOURCE_GUTTER_RENDERER_PIXBUF (self),
BREAKPOINT_ICON_NAME);
+ break;
+
+ case GBP_DEBUGGER_BREAK_COUNTPOINT:
+ gtk_source_gutter_renderer_pixbuf_set_icon_name (GTK_SOURCE_GUTTER_RENDERER_PIXBUF (self),
COUNTPOINT_ICON_NAME);
+ break;
+
+ case GBP_DEBUGGER_BREAK_WATCHPOINT:
+ gtk_source_gutter_renderer_pixbuf_set_icon_name (GTK_SOURCE_GUTTER_RENDERER_PIXBUF (self),
WATCHPOINT_ICON_NAME);
+ break;
+
+ case GBP_DEBUGGER_BREAK_NONE:
+ default:
+ /* Setting pixbuf to NULL via g_object_set() seems to be
+ * the only way to clear this without g_warning()s.
+ */
+ g_object_set (self, "pixbuf", NULL, NULL);
+ break;
+ }
+}
+
+static void
+gbp_debugger_gutter_renderer_breakpoints_changed (GbpDebuggerGutterRenderer *self,
+ GbpDebuggerBreakpoints *breakpoints)
+{
+ g_assert (GBP_IS_DEBUGGER_GUTTER_RENDERER (self));
+ g_assert (GBP_IS_DEBUGGER_BREAKPOINTS (breakpoints));
+
+ gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (self));
+}
+
+static void
+gbp_debugger_gutter_renderer_set_breakpoints (GbpDebuggerGutterRenderer *self,
+ GbpDebuggerBreakpoints *breakpoints)
+{
+ g_return_if_fail (GBP_IS_DEBUGGER_GUTTER_RENDERER (self));
+ g_return_if_fail (!breakpoints || GBP_IS_DEBUGGER_BREAKPOINTS (breakpoints));
+
+ if (self->breakpoints != breakpoints)
+ {
+ if (self->breakpoints != NULL)
+ {
+ g_signal_handler_disconnect (self->breakpoints, self->breakpoints_changed_handler);
+ self->breakpoints_changed_handler = 0;
+ g_clear_object (&self->breakpoints);
+ }
+
+ if (breakpoints != NULL)
+ {
+ self->breakpoints = g_object_ref (breakpoints);
+ self->breakpoints_changed_handler =
+ g_signal_connect_object (breakpoints,
+ "changed",
+ G_CALLBACK (gbp_debugger_gutter_renderer_breakpoints_changed),
+ self,
+ G_CONNECT_SWAPPED);
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_BREAKPOINTS]);
+ }
+}
+
+static void
+gbp_debugger_gutter_renderer_finalize (GObject *object)
+{
+ GbpDebuggerGutterRenderer *self = (GbpDebuggerGutterRenderer *)object;
+
+ g_clear_object (&self->breakpoints);
+
+ G_OBJECT_CLASS (gbp_debugger_gutter_renderer_parent_class)->finalize (object);
+}
+
+static void
+gbp_debugger_gutter_renderer_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpDebuggerGutterRenderer *self = GBP_DEBUGGER_GUTTER_RENDERER (object);
+
+ switch (prop_id)
+ {
+ case PROP_BREAKPOINTS:
+ g_value_set_object (value, self->breakpoints);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_debugger_gutter_renderer_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpDebuggerGutterRenderer *self = GBP_DEBUGGER_GUTTER_RENDERER (object);
+
+ switch (prop_id)
+ {
+ case PROP_BREAKPOINTS:
+ gbp_debugger_gutter_renderer_set_breakpoints (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_debugger_gutter_renderer_class_init (GbpDebuggerGutterRendererClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gbp_debugger_gutter_renderer_finalize;
+ object_class->get_property = gbp_debugger_gutter_renderer_get_property;
+ object_class->set_property = gbp_debugger_gutter_renderer_set_property;
+
+ properties [PROP_BREAKPOINTS] =
+ g_param_spec_object ("breakpoints",
+ "Breakpoints",
+ "Breakpoints",
+ GBP_TYPE_DEBUGGER_BREAKPOINTS,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gbp_debugger_gutter_renderer_init (GbpDebuggerGutterRenderer *self)
+{
+ g_signal_connect (self,
+ "activate",
+ G_CALLBACK (gbp_debugger_gutter_renderer_activate),
+ NULL);
+
+ g_signal_connect (self,
+ "query-activatable",
+ G_CALLBACK (gbp_debugger_gutter_renderer_query_activatable),
+ NULL);
+
+ g_signal_connect (self,
+ "query-data",
+ G_CALLBACK (gbp_debugger_gutter_renderer_query_data),
+ NULL);
+}
+
+GtkSourceGutterRenderer *
+gbp_debugger_gutter_renderer_new (void)
+{
+ return g_object_new (GBP_TYPE_DEBUGGER_GUTTER_RENDERER, NULL);
+}
diff --git a/plugins/debugger/gbp-debugger-gutter-renderer.h b/plugins/debugger/gbp-debugger-gutter-renderer.h
new file mode 100644
index 0000000..1a33297
--- /dev/null
+++ b/plugins/debugger/gbp-debugger-gutter-renderer.h
@@ -0,0 +1,35 @@
+/* gbp-debugger-gutter-renderer.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_DEBUGGER_GUTTER_RENDERER_H
+#define GBP_DEBUGGER_GUTTER_RENDERER_H
+
+#include <gtksourceview/gtksource.h>
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_DEBUGGER_GUTTER_RENDERER (gbp_debugger_gutter_renderer_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpDebuggerGutterRenderer, gbp_debugger_gutter_renderer, GBP,
DEBUGGER_GUTTER_RENDERER, GtkSourceGutterRendererPixbuf)
+
+GtkSourceGutterRenderer *gbp_debugger_gutter_renderer_new (void);
+
+G_END_DECLS
+
+#endif /* GBP_DEBUGGER_GUTTER_RENDERER_H */
diff --git a/plugins/debugger/gbp-debugger-perspective.c b/plugins/debugger/gbp-debugger-perspective.c
new file mode 100644
index 0000000..4a494dd
--- /dev/null
+++ b/plugins/debugger/gbp-debugger-perspective.c
@@ -0,0 +1,126 @@
+/* gbp-debugger-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-debugger-perspective"
+
+#include <glib/gi18n.h>
+
+#include "gbp-debugger-perspective.h"
+
+struct _GbpDebuggerPerspective
+{
+ IdeLayout parent_instance;
+};
+
+enum {
+ PROP_0,
+ N_PROPS
+};
+
+static gchar *
+gbp_debugger_perspective_get_title (IdePerspective *perspective)
+{
+ return g_strdup (_("Debugger"));
+}
+
+static gchar *
+gbp_debugger_perspective_get_id (IdePerspective *perspective)
+{
+ return g_strdup ("debugger");
+}
+
+static gchar *
+gbp_debugger_perspective_get_icon_name (IdePerspective *perspective)
+{
+ return g_strdup ("nemiver-symbolic");
+}
+
+static gchar *
+gbp_debugger_perspective_get_accelerator (IdePerspective *perspective)
+{
+ return g_strdup ("<Alt>2");
+}
+
+static void
+perspective_iface_init (IdePerspectiveInterface *iface)
+{
+ iface->get_accelerator = gbp_debugger_perspective_get_accelerator;
+ iface->get_icon_name = gbp_debugger_perspective_get_icon_name;
+ iface->get_id = gbp_debugger_perspective_get_id;
+ iface->get_title = gbp_debugger_perspective_get_title;
+}
+
+G_DEFINE_TYPE_EXTENDED (GbpDebuggerPerspective, gbp_debugger_perspective, IDE_TYPE_LAYOUT, 0,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_PERSPECTIVE, perspective_iface_init))
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+gbp_debugger_perspective_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (gbp_debugger_perspective_parent_class)->finalize (object);
+}
+
+static void
+gbp_debugger_perspective_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpDebuggerPerspective *self = GBP_DEBUGGER_PERSPECTIVE (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_debugger_perspective_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpDebuggerPerspective *self = GBP_DEBUGGER_PERSPECTIVE (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_debugger_perspective_class_init (GbpDebuggerPerspectiveClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = gbp_debugger_perspective_finalize;
+ object_class->get_property = gbp_debugger_perspective_get_property;
+ object_class->set_property = gbp_debugger_perspective_set_property;
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/builder/plugins/debugger-plugin/gbp-debugger-perspective.ui");
+}
+
+static void
+gbp_debugger_perspective_init (GbpDebuggerPerspective *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/plugins/debugger/gbp-debugger-perspective.h b/plugins/debugger/gbp-debugger-perspective.h
new file mode 100644
index 0000000..1abf8da
--- /dev/null
+++ b/plugins/debugger/gbp-debugger-perspective.h
@@ -0,0 +1,32 @@
+/* gbp-debugger-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_DEBUGGER_PERSPECTIVE_H
+#define GBP_DEBUGGER_PERSPECTIVE_H
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_DEBUGGER_PERSPECTIVE (gbp_debugger_perspective_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpDebuggerPerspective, gbp_debugger_perspective, GBP, DEBUGGER_PERSPECTIVE, IdeLayout)
+
+G_END_DECLS
+
+#endif /* GBP_DEBUGGER_PERSPECTIVE_H */
diff --git a/plugins/debugger/gbp-debugger-perspective.ui b/plugins/debugger/gbp-debugger-perspective.ui
new file mode 100644
index 0000000..9f66b98
--- /dev/null
+++ b/plugins/debugger/gbp-debugger-perspective.ui
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GbpDebuggerPerspective" parent="IdeLayout">
+ </template>
+</interface>
diff --git a/plugins/debugger/gbp-debugger-plugin.c b/plugins/debugger/gbp-debugger-plugin.c
new file mode 100644
index 0000000..58ba703
--- /dev/null
+++ b/plugins/debugger/gbp-debugger-plugin.c
@@ -0,0 +1,36 @@
+/* gbp-debugger-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/>.
+ */
+
+#define G_LOG_DOMAIN "gbp-debugger-plugin"
+
+#include <libpeas/peas.h>
+#include <ide.h>
+
+#include "gbp-debugger-editor-view-addin.h"
+#include "gbp-debugger-workbench-addin.h"
+
+void
+peas_register_types (PeasObjectModule *module)
+{
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_EDITOR_VIEW_ADDIN,
+ GBP_TYPE_DEBUGGER_EDITOR_VIEW_ADDIN);
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_WORKBENCH_ADDIN,
+ GBP_TYPE_DEBUGGER_WORKBENCH_ADDIN);
+}
diff --git a/plugins/debugger/gbp-debugger-service.c b/plugins/debugger/gbp-debugger-service.c
new file mode 100644
index 0000000..498a70d
--- /dev/null
+++ b/plugins/debugger/gbp-debugger-service.c
@@ -0,0 +1,153 @@
+/* gbp-debugger-service.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-debugger-service"
+
+#include "gbp-debugger-service.h"
+
+struct _GbpDebuggerService
+{
+ IdeObject parent_instance;
+};
+
+enum {
+ PROP_0,
+ N_PROPS
+};
+
+enum {
+ BREAKPOINT_ADDED,
+ BREAKPOINT_REMOVED,
+ N_SIGNALS
+};
+
+static void
+service_iface_init (IdeServiceInterface *iface)
+{
+}
+
+G_DEFINE_TYPE_EXTENDED (GbpDebuggerService, gbp_debugger_service, IDE_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_SERVICE, service_iface_init))
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+gbp_debugger_service_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (gbp_debugger_service_parent_class)->finalize (object);
+}
+
+static void
+gbp_debugger_service_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpDebuggerService *self = GBP_DEBUGGER_SERVICE (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_debugger_service_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpDebuggerService *self = GBP_DEBUGGER_SERVICE (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_debugger_service_class_init (GbpDebuggerServiceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gbp_debugger_service_finalize;
+ object_class->get_property = gbp_debugger_service_get_property;
+ object_class->set_property = gbp_debugger_service_set_property;
+}
+
+static void
+gbp_debugger_service_init (GbpDebuggerService *self)
+{
+}
+
+/**
+ * gbp_debugger_service_get_breakpoints_for_file:
+ *
+ * Gets a #GbpDebuggerBreakpoints for a given #GFile.
+ *
+ * This is useful for gutter renderers that need very fast access to whether or
+ * not a line has a breakpoint on it.
+ *
+ * Returns: (transfer full): A #GbpDebuggerBreakpoints
+ */
+GbpDebuggerBreakpoints *
+gbp_debugger_service_get_breakpoints_for_file (GbpDebuggerService *self,
+ GFile *file)
+{
+ GbpDebuggerBreakpoints *ret;
+ IdeContext *context;
+
+ g_return_val_if_fail (GBP_IS_DEBUGGER_SERVICE (self), NULL);
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+
+ ret = g_object_new (GBP_TYPE_DEBUGGER_BREAKPOINTS,
+ "context", context,
+ "file", file,
+ NULL);
+
+ /* TODO: Load breakpoints from current IDebugger */
+
+ return ret;
+}
+
+void
+gbp_debugger_service_begin (GbpDebuggerService *self,
+ IdeRunner *runner)
+{
+ g_return_if_fail (GBP_IS_DEBUGGER_SERVICE (self));
+ g_return_if_fail (IDE_IS_RUNNER (runner));
+
+ g_warning ("TODO: hook in GDB into runner execution");
+
+}
+
+void
+gbp_debugger_service_toggle_breakpoint (GbpDebuggerService *self,
+ GFile *file,
+ guint line)
+{
+ g_return_if_fail (GBP_IS_DEBUGGER_SERVICE (self));
+ g_return_if_fail (G_IS_FILE (file));
+
+ g_warning ("TODO: toggle breakpoint for debugger instance");
+
+}
diff --git a/plugins/debugger/gbp-debugger-service.h b/plugins/debugger/gbp-debugger-service.h
new file mode 100644
index 0000000..b0b5145
--- /dev/null
+++ b/plugins/debugger/gbp-debugger-service.h
@@ -0,0 +1,37 @@
+/* gbp-debugger-service.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_DEBUGGER_SERVICE_H
+#define GBP_DEBUGGER_SERVICE_H
+
+#include <ide.h>
+
+#include "gbp-debugger-breakpoints.h"
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_DEBUGGER_SERVICE (gbp_debugger_service_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpDebuggerService, gbp_debugger_service, GBP, DEBUGGER_SERVICE, IdeObject)
+
+void gbp_debugger_service_begin (GbpDebuggerService *self,
+ IdeRunner *runner);
+
+G_END_DECLS
+
+#endif /* GBP_DEBUGGER_SERVICE_H */
diff --git a/plugins/debugger/gbp-debugger-workbench-addin.c b/plugins/debugger/gbp-debugger-workbench-addin.c
new file mode 100644
index 0000000..3417d04
--- /dev/null
+++ b/plugins/debugger/gbp-debugger-workbench-addin.c
@@ -0,0 +1,295 @@
+/* gbp-debugger-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/>.
+ */
+
+#define G_LOG_DOMAIN "gbp-debugger-workbench-addin"
+
+#include <glib/gi18n.h>
+
+#include "gbp-debugger-perspective.h"
+#include "gbp-debugger-workbench-addin.h"
+
+struct _GbpDebuggerWorkbenchAddin
+{
+ GObject parent_instance;
+
+ IdeWorkbench *workbench;
+ GbpDebuggerPerspective *perspective;
+ GSimpleActionGroup *actions;
+
+ GtkBox *exec_controls;
+ GtkBox *step_controls;
+};
+
+static void
+gbp_debugger_workbench_addin_runner_exited (GbpDebuggerWorkbenchAddin *self,
+ IdeRunner *runner)
+{
+ g_assert (GBP_IS_DEBUGGER_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_RUNNER (runner));
+
+ gtk_widget_hide (GTK_WIDGET (self->exec_controls));
+ gtk_widget_hide (GTK_WIDGET (self->step_controls));
+
+ ide_workbench_set_visible_perspective_name (self->workbench, "editor");
+}
+
+static void
+debugger_run_handler (IdeRunManager *run_manager,
+ IdeRunner *runner,
+ gpointer user_data)
+{
+ GbpDebuggerWorkbenchAddin *self = user_data;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_RUN_MANAGER (run_manager));
+ g_assert (IDE_IS_RUNNER (runner));
+ g_assert (GBP_IS_DEBUGGER_WORKBENCH_ADDIN (self));
+
+ ide_workbench_set_visible_perspective_name (self->workbench, "debugger");
+
+ g_signal_connect_object (runner,
+ "exited",
+ G_CALLBACK (gbp_debugger_workbench_addin_runner_exited),
+ self,
+ G_CONNECT_SWAPPED);
+
+ gtk_widget_show (GTK_WIDGET (self->exec_controls));
+ gtk_widget_show (GTK_WIDGET (self->step_controls));
+
+#if 0
+ ide_runner_prepend_argv (runner, "--args");
+ ide_runner_prepend_argv (runner, "run");
+ ide_runner_prepend_argv (runner, "-ex");
+ ide_runner_prepend_argv (runner, "gdb");
+#endif
+
+ IDE_EXIT;
+}
+
+static void
+gbp_debugger_workbench_addin_load (IdeWorkbenchAddin *addin,
+ IdeWorkbench *workbench)
+{
+ GbpDebuggerWorkbenchAddin *self = (GbpDebuggerWorkbenchAddin *)addin;
+ IdeWorkbenchHeaderBar *headerbar;
+ IdeRunManager *run_manager;
+ IdeContext *context;
+ GtkBox *box;
+
+ g_assert (IDE_IS_WORKBENCH_ADDIN (addin));
+ g_assert (IDE_IS_WORKBENCH (workbench));
+
+ self->workbench = workbench;
+
+ gtk_widget_insert_action_group (GTK_WIDGET (workbench),
+ "debugger",
+ G_ACTION_GROUP (self->actions));
+
+ headerbar = ide_workbench_get_headerbar (workbench);
+
+ context = ide_workbench_get_context (workbench);
+
+ run_manager = ide_context_get_run_manager (context);
+ ide_run_manager_add_handler (run_manager,
+ "debugger",
+ _("Run with Debugger"),
+ "nemiver-symbolic",
+ "F5",
+ debugger_run_handler,
+ g_object_ref (self),
+ g_object_unref);
+
+ self->perspective = g_object_new (GBP_TYPE_DEBUGGER_PERSPECTIVE,
+ "visible", TRUE,
+ NULL);
+ ide_workbench_add_perspective (workbench, IDE_PERSPECTIVE (self->perspective));
+
+ self->exec_controls = g_object_new (GTK_TYPE_BOX,
+ "orientation", GTK_ORIENTATION_HORIZONTAL,
+ NULL);
+ ide_widget_add_style_class (GTK_WIDGET (self->exec_controls), "linked");
+ ide_workbench_header_bar_insert_left (headerbar, GTK_WIDGET (self->exec_controls), GTK_PACK_START, 100);
+
+#define ADD_BUTTON(action_name, icon_name, tooltip_text) \
+ G_STMT_START { \
+ GtkButton *button; \
+ button = g_object_new (GTK_TYPE_BUTTON, \
+ "action-name", action_name, \
+ "child", g_object_new (GTK_TYPE_IMAGE, \
+ "icon-name", icon_name, \
+ "visible", TRUE, \
+ NULL), \
+ "tooltip-text", tooltip_text, \
+ "visible", TRUE, \
+ NULL); \
+ gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (button)); \
+ } G_STMT_END
+
+ box = self->exec_controls;
+ ADD_BUTTON ("debugger.continue", "debug-continue-symbolic", _("Continue"));
+ ADD_BUTTON ("debugger.execute-from-cursor", "debug-execute-to-cursor-symbolic", _("Execute to cursor"));
+ ADD_BUTTON ("debugger.execute-to-cursor", "debug-execute-from-cursor-symbolic", _("Execute from
cursor"));
+
+ self->step_controls = g_object_new (GTK_TYPE_BOX,
+ "orientation", GTK_ORIENTATION_HORIZONTAL,
+ NULL);
+ ide_widget_add_style_class (GTK_WIDGET (self->step_controls), "linked");
+ ide_workbench_header_bar_insert_left (headerbar, GTK_WIDGET (self->step_controls), GTK_PACK_START, 110);
+
+ box = self->step_controls;
+ ADD_BUTTON ("debugger.step-in", "debug-step-in-symbolic", _("Step in"));
+ ADD_BUTTON ("debugger.step-out", "debug-step-out-symbolic", _("Step out"));
+ ADD_BUTTON ("debugger.step-over", "debug-step-over-symbolic", _("Step over"));
+}
+
+static void
+gbp_debugger_workbench_addin_unload (IdeWorkbenchAddin *addin,
+ IdeWorkbench *workbench)
+{
+ GbpDebuggerWorkbenchAddin *self = (GbpDebuggerWorkbenchAddin *)addin;
+ IdeRunManager *run_manager;
+ IdeContext *context;
+
+ g_assert (IDE_IS_WORKBENCH_ADDIN (addin));
+ 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, "debugger");
+
+ gtk_widget_insert_action_group (GTK_WIDGET (workbench), "debugger", NULL);
+
+ 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_debugger_workbench_addin_load;
+ iface->unload = gbp_debugger_workbench_addin_unload;
+}
+
+G_DEFINE_TYPE_EXTENDED (GbpDebuggerWorkbenchAddin, gbp_debugger_workbench_addin, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKBENCH_ADDIN, workbench_addin_iface_init))
+
+static void
+gbp_debugger_workbench_addin_finalize (GObject *object)
+{
+ GbpDebuggerWorkbenchAddin *self = (GbpDebuggerWorkbenchAddin *)object;
+
+ g_clear_object (&self->actions);
+
+ G_OBJECT_CLASS (gbp_debugger_workbench_addin_parent_class)->finalize (object);
+}
+
+static void
+gbp_debugger_workbench_addin_class_init (GbpDebuggerWorkbenchAddinClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gbp_debugger_workbench_addin_finalize;
+}
+
+static void
+step_in_activate (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+ GbpDebuggerWorkbenchAddin *self = user_data;
+
+ g_assert (GBP_IS_DEBUGGER_WORKBENCH_ADDIN (self));
+
+}
+
+static void
+step_out_activate (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+ GbpDebuggerWorkbenchAddin *self = user_data;
+
+ g_assert (GBP_IS_DEBUGGER_WORKBENCH_ADDIN (self));
+
+}
+
+static void
+step_over_activate (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+ GbpDebuggerWorkbenchAddin *self = user_data;
+
+ g_assert (GBP_IS_DEBUGGER_WORKBENCH_ADDIN (self));
+
+}
+
+static void
+continue_action (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+ GbpDebuggerWorkbenchAddin *self = user_data;
+
+ g_assert (GBP_IS_DEBUGGER_WORKBENCH_ADDIN (self));
+
+}
+
+static void
+execute_to_cursor_action (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+ GbpDebuggerWorkbenchAddin *self = user_data;
+
+ g_assert (GBP_IS_DEBUGGER_WORKBENCH_ADDIN (self));
+
+}
+
+static void
+execute_from_cursor_action (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+ GbpDebuggerWorkbenchAddin *self = user_data;
+
+ g_assert (GBP_IS_DEBUGGER_WORKBENCH_ADDIN (self));
+
+}
+
+static GActionEntry action_entries[] = {
+ { "continue", continue_action },
+ { "step-in", step_in_activate },
+ { "step-out", step_out_activate },
+ { "step-over", step_over_activate },
+ { "execute-from-cursor", execute_from_cursor_action },
+ { "execute-to-cursor", execute_to_cursor_action },
+};
+
+static void
+gbp_debugger_workbench_addin_init (GbpDebuggerWorkbenchAddin *self)
+{
+ self->actions = g_simple_action_group_new ();
+ g_action_map_add_action_entries (G_ACTION_MAP (self->actions),
+ action_entries,
+ G_N_ELEMENTS (action_entries),
+ self);
+}
diff --git a/plugins/debugger/gbp-debugger-workbench-addin.h b/plugins/debugger/gbp-debugger-workbench-addin.h
new file mode 100644
index 0000000..2e95623
--- /dev/null
+++ b/plugins/debugger/gbp-debugger-workbench-addin.h
@@ -0,0 +1,32 @@
+/* gbp-debugger-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_DEBUGGER_WORKBENCH_ADDIN_H
+#define GBP_DEBUGGER_WORKBENCH_ADDIN_H
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_DEBUGGER_WORKBENCH_ADDIN (gbp_debugger_workbench_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpDebuggerWorkbenchAddin, gbp_debugger_workbench_addin, GBP,
DEBUGGER_WORKBENCH_ADDIN, GObject)
+
+G_END_DECLS
+
+#endif /* GBP_DEBUGGER_WORKBENCH_ADDIN_H */
diff --git a/plugins/debugger/gtk/menus.ui b/plugins/debugger/gtk/menus.ui
new file mode 100644
index 0000000..b2e03ef
--- /dev/null
+++ b/plugins/debugger/gtk/menus.ui
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+</interface>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index bc25d34..86029e0 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -133,6 +133,10 @@ plugins/create-project/gbp-create-project-genesis-addin.c
plugins/create-project/gbp-create-project-tool.c
plugins/create-project/gbp-create-project-widget.c
plugins/create-project/gbp-create-project-widget.ui
+plugins/debugger/gbp-debugger-perspective.c
+plugins/debugger/gbp-debugger-perspective.ui
+plugins/debugger/gbp-debugger-service.c
+plugins/debugger/gbp-debugger-workbench-addin.c
plugins/devhelp/gbp-devhelp-panel.c
plugins/file-search/gb-file-search-provider.c
plugins/fpaste/fpaste_plugin/gtk/menus.ui
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]