[anjuta] search: Improve find in files dialog



commit 8aee876aeb591ba68177c83413dd5ffbe8d3a279
Author: Johannes Schmid <jhs gnome org>
Date:   Sat Feb 11 17:43:02 2012 +0100

    search: Improve find in files dialog
    
    * Double click on result opens in editor
    * SearchBox in editor will highlight all matches with the same settings as "Find in files"
    * Basic replace implementation

 plugins/document-manager/action-callbacks.c        |    5 +-
 plugins/document-manager/anjuta-docman.c           |   55 ++--
 .../document-manager/anjuta-document-manager.ui    |   55 +++-
 plugins/document-manager/search-box.c              |   28 ++-
 plugins/document-manager/search-file-command.c     |   86 +++--
 plugins/document-manager/search-file-command.h     |    6 +-
 plugins/document-manager/search-files.c            |  407 ++++++++++++++++++--
 plugins/document-manager/search-files.h            |    5 +-
 8 files changed, 541 insertions(+), 106 deletions(-)
---
diff --git a/plugins/document-manager/action-callbacks.c b/plugins/document-manager/action-callbacks.c
index 3096783..19d4035 100644
--- a/plugins/document-manager/action-callbacks.c
+++ b/plugins/document-manager/action-callbacks.c
@@ -920,7 +920,8 @@ on_search_find_in_files (GtkAction *action, gpointer user_data)
 
 	if (!plugin->search_files)
 	{
-		plugin->search_files = G_OBJECT (search_files_new (ANJUTA_DOCMAN (plugin->docman)));
+		plugin->search_files = G_OBJECT (search_files_new (ANJUTA_DOCMAN (plugin->docman),
+		                                                   SEARCH_BOX(plugin->search_box)));
 	}
 	search_files_present (SEARCH_FILES(plugin->search_files));
 }
