[gnome-builder] build-tools: start on a build panel
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] build-tools: start on a build panel
- Date: Mon, 21 Dec 2015 08:07:30 +0000 (UTC)
commit 7820cd7fa4100fd84f5f03cf70dec47b48c0fee5
Author: Christian Hergert <chergert redhat com>
Date: Tue Dec 15 15:07:26 2015 -0800
build-tools: start on a build panel
configure.ac | 2 +
data/theme/shared.css | 7 +
libide/ide-build-system.c | 7 +-
libide/ide-builder.c | 5 +
plugins/Makefile.am | 1 +
plugins/build-tools/Makefile.am | 50 +++
plugins/build-tools/build-tools.gresource.xml | 5 +
plugins/build-tools/build-tools.plugin | 9 +
plugins/build-tools/configure.ac | 12 +
plugins/build-tools/gbp-build-panel-row.c | 123 ++++++
plugins/build-tools/gbp-build-panel-row.h | 29 ++
plugins/build-tools/gbp-build-panel-row.ui | 22 +
plugins/build-tools/gbp-build-panel.c | 409 +++++++++++++++++++
plugins/build-tools/gbp-build-panel.h | 35 ++
plugins/build-tools/gbp-build-panel.ui | 356 +++++++++++++++++
plugins/build-tools/gbp-build-plugin.c | 30 ++
plugins/build-tools/gbp-build-tools.gresource.xml | 9 +
plugins/build-tools/gbp-build-workbench-addin.c | 441 +++++++++++++++++++++
plugins/build-tools/gbp-build-workbench-addin.h | 29 ++
plugins/build-tools/gtk/menus.ui | 2 +
plugins/build-tools/theme/shared.css | 19 +
21 files changed, 1600 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 3554bb8..ea23a33 100644
--- a/configure.ac
+++ b/configure.ac
@@ -228,6 +228,7 @@ dnl ***********************************************************************
dnl Check for supported plugins
dnl ***********************************************************************
m4_include([plugins/autotools/configure.ac])
+m4_include([plugins/build-tools/configure.ac])
m4_include([plugins/c-pack/configure.ac])
m4_include([plugins/clang/configure.ac])
m4_include([plugins/command-bar/configure.ac])
@@ -484,6 +485,7 @@ echo ""
echo " Plugins"
echo ""
echo " Autotools ............................ : ${enable_autotools_plugin}"
+echo " Build Tools .......................... : ${enable_build_tools_plugin}"
echo " C Language Pack ...................... : ${enable_c_pack_plugin}"
echo " Clang ................................ : ${enable_clang_plugin}"
echo " Command Bar .......................... : ${enable_command_bar_plugin}"
diff --git a/data/theme/shared.css b/data/theme/shared.css
index 83b6b55..2f01e04 100644
--- a/data/theme/shared.css
+++ b/data/theme/shared.css
@@ -175,3 +175,10 @@ editortweak box.indentation button {
editortweak box.indentation button label {
padding: 2px 12px 2px 12px;
}
+
+
+
+box.build-status {
+ background-image: none;
+ background-color: shade(@theme_bg_color, 1.05);
+}
diff --git a/libide/ide-build-system.c b/libide/ide-build-system.c
index fdd6747..90b7f33 100644
--- a/libide/ide-build-system.c
+++ b/libide/ide-build-system.c
@@ -196,7 +196,7 @@ ide_build_system_new_finish (GAsyncResult *result,
/**
* ide_build_system_get_builder:
* @system: The #IdeBuildSystem to perform the build.
- * @config: The configuration options for the build.
+ * @config: (nullable): The configuration options for the build.
* @device: The #IdeDevice the result should be able to run on.
*
* This function should return an #IdeBuilder that can be used to perform a
@@ -213,11 +213,14 @@ ide_build_system_get_builder (IdeBuildSystem *system,
{
IdeBuildSystemInterface *iface;
IdeBuilder *ret = NULL;
+ g_autoptr(GKeyFile) local = NULL;
g_return_val_if_fail (IDE_IS_BUILD_SYSTEM (system), NULL);
- g_return_val_if_fail (config, NULL);
g_return_val_if_fail (IDE_IS_DEVICE (device), NULL);
+ if (config == NULL)
+ config = local = g_key_file_new ();
+
iface = IDE_BUILD_SYSTEM_GET_IFACE (system);
if (iface->get_builder)
diff --git a/libide/ide-builder.c b/libide/ide-builder.c
index 74536a1..520e177 100644
--- a/libide/ide-builder.c
+++ b/libide/ide-builder.c
@@ -23,6 +23,11 @@
G_DEFINE_ABSTRACT_TYPE (IdeBuilder, ide_builder, IDE_TYPE_OBJECT)
+/**
+ * ide_builder_build_async:
+ * @result: (out) (transfer none): A location for an #IdeBuildResult.
+ *
+ */
void
ide_builder_build_async (IdeBuilder *builder,
IdeBuilderBuildFlags flags,
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index bda42fb..f729ada 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -1,5 +1,6 @@
SUBDIRS = \
autotools \
+ build-tools \
clang \
command-bar \
c-pack \
diff --git a/plugins/build-tools/Makefile.am b/plugins/build-tools/Makefile.am
new file mode 100644
index 0000000..5fadfa7
--- /dev/null
+++ b/plugins/build-tools/Makefile.am
@@ -0,0 +1,50 @@
+if ENABLE_BUILD_TOOLS_PLUGIN
+
+DISTCLEANFILES =
+BUILT_SOURCES =
+CLEANFILES =
+EXTRA_DIST = $(plugin_DATA)
+
+plugindir = $(libdir)/gnome-builder/plugins
+plugin_LTLIBRARIES = libbuild-tools-plugin.la
+dist_plugin_DATA = build-tools.plugin
+
+libbuild_tools_plugin_la_SOURCES = \
+ gbp-build-panel.c \
+ gbp-build-panel.h \
+ gbp-build-panel-row.c \
+ gbp-build-panel-row.h \
+ gbp-build-plugin.c \
+ gbp-build-workbench-addin.c \
+ gbp-build-workbench-addin.h \
+ $(NULL)
+
+nodist_libbuild_tools_plugin_la_SOURCES = \
+ gbp-build-resources.c \
+ gbp-build-resources.h
+
+libbuild_tools_plugin_la_CFLAGS = \
+ $(LIBIDE_CFLAGS) \
+ $(OPTIMIZE_CFLAGS) \
+ -I$(top_srcdir)/libide \
+ -I$(top_srcdir)/contrib/egg \
+ $(NULL)
+
+libbuild_tools_plugin_la_LDFLAGS = \
+ $(OPTIMIZE_LDFLAGS) \
+ -avoid-version \
+ -module \
+ -export-regex peas_register_types \
+ $(NULL)
+
+glib_resources_c = gbp-build-resources.c
+glib_resources_h = gbp-build-resources.h
+glib_resources_xml = gbp-build-tools.gresource.xml
+glib_resources_namespace = gbp_build_tools
+include $(top_srcdir)/build/autotools/Makefile.am.gresources
+
+include $(top_srcdir)/plugins/Makefile.plugin
+
+endif
+
+-include $(top_srcdir)/git.mk
diff --git a/plugins/build-tools/build-tools.gresource.xml b/plugins/build-tools/build-tools.gresource.xml
new file mode 100644
index 0000000..2db9a35
--- /dev/null
+++ b/plugins/build-tools/build-tools.gresource.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/builder/plugins/build-tools-plugin">
+ </gresource>
+</gresources>
diff --git a/plugins/build-tools/build-tools.plugin b/plugins/build-tools/build-tools.plugin
new file mode 100644
index 0000000..4121e6e
--- /dev/null
+++ b/plugins/build-tools/build-tools.plugin
@@ -0,0 +1,9 @@
+[Plugin]
+Module=build-tools-plugin
+Name=Build Tools
+Description=Build panel and command line tools
+Authors=Christian Hergert <christian hergert me>
+Copyright=Copyright © 2015 Christian Hergert
+Depends=editor
+Hidden=true
+Builtin=true
diff --git a/plugins/build-tools/configure.ac b/plugins/build-tools/configure.ac
new file mode 100644
index 0000000..13bf717
--- /dev/null
+++ b/plugins/build-tools/configure.ac
@@ -0,0 +1,12 @@
+# --enable-build-tools-plugin=yes/no
+AC_ARG_ENABLE([build-tools-plugin],
+ [AS_HELP_STRING([--enable-build-tools-plugin=@<:@yes/no@:>@],
+ [Build with support for build tools and panels.])],
+ [enable_build_tools_plugin=$enableval],
+ [enable_build_tools_plugin=yes])
+
+# for if ENABLE_BUILD_TOOLS_PLUGIN in Makefile.am
+AM_CONDITIONAL(ENABLE_BUILD_TOOLS_PLUGIN, test x$enable_build_tools_plugin != xno)
+
+# Ensure our makefile is generated by autoconf
+AC_CONFIG_FILES([plugins/build-tools/Makefile])
diff --git a/plugins/build-tools/gbp-build-panel-row.c b/plugins/build-tools/gbp-build-panel-row.c
new file mode 100644
index 0000000..4fffa0c
--- /dev/null
+++ b/plugins/build-tools/gbp-build-panel-row.c
@@ -0,0 +1,123 @@
+/* gbp-build-panel-row.c
+ *
+ * Copyright (C) 2015 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 <ide.h>
+
+#include "gbp-build-panel-row.h"
+
+struct _GbpBuildPanelRow
+{
+ GtkListBoxRow parent_instance;
+
+ GtkLabel *file_label;
+ GtkLabel *message_label;
+
+ IdeDiagnostic *diagnostic;
+};
+
+G_DEFINE_TYPE (GbpBuildPanelRow, gbp_build_panel_row, GTK_TYPE_LIST_BOX_ROW)
+
+enum {
+ PROP_0,
+ PROP_DIAGNOSTIC,
+ LAST_PROP
+};
+
+static GParamSpec *properties [LAST_PROP];
+
+static void
+gbp_build_panel_row_set_diagnostic (GbpBuildPanelRow *self,
+ IdeDiagnostic *diagnostic)
+{
+ gchar *text;
+
+ g_return_if_fail (GBP_IS_BUILD_PANEL_ROW (self));
+ g_return_if_fail (diagnostic != NULL);
+
+ text = ide_diagnostic_get_text_for_display (diagnostic);
+ gtk_label_set_label (self->message_label, text);
+ g_free (text);
+}
+
+static void
+gbp_build_panel_row_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpBuildPanelRow *self = GBP_BUILD_PANEL_ROW(object);
+
+ switch (prop_id)
+ {
+ case PROP_DIAGNOSTIC:
+ g_value_set_boxed (value, self->diagnostic);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_build_panel_row_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpBuildPanelRow *self = GBP_BUILD_PANEL_ROW(object);
+
+ switch (prop_id)
+ {
+ case PROP_DIAGNOSTIC:
+ gbp_build_panel_row_set_diagnostic (self, g_value_get_boxed (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_build_panel_row_class_init (GbpBuildPanelRowClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gbp_build_panel_row_get_property;
+ object_class->set_property = gbp_build_panel_row_set_property;
+
+ properties [PROP_DIAGNOSTIC] =
+ g_param_spec_boxed ("diagnostic",
+ "Diagnostic",
+ "Diagnostic",
+ IDE_TYPE_DIAGNOSTIC,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, LAST_PROP, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/builder/plugins/build-tools-plugin/gbp-build-panel-row.ui");
+ gtk_widget_class_set_css_name (widget_class, "buildpanelrow");
+ gtk_widget_class_bind_template_child (widget_class, GbpBuildPanelRow, file_label);
+ gtk_widget_class_bind_template_child (widget_class, GbpBuildPanelRow, message_label);
+}
+
+static void
+gbp_build_panel_row_init (GbpBuildPanelRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/plugins/build-tools/gbp-build-panel-row.h b/plugins/build-tools/gbp-build-panel-row.h
new file mode 100644
index 0000000..afd2d9b
--- /dev/null
+++ b/plugins/build-tools/gbp-build-panel-row.h
@@ -0,0 +1,29 @@
+/* gbp-build-panel-row.h
+ *
+ * Copyright (C) 2015 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/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_BUILD_PANEL_ROW (gbp_build_panel_row_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpBuildPanelRow, gbp_build_panel_row, GBP, BUILD_PANEL_ROW, GObject)
+
+G_END_DECLS
diff --git a/plugins/build-tools/gbp-build-panel-row.ui b/plugins/build-tools/gbp-build-panel-row.ui
new file mode 100644
index 0000000..5079030
--- /dev/null
+++ b/plugins/build-tools/gbp-build-panel-row.ui
@@ -0,0 +1,22 @@
+<interface>
+ <template class="GbpBuildPanelRow" parent="GtkListBoxRow">
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkLabel" id="file_label">
+ <property name="visible">true</property>
+ <property name="xalign">0.0</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="message_label">
+ <property name="visible">true</property>
+ <property name="xalign">0.0</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/plugins/build-tools/gbp-build-panel.c b/plugins/build-tools/gbp-build-panel.c
new file mode 100644
index 0000000..b9e689f
--- /dev/null
+++ b/plugins/build-tools/gbp-build-panel.c
@@ -0,0 +1,409 @@
+/* gbp-build-panel.c
+ *
+ * Copyright (C) 2015 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 "egg-binding-group.h"
+#include "egg-signal-group.h"
+
+#include "gbp-build-panel.h"
+#include "gbp-build-panel-row.h"
+
+struct _GbpBuildPanel
+{
+ GtkBin parent_instance;
+
+ IdeBuildResult *result;
+ EggSignalGroup *signals;
+ EggBindingGroup *bindings;
+
+ IdeDevice *device;
+
+ GtkListBox *diagnostics;
+ GtkRevealer *status_revealer;
+ GtkLabel *status_label;
+ GtkLabel *running_time_label;
+ GtkMenuButton *device_button;
+ GtkLabel *device_label;
+ GtkListBox *devices;
+ GtkPopover *device_popover;
+
+ guint running_time_source;
+};
+
+G_DEFINE_TYPE (GbpBuildPanel, gbp_build_panel, GTK_TYPE_BIN)
+
+enum {
+ PROP_0,
+ PROP_DEVICE,
+ PROP_DEVICE_MANAGER,
+ PROP_RESULT,
+ LAST_PROP
+};
+
+static GParamSpec *properties [LAST_PROP];
+
+static GtkWidget *
+create_device_row (gpointer item,
+ gpointer user_data)
+{
+ GtkListBoxRow *row;
+ IdeDevice *device = item;
+ const gchar *type;
+ const gchar *name;
+ GtkLabel *label;
+ gchar *str;
+
+ g_assert (IDE_IS_DEVICE (device));
+
+ row = g_object_new (GTK_TYPE_LIST_BOX_ROW,
+ "visible", TRUE,
+ NULL);
+
+ g_object_set_data_full (G_OBJECT (row),
+ "IDE_DEVICE_ID",
+ g_strdup (ide_device_get_id (device)),
+ g_free);
+
+ name = ide_device_get_display_name (device);
+ type = ide_device_get_system_type (device);
+ str = g_strdup_printf ("%s (%s)", name, type);
+
+ label = g_object_new (GTK_TYPE_LABEL,
+ "label", str,
+ "xalign", 0.0f,
+ "visible", TRUE,
+ NULL);
+ gtk_container_add (GTK_CONTAINER (row), GTK_WIDGET (label));
+
+ g_free (str);
+
+ return GTK_WIDGET (row);
+}
+
+static void
+gbp_build_panel_set_device (GbpBuildPanel *self,
+ IdeDevice *device)
+{
+ g_return_if_fail (GBP_IS_BUILD_PANEL (self));
+ g_return_if_fail (!device || IDE_IS_DEVICE (device));
+
+ if (g_set_object (&self->device, device))
+ {
+ const gchar *name = NULL;
+
+ if (device != NULL)
+ name = ide_device_get_display_name (device);
+ gtk_label_set_label (self->device_label, name);
+ }
+}
+
+static void
+gbp_build_panel_set_device_manager (GbpBuildPanel *self,
+ IdeDeviceManager *device_manager)
+{
+ g_return_if_fail (GBP_IS_BUILD_PANEL (self));
+ g_return_if_fail (!device_manager || IDE_IS_DEVICE_MANAGER (device_manager));
+
+ gtk_list_box_bind_model (self->devices,
+ G_LIST_MODEL (device_manager),
+ create_device_row, NULL, NULL);
+}
+
+void
+gbp_build_panel_add_error (GbpBuildPanel *self,
+ const gchar *message)
+{
+ g_return_if_fail (GBP_IS_BUILD_PANEL (self));
+ g_return_if_fail (message != NULL);
+
+}
+
+static void
+gbp_build_panel_diagnostic (GbpBuildPanel *self,
+ IdeDiagnostic *diagnostic,
+ IdeBuildResult *result)
+{
+ GtkWidget *row;
+
+ g_assert (GBP_IS_BUILD_PANEL (self));
+ g_assert (diagnostic != NULL);
+ g_assert (IDE_IS_BUILD_RESULT (result));
+
+ row = g_object_new (GBP_TYPE_BUILD_PANEL_ROW,
+ "diagnostic", diagnostic,
+ "visible", TRUE,
+ NULL);
+ gtk_container_add (GTK_CONTAINER (self->diagnostics), row);
+}
+
+static gboolean
+gbp_build_panel_update_running_time (GbpBuildPanel *self)
+{
+ g_assert (GBP_IS_BUILD_PANEL (self));
+
+ if (self->result != NULL)
+ {
+ GTimeSpan span;
+ guint hours;
+ guint minutes;
+ guint seconds;
+ gchar *text;
+
+ span = ide_build_result_get_running_time (self->result);
+
+ hours = span / G_TIME_SPAN_HOUR;
+ minutes = (span % G_TIME_SPAN_HOUR) / G_TIME_SPAN_MINUTE;
+ seconds = (span % G_TIME_SPAN_MINUTE) / G_TIME_SPAN_SECOND;
+
+ text = g_strdup_printf ("%02u:%02u:%02u", hours, minutes, seconds);
+ gtk_label_set_label (self->running_time_label, text);
+ g_free (text);
+ }
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+gbp_build_panel_connect (GbpBuildPanel *self,
+ IdeBuildResult *result)
+{
+ g_return_if_fail (GBP_IS_BUILD_PANEL (self));
+ g_return_if_fail (IDE_IS_BUILD_RESULT (result));
+ g_return_if_fail (self->result == NULL);
+
+ self->result = g_object_ref (result);
+
+ egg_signal_group_set_target (self->signals, result);
+ egg_binding_group_set_source (self->bindings, result);
+
+ if (ide_build_result_get_running (result))
+ {
+ gtk_label_set_label (self->running_time_label, NULL);
+ self->running_time_source =
+ g_timeout_add_seconds (1, (GSourceFunc)gbp_build_panel_update_running_time, self);
+ }
+
+ gtk_revealer_set_reveal_child (self->status_revealer, TRUE);
+}
+
+static void
+gbp_build_panel_disconnect (GbpBuildPanel *self)
+{
+ g_return_if_fail (GBP_IS_BUILD_PANEL (self));
+
+ gtk_revealer_set_reveal_child (self->status_revealer, FALSE);
+
+ egg_signal_group_set_target (self->signals, NULL);
+ egg_binding_group_set_source (self->bindings, NULL);
+ ide_clear_source (&self->running_time_source);
+ g_clear_object (&self->result);
+}
+
+void
+gbp_build_panel_set_result (GbpBuildPanel *self,
+ IdeBuildResult *result)
+{
+ g_return_if_fail (GBP_IS_BUILD_PANEL (self));
+ g_return_if_fail (!result || IDE_IS_BUILD_RESULT (result));
+
+ if (result != self->result)
+ {
+ if (self->result)
+ gbp_build_panel_disconnect (self);
+
+ if (result)
+ gbp_build_panel_connect (self, result);
+ }
+}
+
+static void
+gbp_build_panel_notify_running (GbpBuildPanel *self,
+ GParamSpec *pspec,
+ IdeBuildResult *result)
+{
+ g_assert (GBP_IS_BUILD_PANEL (self));
+ g_assert (IDE_IS_BUILD_RESULT (result));
+
+ if (!ide_build_result_get_running (result))
+ ide_clear_source (&self->running_time_source);
+
+ gbp_build_panel_update_running_time (self);
+}
+
+static void
+gbp_build_panel_device_activated (GbpBuildPanel *self,
+ GtkListBoxRow *row,
+ GtkListBox *list_box)
+{
+ const gchar *id;
+
+ g_assert (GBP_IS_BUILD_PANEL (self));
+ g_assert (GTK_IS_LIST_BOX_ROW (row));
+ g_assert (GTK_IS_LIST_BOX (list_box));
+
+ if ((id = g_object_get_data (G_OBJECT (row), "IDE_DEVICE_ID")))
+ ide_widget_action (GTK_WIDGET (self),
+ "build-tools", "device",
+ g_variant_new_string (id));
+
+ gtk_widget_hide (GTK_WIDGET (self->device_popover));
+}
+
+static void
+gbp_build_panel_destroy (GtkWidget *widget)
+{
+ GbpBuildPanel *self = (GbpBuildPanel *)widget;
+
+ if (self->result)
+ gbp_build_panel_disconnect (self);
+
+ g_clear_object (&self->bindings);
+ g_clear_object (&self->signals);
+ g_clear_object (&self->device);
+
+ GTK_WIDGET_CLASS (gbp_build_panel_parent_class)->destroy (widget);
+}
+
+static void
+gbp_build_panel_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpBuildPanel *self = GBP_BUILD_PANEL(object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE:
+ g_value_set_object (value, self->device);
+ break;
+
+ case PROP_RESULT:
+ g_value_set_object (value, self->result);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_build_panel_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpBuildPanel *self = GBP_BUILD_PANEL(object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE:
+ gbp_build_panel_set_device (self, g_value_get_object (value));
+ break;
+
+ case PROP_DEVICE_MANAGER:
+ gbp_build_panel_set_device_manager (self, g_value_get_object (value));
+ break;
+
+ case PROP_RESULT:
+ gbp_build_panel_set_result (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_build_panel_class_init (GbpBuildPanelClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gbp_build_panel_get_property;
+ object_class->set_property = gbp_build_panel_set_property;
+
+ widget_class->destroy = gbp_build_panel_destroy;
+
+ properties [PROP_DEVICE] =
+ g_param_spec_object ("device",
+ "Device",
+ "Device",
+ IDE_TYPE_DEVICE,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_DEVICE_MANAGER] =
+ g_param_spec_object ("device-manager",
+ "Device Manager",
+ "Device Manager",
+ IDE_TYPE_DEVICE_MANAGER,
+ (G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_RESULT] =
+ g_param_spec_object ("result",
+ "Result",
+ "Result",
+ IDE_TYPE_BUILD_RESULT,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, LAST_PROP, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/builder/plugins/build-tools-plugin/gbp-build-panel.ui");
+ gtk_widget_class_set_css_name (widget_class, "buildpanel");
+ gtk_widget_class_bind_template_child (widget_class, GbpBuildPanel, device_button);
+ gtk_widget_class_bind_template_child (widget_class, GbpBuildPanel, device_label);
+ gtk_widget_class_bind_template_child (widget_class, GbpBuildPanel, device_popover);
+ gtk_widget_class_bind_template_child (widget_class, GbpBuildPanel, devices);
+ gtk_widget_class_bind_template_child (widget_class, GbpBuildPanel, diagnostics);
+ gtk_widget_class_bind_template_child (widget_class, GbpBuildPanel, running_time_label);
+ gtk_widget_class_bind_template_child (widget_class, GbpBuildPanel, status_label);
+ gtk_widget_class_bind_template_child (widget_class, GbpBuildPanel, status_revealer);
+}
+
+static void
+gbp_build_panel_init (GbpBuildPanel *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->signals = egg_signal_group_new (IDE_TYPE_BUILD_RESULT);
+
+ egg_signal_group_connect_object (self->signals,
+ "diagnostic",
+ G_CALLBACK (gbp_build_panel_diagnostic),
+ self,
+ G_CONNECT_SWAPPED);
+
+ egg_signal_group_connect_object (self->signals,
+ "notify::running",
+ G_CALLBACK (gbp_build_panel_notify_running),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->devices,
+ "row-activated",
+ G_CALLBACK (gbp_build_panel_device_activated),
+ self,
+ G_CONNECT_SWAPPED);
+
+ self->bindings = egg_binding_group_new ();
+
+ egg_binding_group_bind (self->bindings, "mode",
+ self->status_label, "label",
+ G_BINDING_SYNC_CREATE);
+}
diff --git a/plugins/build-tools/gbp-build-panel.h b/plugins/build-tools/gbp-build-panel.h
new file mode 100644
index 0000000..e7a9b5f
--- /dev/null
+++ b/plugins/build-tools/gbp-build-panel.h
@@ -0,0 +1,35 @@
+/* gbp-build-panel.h
+ *
+ * Copyright (C) 2015 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/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_BUILD_PANEL (gbp_build_panel_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpBuildPanel, gbp_build_panel, GBP, BUILD_PANEL, GtkBin)
+
+void gbp_build_panel_set_result (GbpBuildPanel *self,
+ IdeBuildResult *result);
+void gbp_build_panel_add_error (GbpBuildPanel *self,
+ const gchar *message);
+
+G_END_DECLS
diff --git a/plugins/build-tools/gbp-build-panel.ui b/plugins/build-tools/gbp-build-panel.ui
new file mode 100644
index 0000000..e928112
--- /dev/null
+++ b/plugins/build-tools/gbp-build-panel.ui
@@ -0,0 +1,356 @@
+<interface>
+ <template class="GbpBuildPanel" parent="GtkBin">
+ <child>
+ <object class="GtkBox" id="toplevel">
+ <property name="visible">true</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="border-width">12</property>
+ <property name="column-spacing">12</property>
+ <property name="column-homogeneous">true</property>
+ <property name="row-spacing">6</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="label" translatable="yes">Device:</property>
+ <property name="xalign">1.0</property>
+ <property name="visible">true</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="label" translatable="yes">Framework:</property>
+ <property name="xalign">1.0</property>
+ <property name="visible">false</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="label" translatable="yes">Packaging:</property>
+ <property name="xalign">1.0</property>
+ <property name="visible">false</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">true</property>
+ <property name="margin-top">6</property>
+ <property name="halign">end</property>
+ <property name="hexpand">true</property>
+ <property name="spacing">6</property>
+ <property name="homogeneous">true</property>
+ <child>
+ <object class="GtkButton">
+ <property name="action-name">build-tools.build</property>
+ <property name="label" translatable="yes">_Build</property>
+ <property name="use-underline">true</property>
+ <property name="visible">true</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="action-name">build-tools.rebuild</property>
+ <property name="label" translatable="yes">_Rebuild</property>
+ <property name="use-underline">true</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="action-name">build-tools.clean</property>
+ <property name="label" translatable="yes">_Clean</property>
+ <property name="use-underline">true</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="device_button">
+ <property name="focus-on-click">false</property>
+ <property name="popover">device_popover</property>
+ <property name="visible">true</property>
+ <style>
+ <class name="flat"/>
+ </style>
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkLabel" id="device_label">
+ <property name="visible">true</property>
+ <property name="hexpand">false</property>
+ <property name="xalign">0.0</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">pan-down-symbolic</property>
+ <property name="visible">true</property>
+ <property name="hexpand">false</property>
+ <property name="xalign">0.0</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkMenuButton">
+ <property name="label" translatable="yes">framework</property>
+ <property name="visible">false</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkMenuButton">
+ <property name="label" translatable="yes">packaging</property>
+ <property name="visible">false</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="orientation">horizontal</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkRevealer" id="status_revealer">
+ <property name="transition-type">slide-down</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="visible">true</property>
+ <style>
+ <class name="build-status"/>
+ </style>
+ <child>
+ <object class="GtkGrid">
+ <property name="border-width">12</property>
+ <property name="column-spacing">12</property>
+ <property name="column-homogeneous">true</property>
+ <property name="row-spacing">6</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="label" translatable="yes">Status:</property>
+ <property name="xalign">1.0</property>
+ <property name="visible">true</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="status_label">
+ <property name="xalign">0.0</property>
+ <property name="visible">true</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="label" translatable="yes">Running Time:</property>
+ <property name="xalign">1.0</property>
+ <property name="visible">true</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="running_time_label">
+ <property name="xalign">0.0</property>
+ <property name="visible">true</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="label" translatable="yes">Warnings:</property>
+ <property name="xalign">1.0</property>
+ <property name="visible">true</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="warnings_label">
+ <property name="xalign">0.0</property>
+ <property name="visible">true</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">true</property>
+ <property name="margin-top">6</property>
+ <property name="hexpand">true</property>
+ <property name="halign">end</property>
+ <property name="spacing">6</property>
+ <property name="homogeneous">true</property>
+ <child>
+ <object class="GtkButton">
+ <property name="action-name">build-tools.cancel</property>
+ <property name="label" translatable="yes">Cancel</property>
+ <property name="use-underline">true</property>
+ <property name="visible">true</property>
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="action-name">build-tools.deploy</property>
+ <property name="label" translatable="yes">Deploy</property>
+ <property name="use-underline">true</property>
+ <property name="visible">false</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="action-name">build-tools.export</property>
+ <property name="label" translatable="yes">Export</property>
+ <property name="use-underline">true</property>
+ <property name="visible">false</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="orientation">horizontal</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="vexpand">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkListBox" id="diagnostics">
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkPopover" id="device_popover">
+ <child>
+ <object class="EggScrolledWindow">
+ <property name="min-content-width">100</property>
+ <property name="max-content-width">300</property>
+ <property name="max-content-height">300</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkListBox" id="devices">
+ <property name="selection-mode">none</property>
+ <property name="visible">true</property>
+ <style>
+ <class name="buildpanel"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/plugins/build-tools/gbp-build-plugin.c b/plugins/build-tools/gbp-build-plugin.c
new file mode 100644
index 0000000..e030fc2
--- /dev/null
+++ b/plugins/build-tools/gbp-build-plugin.c
@@ -0,0 +1,30 @@
+/* gbp-build-plugin.c
+ *
+ * Copyright (C) 2015 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-build-workbench-addin.h"
+
+void
+peas_register_types (PeasObjectModule *module)
+{
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_WORKBENCH_ADDIN,
+ GBP_TYPE_BUILD_WORKBENCH_ADDIN);
+}
diff --git a/plugins/build-tools/gbp-build-tools.gresource.xml
b/plugins/build-tools/gbp-build-tools.gresource.xml
new file mode 100644
index 0000000..6c6a860
--- /dev/null
+++ b/plugins/build-tools/gbp-build-tools.gresource.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/builder/plugins/build-tools-plugin">
+ <file>gtk/menus.ui</file>
+ <file>theme/shared.css</file>
+ <file>gbp-build-panel.ui</file>
+ <file>gbp-build-panel-row.ui</file>
+ </gresource>
+</gresources>
diff --git a/plugins/build-tools/gbp-build-workbench-addin.c b/plugins/build-tools/gbp-build-workbench-addin.c
new file mode 100644
index 0000000..cbca0bb
--- /dev/null
+++ b/plugins/build-tools/gbp-build-workbench-addin.c
@@ -0,0 +1,441 @@
+/* gbp-build-workbench-addin.c
+ *
+ * Copyright (C) 2015 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 "egg-binding-group.h"
+
+#include "gbp-build-panel.h"
+#include "gbp-build-workbench-addin.h"
+
+struct _GbpBuildWorkbenchAddin
+{
+ GObject parent_instance;
+
+ /* Unowned */
+ GbpBuildPanel *panel;
+ IdeWorkbench *workbench;
+
+ /* Owned */
+ EggBindingGroup *bindings;
+ IdeBuildResult *result;
+ GSimpleActionGroup *actions;
+ GCancellable *cancellable;
+ IdeDevice *device;
+};
+
+static void workbench_addin_iface_init (IdeWorkbenchAddinInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (GbpBuildWorkbenchAddin, gbp_build_workbench_addin, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKBENCH_ADDIN,
+ workbench_addin_iface_init))
+
+enum {
+ PROP_0,
+ PROP_DEVICE,
+ PROP_RESULT,
+ LAST_PROP
+};
+
+static GParamSpec *properties [LAST_PROP];
+
+static void
+gbp_build_workbench_addin_set_device (GbpBuildWorkbenchAddin *self,
+ IdeDevice *device)
+{
+ g_assert (GBP_IS_BUILD_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_DEVICE (device));
+
+ if (g_set_object (&self->device, device))
+ {
+ const gchar *id = ide_device_get_id (device);
+ GAction *action;
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (self->actions), "device");
+ g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_string (id));
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DEVICE]);
+ }
+}
+
+static void
+gbp_build_workbench_addin_set_result (GbpBuildWorkbenchAddin *self,
+ IdeBuildResult *result)
+{
+ g_return_if_fail (GBP_IS_BUILD_WORKBENCH_ADDIN (self));
+ g_return_if_fail (!result || IDE_IS_BUILD_RESULT (result));
+
+ if (g_set_object (&self->result, result))
+ {
+ egg_binding_group_set_source (self->bindings, result);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_RESULT]);
+ }
+}
+
+static void
+gbp_build_workbench_addin_build_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeBuilder *builder = (IdeBuilder *)object;
+ g_autoptr(GbpBuildWorkbenchAddin) self = user_data;
+ g_autoptr(IdeBuildResult) build_result = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (IDE_IS_BUILDER (builder));
+ g_assert (GBP_IS_BUILD_WORKBENCH_ADDIN (self));
+
+ build_result = ide_builder_build_finish (builder, result, &error);
+
+ if (error != NULL)
+ g_warning ("%s", error->message);
+}
+
+static void
+gbp_build_workbench_addin_do_build (GbpBuildWorkbenchAddin *self,
+ IdeBuilderBuildFlags flags)
+{
+ g_autoptr(IdeBuildResult) build_result = NULL;
+ g_autoptr(IdeBuilder) builder = NULL;
+ g_autoptr(GError) error = NULL;
+ IdeBuildSystem *build_system;
+ IdeWorkbench *workbench;
+ IdeContext *context;
+
+ g_assert (GBP_IS_BUILD_WORKBENCH_ADDIN (self));
+
+ gbp_build_workbench_addin_set_result (self, NULL);
+
+ workbench = ide_widget_get_workbench (GTK_WIDGET (self->panel));
+ context = ide_workbench_get_context (workbench);
+ build_system = ide_context_get_build_system (context);
+ builder = ide_build_system_get_builder (build_system, NULL, self->device, &error);
+
+ if (error != NULL)
+ {
+ gbp_build_panel_add_error (self->panel, error->message);
+ return;
+ }
+
+ g_clear_object (&self->cancellable);
+ self->cancellable = g_cancellable_new ();
+
+ ide_builder_build_async (builder,
+ flags,
+ &build_result,
+ self->cancellable,
+ gbp_build_workbench_addin_build_cb,
+ g_object_ref (self));
+
+ gbp_build_workbench_addin_set_result (self, build_result);
+}
+
+static void
+gbp_build_workbench_addin_build (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+ GbpBuildWorkbenchAddin *self = user_data;
+
+ g_assert (G_IS_SIMPLE_ACTION (action));
+ g_assert (GBP_IS_BUILD_WORKBENCH_ADDIN (self));
+
+ gbp_build_workbench_addin_do_build (self, 0);
+}
+
+static void
+gbp_build_workbench_addin_rebuild (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+ GbpBuildWorkbenchAddin *self = user_data;
+
+ g_assert (G_IS_SIMPLE_ACTION (action));
+ g_assert (GBP_IS_BUILD_WORKBENCH_ADDIN (self));
+
+ gbp_build_workbench_addin_do_build (self, IDE_BUILDER_BUILD_FLAGS_FORCE_REBUILD);
+}
+
+static void
+gbp_build_workbench_addin_clean (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+ GbpBuildWorkbenchAddin *self = user_data;
+
+ g_assert (G_IS_SIMPLE_ACTION (action));
+ g_assert (GBP_IS_BUILD_WORKBENCH_ADDIN (self));
+
+ gbp_build_workbench_addin_do_build (self, IDE_BUILDER_BUILD_FLAGS_CLEAN);
+}
+
+static void
+gbp_build_workbench_addin_cancel (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+ GbpBuildWorkbenchAddin *self = user_data;
+
+ g_assert (GBP_IS_BUILD_WORKBENCH_ADDIN (self));
+
+ if (self->cancellable)
+ g_cancellable_cancel (self->cancellable);
+}
+
+static void
+gbp_build_workbench_addin_deploy (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+}
+
+static void
+gbp_build_workbench_addin_export (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+}
+
+static void
+gbp_build_workbench_addin_device (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+ GbpBuildWorkbenchAddin *self = user_data;
+ IdeDeviceManager *device_manager;
+ IdeContext *context;
+ IdeDevice *device;
+ const gchar *id;
+
+ g_assert (GBP_IS_BUILD_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_WORKBENCH (self->workbench));
+
+ id = g_variant_get_string (param, NULL);
+ if (id == NULL)
+ id = "local";
+
+ context = ide_workbench_get_context (self->workbench);
+ device_manager = ide_context_get_device_manager (context);
+ device = ide_device_manager_get_device (device_manager, id);
+
+ if (device == NULL)
+ device = ide_device_manager_get_device (device_manager, "local");
+
+ gbp_build_workbench_addin_set_device (self, device);
+}
+
+static const GActionEntry actions[] = {
+ { "build", gbp_build_workbench_addin_build },
+ { "rebuild", gbp_build_workbench_addin_rebuild },
+ { "clean", gbp_build_workbench_addin_clean },
+ { "cancel", gbp_build_workbench_addin_cancel },
+ { "deploy", gbp_build_workbench_addin_deploy },
+ { "export", gbp_build_workbench_addin_export },
+ { "device", NULL, "s", "'local'", gbp_build_workbench_addin_device },
+};
+
+static void
+gbp_build_workbench_addin_load (IdeWorkbenchAddin *addin,
+ IdeWorkbench *workbench)
+{
+ GbpBuildWorkbenchAddin *self = (GbpBuildWorkbenchAddin *)addin;
+ IdePerspective *editor;
+ GtkWidget *pane;
+ IdeContext *context;
+ IdeDeviceManager *device_manager;
+ IdeDevice *device;
+
+ g_assert (IDE_IS_WORKBENCH_ADDIN (addin));
+ g_assert (GBP_IS_BUILD_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_WORKBENCH (workbench));
+
+ self->workbench = workbench;
+
+ context = ide_workbench_get_context (workbench);
+ device_manager = ide_context_get_device_manager (context);
+ device = ide_device_manager_get_device (device_manager, "local");
+
+ editor = ide_workbench_get_perspective_by_name (workbench, "editor");
+ pane = ide_layout_get_right_pane (IDE_LAYOUT (editor));
+ self->panel = g_object_new (GBP_TYPE_BUILD_PANEL,
+ "device", device,
+ "device-manager", device_manager,
+ "visible", TRUE,
+ NULL);
+ ide_layout_pane_add_page (IDE_LAYOUT_PANE (pane),
+ GTK_WIDGET (self->panel),
+ _("Build"), NULL);
+
+ gtk_widget_insert_action_group (GTK_WIDGET (workbench), "build-tools",
+ G_ACTION_GROUP (self->actions));
+
+ g_object_bind_property (self, "result", self->panel, "result", 0);
+ g_object_bind_property (self, "device", self->panel, "device", 0);
+
+ gbp_build_workbench_addin_set_device (self, device);
+}
+
+static void
+gbp_build_workbench_addin_unload (IdeWorkbenchAddin *addin,
+ IdeWorkbench *workbench)
+{
+ GbpBuildWorkbenchAddin *self = (GbpBuildWorkbenchAddin *)addin;
+ IdePerspective *editor;
+ GtkWidget *pane;
+
+ g_assert (IDE_IS_WORKBENCH_ADDIN (addin));
+ g_assert (GBP_IS_BUILD_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_WORKBENCH (workbench));
+
+ if (self->cancellable)
+ g_cancellable_cancel (self->cancellable);
+
+ g_clear_object (&self->cancellable);
+
+ gtk_widget_insert_action_group (GTK_WIDGET (workbench), "build-tools", NULL);
+
+ editor = ide_workbench_get_perspective_by_name (workbench, "editor");
+ pane = ide_layout_get_right_pane (IDE_LAYOUT (editor));
+ ide_layout_pane_remove_page (IDE_LAYOUT_PANE (pane), GTK_WIDGET (self->panel));
+}
+
+static void
+gbp_build_workbench_addin_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpBuildWorkbenchAddin *self = GBP_BUILD_WORKBENCH_ADDIN(object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE:
+ g_value_set_object (value, self->device);
+ break;
+
+ case PROP_RESULT:
+ g_value_set_object (value, self->result);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_build_workbench_addin_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpBuildWorkbenchAddin *self = GBP_BUILD_WORKBENCH_ADDIN(object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE:
+ gbp_build_workbench_addin_set_device (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_build_workbench_addin_finalize (GObject *object)
+{
+ GbpBuildWorkbenchAddin *self = (GbpBuildWorkbenchAddin *)object;
+
+ g_clear_object (&self->device);
+ g_clear_object (&self->bindings);
+ g_clear_object (&self->actions);
+ g_clear_object (&self->result);
+ g_clear_object (&self->cancellable);
+
+ G_OBJECT_CLASS (gbp_build_workbench_addin_parent_class)->finalize (object);
+}
+
+static void
+gbp_build_workbench_addin_class_init (GbpBuildWorkbenchAddinClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gbp_build_workbench_addin_finalize;
+ object_class->get_property = gbp_build_workbench_addin_get_property;
+ object_class->set_property = gbp_build_workbench_addin_set_property;
+
+ properties [PROP_DEVICE] =
+ g_param_spec_object ("device",
+ "Device",
+ "The device the build is for",
+ IDE_TYPE_DEVICE,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_RESULT] =
+ g_param_spec_object ("result",
+ "Result",
+ "The current build result",
+ IDE_TYPE_BUILD_RESULT,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, LAST_PROP, properties);
+}
+
+static void
+gbp_build_workbench_addin_init (GbpBuildWorkbenchAddin *self)
+{
+ gint i;
+ static const struct {
+ const gchar *property;
+ const gchar *action;
+ GBindingFlags flags;
+ } bindings[] = {
+ { "running", "build", G_BINDING_INVERT_BOOLEAN },
+ { "running", "rebuild", G_BINDING_INVERT_BOOLEAN },
+ { "running", "clean", G_BINDING_INVERT_BOOLEAN },
+ { "running", "cancel", 0 },
+ { "running", "deploy", G_BINDING_INVERT_BOOLEAN },
+ { "running", "export", G_BINDING_INVERT_BOOLEAN },
+ { NULL }
+ };
+
+ self->actions = g_simple_action_group_new ();
+ g_action_map_add_action_entries (G_ACTION_MAP (self->actions),
+ actions, G_N_ELEMENTS (actions),
+ self);
+
+ self->bindings = egg_binding_group_new ();
+
+ for (i = 0; bindings [i].property; i++)
+ {
+ GActionMap *map = G_ACTION_MAP (self->actions);
+ GAction *action;
+
+ action = g_action_map_lookup_action (map, bindings [i].action);
+ egg_binding_group_bind (self->bindings, bindings [i].property,
+ action, "enabled",
+ G_BINDING_SYNC_CREATE | bindings [i].flags);
+ }
+}
+
+static void
+workbench_addin_iface_init (IdeWorkbenchAddinInterface *iface)
+{
+ iface->load = gbp_build_workbench_addin_load;
+ iface->unload = gbp_build_workbench_addin_unload;
+}
diff --git a/plugins/build-tools/gbp-build-workbench-addin.h b/plugins/build-tools/gbp-build-workbench-addin.h
new file mode 100644
index 0000000..3b3d748
--- /dev/null
+++ b/plugins/build-tools/gbp-build-workbench-addin.h
@@ -0,0 +1,29 @@
+/* gbp-build-workbench-addin.h
+ *
+ * Copyright (C) 2015 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/>.
+ */
+
+#pragma once
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_BUILD_WORKBENCH_ADDIN (gbp_build_workbench_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpBuildWorkbenchAddin, gbp_build_workbench_addin, GBP, BUILD_WORKBENCH_ADDIN, GObject)
+
+G_END_DECLS
diff --git a/plugins/build-tools/gtk/menus.ui b/plugins/build-tools/gtk/menus.ui
new file mode 100644
index 0000000..cb73794
--- /dev/null
+++ b/plugins/build-tools/gtk/menus.ui
@@ -0,0 +1,2 @@
+<interface>
+</interface>
diff --git a/plugins/build-tools/theme/shared.css b/plugins/build-tools/theme/shared.css
new file mode 100644
index 0000000..272cdb0
--- /dev/null
+++ b/plugins/build-tools/theme/shared.css
@@ -0,0 +1,19 @@
+buildpanel button.popup:active,
+buildpanel button.popup:checked,
+buildpanel button.popup {
+ background-image: none;
+ background-color: transparent;
+ box-shadow: none;
+ border-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+list.buildpanel row {
+ padding: 10px;
+ border-bottom: 1px solid @borders;
+}
+
+list.buildpanel row:last-child {
+ border-bottom: none;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]