nautilus-3.6.3/libnautilus-private/nautilus-search-engine.c

No issues found

  1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
  2 /*
  3  * Copyright (C) 2005 Novell, Inc.
  4  *
  5  * Nautilus is free software; you can redistribute it and/or
  6  * modify it under the terms of the GNU General Public License as
  7  * published by the Free Software Foundation; either version 2 of the
  8  * License, or (at your option) any later version.
  9  *
 10  * Nautilus is distributed in the hope that it will be useful,
 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  * General Public License for more details.
 14  *
 15  * You should have received a copy of the GNU General Public
 16  * License along with this program; see the file COPYING.  If not,
 17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 18  * Boston, MA 02111-1307, USA.
 19  *
 20  * Author: Anders Carlsson <andersca@imendio.com>
 21  *
 22  */
 23 
 24 #include <config.h>
 25 
 26 #include <glib/gi18n.h>
 27 #include "nautilus-search-provider.h"
 28 #include "nautilus-search-engine.h"
 29 #include "nautilus-search-engine-simple.h"
 30 #include "nautilus-search-engine-model.h"
 31 #define DEBUG_FLAG NAUTILUS_DEBUG_SEARCH
 32 #include "nautilus-debug.h"
 33 
 34 #ifdef ENABLE_TRACKER
 35 #include "nautilus-search-engine-tracker.h"
 36 #endif
 37 
 38 struct NautilusSearchEngineDetails
 39 {
 40 #ifdef ENABLE_TRACKER
 41 	NautilusSearchEngineTracker *tracker;
 42 #endif
 43 	NautilusSearchEngineSimple *simple;
 44 	NautilusSearchEngineModel *model;
 45 
 46 	GHashTable *uris;
 47 	guint providers_running;
 48 	guint providers_finished;
 49 	guint providers_error;
 50 
 51 	gboolean running;
 52 	gboolean restart;
 53 };
 54 
 55 static void nautilus_search_provider_init (NautilusSearchProviderIface  *iface);
 56 
 57 G_DEFINE_TYPE_WITH_CODE (NautilusSearchEngine,
 58 			 nautilus_search_engine,
 59 			 G_TYPE_OBJECT,
 60 			 G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_SEARCH_PROVIDER,
 61 						nautilus_search_provider_init))
 62 
 63 static void
 64 nautilus_search_engine_set_query (NautilusSearchProvider *provider,
 65 				  NautilusQuery          *query)
 66 {
 67 	NautilusSearchEngine *engine = NAUTILUS_SEARCH_ENGINE (provider);
 68 #ifdef ENABLE_TRACKER
 69 	nautilus_search_provider_set_query (NAUTILUS_SEARCH_PROVIDER (engine->details->tracker), query);
 70 #endif
 71 	nautilus_search_provider_set_query (NAUTILUS_SEARCH_PROVIDER (engine->details->model), query);
 72 	nautilus_search_provider_set_query (NAUTILUS_SEARCH_PROVIDER (engine->details->simple), query);
 73 }
 74 
 75 static void
 76 search_engine_start_real (NautilusSearchEngine *engine)
 77 {
 78 	engine->details->providers_running = 0;
 79 	engine->details->providers_finished = 0;
 80 	engine->details->providers_error = 0;
 81 
 82 	engine->details->restart = FALSE;
 83 
 84 	DEBUG ("Search engine start real");
 85 
 86 	g_object_ref (engine);
 87 
 88 #ifdef ENABLE_TRACKER
 89 	nautilus_search_provider_start (NAUTILUS_SEARCH_PROVIDER (engine->details->tracker));
 90 	engine->details->providers_running++;
 91 #endif
 92 	if (nautilus_search_engine_model_get_model (engine->details->model)) {
 93 		nautilus_search_provider_start (NAUTILUS_SEARCH_PROVIDER (engine->details->model));
 94 		engine->details->providers_running++;
 95 	} else {
 96 		nautilus_search_provider_start (NAUTILUS_SEARCH_PROVIDER (engine->details->simple));
 97 		engine->details->providers_running++;
 98 	}
 99 }