@@ -1037,9 +1038,7 @@ void
 on_autocomplete_activate (GtkAction *action, gpointer user_data)
 {
 	IAnjutaDocument *doc;
-	DocmanPlugin *plugin;
 	doc = get_current_document (user_data);
-	plugin = ANJUTA_PLUGIN_DOCMAN (user_data);
 	if (doc && IANJUTA_IS_EDITOR_ASSIST(doc))
 	{
 		IAnjutaEditorAssist* assist = IANJUTA_EDITOR_ASSIST (doc);
diff --git a/plugins/document-manager/anjuta-docman.c b/plugins/document-manager/anjuta-docman.c
index 0f3bbba..e7c1c3c 100644
--- a/plugins/document-manager/anjuta-docman.c
+++ b/plugins/document-manager/anjuta-docman.c
@@ -1633,30 +1633,9 @@ anjuta_docman_get_document_for_file (AnjutaDocman *docman, GFile* file)
 {
 	IAnjutaDocument *file_doc = NULL;
 	GList *node;
-	gchar *path;
-	gchar *local_real_path = NULL;
 
 	g_return_val_if_fail (file != NULL, NULL);
 
-
-	path = g_file_get_path (file);
-	if (path)
-	{
-		local_real_path = anjuta_util_get_real_path (path);
-		if (local_real_path)
-		{
-			g_free (path);
-		}
-		else
-		{
-			local_real_path = path;
-		}
-	}
-	else
-	{
-		return NULL;
-	}
-
 	for (node = docman->priv->pages; node != NULL; node = g_list_next (node))
 	{
 		AnjutaDocmanPage *page;
@@ -1672,7 +1651,9 @@ anjuta_docman_get_document_for_file (AnjutaDocman *docman, GFile* file)
 			doc_file = ianjuta_file_get_file (IANJUTA_FILE (doc), NULL);
 			if (doc_file)
 			{
-
+				gchar *path;
+				gchar *local_real_path = NULL;
+				
 				/* Try exact match first */
 				if (g_file_equal (file, doc_file))
 				{
@@ -1682,19 +1663,37 @@ anjuta_docman_get_document_for_file (AnjutaDocman *docman, GFile* file)
 				}
 
 				/* Try a local file alias */
+				path = g_file_get_path (file);
+				if (path)
+				{
+					local_real_path = anjuta_util_get_real_path (path);
+					if (local_real_path)
+					{
+						g_free (path);
+					}
+					else
+					{
+						local_real_path = path;
+					}
+				}
+				else
+				{
+					continue;
+				}
+				
 				if ((file_doc == NULL) && (local_real_path))
 				{
-					gchar *path = g_file_get_path (doc_file);
-					if (path)
+					gchar *doc_path = g_file_get_path (doc_file);
+					if (doc_path)
 					{
-						gchar *doc_real_path = anjuta_util_get_real_path (path);
+						gchar *doc_real_path = anjuta_util_get_real_path (doc_path);
 						if (doc_real_path)
 						{
-							g_free (path);
+							g_free (doc_path);
 						}
 						else
 						{
-							doc_real_path = path;
+							doc_real_path = doc_path;
 						}
 						if ((strcmp (doc_real_path, local_real_path) == 0))
 						{
@@ -1703,11 +1702,11 @@ anjuta_docman_get_document_for_file (AnjutaDocman *docman, GFile* file)
 						g_free (doc_real_path);
 					}
 				}
+				g_free (local_real_path);
 				g_object_unref (doc_file);
 			}
 		}
 	}
-	g_free (local_real_path);
 
 	return file_doc;
 }
diff --git a/plugins/document-manager/anjuta-document-manager.ui b/plugins/document-manager/anjuta-document-manager.ui
index a3a522c..fed8c72 100644
--- a/plugins/document-manager/anjuta-document-manager.ui
+++ b/plugins/document-manager/anjuta-document-manager.ui
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
-  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-requires gtk+ 3.0 -->
   <!-- interface-requires anjuta 0.0 -->
   <object class="GtkAdjustment" id="adjustment1">
     <property name="lower">1</property>
@@ -414,6 +414,7 @@
             <property name="invisible_char">â</property>
             <property name="invisible_char_set">True</property>
             <property name="primary_icon_stock">gtk-find</property>
+            <signal name="changed" handler="search_files_update_ui" swapped="yes"/>
           </object>
           <packing>
             <property name="left_attach">0</property>
@@ -485,7 +486,7 @@
             <property name="row_spacing">5</property>
             <property name="column_spacing">5</property>
             <property name="n_rows">1</property>
-            <property name="n_columns">2</property>
+            <property name="n_columns">5</property>
             <child>
               <object class="GtkComboBox" id="file_type_combo">
                 <property name="visible">True</property>
@@ -517,6 +518,53 @@
                 <property name="height">1</property>
               </packing>
             </child>
+            <child>
+              <object class="GtkCheckButton" id="case_check">
+                <property name="label" translatable="yes">Case sensitive</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_action_appearance">False</property>
+                <property name="xalign">0</property>
+                <property name="active">True</property>
+                <property name="draw_indicator">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">2</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkCheckButton" id="regex_check">
+                <property name="label" translatable="yes">Regular expression</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_action_appearance">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>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkSpinner" id="spinner_busy">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+              </object>
+              <packing>
+                <property name="left_attach">4</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>
@@ -569,9 +617,6 @@
             <property name="height">1</property>
           </packing>
         </child>
-        <child>
-          <placeholder/>
-        </child>
       </object>
     </child>
   </object>
diff --git a/plugins/document-manager/search-box.c b/plugins/document-manager/search-box.c
index 5cc18c9..9359b77 100644
--- a/plugins/document-manager/search-box.c
+++ b/plugins/document-manager/search-box.c
@@ -62,12 +62,18 @@ struct _SearchBoxPrivate
 
 	IAnjutaEditor* current_editor;
 	AnjutaStatus* status;
+	AnjutaShell* shell;
 
 	/* Search options popup menu */
 	GtkWidget* popup_menu;
+	GtkAction* case_action;
+	GtkAction* highlight_action;
+	GtkAction* regex_action;
+	
 	gboolean case_sensitive;
 	gboolean highlight_all;	
 	gboolean regex_mode;
+	
 	gboolean highlight_complete;
 	
 };
@@ -611,6 +617,8 @@ search_box_toggle_highlight (SearchBox * search_box, gboolean status)
 		return;
 
 	search_box->priv->highlight_all = status;
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(search_box->priv->highlight_action),
+	                             status);
 
 	if (!status)
 	{
@@ -621,10 +629,12 @@ search_box_toggle_highlight (SearchBox * search_box, gboolean status)
 
 void 
 search_box_toggle_case_sensitive (SearchBox * search_box, gboolean status)
-{
+{	
 	if (!search_box->priv->current_editor)
 		return;
-
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(search_box->priv->case_action),
+	                             status);
+	                               
 	search_box->priv->case_sensitive = status;
 	search_box_clear_highlight(search_box);
 }
@@ -635,6 +645,9 @@ search_box_toggle_regex (SearchBox * search_box, gboolean status)
 	if (!search_box->priv->current_editor)
 		return;
 
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(search_box->priv->regex_action),
+	                             status);
+	
 	search_box->priv->regex_mode = status;
 	search_box_clear_highlight(search_box);
 
@@ -1083,6 +1096,17 @@ search_box_new (AnjutaDocman *docman)
 											"/SearchboxPopup");
 	g_assert (search_box->priv->popup_menu != NULL && GTK_IS_MENU (search_box->priv->popup_menu));
 
