[gnome-builder/wip/gtk4-port] plugins/buildui: show errors and warnings in status popover
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/gtk4-port] plugins/buildui: show errors and warnings in status popover
- Date: Fri, 20 May 2022 21:39:47 +0000 (UTC)
commit 02eab61a7b96444c219f4195475077d9a2db7f60
Author: Christian Hergert <chergert redhat com>
Date: Fri May 20 14:38:26 2022 -0700
plugins/buildui: show errors and warnings in status popover
src/plugins/buildui/buildui.gresource.xml | 2 +
.../buildui/gbp-buildui-status-indicator.ui | 14 +-
.../buildui/gbp-buildui-status-popover-row.ui | 45 ++++
src/plugins/buildui/gbp-buildui-status-popover.c | 241 +++++++++++++++++++++
src/plugins/buildui/gbp-buildui-status-popover.h | 35 +++
src/plugins/buildui/gbp-buildui-status-popover.ui | 114 ++++++++++
src/plugins/buildui/gbp-buildui-workspace-addin.c | 9 +-
src/plugins/buildui/meson.build | 1 +
8 files changed, 453 insertions(+), 8 deletions(-)
---
diff --git a/src/plugins/buildui/buildui.gresource.xml b/src/plugins/buildui/buildui.gresource.xml
index 66bb58b38..747861b34 100644
--- a/src/plugins/buildui/buildui.gresource.xml
+++ b/src/plugins/buildui/buildui.gresource.xml
@@ -7,6 +7,8 @@
<file preprocess="xml-stripblanks">gbp-buildui-pane.ui</file>
<file preprocess="xml-stripblanks">gbp-buildui-stage-row.ui</file>
<file preprocess="xml-stripblanks">gbp-buildui-status-indicator.ui</file>
+ <file preprocess="xml-stripblanks">gbp-buildui-status-popover.ui</file>
+ <file preprocess="xml-stripblanks">gbp-buildui-status-popover-row.ui</file>
<file preprocess="xml-stripblanks">gbp-buildui-targets-dialog.ui</file>
<file preprocess="xml-stripblanks">gtk/menus.ui</file>
</gresource>
diff --git a/src/plugins/buildui/gbp-buildui-status-indicator.ui
b/src/plugins/buildui/gbp-buildui-status-indicator.ui
index 730d8398f..58d942aa0 100644
--- a/src/plugins/buildui/gbp-buildui-status-indicator.ui
+++ b/src/plugins/buildui/gbp-buildui-status-indicator.ui
@@ -9,13 +9,16 @@
<property name="spacing">3</property>
<child>
<object class="GtkImage">
- <property name="icon-name">dialog-warning-symbolic</property>
+ <property name="icon-name">dialog-error-symbolic</property>
<property name="pixel-size">12</property>
</object>
</child>
<child>
- <object class="GtkLabel" id="warning_label">
+ <object class="GtkLabel" id="error_label">
<property name="label">0</property>
+ <attributes>
+ <attribute name="font-features" value="tnum"/>
+ </attributes>
</object>
</child>
</object>
@@ -25,13 +28,16 @@
<property name="spacing">3</property>
<child>
<object class="GtkImage">
- <property name="icon-name">dialog-error-symbolic</property>
+ <property name="icon-name">dialog-warning-symbolic</property>
<property name="pixel-size">12</property>
</object>
</child>
<child>
- <object class="GtkLabel" id="error_label">
+ <object class="GtkLabel" id="warning_label">
<property name="label">0</property>
+ <attributes>
+ <attribute name="font-features" value="tnum"/>
+ </attributes>
</object>
</child>
</object>
diff --git a/src/plugins/buildui/gbp-buildui-status-popover-row.ui
b/src/plugins/buildui/gbp-buildui-status-popover-row.ui
new file mode 100644
index 000000000..ca4af3f55
--- /dev/null
+++ b/src/plugins/buildui/gbp-buildui-status-popover-row.ui
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkListItem">
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin-top">3</property>
+ <property name="margin-bottom">3</property>
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">start</property>
+ <property name="hexpand">true</property>
+ <property name="ellipsize">start</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <binding name="label">
+ <lookup name="title" type="IdeLocation">
+ <lookup name="location" type="IdeDiagnostic">
+ <lookup name="item">GtkListItem</lookup>
+ </lookup>
+ </lookup>
+ </binding>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">start</property>
+ <property name="hexpand">true</property>
+ <property name="wrap">true</property>
+ <binding name="label">
+ <lookup name="text" type="IdeDiagnostic">
+ <lookup name="item">GtkListItem</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </child>
+ </object>
+ </property>
+ </template>
+</interface>
+
diff --git a/src/plugins/buildui/gbp-buildui-status-popover.c
b/src/plugins/buildui/gbp-buildui-status-popover.c
new file mode 100644
index 000000000..401bdf428
--- /dev/null
+++ b/src/plugins/buildui/gbp-buildui-status-popover.c
@@ -0,0 +1,241 @@
+/* gbp-buildui-status-popover.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-buildui-status-popover"
+
+#include "config.h"
+
+#include <libide-editor.h>
+#include <libide-foundry.h>
+#include <libide-gui.h>
+
+#include "gbp-buildui-status-popover.h"
+
+struct _GbpBuilduiStatusPopover
+{
+ GtkPopover parent_instance;
+
+ /* Owned references */
+ IdeSignalGroup *pipeline_signals;
+ GHashTable *deduplicator;
+ GtkCustomFilter *error_filter;
+ GtkCustomFilter *warning_filter;
+
+ /* Template references */
+ GListStore *diagnostics;
+};
+
+G_DEFINE_FINAL_TYPE (GbpBuilduiStatusPopover, gbp_buildui_status_popover, GTK_TYPE_POPOVER)
+
+static void
+gbp_buildui_status_popover_clear (GbpBuilduiStatusPopover *self)
+{
+ g_assert (GBP_IS_BUILDUI_STATUS_POPOVER (self));
+
+ if (self->diagnostics != NULL)
+ g_list_store_remove_all (self->diagnostics);
+
+ if (self->deduplicator != NULL)
+ g_hash_table_remove_all (self->deduplicator);
+}
+
+static void
+gbp_buildui_status_popover_add_diagnsotic (GbpBuilduiStatusPopover *self,
+ IdeDiagnostic *diagnostic,
+ IdePipeline *pipeline)
+{
+ g_assert (GBP_IS_BUILDUI_STATUS_POPOVER (self));
+ g_assert (IDE_IS_DIAGNOSTIC (diagnostic));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+
+ if (g_hash_table_contains (self->deduplicator, diagnostic))
+ return;
+
+ g_hash_table_insert (self->deduplicator, g_object_ref (diagnostic), NULL);
+ g_list_store_insert_sorted (self->diagnostics,
+ diagnostic,
+ (GCompareDataFunc)ide_diagnostic_compare,
+ NULL);
+}
+
+static void
+gbp_buildui_status_popover_bind_pipeline (GbpBuilduiStatusPopover *self,
+ IdePipeline *pipeline,
+ IdeSignalGroup *signal_group)
+{
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_BUILDUI_STATUS_POPOVER (self));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+ g_assert (IDE_IS_SIGNAL_GROUP (signal_group));
+
+ gbp_buildui_status_popover_clear (self);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_buildui_status_popover_unbind_pipeline (GbpBuilduiStatusPopover *self,
+ IdeSignalGroup *signal_group)
+{
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_BUILDUI_STATUS_POPOVER (self));
+ g_assert (IDE_IS_SIGNAL_GROUP (signal_group));
+
+ IDE_EXIT;
+}
+
+static void
+gbp_buildui_status_popover_activate_cb (GbpBuilduiStatusPopover *self,
+ guint item_position,
+ GtkListView *list_view)
+{
+ g_autoptr(IdePanelPosition) position = NULL;
+ g_autoptr(IdeDiagnostic) diagnostic = NULL;
+ IdeWorkspace *workspace;
+ IdeLocation *location;
+ GListModel *model;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_BUILDUI_STATUS_POPOVER (self));
+ g_assert (GTK_IS_LIST_VIEW (list_view));
+
+ if (!(model = G_LIST_MODEL (gtk_list_view_get_model (list_view))) ||
+ !(diagnostic = g_list_model_get_item (model, item_position)) ||
+ !IDE_IS_DIAGNOSTIC (diagnostic) ||
+ !(location = ide_diagnostic_get_location (diagnostic)))
+ IDE_EXIT;
+
+ workspace = ide_widget_get_workspace (GTK_WIDGET (self));
+ position = ide_panel_position_new ();
+ ide_editor_focus_location (workspace, position, location);
+
+ gtk_popover_popdown (GTK_POPOVER (self));
+
+ IDE_EXIT;
+}
+
+static gboolean
+is_warning (gpointer data,
+ gpointer user_data)
+{
+ return ide_diagnostic_get_severity (data) == IDE_DIAGNOSTIC_WARNING;
+}
+
+static gboolean
+is_error (gpointer data,
+ gpointer user_data)
+{
+ return ide_diagnostic_get_severity (data) == IDE_DIAGNOSTIC_ERROR;
+}
+
+static void
+gbp_buildui_status_popover_dispose (GObject *object)
+{
+ GbpBuilduiStatusPopover *self = (GbpBuilduiStatusPopover *)object;
+
+ g_clear_object (&self->pipeline_signals);
+
+ G_OBJECT_CLASS (gbp_buildui_status_popover_parent_class)->dispose (object);
+}
+
+static void
+gbp_buildui_status_popover_class_init (GbpBuilduiStatusPopoverClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = gbp_buildui_status_popover_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/plugins/buildui/gbp-buildui-status-popover.ui");
+ gtk_widget_class_bind_template_child (widget_class, GbpBuilduiStatusPopover, diagnostics);
+ gtk_widget_class_bind_template_child (widget_class, GbpBuilduiStatusPopover, error_filter);
+ gtk_widget_class_bind_template_child (widget_class, GbpBuilduiStatusPopover, warning_filter);
+ gtk_widget_class_bind_template_callback (widget_class, gbp_buildui_status_popover_activate_cb);
+
+ g_type_ensure (IDE_TYPE_DIAGNOSTIC);
+ g_type_ensure (IDE_TYPE_LOCATION);
+}
+
+static void
+gbp_buildui_status_popover_init (GbpBuilduiStatusPopover *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_custom_filter_set_filter_func (self->warning_filter, is_warning, NULL, NULL);
+ gtk_custom_filter_set_filter_func (self->error_filter, is_error, NULL, NULL);
+
+ self->deduplicator = g_hash_table_new_full ((GHashFunc)ide_diagnostic_hash,
+ (GEqualFunc)ide_diagnostic_equal,
+ g_object_unref,
+ NULL);
+ self->pipeline_signals = ide_signal_group_new (IDE_TYPE_PIPELINE);
+ g_signal_connect_object (self->pipeline_signals,
+ "bind",
+ G_CALLBACK (gbp_buildui_status_popover_bind_pipeline),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->pipeline_signals,
+ "unbind",
+ G_CALLBACK (gbp_buildui_status_popover_unbind_pipeline),
+ self,
+ G_CONNECT_SWAPPED);
+ ide_signal_group_connect_object (self->pipeline_signals,
+ "diagnostic",
+ G_CALLBACK (gbp_buildui_status_popover_add_diagnsotic),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+static void
+gbp_buildui_status_popover_connect (GbpBuilduiStatusPopover *self,
+ IdeContext *context)
+{
+ IdeBuildManager *build_manager;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_BUILDUI_STATUS_POPOVER (self));
+ g_assert (IDE_IS_CONTEXT (context));
+
+ build_manager = ide_build_manager_from_context (context);
+ g_assert (IDE_IS_BUILD_MANAGER (build_manager));
+
+ g_object_bind_property (build_manager, "pipeline",
+ self->pipeline_signals, "target",
+ G_BINDING_SYNC_CREATE);
+
+ IDE_EXIT;
+}
+
+GbpBuilduiStatusPopover *
+gbp_buildui_status_popover_new (IdeContext *context)
+{
+ GbpBuilduiStatusPopover *self;
+
+ g_return_val_if_fail (IDE_IS_CONTEXT (context), NULL);
+
+ self = g_object_new (GBP_TYPE_BUILDUI_STATUS_POPOVER, NULL);
+ gbp_buildui_status_popover_connect (self, context);
+
+ return self;
+}
diff --git a/src/plugins/buildui/gbp-buildui-status-popover.h
b/src/plugins/buildui/gbp-buildui-status-popover.h
new file mode 100644
index 000000000..c12543f28
--- /dev/null
+++ b/src/plugins/buildui/gbp-buildui-status-popover.h
@@ -0,0 +1,35 @@
+/* gbp-buildui-status-popover.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <libide-core.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_BUILDUI_STATUS_POPOVER (gbp_buildui_status_popover_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpBuilduiStatusPopover, gbp_buildui_status_popover, GBP, BUILDUI_STATUS_POPOVER,
GtkPopover)
+
+GbpBuilduiStatusPopover *gbp_buildui_status_popover_new (IdeContext *context);
+
+G_END_DECLS
diff --git a/src/plugins/buildui/gbp-buildui-status-popover.ui
b/src/plugins/buildui/gbp-buildui-status-popover.ui
new file mode 100644
index 000000000..a3d02bb53
--- /dev/null
+++ b/src/plugins/buildui/gbp-buildui-status-popover.ui
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GbpBuilduiStatusPopover" parent="GtkPopover">
+ <property name="width-request">400</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkStackSwitcher">
+ <property name="stack">stack</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkFrame">
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="hhomogeneous">false</property>
+ <property name="vhomogeneous">false</property>
+ <property name="transition-duration">200</property>
+ <property name="transition-type">crossfade</property>
+ <child>
+ <object class="GtkStackPage">
+ <property name="title" translatable="yes">_Errors</property>
+ <property name="use-underline">true</property>
+ <property name="name">errors</property>
+ <property name="child">
+ <object class="GtkScrolledWindow">
+ <property name="has-frame">true</property>
+ <property name="propagate-natural-height">true</property>
+ <property name="propagate-natural-width">true</property>
+ <property name="min-content-height">300</property>
+ <property name="max-content-height">600</property>
+ <property name="min-content-width">400</property>
+ <property name="max-content-width">400</property>
+ <child>
+ <object class="GtkListView">
+ <signal name="activate" handler="gbp_buildui_status_popover_activate_cb"
swapped="true" object="GbpBuilduiStatusPopover"/>
+ <property name="orientation">vertical</property>
+ <property name="single-click-activate">True</property>
+ <property name="factory">
+ <object class="GtkBuilderListItemFactory">
+ <property
name="resource">/plugins/buildui/gbp-buildui-status-popover-row.ui</property>
+ </object>
+ </property>
+ <property name="model">
+ <object class="GtkNoSelection">
+ <property name="model">
+ <object class="GtkFilterListModel">
+ <property name="model">diagnostics</property>
+ <property name="filter">error_filter</property>
+ </object>
+ </property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStackPage">
+ <property name="title" translatable="yes">_Warnings</property>
+ <property name="use-underline">true</property>
+ <property name="name">warnings</property>
+ <property name="child">
+ <object class="GtkScrolledWindow">
+ <property name="has-frame">true</property>
+ <property name="propagate-natural-height">true</property>
+ <property name="propagate-natural-width">true</property>
+ <property name="min-content-height">300</property>
+ <property name="max-content-height">600</property>
+ <property name="min-content-width">400</property>
+ <property name="max-content-width">400</property>
+ <child>
+ <object class="GtkListView">
+ <signal name="activate" handler="gbp_buildui_status_popover_activate_cb"
swapped="true" object="GbpBuilduiStatusPopover"/>
+ <property name="orientation">vertical</property>
+ <property name="single-click-activate">True</property>
+ <property name="factory">
+ <object class="GtkBuilderListItemFactory">
+ <property
name="resource">/plugins/buildui/gbp-buildui-status-popover-row.ui</property>
+ </object>
+ </property>
+ <property name="model">
+ <object class="GtkNoSelection">
+ <property name="model">
+ <object class="GtkFilterListModel">
+ <property name="model">diagnostics</property>
+ <property name="filter">warning_filter</property>
+ </object>
+ </property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GListStore" id="diagnostics">
+ <property name="item-type">IdeDiagnostic</property>
+ </object>
+ <object class="GtkCustomFilter" id="warning_filter"/>
+ <object class="GtkCustomFilter" id="error_filter"/>
+</interface>
diff --git a/src/plugins/buildui/gbp-buildui-workspace-addin.c
b/src/plugins/buildui/gbp-buildui-workspace-addin.c
index 2339b197b..654540e8a 100644
--- a/src/plugins/buildui/gbp-buildui-workspace-addin.c
+++ b/src/plugins/buildui/gbp-buildui-workspace-addin.c
@@ -31,6 +31,7 @@
#include "gbp-buildui-omni-bar-section.h"
#include "gbp-buildui-pane.h"
#include "gbp-buildui-status-indicator.h"
+#include "gbp-buildui-status-popover.h"
#include "gbp-buildui-targets-dialog.h"
#include "gbp-buildui-workspace-addin.h"
@@ -48,7 +49,6 @@ struct _GbpBuilduiWorkspaceAddin
GtkLabel *error_label;
GtkImage *warning_image;
GtkLabel *warning_label;
- GbpBuilduiStatusIndicator *status_indicator;
GtkMenuButton *status_button;
/* Owned references */
@@ -267,9 +267,11 @@ gbp_buildui_workspace_addin_load (IdeWorkspaceAddin *addin,
build_manager = ide_build_manager_from_context (context);
statusbar = ide_workspace_get_statusbar (workspace);
- self->status_indicator = gbp_buildui_status_indicator_new (context);
self->status_button = g_object_new (GTK_TYPE_MENU_BUTTON,
- "child", self->status_indicator,
+ "child", gbp_buildui_status_indicator_new (context),
+ "popover", gbp_buildui_status_popover_new (context),
+ "direction", GTK_ARROW_UP,
+ "focus-on-click", FALSE,
NULL);
panel_statusbar_add_prefix (statusbar, 1000, GTK_WIDGET (self->status_button));
@@ -394,7 +396,6 @@ gbp_buildui_workspace_addin_unload (IdeWorkspaceAddin *addin,
statusbar = ide_workspace_get_statusbar (workspace);
panel_statusbar_remove (statusbar, GTK_WIDGET (self->status_button));
self->status_button = NULL;
- self->status_indicator = NULL;
for (guint i = 0; i < G_N_ELEMENTS (actions); i++)
g_action_map_remove_action (G_ACTION_MAP (workspace), actions[i].name);
diff --git a/src/plugins/buildui/meson.build b/src/plugins/buildui/meson.build
index cf90b69e8..0cb5fed4b 100644
--- a/src/plugins/buildui/meson.build
+++ b/src/plugins/buildui/meson.build
@@ -10,6 +10,7 @@ plugins_sources += files([
'gbp-buildui-runtime-row.c',
'gbp-buildui-stage-row.c',
'gbp-buildui-status-indicator.c',
+ 'gbp-buildui-status-popover.c',
'gbp-buildui-targets-dialog.c',
'gbp-buildui-tree-addin.c',
'gbp-buildui-workspace-addin.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]