2012-11-07 11:39:51 -05:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 Red Hat, Inc
|
|
|
|
*
|
|
|
|
* 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 2 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, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* Author: Cosimo Cecchi <cosimoc@gnome.org>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "cc-search-locations-dialog.h"
|
|
|
|
|
|
|
|
#include <egg-list-box/egg-list-box.h>
|
|
|
|
#include <glib/gi18n.h>
|
|
|
|
|
|
|
|
#define TRACKER_SCHEMA "org.freedesktop.Tracker.Miner.Files"
|
|
|
|
#define TRACKER_KEY_RECURSIVE_DIRECTORIES "index-recursive-directories"
|
|
|
|
#define TRACKER_KEY_SINGLE_DIRECTORIES "index-single-directories"
|
|
|
|
|
|
|
|
static GSettings *tracker_preferences = NULL;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
PLACE_XDG,
|
|
|
|
PLACE_BOOKMARKS,
|
|
|
|
PLACE_OTHER
|
|
|
|
} PlaceType;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
GFile *location;
|
|
|
|
gchar *display_name;
|
|
|
|
PlaceType place_type;
|
|
|
|
GIcon *icon;
|
|
|
|
GCancellable *cancellable;
|
|
|
|
const gchar *settings_key;
|
|
|
|
} Place;
|
|
|
|
|
|
|
|
static void
|
|
|
|
place_free (Place * p)
|
|
|
|
{
|
|
|
|
if (p->cancellable != NULL)
|
|
|
|
{
|
|
|
|
g_cancellable_cancel (p->cancellable);
|
|
|
|
g_object_unref (p->cancellable);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_clear_object (&p->icon);
|
|
|
|
g_object_unref (p->location);
|
|
|
|
g_free (p->display_name);
|
|
|
|
|
|
|
|
g_slice_free (Place, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
static GList *
|
|
|
|
get_bookmarks (void)
|
|
|
|
{
|
|
|
|
GFile *file;
|
|
|
|
gchar *contents;
|
|
|
|
gchar *path;
|
|
|
|
gchar **lines;
|
|
|
|
GList *bookmarks;
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
path = g_build_filename (g_get_user_config_dir (), "gtk-3.0",
|
|
|
|
"bookmarks", NULL);
|
|
|
|
file = g_file_new_for_path (path);
|
|
|
|
g_free (path);
|
|
|
|
|
|
|
|
contents = NULL;
|
|
|
|
g_file_load_contents (file, NULL, &contents, NULL, NULL, &error);
|
|
|
|
g_object_unref (file);
|
|
|
|
|
|
|
|
bookmarks = NULL;
|
|
|
|
lines = NULL;
|
|
|
|
|
|
|
|
if (error != NULL)
|
|
|
|
{
|
|
|
|
g_error_free (error);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gint idx;
|
|
|
|
|
|
|
|
lines = g_strsplit (contents, "\n", -1);
|
|
|
|
for (idx = 0; lines[idx]; idx++)
|
|
|
|
{
|
|
|
|
/* Ignore empty or invalid lines that cannot be parsed properly */
|
|
|
|
if (lines[idx][0] != '\0' && lines[idx][0] != ' ')
|
|
|
|
{
|
|
|
|
/* gtk 2.7/2.8 might have labels appended to bookmarks which are separated by a space */
|
|
|
|
/* we must seperate the bookmark uri and the potential label */
|
|
|
|
char *space, *label;
|
|
|
|
Place *bookmark;
|
|
|
|
|
|
|
|
label = NULL;
|
|
|
|
space = strchr (lines[idx], ' ');
|
|
|
|
if (space)
|
|
|
|
{
|
|
|
|
*space = '\0';
|
|
|
|
label = g_strdup (space + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
bookmark = g_slice_new0 (Place);
|
2013-02-28 15:52:14 +01:00
|
|
|
bookmark->location = g_file_new_for_uri (lines[idx]);
|
|
|
|
|
2012-11-07 11:39:51 -05:00
|
|
|
if (label != NULL)
|
|
|
|
bookmark->display_name = label;
|
|
|
|
else
|
2013-02-28 15:52:14 +01:00
|
|
|
bookmark->display_name = g_file_get_basename (bookmark->location);
|
2012-11-07 11:39:51 -05:00
|
|
|
|
|
|
|
bookmark->place_type = PLACE_BOOKMARKS;
|
|
|
|
|
|
|
|
bookmarks = g_list_prepend (bookmarks, bookmark);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_strfreev (lines);
|
|
|
|
g_free (contents);
|
|
|
|
|
|
|
|
return g_list_reverse (bookmarks);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const gchar *
|
|
|
|
get_user_special_dir_if_not_home (GUserDirectory idx)
|
|
|
|
{
|
|
|
|
const gchar *path;
|
|
|
|
path = g_get_user_special_dir (idx);
|
|
|
|
if (g_strcmp0 (path, g_get_home_dir ()) == 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GList *
|
|
|
|
get_xdg_dirs (void)
|
|
|
|
{
|
|
|
|
GList *xdg_dirs = NULL;
|
|
|
|
gint idx;
|
|
|
|
const gchar *path;
|
|
|
|
Place *xdg_dir;
|
|
|
|
|
|
|
|
for (idx = 0; idx < G_USER_N_DIRECTORIES; idx++)
|
|
|
|
{
|
|
|
|
path = get_user_special_dir_if_not_home (idx);
|
|
|
|
if (path == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (idx == G_USER_DIRECTORY_TEMPLATES ||
|
|
|
|
idx == G_USER_DIRECTORY_PUBLIC_SHARE ||
|
|
|
|
idx == G_USER_DIRECTORY_DESKTOP)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
xdg_dir = g_slice_new0 (Place);
|
|
|
|
xdg_dir->location = g_file_new_for_path (path);
|
2013-02-28 15:52:14 +01:00
|
|
|
xdg_dir->display_name = g_file_get_basename (xdg_dir->location);
|
2012-11-07 11:39:51 -05:00
|
|
|
xdg_dir->place_type = PLACE_XDG;
|
|
|
|
|
|
|
|
xdg_dirs = g_list_prepend (xdg_dirs, xdg_dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
return g_list_reverse (xdg_dirs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const gchar *
|
|
|
|
path_to_tracker_dir (const gchar *path)
|
|
|
|
{
|
|
|
|
const gchar *value;
|
|
|
|
|
|
|
|
if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_DESKTOP)) == 0)
|
|
|
|
value = "&DESKTOP";
|
|
|
|
else if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_DOCUMENTS)) == 0)
|
|
|
|
value = "&DOCUMENTS";
|
|
|
|
else if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_DOWNLOAD)) == 0)
|
|
|
|
value = "&DOWNLOAD";
|
|
|
|
else if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_MUSIC)) == 0)
|
|
|
|
value = "&MUSIC";
|
|
|
|
else if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_PICTURES)) == 0)
|
|
|
|
value = "&PICTURES";
|
|
|
|
else if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_PUBLIC_SHARE)) == 0)
|
|
|
|
value = "&PUBLIC_SHARE";
|
|
|
|
else if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_TEMPLATES)) == 0)
|
|
|
|
value = "&TEMPLATES";
|
|
|
|
else if (g_strcmp0 (path, get_user_special_dir_if_not_home (G_USER_DIRECTORY_VIDEOS)) == 0)
|
|
|
|
value = "&VIDEOS";
|
|
|
|
else if (g_strcmp0 (path, g_get_home_dir ()) == 0)
|
|
|
|
value = "$HOME";
|
|
|
|
else
|
|
|
|
value = path;
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const gchar *
|
|
|
|
path_from_tracker_dir (const gchar *value)
|
|
|
|
{
|
|
|
|
const gchar *path;
|
|
|
|
|
|
|
|
if (g_strcmp0 (value, "&DESKTOP") == 0)
|
|
|
|
path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_DESKTOP);
|
|
|
|
else if (g_strcmp0 (value, "&DOCUMENTS") == 0)
|
|
|
|
path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_DOCUMENTS);
|
|
|
|
else if (g_strcmp0 (value, "&DOWNLOAD") == 0)
|
|
|
|
path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_DOWNLOAD);
|
|
|
|
else if (g_strcmp0 (value, "&MUSIC") == 0)
|
|
|
|
path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_MUSIC);
|
|
|
|
else if (g_strcmp0 (value, "&PICTURES") == 0)
|
|
|
|
path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_PICTURES);
|
|
|
|
else if (g_strcmp0 (value, "&PUBLIC_SHARE") == 0)
|
|
|
|
path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_PUBLIC_SHARE);
|
|
|
|
else if (g_strcmp0 (value, "&TEMPLATES") == 0)
|
|
|
|
path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_TEMPLATES);
|
|
|
|
else if (g_strcmp0 (value, "&VIDEOS") == 0)
|
|
|
|
path = get_user_special_dir_if_not_home (G_USER_DIRECTORY_VIDEOS);
|
|
|
|
else if (g_strcmp0 (value, "$HOME") == 0)
|
|
|
|
path = g_get_home_dir ();
|
|
|
|
else
|
|
|
|
path = value;
|
|
|
|
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GList *
|
|
|
|
get_tracker_locations (void)
|
|
|
|
{
|
|
|
|
gchar **locations;
|
|
|
|
GList *list;
|
|
|
|
gint idx;
|
|
|
|
Place *location;
|
|
|
|
const gchar *path;
|
|
|
|
|
|
|
|
locations = g_settings_get_strv (tracker_preferences, TRACKER_KEY_RECURSIVE_DIRECTORIES);
|
|
|
|
list = NULL;
|
|
|
|
|
|
|
|
for (idx = 0; locations[idx] != NULL; idx++)
|
|
|
|
{
|
|
|
|
path = path_from_tracker_dir (locations[idx]);
|
|
|
|
|
|
|
|
location = g_slice_new0 (Place);
|
|
|
|
location->location = g_file_new_for_commandline_arg (path);
|
2013-02-28 15:52:14 +01:00
|
|
|
location->display_name = g_file_get_basename (location->location);
|
2012-11-07 11:39:51 -05:00
|
|
|
location->place_type = PLACE_OTHER;
|
|
|
|
|
|
|
|
list = g_list_prepend (list, location);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_strfreev (locations);
|
|
|
|
|
|
|
|
return g_list_reverse (list);
|
|
|
|
}
|
|
|
|
|
|
|
|
static GList *
|
|
|
|
get_places_list (void)
|
|
|
|
{
|
|
|
|
GList *list, *l;
|
|
|
|
GHashTable *places;
|
|
|
|
Place *place, *old_place;
|
|
|
|
GList *places_list;
|
|
|
|
|
|
|
|
places = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, NULL, (GDestroyNotify) place_free);
|
|
|
|
|
|
|
|
/* add home */
|
|
|
|
place = g_slice_new0 (Place);
|
|
|
|
place->location = g_file_new_for_path (g_get_home_dir ());
|
|
|
|
place->place_type = PLACE_XDG;
|
|
|
|
place->display_name = g_strdup (_("Home"));
|
|
|
|
g_hash_table_insert (places, place->location, place);
|
|
|
|
|
|
|
|
/* first, load the XDG dirs */
|
|
|
|
list = get_xdg_dirs ();
|
|
|
|
for (l = list; l != NULL; l = l->next)
|
|
|
|
{
|
|
|
|
place = l->data;
|
|
|
|
g_hash_table_insert (places, place->location, place);
|
|
|
|
}
|
|
|
|
g_list_free (list);
|
|
|
|
|
|
|
|
/* then, insert all the tracker locations that are not XDG dirs */
|
|
|
|
list = get_tracker_locations ();
|
|
|
|
for (l = list; l != NULL; l = l->next)
|
|
|
|
{
|
|
|
|
place = l->data;
|
|
|
|
old_place = g_hash_table_lookup (places, place->location);
|
|
|
|
if (old_place == NULL)
|
|
|
|
g_hash_table_insert (places, place->location, place);
|
|
|
|
else
|
|
|
|
place_free (place);
|
|
|
|
}
|
|
|
|
g_list_free (list);
|
|
|
|
|
|
|
|
/* finally, load bookmarks, and possibly update attributes */
|
|
|
|
list = get_bookmarks ();
|
|
|
|
for (l = list; l != NULL; l = l->next)
|
|
|
|
{
|
|
|
|
place = l->data;
|
|
|
|
old_place = g_hash_table_lookup (places, place->location);
|
|
|
|
if (old_place == NULL)
|
|
|
|
{
|
|
|
|
g_hash_table_insert (places, place->location, place);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_free (old_place->display_name);
|
|
|
|
old_place->display_name = g_strdup (place->display_name);
|
|
|
|
|
|
|
|
if (old_place->place_type == PLACE_OTHER)
|
|
|
|
old_place->place_type = PLACE_BOOKMARKS;
|
|
|
|
|
|
|
|
place_free (place);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_list_free (list);
|
|
|
|
|
|
|
|
places_list = g_hash_table_get_values (places);
|
|
|
|
g_hash_table_steal_all (places);
|
|
|
|
g_hash_table_unref (places);
|
|
|
|
|
|
|
|
return places_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
switch_tracker_get_mapping (GValue *value,
|
|
|
|
GVariant *variant,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
Place *place = user_data;
|
|
|
|
const gchar **locations;
|
|
|
|
GFile *location;
|
|
|
|
gint idx;
|
|
|
|
gboolean found;
|
|
|
|
|
|
|
|
found = FALSE;
|
|
|
|
locations = g_variant_get_strv (variant, NULL);
|
|
|
|
for (idx = 0; locations[idx] != NULL; idx++)
|
|
|
|
{
|
|
|
|
location = g_file_new_for_path (path_from_tracker_dir(locations[idx]));
|
|
|
|
if ((found = g_file_equal (location, place->location)))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_value_set_boolean (value, found);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GPtrArray *
|
|
|
|
place_get_new_settings_values (Place *place,
|
|
|
|
gboolean remove)
|
|
|
|
{
|
|
|
|
gchar **values;
|
|
|
|
gchar *path;
|
|
|
|
GPtrArray *new_values;
|
|
|
|
const gchar *tracker_dir;
|
|
|
|
gboolean found;
|
|
|
|
gint idx;
|
|
|
|
|
|
|
|
new_values = g_ptr_array_new_with_free_func (g_free);
|
|
|
|
values = g_settings_get_strv (tracker_preferences, place->settings_key);
|
|
|
|
path = g_file_get_path (place->location);
|
|
|
|
tracker_dir = path_to_tracker_dir (path);
|
|
|
|
|
|
|
|
found = FALSE;
|
|
|
|
|
|
|
|
for (idx = 0; values[idx] != NULL; idx++)
|
|
|
|
{
|
|
|
|
if (g_strcmp0 (values[idx], tracker_dir) == 0)
|
|
|
|
{
|
|
|
|
found = TRUE;
|
|
|
|
|
|
|
|
if (remove)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_ptr_array_add (new_values, g_strdup (values[idx]));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found && !remove)
|
|
|
|
g_ptr_array_add (new_values, g_strdup (tracker_dir));
|
|
|
|
|
|
|
|
g_ptr_array_add (new_values, NULL);
|
|
|
|
|
|
|
|
g_strfreev (values);
|
|
|
|
g_free (path);
|
|
|
|
|
|
|
|
return new_values;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GVariant *
|
|
|
|
switch_tracker_set_mapping (const GValue *value,
|
|
|
|
const GVariantType *expected_type,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
Place *place = user_data;
|
|
|
|
GPtrArray *new_values;
|
|
|
|
gboolean remove;
|
|
|
|
GVariant *variant;
|
|
|
|
|
|
|
|
remove = !g_value_get_boolean (value);
|
|
|
|
new_values = place_get_new_settings_values (place, remove);
|
|
|
|
variant = g_variant_new_strv ((const gchar **) new_values->pdata, -1);
|
|
|
|
|
|
|
|
g_ptr_array_unref (new_values);
|
|
|
|
|
|
|
|
return variant;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
place_query_info_ready (GObject *source,
|
|
|
|
GAsyncResult *res,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
GtkWidget *child, *w;
|
|
|
|
Place *place;
|
|
|
|
GFileInfo *info;
|
|
|
|
const gchar *desktop_path;
|
|
|
|
gchar *path;
|
|
|
|
|
|
|
|
info = g_file_query_info_finish (G_FILE (source), res, NULL);
|
|
|
|
if (!info)
|
|
|
|
return;
|
|
|
|
|
|
|
|
child = user_data;
|
|
|
|
place = g_object_get_data (G_OBJECT (child), "place");
|
|
|
|
g_clear_object (&place->cancellable);
|
|
|
|
|
|
|
|
/* FIXME: GLib is currently buggy and returns a non-existent icon name
|
|
|
|
* when asked for the desktop symbolic icon.
|
|
|
|
*/
|
|
|
|
desktop_path = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
|
|
|
|
path = g_file_get_path (G_FILE (source));
|
|
|
|
|
|
|
|
if (g_strcmp0 (path, desktop_path) == 0)
|
|
|
|
place->icon = g_themed_icon_new ("folder-symbolic");
|
|
|
|
else
|
|
|
|
place->icon = g_object_ref (g_file_info_get_symbolic_icon (info));
|
|
|
|
|
|
|
|
if (g_strcmp0 (path, g_get_home_dir ()) == 0)
|
|
|
|
place->settings_key = TRACKER_KEY_SINGLE_DIRECTORIES;
|
|
|
|
else
|
|
|
|
place->settings_key = TRACKER_KEY_RECURSIVE_DIRECTORIES;
|
|
|
|
|
|
|
|
g_free (path);
|
|
|
|
|
|
|
|
w = gtk_image_new_from_gicon (place->icon, GTK_ICON_SIZE_MENU);
|
|
|
|
gtk_container_add (GTK_CONTAINER (child), w);
|
|
|
|
|
|
|
|
w = gtk_label_new (place->display_name);
|
|
|
|
gtk_container_add (GTK_CONTAINER (child), w);
|
|
|
|
|
|
|
|
w = gtk_switch_new ();
|
|
|
|
gtk_box_pack_end (GTK_BOX (child), w, FALSE, FALSE, 0);
|
|
|
|
g_settings_bind_with_mapping (tracker_preferences, place->settings_key,
|
|
|
|
w, "active",
|
|
|
|
G_SETTINGS_BIND_DEFAULT,
|
|
|
|
switch_tracker_get_mapping,
|
|
|
|
switch_tracker_set_mapping,
|
|
|
|
place, NULL);
|
|
|
|
|
|
|
|
gtk_widget_show_all (child);
|
|
|
|
g_object_unref (info);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const gchar *
|
|
|
|
get_heading_name (PlaceType place)
|
|
|
|
{
|
|
|
|
if (place == PLACE_XDG)
|
|
|
|
return _("Places");
|
|
|
|
if (place == PLACE_BOOKMARKS)
|
|
|
|
return _("Bookmarks");
|
|
|
|
if (place == PLACE_OTHER)
|
|
|
|
return _("Other");
|
|
|
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
place_separator_func (GtkWidget **separator,
|
|
|
|
GtkWidget *child,
|
|
|
|
GtkWidget *before,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
gboolean need_separator;
|
|
|
|
Place *place, *place_before;
|
|
|
|
gchar *text;
|
|
|
|
GtkWidget *w;
|
|
|
|
|
|
|
|
need_separator = FALSE;
|
|
|
|
place = g_object_get_data (G_OBJECT (child), "place");
|
|
|
|
|
|
|
|
if (before != NULL)
|
|
|
|
{
|
|
|
|
place_before = g_object_get_data (G_OBJECT (before), "place");
|
|
|
|
if (place_before->place_type < place->place_type)
|
|
|
|
/* use a separator before the first item of a new type */
|
|
|
|
need_separator = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* always put a separator before the first item */
|
|
|
|
need_separator = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (need_separator && *separator == NULL)
|
|
|
|
{
|
|
|
|
text = g_strdup_printf ("<b>%s</b>", get_heading_name (place->place_type));
|
|
|
|
w = gtk_label_new (NULL);
|
|
|
|
g_object_set (w,
|
|
|
|
"margin-top", 6,
|
|
|
|
"margin-right", 10,
|
|
|
|
"margin-bottom", 6,
|
|
|
|
"margin-left", 10,
|
|
|
|
NULL);
|
|
|
|
gtk_label_set_markup (GTK_LABEL (w), text);
|
|
|
|
gtk_widget_set_halign (w, GTK_ALIGN_START);
|
|
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (w), "dim-label");
|
|
|
|
|
2012-12-03 11:08:59 +01:00
|
|
|
g_object_ref_sink (w);
|
2012-11-07 11:39:51 -05:00
|
|
|
*separator = w;
|
|
|
|
|
|
|
|
g_free (text);
|
|
|
|
}
|
|
|
|
else if (!need_separator && *separator != NULL)
|
|
|
|
{
|
|
|
|
gtk_widget_destroy (*separator);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
place_compare_func (gconstpointer a,
|
|
|
|
gconstpointer b,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
GtkWidget *child_a, *child_b;
|
|
|
|
Place *place_a, *place_b;
|
|
|
|
gchar *path;
|
|
|
|
gboolean is_home;
|
|
|
|
|
|
|
|
child_a = GTK_WIDGET (a);
|
|
|
|
child_b = GTK_WIDGET (b);
|
|
|
|
|
|
|
|
place_a = g_object_get_data (G_OBJECT (child_a), "place");
|
|
|
|
place_b = g_object_get_data (G_OBJECT (child_b), "place");
|
|
|
|
|
|
|
|
path = g_file_get_path (place_a->location);
|
|
|
|
is_home = (g_strcmp0 (path, g_get_home_dir ()) == 0);
|
|
|
|
g_free (path);
|
|
|
|
|
|
|
|
if (is_home)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (place_a->place_type == place_b->place_type)
|
|
|
|
return g_utf8_collate (place_a->display_name, place_b->display_name);
|
|
|
|
|
|
|
|
if (place_a->place_type == PLACE_XDG)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if ((place_a->place_type == PLACE_BOOKMARKS) && (place_b->place_type == PLACE_OTHER))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GtkWidget *
|
|
|
|
create_child_for_place (Place *place)
|
|
|
|
{
|
|
|
|
GtkWidget *child;
|
|
|
|
|
|
|
|
child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
|
|
|
g_object_set (child, "margin-left", 16, "margin-right", 16, NULL);
|
|
|
|
g_object_set_data_full (G_OBJECT (child), "place", place, (GDestroyNotify) place_free);
|
|
|
|
|
|
|
|
place->cancellable = g_cancellable_new ();
|
|
|
|
g_file_query_info_async (place->location, "standard::symbolic-icon",
|
|
|
|
G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT,
|
|
|
|
place->cancellable, place_query_info_ready, child);
|
|
|
|
|
|
|
|
return child;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
populate_list_box (GtkWidget *list_box)
|
|
|
|
{
|
|
|
|
GList *places, *l;
|
|
|
|
GtkWidget *child;
|
|
|
|
|
|
|
|
places = get_places_list ();
|
|
|
|
for (l = places; l != NULL; l = l->next)
|
|
|
|
{
|
|
|
|
/* assumes ownership of place */
|
|
|
|
child = create_child_for_place (l->data);
|
|
|
|
gtk_container_add (GTK_CONTAINER (list_box), child);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_list_free (places);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
list_box_child_selected (EggListBox *list_box,
|
|
|
|
GtkWidget *child,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
GtkWidget *remove_button = user_data;
|
|
|
|
Place *place;
|
|
|
|
gboolean sensitive = FALSE;
|
|
|
|
|
|
|
|
if (child != NULL)
|
|
|
|
{
|
|
|
|
place = g_object_get_data (G_OBJECT (child), "place");
|
|
|
|
sensitive = (place->place_type == PLACE_OTHER);
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_widget_set_sensitive (remove_button, sensitive);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
remove_button_clicked (GtkWidget *widget,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
GtkWidget *list_box = user_data;
|
|
|
|
GtkWidget *child;
|
|
|
|
Place *place;
|
|
|
|
GPtrArray *new_values;
|
|
|
|
|
|
|
|
child = egg_list_box_get_selected_child (EGG_LIST_BOX (list_box));
|
|
|
|
place = g_object_get_data (G_OBJECT (child), "place");
|
|
|
|
new_values = place_get_new_settings_values (place, TRUE);
|
|
|
|
g_settings_set_strv (tracker_preferences, place->settings_key, (const gchar **) new_values->pdata);
|
|
|
|
|
|
|
|
g_ptr_array_unref (new_values);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
add_file_chooser_response (GtkDialog *widget,
|
|
|
|
GtkResponseType response,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
Place *place;
|
|
|
|
GPtrArray *new_values;
|
|
|
|
|
|
|
|
if (response != GTK_RESPONSE_OK)
|
|
|
|
{
|
|
|
|
gtk_widget_destroy (GTK_WIDGET (widget));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
place = g_slice_new0 (Place);
|
|
|
|
place->location = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (widget));
|
|
|
|
place->settings_key = TRACKER_KEY_RECURSIVE_DIRECTORIES;
|
|
|
|
place->display_name = g_file_get_basename (place->location);
|
|
|
|
|
|
|
|
new_values = place_get_new_settings_values (place, FALSE);
|
|
|
|
g_settings_set_strv (tracker_preferences, place->settings_key, (const gchar **) new_values->pdata);
|
|
|
|
|
|
|
|
g_ptr_array_unref (new_values);
|
|
|
|
gtk_widget_destroy (GTK_WIDGET (widget));
|
|
|
|
place_free (place);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
add_button_clicked (GtkWidget *widget,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
GtkWidget *list_box = user_data;
|
|
|
|
GtkWidget *file_chooser;
|
|
|
|
|
|
|
|
file_chooser = gtk_file_chooser_dialog_new (_("Select Location"),
|
|
|
|
GTK_WINDOW (gtk_widget_get_toplevel (widget)),
|
|
|
|
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
|
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
|
|
GTK_STOCK_OK, GTK_RESPONSE_OK,
|
|
|
|
NULL);
|
|
|
|
gtk_window_set_modal (GTK_WINDOW (file_chooser), TRUE);
|
|
|
|
g_signal_connect (file_chooser, "response",
|
|
|
|
G_CALLBACK (add_file_chooser_response), list_box);
|
|
|
|
gtk_widget_show (file_chooser);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
locations_dialog_refresh (GtkWidget *list_box)
|
|
|
|
{
|
|
|
|
gtk_container_foreach (GTK_CONTAINER (list_box), (GtkCallback) gtk_widget_destroy, NULL);
|
|
|
|
populate_list_box (list_box);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
locations_dialog_destroy (GtkWidget *widget)
|
|
|
|
{
|
|
|
|
g_clear_object (&tracker_preferences);
|
|
|
|
}
|
|
|
|
|
|
|
|
GtkWidget *
|
|
|
|
cc_search_locations_dialog_new (CcSearchPanel *self)
|
|
|
|
{
|
|
|
|
GtkWidget *locations_dialog, *widget, *list_box;
|
|
|
|
GtkBuilder *dialog_builder;
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
dialog_builder = gtk_builder_new ();
|
2013-01-04 16:12:55 +01:00
|
|
|
gtk_builder_add_from_resource (dialog_builder,
|
|
|
|
"/org/gnome/control-center/search/search-locations-dialog.ui",
|
|
|
|
&error);
|
2012-11-07 11:39:51 -05:00
|
|
|
|
|
|
|
if (error != NULL)
|
|
|
|
{
|
|
|
|
g_warning ("Could not load interface file: %s", error->message);
|
|
|
|
g_error_free (error);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
tracker_preferences = g_settings_new (TRACKER_SCHEMA);
|
|
|
|
|
|
|
|
locations_dialog = GTK_WIDGET (gtk_builder_get_object (dialog_builder, "locations_dialog"));
|
|
|
|
widget = GTK_WIDGET (gtk_builder_get_object (dialog_builder, "locations_scrolledwindow"));
|
|
|
|
list_box = GTK_WIDGET (egg_list_box_new ());
|
|
|
|
egg_list_box_add_to_scrolled (EGG_LIST_BOX (list_box), GTK_SCROLLED_WINDOW (widget));
|
|
|
|
egg_list_box_set_sort_func (EGG_LIST_BOX (list_box),
|
|
|
|
place_compare_func, NULL, NULL);
|
|
|
|
egg_list_box_set_separator_funcs (EGG_LIST_BOX (list_box),
|
|
|
|
place_separator_func, NULL, NULL);
|
|
|
|
gtk_widget_show (list_box);
|
|
|
|
|
|
|
|
widget = GTK_WIDGET (gtk_builder_get_object (dialog_builder, "locations_remove"));
|
|
|
|
gtk_widget_set_sensitive (widget, FALSE);
|
|
|
|
g_signal_connect (list_box, "child-selected",
|
|
|
|
G_CALLBACK (list_box_child_selected), widget);
|
|
|
|
g_signal_connect (widget, "clicked",
|
|
|
|
G_CALLBACK (remove_button_clicked), list_box);
|
|
|
|
g_signal_connect_swapped (tracker_preferences, "changed::" TRACKER_KEY_RECURSIVE_DIRECTORIES,
|
|
|
|
G_CALLBACK (locations_dialog_refresh), list_box);
|
|
|
|
|
|
|
|
widget = GTK_WIDGET (gtk_builder_get_object (dialog_builder, "locations_add"));
|
|
|
|
g_signal_connect (widget, "clicked",
|
|
|
|
G_CALLBACK (add_button_clicked), list_box);
|
|
|
|
|
|
|
|
gtk_window_set_transient_for (GTK_WINDOW (locations_dialog),
|
|
|
|
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))));
|
|
|
|
g_signal_connect (locations_dialog, "response",
|
|
|
|
G_CALLBACK (gtk_widget_destroy), NULL);
|
|
|
|
g_signal_connect (locations_dialog, "destroy",
|
|
|
|
G_CALLBACK (locations_dialog_destroy), NULL);
|
|
|
|
|
|
|
|
populate_list_box (list_box);
|
|
|
|
|
|
|
|
g_object_unref (dialog_builder);
|
|
|
|
|
|
|
|
return locations_dialog;
|
|
|
|
}
|
2012-11-14 10:47:50 -05:00
|
|
|
|
|
|
|
gboolean
|
|
|
|
cc_search_locations_dialog_is_available (void)
|
|
|
|
{
|
|
|
|
const gchar * const *schemas;
|
|
|
|
const gchar *schema;
|
|
|
|
gint idx;
|
|
|
|
gboolean found = FALSE;
|
|
|
|
|
|
|
|
schemas = g_settings_list_schemas ();
|
|
|
|
for (idx = 0; schemas[idx] != NULL; idx++)
|
|
|
|
{
|
|
|
|
schema = schemas[idx];
|
|
|
|
if (g_strcmp0 (schema, TRACKER_SCHEMA) == 0)
|
|
|
|
{
|
|
|
|
found = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|