mirror of
https://gitlab.gnome.org/GNOME/nautilus
synced 2024-09-17 23:01:59 +00:00
Merge branch 'wip/carlosg/favorites' into 'master'
Add starred files See https://gitlab.gnome.org/GNOME/nautilus/merge_requests/21
This commit is contained in:
commit
6af42427f8
|
@ -255,11 +255,11 @@
|
|||
<summary>Default list view zoom level</summary>
|
||||
</key>
|
||||
<key type="as" name="default-visible-columns">
|
||||
<default>[ 'name', 'size', 'date_modified' ]</default>
|
||||
<default>[ 'name', 'size', 'date_modified', 'favorite' ]</default>
|
||||
<summary>Columns visible in list view</summary>
|
||||
</key>
|
||||
<key type="as" name="default-column-order">
|
||||
<default>[ 'name', 'size', 'type', 'owner', 'group', 'permissions', 'mime_type', 'where', 'date_modified', 'date_modified_with_time', 'date_accessed' ]</default>
|
||||
<default>[ 'name', 'size', 'type', 'owner', 'group', 'permissions', 'mime_type', 'where', 'date_modified', 'date_modified_with_time', 'date_accessed', 'recency', 'favorite' ]</default>
|
||||
<summary>Column order in list view</summary>
|
||||
</key>
|
||||
<key type="b" name="use-tree-view">
|
||||
|
|
|
@ -37,6 +37,12 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
gboolean
|
||||
eel_uri_is_favorites (const gchar *uri)
|
||||
{
|
||||
return g_str_has_prefix (uri, "favorites:");
|
||||
}
|
||||
|
||||
gboolean
|
||||
eel_uri_is_trash (const char *uri)
|
||||
{
|
||||
|
|
|
@ -35,6 +35,7 @@ G_BEGIN_DECLS
|
|||
#define EEL_DESKTOP_URI "x-nautilus-desktop:"
|
||||
#define EEL_SEARCH_URI "x-nautilus-search:"
|
||||
|
||||
gboolean eel_uri_is_favorites (const char *uri);
|
||||
gboolean eel_uri_is_trash (const char *uri);
|
||||
gboolean eel_uri_is_trash_folder (const char *uri);
|
||||
gboolean eel_uri_is_in_trash (const char *uri);
|
||||
|
|
|
@ -259,7 +259,11 @@ libnautilus_sources = [
|
|||
'nautilus-batch-rename-utilities.c',
|
||||
'nautilus-batch-rename-utilities.h',
|
||||
'nautilus-search-engine-tracker.c',
|
||||
'nautilus-search-engine-tracker.h'
|
||||
'nautilus-search-engine-tracker.h',
|
||||
'nautilus-tag-manager.c',
|
||||
'nautilus-tag-manager.h',
|
||||
'nautilus-favorite-directory.c',
|
||||
'nautilus-favorite-directory.h'
|
||||
]
|
||||
|
||||
nautilus_deps = [glib,
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "nautilus-window.h"
|
||||
#include "nautilus-window-slot.h"
|
||||
#include "nautilus-preferences-window.h"
|
||||
#include "nautilus-tag-manager.h"
|
||||
|
||||
#include "nautilus-directory-private.h"
|
||||
#include "nautilus-file-utilities.h"
|
||||
|
@ -80,6 +81,9 @@ typedef struct
|
|||
GHashTable *notifications;
|
||||
|
||||
NautilusFileUndoManager *undo_manager;
|
||||
|
||||
NautilusTagManager *tag_manager;
|
||||
GCancellable *tag_manager_cancellable;
|
||||
} NautilusApplicationPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (NautilusApplication, nautilus_application, GTK_TYPE_APPLICATION);
|
||||
|
@ -612,6 +616,11 @@ nautilus_application_finalize (GObject *object)
|
|||
|
||||
g_clear_object (&priv->undo_manager);
|
||||
|
||||
g_clear_object (&priv->tag_manager);
|
||||
|
||||
g_cancellable_cancel (priv->tag_manager_cancellable);
|
||||
g_clear_object (&priv->tag_manager_cancellable);
|
||||
|
||||
G_OBJECT_CLASS (nautilus_application_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
@ -1103,6 +1112,11 @@ nautilus_application_init (NautilusApplication *self)
|
|||
|
||||
priv->undo_manager = nautilus_file_undo_manager_new ();
|
||||
|
||||
priv->tag_manager_cancellable = g_cancellable_new ();
|
||||
priv->tag_manager = nautilus_tag_manager_get ();
|
||||
nautilus_tag_manager_set_cancellable (priv->tag_manager,
|
||||
priv->tag_manager_cancellable);
|
||||
|
||||
g_application_add_main_option_entries (G_APPLICATION (self), options);
|
||||
|
||||
nautilus_ensure_extension_points ();
|
||||
|
|
|
@ -643,6 +643,11 @@ nautilus_bookmark_list_can_bookmark_location (NautilusBookmarkList *list,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (nautilus_is_favorite_directory (location))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bookmark = nautilus_bookmark_new (location, NULL);
|
||||
is_builtin = nautilus_bookmark_get_is_builtin (bookmark);
|
||||
g_object_unref (bookmark);
|
||||
|
|
|
@ -42,6 +42,7 @@ static const char *default_column_order[] =
|
|||
"date_modified",
|
||||
"date_accessed",
|
||||
"recency",
|
||||
"favorite",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -149,6 +150,16 @@ get_builtin_columns (void)
|
|||
"xalign", 1.0,
|
||||
NULL));
|
||||
|
||||
columns = g_list_append (columns,
|
||||
g_object_new (NAUTILUS_TYPE_COLUMN,
|
||||
"name", "favorite",
|
||||
"attribute", "favorite",
|
||||
"label", _("Star"),
|
||||
"description", _("Shows if file is favorite."),
|
||||
"default-sort-order", GTK_SORT_DESCENDING,
|
||||
"xalign", 0.5,
|
||||
NULL));
|
||||
|
||||
return columns;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "nautilus-file-private.h"
|
||||
#include "nautilus-file-utilities.h"
|
||||
#include "nautilus-search-directory.h"
|
||||
#include "nautilus-favorite-directory.h"
|
||||
#include "nautilus-search-directory-file.h"
|
||||
#include "nautilus-vfs-file.h"
|
||||
#include "nautilus-global-preferences.h"
|
||||
|
@ -801,6 +802,19 @@ nautilus_directory_is_in_recent (NautilusDirectory *directory)
|
|||
return g_file_has_uri_scheme (directory->details->location, "recent");
|
||||
}
|
||||
|
||||
gboolean
|
||||
nautilus_directory_is_in_starred (NautilusDirectory *directory)
|
||||
{
|
||||
g_assert (NAUTILUS_IS_DIRECTORY (directory));
|
||||
|
||||
if (directory->details->location == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return g_file_has_uri_scheme (directory->details->location, "favorites");
|
||||
}
|
||||
|
||||
gboolean
|
||||
nautilus_directory_is_in_admin (NautilusDirectory *directory)
|
||||
{
|
||||
|
|
|
@ -227,6 +227,7 @@ gboolean nautilus_directory_is_local_or_fuse (NautilusDirector
|
|||
|
||||
gboolean nautilus_directory_is_in_trash (NautilusDirectory *directory);
|
||||
gboolean nautilus_directory_is_in_recent (NautilusDirectory *directory);
|
||||
gboolean nautilus_directory_is_in_starred (NautilusDirectory *directory);
|
||||
gboolean nautilus_directory_is_in_admin (NautilusDirectory *directory);
|
||||
|
||||
/* Return false if directory contains anything besides a Nautilus metafile.
|
||||
|
|
585
src/nautilus-favorite-directory.c
Normal file
585
src/nautilus-favorite-directory.c
Normal file
|
@ -0,0 +1,585 @@
|
|||
/* nautilus-favorite-directory.c
|
||||
*
|
||||
* Copyright (C) 2017 Alexandru Pandelea <alexandru.pandelea@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 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "nautilus-favorite-directory.h"
|
||||
#include "nautilus-tag-manager.h"
|
||||
#include "nautilus-file-utilities.h"
|
||||
#include "nautilus-directory-private.h"
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
struct NautilusFavoriteDirectoryDetails
|
||||
{
|
||||
NautilusTagManager *tag_manager;
|
||||
GList *files;
|
||||
|
||||
GList *monitor_list;
|
||||
GList *callback_list;
|
||||
GList *pending_callback_list;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gboolean monitor_hidden_files;
|
||||
NautilusFileAttributes monitor_attributes;
|
||||
|
||||
gconstpointer client;
|
||||
} FavoriteMonitor;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NautilusFavoriteDirectory *favorite_directory;
|
||||
|
||||
NautilusDirectoryCallback callback;
|
||||
gpointer callback_data;
|
||||
|
||||
NautilusFileAttributes wait_for_attributes;
|
||||
gboolean wait_for_file_list;
|
||||
GList *file_list;
|
||||
} FavoriteCallback;
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (NautilusFavoriteDirectory, nautilus_favorite_directory, NAUTILUS_TYPE_DIRECTORY,
|
||||
nautilus_ensure_extension_points ();
|
||||
g_io_extension_point_implement (NAUTILUS_DIRECTORY_PROVIDER_EXTENSION_POINT_NAME,
|
||||
g_define_type_id,
|
||||
NAUTILUS_FAVORITE_DIRECTORY_PROVIDER_NAME,
|
||||
0));
|
||||
|
||||
static void
|
||||
file_changed (NautilusFile *file,
|
||||
NautilusFavoriteDirectory *favorite)
|
||||
{
|
||||
GList list;
|
||||
|
||||
list.data = file;
|
||||
list.next = NULL;
|
||||
|
||||
nautilus_directory_emit_files_changed (NAUTILUS_DIRECTORY (favorite), &list);
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_favorite_directory_update_files (NautilusFavoriteDirectory *self)
|
||||
{
|
||||
GList *l;
|
||||
GList *tmp_l;
|
||||
GList *new_favorite_files;
|
||||
GList *monitor_list;
|
||||
FavoriteMonitor *monitor;
|
||||
NautilusFile *file;
|
||||
GHashTable *uri_table;
|
||||
GList *files_added;
|
||||
GList *files_removed;
|
||||
gchar *uri;
|
||||
|
||||
files_added = NULL;
|
||||
files_removed = NULL;
|
||||
|
||||
uri_table = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
(GDestroyNotify) g_free,
|
||||
NULL);
|
||||
|
||||
for (l = self->details->files; l != NULL; l = l->next)
|
||||
{
|
||||
g_hash_table_add (uri_table, nautilus_file_get_uri (NAUTILUS_FILE (l->data)));
|
||||
}
|
||||
|
||||
new_favorite_files = nautilus_tag_manager_get_favorite_files (self->details->tag_manager);
|
||||
|
||||
for (l = new_favorite_files; l != NULL; l = l->next)
|
||||
{
|
||||
if (!g_hash_table_contains (uri_table, l->data))
|
||||
{
|
||||
file = nautilus_file_get_by_uri ((gchar*) l->data);
|
||||
|
||||
for (monitor_list = self->details->monitor_list; monitor_list; monitor_list = monitor_list->next)
|
||||
{
|
||||
monitor = monitor_list->data;
|
||||
|
||||
/* Add monitors */
|
||||
nautilus_file_monitor_add (file, monitor, monitor->monitor_attributes);
|
||||
}
|
||||
|
||||
g_signal_connect (file, "changed", G_CALLBACK (file_changed), self);
|
||||
|
||||
files_added = g_list_prepend (files_added, file);
|
||||
}
|
||||
}
|
||||
|
||||
l = self->details->files;
|
||||
while (l != NULL)
|
||||
{
|
||||
uri = nautilus_file_get_uri (NAUTILUS_FILE (l->data));
|
||||
|
||||
if (!nautilus_tag_manager_file_is_favorite (self->details->tag_manager, uri))
|
||||
{
|
||||
files_removed = g_list_prepend (files_removed,
|
||||
nautilus_file_ref (NAUTILUS_FILE (l->data)));
|
||||
|
||||
g_signal_handlers_disconnect_by_func (NAUTILUS_FILE (l->data),
|
||||
file_changed,
|
||||
self);
|
||||
|
||||
/* Remove monitors */
|
||||
for (monitor_list = self->details->monitor_list; monitor_list;
|
||||
monitor_list = monitor_list->next)
|
||||
{
|
||||
monitor = monitor_list->data;
|
||||
nautilus_file_monitor_remove (NAUTILUS_FILE (l->data), monitor);
|
||||
}
|
||||
|
||||
if (l == self->details->files)
|
||||
{
|
||||
self->details->files = g_list_delete_link (self->details->files, l);
|
||||
l = self->details->files;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_l = l->prev;
|
||||
self->details->files = g_list_delete_link (self->details->files, l);
|
||||
l = tmp_l->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
if (files_added)
|
||||
{
|
||||
nautilus_directory_emit_files_added (NAUTILUS_DIRECTORY (self), files_added);
|
||||
|
||||
for (l = files_added; l != NULL; l = l->next)
|
||||
{
|
||||
self->details->files = g_list_prepend (self->details->files, nautilus_file_ref (NAUTILUS_FILE (l->data)));
|
||||
}
|
||||
}
|
||||
|
||||
if (files_removed)
|
||||
{
|
||||
nautilus_directory_emit_files_changed (NAUTILUS_DIRECTORY (self), files_removed);
|
||||
}
|
||||
|
||||
nautilus_file_list_free (files_added);
|
||||
nautilus_file_list_free (files_removed);
|
||||
g_hash_table_destroy (uri_table);
|
||||
}
|
||||
|
||||
static void
|
||||
on_favorites_files_changed (NautilusTagManager *tag_manager,
|
||||
GList *changed_files,
|
||||
gpointer user_data)
|
||||
{
|
||||
NautilusFavoriteDirectory *self;
|
||||
|
||||
self = NAUTILUS_FAVORITE_DIRECTORY (user_data);
|
||||
|
||||
nautilus_favorite_directory_update_files (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
real_contains_file (NautilusDirectory *directory,
|
||||
NautilusFile *file)
|
||||
{
|
||||
NautilusFavoriteDirectory *self;
|
||||
g_autofree gchar *uri = NULL;
|
||||
|
||||
self = NAUTILUS_FAVORITE_DIRECTORY (directory);
|
||||
|
||||
uri = nautilus_file_get_uri (file);
|
||||
|
||||
return nautilus_tag_manager_file_is_favorite (self->details->tag_manager, uri);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
real_is_editable (NautilusDirectory *directory)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
real_force_reload (NautilusDirectory *directory)
|
||||
{
|
||||
nautilus_favorite_directory_update_files (NAUTILUS_FAVORITE_DIRECTORY (directory));
|
||||
}
|
||||
|
||||
static void
|
||||
real_call_when_ready (NautilusDirectory *directory,
|
||||
NautilusFileAttributes file_attributes,
|
||||
gboolean wait_for_file_list,
|
||||
NautilusDirectoryCallback callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
GList *file_list;
|
||||
NautilusFavoriteDirectory *favorite;
|
||||
|
||||
favorite = NAUTILUS_FAVORITE_DIRECTORY (directory);
|
||||
|
||||
file_list = nautilus_file_list_copy (favorite->details->files);
|
||||
|
||||
callback (NAUTILUS_DIRECTORY (directory),
|
||||
file_list,
|
||||
callback_data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
real_are_all_files_seen (NautilusDirectory *directory)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
real_file_monitor_add (NautilusDirectory *directory,
|
||||
gconstpointer client,
|
||||
gboolean monitor_hidden_files,
|
||||
NautilusFileAttributes file_attributes,
|
||||
NautilusDirectoryCallback callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
GList *list;
|
||||
FavoriteMonitor *monitor;
|
||||
NautilusFavoriteDirectory *favorite;
|
||||
NautilusFile *file;
|
||||
|
||||
favorite = NAUTILUS_FAVORITE_DIRECTORY (directory);
|
||||
|
||||
monitor = g_new0 (FavoriteMonitor, 1);
|
||||
monitor->monitor_hidden_files = monitor_hidden_files;
|
||||
monitor->monitor_attributes = file_attributes;
|
||||
monitor->client = client;
|
||||
|
||||
favorite->details->monitor_list = g_list_prepend (favorite->details->monitor_list, monitor);
|
||||
|
||||
if (callback != NULL)
|
||||
{
|
||||
(*callback) (directory, favorite->details->files, callback_data);
|
||||
}
|
||||
|
||||
for (list = favorite->details->files; list != NULL; list = list->next)
|
||||
{
|
||||
file = list->data;
|
||||
|
||||
/* Add monitors */
|
||||
nautilus_file_monitor_add (file, monitor, file_attributes);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
favorite_monitor_destroy (FavoriteMonitor *monitor,
|
||||
NautilusFavoriteDirectory *favorite)
|
||||
{
|
||||
GList *l;
|
||||
NautilusFile *file;
|
||||
|
||||
for (l = favorite->details->files; l != NULL; l = l->next)
|
||||
{
|
||||
file = l->data;
|
||||
|
||||
nautilus_file_monitor_remove (file, monitor);
|
||||
}
|
||||
|
||||
g_free (monitor);
|
||||
}
|
||||
|
||||
static void
|
||||
real_monitor_remove (NautilusDirectory *directory,
|
||||
gconstpointer client)
|
||||
{
|
||||
NautilusFavoriteDirectory *favorite;
|
||||
FavoriteMonitor *monitor;
|
||||
GList *list;
|
||||
|
||||
favorite = NAUTILUS_FAVORITE_DIRECTORY (directory);
|
||||
|
||||
for (list = favorite->details->monitor_list; list != NULL; list = list->next)
|
||||
{
|
||||
monitor = list->data;
|
||||
|
||||
if (monitor->client != client)
|
||||
continue;
|
||||
|
||||
favorite->details->monitor_list = g_list_delete_link (favorite->details->monitor_list, list);
|
||||
|
||||
favorite_monitor_destroy (monitor, favorite);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
real_handles_location (GFile *location)
|
||||
{
|
||||
g_autofree gchar *uri = NULL;
|
||||
|
||||
uri = g_file_get_uri (location);
|
||||
|
||||
if (eel_uri_is_favorites (uri))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static FavoriteCallback*
|
||||
favorite_callback_find_pending (NautilusFavoriteDirectory *favorite,
|
||||
NautilusDirectoryCallback callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
FavoriteCallback *favorite_callback;
|
||||
GList *list;
|
||||
|
||||
for (list = favorite->details->pending_callback_list; list != NULL; list = list->next)
|
||||
{
|
||||
favorite_callback = list->data;
|
||||
|
||||
if (favorite_callback->callback == callback &&
|
||||
favorite_callback->callback_data == callback_data)
|
||||
{
|
||||
return favorite_callback;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static FavoriteCallback*
|
||||
favorite_callback_find (NautilusFavoriteDirectory *favorite,
|
||||
NautilusDirectoryCallback callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
FavoriteCallback *favorite_callback;
|
||||
GList *list;
|
||||
|
||||
for (list = favorite->details->callback_list; list != NULL; list = list->next)
|
||||
{
|
||||
favorite_callback = list->data;
|
||||
|
||||
if (favorite_callback->callback == callback &&
|
||||
favorite_callback->callback_data == callback_data)
|
||||
{
|
||||
return favorite_callback;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
favorite_callback_destroy (FavoriteCallback *favorite_callback)
|
||||
{
|
||||
nautilus_file_list_free (favorite_callback->file_list);
|
||||
|
||||
g_free (favorite_callback);
|
||||
}
|
||||
|
||||
static void
|
||||
real_cancel_callback (NautilusDirectory *directory,
|
||||
NautilusDirectoryCallback callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
NautilusFavoriteDirectory *favorite;
|
||||
FavoriteCallback *favorite_callback;
|
||||
|
||||
favorite = NAUTILUS_FAVORITE_DIRECTORY (directory);
|
||||
favorite_callback = favorite_callback_find (favorite, callback, callback_data);
|
||||
|
||||
if (favorite_callback)
|
||||
{
|
||||
favorite->details->callback_list = g_list_remove (favorite->details->callback_list, favorite_callback);
|
||||
|
||||
favorite_callback_destroy (favorite_callback);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for a pending callback */
|
||||
favorite_callback = favorite_callback_find_pending (favorite, callback, callback_data);
|
||||
|
||||
if (favorite_callback)
|
||||
{
|
||||
favorite->details->pending_callback_list = g_list_remove (favorite->details->pending_callback_list, favorite_callback);
|
||||
|
||||
favorite_callback_destroy (favorite_callback);
|
||||
}
|
||||
}
|
||||
|
||||
static GList*
|
||||
real_get_file_list (NautilusDirectory *directory)
|
||||
{
|
||||
NautilusFavoriteDirectory *favorite;
|
||||
|
||||
favorite = NAUTILUS_FAVORITE_DIRECTORY (directory);
|
||||
|
||||
return nautilus_file_list_copy (favorite->details->files);
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_favorite_directory_set_files (NautilusFavoriteDirectory *self)
|
||||
{
|
||||
GList *favorite_files;
|
||||
NautilusFile *file;
|
||||
GList *l;
|
||||
GList *file_list;
|
||||
FavoriteMonitor *monitor;
|
||||
GList *monitor_list;
|
||||
|
||||
file_list = NULL;
|
||||
|
||||
favorite_files = nautilus_tag_manager_get_favorite_files (self->details->tag_manager);
|
||||
|
||||
for (l = favorite_files; l != NULL; l = l->next)
|
||||
{
|
||||
file = nautilus_file_get_by_uri ((gchar*) l->data);
|
||||
|
||||
g_signal_connect (file, "changed", G_CALLBACK (file_changed), self);
|
||||
|
||||
for (monitor_list = self->details->monitor_list; monitor_list; monitor_list = monitor_list->next)
|
||||
{
|
||||
monitor = monitor_list->data;
|
||||
|
||||
/* Add monitors */
|
||||
nautilus_file_monitor_add (file, monitor, monitor->monitor_attributes);
|
||||
}
|
||||
|
||||
file_list = g_list_prepend (file_list, file);
|
||||
}
|
||||
|
||||
nautilus_directory_emit_files_added (NAUTILUS_DIRECTORY (self), file_list);
|
||||
|
||||
self->details->files = file_list;
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_favorite_directory_finalize (GObject *object)
|
||||
{
|
||||
NautilusFavoriteDirectory *self;
|
||||
|
||||
self = NAUTILUS_FAVORITE_DIRECTORY (object);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (self->details->tag_manager,
|
||||
on_favorites_files_changed,
|
||||
self);
|
||||
|
||||
g_object_unref (self->details->tag_manager);
|
||||
nautilus_file_list_free (self->details->files);
|
||||
|
||||
G_OBJECT_CLASS (nautilus_favorite_directory_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_favorite_directory_dispose (GObject *object)
|
||||
{
|
||||
NautilusFavoriteDirectory *favorite;
|
||||
GList *l;
|
||||
GList *monitor_list;
|
||||
FavoriteMonitor *monitor;
|
||||
NautilusFile *file;
|
||||
|
||||
favorite = NAUTILUS_FAVORITE_DIRECTORY (object);
|
||||
|
||||
/* Remove file connections */
|
||||
for (l = favorite->details->files; l != NULL; l = l->next)
|
||||
{
|
||||
file = l->data;
|
||||
|
||||
/* Disconnect change handler */
|
||||
g_signal_handlers_disconnect_by_func (file, file_changed, favorite);
|
||||
|
||||
/* Remove monitors */
|
||||
for (monitor_list = favorite->details->monitor_list; monitor_list;
|
||||
monitor_list = monitor_list->next)
|
||||
{
|
||||
monitor = monitor_list->data;
|
||||
nautilus_file_monitor_remove (file, monitor);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove search monitors */
|
||||
if (favorite->details->monitor_list)
|
||||
{
|
||||
for (l = favorite->details->monitor_list; l != NULL; l = l->next)
|
||||
{
|
||||
favorite_monitor_destroy ((FavoriteMonitor*) l->data, favorite);
|
||||
}
|
||||
|
||||
g_list_free (favorite->details->monitor_list);
|
||||
favorite->details->monitor_list = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (nautilus_favorite_directory_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_favorite_directory_class_init (NautilusFavoriteDirectoryClass *klass)
|
||||
{
|
||||
GObjectClass *oclass;
|
||||
NautilusDirectoryClass *directory_class;
|
||||
|
||||
oclass = G_OBJECT_CLASS (klass);
|
||||
directory_class = NAUTILUS_DIRECTORY_CLASS (klass);
|
||||
|
||||
oclass->finalize = nautilus_favorite_directory_finalize;
|
||||
oclass->dispose = nautilus_favorite_directory_dispose;
|
||||
|
||||
directory_class->handles_location = real_handles_location;
|
||||
directory_class->contains_file = real_contains_file;
|
||||
directory_class->is_editable = real_is_editable;
|
||||
directory_class->force_reload = real_force_reload;
|
||||
directory_class->call_when_ready = real_call_when_ready;
|
||||
directory_class->are_all_files_seen = real_are_all_files_seen;
|
||||
directory_class->file_monitor_add = real_file_monitor_add;
|
||||
directory_class->file_monitor_remove = real_monitor_remove;
|
||||
directory_class->cancel_callback = real_cancel_callback;
|
||||
directory_class->get_file_list = real_get_file_list;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (NautilusFavoriteDirectoryDetails));
|
||||
}
|
||||
|
||||
NautilusFavoriteDirectory*
|
||||
nautilus_favorite_directory_new ()
|
||||
{
|
||||
NautilusFavoriteDirectory *self;
|
||||
|
||||
self = g_object_new (NAUTILUS_TYPE_FAVORITE_DIRECTORY, NULL);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_favorite_directory_init (NautilusFavoriteDirectory *self)
|
||||
{
|
||||
NautilusTagManager *tag_manager;
|
||||
|
||||
self->details = G_TYPE_INSTANCE_GET_PRIVATE (self, NAUTILUS_TYPE_FAVORITE_DIRECTORY,
|
||||
NautilusFavoriteDirectoryDetails);
|
||||
|
||||
tag_manager = nautilus_tag_manager_get ();
|
||||
|
||||
g_signal_connect (tag_manager,
|
||||
"favorites-changed",
|
||||
(GCallback) on_favorites_files_changed,
|
||||
self);
|
||||
|
||||
self->details->tag_manager = tag_manager;
|
||||
|
||||
nautilus_favorite_directory_set_files (self);
|
||||
|
||||
}
|
57
src/nautilus-favorite-directory.h
Normal file
57
src/nautilus-favorite-directory.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/* nautilus-favorite-directory.h
|
||||
*
|
||||
* Copyright (C) 2017 Alexandru Pandelea <alexandru.pandelea@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 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NAUTILUS_FAVORITE_DIRECTORY_H
|
||||
#define NAUTILUS_FAVORITE_DIRECTORY_H
|
||||
|
||||
#include "nautilus-directory.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define NAUTILUS_FAVORITE_DIRECTORY_PROVIDER_NAME "favorite-directory-provider"
|
||||
|
||||
#define NAUTILUS_TYPE_FAVORITE_DIRECTORY nautilus_favorite_directory_get_type()
|
||||
#define NAUTILUS_FAVORITE_DIRECTORY(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_FAVORITE_DIRECTORY, NautilusFavoriteDirectory))
|
||||
#define NAUTILUS_FAVORITE_DIRECTORY_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_FAVORITE_DIRECTORY, NautilusFavoriteDirectoryClass))
|
||||
#define NAUTILUS_IS_FAVORITE_DIRECTORY(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_FAVORITE_DIRECTORY))
|
||||
#define NAUTILUS_IS_FAVORITE_DIRECTORY_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_FAVORITE_DIRECTORY))
|
||||
#define NAUTILUS_FAVORITE_DIRECTORY_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_FAVORITE_DIRECTORY, NautilusFavoriteDirectoryClass))
|
||||
|
||||
typedef struct NautilusFavoriteDirectoryDetails NautilusFavoriteDirectoryDetails;
|
||||
|
||||
typedef struct {
|
||||
NautilusDirectory parent_slot;
|
||||
NautilusFavoriteDirectoryDetails *details;
|
||||
} NautilusFavoriteDirectory;
|
||||
|
||||
typedef struct {
|
||||
NautilusDirectoryClass parent_slot;
|
||||
} NautilusFavoriteDirectoryClass;
|
||||
|
||||
GType nautilus_favorite_directory_get_type (void);
|
||||
|
||||
NautilusFavoriteDirectory* nautilus_favorite_directory_new ();
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
|
@ -33,6 +33,7 @@
|
|||
#include "nautilus-file-undo-manager.h"
|
||||
#include "nautilus-batch-rename-dialog.h"
|
||||
#include "nautilus-batch-rename-utilities.h"
|
||||
#include "nautilus-tag-manager.h"
|
||||
|
||||
|
||||
/* Since we use g_get_current_time for setting "orig_trash_time" in the undo
|
||||
|
@ -1304,6 +1305,226 @@ nautilus_file_undo_info_batch_rename_set_data_post (NautilusFileUndoInfoBatchRen
|
|||
self->priv->new_display_names = g_list_reverse (self->priv->new_display_names);
|
||||
}
|
||||
|
||||
/* favorite files */
|
||||
G_DEFINE_TYPE (NautilusFileUndoInfoFavorites, nautilus_file_undo_info_favorites, NAUTILUS_TYPE_FILE_UNDO_INFO);
|
||||
|
||||
struct _NautilusFileUndoInfoFavoritesDetails
|
||||
{
|
||||
GList *files;
|
||||
/* Whether the action was starring or unstarring */
|
||||
gboolean starred;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_FILES = 1,
|
||||
PROP_STARRED,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static void
|
||||
favorites_strings_func (NautilusFileUndoInfo *info,
|
||||
gchar **undo_label,
|
||||
gchar **undo_description,
|
||||
gchar **redo_label,
|
||||
gchar **redo_description)
|
||||
{
|
||||
NautilusFileUndoInfoFavorites *self = NAUTILUS_FILE_UNDO_INFO_FAVORITES (info);
|
||||
|
||||
if (self->priv->starred)
|
||||
{
|
||||
*undo_description = g_strdup_printf (ngettext ("Unstar %d file",
|
||||
"Unstar %d files",
|
||||
g_list_length (self->priv->files)),
|
||||
g_list_length (self->priv->files));
|
||||
*redo_description = g_strdup_printf (ngettext ("Star %d file",
|
||||
"Star %d files",
|
||||
g_list_length (self->priv->files)),
|
||||
g_list_length (self->priv->files));
|
||||
*undo_label = g_strdup (_("_Undo Starring"));
|
||||
*redo_label = g_strdup (_("_Redo Starring"));
|
||||
}
|
||||
else
|
||||
{
|
||||
*undo_description = g_strdup_printf (ngettext ("Star %d file",
|
||||
"Star %d files",
|
||||
g_list_length (self->priv->files)),
|
||||
g_list_length (self->priv->files));
|
||||
*redo_description = g_strdup_printf (ngettext ("Unstar %d file",
|
||||
"Unstar %d files",
|
||||
g_list_length (self->priv->files)),
|
||||
g_list_length (self->priv->files));
|
||||
*undo_label = g_strdup (_("_Undo Unstarring"));
|
||||
*redo_label = g_strdup (_("_Redo Unstarring"));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_undo_favorite_tags_updated (GObject *object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
NautilusFileUndoInfo *undo_info;
|
||||
|
||||
undo_info = NAUTILUS_FILE_UNDO_INFO (object);
|
||||
|
||||
task = user_data;
|
||||
g_clear_object (&task);
|
||||
|
||||
file_undo_info_operation_callback (NULL, NULL, NULL, undo_info);
|
||||
}
|
||||
|
||||
static void
|
||||
favorites_redo_func (NautilusFileUndoInfo *info,
|
||||
GtkWindow *parent_window)
|
||||
{
|
||||
NautilusFileUndoInfoFavorites *self = NAUTILUS_FILE_UNDO_INFO_FAVORITES (info);
|
||||
NautilusTagManager *tag_manager;
|
||||
|
||||
tag_manager = nautilus_tag_manager_get ();
|
||||
|
||||
if (self->priv->starred)
|
||||
{
|
||||
nautilus_tag_manager_star_files (tag_manager,
|
||||
G_OBJECT (info),
|
||||
self->priv->files,
|
||||
on_undo_favorite_tags_updated,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
nautilus_tag_manager_unstar_files (tag_manager,
|
||||
G_OBJECT (info),
|
||||
self->priv->files,
|
||||
on_undo_favorite_tags_updated,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
favorites_undo_func (NautilusFileUndoInfo *info,
|
||||
GtkWindow *parent_window)
|
||||
{
|
||||
NautilusFileUndoInfoFavorites *self = NAUTILUS_FILE_UNDO_INFO_FAVORITES (info);
|
||||
NautilusTagManager *tag_manager;
|
||||
|
||||
tag_manager = nautilus_tag_manager_get ();
|
||||
|
||||
if (self->priv->starred)
|
||||
{
|
||||
nautilus_tag_manager_unstar_files (tag_manager,
|
||||
G_OBJECT (info),
|
||||
self->priv->files,
|
||||
on_undo_favorite_tags_updated,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
nautilus_tag_manager_star_files (tag_manager,
|
||||
G_OBJECT (info),
|
||||
self->priv->files,
|
||||
on_undo_favorite_tags_updated,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_file_undo_info_favorites_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
NautilusFileUndoInfoFavorites *self = NAUTILUS_FILE_UNDO_INFO_FAVORITES (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_FILES:
|
||||
{
|
||||
self->priv->files = nautilus_file_list_copy (g_value_get_pointer (value));
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_STARRED:
|
||||
{
|
||||
self->priv->starred = g_value_get_boolean (value);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_file_undo_info_favorites_init (NautilusFileUndoInfoFavorites *self)
|
||||
{
|
||||
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, nautilus_file_undo_info_favorites_get_type (),
|
||||
NautilusFileUndoInfoFavoritesDetails);
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_file_undo_info_favorites_finalize (GObject *obj)
|
||||
{
|
||||
NautilusFileUndoInfoFavorites *self = NAUTILUS_FILE_UNDO_INFO_FAVORITES (obj);
|
||||
|
||||
nautilus_file_list_free (self->priv->files);
|
||||
|
||||
G_OBJECT_CLASS (nautilus_file_undo_info_favorites_parent_class)->finalize (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_file_undo_info_favorites_class_init (NautilusFileUndoInfoFavoritesClass *klass)
|
||||
{
|
||||
GObjectClass *oclass = G_OBJECT_CLASS (klass);
|
||||
NautilusFileUndoInfoClass *iclass = NAUTILUS_FILE_UNDO_INFO_CLASS (klass);
|
||||
|
||||
oclass->finalize = nautilus_file_undo_info_favorites_finalize;
|
||||
oclass->set_property = nautilus_file_undo_info_favorites_set_property;
|
||||
|
||||
iclass->undo_func = favorites_undo_func;
|
||||
iclass->redo_func = favorites_redo_func;
|
||||
iclass->strings_func = favorites_strings_func;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (NautilusFileUndoInfoFavoritesDetails));
|
||||
|
||||
g_object_class_install_property (oclass,
|
||||
PROP_FILES,
|
||||
g_param_spec_pointer ("files",
|
||||
"files",
|
||||
"The files for which to undo star/unstar",
|
||||
G_PARAM_WRITABLE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property (oclass,
|
||||
PROP_STARRED,
|
||||
g_param_spec_boolean ("starred",
|
||||
"starred",
|
||||
"Whether the files were starred or unstarred",
|
||||
FALSE,
|
||||
G_PARAM_WRITABLE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
}
|
||||
|
||||
NautilusFileUndoInfo *
|
||||
nautilus_file_undo_info_favorites_new (GList *files,
|
||||
gboolean starred)
|
||||
{
|
||||
NautilusFileUndoInfoFavorites *self;
|
||||
|
||||
self = g_object_new (NAUTILUS_TYPE_FILE_UNDO_INFO_FAVORITES,
|
||||
"op-type", NAUTILUS_FILE_UNDO_OP_FAVORITES,
|
||||
"item-count", g_list_length (files),
|
||||
"files", files,
|
||||
"starred", starred,
|
||||
NULL);
|
||||
|
||||
return NAUTILUS_FILE_UNDO_INFO (self);
|
||||
}
|
||||
|
||||
/* trash */
|
||||
G_DEFINE_TYPE (NautilusFileUndoInfoTrash, nautilus_file_undo_info_trash, NAUTILUS_TYPE_FILE_UNDO_INFO)
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ typedef enum {
|
|||
NAUTILUS_FILE_UNDO_OP_MOVE,
|
||||
NAUTILUS_FILE_UNDO_OP_RENAME,
|
||||
NAUTILUS_FILE_UNDO_OP_BATCH_RENAME,
|
||||
NAUTILUS_FILE_UNDO_OP_FAVORITES,
|
||||
NAUTILUS_FILE_UNDO_OP_CREATE_EMPTY_FILE,
|
||||
NAUTILUS_FILE_UNDO_OP_CREATE_FILE_FROM_TEMPLATE,
|
||||
NAUTILUS_FILE_UNDO_OP_CREATE_FOLDER,
|
||||
|
@ -217,6 +218,31 @@ void nautilus_file_undo_info_batch_rename_set_data_pre (NautilusFileUndoInfoBatc
|
|||
void nautilus_file_undo_info_batch_rename_set_data_post (NautilusFileUndoInfoBatchRename *self,
|
||||
GList *new_files);
|
||||
|
||||
/* favorite files */
|
||||
#define NAUTILUS_TYPE_FILE_UNDO_INFO_FAVORITES (nautilus_file_undo_info_favorites_get_type ())
|
||||
#define NAUTILUS_FILE_UNDO_INFO_FAVORITES(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NAUTILUS_TYPE_FILE_UNDO_INFO_FAVORITES, NautilusFileUndoInfoFavorites))
|
||||
#define NAUTILUS_FILE_UNDO_INFO_FAVORITES_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NAUTILUS_TYPE_FILE_UNDO_INFO_FAVORITES, NautilusFileUndoInfoFavoritesClass))
|
||||
#define NAUTILUS_IS_FILE_UNDO_INFO_FAVORITES(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NAUTILUS_TYPE_FILE_UNDO_INFO_FAVORITES))
|
||||
#define NAUTILUS_IS_FILE_UNDO_INFO_FAVORITES_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NAUTILUS_TYPE_FILE_UNDO_INFO_FAVORITES))
|
||||
#define NAUTILUS_FILE_UNDO_INFO_FAVORITES_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NAUTILUS_TYPE_FILE_UNDO_INFO_FAVORITES, NautilusFileUndoInfoFavoritesClass))
|
||||
|
||||
typedef struct _NautilusFileUndoInfoFavorites NautilusFileUndoInfoFavorites;
|
||||
typedef struct _NautilusFileUndoInfoFavoritesClass NautilusFileUndoInfoFavoritesClass;
|
||||
typedef struct _NautilusFileUndoInfoFavoritesDetails NautilusFileUndoInfoFavoritesDetails;
|
||||
|
||||
struct _NautilusFileUndoInfoFavorites {
|
||||
NautilusFileUndoInfo parent;
|
||||
NautilusFileUndoInfoFavoritesDetails *priv;
|
||||
};
|
||||
|
||||
struct _NautilusFileUndoInfoFavoritesClass {
|
||||
NautilusFileUndoInfoClass parent_class;
|
||||
};
|
||||
|
||||
GType nautilus_file_undo_info_favorites_get_type (void) G_GNUC_CONST;
|
||||
NautilusFileUndoInfo *nautilus_file_undo_info_favorites_new (GList *files,
|
||||
gboolean starred);
|
||||
|
||||
/* trash */
|
||||
#define NAUTILUS_TYPE_FILE_UNDO_INFO_TRASH (nautilus_file_undo_info_trash_get_type ())
|
||||
#define NAUTILUS_FILE_UNDO_INFO_TRASH(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NAUTILUS_TYPE_FILE_UNDO_INFO_TRASH, NautilusFileUndoInfoTrash))
|
||||
|
|
|
@ -322,7 +322,10 @@ nautilus_compute_title_for_location (GFile *location)
|
|||
{
|
||||
title = g_strdup (_("Other Locations"));
|
||||
}
|
||||
else
|
||||
else if (nautilus_file_is_favorite_location (file))
|
||||
{
|
||||
title = g_strdup (_("Starred"));
|
||||
}
|
||||
{
|
||||
title = nautilus_file_get_description (file);
|
||||
|
||||
|
@ -592,6 +595,19 @@ nautilus_is_search_directory (GFile *dir)
|
|||
return eel_uri_is_search (uri);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nautilus_is_favorite_directory (GFile *dir)
|
||||
{
|
||||
g_autofree gchar *uri = NULL;
|
||||
|
||||
uri = g_file_get_uri (dir);
|
||||
|
||||
if (eel_uri_is_favorites (uri))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nautilus_is_other_locations_directory (GFile *dir)
|
||||
{
|
||||
|
|
|
@ -45,6 +45,7 @@ gboolean nautilus_is_home_directory_file (GFile *dir,
|
|||
const char *filename);
|
||||
gboolean nautilus_is_in_system_dir (GFile *location);
|
||||
gboolean nautilus_is_search_directory (GFile *dir);
|
||||
gboolean nautilus_is_favorite_directory (GFile *dir);
|
||||
gboolean nautilus_is_other_locations_directory (GFile *dir);
|
||||
GMount * nautilus_get_mounted_mount_for_root (GFile *location);
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "nautilus-vfs-file.h"
|
||||
#include "nautilus-file-undo-operations.h"
|
||||
#include "nautilus-file-undo-manager.h"
|
||||
#include "nautilus-tag-manager.h"
|
||||
#include <eel/eel-debug.h>
|
||||
#include <eel/eel-glib-extensions.h>
|
||||
#include <eel/eel-gtk-extensions.h>
|
||||
|
@ -159,7 +160,8 @@ static GQuark attribute_name_q,
|
|||
attribute_where_q,
|
||||
attribute_link_target_q,
|
||||
attribute_volume_q,
|
||||
attribute_free_space_q;
|
||||
attribute_free_space_q,
|
||||
attribute_favorite_q;
|
||||
|
||||
static void nautilus_file_info_iface_init (NautilusFileInfoIface *iface);
|
||||
static char *nautilus_file_get_owner_as_string (NautilusFile *file,
|
||||
|
@ -3660,6 +3662,39 @@ compare_by_type (NautilusFile *file_1,
|
|||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
compare_by_favorite (NautilusFile *file_1,
|
||||
NautilusFile *file_2)
|
||||
{
|
||||
NautilusTagManager *tag_manager;
|
||||
g_autofree gchar *uri_1 = NULL;
|
||||
g_autofree gchar *uri_2 = NULL;
|
||||
gboolean file_1_is_favorite;
|
||||
gboolean file_2_is_favorite;
|
||||
|
||||
tag_manager = nautilus_tag_manager_get ();
|
||||
|
||||
uri_1 = nautilus_file_get_uri (file_1);
|
||||
uri_2 = nautilus_file_get_uri (file_2);
|
||||
|
||||
file_1_is_favorite = nautilus_tag_manager_file_is_favorite (tag_manager,
|
||||
uri_1);
|
||||
file_2_is_favorite = nautilus_tag_manager_file_is_favorite (tag_manager,
|
||||
uri_2);
|
||||
if (!!file_1_is_favorite == !!file_2_is_favorite)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (file_1_is_favorite && !file_2_is_favorite)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static Knowledge
|
||||
get_search_relevance (NautilusFile *file,
|
||||
gdouble *relevance_out)
|
||||
|
@ -3863,6 +3898,16 @@ nautilus_file_compare_for_sort (NautilusFile *file_1,
|
|||
}
|
||||
break;
|
||||
|
||||
case NAUTILUS_FILE_SORT_BY_FAVORITE:
|
||||
{
|
||||
result = compare_by_favorite (file_1, file_2);
|
||||
if (result == 0)
|
||||
{
|
||||
result = compare_by_full_path (file_1, file_2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NAUTILUS_FILE_SORT_BY_MTIME:
|
||||
{
|
||||
result = compare_by_time (file_1, file_2, NAUTILUS_DATE_TYPE_MODIFIED);
|
||||
|
@ -3967,6 +4012,13 @@ nautilus_file_compare_for_sort_by_attribute_q (NautilusFile *file_1,
|
|||
directories_first,
|
||||
reversed);
|
||||
}
|
||||
else if (attribute == attribute_favorite_q)
|
||||
{
|
||||
return nautilus_file_compare_for_sort (file_1, file_2,
|
||||
NAUTILUS_FILE_SORT_BY_FAVORITE,
|
||||
directories_first,
|
||||
reversed);
|
||||
}
|
||||
else if (attribute == attribute_modification_date_q || attribute == attribute_date_modified_q || attribute == attribute_date_modified_with_time_q || attribute == attribute_date_modified_full_q)
|
||||
{
|
||||
return nautilus_file_compare_for_sort (file_1, file_2,
|
||||
|
@ -4576,6 +4628,11 @@ nautilus_file_peek_display_name (NautilusFile *file)
|
|||
char *
|
||||
nautilus_file_get_display_name (NautilusFile *file)
|
||||
{
|
||||
if (nautilus_file_is_other_locations (file))
|
||||
return g_strdup (_("Other Locations"));
|
||||
if (nautilus_file_is_favorite_location (file))
|
||||
return g_strdup (_("Starred"));
|
||||
|
||||
return g_strdup (nautilus_file_peek_display_name (file));
|
||||
}
|
||||
|
||||
|
@ -7608,6 +7665,11 @@ nautilus_file_get_string_attribute_with_default_q (NautilusFile *file,
|
|||
/* If n/a */
|
||||
return g_strdup ("");
|
||||
}
|
||||
if (attribute_q == attribute_favorite_q)
|
||||
{
|
||||
/* If n/a */
|
||||
return g_strdup ("");
|
||||
}
|
||||
|
||||
/* Fallback, use for both unknown attributes and attributes
|
||||
* for which we have no more appropriate default.
|
||||
|
@ -8298,6 +8360,23 @@ nautilus_file_is_in_recent (NautilusFile *file)
|
|||
return nautilus_directory_is_in_recent (file->details->directory);
|
||||
}
|
||||
|
||||
/**
|
||||
* nautilus_file_is_in_starred
|
||||
*
|
||||
* Check if this file is a file in Starred.
|
||||
* @file: NautilusFile representing the file in question.
|
||||
*
|
||||
* Returns: TRUE if @file is in Starred.
|
||||
*
|
||||
**/
|
||||
gboolean
|
||||
nautilus_file_is_in_starred (NautilusFile *file)
|
||||
{
|
||||
g_assert (NAUTILUS_IS_FILE (file));
|
||||
|
||||
return nautilus_directory_is_in_starred (file->details->directory);
|
||||
}
|
||||
|
||||
static const gchar * const remote_types[] =
|
||||
{
|
||||
"afp",
|
||||
|
@ -8356,6 +8435,27 @@ nautilus_file_is_other_locations (NautilusFile *file)
|
|||
return is_other_locations;
|
||||
}
|
||||
|
||||
/**
|
||||
* nautilus_file_is_favorite_location
|
||||
*
|
||||
* Check if this file is the Favorite location.
|
||||
* @file: NautilusFile representing the file in question.
|
||||
*
|
||||
* Returns: TRUE if @file is the Favorite location.
|
||||
*
|
||||
**/
|
||||
gboolean
|
||||
nautilus_file_is_favorite_location (NautilusFile *file)
|
||||
{
|
||||
g_autofree gchar *uri = NULL;
|
||||
|
||||
g_assert (NAUTILUS_IS_FILE (file));
|
||||
|
||||
uri = nautilus_file_get_uri (file);
|
||||
|
||||
return eel_uri_is_favorites (uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* nautilus_file_is_in_admin
|
||||
*
|
||||
|
@ -9371,6 +9471,7 @@ nautilus_file_class_init (NautilusFileClass *class)
|
|||
attribute_link_target_q = g_quark_from_static_string ("link_target");
|
||||
attribute_volume_q = g_quark_from_static_string ("volume");
|
||||
attribute_free_space_q = g_quark_from_static_string ("free_space");
|
||||
attribute_favorite_q = g_quark_from_static_string ("favorite");
|
||||
|
||||
G_OBJECT_CLASS (class)->finalize = finalize;
|
||||
G_OBJECT_CLASS (class)->constructor = nautilus_file_constructor;
|
||||
|
|
|
@ -55,6 +55,7 @@ typedef enum {
|
|||
NAUTILUS_FILE_SORT_BY_DISPLAY_NAME,
|
||||
NAUTILUS_FILE_SORT_BY_SIZE,
|
||||
NAUTILUS_FILE_SORT_BY_TYPE,
|
||||
NAUTILUS_FILE_SORT_BY_FAVORITE,
|
||||
NAUTILUS_FILE_SORT_BY_MTIME,
|
||||
NAUTILUS_FILE_SORT_BY_ATIME,
|
||||
NAUTILUS_FILE_SORT_BY_TRASHED_TIME,
|
||||
|
@ -215,9 +216,11 @@ gboolean nautilus_file_is_archive (NautilusFile *file);
|
|||
gboolean nautilus_file_is_in_search (NautilusFile *file);
|
||||
gboolean nautilus_file_is_in_trash (NautilusFile *file);
|
||||
gboolean nautilus_file_is_in_recent (NautilusFile *file);
|
||||
gboolean nautilus_file_is_in_starred (NautilusFile *file);
|
||||
gboolean nautilus_file_is_in_admin (NautilusFile *file);
|
||||
gboolean nautilus_file_is_remote (NautilusFile *file);
|
||||
gboolean nautilus_file_is_other_locations (NautilusFile *file);
|
||||
gboolean nautilus_file_is_favorite_location (NautilusFile *file);
|
||||
gboolean nautilus_file_is_home (NautilusFile *file);
|
||||
gboolean nautilus_file_is_desktop_directory (NautilusFile *file);
|
||||
gboolean nautilus_file_is_child_of_desktop_directory (NautilusFile *file);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "nautilus-window.h"
|
||||
#include "nautilus-toolbar.h"
|
||||
#include "nautilus-view.h"
|
||||
#include "nautilus-tag-manager.h"
|
||||
|
||||
#ifdef HAVE_X11_XF86KEYSYM_H
|
||||
#include <X11/XF86keysym.h>
|
||||
|
@ -70,6 +71,7 @@
|
|||
#include <libnautilus-extension/nautilus-menu-provider.h>
|
||||
#include "nautilus-clipboard.h"
|
||||
#include "nautilus-search-directory.h"
|
||||
#include "nautilus-favorite-directory.h"
|
||||
#include "nautilus-directory.h"
|
||||
#include "nautilus-dnd.h"
|
||||
#include "nautilus-file-attributes.h"
|
||||
|
@ -254,6 +256,7 @@ typedef struct
|
|||
GtkWidget *folder_is_empty_widget;
|
||||
GtkWidget *trash_is_empty_widget;
|
||||
GtkWidget *no_search_results_widget;
|
||||
GtkWidget *starred_is_empty_widget;
|
||||
|
||||
/* Floating bar */
|
||||
guint floating_bar_set_status_timeout_id;
|
||||
|
@ -273,6 +276,9 @@ typedef struct
|
|||
|
||||
gulong stop_signal_handler;
|
||||
gulong reload_signal_handler;
|
||||
|
||||
GCancellable *favorite_cancellable;
|
||||
NautilusTagManager *tag_manager;
|
||||
} NautilusFilesViewPrivate;
|
||||
|
||||
typedef struct
|
||||
|
@ -747,6 +753,19 @@ showing_recent_directory (NautilusFilesView *view)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
showing_starred_directory (NautilusFilesView *view)
|
||||
{
|
||||
NautilusFile *file;
|
||||
|
||||
file = nautilus_files_view_get_directory_as_file (view);
|
||||
if (file != NULL)
|
||||
{
|
||||
return nautilus_file_is_in_starred (file);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nautilus_files_view_supports_creating_files (NautilusFilesView *view)
|
||||
{
|
||||
|
@ -754,7 +773,8 @@ nautilus_files_view_supports_creating_files (NautilusFilesView *view)
|
|||
|
||||
return !nautilus_files_view_is_read_only (view)
|
||||
&& !showing_trash_directory (view)
|
||||
&& !showing_recent_directory (view);
|
||||
&& !showing_recent_directory (view)
|
||||
&& !showing_starred_directory (view);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -1561,6 +1581,46 @@ action_delete (GSimpleAction *action,
|
|||
delete_selected_files (NAUTILUS_FILES_VIEW (user_data));
|
||||
}
|
||||
|
||||
static void
|
||||
action_star (GSimpleAction *action,
|
||||
GVariant *state,
|
||||
gpointer user_data)
|
||||
{
|
||||
NautilusFilesView *view;
|
||||
GList *selection;
|
||||
NautilusFilesViewPrivate *priv;
|
||||
|
||||
view = NAUTILUS_FILES_VIEW (user_data);
|
||||
priv = nautilus_files_view_get_instance_private (view);
|
||||
selection = nautilus_view_get_selection (NAUTILUS_VIEW (view));
|
||||
|
||||
nautilus_tag_manager_star_files (priv->tag_manager,
|
||||
G_OBJECT (view),
|
||||
selection,
|
||||
NULL,
|
||||
priv->favorite_cancellable);
|
||||
}
|
||||
|
||||
static void
|
||||
action_unstar (GSimpleAction *action,
|
||||
GVariant *state,
|
||||
gpointer user_data)
|
||||
{
|
||||
NautilusFilesView *view;
|
||||
GList *selection;
|
||||
NautilusFilesViewPrivate *priv;
|
||||
|
||||
view = NAUTILUS_FILES_VIEW (user_data);
|
||||
priv = nautilus_files_view_get_instance_private (view);
|
||||
selection = nautilus_view_get_selection (NAUTILUS_VIEW (view));
|
||||
|
||||
nautilus_tag_manager_unstar_files (priv->tag_manager,
|
||||
G_OBJECT (view),
|
||||
selection,
|
||||
NULL,
|
||||
priv->favorite_cancellable);
|
||||
}
|
||||
|
||||
static void
|
||||
action_restore_from_trash (GSimpleAction *action,
|
||||
GVariant *state,
|
||||
|
@ -3226,6 +3286,9 @@ nautilus_files_view_finalize (GObject *object)
|
|||
g_hash_table_destroy (priv->non_ready_files);
|
||||
g_hash_table_destroy (priv->pending_reveal);
|
||||
|
||||
g_cancellable_cancel (priv->favorite_cancellable);
|
||||
g_clear_object (&priv->favorite_cancellable);
|
||||
|
||||
G_OBJECT_CLASS (nautilus_files_view_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
@ -3474,6 +3537,10 @@ nautilus_files_view_set_location (NautilusView *view,
|
|||
set_search_query_internal (files_view, previous_query, base_model);
|
||||
g_object_unref (previous_query);
|
||||
}
|
||||
else if (NAUTILUS_IS_FAVORITE_DIRECTORY (directory))
|
||||
{
|
||||
load_directory (NAUTILUS_FILES_VIEW (view), directory);
|
||||
}
|
||||
else
|
||||
{
|
||||
load_directory (NAUTILUS_FILES_VIEW (view), directory);
|
||||
|
@ -3514,6 +3581,7 @@ real_check_empty_states (NautilusFilesView *view)
|
|||
gtk_widget_hide (priv->no_search_results_widget);
|
||||
gtk_widget_hide (priv->folder_is_empty_widget);
|
||||
gtk_widget_hide (priv->trash_is_empty_widget);
|
||||
gtk_widget_hide (priv->starred_is_empty_widget);
|
||||
|
||||
if (!priv->loading &&
|
||||
nautilus_files_view_is_empty (view))
|
||||
|
@ -3528,6 +3596,10 @@ real_check_empty_states (NautilusFilesView *view)
|
|||
{
|
||||
gtk_widget_show (priv->trash_is_empty_widget);
|
||||
}
|
||||
else if (eel_uri_is_favorites (uri))
|
||||
{
|
||||
gtk_widget_show (priv->starred_is_empty_widget);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_show (priv->folder_is_empty_widget);
|
||||
|
@ -7014,6 +7086,8 @@ const GActionEntry view_entries[] =
|
|||
{ "copy-to", action_copy_to},
|
||||
{ "move-to-trash", action_move_to_trash},
|
||||
{ "delete-from-trash", action_delete },
|
||||
{ "star", action_star},
|
||||
{ "unstar", action_unstar},
|
||||
/* We separate the shortcut and the menu item since we want the shortcut
|
||||
* to always be available, but we don't want the menu item shown if not
|
||||
* completely necesary. Since the visibility of the menu item is based on
|
||||
|
@ -7093,6 +7167,7 @@ on_clipboard_contents_received (GtkClipboard *clipboard,
|
|||
gboolean settings_show_create_link;
|
||||
gboolean is_read_only;
|
||||
gboolean selection_contains_recent;
|
||||
gboolean selection_contains_starred;
|
||||
GAction *action;
|
||||
|
||||
view = NAUTILUS_FILES_VIEW (user_data);
|
||||
|
@ -7110,9 +7185,10 @@ on_clipboard_contents_received (GtkClipboard *clipboard,
|
|||
NAUTILUS_PREFERENCES_SHOW_CREATE_LINK);
|
||||
is_read_only = nautilus_files_view_is_read_only (view);
|
||||
selection_contains_recent = showing_recent_directory (view);
|
||||
selection_contains_starred = showing_starred_directory (view);
|
||||
can_link_from_copied_files = !nautilus_clipboard_is_cut_from_selection_data (selection_data) &&
|
||||
!selection_contains_recent && !is_read_only &&
|
||||
gtk_selection_data_get_length (selection_data) > 0;
|
||||
!selection_contains_recent && !selection_contains_starred &&
|
||||
!is_read_only && gtk_selection_data_get_length (selection_data) > 0;
|
||||
|
||||
action = g_action_map_lookup_action (G_ACTION_MAP (priv->view_action_group),
|
||||
"create-link");
|
||||
|
@ -7399,6 +7475,7 @@ real_update_actions_state (NautilusFilesView *view)
|
|||
gboolean selection_contains_desktop_or_home_dir;
|
||||
gboolean selection_contains_recent;
|
||||
gboolean selection_contains_search;
|
||||
gboolean selection_contains_starred;
|
||||
gboolean selection_all_in_trash;
|
||||
gboolean selection_is_read_only;
|
||||
gboolean can_create_files;
|
||||
|
@ -7423,6 +7500,9 @@ real_update_actions_state (NautilusFilesView *view)
|
|||
gboolean settings_show_delete_permanently;
|
||||
gboolean settings_show_create_link;
|
||||
GDriveStartStopType start_stop_type;
|
||||
gboolean show_star;
|
||||
gboolean show_unstar;
|
||||
gchar *uri;
|
||||
|
||||
priv = nautilus_files_view_get_instance_private (view);
|
||||
|
||||
|
@ -7433,6 +7513,7 @@ real_update_actions_state (NautilusFilesView *view)
|
|||
selection_contains_special_link = nautilus_files_view_special_link_in_selection (view, selection);
|
||||
selection_contains_desktop_or_home_dir = desktop_or_home_dir_in_selection (selection);
|
||||
selection_contains_recent = showing_recent_directory (view);
|
||||
selection_contains_starred = showing_starred_directory (view);
|
||||
selection_contains_search = nautilus_view_is_searching (NAUTILUS_VIEW (view));
|
||||
selection_is_read_only = selection_count == 1 &&
|
||||
(!nautilus_file_can_write (NAUTILUS_FILE (selection->data)) &&
|
||||
|
@ -7454,8 +7535,10 @@ real_update_actions_state (NautilusFilesView *view)
|
|||
!selection_contains_desktop_or_home_dir;
|
||||
can_copy_files = selection_count != 0
|
||||
&& !selection_contains_special_link;
|
||||
can_move_files = can_delete_files && !selection_contains_recent;
|
||||
can_move_files = can_delete_files && !selection_contains_recent &&
|
||||
!selection_contains_starred;
|
||||
can_paste_files_into = (!selection_contains_recent &&
|
||||
!selection_contains_starred &&
|
||||
selection_count == 1 &&
|
||||
can_paste_into_file (NAUTILUS_FILE (selection->data)));
|
||||
can_extract_files = selection_count != 0 &&
|
||||
|
@ -7471,7 +7554,8 @@ real_update_actions_state (NautilusFilesView *view)
|
|||
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
|
||||
"new-folder-with-selection");
|
||||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
|
||||
can_create_files && can_delete_files && (selection_count > 1) && !selection_contains_recent);
|
||||
can_create_files && can_delete_files && (selection_count > 1) && !selection_contains_recent
|
||||
&& !selection_contains_starred);
|
||||
|
||||
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
|
||||
"rename");
|
||||
|
@ -7519,7 +7603,8 @@ real_update_actions_state (NautilusFilesView *view)
|
|||
|
||||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
|
||||
selection_count == 1 &&
|
||||
(selection_contains_recent || selection_contains_search));
|
||||
(selection_contains_recent || selection_contains_search ||
|
||||
selection_contains_starred));
|
||||
|
||||
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
|
||||
"new-folder");
|
||||
|
@ -7585,14 +7670,16 @@ real_update_actions_state (NautilusFilesView *view)
|
|||
"delete-permanently-menu-item");
|
||||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
|
||||
can_delete_files && !can_trash_files &&
|
||||
!selection_all_in_trash && !selection_contains_recent);
|
||||
!selection_all_in_trash && !selection_contains_recent &&
|
||||
!selection_contains_starred);
|
||||
|
||||
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
|
||||
"permanent-delete-permanently-menu-item");
|
||||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
|
||||
can_delete_files && can_trash_files &&
|
||||
settings_show_delete_permanently &&
|
||||
!selection_all_in_trash && !selection_contains_recent);
|
||||
!selection_all_in_trash && !selection_contains_recent &&
|
||||
!selection_contains_starred);
|
||||
|
||||
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
|
||||
"remove-from-recent");
|
||||
|
@ -7602,7 +7689,8 @@ real_update_actions_state (NautilusFilesView *view)
|
|||
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
|
||||
"cut");
|
||||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
|
||||
can_move_files && !selection_contains_recent);
|
||||
can_move_files && !selection_contains_recent &&
|
||||
!selection_contains_starred);
|
||||
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
|
||||
"copy");
|
||||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
|
||||
|
@ -7620,7 +7708,8 @@ real_update_actions_state (NautilusFilesView *view)
|
|||
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
|
||||
"move-to");
|
||||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
|
||||
can_move_files && !selection_contains_recent);
|
||||
can_move_files && !selection_contains_recent &&
|
||||
!selection_contains_starred);
|
||||
|
||||
/* Drive menu */
|
||||
show_mount = (selection != NULL);
|
||||
|
@ -7697,13 +7786,14 @@ real_update_actions_state (NautilusFilesView *view)
|
|||
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
|
||||
"paste");
|
||||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
|
||||
!is_read_only && !selection_contains_recent);
|
||||
!is_read_only && !selection_contains_recent &&
|
||||
!selection_contains_starred);
|
||||
|
||||
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
|
||||
"paste-into");
|
||||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
|
||||
!selection_is_read_only && !selection_contains_recent &&
|
||||
can_paste_files_into);
|
||||
can_paste_files_into && !selection_contains_starred);
|
||||
|
||||
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
|
||||
"properties");
|
||||
|
@ -7714,6 +7804,7 @@ real_update_actions_state (NautilusFilesView *view)
|
|||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
|
||||
can_create_files &&
|
||||
!selection_contains_recent &&
|
||||
!selection_contains_starred &&
|
||||
priv->templates_present);
|
||||
|
||||
/* Actions that are related to the clipboard need request, request the data
|
||||
|
@ -7757,6 +7848,38 @@ real_update_actions_state (NautilusFilesView *view)
|
|||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
|
||||
!nautilus_files_view_is_empty (view));
|
||||
|
||||
show_star = (selection != NULL);
|
||||
show_unstar = (selection != NULL);
|
||||
for (l = selection; l != NULL; l = l->next)
|
||||
{
|
||||
file = NAUTILUS_FILE (l->data);
|
||||
uri = nautilus_file_get_uri (file);
|
||||
|
||||
if (!show_star && !show_unstar)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (nautilus_tag_manager_file_is_favorite (priv->tag_manager, uri))
|
||||
{
|
||||
show_star = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
show_unstar = FALSE;
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
|
||||
"star");
|
||||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), show_star);
|
||||
|
||||
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
|
||||
"unstar");
|
||||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), show_unstar);
|
||||
|
||||
nautilus_file_list_free (selection);
|
||||
}
|
||||
|
||||
|
@ -8031,7 +8154,8 @@ static void
|
|||
update_background_menu (NautilusFilesView *view)
|
||||
{
|
||||
if (nautilus_files_view_supports_creating_files (view) &&
|
||||
!showing_recent_directory (view))
|
||||
!showing_recent_directory (view) &&
|
||||
!showing_starred_directory (view))
|
||||
{
|
||||
update_templates_menu (view);
|
||||
}
|
||||
|
@ -9601,6 +9725,14 @@ nautilus_files_view_init (NautilusFilesView *view)
|
|||
TRUE);
|
||||
g_object_unref (builder);
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/ui/nautilus-starred-is-empty.ui");
|
||||
priv->starred_is_empty_widget = GTK_WIDGET (gtk_builder_get_object (builder, "starred_is_empty"));
|
||||
gtk_overlay_add_overlay (GTK_OVERLAY (priv->overlay), priv->starred_is_empty_widget);
|
||||
gtk_overlay_set_overlay_pass_through (GTK_OVERLAY (priv->overlay),
|
||||
priv->starred_is_empty_widget,
|
||||
TRUE);
|
||||
g_object_unref (builder);
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/ui/nautilus-trash-is-empty.ui");
|
||||
priv->trash_is_empty_widget = GTK_WIDGET (gtk_builder_get_object (builder, "trash_is_empty"));
|
||||
gtk_overlay_add_overlay (GTK_OVERLAY (priv->overlay), priv->trash_is_empty_widget);
|
||||
|
@ -9742,6 +9874,9 @@ nautilus_files_view_init (NautilusFilesView *view)
|
|||
* changed */
|
||||
nautilus_application_set_accelerator (app, "view.show-move-to-trash-shortcut-changed-dialog", "<control>Delete");
|
||||
|
||||
priv->favorite_cancellable = g_cancellable_new ();
|
||||
priv->tag_manager = nautilus_tag_manager_get ();
|
||||
|
||||
nautilus_profile_end (NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "nautilus-list-model.h"
|
||||
#include "nautilus-tree-view-drag-dest.h"
|
||||
#include "nautilus-dnd.h"
|
||||
#include "nautilus-tag-manager.h"
|
||||
|
||||
struct NautilusListViewDetails {
|
||||
GtkTreeView *tree_view;
|
||||
|
@ -66,5 +67,8 @@ struct NautilusListViewDetails {
|
|||
GQuark last_sort_attr;
|
||||
|
||||
GRegex *regex;
|
||||
|
||||
NautilusTagManager *tag_manager;
|
||||
GCancellable *favorite_cancellable;
|
||||
};
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "nautilus-toolbar.h"
|
||||
#include "nautilus-list-view-dnd.h"
|
||||
#include "nautilus-view.h"
|
||||
#include "nautilus-tag-manager.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <eel/eel-vfs-extensions.h>
|
||||
|
@ -457,6 +458,90 @@ row_activated_callback (GtkTreeView *treeview,
|
|||
activate_selected_items (view);
|
||||
}
|
||||
|
||||
gboolean
|
||||
check_starred_status (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
NautilusFile *file;
|
||||
GList *l;
|
||||
GList *changed_files;
|
||||
|
||||
changed_files = data;
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (model),
|
||||
iter,
|
||||
NAUTILUS_LIST_MODEL_FILE_COLUMN, &file,
|
||||
-1);
|
||||
|
||||
if (!file)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (l = changed_files; l != NULL; l = l->next)
|
||||
{
|
||||
if (nautilus_file_compare_location (NAUTILUS_FILE (l->data), file) == 0)
|
||||
{
|
||||
gtk_tree_model_row_changed (model, path, iter);
|
||||
}
|
||||
}
|
||||
|
||||
nautilus_file_unref (file);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_favorites_files_changed (NautilusTagManager *tag_manager,
|
||||
GList *changed_files,
|
||||
gpointer user_data)
|
||||
{
|
||||
NautilusListView *list_view;
|
||||
|
||||
list_view = NAUTILUS_LIST_VIEW (user_data);
|
||||
|
||||
gtk_tree_model_foreach (GTK_TREE_MODEL (list_view->details->model),
|
||||
check_starred_status,
|
||||
changed_files);
|
||||
}
|
||||
|
||||
static void
|
||||
on_star_cell_renderer_clicked (GtkTreePath *path,
|
||||
NautilusListView *list_view)
|
||||
{
|
||||
NautilusListModel *list_model;
|
||||
NautilusFile *file;
|
||||
g_autofree gchar *uri = NULL;
|
||||
GList *selection;
|
||||
|
||||
list_model = list_view->details->model;
|
||||
|
||||
file = nautilus_list_model_file_for_path (list_model, path);
|
||||
uri = nautilus_file_get_uri (file);
|
||||
selection = g_list_prepend (NULL, file);
|
||||
|
||||
if (nautilus_tag_manager_file_is_favorite (list_view->details->tag_manager, uri))
|
||||
{
|
||||
nautilus_tag_manager_unstar_files (list_view->details->tag_manager,
|
||||
G_OBJECT (list_view),
|
||||
selection,
|
||||
NULL,
|
||||
list_view->details->favorite_cancellable);
|
||||
}
|
||||
else
|
||||
{
|
||||
nautilus_tag_manager_star_files (list_view->details->tag_manager,
|
||||
G_OBJECT (list_view),
|
||||
selection,
|
||||
NULL,
|
||||
list_view->details->favorite_cancellable);
|
||||
}
|
||||
|
||||
nautilus_file_list_free (selection);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
button_press_callback (GtkWidget *widget,
|
||||
GdkEventButton *event,
|
||||
|
@ -703,6 +788,32 @@ button_press_callback (GtkWidget *widget,
|
|||
}
|
||||
}
|
||||
|
||||
if (is_simple_click)
|
||||
{
|
||||
GtkTreeViewColumn *column = NULL;
|
||||
gdouble cell_middle_x;
|
||||
|
||||
gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (view->details->tree_view),
|
||||
event->x,
|
||||
event->y,
|
||||
NULL,
|
||||
&column,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (g_strcmp0 (gtk_tree_view_column_get_title (column), "Star") == 0)
|
||||
{
|
||||
cell_middle_x = gtk_tree_view_column_get_width (column) / 2 +
|
||||
gtk_tree_view_column_get_x_offset (column);
|
||||
|
||||
if (event->x > cell_middle_x - 10 &&
|
||||
event->x < cell_middle_x + 10)
|
||||
{
|
||||
on_star_cell_renderer_clicked (path, view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
/* We chained to the default handler in this method, so never
|
||||
|
@ -1546,6 +1657,45 @@ apply_columns_settings (NautilusListView *list_view,
|
|||
g_list_free (view_columns);
|
||||
}
|
||||
|
||||
static void
|
||||
favorite_cell_data_func (GtkTreeViewColumn *column,
|
||||
GtkCellRenderer *renderer,
|
||||
GtkTreeModel *model,
|
||||
GtkTreeIter *iter,
|
||||
NautilusListView *view)
|
||||
{
|
||||
g_autofree gchar *text = NULL;
|
||||
g_autofree gchar *uri = NULL;
|
||||
NautilusFile *file;
|
||||
|
||||
gtk_tree_model_get (model, iter,
|
||||
view->details->file_name_column_num, &text,
|
||||
-1);
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (model),
|
||||
iter,
|
||||
NAUTILUS_LIST_MODEL_FILE_COLUMN, &file,
|
||||
-1);
|
||||
|
||||
uri = nautilus_file_get_uri (file);
|
||||
|
||||
if (nautilus_tag_manager_file_is_favorite (view->details->tag_manager, uri))
|
||||
{
|
||||
g_object_set (renderer,
|
||||
"icon-name", "starred-symbolic",
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_set (renderer,
|
||||
"icon-name", "non-starred-symbolic",
|
||||
NULL);
|
||||
|
||||
}
|
||||
|
||||
nautilus_file_unref (file);
|
||||
}
|
||||
|
||||
static void
|
||||
filename_cell_data_func (GtkTreeViewColumn *column,
|
||||
GtkCellRenderer *renderer,
|
||||
|
@ -2040,13 +2190,34 @@ create_and_set_up_tree_view (NautilusListView *view)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* We need to use libgd */
|
||||
cell = gd_styled_text_renderer_new ();
|
||||
/* FIXME: should be just dim-label.
|
||||
* See https://bugzilla.gnome.org/show_bug.cgi?id=744397
|
||||
*/
|
||||
gd_styled_text_renderer_add_class (GD_STYLED_TEXT_RENDERER (cell),
|
||||
"nautilus-list-dim-label");
|
||||
if (g_strcmp0 (name, "favorite") == 0)
|
||||
{
|
||||
cell = gtk_cell_renderer_pixbuf_new ();
|
||||
g_object_set (cell,
|
||||
"icon-name", "non-starred-symbolic",
|
||||
"mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
|
||||
NULL);
|
||||
|
||||
column = gtk_tree_view_column_new_with_attributes (label,
|
||||
cell,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We need to use libgd */
|
||||
cell = gd_styled_text_renderer_new ();
|
||||
/* FIXME: should be just dim-label.
|
||||
* See https://bugzilla.gnome.org/show_bug.cgi?id=744397
|
||||
*/
|
||||
gd_styled_text_renderer_add_class (GD_STYLED_TEXT_RENDERER (cell),
|
||||
"nautilus-list-dim-label");
|
||||
|
||||
column = gtk_tree_view_column_new_with_attributes (label,
|
||||
cell,
|
||||
"text", column_num,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
g_object_set (cell,
|
||||
"xalign", xalign,
|
||||
|
@ -2060,10 +2231,7 @@ create_and_set_up_tree_view (NautilusListView *view)
|
|||
}
|
||||
view->details->cells = g_list_append (view->details->cells,
|
||||
cell);
|
||||
column = gtk_tree_view_column_new_with_attributes (label,
|
||||
cell,
|
||||
"text", column_num,
|
||||
NULL);
|
||||
|
||||
gtk_tree_view_append_column (view->details->tree_view, column);
|
||||
gtk_tree_view_column_set_sort_column_id (column, column_num);
|
||||
g_hash_table_insert (view->details->columns,
|
||||
|
@ -2090,6 +2258,12 @@ create_and_set_up_tree_view (NautilusListView *view)
|
|||
(GtkTreeCellDataFunc) trash_orig_path_cell_data_func,
|
||||
view, NULL);
|
||||
}
|
||||
else if (!strcmp (name, "favorite"))
|
||||
{
|
||||
gtk_tree_view_column_set_cell_data_func (column, cell,
|
||||
(GtkTreeCellDataFunc) favorite_cell_data_func,
|
||||
view, NULL);
|
||||
}
|
||||
}
|
||||
g_free (name);
|
||||
g_free (label);
|
||||
|
@ -3378,6 +3552,13 @@ nautilus_list_view_finalize (GObject *object)
|
|||
|
||||
g_regex_unref (list_view->details->regex);
|
||||
|
||||
g_cancellable_cancel (list_view->details->favorite_cancellable);
|
||||
g_clear_object (&list_view->details->favorite_cancellable);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (list_view->details->tag_manager,
|
||||
on_favorites_files_changed,
|
||||
list_view);
|
||||
|
||||
g_free (list_view->details);
|
||||
|
||||
G_OBJECT_CLASS (nautilus_list_view_parent_class)->finalize (object);
|
||||
|
@ -3664,6 +3845,14 @@ nautilus_list_view_init (NautilusListView *list_view)
|
|||
"zoom-to-level", g_variant_new_int32 (get_default_zoom_level ()));
|
||||
|
||||
list_view->details->regex = g_regex_new ("\\R+", 0, G_REGEX_MATCH_NEWLINE_ANY, NULL);
|
||||
|
||||
list_view->details->tag_manager = nautilus_tag_manager_get ();
|
||||
list_view->details->favorite_cancellable = g_cancellable_new ();
|
||||
|
||||
g_signal_connect (list_view->details->tag_manager,
|
||||
"favorites-changed",
|
||||
(GCallback) on_favorites_files_changed,
|
||||
list_view);
|
||||
}
|
||||
|
||||
NautilusFilesView *
|
||||
|
|
|
@ -47,7 +47,8 @@ typedef enum
|
|||
OTHER_LOCATIONS_BUTTON,
|
||||
ROOT_BUTTON,
|
||||
HOME_BUTTON,
|
||||
MOUNT_BUTTON
|
||||
MOUNT_BUTTON,
|
||||
FAVORITE_LOCATION_BUTTON
|
||||
} ButtonType;
|
||||
|
||||
#define BUTTON_DATA(x) ((ButtonData *) (x))
|
||||
|
@ -454,6 +455,11 @@ get_dir_name (ButtonData *button_data)
|
|||
return _("Other Locations");
|
||||
}
|
||||
|
||||
case FAVORITE_LOCATION_BUTTON:
|
||||
{
|
||||
return _("Starred");
|
||||
}
|
||||
|
||||
default:
|
||||
return button_data->dir_name;
|
||||
}
|
||||
|
@ -1924,6 +1930,10 @@ setup_button_type (ButtonData *button_data,
|
|||
|
||||
g_object_unref (mount);
|
||||
}
|
||||
else if (nautilus_is_favorite_directory (location))
|
||||
{
|
||||
button_data->type = FAVORITE_LOCATION_BUTTON;
|
||||
}
|
||||
else
|
||||
{
|
||||
button_data->type = NORMAL_BUTTON;
|
||||
|
|
|
@ -46,6 +46,7 @@ struct _NautilusQuery
|
|||
GPtrArray *date_range;
|
||||
NautilusQuerySearchType search_type;
|
||||
NautilusQuerySearchContent search_content;
|
||||
gboolean search_favorite;
|
||||
|
||||
gboolean searching;
|
||||
gboolean recursive;
|
||||
|
@ -343,6 +344,7 @@ nautilus_query_init (NautilusQuery *query)
|
|||
query->location = g_file_new_for_path (g_get_home_dir ());
|
||||
query->search_type = g_settings_get_enum (nautilus_preferences, "search-filter-time-type");
|
||||
query->search_content = NAUTILUS_QUERY_SEARCH_CONTENT_SIMPLE;
|
||||
query->search_favorite = FALSE;
|
||||
g_mutex_init (&query->prepared_words_mutex);
|
||||
}
|
||||
|
||||
|
@ -550,6 +552,23 @@ nautilus_query_set_search_content (NautilusQuery *query,
|
|||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
nautilus_query_get_search_favorite (NautilusQuery *query)
|
||||
{
|
||||
g_return_val_if_fail (NAUTILUS_IS_QUERY (query), FALSE);
|
||||
|
||||
return query->search_favorite;
|
||||
}
|
||||
|
||||
void
|
||||
nautilus_query_set_search_favorite (NautilusQuery *query,
|
||||
gboolean search_favorite)
|
||||
{
|
||||
g_return_if_fail (NAUTILUS_IS_QUERY (query));
|
||||
|
||||
query->search_favorite = search_favorite;
|
||||
}
|
||||
|
||||
NautilusQuerySearchType
|
||||
nautilus_query_get_search_type (NautilusQuery *query)
|
||||
{
|
||||
|
|
|
@ -59,6 +59,10 @@ NautilusQuerySearchContent nautilus_query_get_search_content (NautilusQuery *que
|
|||
void nautilus_query_set_search_content (NautilusQuery *query,
|
||||
NautilusQuerySearchContent content);
|
||||
|
||||
gboolean nautilus_query_get_search_favorite (NautilusQuery *query);
|
||||
void nautilus_query_set_search_favorite (NautilusQuery *query,
|
||||
gboolean search_favorite);
|
||||
|
||||
NautilusQuerySearchType nautilus_query_get_search_type (NautilusQuery *query);
|
||||
void nautilus_query_set_search_type (NautilusQuery *query,
|
||||
NautilusQuerySearchType type);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "nautilus-directory-private.h"
|
||||
#include "nautilus-file.h"
|
||||
#include "nautilus-ui-utilities.h"
|
||||
#include "nautilus-tag-manager.h"
|
||||
#define DEBUG_FLAG NAUTILUS_DEBUG_SEARCH
|
||||
#include "nautilus-debug.h"
|
||||
|
||||
|
@ -139,6 +140,7 @@ model_directory_ready_cb (NautilusDirectory *directory,
|
|||
GDateTime *initial_date;
|
||||
GDateTime *end_date;
|
||||
GPtrArray *date_range;
|
||||
NautilusTagManager *tag_manager;
|
||||
|
||||
files = nautilus_directory_get_file_list (directory);
|
||||
mime_types = nautilus_query_get_mime_types (model->query);
|
||||
|
@ -191,12 +193,27 @@ model_directory_ready_cb (NautilusDirectory *directory,
|
|||
g_ptr_array_unref (date_range);
|
||||
}
|
||||
|
||||
if (nautilus_query_get_search_favorite (model->query))
|
||||
{
|
||||
tag_manager = nautilus_tag_manager_get ();
|
||||
|
||||
uri = nautilus_file_get_uri (file);
|
||||
|
||||
if (!nautilus_tag_manager_file_is_favorite (tag_manager, uri))
|
||||
{
|
||||
found = FALSE;
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
uri = nautilus_file_get_uri (file);
|
||||
hit = nautilus_search_hit_new (uri);
|
||||
nautilus_search_hit_set_fts_rank (hit, match);
|
||||
hits = g_list_prepend (hits, hit);
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "nautilus-search-provider.h"
|
||||
#include "nautilus-search-engine-simple.h"
|
||||
#include "nautilus-ui-utilities.h"
|
||||
#include "nautilus-tag-manager.h"
|
||||
#define DEBUG_FLAG NAUTILUS_DEBUG_SEARCH
|
||||
#include "nautilus-debug.h"
|
||||
|
||||
|
@ -222,7 +223,8 @@ visit_directory (GFile *dir,
|
|||
GPtrArray *date_range;
|
||||
GDateTime *initial_date;
|
||||
GDateTime *end_date;
|
||||
|
||||
NautilusTagManager *tag_manager;
|
||||
gchar *uri;
|
||||
|
||||
enumerator = g_file_enumerate_children (dir,
|
||||
data->mime_types != NULL ?
|
||||
|
@ -299,11 +301,24 @@ visit_directory (GFile *dir,
|
|||
g_ptr_array_unref (date_range);
|
||||
}
|
||||
|
||||
if (nautilus_query_get_search_favorite (data->query))
|
||||
{
|
||||
tag_manager = nautilus_tag_manager_get ();
|
||||
|
||||
uri = g_file_get_uri (child);
|
||||
|
||||
if (!nautilus_tag_manager_file_is_favorite (tag_manager, uri))
|
||||
{
|
||||
found = FALSE;
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
NautilusSearchHit *hit;
|
||||
GDateTime *date;
|
||||
char *uri;
|
||||
|
||||
uri = g_file_get_uri (child);
|
||||
hit = nautilus_search_hit_new (uri);
|
||||
|
|
|
@ -353,6 +353,11 @@ nautilus_search_engine_tracker_start (NautilusSearchProvider *provider)
|
|||
g_string_append_printf (sparql, "; fts:match '\"%s\"*'", search_text);
|
||||
}
|
||||
|
||||
if (nautilus_query_get_search_favorite (tracker->query))
|
||||
{
|
||||
g_string_append_printf (sparql, "; nao:hasTag nao:predefined-tag-favorite");
|
||||
}
|
||||
|
||||
if (mime_count > 0)
|
||||
{
|
||||
g_string_append (sparql, "; nie:mimeType ?mime");
|
||||
|
|
|
@ -95,17 +95,17 @@ search_engine_start_real (NautilusSearchEngine *engine)
|
|||
|
||||
g_object_ref (engine);
|
||||
|
||||
nautilus_search_provider_start (NAUTILUS_SEARCH_PROVIDER (priv->tracker));
|
||||
priv->providers_running++;
|
||||
nautilus_search_provider_start (NAUTILUS_SEARCH_PROVIDER (priv->tracker));
|
||||
|
||||
if (nautilus_search_engine_model_get_model (priv->model))
|
||||
{
|
||||
nautilus_search_provider_start (NAUTILUS_SEARCH_PROVIDER (priv->model));
|
||||
priv->providers_running++;
|
||||
nautilus_search_provider_start (NAUTILUS_SEARCH_PROVIDER (priv->model));
|
||||
}
|
||||
|
||||
nautilus_search_provider_start (NAUTILUS_SEARCH_PROVIDER (priv->simple));
|
||||
priv->providers_running++;
|
||||
nautilus_search_provider_start (NAUTILUS_SEARCH_PROVIDER (priv->simple));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
884
src/nautilus-tag-manager.c
Normal file
884
src/nautilus-tag-manager.c
Normal file
|
@ -0,0 +1,884 @@
|
|||
/* nautilus-tag-manager.c
|
||||
*
|
||||
* Copyright (C) 2017 Alexandru Pandelea <alexandru.pandelea@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 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "nautilus-tag-manager.h"
|
||||
#include "nautilus-file.h"
|
||||
#include "nautilus-file-undo-operations.h"
|
||||
#include "nautilus-file-undo-manager.h"
|
||||
|
||||
#include <tracker-sparql.h>
|
||||
|
||||
struct _NautilusTagManager
|
||||
{
|
||||
GObject object;
|
||||
|
||||
TrackerNotifier *notifier;
|
||||
GError *notifier_error;
|
||||
|
||||
GHashTable *favorite_files;
|
||||
GCancellable *cancellable;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (NautilusTagManager, nautilus_tag_manager, G_TYPE_OBJECT);
|
||||
|
||||
static NautilusTagManager *tag_manager = NULL;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GET_FAVORITE_FILES,
|
||||
GET_IDS_FOR_URLS
|
||||
} OperationType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GTask *task;
|
||||
GList *selection;
|
||||
GHashTable *ids;
|
||||
GObject *object;
|
||||
GAsyncReadyCallback callback;
|
||||
GCancellable *cancellable;
|
||||
} InsertTaskData;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NautilusTagManager *tag_manager;
|
||||
GTask *task;
|
||||
GList *selection;
|
||||
gboolean star;
|
||||
GHashTable *ids;
|
||||
} UpdateData;
|
||||
|
||||
enum
|
||||
{
|
||||
FAVORITES_CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
static const gchar*
|
||||
nautilus_tag_manager_file_with_id_changed_url (GHashTable *hash_table,
|
||||
gint64 id,
|
||||
const gchar *url)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
g_hash_table_iter_init (&iter, hash_table);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
if ((gint64) value == id && g_strcmp0 (url, key) != 0)
|
||||
{
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
destroy_insert_task_data (gpointer data)
|
||||
{
|
||||
InsertTaskData *task_data;
|
||||
|
||||
task_data = data;
|
||||
|
||||
nautilus_file_list_free (task_data->selection);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static GString*
|
||||
add_selection_filter (GList *selection,
|
||||
GString *query)
|
||||
{
|
||||
NautilusFile *file;
|
||||
GList *l;
|
||||
gchar *uri;
|
||||
|
||||
g_string_append (query, " FILTER(?url IN (");
|
||||
|
||||
for (l = selection; l != NULL; l = l->next)
|
||||
{
|
||||
file = l->data;
|
||||
|
||||
uri = nautilus_file_get_uri (file);
|
||||
|
||||
g_string_append_printf (query, "'%s'", uri);
|
||||
|
||||
if (l->next != NULL)
|
||||
{
|
||||
g_string_append (query, ", ");
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
g_string_append (query, "))");
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
static void
|
||||
start_query_or_update (GString *query,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data,
|
||||
gboolean is_query,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
TrackerSparqlConnection *connection;
|
||||
|
||||
connection = tracker_sparql_connection_get (cancellable, &error);
|
||||
if (!connection)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Error on getting connection: %s", error->message);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_query)
|
||||
{
|
||||
tracker_sparql_connection_query_async (connection,
|
||||
query->str,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
tracker_sparql_connection_update_async (connection,
|
||||
query->str,
|
||||
G_PRIORITY_DEFAULT,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
g_object_unref (connection);
|
||||
}
|
||||
|
||||
static void
|
||||
on_query_callback (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data,
|
||||
GAsyncReadyCallback callback,
|
||||
OperationType op_type,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
TrackerSparqlCursor *cursor;
|
||||
g_autoptr (GError) error = NULL;
|
||||
TrackerSparqlConnection *connection;
|
||||
GTask *task;
|
||||
|
||||
task = user_data;
|
||||
|
||||
connection = TRACKER_SPARQL_CONNECTION (object);
|
||||
|
||||
cursor = tracker_sparql_connection_query_finish (connection,
|
||||
result,
|
||||
&error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
if (error->code != G_IO_ERROR_CANCELLED)
|
||||
{
|
||||
if (op_type == GET_FAVORITE_FILES)
|
||||
{
|
||||
g_warning ("Error on getting favorite files: %s", error->message);
|
||||
}
|
||||
else if (op_type == GET_IDS_FOR_URLS)
|
||||
{
|
||||
g_warning ("Error on getting id for url: %s", error->message);
|
||||
g_task_return_pointer (task, g_task_get_task_data (task), NULL);
|
||||
g_object_unref (task);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Error on getting query callback: %s", error->message);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tracker_sparql_cursor_next_async (cursor,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_update_callback (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
TrackerSparqlConnection *connection;
|
||||
GError *error;
|
||||
UpdateData *data;
|
||||
gint64 *id;
|
||||
GList *l;
|
||||
gchar *uri;
|
||||
|
||||
data = user_data;
|
||||
|
||||
error = NULL;
|
||||
|
||||
connection = TRACKER_SPARQL_CONNECTION (object);
|
||||
|
||||
tracker_sparql_connection_update_finish (connection, result, &error);
|
||||
|
||||
if (error == NULL ||
|
||||
(error != NULL && error->code != G_IO_ERROR_CANCELLED))
|
||||
{
|
||||
for (l = data->selection; l != NULL; l = l->next)
|
||||
{
|
||||
uri = nautilus_file_get_uri (NAUTILUS_FILE (l->data));
|
||||
|
||||
if (data->star)
|
||||
{
|
||||
if (g_hash_table_contains (data->ids, uri))
|
||||
{
|
||||
id = g_new0 (gint64, 1);
|
||||
|
||||
*id = (gint64) g_hash_table_lookup (data->ids, uri);
|
||||
g_hash_table_insert (data->tag_manager->favorite_files,
|
||||
nautilus_file_get_uri (NAUTILUS_FILE (l->data)),
|
||||
id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_hash_table_remove (data->tag_manager->favorite_files, uri);
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
if (!nautilus_file_undo_manager_is_operating ())
|
||||
{
|
||||
NautilusFileUndoInfo *undo_info;
|
||||
|
||||
undo_info = nautilus_file_undo_info_favorites_new (data->selection, data->star);
|
||||
nautilus_file_undo_manager_set_action (undo_info);
|
||||
|
||||
g_object_unref (undo_info);
|
||||
}
|
||||
|
||||
g_signal_emit_by_name (data->tag_manager, "favorites-changed", nautilus_file_list_copy (data->selection));
|
||||
|
||||
g_task_return_boolean (data->task, TRUE);
|
||||
g_object_unref (data->task);
|
||||
}
|
||||
else if (error && error->code == G_IO_ERROR_CANCELLED)
|
||||
{
|
||||
g_error_free (error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_error (data->task, error);
|
||||
g_object_unref (data->task);
|
||||
g_warning ("error updating tags: %s", error->message);
|
||||
}
|
||||
|
||||
if (data->ids)
|
||||
{
|
||||
g_hash_table_destroy (data->ids);
|
||||
}
|
||||
nautilus_file_list_free (data->selection);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_query_status (TrackerSparqlCursor *cursor,
|
||||
GAsyncResult *result,
|
||||
OperationType op_type,
|
||||
gpointer user_data)
|
||||
{
|
||||
gboolean success;
|
||||
GTask *task;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
task = user_data;
|
||||
|
||||
success = tracker_sparql_cursor_next_finish (cursor, result, &error);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Error on getting all tags cursor callback: %s", error->message);
|
||||
}
|
||||
|
||||
g_clear_object (&cursor);
|
||||
|
||||
if (error == NULL ||
|
||||
(error != NULL && error->code != G_IO_ERROR_CANCELLED))
|
||||
{
|
||||
if (op_type == GET_IDS_FOR_URLS)
|
||||
{
|
||||
g_task_return_pointer (task, g_task_get_task_data (task), NULL);
|
||||
g_object_unref (task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
GList*
|
||||
nautilus_tag_manager_get_favorite_files (NautilusTagManager *self)
|
||||
{
|
||||
return g_hash_table_get_keys (self->favorite_files);
|
||||
}
|
||||
|
||||
static void
|
||||
on_get_favorite_files_cursor_callback (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
TrackerSparqlCursor *cursor;
|
||||
const gchar *url;
|
||||
gint64 *id;
|
||||
gboolean success;
|
||||
NautilusTagManager *self;
|
||||
GList *changed_files;
|
||||
NautilusFile *file;
|
||||
|
||||
cursor = TRACKER_SPARQL_CURSOR (object);
|
||||
|
||||
self = NAUTILUS_TAG_MANAGER (user_data);
|
||||
|
||||
success = get_query_status (cursor, result, GET_FAVORITE_FILES, NULL);
|
||||
if (!success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
id = g_new0 (gint64, 1);
|
||||
|
||||
url = tracker_sparql_cursor_get_string (cursor, 0, NULL);
|
||||
*id = tracker_sparql_cursor_get_integer (cursor, 1);
|
||||
|
||||
g_hash_table_insert (self->favorite_files,
|
||||
g_strdup (url),
|
||||
id);
|
||||
|
||||
file = nautilus_file_get_by_uri (url);
|
||||
changed_files = g_list_prepend (NULL, file);
|
||||
|
||||
g_signal_emit_by_name (self, "favorites-changed", changed_files);
|
||||
|
||||
nautilus_file_list_free (changed_files);
|
||||
|
||||
tracker_sparql_cursor_next_async (cursor,
|
||||
self->cancellable,
|
||||
on_get_favorite_files_cursor_callback,
|
||||
self);
|
||||
}
|
||||
|
||||
static void
|
||||
on_get_favorite_files_query_callback (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
NautilusTagManager *self;
|
||||
|
||||
self = NAUTILUS_TAG_MANAGER (user_data);
|
||||
|
||||
on_query_callback (object,
|
||||
result,
|
||||
user_data,
|
||||
on_get_favorite_files_cursor_callback,
|
||||
GET_FAVORITE_FILES,
|
||||
self->cancellable);
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_tag_manager_query_favorite_files (NautilusTagManager *self,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GString *query;
|
||||
|
||||
self->cancellable = cancellable;
|
||||
|
||||
query = g_string_new ("SELECT ?url tracker:id(?urn) WHERE { ?urn nie:url ?url ; nao:hasTag nao:predefined-tag-favorite}");
|
||||
|
||||
start_query_or_update (query,
|
||||
on_get_favorite_files_query_callback,
|
||||
self,
|
||||
TRUE,
|
||||
cancellable);
|
||||
|
||||
g_string_free (query, TRUE);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
nautilus_tag_manager_gpointer_task_finish (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (res, source_object), FALSE);
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (res), error);
|
||||
}
|
||||
|
||||
static GString*
|
||||
nautilus_tag_manager_delete_tag (NautilusTagManager *self,
|
||||
GList *selection,
|
||||
GString *query)
|
||||
{
|
||||
|
||||
g_string_append (query,
|
||||
"DELETE { ?urn nao:hasTag nao:predefined-tag-favorite }"
|
||||
"WHERE { ?urn a nfo:FileDataObject ; nie:url ?url .");
|
||||
|
||||
query = add_selection_filter (selection, query);
|
||||
|
||||
g_string_append (query, "}\n");
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
static GString*
|
||||
nautilus_tag_manager_insert_tag (NautilusTagManager *self,
|
||||
GList *selection,
|
||||
GString *query)
|
||||
{
|
||||
g_string_append (query,
|
||||
"INSERT { ?urn nao:hasTag nao:predefined-tag-favorite }"
|
||||
"WHERE { ?urn a nfo:FileDataObject ; nie:url ?url .");
|
||||
|
||||
query = add_selection_filter (selection, query);
|
||||
|
||||
g_string_append (query, "}\n");
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nautilus_tag_manager_file_is_favorite (NautilusTagManager *self,
|
||||
const gchar *file_name)
|
||||
{
|
||||
return g_hash_table_contains (self->favorite_files, file_name);
|
||||
}
|
||||
|
||||
static void
|
||||
on_get_file_ids_for_urls_cursor_callback (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
TrackerSparqlCursor *cursor;
|
||||
GTask *task;
|
||||
gint64 *id;
|
||||
const gchar *url;
|
||||
gboolean success;
|
||||
GList *l;
|
||||
gchar *file_url;
|
||||
InsertTaskData *data;
|
||||
|
||||
task = user_data;
|
||||
data = g_task_get_task_data (task);
|
||||
|
||||
cursor = TRACKER_SPARQL_CURSOR (object);
|
||||
|
||||
success = get_query_status (cursor, result, GET_IDS_FOR_URLS, task);
|
||||
if (!success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
id = g_new0 (gint64, 1);
|
||||
|
||||
url = tracker_sparql_cursor_get_string (cursor, 0, NULL);
|
||||
*id = tracker_sparql_cursor_get_integer (cursor, 1);
|
||||
|
||||
for (l = data->selection; l != NULL; l = l->next)
|
||||
{
|
||||
file_url = nautilus_file_get_uri (NAUTILUS_FILE (l->data));
|
||||
|
||||
if (g_strcmp0 (file_url, url) == 0)
|
||||
{
|
||||
g_hash_table_insert (data->ids,
|
||||
g_strdup (url),
|
||||
id);
|
||||
|
||||
g_free (file_url);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (file_url);
|
||||
}
|
||||
|
||||
tracker_sparql_cursor_next_async (cursor,
|
||||
g_task_get_cancellable (task),
|
||||
on_get_file_ids_for_urls_cursor_callback,
|
||||
task);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
on_get_file_ids_for_urls_query_callback (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = user_data;
|
||||
|
||||
on_query_callback (object,
|
||||
result,
|
||||
user_data,
|
||||
on_get_file_ids_for_urls_cursor_callback,
|
||||
GET_IDS_FOR_URLS,
|
||||
g_task_get_cancellable (task));
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_tag_manager_get_file_ids_for_urls (GObject *object,
|
||||
GList *selection,
|
||||
GTask *task)
|
||||
{
|
||||
GString *query;
|
||||
|
||||
query = g_string_new ("SELECT ?url tracker:id(?urn) WHERE { ?urn nie:url ?url; .");
|
||||
|
||||
query = add_selection_filter (selection, query);
|
||||
|
||||
g_string_append (query, "}\n");
|
||||
|
||||
start_query_or_update (query,
|
||||
on_get_file_ids_for_urls_query_callback,
|
||||
task,
|
||||
TRUE,
|
||||
g_task_get_cancellable (task));
|
||||
|
||||
g_string_free (query, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
on_star_files_callback (GObject *object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
NautilusTagManager *self;
|
||||
GString *query;
|
||||
InsertTaskData *data;
|
||||
g_autoptr (GError) error = NULL;
|
||||
GTask *task;
|
||||
UpdateData *update_data;
|
||||
|
||||
self = NAUTILUS_TAG_MANAGER (object);
|
||||
|
||||
data = nautilus_tag_manager_gpointer_task_finish (object, res, &error);
|
||||
|
||||
task = g_task_new (data->object, data->cancellable, data->callback, NULL);
|
||||
|
||||
query = g_string_new ("");
|
||||
|
||||
query = nautilus_tag_manager_insert_tag (self,
|
||||
data->selection,
|
||||
query);
|
||||
|
||||
update_data = g_new0 (UpdateData, 1);
|
||||
update_data->task = task;
|
||||
update_data->tag_manager = self;
|
||||
update_data->selection = nautilus_file_list_copy (data->selection);
|
||||
update_data->star = TRUE;
|
||||
update_data->ids = data->ids;
|
||||
|
||||
/* the ids hash table is now owned by the update_data,
|
||||
* so it will be freed by it.
|
||||
*/
|
||||
destroy_insert_task_data (data);
|
||||
|
||||
start_query_or_update (query,
|
||||
on_update_callback,
|
||||
update_data,
|
||||
FALSE,
|
||||
g_task_get_cancellable (task));
|
||||
|
||||
g_string_free (query, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
nautilus_tag_manager_star_files (NautilusTagManager *self,
|
||||
GObject *object,
|
||||
GList *selection,
|
||||
GAsyncReadyCallback callback,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GTask *task;
|
||||
InsertTaskData *data;
|
||||
|
||||
data = g_new0 (InsertTaskData, 1);
|
||||
data->selection = nautilus_file_list_copy (selection);
|
||||
data->ids = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
(GDestroyNotify) g_free,
|
||||
(GDestroyNotify) g_free);
|
||||
data->callback = callback;
|
||||
data->object = object;
|
||||
data->cancellable = cancellable;
|
||||
|
||||
task = g_task_new (self, cancellable, on_star_files_callback, NULL);
|
||||
g_task_set_task_data (task,
|
||||
data,
|
||||
NULL);
|
||||
|
||||
nautilus_tag_manager_get_file_ids_for_urls (G_OBJECT (self), selection, task);
|
||||
}
|
||||
|
||||
void
|
||||
nautilus_tag_manager_unstar_files (NautilusTagManager *self,
|
||||
GObject *object,
|
||||
GList *selection,
|
||||
GAsyncReadyCallback callback,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GString *query;
|
||||
GTask *task;
|
||||
UpdateData *update_data;
|
||||
|
||||
task = g_task_new (object, cancellable, callback, NULL);
|
||||
|
||||
query = g_string_new ("");
|
||||
|
||||
query = nautilus_tag_manager_delete_tag (self,
|
||||
selection,
|
||||
query);
|
||||
|
||||
update_data = g_new0 (UpdateData, 1);
|
||||
update_data->task = task;
|
||||
update_data->tag_manager = self;
|
||||
update_data->selection = nautilus_file_list_copy (selection);
|
||||
update_data->star = FALSE;
|
||||
|
||||
start_query_or_update (query,
|
||||
on_update_callback,
|
||||
update_data,
|
||||
FALSE,
|
||||
cancellable);
|
||||
|
||||
g_string_free (query, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
on_tracker_notifier_events(TrackerNotifier *notifier,
|
||||
GPtrArray *events,
|
||||
gpointer user_data)
|
||||
{
|
||||
TrackerNotifierEvent *event;
|
||||
NautilusTagManager *self;
|
||||
int i;
|
||||
const gchar *location_uri;
|
||||
const gchar *new_location_uri;
|
||||
GError *error = NULL;
|
||||
TrackerSparqlConnection *connection;
|
||||
TrackerSparqlCursor *cursor;
|
||||
GString *query;
|
||||
gboolean query_has_results;
|
||||
gint64 *id;
|
||||
GList *changed_files;
|
||||
NautilusFile *file;
|
||||
|
||||
self = NAUTILUS_TAG_MANAGER (user_data);
|
||||
|
||||
for (i = 0; i < events->len; i++)
|
||||
{
|
||||
event = g_ptr_array_index (events, i);
|
||||
|
||||
location_uri = tracker_notifier_event_get_location (event);
|
||||
|
||||
query = g_string_new ("");
|
||||
g_string_append_printf (query,
|
||||
"SELECT ?url WHERE { ?urn nie:url ?url; nao:hasTag nao:predefined-tag-favorite . FILTER (tracker:id(?urn) = %ld)}",
|
||||
tracker_notifier_event_get_id (event));
|
||||
|
||||
/* check if the file changed it's location and update hash table if so */
|
||||
new_location_uri = nautilus_tag_manager_file_with_id_changed_url (self->favorite_files,
|
||||
tracker_notifier_event_get_id (event),
|
||||
location_uri);
|
||||
if (new_location_uri)
|
||||
{
|
||||
id = g_new0 (gint64, 1);
|
||||
*id = tracker_notifier_event_get_id (event);
|
||||
|
||||
g_hash_table_remove (self->favorite_files, new_location_uri);
|
||||
g_hash_table_insert (self->favorite_files,
|
||||
g_strdup (location_uri),
|
||||
id);
|
||||
|
||||
file = nautilus_file_get_by_uri (location_uri);
|
||||
changed_files = g_list_prepend (NULL, file);
|
||||
|
||||
g_signal_emit_by_name (self, "favorites-changed", changed_files);
|
||||
|
||||
nautilus_file_list_free (changed_files);
|
||||
}
|
||||
|
||||
connection = tracker_sparql_connection_get (NULL, &error);
|
||||
|
||||
if (!connection)
|
||||
{
|
||||
g_printerr ("Couldn't obtain a direct connection to the Tracker store: %s",
|
||||
error ? error->message : "unknown error");
|
||||
g_clear_error (&error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
cursor = tracker_sparql_connection_query (connection,
|
||||
query->str,
|
||||
NULL,
|
||||
&error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_printerr ("Couldn't query the Tracker Store: '%s'", error->message);
|
||||
|
||||
g_clear_error (&error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (cursor)
|
||||
{
|
||||
query_has_results = tracker_sparql_cursor_next (cursor, NULL, &error);
|
||||
|
||||
/* if no results are found, then the file isn't marked as favorite.
|
||||
* If needed, update the hashtable.
|
||||
*/
|
||||
if (!query_has_results && location_uri && g_hash_table_contains (self->favorite_files, location_uri))
|
||||
{
|
||||
g_hash_table_remove (self->favorite_files, location_uri);
|
||||
|
||||
file = nautilus_file_get_by_uri (location_uri);
|
||||
changed_files = g_list_prepend (NULL, file);
|
||||
|
||||
g_signal_emit_by_name (self, "favorites-changed", changed_files);
|
||||
|
||||
nautilus_file_list_free (changed_files);
|
||||
}
|
||||
else if (query_has_results && location_uri && !g_hash_table_contains (self->favorite_files, location_uri))
|
||||
{
|
||||
id = g_new0 (gint64, 1);
|
||||
*id = tracker_notifier_event_get_id (event);
|
||||
|
||||
g_hash_table_insert (self->favorite_files,
|
||||
g_strdup (location_uri),
|
||||
id);
|
||||
|
||||
file = nautilus_file_get_by_uri (location_uri);
|
||||
changed_files = g_list_prepend (NULL, file);
|
||||
|
||||
g_signal_emit_by_name (self, "favorites-changed", changed_files);
|
||||
|
||||
nautilus_file_list_free (changed_files);
|
||||
}
|
||||
|
||||
g_object_unref (cursor);
|
||||
}
|
||||
|
||||
g_object_unref (connection);
|
||||
|
||||
g_string_free (query, TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_tag_manager_finalize (GObject *object)
|
||||
{
|
||||
NautilusTagManager *self;
|
||||
|
||||
self = NAUTILUS_TAG_MANAGER (object);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (self->notifier,
|
||||
G_CALLBACK (on_tracker_notifier_events),
|
||||
self);
|
||||
g_clear_object (&self->notifier);
|
||||
|
||||
g_hash_table_destroy (self->favorite_files);
|
||||
|
||||
G_OBJECT_CLASS (nautilus_tag_manager_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_tag_manager_class_init (NautilusTagManagerClass *klass)
|
||||
{
|
||||
GObjectClass *oclass;
|
||||
|
||||
oclass = G_OBJECT_CLASS (klass);
|
||||
|
||||
oclass->finalize = nautilus_tag_manager_finalize;
|
||||
|
||||
signals[FAVORITES_CHANGED] = g_signal_new ("favorites-changed",
|
||||
NAUTILUS_TYPE_TAG_MANAGER,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__POINTER,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_POINTER);
|
||||
}
|
||||
|
||||
NautilusTagManager* nautilus_tag_manager_get ()
|
||||
{
|
||||
if (tag_manager != NULL)
|
||||
{
|
||||
return g_object_ref (tag_manager);
|
||||
}
|
||||
|
||||
tag_manager = g_object_new (NAUTILUS_TYPE_TAG_MANAGER, NULL);
|
||||
g_object_add_weak_pointer (G_OBJECT (tag_manager), (gpointer)&tag_manager);
|
||||
|
||||
return tag_manager;
|
||||
}
|
||||
|
||||
void nautilus_tag_manager_set_cancellable (NautilusTagManager *tag_manager,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
nautilus_tag_manager_query_favorite_files (tag_manager, cancellable);
|
||||
|
||||
tag_manager->notifier = tracker_notifier_new (NULL,
|
||||
TRACKER_NOTIFIER_FLAG_QUERY_LOCATION,
|
||||
cancellable,
|
||||
&tag_manager->notifier_error);
|
||||
|
||||
g_signal_connect (tag_manager->notifier,
|
||||
"events",
|
||||
G_CALLBACK (on_tracker_notifier_events),
|
||||
tag_manager);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
nautilus_tag_manager_init (NautilusTagManager *self)
|
||||
{
|
||||
self->favorite_files = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
(GDestroyNotify) g_free,
|
||||
(GDestroyNotify) g_free);
|
||||
}
|
57
src/nautilus-tag-manager.h
Normal file
57
src/nautilus-tag-manager.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/* nautilus-tag-manager.h
|
||||
*
|
||||
* Copyright (C) 2017 Alexandru Pandelea <alexandru.pandelea@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 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NAUTILUS_TAG_MANAGER_H
|
||||
#define NAUTILUS_TAG_MANAGER_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define NAUTILUS_TYPE_TAG_MANAGER (nautilus_tag_manager_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (NautilusTagManager, nautilus_tag_manager, NAUTILUS, TAG_MANAGER, GObject);
|
||||
|
||||
NautilusTagManager* nautilus_tag_manager_get ();
|
||||
|
||||
void nautilus_tag_manager_set_cancellable (NautilusTagManager *tag_manager,
|
||||
GCancellable *cancellable);
|
||||
|
||||
GList* nautilus_tag_manager_get_favorite_files (NautilusTagManager *self);
|
||||
|
||||
void nautilus_tag_manager_star_files (NautilusTagManager *self,
|
||||
GObject *object,
|
||||
GList *selection,
|
||||
GAsyncReadyCallback callback,
|
||||
GCancellable *cancellable);
|
||||
|
||||
void nautilus_tag_manager_unstar_files (NautilusTagManager *self,
|
||||
GObject *object,
|
||||
GList *selection,
|
||||
GAsyncReadyCallback callback,
|
||||
GCancellable *cancellable);
|
||||
|
||||
|
||||
gboolean nautilus_tag_manager_file_is_favorite (NautilusTagManager *self,
|
||||
const gchar *file_name);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
|
@ -1140,6 +1140,19 @@ places_sidebar_show_other_locations_with_flags (NautilusWindow *window,
|
|||
g_object_unref (location);
|
||||
}
|
||||
|
||||
static void
|
||||
places_sidebar_show_starred_location (NautilusWindow *window,
|
||||
GtkPlacesOpenFlags open_flags)
|
||||
{
|
||||
GFile *location;
|
||||
|
||||
location = g_file_new_for_uri ("favorites:///");
|
||||
|
||||
open_location_cb (window, location, open_flags);
|
||||
|
||||
g_object_unref (location);
|
||||
}
|
||||
|
||||
static GList *
|
||||
build_selection_list_from_gfile_list (GList *gfile_list)
|
||||
{
|
||||
|
@ -2947,6 +2960,7 @@ nautilus_window_class_init (NautilusWindowClass *class)
|
|||
gtk_widget_class_bind_template_child_private (wclass, NautilusWindow, notification_operation_close);
|
||||
|
||||
gtk_widget_class_bind_template_callback (wclass, places_sidebar_show_other_locations_with_flags);
|
||||
gtk_widget_class_bind_template_callback (wclass, places_sidebar_show_starred_location);
|
||||
|
||||
properties[PROP_DISABLE_CHROME] =
|
||||
g_param_spec_boolean ("disable-chrome",
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
<file>ui/nautilus-no-search-results.ui</file>
|
||||
<file>ui/nautilus-folder-is-empty.ui</file>
|
||||
<file>ui/nautilus-trash-is-empty.ui</file>
|
||||
<file>ui/nautilus-starred-is-empty.ui</file>
|
||||
<file>gtk/help-overlay.ui</file>
|
||||
<file>ui/nautilus-batch-rename-dialog.ui</file>
|
||||
<file alias="gtk/ui/nautilusgtkplacesview.ui">../gtk/nautilusgtkplacesview.ui</file>
|
||||
|
|
|
@ -251,6 +251,23 @@
|
|||
<attribute name="hidden-when">action-disabled</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Tags</attribute>
|
||||
<attribute name="action">view.edit-tags</attribute>
|
||||
<attribute name="hidden-when">action-disabled</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Star</attribute>
|
||||
<attribute name="action">view.star</attribute>
|
||||
<attribute name="hidden-when">action-disabled</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Unstar</attribute>
|
||||
<attribute name="action">view.unstar</attribute>
|
||||
<attribute name="hidden-when">action-disabled</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">P_roperties</attribute>
|
||||
|
|
42
src/resources/ui/nautilus-starred-is-empty.ui
Normal file
42
src/resources/ui/nautilus-starred-is-empty.ui
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkGrid" id="starred_is_empty">
|
||||
<property name="visible">False</property>
|
||||
<property name="row_spacing">12</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="icon-name">starred-symbolic</property>
|
||||
<property name="pixel-size">72</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Starred files will appear here</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
<attribute name="scale" value="1.44"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -34,7 +34,9 @@
|
|||
<property name="visible">True</property>
|
||||
<property name="populate-all">True</property>
|
||||
<property name="show-other-locations">True</property>
|
||||
<property name="show-starred-location">True</property>
|
||||
<signal name="show-other-locations-with-flags" handler="places_sidebar_show_other_locations_with_flags" object="NautilusWindow" swapped="yes" />
|
||||
<signal name="show-starred-location" handler="places_sidebar_show_starred_location" object="NautilusWindow" swapped="yes" />
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">start</property>
|
||||
|
|
Loading…
Reference in a new issue