1 /*
2  * Copyright (C) 2005 Red Hat, Inc.
3  *
4  * Nautilus is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * Nautilus is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public
15  * License along with this program; see the file COPYING.  If not,
16  * see <http://www.gnu.org/licenses/>.
17  *
18  * Author: Alexander Larsson <alexl@redhat.com>
19  *         Georges Basile Stavracas Neto <gbsneto@gnome.org>
20  *
21  */
22 
23 #include "nautilus-query-editor.h"
24 
25 #include <gdk/gdkkeysyms.h>
26 #include <gio/gio.h>
27 #include <glib/gi18n.h>
28 #include <gtk/gtk.h>
29 #include <libgd/gd.h>
30 #include <string.h>
31 
32 #include "nautilus-file.h"
33 #include "nautilus-file-utilities.h"
34 #include "nautilus-global-preferences.h"
35 #include "nautilus-search-directory.h"
36 #include "nautilus-search-popover.h"
37 #include "nautilus-mime-actions.h"
38 #include "nautilus-ui-utilities.h"
39 
40 struct _NautilusQueryEditor
41 {
42     GtkBox parent_instance;
43 
44     GtkWidget *entry;
45     GtkWidget *popover;
46     GtkWidget *dropdown_button;
47 
48     GdTaggedEntryTag *mime_types_tag;
49     GdTaggedEntryTag *date_range_tag;
50 
51     gboolean change_frozen;
52 
53     GFile *location;
54 
55     NautilusQuery *query;
56 };
57 
58 enum
59 {
60     ACTIVATED,
61     FOCUS_VIEW,
62     CHANGED,
63     CANCEL,
64     LAST_SIGNAL
65 };
66 
67 enum
68 {
69     PROP_0,
70     PROP_LOCATION,
71     PROP_QUERY,
72     LAST_PROP
73 };
74 
75 static guint signals[LAST_SIGNAL];
76 
77 static void entry_activate_cb (GtkWidget           *entry,
78                                NautilusQueryEditor *editor);
79 static void entry_changed_cb (GtkWidget           *entry,
80                               NautilusQueryEditor *editor);
81 static void nautilus_query_editor_changed (NautilusQueryEditor *editor);
82 
83 G_DEFINE_TYPE (NautilusQueryEditor, nautilus_query_editor, GTK_TYPE_BOX);
84 
85 static void
update_fts_sensitivity(NautilusQueryEditor * editor)86 update_fts_sensitivity (NautilusQueryEditor *editor)
87 {
88     gboolean fts_sensitive = TRUE;
89 
90     if (editor->location)
91     {
92         g_autoptr (NautilusFile) file = NULL;
93         g_autofree gchar *uri = NULL;
94 
95         file = nautilus_file_get (editor->location);
96         uri = g_file_get_uri (editor->location);
97 
98         fts_sensitive = !nautilus_file_is_other_locations (file) &&
99                         !g_str_has_prefix (uri, "network://") &&
100                         !(nautilus_file_is_remote (file) &&
101                           location_settings_search_get_recursive_for_location (editor->location) == NAUTILUS_QUERY_RECURSIVE_NEVER);
102         nautilus_search_popover_set_fts_sensitive (NAUTILUS_SEARCH_POPOVER (editor->popover),
103                                                    fts_sensitive);
104     }
105 }
106 
107 static void
recursive_search_preferences_changed(GSettings * settings,gchar * key,NautilusQueryEditor * editor)108 recursive_search_preferences_changed (GSettings           *settings,
109                                       gchar               *key,
110                                       NautilusQueryEditor *editor)
111 {
112     NautilusQueryRecursive recursive;
113 
114     if (!editor->query)
115     {
116         return;
117     }
118 
119     recursive = location_settings_search_get_recursive ();
120     if (recursive != nautilus_query_get_recursive (editor->query))
121     {
122         nautilus_query_set_recursive (editor->query, recursive);
123         nautilus_query_editor_changed (editor);
124     }
125 
126     update_fts_sensitivity (editor);
127 }
128 
129 
130 static void
nautilus_query_editor_dispose(GObject * object)131 nautilus_query_editor_dispose (GObject *object)
132 {
133     NautilusQueryEditor *editor;
134 
135     editor = NAUTILUS_QUERY_EDITOR (object);
136 
137     g_clear_object (&editor->location);
138     g_clear_object (&editor->query);
139 
140     g_signal_handlers_disconnect_by_func (nautilus_preferences,
141                                           recursive_search_preferences_changed,
142                                           object);
143 
144     G_OBJECT_CLASS (nautilus_query_editor_parent_class)->dispose (object);
145 }
146 
147 static void
nautilus_query_editor_grab_focus(GtkWidget * widget)148 nautilus_query_editor_grab_focus (GtkWidget *widget)
149 {
150     NautilusQueryEditor *editor;
151 
152     editor = NAUTILUS_QUERY_EDITOR (widget);
153 
154     if (gtk_widget_get_visible (widget) && !gtk_widget_is_focus (editor->entry))
155     {
156         /* avoid selecting the entry text */
157         gtk_widget_grab_focus (editor->entry);
158         gtk_editable_set_position (GTK_EDITABLE (editor->entry), -1);
159     }
160 }
161 
162 static void
nautilus_query_editor_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)163 nautilus_query_editor_get_property (GObject    *object,
164                                     guint       prop_id,
165                                     GValue     *value,
166                                     GParamSpec *pspec)
167 {
168     NautilusQueryEditor *editor;
169 
170     editor = NAUTILUS_QUERY_EDITOR (object);
171 
172     switch (prop_id)
173     {
174         case PROP_LOCATION:
175         {
176             g_value_set_object (value, editor->location);
177         }
178         break;
179 
180         case PROP_QUERY:
181         {
182             g_value_set_object (value, editor->query);
183         }
184         break;
185 
186         default:
187         {
188             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
189         }
190     }
191 }
192 
193 static void
nautilus_query_editor_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)194 nautilus_query_editor_set_property (GObject      *object,
195                                     guint         prop_id,
196                                     const GValue *value,
197                                     GParamSpec   *pspec)
198 {
199     NautilusQueryEditor *self;
200 
201     self = NAUTILUS_QUERY_EDITOR (object);
202 
203     switch (prop_id)
204     {
205         case PROP_LOCATION:
206         {
207             nautilus_query_editor_set_location (self, g_value_get_object (value));
208         }
209         break;
210 
211         case PROP_QUERY:
212         {
213             nautilus_query_editor_set_query (self, g_value_get_object (value));
214         }
215         break;
216 
217         default:
218         {
219             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
220         }
221     }
222 }
223 
224 static void
nautilus_query_editor_finalize(GObject * object)225 nautilus_query_editor_finalize (GObject *object)
226 {
227     NautilusQueryEditor *editor;
228 
229     editor = NAUTILUS_QUERY_EDITOR (object);
230 
231     g_clear_object (&editor->date_range_tag);
232     g_clear_object (&editor->mime_types_tag);
233 
234     G_OBJECT_CLASS (nautilus_query_editor_parent_class)->finalize (object);
235 }
236 
237 static void
nautilus_query_editor_class_init(NautilusQueryEditorClass * class)238 nautilus_query_editor_class_init (NautilusQueryEditorClass *class)
239 {
240     GObjectClass *gobject_class;
241     GtkWidgetClass *widget_class;
242 
243     gobject_class = G_OBJECT_CLASS (class);
244     gobject_class->finalize = nautilus_query_editor_finalize;
245     gobject_class->dispose = nautilus_query_editor_dispose;
246     gobject_class->get_property = nautilus_query_editor_get_property;
247     gobject_class->set_property = nautilus_query_editor_set_property;
248 
249     widget_class = GTK_WIDGET_CLASS (class);
250     widget_class->grab_focus = nautilus_query_editor_grab_focus;
251 
252     signals[CHANGED] =
253         g_signal_new ("changed",
254                       G_TYPE_FROM_CLASS (class),
255                       G_SIGNAL_RUN_LAST,
256                       0,
257                       NULL, NULL,
258                       g_cclosure_marshal_generic,
259                       G_TYPE_NONE, 2, NAUTILUS_TYPE_QUERY, G_TYPE_BOOLEAN);
260 
261     signals[CANCEL] =
262         g_signal_new ("cancel",
263                       G_TYPE_FROM_CLASS (class),
264                       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
265                       0,
266                       NULL, NULL,
267                       g_cclosure_marshal_VOID__VOID,
268                       G_TYPE_NONE, 0);
269 
270     signals[ACTIVATED] =
271         g_signal_new ("activated",
272                       G_TYPE_FROM_CLASS (class),
273                       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
274                       0,
275                       NULL, NULL,
276                       g_cclosure_marshal_VOID__VOID,
277                       G_TYPE_NONE, 0);
278 
279     signals[FOCUS_VIEW] =
280         g_signal_new ("focus-view",
281                       G_TYPE_FROM_CLASS (class),
282                       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
283                       0,
284                       NULL, NULL,
285                       g_cclosure_marshal_VOID__VOID,
286                       G_TYPE_NONE, 0);
287 
288     gtk_binding_entry_add_signal (gtk_binding_set_by_class (class),
289                                   GDK_KEY_Down,
290                                   0,
291                                   "focus-view",
292                                   0);
293 
294     /**
295      * NautilusQueryEditor::location:
296      *
297      * The current location of the query editor.
298      */
299     g_object_class_install_property (gobject_class,
300                                      PROP_LOCATION,
301                                      g_param_spec_object ("location",
302                                                           "Location of the search",
303                                                           "The current location of the editor",
304                                                           G_TYPE_FILE,
305                                                           G_PARAM_READWRITE));
306 
307     /**
308      * NautilusQueryEditor::query:
309      *
310      * The current query of the query editor. It it always synchronized
311      * with the filter popover's query.
312      */
313     g_object_class_install_property (gobject_class,
314                                      PROP_QUERY,
315                                      g_param_spec_object ("query",
316                                                           "Query of the search",
317                                                           "The query that the editor is handling",
318                                                           NAUTILUS_TYPE_QUERY,
319                                                           G_PARAM_READWRITE));
320 }
321 
322 GFile *
nautilus_query_editor_get_location(NautilusQueryEditor * editor)323 nautilus_query_editor_get_location (NautilusQueryEditor *editor)
324 {
325     g_return_val_if_fail (NAUTILUS_IS_QUERY_EDITOR (editor), NULL);
326 
327     return g_object_ref (editor->location);
328 }
329 
330 static void
create_query(NautilusQueryEditor * editor)331 create_query (NautilusQueryEditor *editor)
332 {
333     NautilusQuery *query;
334     g_autoptr (NautilusFile) file = NULL;
335     gboolean fts_enabled;
336 
337     g_return_if_fail (editor->query == NULL);
338 
339     fts_enabled = nautilus_search_popover_get_fts_enabled (NAUTILUS_SEARCH_POPOVER (editor->popover));
340 
341     if (editor->location == NULL)
342     {
343         return;
344     }
345 
346     file = nautilus_file_get (editor->location);
347     query = nautilus_query_new ();
348 
349     nautilus_query_set_search_content (query, fts_enabled);
350 
351     nautilus_query_set_text (query, gtk_entry_get_text (GTK_ENTRY (editor->entry)));
352     nautilus_query_set_location (query, editor->location);
353 
354     /* We only set the query using the global setting for recursivity here,
355      * it's up to the search engine to check weather it can proceed with
356      * deep search in the current directory or not. */
357     nautilus_query_set_recursive (query, location_settings_search_get_recursive ());
358 
359     nautilus_query_editor_set_query (editor, query);
360 }
361 
362 static void
entry_activate_cb(GtkWidget * entry,NautilusQueryEditor * editor)363 entry_activate_cb (GtkWidget           *entry,
364                    NautilusQueryEditor *editor)
365 {
366     g_signal_emit (editor, signals[ACTIVATED], 0);
367 }
368 
369 static void
entry_changed_cb(GtkWidget * entry,NautilusQueryEditor * editor)370 entry_changed_cb (GtkWidget           *entry,
371                   NautilusQueryEditor *editor)
372 {
373     if (editor->change_frozen)
374     {
375         return;
376     }
377 
378     if (editor->query == NULL)
379     {
380         create_query (editor);
381     }
382     else
383     {
384         g_autofree gchar *text = NULL;
385 
386         text = g_strdup (gtk_entry_get_text (GTK_ENTRY (editor->entry)));
387         text = g_strstrip (text);
388 
389         nautilus_query_set_text (editor->query, text);
390     }
391 
392     nautilus_query_editor_changed (editor);
393 }
394 
395 static void
nautilus_query_editor_on_stop_search(GtkWidget * entry,NautilusQueryEditor * editor)396 nautilus_query_editor_on_stop_search (GtkWidget           *entry,
397                                       NautilusQueryEditor *editor)
398 {
399     g_signal_emit (editor, signals[CANCEL], 0);
400 }
401 
402 /* Type */
403 
404 static void
nautilus_query_editor_init(NautilusQueryEditor * editor)405 nautilus_query_editor_init (NautilusQueryEditor *editor)
406 {
407     g_signal_connect (nautilus_preferences,
408                       "changed::recursive-search",
409                       G_CALLBACK (recursive_search_preferences_changed),
410                       editor);
411 }
412 
413 static void
search_popover_date_range_changed_cb(NautilusSearchPopover * popover,GPtrArray * date_range,gpointer user_data)414 search_popover_date_range_changed_cb (NautilusSearchPopover *popover,
415                                       GPtrArray             *date_range,
416                                       gpointer               user_data)
417 {
418     NautilusQueryEditor *editor;
419 
420     editor = NAUTILUS_QUERY_EDITOR (user_data);
421 
422     if (editor->query == NULL)
423     {
424         create_query (editor);
425     }
426 
427     gd_tagged_entry_remove_tag (GD_TAGGED_ENTRY (editor->entry),
428                                 editor->date_range_tag);
429     if (date_range)
430     {
431         g_autofree gchar *text_for_date_range = NULL;
432 
433         text_for_date_range = get_text_for_date_range (date_range, TRUE);
434         gd_tagged_entry_tag_set_label (editor->date_range_tag,
435                                        text_for_date_range);
436         gd_tagged_entry_add_tag (GD_TAGGED_ENTRY (editor->entry),
437                                  GD_TAGGED_ENTRY_TAG (editor->date_range_tag));
438     }
439 
440     nautilus_query_set_date_range (editor->query, date_range);
441 
442     nautilus_query_editor_changed (editor);
443 }
444 
445 static void
search_popover_mime_type_changed_cb(NautilusSearchPopover * popover,gint mimetype_group,const gchar * mimetype,gpointer user_data)446 search_popover_mime_type_changed_cb (NautilusSearchPopover *popover,
447                                      gint                   mimetype_group,
448                                      const gchar           *mimetype,
449                                      gpointer               user_data)
450 {
451     NautilusQueryEditor *editor;
452     g_autoptr (GPtrArray) mimetypes = NULL;
453 
454     editor = NAUTILUS_QUERY_EDITOR (user_data);
455 
456     if (editor->query == NULL)
457     {
458         create_query (editor);
459     }
460 
461     gd_tagged_entry_remove_tag (GD_TAGGED_ENTRY (editor->entry),
462                                 editor->mime_types_tag);
463     /* group 0 is anything */
464     if (mimetype_group == 0)
465     {
466         mimetypes = nautilus_mime_types_group_get_mimetypes (mimetype_group);
467     }
468     else if (mimetype_group > 0)
469     {
470         mimetypes = nautilus_mime_types_group_get_mimetypes (mimetype_group);
471         gd_tagged_entry_tag_set_label (editor->mime_types_tag,
472                                        nautilus_mime_types_group_get_name (mimetype_group));
473         gd_tagged_entry_add_tag (GD_TAGGED_ENTRY (editor->entry),
474                                  GD_TAGGED_ENTRY_TAG (editor->mime_types_tag));
475     }
476     else
477     {
478         g_autofree gchar *display_name = NULL;
479 
480         mimetypes = g_ptr_array_new_full (1, g_free);
481         g_ptr_array_add (mimetypes, g_strdup (mimetype));
482         display_name = g_content_type_get_description (mimetype);
483         gd_tagged_entry_tag_set_label (editor->mime_types_tag, display_name);
484         gd_tagged_entry_add_tag (GD_TAGGED_ENTRY (editor->entry),
485                                  GD_TAGGED_ENTRY_TAG (editor->mime_types_tag));
486     }
487     nautilus_query_set_mime_types (editor->query, mimetypes);
488 
489     nautilus_query_editor_changed (editor);
490 }
491 
492 static void
search_popover_time_type_changed_cb(NautilusSearchPopover * popover,NautilusQuerySearchType data,gpointer user_data)493 search_popover_time_type_changed_cb (NautilusSearchPopover   *popover,
494                                      NautilusQuerySearchType  data,
495                                      gpointer                 user_data)
496 {
497     NautilusQueryEditor *editor;
498 
499     editor = NAUTILUS_QUERY_EDITOR (user_data);
500 
501     if (editor->query == NULL)
502     {
503         create_query (editor);
504     }
505 
506     nautilus_query_set_search_type (editor->query, data);
507 
508     nautilus_query_editor_changed (editor);
509 }
510 
511 static void
search_popover_fts_changed_cb(GObject * popover,GParamSpec * pspec,gpointer user_data)512 search_popover_fts_changed_cb (GObject    *popover,
513                                GParamSpec *pspec,
514                                gpointer    user_data)
515 {
516     NautilusQueryEditor *editor;
517 
518     editor = NAUTILUS_QUERY_EDITOR (user_data);
519 
520     if (editor->query == NULL)
521     {
522         create_query (editor);
523     }
524 
525     nautilus_query_set_search_content (editor->query,
526                                        nautilus_search_popover_get_fts_enabled (NAUTILUS_SEARCH_POPOVER (popover)));
527 
528     nautilus_query_editor_changed (editor);
529 }
530 
531 static void
entry_tag_clicked(NautilusQueryEditor * editor)532 entry_tag_clicked (NautilusQueryEditor *editor)
533 {
534     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (editor->dropdown_button),
535                                   TRUE);
536 }
537 
538 static void
entry_tag_close_button_clicked(NautilusQueryEditor * editor,GdTaggedEntryTag * tag)539 entry_tag_close_button_clicked (NautilusQueryEditor *editor,
540                                 GdTaggedEntryTag    *tag)
541 {
542     if (tag == editor->mime_types_tag)
543     {
544         nautilus_search_popover_reset_mime_types (NAUTILUS_SEARCH_POPOVER (editor->popover));
545     }
546     else
547     {
548         nautilus_search_popover_reset_date_range (NAUTILUS_SEARCH_POPOVER (editor->popover));
549     }
550 }
551 
552 static void
setup_widgets(NautilusQueryEditor * editor)553 setup_widgets (NautilusQueryEditor *editor)
554 {
555     GtkWidget *hbox;
556     GtkWidget *vbox;
557 
558     /* vertical box that holds the search entry and the label below */
559     vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
560     gtk_container_add (GTK_CONTAINER (editor), vbox);
561 
562     /* horizontal box */
563     hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
564     gtk_style_context_add_class (gtk_widget_get_style_context (hbox), "linked");
565     gtk_container_add (GTK_CONTAINER (vbox), hbox);
566 
567     /* create the search entry */
568     editor->entry = GTK_WIDGET (gd_tagged_entry_new ());
569     gtk_widget_set_hexpand (editor->entry, TRUE);
570 
571     gtk_container_add (GTK_CONTAINER (hbox), editor->entry);
572 
573     editor->mime_types_tag = gd_tagged_entry_tag_new (NULL);
574     editor->date_range_tag = gd_tagged_entry_tag_new (NULL);
575 
576     g_signal_connect_swapped (editor->entry,
577                               "tag-clicked",
578                               G_CALLBACK (entry_tag_clicked),
579                               editor);
580     g_signal_connect_swapped (editor->entry,
581                               "tag-button-clicked",
582                               G_CALLBACK (entry_tag_close_button_clicked),
583                               editor);
584 
585     /* setup the search popover */
586     editor->popover = nautilus_search_popover_new ();
587 
588     g_signal_connect (editor->popover, "show",
589                       G_CALLBACK (gtk_widget_grab_focus), NULL);
590     g_signal_connect_swapped (editor->popover, "closed",
591                               G_CALLBACK (gtk_widget_grab_focus), editor);
592 
593     g_object_bind_property (editor, "query",
594                             editor->popover, "query",
595                             G_BINDING_DEFAULT);
596 
597     /* setup the filter menu button */
598     editor->dropdown_button = gtk_menu_button_new ();
599     gtk_menu_button_set_popover (GTK_MENU_BUTTON (editor->dropdown_button), editor->popover);
600     gtk_container_add (GTK_CONTAINER (hbox), editor->dropdown_button);
601 
602     g_signal_connect (editor->entry, "activate",
603                       G_CALLBACK (entry_activate_cb), editor);
604     g_signal_connect (editor->entry, "search-changed",
605                       G_CALLBACK (entry_changed_cb), editor);
606     g_signal_connect (editor->entry, "stop-search",
607                       G_CALLBACK (nautilus_query_editor_on_stop_search), editor);
608     g_signal_connect (editor->popover, "date-range",
609                       G_CALLBACK (search_popover_date_range_changed_cb), editor);
610     g_signal_connect (editor->popover, "mime-type",
611                       G_CALLBACK (search_popover_mime_type_changed_cb), editor);
612     g_signal_connect (editor->popover, "time-type",
613                       G_CALLBACK (search_popover_time_type_changed_cb), editor);
614     g_signal_connect (editor->popover, "notify::fts-enabled",
615                       G_CALLBACK (search_popover_fts_changed_cb), editor);
616 
617     /* show everything */
618     gtk_widget_show_all (vbox);
619 }
620 
621 static void
nautilus_query_editor_changed(NautilusQueryEditor * editor)622 nautilus_query_editor_changed (NautilusQueryEditor *editor)
623 {
624     if (editor->change_frozen)
625     {
626         return;
627     }
628 
629     g_signal_emit (editor, signals[CHANGED], 0, editor->query, TRUE);
630 }
631 
632 NautilusQuery *
nautilus_query_editor_get_query(NautilusQueryEditor * editor)633 nautilus_query_editor_get_query (NautilusQueryEditor *editor)
634 {
635     g_return_val_if_fail (NAUTILUS_IS_QUERY_EDITOR (editor), NULL);
636 
637     if (editor->entry == NULL)
638     {
639         return NULL;
640     }
641 
642     return editor->query;
643 }
644 
645 GtkWidget *
nautilus_query_editor_new(void)646 nautilus_query_editor_new (void)
647 {
648     NautilusQueryEditor *editor;
649 
650     editor = g_object_new (NAUTILUS_TYPE_QUERY_EDITOR, NULL);
651 
652     setup_widgets (editor);
653 
654     return GTK_WIDGET (editor);
655 }
656 
657 void
nautilus_query_editor_set_location(NautilusQueryEditor * editor,GFile * location)658 nautilus_query_editor_set_location (NautilusQueryEditor *editor,
659                                     GFile               *location)
660 {
661     g_autoptr (NautilusDirectory) directory = NULL;
662     NautilusDirectory *base_model;
663     gboolean should_notify;
664 
665     g_return_if_fail (NAUTILUS_IS_QUERY_EDITOR (editor));
666 
667     /* The client could set us a location that is actually a search directory,
668      * like what happens with the slot when updating the query editor location.
669      * However here we want the real location used as a model for the search,
670      * not the search directory invented uri. */
671     directory = nautilus_directory_get (location);
672     if (NAUTILUS_IS_SEARCH_DIRECTORY (directory))
673     {
674         g_autoptr (GFile) real_location = NULL;
675 
676         base_model = nautilus_search_directory_get_base_model (NAUTILUS_SEARCH_DIRECTORY (directory));
677         real_location = nautilus_directory_get_location (base_model);
678 
679         should_notify = g_set_object (&editor->location, real_location);
680     }
681     else
682     {
683         should_notify = g_set_object (&editor->location, location);
684     }
685 
686     if (editor->query == NULL)
687     {
688         create_query (editor);
689     }
690     nautilus_query_set_location (editor->query, editor->location);
691 
692     update_fts_sensitivity (editor);
693 
694     if (should_notify)
695     {
696         g_object_notify (G_OBJECT (editor), "location");
697     }
698 }
699 
700 void
nautilus_query_editor_set_query(NautilusQueryEditor * self,NautilusQuery * query)701 nautilus_query_editor_set_query (NautilusQueryEditor *self,
702                                  NautilusQuery       *query)
703 {
704     g_autofree char *text = NULL;
705     g_autofree char *current_text = NULL;
706 
707     g_return_if_fail (NAUTILUS_IS_QUERY_EDITOR (self));
708 
709     if (query != NULL)
710     {
711         text = nautilus_query_get_text (query);
712     }
713 
714     if (!text)
715     {
716         text = g_strdup ("");
717     }
718 
719     self->change_frozen = TRUE;
720 
721     current_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->entry)));
722     current_text = g_strstrip (current_text);
723     if (!g_str_equal (current_text, text))
724     {
725         gtk_entry_set_text (GTK_ENTRY (self->entry), text);
726     }
727 
728     if (g_set_object (&self->query, query))
729     {
730         g_object_notify (G_OBJECT (self), "query");
731     }
732 
733     self->change_frozen = FALSE;
734 }
735 
736 void
nautilus_query_editor_set_text(NautilusQueryEditor * self,const gchar * text)737 nautilus_query_editor_set_text (NautilusQueryEditor *self,
738                                 const gchar         *text)
739 {
740     g_return_if_fail (NAUTILUS_IS_QUERY_EDITOR (self));
741     g_return_if_fail (text != NULL);
742 
743     /* The handler of the entry will take care of everything */
744     gtk_entry_set_text (GTK_ENTRY (self->entry), text);
745 }
746 
747 gboolean
nautilus_query_editor_handle_event(NautilusQueryEditor * self,GdkEvent * event)748 nautilus_query_editor_handle_event (NautilusQueryEditor *self,
749                                     GdkEvent            *event)
750 {
751     g_return_val_if_fail (NAUTILUS_IS_QUERY_EDITOR (self), GDK_EVENT_PROPAGATE);
752     g_return_val_if_fail (event != NULL, GDK_EVENT_PROPAGATE);
753 
754     return gtk_search_entry_handle_event (GTK_SEARCH_ENTRY (self->entry), event);
755 }
756