100 
101 static void
102 nautilus_search_engine_start (NautilusSearchProvider *provider)
103 {
104 	NautilusSearchEngine *engine = NAUTILUS_SEARCH_ENGINE (provider);
105 	gint num_finished;
106 
107 	DEBUG ("Search engine start");
108 
109 	num_finished = engine->details->providers_error + engine->details->providers_finished;
110 
111 	if (engine->details->running) {
112 		if (num_finished == engine->details->providers_running &&
113 		    engine->details->restart) {
114 			search_engine_start_real (engine);
115 		}
116 
117 		return;
118 	}
119 
120 	engine->details->running = TRUE;
121 
122 	if (num_finished < engine->details->providers_running) {
123 		engine->details->restart = TRUE;
124 	} else {
125 		search_engine_start_real (engine);
126 	}
127 }
128 
129 static void
130 nautilus_search_engine_stop (NautilusSearchProvider *provider)
131 {
132 	NautilusSearchEngine *engine = NAUTILUS_SEARCH_ENGINE (provider);
133 
134 	DEBUG ("Search engine stop");
135 
136 #ifdef ENABLE_TRACKER
137 	nautilus_search_provider_stop (NAUTILUS_SEARCH_PROVIDER (engine->details->tracker));
138 #endif
139 	nautilus_search_provider_stop (NAUTILUS_SEARCH_PROVIDER (engine->details->model));
140 	nautilus_search_provider_stop (NAUTILUS_SEARCH_PROVIDER (engine->details->simple));
141 
142 	engine->details->running = FALSE;
143 	engine->details->restart = FALSE;
144 }
145 
146 static void
147 search_provider_hits_added (NautilusSearchProvider *provider,
148 			    GList                  *hits,
149 			    NautilusSearchEngine   *engine)
150 {
151 	GList *added = NULL;
152 	GList *l;
153 
154 	if (!engine->details->running || engine->details->restart) {
155 		DEBUG ("Ignoring hits-added, since engine is %s",
156 		       !engine->details->running ? "not running" : "waiting to restart");
157 		return;
158 	}
159 
160 	for (l = hits; l != NULL; l = l->next) {
161 		NautilusSearchHit *hit = l->data;
162 		int count;
163 		const char *uri;
164 
165 		uri = nautilus_search_hit_get_uri (hit);
166 		count = GPOINTER_TO_INT (g_hash_table_lookup (engine->details->uris, uri));
167 		if (count == 0)
168 			added = g_list_prepend (added, hit);
169 		g_hash_table_replace (engine->details->uris, g_strdup (uri), GINT_TO_POINTER (++count));
170 	}
171 	if (added != NULL) {
172 		added = g_list_reverse (added);
173 		nautilus_search_provider_hits_added (NAUTILUS_SEARCH_PROVIDER (engine), added);
174 		g_list_free (added);
175 	}
176 }
177 
178 static void
179 check_providers_status (NautilusSearchEngine *engine)
180 {
181 	gint num_finished = engine->details->providers_error + engine->details->providers_finished;
182 
183 	if (num_finished < engine->details->providers_running) {
184 		return;
185 	}
186 
187 	if (num_finished == engine->details->providers_error) {
188 		DEBUG ("Search engine error");
189 		nautilus_search_provider_error (NAUTILUS_SEARCH_PROVIDER (engine),
190 						_("Unable to complete the requested search"));
191 	} else {
192 		DEBUG ("Search engine finished");
193 		nautilus_search_provider_finished (NAUTILUS_SEARCH_PROVIDER (engine));
194 	}
195 
196 	engine->details->running = FALSE;
197 	g_hash_table_remove_all (engine->details->uris);
198 
199 	if (engine->details->restart) {
200 		DEBUG ("Restarting engine");
201 		nautilus_search_engine_start (NAUTILUS_SEARCH_PROVIDER (engine));
202 	}
203 
204 	g_object_unref (engine);
205 }
206 
207 static void
208 search_provider_error (NautilusSearchProvider *provider,
209 		       const char             *error_message,
210 		       NautilusSearchEngine   *engine)
211 
212 {
213 	DEBUG ("Search provider error: %s", error_message);
214 	engine->details->providers_error++;
215 
216 	check_providers_status (engine);
217 }
218 
219 static void
220 search_provider_finished (NautilusSearchProvider *provider,
221 			  NautilusSearchEngine   *engine)
222 
223 {
224 	DEBUG ("Search provider finished");
225 	engine->details->providers_finished++;
226 
227 	check_providers_status (engine);
228 }
229 
230 static void
231 connect_provider_signals (NautilusSearchEngine   *engine,
232 			  NautilusSearchProvider *provider)
233 {
234 	g_signal_connect (provider, "hits-added",
235 			  G_CALLBACK (search_provider_hits_added),
236 			  engine);
237 	g_signal_connect (provider, "finished",
238 			  G_CALLBACK (search_provider_finished),
239 			  engine);
240 	g_signal_connect (provider, "error",
241 			  G_CALLBACK (search_provider_error),
242 			  engine);
243 }
244 
245 static void
246 nautilus_search_provider_init (NautilusSearchProviderIface *iface)
247 {
248 	iface->set_query = nautilus_search_engine_set_query;
249 	iface->start = nautilus_search_engine_start;
250 	iface->stop = nautilus_search_engine_stop;
251 }
252 
253 static void
254 nautilus_search_engine_finalize (GObject *object)
255 {
256 	NautilusSearchEngine *engine = NAUTILUS_SEARCH_ENGINE (object);
257 
258 	g_hash_table_destroy (engine->details->uris);
259 
260 #ifdef ENABLE_TRACKER
261 	g_clear_object (&engine->details->tracker);
262 #endif
263 	g_clear_object (&engine->details->model);
264 	g_clear_object (&engine->details->simple);
265 
266 	G_OBJECT_CLASS (nautilus_search_engine_parent_class)->finalize (object);
267 }
268 
269 static void
270 nautilus_search_engine_class_init (NautilusSearchEngineClass *class)
271 {
272 	GObjectClass *object_class;
273 
274 	object_class = (GObjectClass *) class;
275 
276 	object_class->finalize = nautilus_search_engine_finalize;
277 
278 	g_type_class_add_private (class, sizeof (NautilusSearchEngineDetails));
279 }
280 
281 static void
282 nautilus_search_engine_init (NautilusSearchEngine *engine)
283 {
284 	engine->details = G_TYPE_INSTANCE_GET_PRIVATE (engine,
285 						       NAUTILUS_TYPE_SEARCH_ENGINE,
286 						       NautilusSearchEngineDetails);
287 
288 	engine->details->uris = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
289 
290 #ifdef ENABLE_TRACKER
291 	engine->details->tracker = nautilus_search_engine_tracker_new ();
292 	connect_provider_signals (engine, NAUTILUS_SEARCH_PROVIDER (engine->details->tracker));
293 #endif
294 	engine->details->model = nautilus_search_engine_model_new ();
295 	connect_provider_signals (engine, NAUTILUS_SEARCH_PROVIDER (engine->details->model));
296 
297 	engine->details->simple = nautilus_search_engine_simple_new ();
298 	connect_provider_signals (engine, NAUTILUS_SEARCH_PROVIDER (engine->details->simple));
299 }
300 
301 NautilusSearchEngine *
302 nautilus_search_engine_new (void)
303 {
304 	NautilusSearchEngine *engine;
305 
306 	engine = g_object_new (NAUTILUS_TYPE_SEARCH_ENGINE, NULL);
307 
308 	return engine;
309 }
310 
311 NautilusSearchEngineModel *
312 nautilus_search_engine_get_model_provider (NautilusSearchEngine *engine)
313 {
314 	return engine->details->model;
315 }