[gnome-builder] Search Feature in Terminal
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] Search Feature in Terminal
- Date: Sat, 18 Feb 2017 18:18:07 +0000 (UTC)
commit 4b1ecbe4824c2bbc9aad9565dbea7d3f53306dab
Author: kritarth <kritarth 3010 gmail com>
Date: Sat Jan 21 01:52:06 2017 +0530
Search Feature in Terminal
round 4
Created separate class for the search revealer ui. This helped in
making the code more compact and readable.
https://bugzilla.gnome.org/show_bug.cgi?id=763022
contrib/gd/Makefile.am | 11 +-
libide/Makefile.am | 3 +-
plugins/terminal/Makefile.am | 8 +-
plugins/terminal/gb-terminal-search-private.h | 62 ++++
plugins/terminal/gb-terminal-search.c | 395 +++++++++++++++++++++++++
plugins/terminal/gb-terminal-search.h | 39 +++
plugins/terminal/gb-terminal-search.ui | 220 ++++++++++++++
plugins/terminal/gb-terminal-view-private.h | 13 +
plugins/terminal/gb-terminal-view.c | 36 ++-
plugins/terminal/gb-terminal-view.h | 4 +-
plugins/terminal/gb-terminal-view.ui | 46 ++--
plugins/terminal/gb-terminal.c | 36 +++
plugins/terminal/gb-terminal.gresource.xml | 1 +
13 files changed, 842 insertions(+), 32 deletions(-)
---
diff --git a/contrib/gd/Makefile.am b/contrib/gd/Makefile.am
index 5ac2bd5..58c1820 100644
--- a/contrib/gd/Makefile.am
+++ b/contrib/gd/Makefile.am
@@ -3,14 +3,15 @@ CLEANFILES =
BUILT_SOURCES =
EXTRA_DIST =
-noinst_LTLIBRARIES = libgd.la
+pkglibdir = $(libdir)/gnome-builder
+pkglib_LTLIBRARIES = libgd-private.la
-libgd_la_SOURCES = \
+libgd_private_la_SOURCES = \
gd-tagged-entry.c \
gd-tagged-entry.h \
$(NULL)
-nodist_libgd_la_SOURCES = \
+nodist_libgd_private_la_SOURCES = \
gd-resources.c \
gd-resources.h
@@ -20,7 +21,7 @@ glib_resources_xml = gd-tagged-entry.gresource.xml
glib_resources_namespace = gd
include $(top_srcdir)/build/autotools/Makefile.am.gresources
-libgd_la_CFLAGS = $(GD_CFLAGS)
-libgd_la_LIBADD = $(GD_LIBS)
+libgd_private_la_CFLAGS = $(GD_CFLAGS)
+libgd_private_la_LIBADD = $(GD_LIBS)
-include $(top_srcdir)/git.mk
diff --git a/libide/Makefile.am b/libide/Makefile.am
index ee3ac39..0577dd3 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -588,6 +588,7 @@ libide_1_0_la_LDFLAGS = \
$(OPTIMIZE_LDFLAGS) \
-avoid-version \
-no-undefined \
+ --no-as-needed \
-export-symbols-regex '^(ide_|_ide_).*' \
$(NULL)
@@ -597,7 +598,7 @@ libide_1_0_la_LIBADD = \
-lm \
$(top_builddir)/data/icons/hicolor/libicons.la \
$(top_builddir)/contrib/egg/libegg-private.la \
- $(top_builddir)/contrib/gd/libgd.la \
+ $(top_builddir)/contrib/gd/libgd-private.la \
$(top_builddir)/contrib/jsonrpc-glib/libjsonrpc-glib.la \
$(top_builddir)/contrib/nautilus/libnautilus.la \
$(top_builddir)/contrib/pnl/libpanel-gtk.la \
diff --git a/plugins/terminal/Makefile.am b/plugins/terminal/Makefile.am
index 17c2f13..5483a50 100644
--- a/plugins/terminal/Makefile.am
+++ b/plugins/terminal/Makefile.am
@@ -23,6 +23,9 @@ libterminal_la_SOURCES = \
gb-terminal-view-private.h \
gb-terminal-view-actions.c \
gb-terminal-view-actions.h \
+ gb-terminal-search.c \
+ gb-terminal-search.h \
+ gb-terminal-search-private.h \
gb-terminal-workbench-addin.c \
gb-terminal-workbench-addin.h \
$(NULL)
@@ -33,7 +36,10 @@ nodist_libterminal_la_SOURCES = \
$(NULL)
libterminal_la_CFLAGS = $(PLUGIN_CFLAGS) $(TERMINAL_CFLAGS)
-libterminal_la_LIBADD = $(TERMINAL_LIBS)
+libterminal_la_LIBADD = \
+ $(TERMINAL_LIBS) \
+ $(top_builddir)/contrib/gd/libgd-private.la \
+ $(NULL)
libterminal_la_LDFLAGS = $(PLUGIN_LDFLAGS)
glib_resources_c = gb-terminal-resources.c
diff --git a/plugins/terminal/gb-terminal-search-private.h b/plugins/terminal/gb-terminal-search-private.h
new file mode 100644
index 0000000..0ff7833
--- /dev/null
+++ b/plugins/terminal/gb-terminal-search-private.h
@@ -0,0 +1,62 @@
+/* gb-terminal-view-private.h
+ *
+ * Copyright (C) 2015 Sebastien Lafargue <slafargue gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GB_TERMINAL_SEARCH_PRIVATE_H
+#define GB_TERMINAL_SEARCH_PRIVATE_H
+
+#include <gd-tagged-entry.h>
+#include <ide.h>
+#include <vte/vte.h>
+
+G_BEGIN_DECLS
+
+struct _GbTerminalSearch
+{
+ GtkBin parent_instance;
+
+ VteTerminal *terminal;
+
+ GtkRevealer *search_revealer;
+
+ GdTaggedEntry *search_entry;
+
+ GtkButton *search_prev_button;
+ GtkButton *search_next_button;
+ GtkButton *close_button;
+
+ GtkGrid *search_options;
+
+ GtkToggleButton *reveal_button;
+ GtkToggleButton *match_case_checkbutton;
+ GtkToggleButton *entire_word_checkbutton;
+ GtkToggleButton *regex_checkbutton;
+ GtkToggleButton *wrap_around_checkbutton;
+
+ /* Cached regex */
+ gboolean regex_caseless;
+ gchar *regex_pattern;
+ VteRegex *regex;
+
+ GtkClipboard *clipboard;
+ gchar *selected_text;
+ gchar *selection_buffer;
+};
+
+G_END_DECLS
+
+#endif /* GB_TERMINAL_SEARCH_PRIVATE_H */
diff --git a/plugins/terminal/gb-terminal-search.c b/plugins/terminal/gb-terminal-search.c
new file mode 100644
index 0000000..70c8246
--- /dev/null
+++ b/plugins/terminal/gb-terminal-search.c
@@ -0,0 +1,395 @@
+/* gb-terminal-search.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "gb-terminal-search"
+#define PCRE2_CODE_UNIT_WIDTH 0
+
+#include "config.h"
+
+#include <fcntl.h>
+#include <glib/gi18n.h>
+#include <ide.h>
+#include <pcre2.h>
+#include <stdlib.h>
+#include <vte/vte.h>
+#include <unistd.h>
+
+#include "gb-terminal-search.h"
+#include "gb-terminal-search-private.h"
+
+G_DEFINE_TYPE (GbTerminalSearch, gb_terminal_search, GTK_TYPE_BIN)
+
+enum {
+ PROP_0,
+ PROP_REGEX,
+ PROP_WRAP_AROUND,
+ LAST_PROP
+};
+
+enum {
+ SEARCH,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+static GParamSpec *properties[LAST_PROP];
+
+static void
+update_sensitivity (GbTerminalSearch *self)
+{
+ gboolean can_search;
+
+ can_search = self->regex != NULL;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->search_prev_button), can_search);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->search_next_button), can_search);
+}
+
+static void
+perform_search (GbTerminalSearch *self,
+ gboolean backward)
+{
+ g_assert (GB_IS_TERMINAL_SEARCH (self));
+
+ if (self->regex == NULL)
+ return;
+
+ g_signal_emit (self, signals[SEARCH], 0, backward);
+}
+
+static void
+close_clicked_cb (GtkButton *button,
+ GbTerminalSearch *self)
+{
+ g_assert (GB_IS_TERMINAL_SEARCH (self));
+
+ gtk_revealer_set_reveal_child(self->search_revealer, FALSE);
+}
+
+static void
+search_button_clicked_cb (GtkButton *button,
+ GbTerminalSearch *self)
+{
+ g_assert (GB_IS_TERMINAL_SEARCH (self));
+
+ perform_search (self, button == self->search_prev_button);
+}
+
+static void
+update_regex (GbTerminalSearch *self)
+{
+ const char *search_text;
+ gboolean caseless;
+ g_autofree gchar *pattern = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (GB_IS_TERMINAL_SEARCH (self));
+
+ search_text = gtk_entry_get_text (GTK_ENTRY (self->search_entry));
+ caseless = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->match_case_checkbutton));
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->regex_checkbutton)))
+ pattern = g_strdup (search_text);
+ else
+ pattern = g_regex_escape_string (search_text, -1);
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->entire_word_checkbutton)))
+ {
+ char *new_pattern;
+ new_pattern = g_strdup_printf ("\\b%s\\b", pattern);
+ g_free (pattern);
+ pattern = new_pattern;
+ }
+
+ if (self->regex_caseless == caseless &&
+ g_strcmp0 (self->regex_pattern, pattern) == 0)
+ return;
+
+ if (self->regex)
+ {
+ vte_regex_unref (self->regex);
+ }
+
+ g_clear_pointer (&self->regex_pattern, g_free);
+
+ if (search_text[0] != '\0')
+ {
+ guint32 compile_flags;
+
+ compile_flags = PCRE2_UTF | PCRE2_NO_UTF_CHECK | PCRE2_MULTILINE;
+ if (caseless)
+ compile_flags |= PCRE2_CASELESS;
+
+ self->regex = vte_regex_new_for_search (pattern, -1, compile_flags, &error);
+
+ if (self->regex != NULL)
+ self->regex_pattern = g_steal_pointer (&pattern);
+ }
+ else
+ self->regex = NULL;
+
+ update_sensitivity (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_REGEX]);
+}
+
+static void
+search_text_changed_cb (GdTaggedEntry *search_entry,
+ GbTerminalSearch *self)
+{
+ update_regex (self);
+}
+
+static void
+search_parameters_changed_cb (GtkToggleButton *button,
+ GbTerminalSearch *self)
+{
+ update_regex (self);
+}
+
+static void
+wrap_around_toggled_cb (GtkToggleButton *button,
+ GbTerminalSearch *self)
+{
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WRAP_AROUND]);
+}
+
+static void
+reveal_options_changed_cb (GtkToggleButton *button,
+ GbTerminalSearch *self)
+{
+ g_assert (GB_IS_TERMINAL_SEARCH (self));
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->reveal_button)))
+ gtk_widget_set_visible (GTK_WIDGET (self->search_options), TRUE);
+ else
+ gtk_widget_set_visible (GTK_WIDGET (self->search_options), FALSE);
+}
+
+static void
+search_overlay_notify_regex_cb (VteTerminal *terminal,
+ GParamSpec *pspec G_GNUC_UNUSED,
+ GbTerminalSearch *self)
+{
+ VteRegex *regex;
+
+ g_assert (GB_IS_TERMINAL_SEARCH (self));
+ g_assert (VTE_IS_TERMINAL (terminal));
+
+ regex = terminal_search_get_regex (self);
+ vte_terminal_search_set_regex (VTE_TERMINAL (terminal), regex, 0);
+}
+
+static void
+search_overlay_notify_wrap_around_cb (VteTerminal *terminal,
+ GParamSpec *pspec G_GNUC_UNUSED,
+ GbTerminalSearch *self)
+{
+ gboolean wrap;
+
+ g_assert (GB_IS_TERMINAL_SEARCH (self));
+ g_assert (VTE_IS_TERMINAL (terminal));
+
+ wrap = terminal_search_get_wrap_around (self);
+ vte_terminal_search_set_wrap_around (terminal, wrap);
+}
+
+static void
+search_overlay_search_cb (VteTerminal *terminal,
+ gboolean backward,
+ GbTerminalSearch *self)
+{
+ g_assert (VTE_IS_TERMINAL (terminal));
+
+ if (backward)
+ vte_terminal_search_find_previous (terminal);
+ else
+ vte_terminal_search_find_next (terminal);
+}
+
+static void
+search_revealer_cb (GtkRevealer *search_revealer,
+ GParamSpec *pspec G_GNUC_UNUSED,
+ GbTerminalSearch *self)
+{
+ g_assert (GB_IS_TERMINAL_SEARCH (self));
+
+ if (gtk_revealer_get_child_revealed (search_revealer))
+ {
+ if (vte_terminal_get_has_selection (self->terminal))
+ {
+ vte_terminal_copy_primary (self->terminal);
+ self->selected_text = gtk_clipboard_wait_for_text (self->clipboard);
+ gtk_entry_set_text (GTK_ENTRY (self->search_entry), self->selected_text);
+ }
+ gtk_widget_grab_focus (GTK_WIDGET (self->search_entry));
+ }
+ else
+ {
+ gtk_revealer_set_reveal_child (self->search_revealer, FALSE);
+ }
+}
+
+static void
+gb_terminal_search_connect_terminal (GbTerminalSearch *self)
+{
+ g_signal_connect_object (self,
+ "notify::regex",
+ G_CALLBACK (search_overlay_notify_regex_cb),
+ self->terminal,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self,
+ "notify::wrap-around",
+ G_CALLBACK (search_overlay_notify_wrap_around_cb),
+ self->terminal,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self,
+ "search",
+ G_CALLBACK (search_overlay_search_cb),
+ self->terminal,
+ G_CONNECT_SWAPPED);
+}
+
+static void
+gb_terminal_search_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbTerminalSearch *self = GB_TERMINAL_SEARCH (object);
+
+ switch (prop_id)
+ {
+ case PROP_REGEX:
+ g_value_set_boxed (value, terminal_search_get_regex (self));
+ break;
+
+ case PROP_WRAP_AROUND:
+ g_value_set_boolean (value, terminal_search_get_wrap_around (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gb_terminal_search_class_init (GbTerminalSearchClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = gb_terminal_search_get_property;
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/builder/plugins/terminal/gb-terminal-search.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, GbTerminalSearch, search_prev_button);
+ gtk_widget_class_bind_template_child (widget_class, GbTerminalSearch, search_next_button);
+ gtk_widget_class_bind_template_child (widget_class, GbTerminalSearch, close_button);
+ gtk_widget_class_bind_template_child (widget_class, GbTerminalSearch, search_entry);
+ gtk_widget_class_bind_template_child (widget_class, GbTerminalSearch, match_case_checkbutton);
+ gtk_widget_class_bind_template_child (widget_class, GbTerminalSearch, entire_word_checkbutton);
+ gtk_widget_class_bind_template_child (widget_class, GbTerminalSearch, regex_checkbutton);
+ gtk_widget_class_bind_template_child (widget_class, GbTerminalSearch, wrap_around_checkbutton);
+ gtk_widget_class_bind_template_child (widget_class, GbTerminalSearch, reveal_button);
+ gtk_widget_class_bind_template_child (widget_class, GbTerminalSearch, search_revealer);
+ gtk_widget_class_bind_template_child (widget_class, GbTerminalSearch, search_options);
+
+ g_type_ensure (GD_TYPE_TAGGED_ENTRY);
+
+ signals[SEARCH] =
+ g_signal_new ("search",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_BOOLEAN);
+
+ properties[PROP_REGEX] =
+ g_param_spec_boxed ("regex", NULL, NULL,
+ VTE_TYPE_REGEX,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_WRAP_AROUND] =
+ g_param_spec_boolean ("wrap-around", NULL, NULL,
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, properties);
+}
+
+static void
+gb_terminal_search_init (GbTerminalSearch *self)
+{
+ self->regex_caseless = FALSE;
+ self->regex_pattern = 0;
+
+ self->clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ g_signal_connect (self->search_prev_button, "clicked", G_CALLBACK (search_button_clicked_cb), self);
+ g_signal_connect (self->search_next_button, "clicked", G_CALLBACK (search_button_clicked_cb), self);
+ g_signal_connect (self->close_button, "clicked", G_CALLBACK (close_clicked_cb), self);
+ g_signal_connect (self->search_entry, "search-changed", G_CALLBACK (search_text_changed_cb), self);
+ g_signal_connect (self->match_case_checkbutton, "toggled", G_CALLBACK (search_parameters_changed_cb),
self);
+ g_signal_connect (self->entire_word_checkbutton, "toggled", G_CALLBACK (search_parameters_changed_cb),
self);
+ g_signal_connect (self->regex_checkbutton, "toggled", G_CALLBACK (search_parameters_changed_cb), self);
+ g_signal_connect (self->reveal_button, "toggled", G_CALLBACK (reveal_options_changed_cb), self);
+ g_signal_connect (self->wrap_around_checkbutton, "toggled", G_CALLBACK (wrap_around_toggled_cb), self);
+ g_signal_connect (self->search_revealer, "notify::child-revealed", G_CALLBACK (search_revealer_cb), self);
+}
+
+
+void
+gb_terminal_search_set_terminal (GbTerminalSearch *self,
+ VteTerminal *terminal)
+{
+ g_assert (GB_IS_TERMINAL_SEARCH (self));
+
+ self->terminal = terminal;
+ gb_terminal_search_connect_terminal (self);
+}
+
+VteRegex *
+terminal_search_get_regex (GbTerminalSearch *self)
+{
+ g_return_val_if_fail (GB_IS_TERMINAL_SEARCH (self), NULL);
+
+ return self->regex;
+}
+
+gboolean
+terminal_search_get_wrap_around (GbTerminalSearch *self)
+{
+ g_return_val_if_fail (GB_IS_TERMINAL_SEARCH (self), FALSE);
+
+ return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->wrap_around_checkbutton));
+}
+
+GtkRevealer *
+terminal_search_get_revealer (GbTerminalSearch *self)
+{
+ g_return_val_if_fail (GB_IS_TERMINAL_SEARCH (self), FALSE);
+
+ return self->search_revealer;
+}
\ No newline at end of file
diff --git a/plugins/terminal/gb-terminal-search.h b/plugins/terminal/gb-terminal-search.h
new file mode 100644
index 0000000..e300940
--- /dev/null
+++ b/plugins/terminal/gb-terminal-search.h
@@ -0,0 +1,39 @@
+/* gb-terminal-view.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GB_TERMINAL_SEARCH_H
+#define GB_TERMINAL_SEARCH_H
+
+#include <ide.h>
+#include <vte/vte.h>
+
+G_BEGIN_DECLS
+
+#define GB_TYPE_TERMINAL_SEARCH (gb_terminal_search_get_type())
+
+G_DECLARE_FINAL_TYPE (GbTerminalSearch, gb_terminal_search, GB, TERMINAL_SEARCH, GtkBin)
+
+VteRegex *terminal_search_get_regex (GbTerminalSearch *self);
+gboolean terminal_search_get_wrap_around (GbTerminalSearch *self);
+void gb_terminal_search_set_terminal (GbTerminalSearch *self,
+ VteTerminal *terminal);
+GtkRevealer *terminal_search_get_revealer (GbTerminalSearch *self);
+
+G_END_DECLS
+
+#endif /* GB_TERMINAL_SEARCH_H */
diff --git a/plugins/terminal/gb-terminal-search.ui b/plugins/terminal/gb-terminal-search.ui
new file mode 100644
index 0000000..1b1f0e6
--- /dev/null
+++ b/plugins/terminal/gb-terminal-search.ui
@@ -0,0 +1,220 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- <template class="GbTerminalSearch" parent="GtkBin">
+ <child> -->
+ <object class="GtkRevealer" id="search_revealer">
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkFrame">
+ <property name="visible">true</property>
+ <property name="margin-end">12</property>
+ <style>
+ <class name="gb-search-frame"/>
+ </style>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">true</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">7</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">true</property>
+ <property name="can_focus">false</property>
+ <property name="row_spacing">8</property>
+ <property name="column_spacing">8</property>
+ <child>
+ <object class="GdTaggedEntry" id="search_entry">
+ <property name="visible">true</property>
+ <property name="can_focus">true</property>
+ <property name="width-chars">20</property>
+ <property name="max-width-chars">30</property>
+ <property name="primary_icon_name">edit-find-symbolic</property>
+ <property name="primary_icon_activatable">false</property>
+ <property name="primary_icon_sensitive">false</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="homogeneous">true</property>
+ <property name="visible">true</property>
+ <property name="can_focus">false</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="linked"/>
+ </style>
+ <child>
+ <object class="GtkButton" id="search_prev_button">
+ <property name="visible">true</property>
+ <property name="can_focus">false</property>
+ <property name="receives_default">true</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">true</property>
+ <property name="can_focus">false</property>
+ <property name="icon_name">go-up-symbolic</property>
+ <property name="icon_size">1</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_next_button">
+ <property name="visible">true</property>
+ <property name="can_focus">false</property>
+ <property name="receives_default">true</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">true</property>
+ <property name="can_focus">false</property>
+ <property name="icon_name">go-down-symbolic</property>
+ <property name="icon_size">1</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="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="reveal_button">
+ <property name="action-target">true</property>
+ <property name="tooltip-text" translatable="yes">Show or hide search options such as
case sensitivity</property>
+ <property name="visible">true</property>
+ <property name="can_focus">true</property>
+ <property name="receives_default">true</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">true</property>
+ <property name="can_focus">false</property>
+ <property name="icon_name">emblem-system-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="close_button">
+ <property name="visible">true</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="focus_on_click">false</property>
+ <style>
+ <class name="close"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">true</property>
+ <property name="icon_name">window-close-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">0</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="GtkGrid" id="search_options">
+ <property name="visible">false</property>
+ <property name="can_focus">false</property>
+ <property name="column_spacing">8</property>
+ <child>
+ <object class="GtkCheckButton" id="regex_checkbutton">
+ <property name="label" translatable="yes">Regex</property>
+ <property name="visible">true</property>
+ <property name="can_focus">false</property>
+ <property name="receives_default">false</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">true</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="match_case_checkbutton">
+ <property name="label" translatable="yes">Case sensitive</property>
+ <property name="visible">true</property>
+ <property name="can_focus">false</property>
+ <property name="receives_default">false</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">true</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="entire_word_checkbutton">
+ <property name="label" translatable="yes">Match whole word</property>
+ <property name="visible">true</property>
+ <property name="can_focus">false</property>
+ <property name="receives_default">false</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">true</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="wrap_around_checkbutton">
+ <property name="label" translatable="yes">Wrap around</property>
+ <property name="visible">true</property>
+ <property name="can_focus">false</property>
+ <property name="receives_default">false</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">true</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">false</property>
+ <property name="fill">true</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <!-- </child>
+ </template> -->
+</interface>
\ No newline at end of file
diff --git a/plugins/terminal/gb-terminal-view-private.h b/plugins/terminal/gb-terminal-view-private.h
index 775ebdc..a615d37 100644
--- a/plugins/terminal/gb-terminal-view-private.h
+++ b/plugins/terminal/gb-terminal-view-private.h
@@ -19,21 +19,34 @@
#ifndef GB_TERMINAL_VIEW_PRIVATE_H
#define GB_TERMINAL_VIEW_PRIVATE_H
+#include <gd-tagged-entry.h>
#include <ide.h>
#include <vte/vte.h>
+#include "gb-terminal-search.h"
+#include "gb-terminal-search-private.h"
+
G_BEGIN_DECLS
struct _GbTerminalView
{
IdeLayoutView parent_instance;
+ GtkOverlay *terminal_overlay_top;
+ GtkOverlay *terminal_overlay_bottom;
+
+ GtkRevealer *search_revealer_top;
+ GtkRevealer *search_revealer_bottom;
+
VteTerminal *terminal_top;
VteTerminal *terminal_bottom;
GtkScrollbar *top_scrollbar;
GtkScrollbar *bottom_scrollbar;
+ GbTerminalSearch *tsearch;
+ GbTerminalSearch *bsearch;
+
GFile *save_as_file_top;
GFile *save_as_file_bottom;
diff --git a/plugins/terminal/gb-terminal-view.c b/plugins/terminal/gb-terminal-view.c
index bccac42..676b2cd 100644
--- a/plugins/terminal/gb-terminal-view.c
+++ b/plugins/terminal/gb-terminal-view.c
@@ -17,12 +17,14 @@
*/
#define G_LOG_DOMAIN "gb-terminal-view"
+#define PCRE2_CODE_UNIT_WIDTH 0
#include "config.h"
#include <fcntl.h>
#include <glib/gi18n.h>
#include <ide.h>
+#include <pcre2.h>
#include <stdlib.h>
#include <vte/vte.h>
#include <unistd.h>
@@ -43,7 +45,7 @@ enum {
LAST_PROP
};
-static GParamSpec *properties [LAST_PROP];
+static GParamSpec *properties[LAST_PROP];
static gchar *cached_shell;
/* TODO: allow palette to come from gnome-terminal. */
@@ -459,16 +461,18 @@ focus_in_event_cb (VteTerminal *terminal,
g_assert (GB_IS_TERMINAL_VIEW (self));
self->bottom_has_focus = (terminal != self->terminal_top);
-
+
if (terminal == self->terminal_top)
{
self->top_has_needs_attention = FALSE;
gb_terminal_set_needs_attention (self, FALSE, GTK_POS_TOP);
+ gtk_revealer_set_reveal_child (self->search_revealer_top, FALSE);
}
else if (terminal == self->terminal_bottom)
{
self->bottom_has_needs_attention = FALSE;
gb_terminal_set_needs_attention (self, FALSE, GTK_POS_BOTTOM);
+ gtk_revealer_set_reveal_child (self->search_revealer_bottom, FALSE);
}
return GDK_EVENT_PROPAGATE;
@@ -594,9 +598,18 @@ gb_terminal_set_split_view (IdeLayoutView *view,
GTK_WIDGET (self->terminal_bottom),
"position", 0,
NULL);
- gtk_widget_show (self->bottom_container);
+ gtk_widget_show ( GTK_WIDGET (self->terminal_overlay_bottom));
+
+ self->bsearch = g_object_new (GB_TYPE_TERMINAL_SEARCH, NULL);
+ self->search_revealer_bottom = terminal_search_get_revealer (self->bsearch);
+
+ gtk_overlay_add_overlay (self->terminal_overlay_bottom,
+ GTK_WIDGET (self->search_revealer_bottom));
gb_terminal_view_connect_terminal (self, self->terminal_bottom);
+
+ gb_terminal_search_set_terminal (self->bsearch, self->terminal_bottom);
+
style_context_changed (style_context, GB_TERMINAL_VIEW (view));
gtk_widget_grab_focus (GTK_WIDGET (self->terminal_bottom));
@@ -609,15 +622,19 @@ gb_terminal_set_split_view (IdeLayoutView *view,
}
else
{
+ gtk_container_remove (GTK_CONTAINER (self->terminal_overlay_bottom),
+ GTK_WIDGET (self->search_revealer_bottom));
gtk_container_remove (GTK_CONTAINER (self->bottom_container),
GTK_WIDGET (self->terminal_bottom));
- gtk_widget_hide (self->bottom_container);
+ gtk_widget_hide ( GTK_WIDGET (self->terminal_overlay_bottom));
self->terminal_bottom = NULL;
+ self->search_revealer_bottom = NULL;
self->bottom_has_focus = FALSE;
self->bottom_has_spawned = FALSE;
self->bottom_has_needs_attention = FALSE;
g_clear_object (&self->save_as_file_bottom);
+ g_clear_object (&self->bsearch);
gtk_widget_grab_focus (GTK_WIDGET (self->terminal_top));
}
}
@@ -765,6 +782,8 @@ gb_terminal_view_class_init (GbTerminalViewClass *klass)
gtk_widget_class_bind_template_child (widget_class, GbTerminalView, bottom_container);
gtk_widget_class_bind_template_child (widget_class, GbTerminalView, top_scrollbar);
gtk_widget_class_bind_template_child (widget_class, GbTerminalView, bottom_scrollbar);
+ gtk_widget_class_bind_template_child (widget_class, GbTerminalView, terminal_overlay_top);
+ gtk_widget_class_bind_template_child (widget_class, GbTerminalView, terminal_overlay_bottom);
g_type_ensure (VTE_TYPE_TERMINAL);
@@ -802,9 +821,18 @@ gb_terminal_view_init (GbTerminalView *self)
self->manage_spawn = TRUE;
+ self->tsearch = g_object_new (GB_TYPE_TERMINAL_SEARCH, NULL);
+ self->search_revealer_top = terminal_search_get_revealer (self->tsearch);
+
gtk_widget_init_template (GTK_WIDGET (self));
+ gtk_overlay_add_overlay (self->terminal_overlay_top,
+ GTK_WIDGET (self->search_revealer_top));
+
gb_terminal_view_connect_terminal (self, self->terminal_top);
+
+ gb_terminal_search_set_terminal (self->tsearch, self->terminal_top);
+
gb_terminal_view_actions_init (self);
settings = g_settings_new ("org.gnome.builder.terminal");
diff --git a/plugins/terminal/gb-terminal-view.h b/plugins/terminal/gb-terminal-view.h
index b4169da..278d42c 100644
--- a/plugins/terminal/gb-terminal-view.h
+++ b/plugins/terminal/gb-terminal-view.h
@@ -28,8 +28,8 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (GbTerminalView, gb_terminal_view, GB, TERMINAL_VIEW, IdeLayoutView)
-void gb_terminal_view_set_pty (GbTerminalView *self,
- VtePty *pty);
+void gb_terminal_view_set_pty (GbTerminalView *self,
+ VtePty *pty);
G_END_DECLS
diff --git a/plugins/terminal/gb-terminal-view.ui b/plugins/terminal/gb-terminal-view.ui
index 30a3ebe..871333a 100644
--- a/plugins/terminal/gb-terminal-view.ui
+++ b/plugins/terminal/gb-terminal-view.ui
@@ -9,39 +9,47 @@
<property name="orientation">vertical</property>
<property name="visible">true</property>
<child>
- <object class="GtkBox" id="top_container">
- <property name="orientation">horizontal</property>
+ <object class="GtkOverlay" id="terminal_overlay_top">
<property name="expand">true</property>
<property name="visible">true</property>
<child>
- <object class="GbTerminal" id="terminal_top">
- <property name="audible-bell">false</property>
+ <object class="GtkBox" id="top_container">
+ <property name="orientation">horizontal</property>
<property name="expand">true</property>
<property name="visible">true</property>
- <property name="scrollback-lines">0xffffffff</property>
- </object>
- </child>
- <child>
- <object class="GtkScrollbar" id="top_scrollbar">
- <property name="orientation">vertical</property>
- <property name="visible">true</property>
+ <child>
+ <object class="GbTerminal" id="terminal_top">
+ <property name="audible-bell">false</property>
+ <property name="expand">true</property>
+ <property name="visible">true</property>
+ <property name="scrollback-lines">0xffffffff</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrollbar" id="top_scrollbar">
+ <property name="orientation">vertical</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
</object>
</child>
</object>
- <packing>
- <property name="resize">true</property>
- <property name="shrink">true</property>
- </packing>
</child>
<child>
- <object class="GtkBox" id="bottom_container">
- <property name="orientation">horizontal</property>
+ <object class="GtkOverlay" id="terminal_overlay_bottom">
<property name="expand">true</property>
<property name="visible">false</property>
<child>
- <object class="GtkScrollbar" id="bottom_scrollbar">
- <property name="orientation">vertical</property>
+ <object class="GtkBox" id="bottom_container">
+ <property name="orientation">horizontal</property>
+ <property name="expand">true</property>
<property name="visible">true</property>
+ <child>
+ <object class="GtkScrollbar" id="bottom_scrollbar">
+ <property name="orientation">vertical</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
</object>
</child>
</object>
diff --git a/plugins/terminal/gb-terminal.c b/plugins/terminal/gb-terminal.c
index 872477e..8e64bf8 100644
--- a/plugins/terminal/gb-terminal.c
+++ b/plugins/terminal/gb-terminal.c
@@ -48,6 +48,7 @@ struct _GbTerminalClass
GtkWidget *widget);
void (*select_all) (GbTerminal *self,
gboolean all);
+ void (*search_reveal) (GbTerminal *self);
gboolean (*open_link) (GbTerminal *self);
gboolean (*copy_link_address) (GbTerminal *self);
};
@@ -59,6 +60,7 @@ enum {
OPEN_LINK,
POPULATE_POPUP,
SELECT_ALL,
+ SEARCH_REVEAL,
LAST_SIGNAL
};
@@ -233,6 +235,24 @@ gb_terminal_open_link (GbTerminal *self)
}
static void
+gb_terminal_real_search_reveal (GbTerminal *self)
+{
+ GtkWidget *parent_overlay;
+
+ g_assert (GB_IS_TERMINAL (self));
+
+ parent_overlay = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_OVERLAY);
+
+ if (parent_overlay != NULL)
+ {
+ GtkRevealer *revealer = ide_widget_find_child_typed (parent_overlay, GTK_TYPE_REVEALER);
+
+ if (revealer != NULL && !gtk_revealer_get_child_revealed (revealer))
+ gtk_revealer_set_reveal_child (revealer, TRUE);
+ }
+}
+
+static void
gb_terminal_class_init (GbTerminalClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
@@ -244,6 +264,7 @@ gb_terminal_class_init (GbTerminalClass *klass)
klass->copy_link_address = gb_terminal_copy_link_address;
klass->open_link = gb_terminal_open_link;
klass->select_all = gb_terminal_real_select_all;
+ klass->search_reveal = gb_terminal_real_search_reveal;
signals [COPY_LINK_ADDRESS] =
g_signal_new ("copy-link-address",
@@ -254,6 +275,15 @@ gb_terminal_class_init (GbTerminalClass *klass)
G_TYPE_BOOLEAN,
0);
+ signals [SEARCH_REVEAL] =
+ g_signal_new ("search-reveal",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GbTerminalClass, search_reveal),
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 0);
+
signals [OPEN_LINK] =
g_signal_new ("open-link",
G_TYPE_FROM_CLASS (klass),
@@ -296,6 +326,12 @@ gb_terminal_class_init (GbTerminalClass *klass)
GDK_SHIFT_MASK | GDK_CONTROL_MASK,
"paste-clipboard",
0);
+
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_f,
+ GDK_CONTROL_MASK,
+ "search-reveal",
+ 0);
}
static void
diff --git a/plugins/terminal/gb-terminal.gresource.xml b/plugins/terminal/gb-terminal.gresource.xml
index ab0134e..215c200 100644
--- a/plugins/terminal/gb-terminal.gresource.xml
+++ b/plugins/terminal/gb-terminal.gresource.xml
@@ -2,6 +2,7 @@
<gresources>
<gresource prefix="/org/gnome/builder/plugins/terminal">
<file>gb-terminal-view.ui</file>
+ <file>gb-terminal-search.ui</file>
<file>gtk/menus.ui</file>
<file>theme/shared.css</file>
</gresource>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]