[epiphany] Add EphyDataDialog
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany] Add EphyDataDialog
- Date: Fri, 17 Jan 2020 16:52:11 +0000 (UTC)
commit fa64698731653082b6734cb9c31f5abb3731e59a
Author: Adrien Plazas <kekun plazas laposte net>
Date: Tue Jun 25 09:01:11 2019 +0200
Add EphyDataDialog
src/ephy-data-dialog.c | 584 +++++++++++++++++++++++++++++++++++
src/ephy-data-dialog.h | 58 ++++
src/meson.build | 1 +
src/resources/epiphany.gresource.xml | 1 +
src/resources/gtk/data-dialog.ui | 269 ++++++++++++++++
5 files changed, 913 insertions(+)
---
diff --git a/src/ephy-data-dialog.c b/src/ephy-data-dialog.c
new file mode 100644
index 000000000..a70145c12
--- /dev/null
+++ b/src/ephy-data-dialog.c
@@ -0,0 +1,584 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2019 Purism SPC
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany 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.
+ *
+ * Epiphany 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 Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "ephy-data-dialog.h"
+
+#include <ctype.h>
+#include <glib/gi18n.h>
+#define HANDY_USE_UNSTABLE_API
+#include <handy.h>
+
+typedef struct {
+ GtkWidget *box;
+ GtkWidget *child;
+ GtkWidget *clear_all_button;
+ GtkWidget *search_bar;
+ GtkWidget *search_entry;
+ GtkWidget *search_button;
+ GtkWidget *stack;
+ GtkWidget *empty_title_label;
+ GtkWidget *empty_description_label;
+ GtkWidget *spinner;
+
+ gboolean is_loading : 1;
+ gboolean has_data : 1;
+ gboolean has_search_results : 1;
+ gboolean can_clear : 1;
+ char *search_text;
+} EphyDataDialogPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (EphyDataDialog, ephy_data_dialog, GTK_TYPE_WINDOW)
+
+enum {
+ PROP_0,
+ PROP_CLEAR_ALL_ACTION_NAME,
+ PROP_CLEAR_ALL_ACTION_TARGET,
+ PROP_CLEAR_ALL_DESCRIPTION,
+ PROP_SEARCH_DESCRIPTION,
+ PROP_EMPTY_TITLE,
+ PROP_EMPTY_DESCRIPTION,
+ PROP_SEARCH_TEXT,
+ PROP_IS_LOADING,
+ PROP_HAS_DATA,
+ PROP_HAS_SEARCH_RESULTS,
+ PROP_CAN_CLEAR,
+ LAST_PROP,
+};
+
+static GParamSpec *obj_properties[LAST_PROP];
+
+enum {
+ CLEAR_ALL_CLICKED,
+ LAST_SIGNAL,
+};
+
+static gint signals[LAST_SIGNAL] = { 0 };
+
+static void
+update (EphyDataDialog *self)
+{
+ EphyDataDialogPrivate *priv = ephy_data_dialog_get_instance_private (self);
+ gboolean has_data = priv->has_data && priv->child && gtk_widget_get_visible (priv->child);
+
+ if (priv->is_loading) {
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->stack), "loading");
+ gtk_spinner_start (GTK_SPINNER (priv->spinner));
+ } else {
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->search_button))) {
+ if (has_data && priv->has_search_results)
+ gtk_stack_set_visible_child (GTK_STACK (priv->stack), priv->child);
+ else
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->stack), "no-results");
+ } else {
+ if (has_data)
+ gtk_stack_set_visible_child (GTK_STACK (priv->stack), priv->child);
+ else
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->stack), "empty");
+ }
+ gtk_spinner_stop (GTK_SPINNER (priv->spinner));
+ }
+
+ gtk_widget_set_sensitive (priv->clear_all_button, has_data && priv->can_clear);
+ gtk_widget_set_sensitive (priv->search_button, has_data);
+}
+
+static void
+on_clear_all_button_clicked (EphyDataDialog *self)
+{
+ g_signal_emit (self, signals[CLEAR_ALL_CLICKED], 0);
+}
+
+static void
+on_search_entry_changed (GtkSearchEntry *entry,
+ EphyDataDialog *self)
+{
+ EphyDataDialogPrivate *priv = ephy_data_dialog_get_instance_private (self);
+ const char *text;
+
+ text = gtk_entry_get_text (GTK_ENTRY (entry));
+ g_free (priv->search_text);
+ priv->search_text = g_strdup (text);
+
+ g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_SEARCH_TEXT]);
+}
+
+static gboolean
+on_key_press_event (EphyDataDialog *self,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ EphyDataDialogPrivate *priv = ephy_data_dialog_get_instance_private (self);
+ GdkEventKey *key = (GdkEventKey *)event;
+ gint result;
+
+ result = hdy_search_bar_handle_event (HDY_SEARCH_BAR (priv->search_bar), event);
+
+ if (result == GDK_EVENT_STOP)
+ return result;
+
+ if (key->keyval == GDK_KEY_Escape) {
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->search_button)))
+ gtk_widget_destroy (GTK_WIDGET (self));
+ else
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->search_button), FALSE);
+ } else if (isprint (key->keyval))
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->search_button), TRUE);
+
+ return result;
+}
+
+static void
+ephy_data_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphyDataDialog *self = EPHY_DATA_DIALOG (object);
+ EphyDataDialogPrivate *priv = ephy_data_dialog_get_instance_private (self);
+
+ switch (prop_id) {
+ case PROP_CLEAR_ALL_ACTION_NAME:
+ gtk_actionable_set_action_name (GTK_ACTIONABLE (priv->clear_all_button), g_value_get_string (value));
+ break;
+ case PROP_CLEAR_ALL_ACTION_TARGET:
+ gtk_actionable_set_action_target_value (GTK_ACTIONABLE (priv->clear_all_button), g_value_get_variant
(value));
+ break;
+ case PROP_CLEAR_ALL_DESCRIPTION:
+ ephy_data_dialog_set_clear_all_description (self, g_value_get_string (value));
+ break;
+ case PROP_SEARCH_DESCRIPTION:
+ gtk_entry_set_placeholder_text (GTK_ENTRY (priv->search_entry), g_value_get_string (value));
+ atk_object_set_description (gtk_widget_get_accessible (GTK_WIDGET (self)), g_value_get_string (value));
+ break;
+ case PROP_EMPTY_TITLE:
+ gtk_label_set_text (GTK_LABEL (priv->empty_title_label), g_value_get_string (value));
+ break;
+ case PROP_EMPTY_DESCRIPTION:
+ gtk_label_set_text (GTK_LABEL (priv->empty_description_label), g_value_get_string (value));
+ break;
+ case PROP_IS_LOADING:
+ ephy_data_dialog_set_is_loading (self, g_value_get_boolean (value));
+ break;
+ case PROP_HAS_DATA:
+ ephy_data_dialog_set_has_data (self, g_value_get_boolean (value));
+ break;
+ case PROP_HAS_SEARCH_RESULTS:
+ ephy_data_dialog_set_has_search_results (self, g_value_get_boolean (value));
+ break;
+ case PROP_CAN_CLEAR:
+ ephy_data_dialog_set_can_clear (self, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ephy_data_dialog_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphyDataDialog *self = EPHY_DATA_DIALOG (object);
+ EphyDataDialogPrivate *priv = ephy_data_dialog_get_instance_private (self);
+
+ switch (prop_id) {
+ case PROP_CLEAR_ALL_ACTION_NAME:
+ g_value_set_string (value, gtk_actionable_get_action_name (GTK_ACTIONABLE (priv->clear_all_button)));
+ break;
+ case PROP_CLEAR_ALL_ACTION_TARGET:
+ g_value_set_variant (value, gtk_actionable_get_action_target_value (GTK_ACTIONABLE
(priv->clear_all_button)));
+ break;
+ case PROP_CLEAR_ALL_DESCRIPTION:
+ g_value_set_string (value, ephy_data_dialog_get_clear_all_description (self));
+ break;
+ case PROP_SEARCH_DESCRIPTION:
+ g_value_set_string (value, gtk_entry_get_placeholder_text (GTK_ENTRY (priv->search_entry)));
+ break;
+ case PROP_EMPTY_TITLE:
+ g_value_set_string (value, gtk_label_get_text (GTK_LABEL (priv->empty_title_label)));
+ break;
+ case PROP_EMPTY_DESCRIPTION:
+ g_value_set_string (value, gtk_label_get_text (GTK_LABEL (priv->empty_description_label)));
+ break;
+ case PROP_SEARCH_TEXT:
+ g_value_set_string (value, ephy_data_dialog_get_search_text (self));
+ break;
+ case PROP_IS_LOADING:
+ g_value_set_boolean (value, ephy_data_dialog_get_is_loading (self));
+ break;
+ case PROP_HAS_DATA:
+ g_value_set_boolean (value, ephy_data_dialog_get_has_data (self));
+ break;
+ case PROP_HAS_SEARCH_RESULTS:
+ g_value_set_boolean (value, ephy_data_dialog_get_has_search_results (self));
+ break;
+ case PROP_CAN_CLEAR:
+ g_value_set_boolean (value, ephy_data_dialog_get_can_clear (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ephy_data_dialog_finalize (GObject *object)
+{
+ EphyDataDialog *self = EPHY_DATA_DIALOG (object);
+ EphyDataDialogPrivate *priv = ephy_data_dialog_get_instance_private (self);
+
+ g_free (priv->search_text);
+
+ G_OBJECT_CLASS (ephy_data_dialog_parent_class)->finalize (object);
+}
+
+static void
+ephy_data_dialog_add (GtkContainer *container,
+ GtkWidget *child)
+{
+ EphyDataDialog *self = EPHY_DATA_DIALOG (container);
+ EphyDataDialogPrivate *priv = ephy_data_dialog_get_instance_private (self);
+
+ if (!priv->box) {
+ GTK_CONTAINER_CLASS (ephy_data_dialog_parent_class)->add (container, child);
+ return;
+ }
+
+ g_assert (!priv->child);
+
+ priv->child = child;
+ gtk_container_add (GTK_CONTAINER (priv->stack), child);
+
+ update (self);
+}
+
+static void
+ephy_data_dialog_class_init (EphyDataDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+
+ object_class->set_property = ephy_data_dialog_set_property;
+ object_class->get_property = ephy_data_dialog_get_property;
+ object_class->finalize = ephy_data_dialog_finalize;
+
+ container_class->add = ephy_data_dialog_add;
+
+ obj_properties[PROP_CLEAR_ALL_ACTION_NAME] =
+ g_param_spec_string ("clear-all-action-name",
+ _("'Clear all' action name"),
+ _("The name of the action associated to the 'Clear all' button"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_CLEAR_ALL_ACTION_TARGET] =
+ g_param_spec_variant ("clear-all-action-target",
+ _("'Clear all' action target value"),
+ _("The parameter for 'Clear all' action invocations"),
+ G_VARIANT_TYPE_ANY, NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_CLEAR_ALL_DESCRIPTION] =
+ g_param_spec_string ("clear-all-description",
+ _("'Clear all' description"),
+ _("The description of the 'Clear all' action"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_SEARCH_DESCRIPTION] =
+ g_param_spec_string ("search-description",
+ _("'Search' description"),
+ _("The description of the 'Search' action"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_EMPTY_TITLE] =
+ g_param_spec_string ("empty-title",
+ _("'Empty' title"),
+ _("The title of the 'Empty' state page"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_EMPTY_DESCRIPTION] =
+ g_param_spec_string ("empty-description",
+ _("'Empty' description"),
+ _("The description of the 'Empty' state page"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_SEARCH_TEXT] =
+ g_param_spec_string ("search-text",
+ _("Search text"),
+ _("The text of the search entry"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_IS_LOADING] =
+ g_param_spec_boolean ("is-loading",
+ _("Is loading"),
+ _("Whether the dialog is loading its data"),
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_HAS_DATA] =
+ g_param_spec_boolean ("has-data",
+ _("Has data"),
+ _("Whether the dialog has data"),
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_HAS_SEARCH_RESULTS] =
+ g_param_spec_boolean ("has-search-results",
+ _("Has search results"),
+ _("Whether the dialog has search results"),
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_CAN_CLEAR] =
+ g_param_spec_boolean ("can-clear",
+ _("Can clear"),
+ _("Whether the data can be cleared"),
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+
+ /**
+ * EphyLocationEntry::user-changed:
+ * @entry: the object on which the signal is emitted
+ *
+ * Emitted when the user changes the contents of the internal #GtkEntry
+ *
+ */
+ signals[CLEAR_ALL_CLICKED] =
+ g_signal_new ("clear-all-clicked",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 0,
+ G_TYPE_NONE);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/epiphany/gtk/data-dialog.ui");
+ gtk_widget_class_bind_template_child_private (widget_class, EphyDataDialog, box);
+ gtk_widget_class_bind_template_child_private (widget_class, EphyDataDialog, clear_all_button);
+ gtk_widget_class_bind_template_child_private (widget_class, EphyDataDialog, empty_title_label);
+ gtk_widget_class_bind_template_child_private (widget_class, EphyDataDialog, empty_description_label);
+ gtk_widget_class_bind_template_child_private (widget_class, EphyDataDialog, search_bar);
+ gtk_widget_class_bind_template_child_private (widget_class, EphyDataDialog, search_button);
+ gtk_widget_class_bind_template_child_private (widget_class, EphyDataDialog, search_entry);
+ gtk_widget_class_bind_template_child_private (widget_class, EphyDataDialog, spinner);
+ gtk_widget_class_bind_template_child_private (widget_class, EphyDataDialog, stack);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_key_press_event);
+ gtk_widget_class_bind_template_callback (widget_class, on_clear_all_button_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, on_search_entry_changed);
+}
+
+static void
+ephy_data_dialog_init (EphyDataDialog *self)
+{
+ EphyDataDialogPrivate *priv = ephy_data_dialog_get_instance_private (self);
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ hdy_search_bar_connect_entry (HDY_SEARCH_BAR (priv->search_bar), GTK_ENTRY (priv->search_entry));
+
+ update (self);
+}
+
+const gchar *
+ephy_data_dialog_get_clear_all_description (EphyDataDialog *self)
+{
+ EphyDataDialogPrivate *priv;
+
+ g_assert (EPHY_IS_DATA_DIALOG (self));
+
+ priv = ephy_data_dialog_get_instance_private (self);
+
+ return gtk_widget_get_tooltip_text (GTK_WIDGET (priv->clear_all_button));
+}
+
+void
+ephy_data_dialog_set_clear_all_description (EphyDataDialog *self,
+ const gchar *description)
+{
+ EphyDataDialogPrivate *priv;
+
+ g_assert (EPHY_IS_DATA_DIALOG (self));
+
+ priv = ephy_data_dialog_get_instance_private (self);
+
+ if (g_strcmp0 (gtk_widget_get_tooltip_text (GTK_WIDGET (priv->clear_all_button)), description) == 0)
+ return;
+
+ gtk_widget_set_tooltip_text (GTK_WIDGET (priv->clear_all_button), description);
+
+ g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_CLEAR_ALL_DESCRIPTION]);
+}
+
+gboolean
+ephy_data_dialog_get_is_loading (EphyDataDialog *self)
+{
+ EphyDataDialogPrivate *priv;
+
+ g_assert (EPHY_IS_DATA_DIALOG (self));
+
+ priv = ephy_data_dialog_get_instance_private (self);
+
+ return priv->is_loading;
+}
+
+void
+ephy_data_dialog_set_is_loading (EphyDataDialog *self,
+ gboolean is_loading)
+{
+ EphyDataDialogPrivate *priv;
+
+ g_assert (EPHY_IS_DATA_DIALOG (self));
+
+ priv = ephy_data_dialog_get_instance_private (self);
+ is_loading = !!is_loading;
+
+ if (priv->is_loading == is_loading)
+ return;
+
+ priv->is_loading = is_loading;
+
+ update (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_IS_LOADING]);
+}
+
+gboolean
+ephy_data_dialog_get_has_data (EphyDataDialog *self)
+{
+ EphyDataDialogPrivate *priv;
+
+ g_assert (EPHY_IS_DATA_DIALOG (self));
+
+ priv = ephy_data_dialog_get_instance_private (self);
+
+ return priv->has_data;
+}
+
+void
+ephy_data_dialog_set_has_data (EphyDataDialog *self,
+ gboolean has_data)
+{
+ EphyDataDialogPrivate *priv;
+
+ g_assert (EPHY_IS_DATA_DIALOG (self));
+
+ priv = ephy_data_dialog_get_instance_private (self);
+ has_data = !!has_data;
+
+ if (priv->has_data == has_data)
+ return;
+
+ priv->has_data = has_data;
+
+ update (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_HAS_DATA]);
+}
+
+gboolean
+ephy_data_dialog_get_has_search_results (EphyDataDialog *self)
+{
+ EphyDataDialogPrivate *priv;
+
+ g_assert (EPHY_IS_DATA_DIALOG (self));
+
+ priv = ephy_data_dialog_get_instance_private (self);
+
+ return priv->has_search_results;
+}
+
+void
+ephy_data_dialog_set_has_search_results (EphyDataDialog *self,
+ gboolean has_search_results)
+{
+ EphyDataDialogPrivate *priv;
+
+ g_assert (EPHY_IS_DATA_DIALOG (self));
+
+ priv = ephy_data_dialog_get_instance_private (self);
+ has_search_results = !!has_search_results;
+
+ if (priv->has_search_results == has_search_results)
+ return;
+
+ priv->has_search_results = has_search_results;
+
+ update (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_HAS_SEARCH_RESULTS]);
+}
+
+gboolean
+ephy_data_dialog_get_can_clear (EphyDataDialog *self)
+{
+ EphyDataDialogPrivate *priv;
+
+ g_assert (EPHY_IS_DATA_DIALOG (self));
+
+ priv = ephy_data_dialog_get_instance_private (self);
+
+ return priv->can_clear;
+}
+
+void
+ephy_data_dialog_set_can_clear (EphyDataDialog *self,
+ gboolean can_clear)
+{
+ EphyDataDialogPrivate *priv;
+
+ g_assert (EPHY_IS_DATA_DIALOG (self));
+
+ priv = ephy_data_dialog_get_instance_private (self);
+ can_clear = !!can_clear;
+
+ if (priv->can_clear == can_clear)
+ return;
+
+ priv->can_clear = can_clear;
+
+ update (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_CAN_CLEAR]);
+}
+
+const gchar *
+ephy_data_dialog_get_search_text (EphyDataDialog *self)
+{
+ EphyDataDialogPrivate *priv;
+
+ g_assert (EPHY_IS_DATA_DIALOG (self));
+
+ priv = ephy_data_dialog_get_instance_private (self);
+
+ return priv->search_text;
+}
diff --git a/src/ephy-data-dialog.h b/src/ephy-data-dialog.h
new file mode 100644
index 000000000..3b1e57554
--- /dev/null
+++ b/src/ephy-data-dialog.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2019 Purism SPC
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany 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.
+ *
+ * Epiphany 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 Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_DATA_DIALOG (ephy_data_dialog_get_type ())
+
+G_DECLARE_DERIVABLE_TYPE (EphyDataDialog, ephy_data_dialog, EPHY, DATA_DIALOG, GtkWindow)
+
+struct _EphyDataDialogClass
+{
+ GtkWindowClass parent_class;
+};
+
+const gchar *ephy_data_dialog_get_clear_all_description (EphyDataDialog *self);
+void ephy_data_dialog_set_clear_all_description (EphyDataDialog *self,
+ const gchar *description);
+
+gboolean ephy_data_dialog_get_is_loading (EphyDataDialog *self);
+void ephy_data_dialog_set_is_loading (EphyDataDialog *self,
+ gboolean is_loading);
+
+gboolean ephy_data_dialog_get_has_data (EphyDataDialog *self);
+void ephy_data_dialog_set_has_data (EphyDataDialog *self,
+ gboolean has_data);
+
+gboolean ephy_data_dialog_get_has_search_results (EphyDataDialog *self);
+void ephy_data_dialog_set_has_search_results (EphyDataDialog *self,
+ gboolean has_search_results);
+
+gboolean ephy_data_dialog_get_can_clear (EphyDataDialog *self);
+void ephy_data_dialog_set_can_clear (EphyDataDialog *self,
+ gboolean can_clear);
+
+const gchar *ephy_data_dialog_get_search_text (EphyDataDialog *self);
+
+G_END_DECLS
diff --git a/src/meson.build b/src/meson.build
index 8a3a9a8cd..95ff9fdd1 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -25,6 +25,7 @@ libephymain_sources = [
'ephy-action-bar-end.c',
'ephy-action-bar-start.c',
'ephy-action-helper.c',
+ 'ephy-data-dialog.c',
'ephy-desktop-utils.c',
'ephy-encoding-dialog.c',
'ephy-encoding-row.c',
diff --git a/src/resources/epiphany.gresource.xml b/src/resources/epiphany.gresource.xml
index b0ead00fc..ed8ec8cd8 100644
--- a/src/resources/epiphany.gresource.xml
+++ b/src/resources/epiphany.gresource.xml
@@ -22,6 +22,7 @@
<file preprocess="xml-stripblanks" compressed="true">gtk/bookmarks-popover.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/clear-data-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/cookies-dialog.ui</file>
+ <file preprocess="xml-stripblanks" compressed="true">gtk/data-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/encoding-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/encoding-row.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/history-dialog.ui</file>
diff --git a/src/resources/gtk/data-dialog.ui b/src/resources/gtk/data-dialog.ui
new file mode 100644
index 000000000..fe42a1240
--- /dev/null
+++ b/src/resources/gtk/data-dialog.ui
@@ -0,0 +1,269 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <requires lib="libhandy" version="0.0"/>
+ <object class="GtkImage" id="search_image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">edit-find-symbolic</property>
+ </object>
+ <object class="GtkImage" id="clear_all_image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">user-trash-symbolic</property>
+ </object>
+ <template class="EphyDataDialog" parent="GtkWindow">
+ <property name="can_focus">False</property>
+ <property name="modal">True</property>
+ <property name="window_position">center-on-parent</property>
+ <property name="default_width">1000</property>
+ <property name="default_height">600</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <signal name="key-press-event" handler="on_key_press_event" swapped="no"/>
+ <child type="titlebar">
+ <object class="GtkHeaderBar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_close_button">True</property>
+ <child>
+ <object class="GtkButton" id="clear_all_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">clear_all_image</property>
+ <property name="always_show_image">True</property>
+ <signal name="clicked" handler="on_clear_all_button_clicked" swapped="yes"/>
+ <accelerator key="Delete" modifiers="GDK_SHIFT_MASK" signal="clicked"/>
+ <style>
+ <class name="destructive-action"/>
+ <class name="image-button"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="search_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">search_image</property>
+ <property name="always_show_image">True</property>
+ <property name="active" bind-source="search_bar" bind-property="search-mode-enabled"
bind-flags="sync-create|bidirectional"/>
+ <accelerator key="F" modifiers="GDK_CONTROL_MASK" signal="clicked"/>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child internal-child="accessible">
+ <object class="AtkObject">
+ <property name="AtkObject::accessible-name" translatable="yes">Search</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="HdySearchBar" id="search_bar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <property name="search_mode_enabled">False</property>
+ <child>
+ <object class="HdyColumn">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="maximum_width">400</property>
+ <property name="linear_growth_width">300</property>
+ <child>
+ <object class="GtkSearchEntry" id="search_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="primary_icon_name">edit-find-symbolic</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">False</property>
+ <signal name="search-changed" handler="on_search_entry_changed" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="can_focus">False</property>
+ <property name="expand">True</property>
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkSpinner" id="spinner">
+ <property name="can_focus">False</property>
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="name">loading</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="can_focus">False</property>
+ <property name="expand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <property name="vexpand">True</property>
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkImage">
+ <property name="can_focus">False</property>
+ <property name="icon_name">web-browser-symbolic</property>
+ <property name="icon_size">0</property>
+ <property name="margin_bottom">18</property>
+ <property name="pixel_size">128</property>
+ <property name="valign">center</property>
+ <property name="visible">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="margin_end">12</property>
+ <property name="margin_start">12</property>
+ <property name="orientation">vertical</property>
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="empty_title_label">
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="justify">center</property>
+ <property name="margin_bottom">12</property>
+ <property name="opacity">0.5</property>
+ <property name="visible">True</property>
+ <property name="wrap">True</property>
+ <attributes>
+ <attribute name="scale" value="2"/>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="empty_description_label">
+ <property name="can_focus">False</property>
+ <property name="justify">center</property>
+ <property name="margin_bottom">6</property>
+ <property name="opacity">0.5</property>
+ <property name="use_markup">True</property>
+ <property name="visible">True</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">empty</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="can_focus">False</property>
+ <property name="expand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <property name="vexpand">True</property>
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkImage">
+ <property name="can_focus">False</property>
+ <property name="icon_name">edit-find-symbolic</property>
+ <property name="icon_size">0</property>
+ <property name="margin_bottom">18</property>
+ <property name="pixel_size">128</property>
+ <property name="valign">center</property>
+ <property name="visible">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="margin_end">12</property>
+ <property name="margin_start">12</property>
+ <property name="orientation">vertical</property>
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="justify">center</property>
+ <property name="label" translatable="yes">No Results Found</property>
+ <property name="margin_bottom">12</property>
+ <property name="opacity">0.5</property>
+ <property name="visible">True</property>
+ <property name="wrap">True</property>
+ <attributes>
+ <attribute name="scale" value="2"/>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="can_focus">False</property>
+ <property name="justify">center</property>
+ <property name="label" translatable="yes">Try a different search</property>
+ <property name="margin_bottom">6</property>
+ <property name="opacity">0.5</property>
+ <property name="use_markup">True</property>
+ <property name="visible">True</property>
+ <property name="wrap">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">no-results</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]