+	search_box->priv->case_action = 
+		gtk_ui_manager_get_action (GTK_UI_MANAGER (ui),
+		                           "/SearchboxPopup/CaseCheck");
+
+	search_box->priv->highlight_action =
+		gtk_ui_manager_get_action (GTK_UI_MANAGER (ui),
+		                           "/SearchboxPopup/HighlightAll");
+	search_box->priv->regex_action = 
+		gtk_ui_manager_get_action (GTK_UI_MANAGER (ui),
+		                           "/SearchboxPopup/RegexSearch");
+
 	g_signal_connect (search_box->priv->popup_menu, "deactivate",
 					  G_CALLBACK (gtk_widget_hide), NULL);
 
diff --git a/plugins/document-manager/search-file-command.c b/plugins/document-manager/search-file-command.c
index b106ebb..592a740 100644
--- a/plugins/document-manager/search-file-command.c
+++ b/plugins/document-manager/search-file-command.c
@@ -26,6 +26,7 @@ struct _SearchFileCommandPrivate
 	gchar* pattern;
 	gchar* replace;
 	gboolean regex;
+	gboolean case_sensitive;
 
 	gint n_matches;
 };
@@ -36,11 +37,14 @@ enum
 	PROP_FILE,
 	PROP_PATTERN,
 	PROP_REPLACE,
+	PROP_CASE_SENSITIVE,
 	PROP_REGEX
 };
 
 #define BUFFER_SIZE 1024
 
+G_DEFINE_TYPE (SearchFileCommand, search_file_command, ANJUTA_TYPE_ASYNC_COMMAND);
+
 static void
 search_file_command_save (SearchFileCommand* cmd, const gchar* new_content, GError **error)
 {
@@ -84,7 +88,7 @@ search_file_command_load (SearchFileCommand* cmd, GError **error)
 	content = g_string_new (NULL);
 	while ((bytes_read = g_input_stream_read (G_INPUT_STREAM (istream),
 	                                          buffer,
-	                                          BUFFER_SIZE,
+	                                          BUFFER_SIZE - 1,
 	                                          NULL,
 	                                          error)))
 	{
@@ -110,9 +114,12 @@ search_file_command_run (AnjutaCommand* anjuta_cmd)
 	gchar* pattern;
 	gchar* replace;
 	gchar* content;
+	GRegexCompileFlags flags = 0;
+	GRegex *regex;
+	GMatchInfo *match_info;
 	
 	g_return_val_if_fail (cmd->priv->file != NULL && G_IS_FILE (cmd->priv->file), 1);
-
+	g_return_val_if_fail (cmd->priv->pattern != NULL, 1);
 	cmd->priv->n_matches = 0;
 	
 	content = search_file_command_load (cmd, &error);
@@ -140,29 +147,30 @@ search_file_command_run (AnjutaCommand* anjuta_cmd)
 			replace = NULL;
 	}
 
-	if (!replace)
-	{
-		GRegex *regex;
-		GMatchInfo *match_info;
+	if (!cmd->priv->case_sensitive)
+		flags |= G_REGEX_CASELESS;
 
-		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);                      
+	regex = g_regex_new (pattern, flags, 0, &error);
+	if (error)
+	{
+		anjuta_command_set_error_message(anjuta_cmd, error->message);
+		g_error_free (error);
+		g_free (content);
+		return 1;
 	}
-	else
+	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);
+	
+	if (replace && cmd->priv->n_matches)
 	{
 		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);
@@ -173,13 +181,15 @@ search_file_command_run (AnjutaCommand* anjuta_cmd)
 			return 1;
 		}
 	}
+
+	g_regex_unref (regex);
 	g_free (content);
+	g_free (pattern);
+	g_free (replace);
 
 	return 0;
 }
 
