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 }