[epiphany] Implement search engine dialog
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany] Implement search engine dialog
- Date: Fri, 24 Feb 2017 22:10:16 +0000 (UTC)
commit e57ce8d3aa2a1539bb51413afa01ae31374717a4
Author: cedlemo <cedlemo gmx com>
Date: Thu Feb 16 19:22:41 2017 +0100
Implement search engine dialog
https://bugzilla.gnome.org/show_bug.cgi?id=776738
po/POTFILES.in | 2 +
src/Makefile.am | 2 +
src/ephy-search-engine-dialog.c | 715 +++++++++++++++++++++++++++++
src/ephy-search-engine-dialog.h | 33 ++
src/prefs-dialog.c | 135 +-----
src/resources/epiphany.gresource.xml | 1 +
src/resources/gtk/prefs-dialog.ui | 73 ++--
src/resources/gtk/search-engine-dialog.ui | 301 ++++++++++++
8 files changed, 1102 insertions(+), 160 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index af6f0ef..e0c7154 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -36,6 +36,7 @@ src/ephy-header-bar.c
src/ephy-history-dialog.c
src/ephy-main.c
src/ephy-notebook.c
+src/ephy-search-engine-dialog.c
src/ephy-session.c
src/ephy-shell.c
src/ephy-window.c
@@ -55,6 +56,7 @@ src/resources/gtk/page-menu-popover.ui
src/resources/gtk/passwords-dialog.ui
src/resources/gtk/prefs-dialog.ui
src/resources/gtk/prefs-lang-dialog.ui
+src/resources/gtk/search-engine-dialog.ui
src/resources/gtk/shortcuts-dialog.ui
src/search-provider/ephy-search-provider.c
src/sync/ephy-sync-secret.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 0c9da73..9230a3f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -58,6 +58,8 @@ libephymain_la_SOURCES = \
ephy-lockdown.h \
ephy-notebook.c \
ephy-notebook.h \
+ ephy-search-engine-dialog.c \
+ ephy-search-engine-dialog.h \
ephy-session.c \
ephy-session.h \
ephy-shell.c \
diff --git a/src/ephy-search-engine-dialog.c b/src/ephy-search-engine-dialog.c
new file mode 100644
index 0000000..8381c48
--- /dev/null
+++ b/src/ephy-search-engine-dialog.c
@@ -0,0 +1,715 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2017 Cedric Le Moigne <cedlemo gmx com>
+ *
+ * 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-search-engine-dialog.h"
+#include "ephy-shell.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <string.h>
+
+#define NEW_SEARCH_ENGINE_NAME _("New search engine")
+#define NEW_SEARCH_ENGINE_ADDRESS _("New address")
+#define NEW_SEARCH_ENGINE_BANG _("Bang")
+
+struct _EphySearchEngineDialog {
+ GtkDialog parent_instance;
+
+ EphySearchEngineManager *search_engine_manager;
+ GtkWidget *search_engine_add_button;
+ GtkWidget *search_engine_address_entry;
+ GtkWidget *search_engine_default_switch;
+ GtkWidget *search_engine_list_box;
+ GtkWidget *search_engine_name_entry;
+ GtkWidget *search_engine_bang_entry;
+ GtkWidget *search_engine_remove_button;
+};
+
+G_DEFINE_TYPE (EphySearchEngineDialog, ephy_search_engine_dialog, GTK_TYPE_DIALOG)
+
+static GtkWidget *
+container_get_first_child (GtkContainer *container)
+{
+ GList *children;
+ GtkWidget *child;
+
+ children = gtk_container_get_children (container);
+ child = (GtkWidget *)children->data;
+ g_list_free (children);
+ return child;
+}
+
+static int
+dialog_list_box_child_n_occurence (const char *name,
+ EphySearchEngineDialog *dialog)
+{
+ GList *children;
+ GList *c;
+ GtkWidget *label;
+ int count = 0;
+ const char *text;
+
+ children = gtk_container_get_children (GTK_CONTAINER (dialog->search_engine_list_box));
+
+ for (c = children; c != NULL; c = c->next) {
+ label = container_get_first_child (GTK_CONTAINER (c->data));
+ text = gtk_label_get_text (GTK_LABEL (label));
+ if (g_strcmp0 (name, text) == 0)
+ count++;
+ }
+ g_list_free (children);
+
+ return count;
+}
+
+static GtkWidget *
+add_list_box_row (EphySearchEngineDialog *dialog,
+ const char *name,
+ int position)
+{
+ GtkListBox *listbox;
+ GtkWidget *label;
+ GtkWidget *list_box_row;
+
+ label = gtk_label_new (name);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+
+ list_box_row = gtk_list_box_row_new ();
+ gtk_container_add (GTK_CONTAINER (list_box_row), label);
+ gtk_widget_set_size_request (list_box_row, 160, -1);
+ gtk_widget_show_all (list_box_row);
+
+ listbox = GTK_LIST_BOX (dialog->search_engine_list_box);
+ gtk_list_box_insert (listbox, list_box_row, position);
+ return list_box_row;
+}
+
+static void
+dialog_set_entry_error_state (GtkWidget *entry)
+{
+ GtkStyleContext *context;
+
+ gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry),
+ GTK_ENTRY_ICON_SECONDARY,
+ "dialog-warning-symbolic");
+ context = gtk_widget_get_style_context (entry);
+ gtk_style_context_add_class (context, "error");
+}
+
+static void
+dialog_set_entry_normal_state (GtkWidget *entry)
+{
+ GtkStyleContext *context;
+
+ gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry),
+ GTK_ENTRY_ICON_SECONDARY,
+ NULL);
+ context = gtk_widget_get_style_context (entry);
+ gtk_style_context_remove_class (context, "error");
+}
+
+static gboolean
+dialog_check_name_entry (const char *name,
+ EphySearchEngineDialog *dialog)
+{
+ EphySearchEngineManager *manager;
+ const char *search_engine_name;
+ GtkWidget *search_engine_label;
+ GtkListBoxRow *list_box_row;
+
+ manager = dialog->search_engine_manager;
+ list_box_row = gtk_list_box_get_selected_row (GTK_LIST_BOX (dialog->search_engine_list_box));
+ search_engine_label = container_get_first_child (GTK_CONTAINER (list_box_row));
+ search_engine_name = gtk_label_get_text (GTK_LABEL (search_engine_label));
+
+ if (name == NULL || g_strcmp0 (name, "") == 0) {
+ dialog_set_entry_error_state (dialog->search_engine_name_entry);
+ return FALSE;
+ }
+
+ /* Check if name already exist in the search_engine_manager */
+ if (ephy_search_engine_manager_get_address (manager, name) != NULL &&
+ g_strcmp0 (name, search_engine_name) != 0 ) {
+ dialog_set_entry_error_state (dialog->search_engine_name_entry);
+ return FALSE;
+ }
+
+ dialog_set_entry_normal_state (dialog->search_engine_name_entry);
+ return TRUE;
+}
+
+static gboolean
+dialog_check_address_entry (const char *address,
+ EphySearchEngineDialog *dialog)
+{
+ if (address == NULL || !soup_uri_new (address) || strstr (address, "%s") == NULL) {
+ dialog_set_entry_error_state (dialog->search_engine_address_entry);
+ return FALSE;
+ }
+ else
+ dialog_set_entry_normal_state (dialog->search_engine_address_entry);
+
+ return TRUE;
+}
+
+static gboolean
+dialog_check_bang_entry (const char *bang,
+ EphySearchEngineDialog *dialog)
+{
+ EphySearchEngineManager *manager;
+ GtkListBoxRow *list_box_row;
+ GtkWidget *search_engine_label;
+ const char *engine_from_bang;
+ const char *search_engine_name;
+
+ /* Allow empty string */
+ if (g_strcmp0 (bang, "") == 0) {
+ dialog_set_entry_normal_state (dialog->search_engine_bang_entry);
+ return TRUE;
+ }
+
+ manager = dialog->search_engine_manager;
+
+ engine_from_bang = ephy_search_engine_manager_engine_from_bang (manager, bang);
+ list_box_row = gtk_list_box_get_selected_row (GTK_LIST_BOX (dialog->search_engine_list_box));
+ search_engine_label = container_get_first_child (GTK_CONTAINER (list_box_row));
+ search_engine_name = gtk_label_get_text (GTK_LABEL (search_engine_label));
+
+ if (engine_from_bang && (g_strcmp0 (engine_from_bang, search_engine_name) != 0)) {
+ dialog_set_entry_error_state (dialog->search_engine_bang_entry);
+ return FALSE;
+ }
+ else if (g_strcmp0 (bang, NEW_SEARCH_ENGINE_BANG) == 0) {
+ dialog_set_entry_error_state (dialog->search_engine_bang_entry);
+ return FALSE;
+ }
+ else
+ dialog_set_entry_normal_state (dialog->search_engine_bang_entry);
+
+ return TRUE;
+}
+
+static void
+list_box_row_selected_cb (GtkListBox *list_box,
+ GtkListBoxRow *list_box_row,
+ gpointer data)
+{
+ EphySearchEngineDialog *dialog;
+ EphySearchEngineManager *manager;
+ GtkWidget *search_engine_label;
+ const char *search_engine_name;
+ const char *search_engine_address;
+ const char *search_engine_bang;
+ const char *search_engine_default;
+ gboolean is_default = FALSE;
+
+ if (!list_box_row)
+ return;
+
+ dialog = EPHY_SEARCH_ENGINE_DIALOG (data);
+ manager = dialog->search_engine_manager;
+
+ search_engine_label = container_get_first_child (GTK_CONTAINER (list_box_row));
+ search_engine_name = gtk_label_get_text (GTK_LABEL (search_engine_label));
+ search_engine_address = ephy_search_engine_manager_get_address (manager, search_engine_name);
+ search_engine_bang = ephy_search_engine_manager_get_bang (manager, search_engine_name);
+
+ if (!search_engine_address) {
+ gtk_entry_set_text (GTK_ENTRY (dialog->search_engine_name_entry), "");
+ gtk_entry_set_text (GTK_ENTRY (dialog->search_engine_address_entry), "");
+ gtk_entry_set_text (GTK_ENTRY (dialog->search_engine_bang_entry), "");
+ gtk_entry_set_placeholder_text (GTK_ENTRY (dialog->search_engine_address_entry),
+ NEW_SEARCH_ENGINE_ADDRESS);
+ gtk_entry_set_placeholder_text (GTK_ENTRY (dialog->search_engine_bang_entry),
+ NEW_SEARCH_ENGINE_BANG);
+ gtk_entry_set_placeholder_text (GTK_ENTRY (dialog->search_engine_name_entry),
+ search_engine_name);
+ search_engine_name = "";
+ }
+ else
+ {
+ gtk_entry_set_text (GTK_ENTRY (dialog->search_engine_name_entry), search_engine_name);
+ gtk_entry_set_text (GTK_ENTRY (dialog->search_engine_address_entry), search_engine_address);
+ gtk_entry_set_text (GTK_ENTRY (dialog->search_engine_bang_entry), search_engine_bang);
+
+ search_engine_default = ephy_search_engine_manager_get_default_engine (manager);
+ if (g_strcmp0 (search_engine_name, search_engine_default) == 0)
+ is_default = TRUE;
+ }
+
+ gtk_switch_set_active (GTK_SWITCH (dialog->search_engine_default_switch),
+ is_default);
+ gtk_widget_set_sensitive (dialog->search_engine_default_switch, !is_default);
+
+ dialog_check_name_entry (search_engine_name,
+ dialog);
+ dialog_check_address_entry (search_engine_address,
+ dialog);
+ dialog_check_bang_entry (search_engine_bang,
+ dialog);
+}
+
+static void
+ephy_search_engine_dialog_fill_list_box (EphySearchEngineDialog *dialog)
+{
+
+ GtkListBox *listbox;
+ GtkWidget *list_box_row;
+ EphySearchEngineManager *manager;
+ char **engines_names ;
+
+ listbox = GTK_LIST_BOX (dialog->search_engine_list_box);
+ manager = dialog->search_engine_manager;
+ engines_names = ephy_search_engine_manager_get_names (manager);
+
+ for (guint i = 0; engines_names[i] != NULL; i++) {
+ const char *name = engines_names[i];
+ list_box_row = add_list_box_row (dialog, name, i);
+ gtk_list_box_select_row (listbox, GTK_LIST_BOX_ROW (list_box_row));
+ }
+ g_strfreev (engines_names);
+
+ g_signal_connect (listbox,
+ "row-selected",
+ G_CALLBACK (list_box_row_selected_cb),
+ dialog);
+ gtk_list_box_select_row (listbox,
+ gtk_list_box_get_row_at_index (listbox, 0));
+}
+
+static char *
+generate_new_unique_default_engine_name (EphySearchEngineDialog *dialog)
+{
+ guint i = 1;
+ char *default_name = g_strdup_printf ("%s %d", NEW_SEARCH_ENGINE_NAME, i);
+
+ while (dialog_list_box_child_n_occurence (default_name, dialog) != 0)
+ {
+ if (i == UINT_MAX)
+ break;
+
+ i++;
+ g_free (default_name);
+ default_name = g_strdup_printf ("%s %d", NEW_SEARCH_ENGINE_NAME, i);
+ }
+
+ return default_name;
+}
+
+static void
+on_search_engine_add_button_clicked (GtkButton *button,
+ EphySearchEngineDialog *dialog)
+{
+ GtkWidget *list_box_row;
+ char *new_engine_name;
+
+ new_engine_name = generate_new_unique_default_engine_name (dialog);
+ list_box_row = add_list_box_row (dialog, new_engine_name, -1);
+ g_free (new_engine_name);
+ gtk_list_box_select_row (GTK_LIST_BOX (dialog->search_engine_list_box),
+ GTK_LIST_BOX_ROW (list_box_row));
+ gtk_list_box_invalidate_sort (GTK_LIST_BOX (dialog->search_engine_list_box));
+}
+
+static void
+on_search_engine_remove_button_clicked (GtkButton *button,
+ EphySearchEngineDialog *dialog)
+{
+ GtkListBoxRow *list_box_row;
+ GtkListBoxRow *prev_list_box_row;
+ EphySearchEngineManager *manager;
+ GtkWidget *search_engine_label;
+ const char *default_search_engine;
+ const char *search_engine_name;
+ GList *children;
+ guint children_number;
+ guint index;
+
+ /* It should remains at least one search engine */
+ children = gtk_container_get_children (GTK_CONTAINER (dialog->search_engine_list_box));
+ children_number = g_list_length (children);
+ g_list_free (children);
+ if (children_number <= 1)
+ return;
+
+ list_box_row = gtk_list_box_get_selected_row (GTK_LIST_BOX (dialog->search_engine_list_box));
+
+ search_engine_label = container_get_first_child (GTK_CONTAINER (list_box_row));
+ search_engine_name = gtk_label_get_text (GTK_LABEL (search_engine_label));
+ manager = dialog->search_engine_manager;
+ ephy_search_engine_manager_delete_engine (manager, search_engine_name);
+
+ /* Select the previous row before removing the current one */
+ index = gtk_list_box_row_get_index (list_box_row);
+ if (index == 0)
+ index = 2; // Trick in order to select the futur first row
+ prev_list_box_row = gtk_list_box_get_row_at_index (GTK_LIST_BOX (dialog->search_engine_list_box),
+ index - 1);
+ /* If the removed engine is the default, choose the newly selected as default */
+ default_search_engine = ephy_search_engine_manager_get_default_engine (dialog->search_engine_manager);
+
+ if (g_strcmp0(default_search_engine, search_engine_name) == 0) {
+ search_engine_label = container_get_first_child (GTK_CONTAINER (prev_list_box_row));
+ search_engine_name = gtk_label_get_text (GTK_LABEL (search_engine_label));
+ ephy_search_engine_manager_set_default_engine (dialog->search_engine_manager,
+ search_engine_name);
+ }
+
+ gtk_list_box_select_row (GTK_LIST_BOX (dialog->search_engine_list_box),
+ prev_list_box_row);
+
+ gtk_container_remove (GTK_CONTAINER (dialog->search_engine_list_box),
+ GTK_WIDGET (list_box_row));
+ gtk_list_box_invalidate_sort (GTK_LIST_BOX (dialog->search_engine_list_box));
+}
+
+static gboolean
+on_default_search_engine_switch_state_modified (GtkWidget *switch_widget,
+ gboolean state,
+ EphySearchEngineDialog *dialog)
+{
+ GtkListBoxRow *list_box_row;
+ GtkWidget *search_engine_label;
+ const char *search_engine_name;
+ const char *default_search_engine;
+ gboolean active;
+ gboolean is_set;
+
+ active = gtk_widget_get_sensitive (switch_widget);
+ if (!active)
+ return TRUE;
+
+ list_box_row = gtk_list_box_get_selected_row (GTK_LIST_BOX (dialog->search_engine_list_box));
+ search_engine_label = container_get_first_child (GTK_CONTAINER (list_box_row));
+ search_engine_name = gtk_label_get_text (GTK_LABEL (search_engine_label));
+ default_search_engine = ephy_search_engine_manager_get_default_engine (dialog->search_engine_manager);
+
+ if ( g_strcmp0(default_search_engine, search_engine_name) != 0) {
+ is_set = ephy_search_engine_manager_set_default_engine (dialog->search_engine_manager,
+ search_engine_name);
+
+ if (is_set == FALSE) {
+ gtk_switch_set_active (GTK_SWITCH (dialog->search_engine_default_switch),
+ FALSE);
+ return FALSE;
+ }
+
+ gtk_switch_set_active (GTK_SWITCH (dialog->search_engine_default_switch),
+ TRUE);
+ gtk_widget_set_sensitive (dialog->search_engine_default_switch, FALSE);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static void
+ephy_search_engine_dialog_class_init (EphySearchEngineDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/epiphany/gtk/search-engine-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class,
+ EphySearchEngineDialog,
+ search_engine_add_button);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphySearchEngineDialog,
+ search_engine_remove_button);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphySearchEngineDialog,
+ search_engine_list_box);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphySearchEngineDialog,
+ search_engine_bang_entry);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphySearchEngineDialog,
+ search_engine_name_entry);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphySearchEngineDialog,
+ search_engine_address_entry);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphySearchEngineDialog,
+ search_engine_default_switch);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_search_engine_add_button_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, on_search_engine_remove_button_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, on_default_search_engine_switch_state_modified);
+}
+
+static int
+sort_list_box_by_engine_name (GtkListBoxRow *row1,
+ GtkListBoxRow *row2,
+ gpointer data)
+{
+ const char *row1_engine_name;
+ const char *row2_engine_name;
+ GtkWidget *label;
+
+ label = container_get_first_child (GTK_CONTAINER (row1));
+ row1_engine_name = gtk_label_get_text (GTK_LABEL (label));
+
+ label = container_get_first_child (GTK_CONTAINER (row2));
+ row2_engine_name = gtk_label_get_text (GTK_LABEL (label));
+
+ return g_strcmp0 (row1_engine_name, row2_engine_name);
+}
+
+static void
+dialog_entry_change_on_event (GtkWidget *entry,
+ EphySearchEngineDialog *dialog)
+{
+ EphySearchEngineManager *manager;
+ GtkListBoxRow *list_box_row;
+ GtkWidget *search_engine_label;
+ const char *search_engine_name;
+ const char *search_engine_bang;
+ const char *search_engine_address;
+ const char *search_engine_selected_name;
+ gboolean valid_name = TRUE;
+ gboolean valid_address = TRUE;
+ gboolean valid_bang = TRUE;
+
+ manager = dialog->search_engine_manager;
+
+ list_box_row = gtk_list_box_get_selected_row (GTK_LIST_BOX (dialog->search_engine_list_box));
+ search_engine_label = container_get_first_child (GTK_CONTAINER (list_box_row));
+ search_engine_selected_name = gtk_label_get_text (GTK_LABEL (search_engine_label));
+ search_engine_name = gtk_entry_get_text (GTK_ENTRY (dialog->search_engine_name_entry));
+ search_engine_address = gtk_entry_get_text (GTK_ENTRY (dialog->search_engine_address_entry));
+ search_engine_bang = gtk_entry_get_text (GTK_ENTRY (dialog->search_engine_bang_entry));
+
+ /* If entry name is empty, use list box selected label */
+ if (g_strcmp0 (search_engine_name, "") == 0) {
+ search_engine_name = search_engine_selected_name;
+ gtk_entry_set_text (GTK_ENTRY (dialog->search_engine_name_entry), search_engine_name);
+ }
+ valid_name = dialog_check_name_entry (search_engine_name,
+ dialog);
+ valid_address = dialog_check_address_entry (search_engine_address,
+ dialog);
+ valid_bang = dialog_check_bang_entry (search_engine_bang,
+ dialog);
+ if (!valid_name || !valid_address || !valid_bang)
+ return;
+
+ if (ephy_search_engine_manager_get_address (manager, search_engine_name) == NULL) {
+ ephy_search_engine_manager_add_engine (manager,
+ search_engine_name,
+ search_engine_address,
+ search_engine_bang);
+ }
+ else {
+ ephy_search_engine_manager_modify_engine (manager,
+ search_engine_name,
+ search_engine_address,
+ search_engine_bang);
+ }
+
+ /* If the name label was not the same as the list box label, update and sort
+ * the list box */
+ search_engine_name = gtk_entry_get_text (GTK_ENTRY (dialog->search_engine_name_entry));
+ if (g_strcmp0 (search_engine_name, search_engine_selected_name) != 0) {
+ gtk_label_set_text (GTK_LABEL (search_engine_label), search_engine_name);
+ gtk_list_box_invalidate_sort (GTK_LIST_BOX (dialog->search_engine_list_box));
+ }
+ return;
+}
+
+static gboolean
+address_entry_on_focus_out_cb (GtkWidget *entry,
+ GdkEvent *event,
+ gpointer data)
+{
+ EphySearchEngineDialog *dialog;
+ dialog = EPHY_SEARCH_ENGINE_DIALOG (data);
+ dialog_entry_change_on_event (entry, dialog);
+ return FALSE;
+}
+
+static void
+address_entry_on_activate_cb (GtkWidget *entry,
+ gpointer data)
+{
+ EphySearchEngineDialog *dialog;
+ dialog = EPHY_SEARCH_ENGINE_DIALOG (data);
+ dialog_entry_change_on_event (entry, dialog);
+}
+
+static gboolean
+bang_entry_on_focus_out_cb (GtkWidget *entry,
+ GdkEvent *event,
+ gpointer data)
+{
+ EphySearchEngineDialog *dialog;
+ dialog = EPHY_SEARCH_ENGINE_DIALOG (data);
+ dialog_entry_change_on_event (entry, dialog);
+ return FALSE;
+}
+
+static void
+bang_entry_on_activate_cb (GtkWidget *entry,
+ gpointer data)
+{
+ EphySearchEngineDialog *dialog;
+ dialog = EPHY_SEARCH_ENGINE_DIALOG (data);
+ dialog_entry_change_on_event (entry, dialog);
+}
+
+static void
+name_entry_change_on_event (GtkWidget *entry,
+ EphySearchEngineDialog *dialog)
+{
+ EphySearchEngineManager *manager;
+ GtkListBoxRow *list_box_row;
+ GtkWidget *new_list_box_row;
+ GtkWidget *search_engine_label;
+ const char *search_engine_name;
+ const char *new_search_engine_name;
+ const char *search_engine_bang;
+ const char *search_engine_address;
+ const char *default_search_engine;
+ gboolean valid_name = TRUE;
+ gboolean valid_address = TRUE;
+ gboolean valid_bang = TRUE;
+ manager = dialog->search_engine_manager;
+
+ list_box_row = gtk_list_box_get_selected_row (GTK_LIST_BOX (dialog->search_engine_list_box));
+ search_engine_label = container_get_first_child (GTK_CONTAINER (list_box_row));
+ search_engine_name = gtk_label_get_text (GTK_LABEL (search_engine_label));
+ new_search_engine_name = gtk_entry_get_text (GTK_ENTRY (entry));
+ search_engine_address = gtk_entry_get_text (GTK_ENTRY (dialog->search_engine_address_entry));
+ search_engine_bang = gtk_entry_get_text (GTK_ENTRY (dialog->search_engine_bang_entry));
+
+ if (g_strcmp0 (search_engine_name, new_search_engine_name) == 0) {
+ dialog_set_entry_normal_state (dialog->search_engine_name_entry);
+ return;
+ }
+
+ dialog_set_entry_normal_state (dialog->search_engine_name_entry);
+ valid_name = dialog_check_name_entry (new_search_engine_name,
+ dialog);
+
+ valid_address = dialog_check_address_entry (search_engine_address,
+ dialog);
+ valid_bang = dialog_check_bang_entry (search_engine_bang,
+ dialog);
+
+ if (!valid_name || !valid_address || !valid_bang)
+ return;
+
+ /* Create a new search engine */
+ ephy_search_engine_manager_add_engine (manager,
+ new_search_engine_name,
+ search_engine_address,
+ search_engine_bang);
+
+ /* Change the name of the default searche engine too*/
+ default_search_engine = ephy_search_engine_manager_get_default_engine (dialog->search_engine_manager);
+
+ if (g_strcmp0(default_search_engine, search_engine_name) == 0)
+ ephy_search_engine_manager_set_default_engine (dialog->search_engine_manager,
+ new_search_engine_name);
+
+ ephy_search_engine_manager_delete_engine (manager, search_engine_name);
+
+ /* Add new element in the ListBox */
+ new_list_box_row = add_list_box_row (dialog,
+ new_search_engine_name,
+ -1);
+ gtk_container_remove (GTK_CONTAINER (dialog->search_engine_list_box),
+ GTK_WIDGET (list_box_row));
+ gtk_list_box_select_row (GTK_LIST_BOX (dialog->search_engine_list_box),
+ GTK_LIST_BOX_ROW (new_list_box_row));
+ gtk_list_box_invalidate_sort (GTK_LIST_BOX (dialog->search_engine_list_box));
+}
+
+static gboolean
+name_entry_on_focus_out_cb (GtkWidget *entry,
+ GdkEvent *event,
+ gpointer data)
+{
+ EphySearchEngineDialog *dialog;
+ dialog = EPHY_SEARCH_ENGINE_DIALOG (data);
+ name_entry_change_on_event (entry, dialog);
+ return FALSE;
+}
+
+static void
+name_entry_on_activate_cb (GtkWidget *entry,
+ gpointer data)
+{
+ EphySearchEngineDialog *dialog;
+ dialog = EPHY_SEARCH_ENGINE_DIALOG (data);
+ name_entry_change_on_event (entry, dialog);
+}
+
+static void
+ephy_search_engine_dialog_init (EphySearchEngineDialog *dialog)
+{
+ EphyEmbedShell *shell;
+
+ shell = ephy_embed_shell_get_default ();
+ dialog->search_engine_manager = ephy_embed_shell_get_search_engine_manager (shell);
+
+ gtk_widget_init_template (GTK_WIDGET (dialog));
+ gtk_list_box_set_sort_func (GTK_LIST_BOX (dialog->search_engine_list_box),
+ sort_list_box_by_engine_name,
+ NULL,
+ NULL);
+ ephy_search_engine_dialog_fill_list_box (dialog);
+ gtk_list_box_invalidate_sort (GTK_LIST_BOX (dialog->search_engine_list_box));
+
+ g_signal_connect (dialog->search_engine_address_entry,
+ "focus-out-event",
+ G_CALLBACK (address_entry_on_focus_out_cb),
+ dialog);
+ g_signal_connect (dialog->search_engine_address_entry,
+ "activate",
+ G_CALLBACK (address_entry_on_activate_cb),
+ dialog);
+ g_signal_connect (dialog->search_engine_bang_entry,
+ "focus-out-event",
+ G_CALLBACK (bang_entry_on_focus_out_cb),
+ dialog);
+ g_signal_connect (dialog->search_engine_bang_entry,
+ "activate",
+ G_CALLBACK (bang_entry_on_activate_cb),
+ dialog);
+ g_signal_connect (dialog->search_engine_name_entry,
+ "focus-out-event",
+ G_CALLBACK (name_entry_on_focus_out_cb),
+ dialog);
+ g_signal_connect (dialog->search_engine_name_entry,
+ "activate",
+ G_CALLBACK (name_entry_on_activate_cb),
+ dialog);
+}
+
+EphySearchEngineDialog *
+ephy_search_engine_dialog_new (void)
+{
+ return g_object_new (EPHY_TYPE_SEARCH_ENGINE_DIALOG,
+ "use-header-bar", TRUE,
+ NULL);
+}
diff --git a/src/ephy-search-engine-dialog.h b/src/ephy-search-engine-dialog.h
new file mode 100644
index 0000000..55fef91
--- /dev/null
+++ b/src/ephy-search-engine-dialog.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2017 Cedric Le Moigne <cedlemo gmx com>
+ *
+ * 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 "ephy-window.h"
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_SEARCH_ENGINE_DIALOG (ephy_search_engine_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (EphySearchEngineDialog, ephy_search_engine_dialog, EPHY, SEARCH_ENGINE_DIALOG,
GtkDialog);
+
+EphySearchEngineDialog *ephy_search_engine_dialog_new (void);
+
+G_END_DECLS
diff --git a/src/prefs-dialog.c b/src/prefs-dialog.c
index b866e1f..8c07919 100644
--- a/src/prefs-dialog.c
+++ b/src/prefs-dialog.c
@@ -33,6 +33,7 @@
#include "ephy-gui.h"
#include "ephy-langs.h"
#include "ephy-prefs.h"
+#include "ephy-search-engine-dialog.h"
#include "ephy-session.h"
#include "ephy-settings.h"
#include "ephy-shell.h"
@@ -76,7 +77,6 @@ struct _PrefsDialog {
GtkWidget *download_button_label;
GtkWidget *automatic_downloads_checkbutton;
GtkWidget *search_box;
- GtkWidget *search_engine_combo;
GtkWidget *session_box;
GtkWidget *restore_session_checkbutton;
GtkWidget *popups_allow_checkbutton;
@@ -148,10 +148,9 @@ typedef struct {
#endif
enum {
- SEARCH_ENGINE_COL_NAME,
- SEARCH_ENGINE_COL_STOCK_URL,
- SEARCH_ENGINE_COL_URL,
- SEARCH_ENGINE_NUM_COLS
+ COL_TITLE_ELIDED,
+ COL_ENCODING,
+ NUM_COLS
};
G_DEFINE_TYPE (PrefsDialog, prefs_dialog, GTK_TYPE_DIALOG)
@@ -576,6 +575,19 @@ on_manage_passwords_button_clicked (GtkWidget *button,
}
static void
+on_search_engine_dialog_button_clicked (GtkWidget *button,
+ PrefsDialog *dialog)
+{
+ GtkWindow *search_engine_dialog;
+
+ search_engine_dialog = GTK_WINDOW (ephy_search_engine_dialog_new ());
+
+ gtk_window_set_transient_for (search_engine_dialog, GTK_WINDOW (dialog));
+ gtk_window_set_modal (search_engine_dialog, TRUE);
+ gtk_window_present (search_engine_dialog);
+}
+
+static void
prefs_dialog_class_init (PrefsDialogClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -593,7 +605,6 @@ prefs_dialog_class_init (PrefsDialogClass *klass)
gtk_widget_class_bind_template_child (widget_class, PrefsDialog, custom_homepage_entry);
gtk_widget_class_bind_template_child (widget_class, PrefsDialog, automatic_downloads_checkbutton);
gtk_widget_class_bind_template_child (widget_class, PrefsDialog, search_box);
- gtk_widget_class_bind_template_child (widget_class, PrefsDialog, search_engine_combo);
gtk_widget_class_bind_template_child (widget_class, PrefsDialog, session_box);
gtk_widget_class_bind_template_child (widget_class, PrefsDialog, restore_session_checkbutton);
gtk_widget_class_bind_template_child (widget_class, PrefsDialog, popups_allow_checkbutton);
@@ -640,6 +651,7 @@ prefs_dialog_class_init (PrefsDialogClass *klass)
gtk_widget_class_bind_template_callback (widget_class, on_manage_cookies_button_clicked);
gtk_widget_class_bind_template_callback (widget_class, on_manage_passwords_button_clicked);
+ gtk_widget_class_bind_template_callback (widget_class, on_search_engine_dialog_button_clicked);
}
static void
@@ -1355,116 +1367,6 @@ cookies_set_mapping (const GValue *value,
return variant;
}
-static void
-search_engine_combo_add_default_engines (GtkListStore *store)
-{
- guint i;
- const char *default_engines[][3] = { /* Search engine option in the preferences dialog */
- { N_("DuckDuckGo"),
- "https://duckduckgo.com/?q=%s&t=epiphany",
- /* For the preferences dialog. Must exactly match the URL
- * you chose in the gschema, but with & instead of &
- * If the match is not exact, there will be a spurious, ugly
- * entry in the preferences combo, so please test this. */
- N_("https://duckduckgo.com/?q=%s&t=epiphany") },
- /* Search engine option in the preferences dialog */
- { N_("Google"),
- "https://google.com/search?q=%s",
- /* For the preferences dialog. Consider a regional variant, like google.co.uk */
- N_("https://google.com/search?q=%s") },
- /* Search engine option in the preferences dialog */
- { N_("Bing"),
- "https://www.bing.com/search?q=%s",
- /* For the preferences dialog. Consider a regional variant, like uk.bing.com */
- N_("https://www.bing.com/search?q=%s") }
- };
-
- for (i = 0; i < G_N_ELEMENTS (default_engines); ++i) {
- gtk_list_store_insert_with_values (store, NULL, -1,
- SEARCH_ENGINE_COL_NAME,
- _(default_engines[i][0]),
- SEARCH_ENGINE_COL_STOCK_URL,
- default_engines[i][1],
- SEARCH_ENGINE_COL_URL,
- _(default_engines[i][2]),
- -1);
- }
-}
-
-/* Has the user manually set the engine to something not in the combo?
- * If so, add that URL as an extra item in the combo. */
-static void
-search_engine_combo_add_current_engine (GtkListStore *store)
-{
- GtkTreeIter iter;
- char *original_url;
- gboolean in_combo = FALSE;
- gboolean has_next = FALSE;
-
- original_url = g_settings_get_string (EPHY_SETTINGS_MAIN,
- EPHY_PREFS_KEYWORD_SEARCH_URL);
- if (!original_url)
- return;
-
- has_next = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
-
- while (!in_combo && has_next) {
- char *stock_url, *url;
-
- gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
- SEARCH_ENGINE_COL_STOCK_URL, &stock_url,
- SEARCH_ENGINE_COL_URL, &url, -1);
-
- if (strcmp (original_url, stock_url) == 0 ||
- strcmp (original_url, url) == 0)
- in_combo = TRUE;
-
- g_free (stock_url);
- g_free (url);
- has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
- }
-
- if (!in_combo)
- gtk_list_store_insert_with_values (store, NULL, -1,
- SEARCH_ENGINE_COL_NAME, original_url,
- SEARCH_ENGINE_COL_STOCK_URL, original_url,
- SEARCH_ENGINE_COL_URL, original_url,
- -1);
-
- g_free (original_url);
-}
-
-static void
-create_search_engine_combo (GtkComboBox *combo)
-{
- GtkCellRenderer *renderer;
- GtkListStore *store;
-
- store = GTK_LIST_STORE (gtk_combo_box_get_model (combo));
-
- search_engine_combo_add_default_engines (store);
- search_engine_combo_add_current_engine (store);
-
- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), SEARCH_ENGINE_COL_NAME,
- GTK_SORT_ASCENDING);
- gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store));
-
- renderer = gtk_cell_renderer_text_new ();
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
- "text", SEARCH_ENGINE_COL_NAME,
- NULL);
-
- g_settings_bind_with_mapping (EPHY_SETTINGS_MAIN,
- EPHY_PREFS_KEYWORD_SEARCH_URL,
- combo, "active",
- G_SETTINGS_BIND_DEFAULT,
- combo_get_mapping,
- combo_set_mapping,
- combo,
- NULL);
-}
-
static gboolean
new_tab_homepage_get_mapping (GValue *value,
GVariant *variant,
@@ -1686,7 +1588,6 @@ setup_general_page (PrefsDialog *dialog)
dialog);
create_download_path_button (dialog);
- create_search_engine_combo (GTK_COMBO_BOX (dialog->search_engine_combo));
}
static void
diff --git a/src/resources/epiphany.gresource.xml b/src/resources/epiphany.gresource.xml
index 0558568..8580f8f 100644
--- a/src/resources/epiphany.gresource.xml
+++ b/src/resources/epiphany.gresource.xml
@@ -26,6 +26,7 @@
<file preprocess="xml-stripblanks" compressed="true">gtk/passwords-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/prefs-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/prefs-lang-dialog.ui</file>
+ <file preprocess="xml-stripblanks" compressed="true">gtk/search-engine-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/shortcuts-dialog.ui</file>
</gresource>
<gresource prefix="/org/gnome/Epiphany/icons">
diff --git a/src/resources/gtk/prefs-dialog.ui b/src/resources/gtk/prefs-dialog.ui
index 7af529c..c22cb67 100644
--- a/src/resources/gtk/prefs-dialog.ui
+++ b/src/resources/gtk/prefs-dialog.ui
@@ -1,16 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.0"/>
- <object class="GtkListStore" id="liststore1">
- <columns>
- <!-- column-name name -->
- <column type="gchararray"/>
- <!-- column-name stock url -->
- <column type="gchararray"/>
- <!-- column-name url -->
- <column type="gchararray"/>
- </columns>
- </object>
<template class="PrefsDialog" parent="GtkDialog">
<property name="role">epiphany-preferences</property>
<property name="modal">True</property>
@@ -169,47 +159,44 @@
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Search</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- </child>
- <child>
<object class="GtkBox">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="spacing">6</property>
- <property name="margin-start">12</property>
<child>
- <object class="GtkBox">
+ <object class="GtkLabel">
<property name="visible">True</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Engine:</property>
- <property name="use-underline">True</property>
- <property name="mnemonic-widget">search_engine_combo</property>
- </object>
- </child>
- <child>
- <object class="GtkComboBox" id="search_engine_combo">
- <property name="visible">True</property>
- <property name="model">liststore1</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Search Engines</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="search_engine_dialog_button">
+ <property name="label" translatable="yes">_Manage Search Engines…</property>
+ <property name="visible">True</property>
+ <property name="use-underline">True</property>
+ <signal name="clicked" handler="on_search_engine_dialog_button_clicked"/>
</object>
</child>
</object>
</child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="margin_left">12</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">You can select different search engines to
use.</property>
+ <attributes>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
</object>
</child>
<child>
diff --git a/src/resources/gtk/search-engine-dialog.ui b/src/resources/gtk/search-engine-dialog.ui
new file mode 100644
index 0000000..2e7d630
--- /dev/null
+++ b/src/resources/gtk/search-engine-dialog.ui
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.10"/>
+ <template class="EphySearchEngineDialog" parent="GtkDialog">
+ <property name="modal">True</property>
+ <property name="window_position">center</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <property name="title" translatable="yes">Manage Search Engines</property>
+ <property name="show-close-button">True</property>
+ </object>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin">12</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkListBox" id="search_engine_list_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="selection-mode">single</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkButton" id="search_engine_add_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="on_search_engine_add_button_clicked"/>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">list-add-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="search_engine_remove_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="on_search_engine_remove_button_clicked"/>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">list-remove-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Name</property>
+ <property name="justify">right</property>
+ <property name="margin">6</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Address</property>
+ <property name="justify">right</property>
+ <property name="margin">6</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="search_engine_name_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="width_chars">40</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Bang</property>
+ <property name="justify">right</property>
+ <property name="margin">6</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="search_engine_bang_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="search_engine_address_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="width_chars">40</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Default</property>
+ <property name="justify">right</property>
+ <property name="margin">6</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="search_engine_default_switch">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="halign">start</property>
+ <signal name="notify::active"
handler="on_default_search_engine_switch_state_modified"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">dialog-information-symbolic</property>
+ <property name="icon_size">6</property>
+ <property name="margin_left">6</property>
+ <property name="margin_right">6</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">end</property>
+ <property name="label" translatable="yes">To determine the search address, perform a
search using the search engine that you want to add and check the resulting address. Remove the search term
from the resulting address and replace it with %s.</property>
+ <property name="wrap">True</property>
+ <property name="max_width_chars">40</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </template>
+</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]