-G_DEFINE_TYPE (SearchFileCommand, search_file_command, ANJUTA_TYPE_ASYNC_COMMAND);
-
 static void
 search_file_command_init (SearchFileCommand *cmd)
 {
@@ -223,6 +233,9 @@ search_file_command_set_property (GObject *object, guint prop_id, const GValue *
 		g_free (cmd->priv->replace);
 		cmd->priv->replace = g_value_dup_string (value);
 		break;
+	case PROP_CASE_SENSITIVE:
+		cmd->priv->case_sensitive = g_value_get_boolean (value);
+		break;			
 	case PROP_REGEX:
 		cmd->priv->regex = g_value_get_boolean (value);
 		break;
@@ -252,6 +265,9 @@ search_file_command_get_property (GObject *object, guint prop_id, GValue *value,
 	case PROP_REPLACE:
 		g_value_set_string (value, cmd->priv->replace);
 		break;
+	case PROP_CASE_SENSITIVE:
+		g_value_set_boolean (value, cmd->priv->case_sensitive);
+		break;
 	case PROP_REGEX:
 		g_value_set_boolean (value, cmd->priv->regex);
 		break;
@@ -277,24 +293,30 @@ search_file_command_class_init (SearchFileCommandClass *klass)
 	                                                      "filename",
 	                                                      "Filename to search in",
 	                                                      G_TYPE_FILE,
-	                                                      G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY));
+	                                                      G_PARAM_WRITABLE | 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));
+	                                                       NULL,
+	                                                       G_PARAM_WRITABLE | G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY));
 	g_object_class_install_property (object_class,
-	                                 PROP_PATTERN,
+	                                 PROP_REPLACE,
 	                                 g_param_spec_string ("replace", "", "",
-	                                                       "",
-	                                                       G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY));	
+	                                                       NULL,
+	                                                       G_PARAM_WRITABLE | G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY));	
 
 	g_object_class_install_property (object_class,
+	                                 PROP_CASE_SENSITIVE,
+	                                 g_param_spec_boolean ("case-sensitive", "", "",
+	                                                       TRUE,
+	                                                       G_PARAM_WRITABLE | 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));
+	                                                      G_PARAM_WRITABLE | G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY));
 
 	command_class->run = search_file_command_run;
 
@@ -303,7 +325,8 @@ search_file_command_class_init (SearchFileCommandClass *klass)
 
 
 SearchFileCommand*
-search_file_command_new (GFile* file, const gchar* pattern, const gchar* replace, gboolean regex)
+search_file_command_new (GFile* file, const gchar* pattern, 
+                         const gchar* replace, gboolean case_sensitive, gboolean regex)
 {
 	SearchFileCommand* command;
 
@@ -311,14 +334,15 @@ search_file_command_new (GFile* file, const gchar* pattern, const gchar* replace
 	                                             "file", file,
 	                                             "pattern", pattern,
 	                                             "replace", replace,
+	                                             "case-sensitive", case_sensitive,
 	                                             "regex", regex, NULL));
 	return command;
 }
 
 gint
-search_command_get_n_matches (SearchFileCommand* cmd)
+search_file_command_get_n_matches (SearchFileCommand* cmd)
 {
-	g_return_val_if_fail (cmd != NULL && !SEARCH_IS_FILE_COMMAND (cmd), 0);
+	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
index ef606af..20c5f9b 100644
--- a/plugins/document-manager/search-file-command.h
+++ b/plugins/document-manager/search-file-command.h
@@ -51,8 +51,10 @@ struct _SearchFileCommand
 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);
+                                            const gchar* replace,
+                                            gboolean case_sensitive,
+                                            gboolean regex);
+gint search_file_command_get_n_matches (SearchFileCommand* cmd);
 
 G_END_DECLS
 
diff --git a/plugins/document-manager/search-files.c b/plugins/document-manager/search-files.c
index 0162400..e381eea 100644
--- a/plugins/document-manager/search-files.c
+++ b/plugins/document-manager/search-files.c
@@ -18,6 +18,8 @@
  */
 
 #include "search-files.h"
+#include "search-file-command.h"
+#include <libanjuta/anjuta-command-queue.h>
 #include <libanjuta/interfaces/ianjuta-project-manager.h>
 #include <libanjuta/interfaces/ianjuta-project-chooser.h>
 
@@ -40,13 +42,27 @@ struct _SearchFilesPrivate
 	GtkWidget* project_combo;
 	GtkWidget* file_type_combo;
 
+	GtkWidget* case_check;
+	GtkWidget* regex_check;
+
+	GtkWidget* spinner_busy;
+	
 	GtkWidget* files_tree;
 	GtkTreeModel* files_model;
 
 	GtkWidget* files_tree_check;
 	
 	AnjutaDocman* docman;
+	SearchBox* search_box;
 	GtkWidget* dialog;
+
+	/* Saved from last search */
+	gboolean case_sensitive;
+	gboolean regex;
+	gchar* last_search_string;
+	gchar* last_replace_string;
+	
+	gboolean busy;
 };
 
 enum
@@ -56,7 +72,10 @@ enum
 	COLUMN_COUNT,
 	COLUMN_PULSE,
 	COLUMN_SPINNER,
-	COLUMN_FILE
+	COLUMN_FILE,
+	COLUMN_ERROR_TOOLTIP,
+	COLUMN_ERROR_CODE,
+	N_COLUMNS
 };
 
 G_DEFINE_TYPE (SearchFiles, search_files, G_TYPE_OBJECT);
