[anjuta/search-files] search: Initial "Find in files" dialog work
- From: Johannes Schmid <jhs src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [anjuta/search-files] search: Initial "Find in files" dialog work
- Date: Sat, 11 Feb 2012 18:00:09 +0000 (UTC)
commit 7180b3d8e1fe95cc0cefb51c9dbdf2d636ec1776
Author: Johannes Schmid <jhs gnome org>
Date: Fri Feb 10 22:35:39 2012 +0100
search: Initial "Find in files" dialog work
plugins/document-manager/Makefile.am | 6 +-
plugins/document-manager/action-callbacks.c | 14 +
plugins/document-manager/action-callbacks.h | 2 +
.../document-manager/anjuta-document-manager.ui | 225 +++++++++++
.../document-manager/anjuta-document-manager.xml | 2 +
plugins/document-manager/plugin.c | 16 +-
plugins/document-manager/plugin.h | 3 +
plugins/document-manager/search-file-command.c | 324 +++++++++++++++
plugins/document-manager/search-file-command.h | 59 +++
plugins/document-manager/search-files.c | 422 ++++++++++++++++++++
plugins/document-manager/search-files.h | 57 +++
11 files changed, 1122 insertions(+), 8 deletions(-)
---
diff --git a/plugins/document-manager/Makefile.am b/plugins/document-manager/Makefile.am
index 1e102e8..b962516 100644
--- a/plugins/document-manager/Makefile.am
+++ b/plugins/document-manager/Makefile.am
@@ -46,7 +46,11 @@ libanjuta_document_manager_la_SOURCES= \
search-box.h \
search-box.c \
anjuta-bookmarks.h \
- anjuta-bookmarks.c
+ anjuta-bookmarks.c \
+ search-files.c \
+ search-files.h \
+ search-file-command.c \
+ search-file-command.h
gsettings_in_file = org.gnome.anjuta.document-manager.gschema.xml.in
gsettings_SCHEMAS = $(gsettings_in_file:.xml.in=.xml)
diff --git a/plugins/document-manager/action-callbacks.c b/plugins/document-manager/action-callbacks.c
index 2b64379..3096783 100644
--- a/plugins/document-manager/action-callbacks.c
+++ b/plugins/document-manager/action-callbacks.c
@@ -45,6 +45,7 @@
#include "plugin.h"
#include "file_history.h"
#include "search-box.h"
+#include "search-files.h"
#include "anjuta-bookmarks.h"
static IAnjutaDocument *
@@ -911,6 +912,19 @@ on_search_popup_regex_search (GtkAction *action, gpointer user_data)
search_box_toggle_regex (SEARCH_BOX (search_box), regex_active);
}
+void
+on_search_find_in_files (GtkAction *action, gpointer user_data)
+{
+ DocmanPlugin *plugin;
+ plugin = ANJUTA_PLUGIN_DOCMAN (user_data);
+
+ if (!plugin->search_files)
+ {
+ plugin->search_files = G_OBJECT (search_files_new (ANJUTA_DOCMAN (plugin->docman)));
+ }
+ search_files_present (SEARCH_FILES(plugin->search_files));
+}
+
void
on_editor_add_view_activate (GtkAction *action, gpointer user_data)
{
diff --git a/plugins/document-manager/action-callbacks.h b/plugins/document-manager/action-callbacks.h
index fba2e87..b25afe7 100644
--- a/plugins/document-manager/action-callbacks.h
+++ b/plugins/document-manager/action-callbacks.h
@@ -103,6 +103,8 @@ void on_search_popup_clear_highlight (GtkAction *action, gpointer user_data);
void on_search_popup_regex_search (GtkAction *action, gpointer user_data);
+void on_search_find_in_files (GtkAction *action, gpointer user_data);
+
void on_next_document (GtkAction *action, gpointer user_data);
void on_previous_document (GtkAction *action, gpointer user_data);
diff --git a/plugins/document-manager/anjuta-document-manager.ui b/plugins/document-manager/anjuta-document-manager.ui
index 827b673..a3a522c 100644
--- a/plugins/document-manager/anjuta-document-manager.ui
+++ b/plugins/document-manager/anjuta-document-manager.ui
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.16"/>
+ <!-- interface-requires anjuta 0.0 -->
<object class="GtkAdjustment" id="adjustment1">
<property name="lower">1</property>
<property name="upper">1000</property>
@@ -14,6 +15,48 @@
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
+ <object class="GtkListStore" id="file_type_model">
+ <columns>
+ <!-- column-name Name -->
+ <column type="gchararray"/>
+ <!-- column-name mime-types -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">All Files</col>
+ <col id="1" translatable="yes"></col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">C/C++ Source files</col>
+ <col id="1" translatable="yes">text/x-c</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Vala Source files</col>
+ <col id="1" translatable="yes">text/x-vala</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Python Source files</col>
+ <col id="1" translatable="yes">text/x-python,application/x-extension-wsgi</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Javascript Source files</col>
+ <col id="1" translatable="yes">application/javascript</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">XML files</col>
+ <col id="1" translatable="yes">application/xml</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">User interface files</col>
+ <col id="1" translatable="yes">application/x-glade,application/x-designer</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Source files</col>
+ <col id="1" translatable="yes">text/source</col>
+ </row>
+ </data>
+ </object>
<object class="GtkListStore" id="model1">
<columns>
<!-- column-name gchararray -->
@@ -350,4 +393,186 @@
</object>
</child>
</object>
+ <object class="GtkWindow" id="search_files">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkGrid" id="main_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">5</property>
+ <property name="column_spacing">5</property>
+ <property name="n_rows">4</property>
+ <property name="n_columns">2</property>
+ <child>
+ <object class="GtkEntry" id="search_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <property name="invisible_char">â</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_stock">gtk-find</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="replace_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <property name="invisible_char">â</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_stock">gtk-find-and-replace</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="search_button">
+ <property name="label">gtk-find</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="search_files_search_clicked" swapped="yes"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="replace_button">
+ <property name="label" translatable="yes">Replace</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="use_action_appearance">False</property>
+ <signal name="clicked" handler="search_files_replace_clicked" swapped="yes"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">5</property>
+ <property name="column_spacing">5</property>
+ <property name="n_rows">1</property>
+ <property name="n_columns">2</property>
+ <child>
+ <object class="GtkComboBox" id="file_type_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="model">file_type_model</property>
+ <property name="active">0</property>
+ <property name="entry_text_column">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="AnjutaPmChooserButton" id="project_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="valign">start</property>
+ <property name="use_action_appearance">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="find_files_button">
+ <property name="label" translatable="yes">Find Files</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="use_action_appearance">False</property>
+ <signal name="clicked" handler="search_files_find_files_clicked" swapped="yes"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="files_tree">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="enable_search">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">2</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
</interface>
diff --git a/plugins/document-manager/anjuta-document-manager.xml b/plugins/document-manager/anjuta-document-manager.xml
index e544955..ed81080 100644
--- a/plugins/document-manager/anjuta-document-manager.xml
+++ b/plugins/document-manager/anjuta-document-manager.xml
@@ -49,6 +49,8 @@
<menuitem name="QuickSearchPrevious" action="ActionEditSearchFindPrevious"/>
<menuitem name="QuickReplace" action="ActionEditSearchReplace"/>
<separator name="separator8"/>
+ <menuitem name="FindFiles" action="ActionEditFindFiles"/>
+ <separator name="separator9"/>
</placeholder>
</menu>
</placeholder>
diff --git a/plugins/document-manager/plugin.c b/plugins/document-manager/plugin.c
index 1aaaa52..ec0fe8a 100644
--- a/plugins/document-manager/plugin.c
+++ b/plugins/document-manager/plugin.c
@@ -48,6 +48,7 @@
#include "action-callbacks.h"
#include "plugin.h"
#include "search-box.h"
+#include "search-files.h"
#include "anjuta-bookmarks.h"
#define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta-document-manager.xml"
@@ -278,7 +279,10 @@ static GtkActionEntry actions_search[] = {
G_CALLBACK (on_search_previous)},
{ "ActionSearchboxPopupClearHighlight", GTK_STOCK_FIND, N_("Clear Highlight"),
NULL, N_("Clear all highlighted text"),
- G_CALLBACK (on_search_popup_clear_highlight)}
+ G_CALLBACK (on_search_popup_clear_highlight)},
+ { "ActionEditFindFiles", GTK_STOCK_FIND_AND_REPLACE, N_("Find in Files"),
+ NULL, N_("Search in project files"),
+ G_CALLBACK (on_search_find_in_files)}
};
static GtkToggleActionEntry actions_searchbox_popup[] = {
@@ -1649,7 +1653,7 @@ activate_plugin (AnjutaPlugin *plugin)
gint i;
static gboolean initialized = FALSE;
GList *actions, *act;
-
+
DEBUG_PRINT ("%s", "DocmanPlugin: Activating document manager pluginâ");
dplugin = ANJUTA_PLUGIN_DOCMAN (plugin);
@@ -1659,7 +1663,7 @@ activate_plugin (AnjutaPlugin *plugin)
docman = anjuta_docman_new (dplugin);
dplugin->docman = docman;
- ANJUTA_DOCMAN(docman)->shell = plugin->shell;
+ ANJUTA_DOCMAN(docman)->shell = anjuta_plugin_get_shell(plugin);
g_signal_connect (G_OBJECT (docman), "document-added",
G_CALLBACK (on_document_added), plugin);
g_signal_connect (G_OBJECT (docman), "document-changed",
@@ -1729,16 +1733,14 @@ activate_plugin (AnjutaPlugin *plugin)
/* Create the default searchbox instance, but don't yet put it into
dplugin->vbox, to prevent the box being displayed at session start */
dplugin->search_box = search_box_new (ANJUTA_DOCMAN (docman));
-
+
/* Setup popup menu */
popup_menu = gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui),
"/PopupDocumentManager");
g_assert (popup_menu != NULL && GTK_IS_MENU (popup_menu));
anjuta_docman_set_popup_menu (ANJUTA_DOCMAN (docman), popup_menu);
- if (!initialized)
- {
- }
+
/* Connect to save session */
g_signal_connect (G_OBJECT (plugin->shell), "save-session",
G_CALLBACK (on_session_save), plugin);
diff --git a/plugins/document-manager/plugin.h b/plugins/document-manager/plugin.h
index 4644750..2cc127f 100644
--- a/plugins/document-manager/plugin.h
+++ b/plugins/document-manager/plugin.h
@@ -46,6 +46,9 @@ struct _DocmanPlugin{
/* SearchBox */
GtkWidget* search_box;
+
+ /* SearchFiles */
+ GObject* search_files;
/* Base box of the widget */
GtkWidget* vbox;
diff --git a/plugins/document-manager/search-file-command.c b/plugins/document-manager/search-file-command.c
new file mode 100644
index 0000000..b106ebb
--- /dev/null
+++ b/plugins/document-manager/search-file-command.c
@@ -0,0 +1,324 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) Johannes Schmid 2012 <jhs gnome org>
+ *
+ * anjuta 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.
+ *
+ * anjuta 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/>.
+ */
+
+#include "search-file-command.h"
+#include <string.h>
+
+struct _SearchFileCommandPrivate
+{
+ GFile* file;
+ gchar* pattern;
+ gchar* replace;
+ gboolean regex;
+
+ gint n_matches;
+};
+
+enum
+{
+ PROP_0,
+ PROP_FILE,
+ PROP_PATTERN,
+ PROP_REPLACE,
+ PROP_REGEX
+};
+
+#define BUFFER_SIZE 1024
+
+static void
+search_file_command_save (SearchFileCommand* cmd, const gchar* new_content, GError **error)
+{
+ GFileOutputStream* ostream;
+
+ ostream = g_file_replace (cmd->priv->file,
+ NULL,
+ TRUE,
+ G_FILE_CREATE_NONE,
+ NULL,
+ error);
+ if (*error)
+ {
+ return;
+ }
+ /* TODO: Convert to original encoding */
+ g_output_stream_write_all (G_OUTPUT_STREAM(ostream),
+ new_content,
+ strlen(new_content),
+ NULL,
+ NULL,
+ error);
+ g_object_unref (ostream);
+}
+
+static gchar*
+search_file_command_load (SearchFileCommand* cmd, GError **error)
+{
+ GString* content;
+ GFileInputStream* istream;
+ gchar buffer[BUFFER_SIZE];
+ gssize bytes_read;
+
+ istream = g_file_read (cmd->priv->file, NULL, error);
+ if (*error)
+ {
+ return NULL;
+ }
+
+ /* Read file into buffer */
+ content = g_string_new (NULL);
+ while ((bytes_read = g_input_stream_read (G_INPUT_STREAM (istream),
+ buffer,
+ BUFFER_SIZE,
+ NULL,
+ error)))
+ {
+ if (*error)
+ {
+ g_string_free (content, TRUE);
+ g_object_unref (istream);
+ return NULL;
+ }
+ /* TODO: Non-UTF8 files... */
+ g_string_append_len (content, buffer, bytes_read);
+ }
+ g_object_unref (istream);
+
+ return g_string_free (content, FALSE);
+}
+
+static guint
+search_file_command_run (AnjutaCommand* anjuta_cmd)
+{
+ SearchFileCommand* cmd = SEARCH_FILE_COMMAND(anjuta_cmd);
+ GError* error = NULL;
+ gchar* pattern;
+ gchar* replace;
+ gchar* content;
+
+ g_return_val_if_fail (cmd->priv->file != NULL && G_IS_FILE (cmd->priv->file), 1);
+
+ cmd->priv->n_matches = 0;
+
+ content = search_file_command_load (cmd, &error);
+ if (error)
+ {
+ int code = error->code;
+ g_error_free (error);
+ return code;
+ }
+
+ if (!cmd->priv->regex)
+ {
+ pattern = g_regex_escape_string (cmd->priv->pattern, -1);
+ if (cmd->priv->replace)
+ replace = g_regex_escape_string (cmd->priv->replace, -1);
+ else
+ replace = NULL;
+ }
+ else
+ {
+ pattern = g_strdup (cmd->priv->pattern);
+ if (cmd->priv->replace)
+ replace = g_strdup (cmd->priv->replace);
+ else
+ replace = NULL;
+ }
+
+ if (!replace)
+ {
+ GRegex *regex;
+ GMatchInfo *match_info;
+
+ regex = g_regex_new (pattern, 0, 0, NULL);
+ g_regex_match (regex, content, 0, &match_info);
+ while (g_match_info_matches (match_info))
+ {
+ cmd->priv->n_matches++;
+ g_match_info_next (match_info, NULL);
+ }
+ g_match_info_free (match_info);
+ g_regex_unref (regex);
+ }
+ else
+ {
+ gchar* new_content;
+ GRegex *regex;
+
+ regex = g_regex_new (pattern, 0, 0, NULL);
+ new_content = g_regex_replace (regex, content, -1, 0, replace, 0, NULL);
+ g_regex_unref (regex);
+
+ search_file_command_save (cmd, new_content, &error);
+ g_free (new_content);
+
+ if (error)
+ {
+ anjuta_async_command_set_error_message (anjuta_cmd, error->message);
+ return 1;
+ }
+ }
+ g_free (content);
+
+ return 0;
+}
+
+G_DEFINE_TYPE (SearchFileCommand, search_file_command, ANJUTA_TYPE_ASYNC_COMMAND);
+
+static void
+search_file_command_init (SearchFileCommand *cmd)
+{
+ cmd->priv = G_TYPE_INSTANCE_GET_PRIVATE (cmd, SEARCH_TYPE_FILE_COMMAND, SearchFileCommandPrivate);
+
+ cmd->priv->file = NULL;
+ cmd->priv->pattern = NULL;
+ cmd->priv->replace = NULL;
+ cmd->priv->regex = FALSE;
+}
+
+static void
+search_file_command_finalize (GObject *object)
+{
+ /* TODO: Add deinitalization code here */
+
+ G_OBJECT_CLASS (search_file_command_parent_class)->finalize (object);
+}
+
+static void
+search_file_command_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ SearchFileCommand* cmd;
+
+ g_return_if_fail (SEARCH_IS_FILE_COMMAND (object));
+
+ cmd = SEARCH_FILE_COMMAND (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILE:
+ if (cmd->priv->file)
+ g_object_unref (cmd->priv->file);
+ cmd->priv->file = g_value_dup_object (value);
+ break;
+ case PROP_PATTERN:
+ g_free (cmd->priv->pattern);
+ cmd->priv->pattern = g_value_dup_string (value);
+ break;
+ case PROP_REPLACE:
+ g_free (cmd->priv->replace);
+ cmd->priv->replace = g_value_dup_string (value);
+ break;
+ case PROP_REGEX:
+ cmd->priv->regex = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+search_file_command_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ SearchFileCommand* cmd;
+
+ g_return_if_fail (SEARCH_IS_FILE_COMMAND (object));
+
+ cmd = SEARCH_FILE_COMMAND (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILE:
+ g_value_set_object (value, cmd->priv->file);
+ break;
+ case PROP_PATTERN:
+ g_value_set_string (value, cmd->priv->pattern);
+ break;
+ case PROP_REPLACE:
+ g_value_set_string (value, cmd->priv->replace);
+ break;
+ case PROP_REGEX:
+ g_value_set_boolean (value, cmd->priv->regex);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+search_file_command_class_init (SearchFileCommandClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+ AnjutaCommandClass* command_class = ANJUTA_COMMAND_CLASS(klass);
+
+ object_class->finalize = search_file_command_finalize;
+ object_class->set_property = search_file_command_set_property;
+ object_class->get_property = search_file_command_get_property;
+
+ g_object_class_install_property (object_class,
+ PROP_FILE,
+ g_param_spec_object ("file",
+ "filename",
+ "Filename to search in",
+ G_TYPE_FILE,
+ G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_PATTERN,
+ g_param_spec_string ("pattern", "", "",
+ "",
+ G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_PATTERN,
+ g_param_spec_string ("replace", "", "",
+ "",
+ G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_REGEX,
+ g_param_spec_boolean ("regex", "", "",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ command_class->run = search_file_command_run;
+
+ g_type_class_add_private (klass, sizeof(SearchFileCommandPrivate));
+}
+
+
+SearchFileCommand*
+search_file_command_new (GFile* file, const gchar* pattern, const gchar* replace, gboolean regex)
+{
+ SearchFileCommand* command;
+
+ command = SEARCH_FILE_COMMAND (g_object_new (SEARCH_TYPE_FILE_COMMAND,
+ "file", file,
+ "pattern", pattern,
+ "replace", replace,
+ "regex", regex, NULL));
+ return command;
+}
+
+gint
+search_command_get_n_matches (SearchFileCommand* cmd)
+{
+ g_return_val_if_fail (cmd != NULL && !SEARCH_IS_FILE_COMMAND (cmd), 0);
+
+ return cmd->priv->n_matches;
+}
\ No newline at end of file
diff --git a/plugins/document-manager/search-file-command.h b/plugins/document-manager/search-file-command.h
new file mode 100644
index 0000000..ef606af
--- /dev/null
+++ b/plugins/document-manager/search-file-command.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) Johannes Schmid 2012 <jhs gnome org>
+ *
+ * anjuta 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.
+ *
+ * anjuta 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 _SEARCH_FILE_COMMAND_H_
+#define _SEARCH_FILE_COMMAND_H_
+
+#include <libanjuta/anjuta-async-command.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define SEARCH_TYPE_FILE_COMMAND (search_file_command_get_type ())
+#define SEARCH_FILE_COMMAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEARCH_TYPE_FILE_COMMAND, SearchFileCommand))
+#define SEARCH_FILE_COMMAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SEARCH_TYPE_FILE_COMMAND, SearchFileCommandClass))
+#define SEARCH_IS_FILE_COMMAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEARCH_TYPE_FILE_COMMAND))
+#define SEARCH_IS_FILE_COMMAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEARCH_TYPE_FILE_COMMAND))
+#define SEARCH_FILE_COMMAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SEARCH_TYPE_FILE_COMMAND, SearchFileCommandClass))
+
+typedef struct _SearchFileCommandClass SearchFileCommandClass;
+typedef struct _SearchFileCommand SearchFileCommand;
+typedef struct _SearchFileCommandPrivate SearchFileCommandPrivate;
+
+struct _SearchFileCommandClass
+{
+ AnjutaAsyncCommandClass parent_class;
+};
+
+struct _SearchFileCommand
+{
+ AnjutaAsyncCommand parent_instance;
+
+ SearchFileCommandPrivate* priv;
+};
+
+GType search_file_command_get_type (void) G_GNUC_CONST;
+SearchFileCommand* search_file_command_new (GFile* file,
+ const gchar* pattern,
+ const gchar* replace, gboolean regex);
+gint search_command_get_n_matches (SearchFileCommand* cmd);
+
+G_END_DECLS
+
+#endif /* _SEARCH_FILE_COMMAND_H_ */
diff --git a/plugins/document-manager/search-files.c b/plugins/document-manager/search-files.c
new file mode 100644
index 0000000..0162400
--- /dev/null
+++ b/plugins/document-manager/search-files.c
@@ -0,0 +1,422 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) Johannes Schmid 2012 <jhs gnome org>
+ *
+ * anjuta 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.
+ *
+ * anjuta 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/>.
+ */
+
+#include "search-files.h"
+#include <libanjuta/interfaces/ianjuta-project-manager.h>
+#include <libanjuta/interfaces/ianjuta-project-chooser.h>
+
+#define BUILDER_FILE PACKAGE_DATA_DIR"/glade/anjuta-document-manager.ui"
+
+struct _SearchFilesPrivate
+{
+ GtkBuilder* builder;
+
+ GtkWidget* main_box;
+
+ GtkWidget* search_button;
+ GtkWidget* replace_button;
+ GtkWidget* find_files_button;
+
+ GtkWidget* search_entry;
+ GtkWidget* replace_entry;
+
+ GtkWidget* files_combo;
+ GtkWidget* project_combo;
+ GtkWidget* file_type_combo;
+
+ GtkWidget* files_tree;
+ GtkTreeModel* files_model;
+
+ GtkWidget* files_tree_check;
+
+ AnjutaDocman* docman;
+ GtkWidget* dialog;
+};
+
+enum
+{
+ COLUMN_SELECTED,
+ COLUMN_FILENAME,
+ COLUMN_COUNT,
+ COLUMN_PULSE,
+ COLUMN_SPINNER,
+ COLUMN_FILE
+};
+
+G_DEFINE_TYPE (SearchFiles, search_files, G_TYPE_OBJECT);
+
+void search_files_search_clicked (SearchFiles* sf);
+void search_files_replace_clicked (SearchFiles* sf);
+void search_files_find_files_clicked (SearchFiles* sf);
+
+static void
+search_files_get_files (GFile* parent, GList** files, IAnjutaProjectManager* pm)
+{
+ GList* node;
+ GList* children = ianjuta_project_manager_get_children(pm, parent, NULL);
+ for (node = children;node != NULL; node = g_list_next(node))
+ {
+ search_files_get_files(G_FILE(node), files, pm);
+ g_message (g_file_get_path (G_FILE(node)));
+ }
+ g_list_foreach (children, (GFunc)g_object_unref, NULL);
+ g_list_free(children);
+}
+
+static void
+search_files_check_column_clicked (SearchFiles* sf,
+ GtkCheckButton* button)
+{
+
+}
+
+static void
+search_files_check_column_toggled (SearchFiles* sf,
+ GtkCellRenderer* renderer)
+{
+
+}
+
+void
+search_files_search_clicked (SearchFiles* sf)
+{
+
+}
+
+void
+search_files_replace_clicked (SearchFiles* sf)
+{
+
+}
+
+void
+search_files_find_files_clicked (SearchFiles* sf)
+{
+ GFile* selected;
+ IAnjutaProjectManager* pm;
+ GList* files;
+ GList* file;
+
+ gchar* project_uri = NULL;
+ GFile* project_file = NULL;
+
+ g_return_if_fail (sf != NULL && SEARCH_IS_FILES (sf));
+
+ gtk_list_store_clear(GTK_LIST_STORE (sf->priv->files_model));
+
+ pm = anjuta_shell_get_interface (sf->priv->docman->shell,
+ IAnjutaProjectManager,
+ NULL);
+ files = ianjuta_project_manager_get_elements(pm,
+ ANJUTA_PROJECT_SOURCE,
+ NULL);
+ anjuta_shell_get (sf->priv->docman->shell,
+ IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI,
+ G_TYPE_STRING,
+ &project_uri, NULL);
+
+ if (project_uri)
+ project_file = g_file_new_for_uri (project_uri);
+ g_free (project_uri);
+
+ for (file = files; file != NULL; file = g_list_next (file))
+ {
+ GtkTreeIter iter;
+
+ gchar* display_name = NULL;
+
+ if (project_file)
+ {
+ display_name = g_file_get_relative_path (project_file,
+ G_FILE (file->data));
+ if (!display_name)
+ continue;
+ }
+#if 0
+ if (!display_name)
+ display_name = g_file_get_path (G_FILE (file->data));
+ if (!display_name)
+ display_name = g_file_get_uri (G_FILE (file->data));
+#endif
+ gtk_list_store_append(GTK_LIST_STORE (sf->priv->files_model),
+ &iter);
+ gtk_list_store_set (GTK_LIST_STORE (sf->priv->files_model), &iter,
+ COLUMN_SELECTED, TRUE,
+ COLUMN_FILENAME, display_name,
+ COLUMN_FILE, file->data,
+ COLUMN_COUNT, 0,
+ COLUMN_SPINNER, FALSE,
+ COLUMN_PULSE, FALSE, -1);
+ }
+ g_object_unref (project_file);
+
+ g_list_foreach (files, (GFunc) g_object_unref, NULL);
+ g_list_free (files);
+}
+
+static void
+search_files_render_count (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ int count;
+ gchar* count_str;
+
+ gtk_tree_model_get (tree_model, iter,
+ COLUMN_COUNT, &count,
+ -1);
+ count_str = g_strdup_printf("%d", count);
+ g_object_set (cell, "text", count_str, NULL);
+ g_free (count_str);
+}
+
+static void
+search_files_update_ui (SearchFiles* sf)
+{
+ GtkTreeIter iter;
+ gboolean file_available = FALSE;
+
+ if (gtk_tree_model_get_iter_first(sf->priv->files_model, &iter))
+ {
+ do
+ {
+ gboolean selected;
+ gtk_tree_model_get (sf->priv->files_model, &iter,
+ COLUMN_SELECTED, &selected, -1);
+ if (selected)
+ {
+ file_available = TRUE;
+ break;
+ }
+ }
+ while (gtk_tree_model_iter_next(sf->priv->files_model, &iter));
+ }
+
+ gtk_widget_set_sensitive (sf->priv->search_button, file_available);
+ gtk_widget_set_sensitive (sf->priv->replace_button, file_available);
+}
+
+static void
+search_files_init_tree (SearchFiles* sf)
+{
+ GtkTreeViewColumn* column_select;
+ GtkTreeViewColumn* column_filename;
+ GtkTreeViewColumn* column_count;
+
+ GtkCellRenderer* selection_renderer;
+ GtkCellRenderer* filename_renderer;
+ GtkCellRenderer* count_renderer;
+
+ column_select = gtk_tree_view_column_new();
+ sf->priv->files_tree_check = gtk_check_button_new();
+ gtk_widget_show (sf->priv->files_tree_check);
+ gtk_tree_view_column_set_widget(column_select,
+ sf->priv->files_tree_check);
+ g_signal_connect_swapped (sf->priv->files_tree_check, "clicked",
+ G_CALLBACK(search_files_check_column_clicked), sf);
+ selection_renderer = gtk_cell_renderer_toggle_new ();
+ gtk_tree_view_column_pack_start(column_select,
+ selection_renderer,
+ FALSE);
+ gtk_tree_view_column_add_attribute(column_select,
+ selection_renderer,
+ "active",
+ COLUMN_SELECTED);
+ g_signal_connect_swapped (selection_renderer, "toggled",
+ G_CALLBACK(search_files_check_column_toggled), sf);
+
+ column_filename = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_expand(column_filename,
+ TRUE);
+ gtk_tree_view_column_set_title (column_filename, _("Filename"));
+ filename_renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(column_filename,
+ filename_renderer,
+ TRUE);
+ gtk_tree_view_column_add_attribute(column_filename,
+ filename_renderer,
+ "text",
+ COLUMN_FILENAME);
+
+ column_count = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title (column_count, "#");
+ count_renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(column_count,
+ count_renderer,
+ TRUE);
+ gtk_tree_view_column_set_cell_data_func(column_count,
+ count_renderer,
+ search_files_render_count,
+ NULL,
+ NULL);
+
+ sf->priv->files_model = GTK_TREE_MODEL (gtk_list_store_new (6,
+ G_TYPE_BOOLEAN,
+ G_TYPE_STRING,
+ G_TYPE_INT,
+ G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN,
+ G_TYPE_FILE));
+
+ g_signal_connect_swapped (sf->priv->files_model,
+ "row-inserted",
+ G_CALLBACK (search_files_update_ui),
+ sf);
+ g_signal_connect_swapped (sf->priv->files_model,
+ "row-deleted",
+ G_CALLBACK (search_files_update_ui),
+ sf);
+ g_signal_connect_swapped (sf->priv->files_model,
+ "row-changed",
+ G_CALLBACK (search_files_update_ui),
+ sf);
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (sf->priv->files_tree), sf->priv->files_model);
+ gtk_tree_view_append_column(GTK_TREE_VIEW (sf->priv->files_tree),
+ column_select);
+ gtk_tree_view_append_column(GTK_TREE_VIEW (sf->priv->files_tree),
+ column_filename);
+ gtk_tree_view_append_column(GTK_TREE_VIEW (sf->priv->files_tree),
+ column_count);
+}
+
+static void
+search_files_init (SearchFiles* sf)
+{
+ GError* error = NULL;
+ GtkCellRenderer* combo_renderer;
+
+ sf->priv =
+ G_TYPE_INSTANCE_GET_PRIVATE (sf, SEARCH_TYPE_FILES, SearchFilesPrivate);
+
+ sf->priv->builder = gtk_builder_new();
+ gtk_builder_add_from_file(sf->priv->builder, BUILDER_FILE, &error);
+
+ if (error)
+ {
+ g_warning("Could load ui file for search files: %s",
+ error->message);
+ g_error_free(error);
+ return;
+ }
+
+ combo_renderer = gtk_cell_renderer_text_new();
+
+ sf->priv->main_box = GTK_WIDGET (gtk_builder_get_object(sf->priv->builder,
+ "main_box"));
+ sf->priv->search_button = GTK_WIDGET (gtk_builder_get_object(sf->priv->builder,
+ "search_button"));
+ sf->priv->replace_button = GTK_WIDGET (gtk_builder_get_object(sf->priv->builder,
+ "replace_button"));
+ sf->priv->find_files_button = GTK_WIDGET (gtk_builder_get_object(sf->priv->builder,
+ "find_files_button"));
+ sf->priv->search_entry = GTK_WIDGET (gtk_builder_get_object(sf->priv->builder,
+ "search_entry"));
+ sf->priv->replace_entry = GTK_WIDGET (gtk_builder_get_object(sf->priv->builder,
+ "replace_entry"));
+ sf->priv->project_combo = GTK_WIDGET (gtk_builder_get_object(sf->priv->builder,
+ "project_combo"));
+ sf->priv->file_type_combo = GTK_WIDGET (gtk_builder_get_object(sf->priv->builder,
+ "file_type_combo"));
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT (sf->priv->file_type_combo),
+ combo_renderer, TRUE);
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (sf->priv->file_type_combo),
+ combo_renderer, "text", 0);
+ sf->priv->files_tree = GTK_WIDGET (gtk_builder_get_object(sf->priv->builder,
+ "files_tree"));
+
+ search_files_init_tree(sf);
+
+ gtk_builder_connect_signals(sf->priv->builder, sf);
+
+ g_object_ref (sf->priv->main_box);
+ gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (sf->priv->main_box)),
+ sf->priv->main_box);
+
+ search_files_update_ui(sf);
+}
+
+static void
+search_files_finalize (GObject* object)
+{
+ SearchFiles* sf = SEARCH_FILES(object);
+
+ g_object_unref (sf->priv->main_box);
+ g_object_unref (sf->priv->builder);
+
+ G_OBJECT_CLASS (search_files_parent_class)->finalize (object);
+}
+
+static void
+search_files_class_init (SearchFilesClass* klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+ GObjectClass* parent_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = search_files_finalize;
+
+ g_type_class_add_private(klass, sizeof(SearchFilesPrivate));
+}
+
+static void
+search_files_project_loaded (SearchFiles* sf, IAnjutaProjectManager *pm, GError* e)
+{
+ if (!e)
+ {
+ ianjuta_project_chooser_set_project_model(IANJUTA_PROJECT_CHOOSER(sf->priv->project_combo),
+ pm,
+ ANJUTA_PROJECT_GROUP,
+ NULL);
+ }
+}
+
+SearchFiles*
+search_files_new (AnjutaDocman* docman)
+{
+ AnjutaShell* shell = docman->shell;
+ GObject* obj = g_object_new (SEARCH_TYPE_FILES, NULL);
+ SearchFiles* sf = SEARCH_FILES(obj);
+ IAnjutaProjectManager* pm = anjuta_shell_get_interface(shell,
+ IAnjutaProjectManager,
+ NULL);
+ search_files_project_loaded(sf, pm, NULL);
+ g_signal_connect_swapped (pm, "project-loaded",
+ G_CALLBACK (search_files_project_loaded), NULL);
+
+ anjuta_shell_add_widget(shell, sf->priv->main_box,
+ "search_files",
+ _("Find in files"),
+ GTK_STOCK_FIND_AND_REPLACE,
+ ANJUTA_SHELL_PLACEMENT_BOTTOM, NULL);
+
+ sf->priv->docman = docman;
+
+ gtk_widget_show_all (sf->priv->main_box);
+
+ return sf;
+}
+
+void search_files_present (SearchFiles* sf)
+{
+ anjuta_shell_present_widget(sf->priv->docman->shell,
+ sf->priv->main_box,
+ NULL);
+}
\ No newline at end of file
diff --git a/plugins/document-manager/search-files.h b/plugins/document-manager/search-files.h
new file mode 100644
index 0000000..cecc569
--- /dev/null
+++ b/plugins/document-manager/search-files.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) Johannes Schmid 2012 <jhs gnome org>
+ *
+ * anjuta 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.
+ *
+ * anjuta 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 _SEARCH_FILES_H_
+#define _SEARCH_FILES_H_
+
+#include <anjuta-docman.h>
+
+G_BEGIN_DECLS
+
+#define SEARCH_TYPE_FILES (search_files_get_type ())
+#define SEARCH_FILES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEARCH_TYPE_FILES, SearchFiles))
+#define SEARCH_FILES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SEARCH_TYPE_FILES, SearchFilesClass))
+#define SEARCH_IS_FILES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEARCH_TYPE_FILES))
+#define SEARCH_IS_FILES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEARCH_TYPE_FILES))
+#define SEARCH_FILES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SEARCH_TYPE_FILES, SearchFilesClass))
+
+typedef struct _SearchFilesClass SearchFilesClass;
+typedef struct _SearchFiles SearchFiles;
+typedef struct _SearchFilesPrivate SearchFilesPrivate;
+
+struct _SearchFilesClass
+{
+ GObjectClass parent_class;
+};
+
+struct _SearchFiles
+{
+ GObject parent_instance;
+
+ SearchFilesPrivate* priv;
+};
+
+GType search_files_get_type (void) G_GNUC_CONST;
+SearchFiles* search_files_new (AnjutaDocman* docman);
+
+void search_files_present (SearchFiles* files);
+
+G_END_DECLS
+
+#endif /* _SEARCH_FILES_H_ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]