/* nautilus-search-popover.c
*
* Copyright (C) 2015 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* This program 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.
*
* This program 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 "nautilus-enum-types.h"
#include "nautilus-search-popover.h"
#include "nautilus-mime-actions.h"
#include <glib/gi18n.h>
#include "nautilus-file.h"
#include "nautilus-ui-utilities.h"
#include "nautilus-global-preferences.h"
#define SEARCH_FILTER_MAX_YEARS 5
struct _NautilusSearchPopover
{
GtkPopover parent;
GtkWidget *around_revealer;
GtkWidget *around_stack;
GtkWidget *calendar;
GtkWidget *clear_date_button;
GtkWidget *dates_listbox;
GtkWidget *date_entry;
GtkWidget *date_stack;
GtkWidget *select_date_button;
GtkWidget *select_date_button_label;
GtkWidget *type_label;
GtkWidget *type_listbox;
GtkWidget *type_stack;
GtkWidget *last_used_button;
GtkWidget *last_modified_button;
GtkWidget *full_text_search_button;
GtkWidget *filename_search_button;
NautilusQuery *query;
gboolean fts_enabled;
};
static void show_date_selection_widgets (NautilusSearchPopover *popover,
gboolean visible);
static void show_other_types_dialog (NautilusSearchPopover *popover);
static void update_date_label (NautilusSearchPopover *popover,
GPtrArray *date_range);
G_DEFINE_TYPE (NautilusSearchPopover, nautilus_search_popover, GTK_TYPE_POPOVER)
enum
{
PROP_0,
PROP_QUERY,
PROP_FTS_ENABLED,
LAST_PROP
};
enum
{
MIME_TYPE,
TIME_TYPE,
DATE_RANGE,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
/* Callbacks */
static void
calendar_day_selected (GtkCalendar *calendar,
NautilusSearchPopover *popover)
{
GDateTime *date;
guint year, month, day;
GPtrArray *date_range;
gtk_calendar_get_date (calendar, &year, &month, &day);
date = g_date_time_new_local (year, month + 1, day, 0, 0, 0);
date_range = g_ptr_array_new_full (2, (GDestroyNotify) g_date_time_unref);
g_ptr_array_add (date_range, g_date_time_ref (date));
g_ptr_array_add (date_range, g_date_time_ref (date));
update_date_label (popover, date_range);
g_signal_emit_by_name (popover, "date-range", date_range);
g_ptr_array_unref (date_range);
g_date_time_unref (date);
}
/* Range on dates are partially implemented. For now just use it for differentation
* between a exact day or a range of a first day until now.
*/
static void
setup_date (NautilusSearchPopover *popover,
NautilusQuery *query)
{
GPtrArray *date_range;
GDateTime *date_initial;
date_range = nautilus_query_get_date_range (query);
if (date_range)
{
date_initial = g_ptr_array_index (date_range, 0);
g_signal_handlers_block_by_func (popover->calendar, calendar_day_selected, popover);
gtk_calendar_select_month (GTK_CALENDAR (popover->calendar),
g_date_time_get_month (date_initial) - 1,
g_date_time_get_year (date_initial));
gtk_calendar_select_day (GTK_CALENDAR (popover->calendar),
g_date_time_get_day_of_month (date_initial));
update_date_label (popover, date_range);
g_signal_handlers_unblock_by_func (popover->calendar, calendar_day_selected, popover);
}
}
static void
query_date_changed (GObject *object,
GParamSpec *pspec,
NautilusSearchPopover *popover)
{
setup_date (popover, NAUTILUS_QUERY (object));
}
static void
clear_date_button_clicked (GtkButton *button,
NautilusSearchPopover *popover)
{
nautilus_search_popover_reset_date_range (popover);
}
static void
date_entry_activate (GtkEntry *entry,
NautilusSearchPopover *popover)
{
if (gtk_entry_get_text_length (entry) > 0)
{
GDateTime *now;
GDateTime *date_time;
GDate *date;
date = g_date_new ();
g_date_set_parse (date, gtk_entry_get_text (entry));
/* Invalid date silently does nothing */
if (!g_date_valid (date))
{
g_date_free (date);
return;
}
now = g_date_time_new_now_local ();
date_time = g_date_time_new_local (g_date_get_year (date),
g_date_get_month (date),
g_date_get_day (date),
0,
0,
0);
/* Future dates also silently fails */
if (g_date_time_compare (date_time, now) != 1)
{
GPtrArray *date_range;
date_range = g_ptr_array_new_full (2, (GDestroyNotify) g_date_time_unref);
g_ptr_array_add (date_range, g_date_time_ref (date_time));
g_ptr_array_add (date_range, g_date_time_ref (date_time));
update_date_label (popover, date_range);
show_date_selection_widgets (popover, FALSE);
g_signal_emit_by_name (popover, "date-range", date_range);
g_ptr_array_unref (date_range);
}
g_date_time_unref (now);
g_date_time_unref (date_time);
g_date_free (date);
}
}
static void
dates_listbox_row_activated (GtkListBox *listbox,
GtkListBoxRow *row,
NautilusSearchPopover *popover)
{
GDateTime *date;
GDateTime *now;
GPtrArray *date_range = NULL;
now = g_date_time_new_now_local ();
date = g_object_get_data (G_OBJECT (row), "date");
if (date)
{
date_range = g_ptr_array_new_full (2, (GDestroyNotify) g_date_time_unref);
g_ptr_array_add (date_range, g_date_time_ref (date));
g_ptr_array_add (date_range, g_date_time_ref (now));
}
update_date_label (popover, date_range);
show_date_selection_widgets (popover, FALSE);
g_signal_emit_by_name (popover, "date-range", date_range);
if (date_range)
{
g_ptr_array_unref (date_range);
}
g_date_time_unref (now);
}
static void
listbox_header_func (GtkListBoxRow *row,
GtkListBoxRow *before,
NautilusSearchPopover *popover)
{
gboolean show_separator;
show_separator = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (row), "show-separator"));
if (show_separator)
{
GtkWidget *separator;
separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
gtk_widget_show (separator);
gtk_list_box_row_set_header (row, separator);
}
}
static void
select_date_button_clicked (GtkButton *button,
NautilusSearchPopover *popover)
{
/* Hide the type selection widgets when date selection
* widgets are shown.
*/
gtk_stack_set_visible_child_name (GTK_STACK (popover->type_stack), "type-button");
show_date_selection_widgets (popover, TRUE);
}
static void
select_type_button_clicked (GtkButton *button,
NautilusSearchPopover *popover)
{
GtkListBoxRow *selected_row;
selected_row = gtk_list_box_get_selected_row (GTK_LIST_BOX (popover->type_listbox));
gtk_stack_set_visible_child_name (GTK_STACK (popover->type_stack), "type-list");
if (selected_row != NULL)
{
gtk_widget_grab_focus (GTK_WIDGET (selected_row));
}
/* Hide the date selection widgets when the type selection
* listbox is shown.
*/
show_date_selection_widgets (popover, FALSE);
}
static void
toggle_calendar_icon_clicked (GtkEntry *entry,
GtkEntryIconPosition position,
GdkEvent *event,
NautilusSearchPopover *popover)
{
const gchar *current_visible_child;
const gchar *child;
const gchar *icon_name;
const gchar *tooltip;
current_visible_child = gtk_stack_get_visible_child_name (GTK_STACK (popover->around_stack));
if (g_strcmp0 (current_visible_child, "date-list") == 0)
{
child = "date-calendar";
icon_name = "view-list-symbolic";
tooltip = _("Show a list to select the date");
}
else
{
child = "date-list";
icon_name = "x-office-calendar-symbolic";
tooltip = _("Show a calendar to select the date");
}
gtk_stack_set_visible_child_name (GTK_STACK (popover->around_stack), child);
gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY, icon_name);
gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY, tooltip);
}
static void
types_listbox_row_activated (GtkListBox *listbox,
GtkListBoxRow *row,
NautilusSearchPopover *popover)
{
gint group;
group = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (row), "mimetype-group"));
/* The -1 group stands for the "Other Types" group, for which
* we should show the mimetype dialog.
*/
if (group == -1)
{
show_other_types_dialog (popover);
}
else
{
gtk_label_set_label (GTK_LABEL (popover->type_label),
nautilus_mime_types_group_get_name (group));
g_signal_emit_by_name (popover, "mime-type", group, NULL);
}
gtk_stack_set_visible_child_name (GTK_STACK (popover->type_stack), "type-button");
}
static void
search_time_type_changed (GtkToggleButton *button,
NautilusSearchPopover *popover)
{
NautilusQuerySearchType type = -1;
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (popover->last_modified_button)))
{
type = NAUTILUS_QUERY_SEARCH_TYPE_LAST_MODIFIED;
}
else
{
type = NAUTILUS_QUERY_SEARCH_TYPE_LAST_ACCESS;
}
g_settings_set_enum (nautilus_preferences, "search-filter-time-type", type);
g_signal_emit_by_name (popover, "time-type", type, NULL);
}
static void
search_fts_mode_changed (GtkToggleButton *button,
NautilusSearchPopover *popover)
{
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (popover->full_text_search_button)) &&
popover->fts_enabled == FALSE)
{
popover->fts_enabled = TRUE;
g_settings_set_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_FTS_ENABLED, TRUE);
g_object_notify (G_OBJECT (popover), "fts-enabled");
}
else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (popover->filename_search_button)) &&
popover->fts_enabled == TRUE)
{
popover->fts_enabled = FALSE;
g_settings_set_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_FTS_ENABLED, FALSE);
g_object_notify (G_OBJECT (popover), "fts-enabled");
}
}
/* Auxiliary methods */
static GtkWidget *
create_row_for_label (const gchar *text,
gboolean show_separator)
{
GtkWidget *row;
GtkWidget *label;
row = gtk_list_box_row_new ();
g_object_set_data (G_OBJECT (row), "show-separator", GINT_TO_POINTER (show_separator));
label = g_object_new (GTK_TYPE_LABEL,
"label", text,
"hexpand", TRUE,
"xalign", 0.0,
"margin-start", 6,
NULL);
gtk_container_add (GTK_CONTAINER (row), label);
gtk_widget_show_all (row);
return row;
}
static void
fill_fuzzy_dates_listbox (NautilusSearchPopover *popover)
{
GDateTime *maximum_dt, *now;
GtkWidget *row;
GDateTime *current_date;
GPtrArray *date_range;
gint days, max_days;
days = 1;
maximum_dt = g_date_time_new_from_unix_local (0);
now = g_date_time_new_now_local ();
max_days = SEARCH_FILTER_MAX_YEARS * 365;
/* Add the no date filter element first */
row = create_row_for_label (_("Any time"), TRUE);
gtk_container_add (GTK_CONTAINER (popover->dates_listbox), row);
/* This is a tricky loop. The main intention here is that each
* timeslice (day, week, month) have 2 or 3 entries.
*
* For the first appearance of each timeslice, there is made a
* check in order to be sure that there is no offset added to days.
*/
while (days <= max_days)
{
gchar *label;
gint normalized;
gint step;
if (days < 7)
{
/* days */
normalized = days;
step = 2;
}
else if (days < 30)
{
/* weeks */
normalized = days / 7;
if (normalized == 1)
{
days = 7;
}
step = 7;
}
else if (days < 365)
{
/* months */
normalized = days / 30;
if (normalized == 1)
{
days = 30;
}
step = 90;
}
else
{
/* years */
normalized = days / 365;
if (normalized == 1)
{
days = 365;
}
step = 365;
}
current_date = g_date_time_add_days (now, -days);
date_range = g_ptr_array_new_full (2, (GDestroyNotify) g_date_time_unref);
g_ptr_array_add (date_range, g_date_time_ref (current_date));
g_ptr_array_add (date_range, g_date_time_ref (now));
label = get_text_for_date_range (date_range, FALSE);
row = create_row_for_label (label, normalized == 1);
g_object_set_data_full (G_OBJECT (row),
"date",
g_date_time_ref (current_date),
(GDestroyNotify) g_date_time_unref);
gtk_container_add (GTK_CONTAINER (popover->dates_listbox), row);
g_free (label);
g_date_time_unref (current_date);
g_ptr_array_unref (date_range);
days += step;
}
g_date_time_unref (maximum_dt);
g_date_time_unref (now);
}
static void
fill_types_listbox (NautilusSearchPopover *popover)
{
GtkWidget *row;
int i;
gint n_groups;
n_groups = nautilus_mime_types_get_number_of_groups ();
/* Mimetypes */
for (i = 0; i < n_groups; i++)
{
/* On the third row, which is right below "Folders", there should be an
* separator to logically group the types.
*/
row = create_row_for_label (nautilus_mime_types_group_get_name (i), i == 3);
g_object_set_data (G_OBJECT (row), "mimetype-group", GINT_TO_POINTER (i));
gtk_container_add (GTK_CONTAINER (popover->type_listbox), row);
}
/* Other types */
row = create_row_for_label (_("Other Type…"), TRUE);
g_object_set_data (G_OBJECT (row), "mimetype-group", GINT_TO_POINTER (-1));
gtk_container_add (GTK_CONTAINER (popover->type_listbox), row);
}
static void
show_date_selection_widgets (NautilusSearchPopover *popover,
gboolean visible)
{
gtk_stack_set_visible_child_name (GTK_STACK (popover->date_stack),
visible ? "date-entry" : "date-button");
gtk_stack_set_visible_child_name (GTK_STACK (popover->around_stack), "date-list");
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (popover->date_entry),
GTK_ENTRY_ICON_SECONDARY,
"x-office-calendar-symbolic");
gtk_widget_set_visible (popover->around_revealer, visible);
gtk_revealer_set_reveal_child (GTK_REVEALER (popover->around_revealer), visible);
}
static void
show_other_types_dialog (NautilusSearchPopover *popover)
{
GList *mime_infos, *l;
GtkWidget *dialog;
GtkWidget *scrolled, *treeview;
GtkListStore *store;
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
GtkWidget *toplevel;
GtkTreeSelection *selection;
mime_infos = g_content_types_get_registered ();
store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
for (l = mime_infos; l != NULL; l = l->next)
{
GtkTreeIter iter;
char *mime_type = l->data;
char *description;
description = g_content_type_get_description (mime_type);
if (description == NULL)
{
description = g_strdup (mime_type);
}
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
0, description,
1, mime_type,
-1);
g_free (mime_type);
g_free (description);
}
g_list_free (mime_infos);
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (popover));
dialog = gtk_dialog_new_with_buttons (_("Select type"),
GTK_WINDOW (toplevel),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_USE_HEADER_BAR,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("Select"), GTK_RESPONSE_OK,
NULL);
gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 600);
scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_widget_show (scrolled);
gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 0);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), scrolled, TRUE, TRUE, 0);
treeview = gtk_tree_view_new ();
gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (store));
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), 0, GTK_SORT_ASCENDING);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Name",
renderer,
"text",
0,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
gtk_widget_show (treeview);
gtk_container_add (GTK_CONTAINER (scrolled), treeview);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
{
GtkTreeIter iter;
char *mimetype;
char *description;
gtk_tree_selection_get_selected (selection, NULL, &iter);
gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
0, &description,
1, &mimetype,
-1);
gtk_label_set_label (GTK_LABEL (popover->type_label), description);
g_signal_emit_by_name (popover, "mime-type", -1, mimetype);
gtk_stack_set_visible_child_name (GTK_STACK (popover->type_stack), "type-button");
}
gtk_widget_destroy (dialog);
}
static void
update_date_label (NautilusSearchPopover *popover,
GPtrArray *date_range)
{
if (date_range)
{
gint days;
GDateTime *initial_date;
GDateTime *end_date;
GDateTime *now;
gchar *label;
now = g_date_time_new_now_local ();
initial_date = g_ptr_array_index (date_range, 0);
end_date = g_ptr_array_index (date_range, 0);
days = g_date_time_difference (end_date, initial_date) / G_TIME_SPAN_DAY;
label = get_text_for_date_range (date_range, TRUE);
gtk_entry_set_text (GTK_ENTRY (popover->date_entry), days < 1 ? label : "");
gtk_widget_show (popover->clear_date_button);
gtk_label_set_label (GTK_LABEL (popover->select_date_button_label), label);
g_date_time_unref (now);
g_free (label);
}
else
{
gtk_label_set_label (GTK_LABEL (popover->select_date_button_label),
_("Select Dates…"));
gtk_entry_set_text (GTK_ENTRY (popover->date_entry), "");
gtk_widget_hide (popover->clear_date_button);
}
}
void
nautilus_search_popover_set_fts_sensitive (NautilusSearchPopover *popover,
gboolean sensitive)
{
gtk_widget_set_sensitive (popover->full_text_search_button, sensitive);
gtk_widget_set_sensitive (popover->filename_search_button, sensitive);
}
static void
nautilus_search_popover_closed (GtkPopover *popover)
{
NautilusSearchPopover *self = NAUTILUS_SEARCH_POPOVER (popover);
GDateTime *now;
/* Always switch back to the initial states */
gtk_stack_set_visible_child_name (GTK_STACK (self->type_stack), "type-button");
show_date_selection_widgets (self, FALSE);
/* If we're closing an ongoing query, the popover must not
* clear the current settings.
*/
if (self->query)
{
return;
}
now = g_date_time_new_now_local ();
/* Reselect today at the calendar */
g_signal_handlers_block_by_func (self->calendar, calendar_day_selected, self);
gtk_calendar_select_month (GTK_CALENDAR (self->calendar),
g_date_time_get_month (now) - 1,
g_date_time_get_year (now));
gtk_calendar_select_day (GTK_CALENDAR (self->calendar),
g_date_time_get_day_of_month (now));
g_signal_handlers_unblock_by_func (self->calendar, calendar_day_selected, self);
}
static void
nautilus_search_popover_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
NautilusSearchPopover *self;
self = NAUTILUS_SEARCH_POPOVER (object);
switch (prop_id)
{
case PROP_QUERY:
{
g_value_set_object (value, self->query);
}
break;
case PROP_FTS_ENABLED:
{
g_value_set_boolean (value, self->fts_enabled);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
nautilus_search_popover_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
NautilusSearchPopover *self;
self = NAUTILUS_SEARCH_POPOVER (object);
switch (prop_id)
{
case PROP_QUERY:
{
nautilus_search_popover_set_query (self, g_value_get_object (value));
}
break;
case PROP_FTS_ENABLED:
{
self->fts_enabled = g_value_get_boolean (value);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
nautilus_search_popover_class_init (NautilusSearchPopoverClass *klass)
{
GtkPopoverClass *popover_class = GTK_POPOVER_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = nautilus_search_popover_get_property;
object_class->set_property = nautilus_search_popover_set_property;
popover_class->closed = nautilus_search_popover_closed;
signals[DATE_RANGE] = g_signal_new ("date-range",
NAUTILUS_TYPE_SEARCH_POPOVER,
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
g_cclosure_marshal_generic,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
signals[MIME_TYPE] = g_signal_new ("mime-type",
NAUTILUS_TYPE_SEARCH_POPOVER,
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
g_cclosure_marshal_generic,
G_TYPE_NONE,
2,
G_TYPE_INT,
G_TYPE_POINTER);
signals[TIME_TYPE] = g_signal_new ("time-type",
NAUTILUS_TYPE_SEARCH_POPOVER,
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
g_cclosure_marshal_generic,
G_TYPE_NONE,
1,
G_TYPE_INT);
/**
* NautilusSearchPopover::query:
*
* The current #NautilusQuery being edited.
*/
g_object_class_install_property (object_class,
PROP_QUERY,
g_param_spec_object ("query",
"Query of the popover",
"The current query being edited",
NAUTILUS_TYPE_QUERY,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_FTS_ENABLED,
g_param_spec_boolean ("fts-enabled",
"fts enabled",
"fts enabled",
FALSE,
G_PARAM_READWRITE));
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/nautilus/ui/nautilus-search-popover.ui");
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, around_revealer);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, around_stack);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, clear_date_button);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, calendar);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, dates_listbox);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, date_entry);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, date_stack);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, select_date_button);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, select_date_button_label);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, type_label);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, type_listbox);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, type_stack);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, last_used_button);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, last_modified_button);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, full_text_search_button);
gtk_widget_class_bind_template_child (widget_class, NautilusSearchPopover, filename_search_button);
gtk_widget_class_bind_template_callback (widget_class, calendar_day_selected);
gtk_widget_class_bind_template_callback (widget_class, clear_date_button_clicked);
gtk_widget_class_bind_template_callback (widget_class, date_entry_activate);
gtk_widget_class_bind_template_callback (widget_class, dates_listbox_row_activated);
gtk_widget_class_bind_template_callback (widget_class, select_date_button_clicked);
gtk_widget_class_bind_template_callback (widget_class, select_type_button_clicked);
gtk_widget_class_bind_template_callback (widget_class, toggle_calendar_icon_clicked);
gtk_widget_class_bind_template_callback (widget_class, types_listbox_row_activated);
gtk_widget_class_bind_template_callback (widget_class, search_time_type_changed);
gtk_widget_class_bind_template_callback (widget_class, search_fts_mode_changed);
}
static void
nautilus_search_popover_init (NautilusSearchPopover *self)
{
NautilusQuerySearchType filter_time_type;
gtk_widget_init_template (GTK_WIDGET (self));
/* Fuzzy dates listbox */
gtk_list_box_set_header_func (GTK_LIST_BOX (self->dates_listbox),
(GtkListBoxUpdateHeaderFunc) listbox_header_func,
self,
NULL);
fill_fuzzy_dates_listbox (self);
/* Types listbox */
gtk_list_box_set_header_func (GTK_LIST_BOX (self->type_listbox),
(GtkListBoxUpdateHeaderFunc) listbox_header_func,
self,
NULL);
fill_types_listbox (self);
gtk_list_box_select_row (GTK_LIST_BOX (self->type_listbox),
gtk_list_box_get_row_at_index (GTK_LIST_BOX (self->type_listbox), 0));
filter_time_type = g_settings_get_enum (nautilus_preferences, "search-filter-time-type");
if (filter_time_type == NAUTILUS_QUERY_SEARCH_TYPE_LAST_MODIFIED)
{
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->last_modified_button), TRUE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->last_used_button), FALSE);
}
else
{
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->last_modified_button), FALSE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->last_used_button), TRUE);
}
self->fts_enabled = g_settings_get_boolean (nautilus_preferences,
NAUTILUS_PREFERENCES_FTS_ENABLED);
if (self->fts_enabled)
{
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->full_text_search_button), TRUE);
}
else
{
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->filename_search_button), TRUE);
}
}
GtkWidget *
nautilus_search_popover_new (void)
{
return g_object_new (NAUTILUS_TYPE_SEARCH_POPOVER, NULL);
}
/**
* nautilus_search_popover_get_query:
* @popover: a #NautilusSearchPopover
*
* Gets the current query for @popover.
*
* Returns: (transfer none): the current #NautilusQuery from @popover.
*/
NautilusQuery *
nautilus_search_popover_get_query (NautilusSearchPopover *popover)
{
g_return_val_if_fail (NAUTILUS_IS_SEARCH_POPOVER (popover), NULL);
return popover->query;
}
/**
* nautilus_search_popover_set_query:
* @popover: a #NautilusSearchPopover
* @query (nullable): a #NautilusQuery
*
* Sets the current query for @popover.
*
* Returns:
*/
void
nautilus_search_popover_set_query (NautilusSearchPopover *popover,
NautilusQuery *query)
{
NautilusQuery *previous_query;
g_return_if_fail (NAUTILUS_IS_SEARCH_POPOVER (popover));
previous_query = popover->query;
if (popover->query != query)
{
/* Disconnect signals and bindings from the old query */
if (previous_query)
{
g_signal_handlers_disconnect_by_func (previous_query, query_date_changed, popover);
}
g_set_object (&popover->query, query);
if (query)
{
/* Date */
setup_date (popover, query);
g_signal_connect (query,
"notify::date",
G_CALLBACK (query_date_changed),
popover);
}
else
{
nautilus_search_popover_reset_mime_types (popover);
nautilus_search_popover_reset_date_range (popover);
}
}
}
void
nautilus_search_popover_reset_mime_types (NautilusSearchPopover *popover)
{
g_return_if_fail (NAUTILUS_IS_SEARCH_POPOVER (popover));
gtk_list_box_select_row (GTK_LIST_BOX (popover->type_listbox),
gtk_list_box_get_row_at_index (GTK_LIST_BOX (popover->type_listbox), 0));
gtk_label_set_label (GTK_LABEL (popover->type_label),
nautilus_mime_types_group_get_name (0));
g_signal_emit_by_name (popover, "mime-type", 0, NULL);
gtk_stack_set_visible_child_name (GTK_STACK (popover->type_stack), "type-button");
}
void
nautilus_search_popover_reset_date_range (NautilusSearchPopover *popover)
{
g_return_if_fail (NAUTILUS_IS_SEARCH_POPOVER (popover));
gtk_list_box_select_row (GTK_LIST_BOX (popover->dates_listbox),
gtk_list_box_get_row_at_index (GTK_LIST_BOX (popover->dates_listbox), 0));
update_date_label (popover, NULL);
show_date_selection_widgets (popover, FALSE);
g_signal_emit_by_name (popover, "date-range", NULL);
}
gboolean
nautilus_search_popover_get_fts_enabled (NautilusSearchPopover *popover)
{
return popover->fts_enabled;
}