@@ -64,6 +83,47 @@ 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);
+void search_files_update_ui (SearchFiles* sf);
+
+
+void
+search_files_update_ui (SearchFiles* sf)
+{
+	GtkTreeIter iter;
+	gboolean can_search = FALSE;
+	
+	if (!sf->priv->busy)
+	{
+		gtk_spinner_stop(GTK_SPINNER (sf->priv->spinner_busy));
+		gtk_widget_hide (sf->priv->spinner_busy);
+
+		if (strlen(gtk_entry_get_text (GTK_ENTRY (sf->priv->search_entry))) > 0
+		    && 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)
+				{
+					can_search = TRUE;
+					break;
+				}
+			}
+			while (gtk_tree_model_iter_next(sf->priv->files_model, &iter));
+		}
+	}
+	else
+	{
+		gtk_spinner_start(GTK_SPINNER (sf->priv->spinner_busy));
+		gtk_widget_show (sf->priv->spinner_busy);
+	}
+
+	gtk_widget_set_sensitive (sf->priv->search_button, can_search);
+	gtk_widget_set_sensitive (sf->priv->replace_button, can_search);
+	gtk_widget_set_sensitive (sf->priv->find_files_button, !sf->priv->busy);
+}
 
 static void
 search_files_get_files (GFile* parent, GList** files, IAnjutaProjectManager* pm)
@@ -87,22 +147,215 @@ search_files_check_column_clicked (SearchFiles* sf,
 }
 
 static void
-search_files_check_column_toggled (SearchFiles* sf,
-                                   GtkCellRenderer* renderer)
+search_files_check_column_toggled (GtkCellRendererToggle* renderer,
+                                   gchar* path,
+                                   SearchFiles* sf)
+{
+	GtkTreePath* tree_path;
+	GtkTreeIter iter;
+	gboolean state;
+
+	if (sf->priv->busy)
+		return;
+
+	tree_path = gtk_tree_path_new_from_string(path);
+	gtk_tree_model_get_iter (sf->priv->files_model, &iter, tree_path);
+
+	gtk_tree_path_free(tree_path);
+	
+	gtk_tree_model_get (sf->priv->files_model, &iter,
+	                    COLUMN_SELECTED, &state, -1);
+	
+	gtk_list_store_set (GTK_LIST_STORE (sf->priv->files_model), &iter,
+	                    COLUMN_SELECTED, !state,
+	                    -1);
+}
+
+static void
+search_files_finished (SearchFiles* sf, AnjutaCommandQueue* queue)
 {
+	sf->priv->busy = FALSE;
+	g_object_unref (queue);
+
+	search_files_update_ui(sf);
+}
+
+static void
+search_files_command_finished (SearchFileCommand* cmd,
+                               guint return_code,
+                               SearchFiles* sf)
+{	
+	GtkTreeIter iter;
+	GtkTreeRowReference* tree_ref;
+	GtkTreePath* path;
+	
+	tree_ref = g_object_get_data (G_OBJECT (cmd),
+	                              "__tree_ref");
+	path = gtk_tree_row_reference_get_path(tree_ref);
+	
+	gtk_tree_model_get_iter(sf->priv->files_model, &iter, path);
+	gtk_list_store_set (GTK_LIST_STORE (sf->priv->files_model),
+	                    &iter,
+	                    COLUMN_COUNT, search_file_command_get_n_matches(cmd),
+	                    COLUMN_ERROR_CODE, return_code,
+	                    COLUMN_ERROR_TOOLTIP, NULL,
+	                    -1);
+	gtk_tree_row_reference_free(tree_ref);
+	gtk_tree_path_free(path);
 
+	if (return_code)
+	{
+		gtk_list_store_set (GTK_LIST_STORE (sf->priv->files_model),
+		                    &iter,
+		                    COLUMN_ERROR_CODE, return_code,
+		                    COLUMN_ERROR_TOOLTIP,
+		                    anjuta_command_get_error_message(cmd),
+		                    -1);
+	}
+	
+	g_object_unref (cmd);
 }
 
 void
 search_files_search_clicked (SearchFiles* sf)
 {
+	GtkTreeIter iter;
+	
+	if (gtk_tree_model_get_iter_first(sf->priv->files_model, &iter))
+	{
+		AnjutaCommandQueue* queue = anjuta_command_queue_new(ANJUTA_COMMAND_QUEUE_EXECUTE_MANUAL);
+		const gchar* pattern = 
+			gtk_entry_get_text (GTK_ENTRY (sf->priv->search_entry));
+		do
+		{
+			GFile* file;
+			gboolean selected;
+
+			/* Save the current values */
+			sf->priv->regex = 
+				gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (sf->priv->regex_check));
+			sf->priv->case_sensitive =
+				gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (sf->priv->case_check));
+			
+			g_free (sf->priv->last_search_string);
+			sf->priv->last_search_string = g_strdup(pattern);
+			g_free (sf->priv->last_replace_string);
+			sf->priv->last_replace_string = NULL;
+
+			gtk_tree_model_get (sf->priv->files_model, &iter,
+			                    COLUMN_FILE, &file, 
+			                    COLUMN_SELECTED, &selected, -1);
+			if (selected)
+			{
+				GtkTreePath* path;
+				GtkTreeRowReference* ref;
+				
+				path = gtk_tree_model_get_path(sf->priv->files_model, &iter);
+				ref = gtk_tree_row_reference_new(sf->priv->files_model, 
+				                                 path);
+				gtk_tree_path_free(path);
+
+
+				SearchFileCommand* cmd = search_file_command_new(file,
+				                                                 pattern,
+				                                                 NULL,
+				                                                 sf->priv->case_sensitive,
+				                                                 sf->priv->regex);
+				g_object_set_data (G_OBJECT (cmd), "__tree_ref",
+				                   ref);
+
+				g_signal_connect (cmd, "command-finished", 
+				                  G_CALLBACK(search_files_command_finished), sf);
+
+				anjuta_command_queue_push(queue,
+				                          ANJUTA_COMMAND(cmd));
+			}
+			g_object_unref (file);
+		}
+		while (gtk_tree_model_iter_next(sf->priv->files_model, &iter));
 
