diff --git a/src/plugins/grep/gbp-grep-editor-addin.c b/src/plugins/grep/gbp-grep-editor-addin.c new file mode 100644 index 0000000000000000000000000000000000000000..cf41c3901f08848e0cc157c0cbab6ad358b6e494 --- /dev/null +++ b/src/plugins/grep/gbp-grep-editor-addin.c @@ -0,0 +1,89 @@ +/* gbp-grep-editor-addin.c + * + * Copyright 2018-2019 Christian Hergert + * + * 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 . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#define G_LOG_DOMAIN "gbp-grep-editor-addin" + +#include "config.h" + +#include +#include +#include +#include + +#include "gbp-grep-editor-addin.h" +#include "gbp-grep-panel.h" + +struct _GbpGrepEditorAddin +{ + GObject parent_instance; + + GtkWidget *panel; +}; + +static void +gbp_grep_editor_addin_load (IdeEditorAddin *addin, + IdeEditorSurface *editor_surface) +{ + GbpGrepEditorAddin *self = (GbpGrepEditorAddin *)addin; + GtkWidget *utilities; + + g_assert (GBP_IS_GREP_EDITOR_ADDIN (self)); + + utilities = ide_editor_surface_get_utilities (IDE_EDITOR_SURFACE (editor_surface)); + + self->panel = gbp_grep_panel_new (); + gtk_container_add (GTK_CONTAINER (utilities), self->panel); + gtk_widget_show (self->panel); +} + +static void +gbp_grep_editor_addin_unload (IdeEditorAddin *addin, + IdeEditorSurface *editor_surface) +{ + GbpGrepEditorAddin *self = (GbpGrepEditorAddin *)addin; + + g_assert (IDE_IS_MAIN_THREAD ()); + g_assert (GBP_IS_GREP_EDITOR_ADDIN (self)); + + if (self->panel != NULL) + gtk_widget_destroy (GTK_WIDGET (self->panel)); + + g_assert (self->panel == NULL); +} + +static void +editor_addin_iface_init (IdeEditorAddinInterface *iface) +{ + iface->load = gbp_grep_editor_addin_load; + iface->unload = gbp_grep_editor_addin_unload; +} + +G_DEFINE_TYPE_WITH_CODE (GbpGrepEditorAddin, gbp_grep_editor_addin, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (IDE_TYPE_EDITOR_ADDIN, editor_addin_iface_init)) + +static void +gbp_grep_editor_addin_class_init (GbpGrepEditorAddinClass *klass) +{ +} + +static void +gbp_grep_editor_addin_init (GbpGrepEditorAddin *self) +{ +} diff --git a/src/plugins/grep/gbp-grep-editor-addin.h b/src/plugins/grep/gbp-grep-editor-addin.h new file mode 100644 index 0000000000000000000000000000000000000000..e88d813747539b96a11bb27f400408876e486e1b --- /dev/null +++ b/src/plugins/grep/gbp-grep-editor-addin.h @@ -0,0 +1,31 @@ +/* gbp-terminal-editor-addin.h + * + * Copyright 2018-2019 Christian Hergert + * + * 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 . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +#define GBP_TYPE_GREP_EDITOR_ADDIN (gbp_grep_editor_addin_get_type()) + +G_DECLARE_FINAL_TYPE (GbpGrepEditorAddin, gbp_grep_editor_addin, GBP, GREP_EDITOR_ADDIN, GObject) + +G_END_DECLS diff --git a/src/plugins/grep/gbp-grep-model.c b/src/plugins/grep/gbp-grep-model.c index ef0ea9e8a41f7f16861fe971d1c880e58b6b0f89..bdf4950d55f3016954ef2b43e9b750a9d840bd8d 100644 --- a/src/plugins/grep/gbp-grep-model.c +++ b/src/plugins/grep/gbp-grep-model.c @@ -220,6 +220,28 @@ gbp_grep_model_new (IdeContext *context) return g_steal_pointer (&self); } +GbpGrepModel * +gbp_grep_model_from (IdeContext *context, + GbpGrepModel *from) +{ + GbpGrepModel *self; + + g_return_val_if_fail (IDE_IS_CONTEXT (context), NULL); + + self = g_object_new (GBP_TYPE_GREP_MODEL, NULL); + self->context = g_object_ref (context); + + self->use_regex = gbp_grep_model_get_use_regex (from); + self->at_word_boundaries = gbp_grep_model_get_at_word_boundaries (from); + self->case_sensitive = gbp_grep_model_get_case_sensitive (from); + self->recursive = gbp_grep_model_get_recursive (from); + + self->query = gbp_grep_model_get_query (from); + self->directory = gbp_grep_model_get_directory (from); + + return g_steal_pointer (&self); +} + static void gbp_grep_model_dispose (GObject *object) { diff --git a/src/plugins/grep/gbp-grep-model.h b/src/plugins/grep/gbp-grep-model.h index 863934bf6f8d7f113b67381fd3424746a14666f3..66a72c50de6336350550e14d5273cd83c5c270a7 100644 --- a/src/plugins/grep/gbp-grep-model.h +++ b/src/plugins/grep/gbp-grep-model.h @@ -46,6 +46,8 @@ typedef struct G_DECLARE_FINAL_TYPE (GbpGrepModel, gbp_grep_model, GBP, GREP_MODEL, IdeObject) GbpGrepModel *gbp_grep_model_new (IdeContext *context); +GbpGrepModel *gbp_grep_model_from (IdeContext *context, + GbpGrepModel *from); GFile *gbp_grep_model_get_directory (GbpGrepModel *self); void gbp_grep_model_set_directory (GbpGrepModel *self, GFile *directory); diff --git a/src/plugins/grep/gbp-grep-panel.c b/src/plugins/grep/gbp-grep-panel.c index 82f6ca243f353ef570ae93974b10d96363639a13..7c2f8b31629c37efa1f043a6f2064b2637dabc3b 100644 --- a/src/plugins/grep/gbp-grep-panel.c +++ b/src/plugins/grep/gbp-grep-panel.c @@ -37,10 +37,18 @@ struct _GbpGrepPanel GtkTreeView *tree_view; GtkTreeViewColumn *toggle_column; GtkCheckButton *check; - GtkButton *close_button; GtkButton *replace_button; GtkEntry *replace_entry; GtkSpinner *spinner; + + GtkButton *find_button; + GtkEntry *find_entry; + GtkSpinner *find_spinner; + + GtkCheckButton *regex_button; + GtkCheckButton *whole_button; + GtkCheckButton *case_button; + GtkCheckButton *recursive_button; }; enum { @@ -355,6 +363,74 @@ gbp_grep_panel_replace_clicked_cb (GbpGrepPanel *self, g_object_ref (self)); } +static void +gbp_grep_panel_scan_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GbpGrepModel *model = (GbpGrepModel *)object; + g_autoptr(GbpGrepPanel) panel = user_data; + g_autoptr(GError) error = NULL; + + g_assert (GBP_IS_GREP_MODEL (model)); + g_assert (G_IS_ASYNC_RESULT (result)); + g_assert (GBP_IS_GREP_PANEL (panel)); + + if (!gbp_grep_model_scan_finish (model, result, &error)) + g_warning ("Failed to find files: %s", error->message); + else + gbp_grep_panel_set_model (panel, model); + + gtk_widget_grab_focus (GTK_WIDGET (panel)); +} + +static void +gbp_grep_panel_find_clicked_cb (GbpGrepPanel *self, + GtkButton *button) +{ + IdeContext *context; + GbpGrepModel *model; + gboolean use_regex; + gboolean at_word_boundaries; + gboolean case_sensitive; + gboolean recursive; + + g_assert (GBP_IS_GREP_PANEL (self)); + g_assert (GTK_IS_BUTTON (button)); + + context = ide_widget_get_context (GTK_WIDGET (self)); + + use_regex = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->regex_button)); + at_word_boundaries = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->whole_button)); + case_sensitive = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->case_button)); + recursive = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->recursive_button)); + + model = gbp_grep_panel_get_model (self); + + if (model == NULL) + { + model = gbp_grep_model_new (context); + } + else + { + model = gbp_grep_model_from (context, model); + } + + gbp_grep_model_set_use_regex (model, use_regex); + gbp_grep_model_set_at_word_boundaries (model, at_word_boundaries); + gbp_grep_model_set_case_sensitive (model, case_sensitive); + gbp_grep_model_set_query (model, gtk_entry_get_text (self->find_entry)); + + if (gtk_widget_get_visible (GTK_WIDGET (self->recursive_button))) + gbp_grep_model_set_recursive (model, recursive); + else + gbp_grep_model_set_recursive (model, FALSE); + + gbp_grep_model_scan_async (model, + NULL, + gbp_grep_panel_scan_cb, + g_object_ref (self)); +} static void gbp_grep_panel_get_property (GObject *object, guint prop_id, @@ -411,11 +487,17 @@ gbp_grep_panel_class_init (GbpGrepPanelClass *klass) gtk_widget_class_set_css_name (widget_class, "gbpgreppanel"); gtk_widget_class_set_template_from_resource (widget_class, "/plugins/grep/gbp-grep-panel.ui"); - gtk_widget_class_bind_template_child (widget_class, GbpGrepPanel, close_button); gtk_widget_class_bind_template_child (widget_class, GbpGrepPanel, replace_button); gtk_widget_class_bind_template_child (widget_class, GbpGrepPanel, replace_entry); gtk_widget_class_bind_template_child (widget_class, GbpGrepPanel, spinner); gtk_widget_class_bind_template_child (widget_class, GbpGrepPanel, tree_view); + gtk_widget_class_bind_template_child (widget_class, GbpGrepPanel, find_spinner); + gtk_widget_class_bind_template_child (widget_class, GbpGrepPanel, find_entry); + gtk_widget_class_bind_template_child (widget_class, GbpGrepPanel, find_button); + gtk_widget_class_bind_template_child (widget_class, GbpGrepPanel, regex_button); + gtk_widget_class_bind_template_child (widget_class, GbpGrepPanel, whole_button); + gtk_widget_class_bind_template_child (widget_class, GbpGrepPanel, case_button); + gtk_widget_class_bind_template_child (widget_class, GbpGrepPanel, recursive_button); } static void @@ -426,15 +508,15 @@ gbp_grep_panel_init (GbpGrepPanel *self) gtk_widget_init_template (GTK_WIDGET (self)); - g_signal_connect_object (self->close_button, + g_signal_connect_object (self->replace_button, "clicked", - G_CALLBACK (gtk_widget_destroy), + G_CALLBACK (gbp_grep_panel_replace_clicked_cb), self, G_CONNECT_SWAPPED); - g_signal_connect_object (self->replace_button, + g_signal_connect_object (self->find_button, "clicked", - G_CALLBACK (gbp_grep_panel_replace_clicked_cb), + G_CALLBACK (gbp_grep_panel_find_clicked_cb), self, G_CONNECT_SWAPPED); @@ -513,6 +595,11 @@ void gbp_grep_panel_set_model (GbpGrepPanel *self, GbpGrepModel *model) { + gboolean use_regex; + gboolean at_word_boundaries; + gboolean case_sensitive; + gboolean recursive; + g_return_if_fail (GBP_IS_GREP_PANEL (self)); g_return_if_fail (!model || GBP_IS_GREP_MODEL (model)); @@ -525,9 +612,22 @@ gbp_grep_panel_set_model (GbpGrepPanel *self, gtk_widget_set_sensitive (GTK_WIDGET (self->replace_button), FALSE); else gtk_widget_set_sensitive (GTK_WIDGET (self->replace_button), TRUE); + + gtk_entry_set_text (self->find_entry, gbp_grep_model_get_query (model)); } gtk_tree_view_set_model (self->tree_view, GTK_TREE_MODEL (model)); + + // Align the UI with the settings on the model + use_regex = gbp_grep_model_get_use_regex (model); + at_word_boundaries = gbp_grep_model_get_at_word_boundaries (model); + case_sensitive = gbp_grep_model_get_case_sensitive (model); + recursive = gbp_grep_model_get_recursive (model); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->regex_button), use_regex); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->whole_button), at_word_boundaries); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->case_button), case_sensitive); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->recursive_button), recursive); } /** diff --git a/src/plugins/grep/gbp-grep-panel.ui b/src/plugins/grep/gbp-grep-panel.ui index 075256925ae7c87214a9419774b20c47aefd71e7..4a3c097a4568c824c97a3d2ca31d5719a9b4b7a3 100644 --- a/src/plugins/grep/gbp-grep-panel.ui +++ b/src/plugins/grep/gbp-grep-panel.ui @@ -30,7 +30,7 @@ horizontal true - + end @@ -40,22 +40,61 @@ 12 - + 12 false horizontal true + + + true + 30 + + - - Replace With - 1.0 + + Find + true true + + 1 + end + + + + + + + + 6 + 6 + 6 + 6 + horizontal + true + + + end + + + true + true + start + 12 + + + + + 12 + false + horizontal + true true @@ -76,16 +115,43 @@ end - - - Close - true - - - 0 - end - - + + + + + + + 6 + horizontal + true + + + true + Search _recursively through folders + true + true + + + + + Match _case when searching + true + true + true + + + + + Match _whole words + true + true + + + + + Allow regular _expressions + true + true @@ -96,8 +162,8 @@ horizontal - + diff --git a/src/plugins/grep/grep-plugin.c b/src/plugins/grep/grep-plugin.c index 561dc0b1ff216e1d9ccd163c0a9221970045cf5f..71dfcb95f70e8fd2336f7a6ac4d84ebb6862006e 100644 --- a/src/plugins/grep/grep-plugin.c +++ b/src/plugins/grep/grep-plugin.c @@ -21,9 +21,11 @@ #include "config.h" #include +#include #include #include "gbp-grep-tree-addin.h" +#include "gbp-grep-editor-addin.h" _IDE_EXTERN void _gbp_grep_register_types (PeasObjectModule *module) @@ -31,4 +33,7 @@ _gbp_grep_register_types (PeasObjectModule *module) peas_object_module_register_extension_type (module, IDE_TYPE_TREE_ADDIN, GBP_TYPE_GREP_TREE_ADDIN); + peas_object_module_register_extension_type (module, + IDE_TYPE_EDITOR_ADDIN, + GBP_TYPE_GREP_EDITOR_ADDIN); } diff --git a/src/plugins/grep/meson.build b/src/plugins/grep/meson.build index 0803c6e91c9fb8e9f064dc514683427f82e5f457..54a1e1f9bd584263fe50899bd406a751a1ea089b 100644 --- a/src/plugins/grep/meson.build +++ b/src/plugins/grep/meson.build @@ -5,6 +5,7 @@ plugins_sources += files([ 'gbp-grep-panel.c', 'gbp-grep-popover.c', 'gbp-grep-tree-addin.c', + 'gbp-grep-editor-addin.c', 'grep-plugin.c', ])