+		g_signal_connect_swapped (queue, "finished", G_CALLBACK (search_files_finished), sf);
+
+		anjuta_command_queue_start (queue);
+		gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE (sf->priv->files_model),
+		                                     COLUMN_COUNT,
+		                                     GTK_SORT_DESCENDING);
+
+		sf->priv->busy = TRUE;
+		search_files_update_ui(sf);
+	}
 }
 
 void
 search_files_replace_clicked (SearchFiles* sf)
 {
+	GtkTreeIter iter;
+	
+	if (gtk_tree_model_get_iter_first(sf->priv->files_model, &iter))
+	{
+		AnjutaCommandQueue* queue = anjuta_command_queue_new(ANJUTA_COMMAND_QUEUE_EXECUTE_MANUAL);
+		const gchar* pattern = 
+			gtk_entry_get_text (GTK_ENTRY (sf->priv->search_entry));
+		const gchar* replace =
+			gtk_entry_get_text (GTK_ENTRY (sf->priv->replace_entry));
+		do
+		{
+			GFile* file;
+			gboolean selected;
 
+			/* Save the current values */
+			sf->priv->regex = 
+				gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (sf->priv->regex_check));
+			sf->priv->case_sensitive =
+				gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (sf->priv->case_check));
+			
+			g_free (sf->priv->last_search_string);
+			sf->priv->last_search_string = g_strdup(pattern);
+			g_free (sf->priv->last_replace_string);
+			sf->priv->last_replace_string = g_strdup(replace);
+
+			gtk_tree_model_get (sf->priv->files_model, &iter,
+			                    COLUMN_FILE, &file, 
+			                    COLUMN_SELECTED, &selected, -1);
+			if (selected)
+			{
+				GtkTreePath* path;
+				GtkTreeRowReference* ref;
+				
+				path = gtk_tree_model_get_path(sf->priv->files_model, &iter);
+				ref = gtk_tree_row_reference_new(sf->priv->files_model, 
+				                                 path);
+				gtk_tree_path_free(path);
+
+
+				SearchFileCommand* cmd = search_file_command_new(file,
+				                                                 pattern,
+				                                                 replace,
+				                                                 sf->priv->case_sensitive,
+				                                                 sf->priv->regex);
+				g_object_set_data (G_OBJECT (cmd), "__tree_ref",
+				                   ref);
+
+				g_signal_connect (cmd, "command-finished", 
+				                  G_CALLBACK(search_files_command_finished), sf);
+
+				anjuta_command_queue_push(queue,
+				                          ANJUTA_COMMAND(cmd));
+			}
+			g_object_unref (file);
+		}
+		while (gtk_tree_model_iter_next(sf->priv->files_model, &iter));
+
+		g_signal_connect_swapped (queue, "finished", G_CALLBACK (search_files_finished), sf);
+
+		anjuta_command_queue_start (queue);
+		gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE (sf->priv->files_model),
+		                                     COLUMN_COUNT,
+		                                     GTK_SORT_DESCENDING);
+
+		sf->priv->busy = TRUE;
+		search_files_update_ui(sf);
+	}
 }
 
 void
@@ -165,6 +418,10 @@ search_files_find_files_clicked (SearchFiles* sf)
 		                    COLUMN_PULSE, FALSE, -1);
 	}
 	g_object_unref (project_file);
+
+	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE (sf->priv->files_model),
+	                                     COLUMN_FILENAME,
+	                                     GTK_SORT_DESCENDING);
 	
 	g_list_foreach (files, (GFunc) g_object_unref, NULL);
 	g_list_free (files);
@@ -189,29 +446,66 @@ search_files_render_count (GtkTreeViewColumn *tree_column,
 }
 
 static void
-search_files_update_ui (SearchFiles* sf)
+search_files_editor_loaded (SearchFiles* sf, IAnjutaEditor* editor)
+{
+	search_box_set_search_string(sf->priv->search_box, 
+	                             sf->priv->last_search_string);
+	if (sf->priv->last_replace_string)
+	{
+		search_box_set_replace_string(sf->priv->search_box,
+		                              sf->priv->last_replace_string);
+		search_box_set_replace(sf->priv->search_box,
+		                       TRUE);
+	}
+	else
+	{
+		search_box_set_replace(sf->priv->search_box,
+		                       FALSE);
+	}
+	search_box_toggle_case_sensitive(sf->priv->search_box,
+	                                 sf->priv->case_sensitive);
+	search_box_toggle_highlight(sf->priv->search_box,
+	                            TRUE);
+	search_box_toggle_regex(sf->priv->search_box,
+	                        sf->priv->regex);
+	search_box_search_highlight_all(sf->priv->search_box, TRUE);
+	search_box_incremental_search(sf->priv->search_box, TRUE, FALSE);
+
+	gtk_widget_show (GTK_WIDGET(sf->priv->search_box));
+}
+                               
+
+static void
+search_files_result_activated (GtkTreeView* files_tree,
+                               GtkTreePath* path,
+                               GtkTreeViewColumn* column,
+                               SearchFiles* sf)
 {
+	IAnjutaDocument* editor;
+	GFile* file;
 	GtkTreeIter iter;
-	gboolean file_available = FALSE;
+
+	gtk_tree_model_get_iter (sf->priv->files_model, &iter, path);
+	gtk_tree_model_get (sf->priv->files_model, &iter,
+	                    COLUMN_FILE, &file, -1);
 	
-	if (gtk_tree_model_get_iter_first(sf->priv->files_model, &iter))
+	/* Check if document is open */
+	editor = anjuta_docman_get_document_for_file(sf->priv->docman, file);
+	
+	if (editor && IANJUTA_IS_EDITOR(editor))
 	{
-		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));
+		search_files_editor_loaded (sf, IANJUTA_EDITOR(editor));
+	}
+	else
+	{
+		IAnjutaEditor* real_editor = 
+			anjuta_docman_goto_file_line(sf->priv->docman, file, 0);
+		if (real_editor)
+			g_signal_connect_swapped (real_editor, "opened", 
+			                          G_CALLBACK (search_files_editor_loaded), sf);
 	}
 
-	gtk_widget_set_sensitive (sf->priv->search_button, file_available);
-	gtk_widget_set_sensitive (sf->priv->replace_button, file_available);	
+	g_object_unref (file);
 }
 
 static void
@@ -224,6 +518,7 @@ search_files_init_tree (SearchFiles* sf)
 	GtkCellRenderer* selection_renderer;
 	GtkCellRenderer* filename_renderer;
 	GtkCellRenderer* count_renderer;
+	GtkCellRenderer* error_renderer;
 	
 	column_select = gtk_tree_view_column_new();
 	sf->priv->files_tree_check = gtk_check_button_new();
@@ -240,8 +535,8 @@ search_files_init_tree (SearchFiles* sf)
 	                                   selection_renderer,
 	                                   "active",
 	                                   COLUMN_SELECTED);
-	g_signal_connect_swapped (selection_renderer, "toggled",
-	                          G_CALLBACK(search_files_check_column_toggled), sf);
+	g_signal_connect (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,
@@ -251,31 +546,57 @@ search_files_init_tree (SearchFiles* sf)
 	gtk_tree_view_column_pack_start(column_filename,
 	                                filename_renderer,
 	                                TRUE);
-	gtk_tree_view_column_add_attribute(column_filename,
-	                                   filename_renderer,
-	                                   "text",
-	                                   COLUMN_FILENAME);
-
+	gtk_tree_view_column_add_attribute (column_filename,
+	                                    filename_renderer,
+	                                    "text",
+	                                    COLUMN_FILENAME);
+	gtk_tree_view_column_add_attribute (column_filename,
+	                                    filename_renderer,
+	                                    "sensitive",
+	                                    COLUMN_COUNT);
+	gtk_tree_view_column_set_sort_column_id(column_filename,
+	                                        COLUMN_FILENAME);
+	error_renderer = gtk_cell_renderer_pixbuf_new();
+	g_object_set (error_renderer, "stock-id", GTK_STOCK_DIALOG_ERROR, NULL);
+	gtk_tree_view_column_pack_start(column_filename,
+	                                error_renderer,
+	                                FALSE);
+	gtk_tree_view_column_add_attribute (column_filename,
+	                                    error_renderer,
+	                                    "visible",
+	                                    COLUMN_ERROR_CODE);
+	
 	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_add_attribute (column_count,
+	                                    count_renderer,
+	                                    "sensitive",
+	                                    COLUMN_COUNT);	
 	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,
+	gtk_tree_view_column_set_sort_column_id(column_count,
+	                                        COLUMN_COUNT);
+	
+	sf->priv->files_model = GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS,
 	                                                            G_TYPE_BOOLEAN,
 	                                                            G_TYPE_STRING,
 	                                                            G_TYPE_INT,
 	                                                            G_TYPE_BOOLEAN,
 	                                                            G_TYPE_BOOLEAN,
-	                                                            G_TYPE_FILE));
-
+	                                                            G_TYPE_FILE,
+	                                                            G_TYPE_STRING,
+	                                                            G_TYPE_INT));
+	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE (sf->priv->files_model),
+	                                     COLUMN_FILENAME,
+	                                     GTK_SORT_DESCENDING);	
+	
 	g_signal_connect_swapped (sf->priv->files_model,
 	                          "row-inserted",
 	                          G_CALLBACK (search_files_update_ui),
@@ -288,7 +609,7 @@ search_files_init_tree (SearchFiles* sf)
 	                          "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);
@@ -296,6 +617,10 @@ search_files_init_tree (SearchFiles* sf)
 	                            column_filename);
 	gtk_tree_view_append_column(GTK_TREE_VIEW (sf->priv->files_tree),
 	                            column_count);
+	gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW (sf->priv->files_tree),
+	                                 COLUMN_ERROR_TOOLTIP);
+	g_signal_connect (sf->priv->files_tree, "row-activated",
+	                  G_CALLBACK (search_files_result_activated), sf);
 }
 
 static void
@@ -340,6 +665,14 @@ search_files_init (SearchFiles* sf)
 	                           combo_renderer, TRUE);
 	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (sf->priv->file_type_combo),
 	                               combo_renderer, "text", 0);
+
+	sf->priv->case_check = GTK_WIDGET (gtk_builder_get_object(sf->priv->builder,
+	                                                             "case_check"));
+	sf->priv->regex_check = GTK_WIDGET (gtk_builder_get_object(sf->priv->builder,
+	                                                           "regex_check"));
+	sf->priv->spinner_busy = GTK_WIDGET (gtk_builder_get_object(sf->priv->builder,
+	                                                            "spinner_busy"));
+	
 	sf->priv->files_tree = GTK_WIDGET (gtk_builder_get_object(sf->priv->builder,
 	                                                          "files_tree"));	
 
@@ -389,7 +722,7 @@ search_files_project_loaded (SearchFiles* sf, IAnjutaProjectManager *pm, GError*
 }
 
 SearchFiles* 
-search_files_new (AnjutaDocman* docman)
+search_files_new (AnjutaDocman* docman, SearchBox* search_box)
 {
 	AnjutaShell* shell = docman->shell;
 	GObject* obj = g_object_new (SEARCH_TYPE_FILES, NULL);
@@ -408,6 +741,7 @@ search_files_new (AnjutaDocman* docman)
 	                        ANJUTA_SHELL_PLACEMENT_BOTTOM, NULL);
 
 	sf->priv->docman = docman;
+	sf->priv->search_box = search_box;
 	
 	gtk_widget_show_all (sf->priv->main_box);
 	
@@ -416,6 +750,13 @@ search_files_new (AnjutaDocman* docman)
 
 void search_files_present (SearchFiles* sf)
 {
+	g_return_if_fail (sf != NULL && SEARCH_IS_FILES(sf));
+	
+	gtk_entry_set_text (GTK_ENTRY (sf->priv->search_entry),
+	                    search_box_get_search_string(sf->priv->search_box));
+	gtk_entry_set_text (GTK_ENTRY (sf->priv->replace_entry),
+	                    search_box_get_replace_string(sf->priv->search_box));	
+
 	anjuta_shell_present_widget(sf->priv->docman->shell,
 	                            sf->priv->main_box,
 	                            NULL);
diff --git a/plugins/document-manager/search-files.h b/plugins/document-manager/search-files.h
index cecc569..fd7c58f 100644
--- a/plugins/document-manager/search-files.h
+++ b/plugins/document-manager/search-files.h
@@ -20,7 +20,8 @@
 #ifndef _SEARCH_FILES_H_
 #define _SEARCH_FILES_H_
 
-#include <anjuta-docman.h>
+#include "anjuta-docman.h"
+#include "search-box.h"
 
 G_BEGIN_DECLS
 
@@ -48,7 +49,7 @@ struct _SearchFiles
 };
 
 GType search_files_get_type (void) G_GNUC_CONST;
-SearchFiles* search_files_new (AnjutaDocman* docman);
+SearchFiles* search_files_new (AnjutaDocman* docman, SearchBox* search_box);
 
 void search_files_present (SearchFiles* files);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]