[gnome-photos/wip/rishi/collection: 13/13] Add a new mode for importing items from an attached device
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-photos/wip/rishi/collection: 13/13] Add a new mode for importing items from an attached device
- Date: Thu, 15 Feb 2018 08:15:11 +0000 (UTC)
commit cf2516c0ba63e7a43ca397f5487b72061817b214
Author: Debarshi Ray <debarshir gnome org>
Date: Tue Jan 23 13:17:16 2018 +0100
Add a new mode for importing items from an attached device
Based on code written by Petr Štětka.
https://gitlab.gnome.org/GNOME/gnome-photos/issues/29
src/Makefile.am | 4 +
src/photos-application.c | 53 +++-
src/photos-embed.c | 109 ++++++--
src/photos-empty-results-box.c | 3 +
src/photos-item-manager.c | 118 ++++++++-
src/photos-item-manager.h | 1 +
src/photos-main-toolbar.c | 101 +++++++-
src/photos-main-window.c | 4 +
src/photos-offset-import-controller.c | 139 ++++++++++
src/photos-offset-import-controller.h | 41 +++
src/photos-preview-view.c | 4 +
src/photos-query.h | 9 +-
src/photos-search-type-manager.c | 4 +-
src/photos-selection-toolbar.c | 18 ++
src/photos-selection-toolbar.ui | 13 +
src/photos-source-manager.c | 32 ++-
src/photos-source-notification.c | 45 ++++
src/photos-tracker-import-controller.c | 457 +++++++++++++++++++++++++++++++++
src/photos-tracker-import-controller.h | 41 +++
src/photos-utils.c | 8 +
src/photos-view-container.c | 5 +
21 files changed, 1152 insertions(+), 57 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index f2ee3d30..22a33274 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -152,6 +152,8 @@ gnome_photos_SOURCES = \
photos-offset-controller.h \
photos-offset-favorites-controller.c \
photos-offset-favorites-controller.h \
+ photos-offset-import-controller.c \
+ photos-offset-import-controller.h \
photos-offset-overview-controller.c \
photos-offset-overview-controller.h \
photos-offset-search-controller.c \
@@ -287,6 +289,8 @@ gnome_photos_SOURCES = \
photos-tracker-controller.h \
photos-tracker-favorites-controller.c \
photos-tracker-favorites-controller.h \
+ photos-tracker-import-controller.c \
+ photos-tracker-import-controller.h \
photos-tracker-overview-controller.c \
photos-tracker-overview-controller.h \
photos-tracker-search-controller.c \
diff --git a/src/photos-application.c b/src/photos-application.c
index e9dd8484..598053b0 100644
--- a/src/photos-application.c
+++ b/src/photos-application.c
@@ -97,6 +97,8 @@ struct _PhotosApplication
GSimpleAction *edit_revert_action;
GSimpleAction *fs_action;
GSimpleAction *gear_action;
+ GSimpleAction *import_action;
+ GSimpleAction *import_cancel_action;
GSimpleAction *insta_action;
GSimpleAction *load_next_action;
GSimpleAction *load_previous_action;
@@ -414,9 +416,15 @@ photos_application_actions_update (PhotosApplication *self)
case PHOTOS_WINDOW_MODE_FAVORITES:
case PHOTOS_WINDOW_MODE_OVERVIEW:
case PHOTOS_WINDOW_MODE_SEARCH:
+ gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.import-cancel", null_accels);
gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.selection-mode",
cancel_accels);
break;
+ case PHOTOS_WINDOW_MODE_IMPORT:
+ gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.import-cancel", cancel_accels);
+ gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.selection-mode", null_accels);
+ break;
+
case PHOTOS_WINDOW_MODE_NONE:
case PHOTOS_WINDOW_MODE_EDIT:
case PHOTOS_WINDOW_MODE_PREVIEW:
@@ -427,6 +435,7 @@ photos_application_actions_update (PhotosApplication *self)
}
else
{
+ gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.import-cancel", null_accels);
gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.selection-mode", null_accels);
switch (mode)
@@ -434,6 +443,7 @@ photos_application_actions_update (PhotosApplication *self)
case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
case PHOTOS_WINDOW_MODE_COLLECTIONS:
case PHOTOS_WINDOW_MODE_FAVORITES:
+ case PHOTOS_WINDOW_MODE_IMPORT:
case PHOTOS_WINDOW_MODE_OVERVIEW:
case PHOTOS_WINDOW_MODE_PREVIEW:
case PHOTOS_WINDOW_MODE_SEARCH:
@@ -454,6 +464,7 @@ photos_application_actions_update (PhotosApplication *self)
if (mode == PHOTOS_WINDOW_MODE_COLLECTION_VIEW
|| mode == PHOTOS_WINDOW_MODE_COLLECTIONS
|| mode == PHOTOS_WINDOW_MODE_FAVORITES
+ || mode == PHOTOS_WINDOW_MODE_IMPORT
|| mode == PHOTOS_WINDOW_MODE_OVERVIEW
|| mode == PHOTOS_WINDOW_MODE_SEARCH)
{
@@ -493,6 +504,7 @@ photos_application_actions_update (PhotosApplication *self)
enable = ((mode == PHOTOS_WINDOW_MODE_COLLECTION_VIEW
|| mode == PHOTOS_WINDOW_MODE_COLLECTIONS
|| mode == PHOTOS_WINDOW_MODE_FAVORITES
+ || mode == PHOTOS_WINDOW_MODE_IMPORT
|| mode == PHOTOS_WINDOW_MODE_OVERVIEW
|| mode == PHOTOS_WINDOW_MODE_SEARCH)
&& n_items > 0);
@@ -500,6 +512,12 @@ photos_application_actions_update (PhotosApplication *self)
g_simple_action_set_enabled (self->sel_none_action, enable);
g_simple_action_set_enabled (self->selection_mode_action, enable);
+ enable = (mode == PHOTOS_WINDOW_MODE_IMPORT);
+ g_simple_action_set_enabled (self->import_cancel_action, enable);
+
+ enable = (mode == PHOTOS_WINDOW_MODE_IMPORT && selection != NULL);
+ g_simple_action_set_enabled (self->import_action, enable);
+
enable = (mode == PHOTOS_WINDOW_MODE_PREVIEW);
g_simple_action_set_enabled (self->load_next_action, enable);
g_simple_action_set_enabled (self->load_previous_action, enable);
@@ -833,6 +851,7 @@ photos_application_activate_item (PhotosApplication *self, GObject *item)
case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
case PHOTOS_WINDOW_MODE_COLLECTIONS:
case PHOTOS_WINDOW_MODE_FAVORITES:
+ case PHOTOS_WINDOW_MODE_IMPORT:
case PHOTOS_WINDOW_MODE_OVERVIEW:
case PHOTOS_WINDOW_MODE_SEARCH:
can_activate = TRUE;
@@ -864,6 +883,7 @@ photos_application_activate_item (PhotosApplication *self, GObject *item)
break;
case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
+ case PHOTOS_WINDOW_MODE_IMPORT:
photos_mode_controller_go_back (self->state->mode_cntrlr);
break;
@@ -1568,6 +1588,7 @@ photos_application_import_cancel (PhotosApplication *self)
photos_base_manager_set_active_object_by_id (self->state->src_mngr, PHOTOS_SOURCE_STOCK_ALL);
mode = photos_mode_controller_get_window_mode (self->state->mode_cntrlr);
+ g_return_if_fail (mode != PHOTOS_WINDOW_MODE_IMPORT);
g_return_if_fail (mode == PHOTOS_WINDOW_MODE_COLLECTIONS
|| mode == PHOTOS_WINDOW_MODE_FAVORITES
|| mode == PHOTOS_WINDOW_MODE_OVERVIEW);
@@ -1599,6 +1620,7 @@ photos_application_launch_search (PhotosApplication *self, const gchar* const *t
case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
case PHOTOS_WINDOW_MODE_COLLECTIONS:
case PHOTOS_WINDOW_MODE_FAVORITES:
+ case PHOTOS_WINDOW_MODE_IMPORT:
case PHOTOS_WINDOW_MODE_OVERVIEW:
case PHOTOS_WINDOW_MODE_SEARCH:
can_launch = TRUE;
@@ -1636,6 +1658,10 @@ photos_application_launch_search (PhotosApplication *self, const gchar* const *t
case PHOTOS_WINDOW_MODE_SEARCH:
break;
+ case PHOTOS_WINDOW_MODE_IMPORT:
+ photos_mode_controller_go_back (self->state->mode_cntrlr);
+ break;
+
case PHOTOS_WINDOW_MODE_EDIT:
case PHOTOS_WINDOW_MODE_PREVIEW:
default:
@@ -2318,6 +2344,7 @@ photos_application_window_mode_changed (PhotosApplication *self, PhotosWindowMod
case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
case PHOTOS_WINDOW_MODE_COLLECTIONS:
case PHOTOS_WINDOW_MODE_FAVORITES:
+ case PHOTOS_WINDOW_MODE_IMPORT:
case PHOTOS_WINDOW_MODE_OVERVIEW:
case PHOTOS_WINDOW_MODE_SEARCH:
item_mngr_chld = photos_item_manager_get_for_mode (PHOTOS_ITEM_MANAGER (self->state->item_mngr),
old_mode);
@@ -2336,6 +2363,7 @@ photos_application_window_mode_changed (PhotosApplication *self, PhotosWindowMod
case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
case PHOTOS_WINDOW_MODE_COLLECTIONS:
case PHOTOS_WINDOW_MODE_FAVORITES:
+ case PHOTOS_WINDOW_MODE_IMPORT:
case PHOTOS_WINDOW_MODE_OVERVIEW:
case PHOTOS_WINDOW_MODE_SEARCH:
item_mngr_chld = photos_item_manager_get_for_mode (PHOTOS_ITEM_MANAGER (self->state->item_mngr), mode);
@@ -2705,21 +2733,16 @@ photos_application_startup (GApplication *application)
self->gear_action = g_simple_action_new_stateful ("gear-menu", NULL, state);
g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (self->gear_action));
- {
- g_autoptr (GSimpleAction) action = NULL;
+ self->import_action = g_simple_action_new ("import-current", NULL);
+ g_signal_connect_swapped (self->import_action, "activate", G_CALLBACK (photos_application_import), self);
+ g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (self->import_action));
- action = g_simple_action_new ("import-current", NULL);
- g_signal_connect_swapped (action, "activate", G_CALLBACK (photos_application_import), self);
- g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (action));
- }
-
- {
- g_autoptr (GSimpleAction) action = NULL;
-
- action = g_simple_action_new ("import-cancel", NULL);
- g_signal_connect_swapped (action, "activate", G_CALLBACK (photos_application_import_cancel), self);
- g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (action));
- }
+ self->import_cancel_action = g_simple_action_new ("import-cancel", NULL);
+ g_signal_connect_swapped (self->import_cancel_action,
+ "activate",
+ G_CALLBACK (photos_application_import_cancel),
+ self);
+ g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (self->import_cancel_action));
self->insta_action = g_simple_action_new ("insta-current", G_VARIANT_TYPE_INT16);
g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (self->insta_action));
@@ -2952,6 +2975,8 @@ photos_application_dispose (GObject *object)
g_clear_object (&self->edit_revert_action);
g_clear_object (&self->fs_action);
g_clear_object (&self->gear_action);
+ g_clear_object (&self->import_action);
+ g_clear_object (&self->import_cancel_action);
g_clear_object (&self->insta_action);
g_clear_object (&self->load_next_action);
g_clear_object (&self->load_previous_action);
diff --git a/src/photos-embed.c b/src/photos-embed.c
index 09f5bf50..cbcea716 100644
--- a/src/photos-embed.c
+++ b/src/photos-embed.c
@@ -39,6 +39,7 @@
#include "photos-selection-toolbar.h"
#include "photos-spinner-box.h"
#include "photos-search-context.h"
+#include "photos-search-match.h"
#include "photos-search-type.h"
#include "photos-search-type-manager.h"
#include "photos-source.h"
@@ -70,6 +71,7 @@ struct _PhotosEmbed
GtkWidget *collection_view;
GtkWidget *collections;
GtkWidget *favorites;
+ GtkWidget *import;
GtkWidget *no_results;
GtkWidget *ntfctn_mngr;
GtkWidget *overview;
@@ -155,6 +157,10 @@ photos_embed_get_view_container_from_mode (PhotosEmbed *self, PhotosWindowMode m
view_container = self->favorites;
break;
+ case PHOTOS_WINDOW_MODE_IMPORT:
+ view_container = self->import;
+ break;
+
case PHOTOS_WINDOW_MODE_OVERVIEW:
view_container = self->overview;
break;
@@ -442,6 +448,7 @@ photos_embed_prepare_for_collection_view (PhotosEmbed *self, PhotosWindowMode ol
case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
case PHOTOS_WINDOW_MODE_EDIT:
case PHOTOS_WINDOW_MODE_FAVORITES:
+ case PHOTOS_WINDOW_MODE_IMPORT:
case PHOTOS_WINDOW_MODE_OVERVIEW:
default:
g_assert_not_reached ();
@@ -475,6 +482,17 @@ photos_embed_prepare_for_favorites (PhotosEmbed *self, PhotosWindowMode old_mode
}
+static void
+photos_embed_prepare_for_import (PhotosEmbed *self, PhotosWindowMode old_mode)
+{
+ if (old_mode == PHOTOS_WINDOW_MODE_PREVIEW)
+ photos_embed_tracker_controllers_set_frozen (self, FALSE);
+
+ photos_spinner_box_stop (PHOTOS_SPINNER_BOX (self->spinner_box));
+ gtk_stack_set_visible_child_name (GTK_STACK (self->stack), "import");
+}
+
+
static void
photos_embed_prepare_for_overview (PhotosEmbed *self, PhotosWindowMode old_mode)
{
@@ -519,38 +537,83 @@ photos_embed_query_status_changed (PhotosEmbed *self, gboolean querying)
static void
photos_embed_search_changed (PhotosEmbed *self)
{
- /* Whenever a search constraint is specified, we switch to the
- * search mode. Search is always global. If we are in
- * collection-view, we go back to the previous top-level mode and
- * then enter the search mode.
- *
- * When all constraints have been lifted we want to go back to the
- * previous top-level mode which can be either collections,
- * favorites or overview.
- *
- * The constraints are saved when entering collection-view or
- * preview from the search mode. They are restored when going back.
- * Saving and restoring doesn't cause any further mode changes.
- */
+ GMount *mount;
+ PhotosSource *source;
- self->search_changed = TRUE;
+ source = PHOTOS_SOURCE (photos_base_manager_get_active_object (self->src_mngr));
- if (photos_embed_is_search_constraint_present (self))
+ mount = photos_source_get_mount (source);
+ if (mount != NULL)
{
+ GObject *object;
PhotosWindowMode mode;
+ const gchar *search_match_id;
+ const gchar *search_type_id;
mode = photos_mode_controller_get_window_mode (self->mode_cntrlr);
+ g_return_if_fail (mode != PHOTOS_WINDOW_MODE_NONE);
+ g_return_if_fail (mode != PHOTOS_WINDOW_MODE_EDIT);
+ g_return_if_fail (mode != PHOTOS_WINDOW_MODE_IMPORT);
+ g_return_if_fail (mode != PHOTOS_WINDOW_MODE_PREVIEW);
+
+ photos_embed_block_search_changed (self);
+
if (mode == PHOTOS_WINDOW_MODE_COLLECTION_VIEW)
photos_mode_controller_go_back (self->mode_cntrlr);
- photos_mode_controller_set_window_mode (self->mode_cntrlr, PHOTOS_WINDOW_MODE_SEARCH);
+ mode = photos_mode_controller_get_window_mode (self->mode_cntrlr);
+ if (mode == PHOTOS_WINDOW_MODE_SEARCH)
+ photos_mode_controller_go_back (self->mode_cntrlr);
+
+ photos_base_manager_set_active_object (self->src_mngr, G_OBJECT (source));
+
+ object = photos_base_manager_get_active_object (self->srch_mtch_mngr);
+ search_match_id = photos_filterable_get_id (PHOTOS_FILTERABLE (object));
+ g_assert_cmpstr (search_match_id, ==, PHOTOS_SEARCH_MATCH_STOCK_ALL);
+
+ object = photos_base_manager_get_active_object (self->srch_typ_mngr);
+ search_type_id = photos_filterable_get_id (PHOTOS_FILTERABLE (object));
+ g_assert_cmpstr (search_type_id, ==, PHOTOS_SEARCH_TYPE_STOCK_ALL);
+
+ photos_mode_controller_set_window_mode (self->mode_cntrlr, PHOTOS_WINDOW_MODE_IMPORT);
+
+ photos_embed_unblock_search_changed (self);
}
else
{
- photos_mode_controller_go_back (self->mode_cntrlr);
- }
+ /* Whenever a search constraint is specified, we switch to the
+ * search mode. Search is always global. If we are in
+ * collection-view, we go back to the previous top-level mode and
+ * then enter the search mode.
+ *
+ * When all constraints have been lifted we want to go back to the
+ * previous top-level mode which can be either collections,
+ * favorites or overview.
+ *
+ * The constraints are saved when entering collection-view or
+ * preview from the search mode. They are restored when going back.
+ * Saving and restoring doesn't cause any further mode changes.
+ */
+
+ self->search_changed = TRUE;
+
+ if (photos_embed_is_search_constraint_present (self))
+ {
+ PhotosWindowMode mode;
- self->search_changed = FALSE;
+ mode = photos_mode_controller_get_window_mode (self->mode_cntrlr);
+ if (mode == PHOTOS_WINDOW_MODE_COLLECTION_VIEW)
+ photos_mode_controller_go_back (self->mode_cntrlr);
+
+ photos_mode_controller_set_window_mode (self->mode_cntrlr, PHOTOS_WINDOW_MODE_SEARCH);
+ }
+ else
+ {
+ photos_mode_controller_go_back (self->mode_cntrlr);
+ }
+
+ self->search_changed = FALSE;
+ }
}
@@ -645,6 +708,7 @@ photos_embed_window_mode_changed (PhotosModeController *mode_cntrlr,
case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
case PHOTOS_WINDOW_MODE_EDIT:
+ case PHOTOS_WINDOW_MODE_IMPORT:
case PHOTOS_WINDOW_MODE_PREVIEW:
case PHOTOS_WINDOW_MODE_SEARCH:
break;
@@ -674,6 +738,10 @@ photos_embed_window_mode_changed (PhotosModeController *mode_cntrlr,
photos_embed_prepare_for_favorites (self, old_mode);
break;
+ case PHOTOS_WINDOW_MODE_IMPORT:
+ photos_embed_prepare_for_import (self, old_mode);
+ break;
+
case PHOTOS_WINDOW_MODE_OVERVIEW:
photos_embed_prepare_for_overview (self, old_mode);
break;
@@ -763,6 +831,9 @@ photos_embed_init (PhotosEmbed *self)
name = photos_view_container_get_name (PHOTOS_VIEW_CONTAINER (self->favorites));
gtk_stack_add_titled (GTK_STACK (self->stack), self->favorites, "favorites", name);
+ self->import = photos_view_container_new (PHOTOS_WINDOW_MODE_IMPORT, _("Import"));
+ gtk_stack_add_named (GTK_STACK (self->stack), self->import, "import");
+
self->search = photos_view_container_new (PHOTOS_WINDOW_MODE_SEARCH, _("Search"));
gtk_stack_add_named (GTK_STACK (self->stack), self->search, "search");
diff --git a/src/photos-empty-results-box.c b/src/photos-empty-results-box.c
index 9db63a1c..93123a14 100644
--- a/src/photos-empty-results-box.c
+++ b/src/photos-empty-results-box.c
@@ -111,6 +111,7 @@ photos_empty_results_box_add_image (PhotosEmptyResultsBox *self)
* the relevant locations.
*/
case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
+ case PHOTOS_WINDOW_MODE_IMPORT:
case PHOTOS_WINDOW_MODE_OVERVIEW:
icon_name = "camera-photo-symbolic";
break;
@@ -155,6 +156,7 @@ photos_empty_results_box_add_primary_label (PhotosEmptyResultsBox *self)
* the relevant locations.
*/
case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
+ case PHOTOS_WINDOW_MODE_IMPORT:
case PHOTOS_WINDOW_MODE_OVERVIEW:
case PHOTOS_WINDOW_MODE_SEARCH:
text = _("No photos found");
@@ -194,6 +196,7 @@ photos_empty_results_box_add_secondary_label (PhotosEmptyResultsBox *self)
*/
case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
case PHOTOS_WINDOW_MODE_FAVORITES:
+ case PHOTOS_WINDOW_MODE_IMPORT:
break;
case PHOTOS_WINDOW_MODE_OVERVIEW:
diff --git a/src/photos-item-manager.c b/src/photos-item-manager.c
index bed73d64..77692c2e 100644
--- a/src/photos-item-manager.c
+++ b/src/photos-item-manager.c
@@ -31,6 +31,7 @@
#include "egg-counter.h"
#include "photos-debug.h"
+#include "photos-device-item.h"
#include "photos-enums.h"
#include "photos-filterable.h"
#include "photos-item-manager.h"
@@ -241,6 +242,7 @@ static void
photos_item_manager_info_updated (PhotosBaseItem *item, gpointer user_data)
{
PhotosItemManager *self = PHOTOS_ITEM_MANAGER (user_data);
+ GType base_item_type;
PhotosBaseItem *updated_item;
gboolean is_collection;
gboolean is_favorite;
@@ -252,6 +254,10 @@ photos_item_manager_info_updated (PhotosBaseItem *item, gpointer user_data)
updated_item = PHOTOS_BASE_ITEM (photos_base_manager_get_object_by_id (PHOTOS_BASE_MANAGER (self), id));
g_return_if_fail (updated_item == item);
+ base_item_type = G_OBJECT_TYPE (item);
+ if (base_item_type == PHOTOS_TYPE_DEVICE_ITEM)
+ goto out;
+
is_collection = photos_base_item_is_collection (item);
is_favorite = photos_base_item_is_favorite (item);
@@ -281,6 +287,9 @@ photos_item_manager_info_updated (PhotosBaseItem *item, gpointer user_data)
if (!is_favorite)
photos_base_manager_remove_object (self->item_mngr_chldrn[PHOTOS_WINDOW_MODE_FAVORITES], G_OBJECT
(item));
}
+
+ out:
+ return;
}
@@ -374,6 +383,34 @@ photos_item_manager_check_wait_for_changes (PhotosItemManager *self, const gchar
}
+static void
+photos_item_manager_item_created_executed_import (GObject *source_object, GAsyncResult *res, gpointer
user_data)
+{
+ g_autoptr (PhotosItemManager) self = PHOTOS_ITEM_MANAGER (user_data);
+ PhotosSingleItemJob *job_import = PHOTOS_SINGLE_ITEM_JOB (source_object);
+ TrackerSparqlCursor *cursor = NULL; /* TODO: use g_autoptr */
+
+ {
+ g_autoptr (GError) error = NULL;
+
+ cursor = photos_single_item_job_finish (job_import, res, &error);
+ if (error != NULL)
+ {
+ g_warning ("Unable to query single item: %s", error->message);
+ goto out;
+ }
+ }
+
+ if (cursor == NULL)
+ goto out;
+
+ photos_item_manager_add_item_for_mode (self, PHOTOS_TYPE_DEVICE_ITEM, PHOTOS_WINDOW_MODE_IMPORT, cursor);
+
+ out:
+ g_clear_object (&cursor);
+}
+
+
static void
photos_item_manager_item_created_executed_overview (GObject *source_object, GAsyncResult *res, gpointer
user_data)
{
@@ -447,6 +484,7 @@ photos_item_manager_item_created (PhotosItemManager *self, const gchar *urn)
GApplication *app;
PhotosItemManagerHiddenItem *old_hidden_item;
PhotosSearchContextState *state;
+ g_autoptr (PhotosSingleItemJob) job_import = NULL;
g_autoptr (PhotosSingleItemJob) job_overview = NULL;
guint wait_for_changes_size;
@@ -456,6 +494,14 @@ photos_item_manager_item_created (PhotosItemManager *self, const gchar *urn)
app = g_application_get_default ();
state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
+ job_import = photos_single_item_job_new (urn);
+ photos_single_item_job_run (job_import,
+ state,
+ PHOTOS_QUERY_FLAGS_IMPORT,
+ NULL,
+ photos_item_manager_item_created_executed_import,
+ g_object_ref (self));
+
job_overview = photos_single_item_job_new (urn);
photos_single_item_job_run (job_overview,
state,
@@ -875,6 +921,7 @@ photos_item_manager_set_active_object (PhotosBaseManager *manager, GObject *obje
g_return_val_if_fail (object != NULL, FALSE);
g_return_val_if_fail (PHOTOS_IS_BASE_ITEM (object), FALSE);
g_return_val_if_fail (self->mode != PHOTOS_WINDOW_MODE_EDIT, FALSE);
+ g_return_val_if_fail (self->mode != PHOTOS_WINDOW_MODE_IMPORT, FALSE);
is_collection = photos_base_item_is_collection (PHOTOS_BASE_ITEM (object));
if (is_collection)
@@ -1647,14 +1694,20 @@ photos_mode_controller_get_window_mode (PhotosModeController *self)
void
photos_mode_controller_go_back (PhotosModeController *self)
{
+ GAction *selection_mode_action;
+ GApplication *app;
PhotosWindowMode old_mode;
PhotosWindowMode tmp;
gboolean active_changed = FALSE;
gboolean active_collection_changed = FALSE;
+ gboolean unset_selection_mode = FALSE;
g_return_if_fail (PHOTOS_IS_MODE_CONTROLLER (self));
g_return_if_fail (!g_queue_is_empty (self->history));
+ app = g_application_get_default ();
+ selection_mode_action = g_action_map_lookup_action (G_ACTION_MAP (app), "selection-mode");
+
old_mode = (PhotosWindowMode) GPOINTER_TO_INT (g_queue_peek_head (self->history));
g_return_if_fail (old_mode != PHOTOS_WINDOW_MODE_NONE);
@@ -1679,6 +1732,20 @@ photos_mode_controller_go_back (PhotosModeController *self)
g_return_if_fail (old_mode != PHOTOS_WINDOW_MODE_PREVIEW);
break;
+ case PHOTOS_WINDOW_MODE_IMPORT:
+ {
+ g_autoptr (GVariant) state = NULL;
+
+ g_return_if_fail (old_mode == PHOTOS_WINDOW_MODE_COLLECTIONS
+ || old_mode == PHOTOS_WINDOW_MODE_FAVORITES
+ || old_mode == PHOTOS_WINDOW_MODE_OVERVIEW);
+
+ state = g_action_get_state (selection_mode_action);
+ g_return_if_fail (state != NULL);
+ g_return_if_fail (g_variant_get_boolean (state));
+ break;
+ }
+
case PHOTOS_WINDOW_MODE_PREVIEW:
g_return_if_fail (PHOTOS_IS_BASE_ITEM (self->active_object));
g_return_if_fail (self->active_object != (GObject *) self->active_collection);
@@ -1715,6 +1782,10 @@ photos_mode_controller_go_back (PhotosModeController *self)
case PHOTOS_WINDOW_MODE_EDIT:
break;
+ case PHOTOS_WINDOW_MODE_IMPORT:
+ unset_selection_mode = TRUE;
+ break;
+
case PHOTOS_WINDOW_MODE_PREVIEW:
self->load_state = PHOTOS_LOAD_STATE_NONE;
g_set_object (&self->active_object, G_OBJECT (self->active_collection));
@@ -1743,6 +1814,14 @@ photos_mode_controller_go_back (PhotosModeController *self)
break;
}
+ if (unset_selection_mode)
+ {
+ GVariant *state;
+
+ state = g_variant_new_boolean (FALSE);
+ g_action_change_state (selection_mode_action, state);
+ }
+
if (active_changed)
g_signal_emit_by_name (self, "active-changed", self->active_object);
@@ -1777,19 +1856,38 @@ photos_mode_controller_set_fullscreen (PhotosModeController *self, gboolean full
void
photos_mode_controller_set_window_mode (PhotosModeController *self, PhotosWindowMode mode)
{
+ GAction *selection_mode_action;
+ GApplication *app;
PhotosWindowMode old_mode;
+ gboolean active_changed = FALSE;
gboolean active_collection_changed = FALSE;
+ gboolean set_selection_mode = FALSE;
g_return_if_fail (PHOTOS_IS_MODE_CONTROLLER (self));
g_return_if_fail (mode != PHOTOS_WINDOW_MODE_NONE);
g_return_if_fail (mode != PHOTOS_WINDOW_MODE_COLLECTION_VIEW);
g_return_if_fail (mode != PHOTOS_WINDOW_MODE_PREVIEW);
+ app = g_application_get_default ();
+ selection_mode_action = g_action_map_lookup_action (G_ACTION_MAP (app), "selection-mode");
+
if (mode == PHOTOS_WINDOW_MODE_EDIT)
{
g_return_if_fail (self->load_state == PHOTOS_LOAD_STATE_FINISHED);
g_return_if_fail (self->mode == PHOTOS_WINDOW_MODE_PREVIEW);
}
+ else if (mode == PHOTOS_WINDOW_MODE_IMPORT)
+ {
+ g_autoptr (GVariant) state = NULL;
+
+ g_return_if_fail (self->mode == PHOTOS_WINDOW_MODE_COLLECTIONS
+ || self->mode == PHOTOS_WINDOW_MODE_FAVORITES
+ || self->mode == PHOTOS_WINDOW_MODE_OVERVIEW);
+
+ state = g_action_get_state (selection_mode_action);
+ g_return_if_fail (state != NULL);
+ g_return_if_fail (!g_variant_get_boolean (state));
+ }
else
{
g_return_if_fail (self->mode != PHOTOS_WINDOW_MODE_EDIT);
@@ -1813,11 +1911,25 @@ photos_mode_controller_set_window_mode (PhotosModeController *self, PhotosWindow
}
g_clear_object (&self->active_object);
- g_signal_emit_by_name (self, "active-changed", self->active_object);
+ active_changed = TRUE;
+ }
+
+ if (mode == PHOTOS_WINDOW_MODE_IMPORT)
+ set_selection_mode = TRUE;
- if (active_collection_changed)
- g_signal_emit (self, signals[ACTIVE_COLLECTION_CHANGED], 0, self->active_collection);
+ if (set_selection_mode)
+ {
+ GVariant *state;
+
+ state = g_variant_new_boolean (TRUE);
+ g_action_change_state (selection_mode_action, state);
}
+ if (active_changed)
+ g_signal_emit_by_name (self, "active-changed", self->active_object);
+
+ if (active_collection_changed)
+ g_signal_emit (self, signals[ACTIVE_COLLECTION_CHANGED], 0, self->active_collection);
+
g_signal_emit (self, signals[WINDOW_MODE_CHANGED], 0, mode, old_mode);
}
diff --git a/src/photos-item-manager.h b/src/photos-item-manager.h
index 05e0d087..c3eae38a 100644
--- a/src/photos-item-manager.h
+++ b/src/photos-item-manager.h
@@ -60,6 +60,7 @@ typedef enum
PHOTOS_WINDOW_MODE_COLLECTIONS,
PHOTOS_WINDOW_MODE_EDIT,
PHOTOS_WINDOW_MODE_FAVORITES,
+ PHOTOS_WINDOW_MODE_IMPORT,
PHOTOS_WINDOW_MODE_OVERVIEW,
PHOTOS_WINDOW_MODE_PREVIEW,
PHOTOS_WINDOW_MODE_SEARCH
diff --git a/src/photos-main-toolbar.c b/src/photos-main-toolbar.c
index 8de37c4f..258e07fa 100644
--- a/src/photos-main-toolbar.c
+++ b/src/photos-main-toolbar.c
@@ -28,6 +28,7 @@
#include <gtk/gtk.h>
#include <glib/gi18n.h>
+#include "photos-base-manager.h"
#include "photos-dlna-renderers-manager.h"
#include "photos-dropdown.h"
#include "photos-item-manager.h"
@@ -52,6 +53,7 @@ struct _PhotosMainToolbar
GtkWidget *selection_menu;
GtkWidget *stack_switcher;
PhotosBaseManager *item_mngr;
+ PhotosBaseManager *src_mngr;
PhotosModeController *mode_cntrlr;
PhotosRemoteDisplayManager *remote_mngr;
PhotosSelectionController *sel_cntrlr;
@@ -65,7 +67,9 @@ static void photos_main_toolbar_favorite_button_update (PhotosMainToolbar *self,
static gchar *
-photos_main_toolbar_create_selection_mode_label (PhotosMainToolbar *self, PhotosBaseItem *active_collection)
+photos_main_toolbar_create_selection_mode_label (PhotosMainToolbar *self,
+ PhotosBaseItem *active_collection,
+ PhotosSource *source)
{
GList *selection;
g_autofree gchar *label = NULL;
@@ -80,9 +84,20 @@ photos_main_toolbar_create_selection_mode_label (PhotosMainToolbar *self, Photos
label = g_strdup_printf (ngettext ("%d selected", "%d selected", length), length);
if (active_collection != NULL)
- ret_val = g_markup_printf_escaped ("<b>%s</b> (%s)", photos_base_item_get_name (active_collection),
label);
+ {
+ ret_val = g_markup_printf_escaped ("<b>%s</b> (%s)", photos_base_item_get_name (active_collection),
label);
+ }
+ else if (source != NULL)
+ {
+ const gchar *name;
+
+ name = photos_source_get_name (source);
+ ret_val = g_markup_printf_escaped ("<b>%s</b> (%s)", name, label);
+ }
else
- ret_val = g_steal_pointer (&label);
+ {
+ ret_val = g_steal_pointer (&label);
+ }
return ret_val;
}
@@ -92,6 +107,7 @@ static void
photos_main_toolbar_set_toolbar_title (PhotosMainToolbar *self)
{
PhotosBaseItem *active_collection;
+ PhotosSource *source;
PhotosWindowMode window_mode;
gboolean selection_mode;
g_autofree gchar *primary = NULL;
@@ -104,6 +120,7 @@ photos_main_toolbar_set_toolbar_title (PhotosMainToolbar *self)
g_return_if_fail (window_mode == PHOTOS_WINDOW_MODE_COLLECTION_VIEW
|| window_mode == PHOTOS_WINDOW_MODE_COLLECTIONS
|| window_mode == PHOTOS_WINDOW_MODE_FAVORITES
+ || window_mode == PHOTOS_WINDOW_MODE_IMPORT
|| window_mode == PHOTOS_WINDOW_MODE_OVERVIEW
|| window_mode == PHOTOS_WINDOW_MODE_SEARCH);
}
@@ -112,12 +129,24 @@ photos_main_toolbar_set_toolbar_title (PhotosMainToolbar *self)
g_return_if_fail (!selection_mode);
active_collection = photos_item_manager_get_active_collection (PHOTOS_ITEM_MANAGER (self->item_mngr));
+ source = PHOTOS_SOURCE (photos_base_manager_get_active_object (self->src_mngr));
+
+ if (window_mode == PHOTOS_WINDOW_MODE_IMPORT)
+ {
+ GMount *mount;
+
+ g_return_if_fail (active_collection == NULL);
+ g_return_if_fail (PHOTOS_IS_SOURCE (source));
+
+ mount = photos_source_get_mount (source);
+ g_return_if_fail (G_IS_MOUNT (mount));
+ }
switch (window_mode)
{
case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
if (selection_mode)
- primary = photos_main_toolbar_create_selection_mode_label (self, active_collection);
+ primary = photos_main_toolbar_create_selection_mode_label (self, active_collection, NULL);
else
primary = g_strdup (photos_base_item_get_name (active_collection));
break;
@@ -127,7 +156,7 @@ photos_main_toolbar_set_toolbar_title (PhotosMainToolbar *self)
case PHOTOS_WINDOW_MODE_OVERVIEW:
case PHOTOS_WINDOW_MODE_SEARCH:
if (selection_mode)
- primary = photos_main_toolbar_create_selection_mode_label (self, NULL);
+ primary = photos_main_toolbar_create_selection_mode_label (self, NULL, NULL);
break;
case PHOTOS_WINDOW_MODE_EDIT:
@@ -142,6 +171,10 @@ photos_main_toolbar_set_toolbar_title (PhotosMainToolbar *self)
break;
}
+ case PHOTOS_WINDOW_MODE_IMPORT:
+ primary = photos_main_toolbar_create_selection_mode_label (self, NULL, source);
+ break;
+
case PHOTOS_WINDOW_MODE_NONE:
default:
break;
@@ -451,6 +484,28 @@ photos_main_toolbar_populate_for_favorites (PhotosMainToolbar *self)
}
+static void
+photos_main_toolbar_populate_for_import (PhotosMainToolbar *self)
+{
+ GtkStyleContext *context;
+ GtkWidget *cancel_button;
+
+ gtk_header_bar_set_custom_title (GTK_HEADER_BAR (self->header_bar), self->selection_menu);
+ context = gtk_widget_get_style_context (self->header_bar);
+ gtk_style_context_add_class (context, "selection-mode");
+
+ cancel_button = gtk_button_new_with_label (_("Cancel"));
+ gtk_actionable_set_action_name (GTK_ACTIONABLE (cancel_button), "app.import-cancel");
+ gtk_header_bar_pack_end (GTK_HEADER_BAR (self->header_bar), cancel_button);
+
+ g_signal_connect_object (self->sel_cntrlr,
+ "selection-changed",
+ G_CALLBACK (photos_main_toolbar_set_toolbar_title),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+
static void
photos_main_toolbar_populate_for_overview (PhotosMainToolbar *self)
{
@@ -583,6 +638,7 @@ photos_main_toolbar_dispose (GObject *object)
g_clear_object (&self->remote_mngr);
g_clear_object (&self->sel_cntrlr);
g_clear_object (&self->selection_menu);
+ g_clear_object (&self->src_mngr);
g_clear_object (&self->stack_switcher);
G_OBJECT_CLASS (photos_main_toolbar_parent_class)->dispose (object);
@@ -653,6 +709,7 @@ photos_main_toolbar_init (PhotosMainToolbar *self)
self->item_mngr = g_object_ref (state->item_mngr);
self->mode_cntrlr = g_object_ref (state->mode_cntrlr);
self->sel_cntrlr = photos_selection_controller_dup_singleton ();
+ self->src_mngr = g_object_ref (state->src_mngr);
self->remote_mngr = photos_remote_display_manager_dup_singleton ();
g_signal_connect_object (self->remote_mngr,
@@ -727,21 +784,44 @@ photos_main_toolbar_is_focus (PhotosMainToolbar *self)
void
photos_main_toolbar_reset_toolbar_mode (PhotosMainToolbar *self)
{
+ PhotosWindowMode window_mode;
gboolean selection_mode;
photos_main_toolbar_clear_toolbar (self);
+ window_mode = photos_mode_controller_get_window_mode (self->mode_cntrlr);
selection_mode = photos_utils_get_selection_mode ();
if (selection_mode)
- photos_main_toolbar_populate_for_selection_mode (self);
- else
{
- PhotosWindowMode window_mode;
+ switch (window_mode)
+ {
+ case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
+ case PHOTOS_WINDOW_MODE_COLLECTIONS:
+ case PHOTOS_WINDOW_MODE_FAVORITES:
+ case PHOTOS_WINDOW_MODE_OVERVIEW:
+ case PHOTOS_WINDOW_MODE_SEARCH:
+ photos_main_toolbar_populate_for_selection_mode (self);
+ break;
- window_mode = photos_mode_controller_get_window_mode (self->mode_cntrlr);
+ case PHOTOS_WINDOW_MODE_IMPORT:
+ photos_main_toolbar_populate_for_import (self);
+ break;
+ case PHOTOS_WINDOW_MODE_NONE:
+ case PHOTOS_WINDOW_MODE_EDIT:
+ case PHOTOS_WINDOW_MODE_PREVIEW:
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+ else
+ {
switch (window_mode)
{
+ case PHOTOS_WINDOW_MODE_NONE:
+ break;
+
case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
photos_main_toolbar_populate_for_collection_view (self);
break;
@@ -770,8 +850,9 @@ photos_main_toolbar_reset_toolbar_mode (PhotosMainToolbar *self)
photos_main_toolbar_populate_for_search (self);
break;
- case PHOTOS_WINDOW_MODE_NONE:
+ case PHOTOS_WINDOW_MODE_IMPORT:
default:
+ g_assert_not_reached ();
break;
}
}
diff --git a/src/photos-main-window.c b/src/photos-main-window.c
index 2a884a8f..94b06650 100644
--- a/src/photos-main-window.c
+++ b/src/photos-main-window.c
@@ -41,6 +41,7 @@ struct _PhotosMainWindow
{
GtkApplicationWindow parent_instance;
GAction *edit_cancel;
+ GAction *import_cancel;
GAction *load_next;
GAction *load_previous;
GtkWidget *embed;
@@ -166,6 +167,7 @@ photos_main_window_go_back (PhotosMainWindow *self)
case PHOTOS_WINDOW_MODE_COLLECTIONS:
case PHOTOS_WINDOW_MODE_EDIT:
case PHOTOS_WINDOW_MODE_FAVORITES:
+ case PHOTOS_WINDOW_MODE_IMPORT:
case PHOTOS_WINDOW_MODE_OVERVIEW:
case PHOTOS_WINDOW_MODE_SEARCH:
default:
@@ -262,6 +264,7 @@ photos_main_window_key_press_event (GtkWidget *widget, GdkEventKey *event)
case PHOTOS_WINDOW_MODE_COLLECTIONS:
case PHOTOS_WINDOW_MODE_EDIT:
case PHOTOS_WINDOW_MODE_FAVORITES:
+ case PHOTOS_WINDOW_MODE_IMPORT:
case PHOTOS_WINDOW_MODE_OVERVIEW:
case PHOTOS_WINDOW_MODE_SEARCH:
handled = GDK_EVENT_PROPAGATE;
@@ -332,6 +335,7 @@ photos_main_window_constructed (GObject *object)
gtk_application_add_window (GTK_APPLICATION (app), GTK_WINDOW (self));
self->edit_cancel = g_action_map_lookup_action (G_ACTION_MAP (app), "edit-cancel");
+ self->import_cancel = g_action_map_lookup_action (G_ACTION_MAP (app), "import-cancel");
self->load_next = g_action_map_lookup_action (G_ACTION_MAP (app), "load-next");
self->load_previous = g_action_map_lookup_action (G_ACTION_MAP (app), "load-previous");
diff --git a/src/photos-offset-import-controller.c b/src/photos-offset-import-controller.c
new file mode 100644
index 00000000..37d58c1c
--- /dev/null
+++ b/src/photos-offset-import-controller.c
@@ -0,0 +1,139 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2017 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Based on code from:
+ * + Documents
+ */
+
+
+#include "config.h"
+
+#include <gio/gio.h>
+
+#include "photos-base-manager.h"
+#include "photos-filterable.h"
+#include "photos-offset-import-controller.h"
+#include "photos-query.h"
+#include "photos-query-builder.h"
+#include "photos-search-context.h"
+#include "photos-source.h"
+
+
+struct _PhotosOffsetImportController
+{
+ PhotosOffsetController parent_instance;
+ PhotosBaseManager *src_mngr;
+};
+
+
+G_DEFINE_TYPE (PhotosOffsetImportController, photos_offset_import_controller, PHOTOS_TYPE_OFFSET_CONTROLLER);
+
+
+static PhotosQuery *
+photos_offset_import_controller_get_query (PhotosOffsetController *offset_cntrlr)
+{
+ PhotosOffsetImportController *self = PHOTOS_OFFSET_IMPORT_CONTROLLER (offset_cntrlr);
+ GApplication *app;
+ GMount *mount;
+ g_autoptr (PhotosQuery) query = NULL;
+ PhotosQuery *ret_val = NULL;
+ PhotosSearchContextState *state;
+ PhotosSource *source;
+ const gchar *id;
+
+ source = PHOTOS_SOURCE (photos_base_manager_get_active_object (self->src_mngr));
+ g_return_val_if_fail (PHOTOS_IS_SOURCE (source), NULL);
+
+ id = photos_filterable_get_id (PHOTOS_FILTERABLE (source));
+ mount = photos_source_get_mount (source);
+ g_return_val_if_fail (g_strcmp0 (id, PHOTOS_SOURCE_STOCK_ALL) == 0 || G_IS_MOUNT (mount), NULL);
+
+ app = g_application_get_default ();
+ state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
+
+ if (mount != NULL)
+ query = photos_query_builder_count_query (state, PHOTOS_QUERY_FLAGS_IMPORT);
+ else
+ query = photos_query_new (state, "SELECT DISTINCT COUNT (?urn) WHERE { ?urn a rdfs:Resource FILTER
(false) }");
+
+ ret_val = g_steal_pointer (&query);
+ return ret_val;
+}
+
+
+static GObject *
+photos_offset_import_controller_constructor (GType type,
+ guint n_construct_params,
+ GObjectConstructParam *construct_params)
+{
+ static GObject *self = NULL;
+
+ if (self == NULL)
+ {
+ self = G_OBJECT_CLASS (photos_offset_import_controller_parent_class)->constructor (type,
+ n_construct_params,
+ construct_params);
+ g_object_add_weak_pointer (self, (gpointer) &self);
+ return self;
+ }
+
+ return g_object_ref (self);
+}
+
+
+static void
+photos_offset_import_controller_dispose (GObject *object)
+{
+ PhotosOffsetImportController *self = PHOTOS_OFFSET_IMPORT_CONTROLLER (object);
+
+ g_clear_object (&self->src_mngr);
+
+ G_OBJECT_CLASS (photos_offset_import_controller_parent_class)->dispose (object);
+}
+
+
+static void
+photos_offset_import_controller_init (PhotosOffsetImportController *self)
+{
+ GApplication *app;
+ PhotosSearchContextState *state;
+
+ app = g_application_get_default ();
+ state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
+
+ self->src_mngr = g_object_ref (state->src_mngr);
+}
+
+
+static void
+photos_offset_import_controller_class_init (PhotosOffsetImportControllerClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PhotosOffsetControllerClass *offset_controller_class = PHOTOS_OFFSET_CONTROLLER_CLASS (class);
+
+ object_class->constructor = photos_offset_import_controller_constructor;
+ object_class->dispose = photos_offset_import_controller_dispose;
+ offset_controller_class->get_query = photos_offset_import_controller_get_query;
+}
+
+
+PhotosOffsetController *
+photos_offset_import_controller_dup_singleton (void)
+{
+ return g_object_new (PHOTOS_TYPE_OFFSET_IMPORT_CONTROLLER, NULL);
+}
diff --git a/src/photos-offset-import-controller.h b/src/photos-offset-import-controller.h
new file mode 100644
index 00000000..c4623434
--- /dev/null
+++ b/src/photos-offset-import-controller.h
@@ -0,0 +1,41 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2017 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Based on code from:
+ * + Documents
+ */
+
+#ifndef PHOTOS_OFFSET_IMPORT_CONTROLLER_H
+#define PHOTOS_OFFSET_IMPORT_CONTROLLER_H
+
+#include "photos-offset-controller.h"
+
+G_BEGIN_DECLS
+
+#define PHOTOS_TYPE_OFFSET_IMPORT_CONTROLLER (photos_offset_import_controller_get_type ())
+G_DECLARE_FINAL_TYPE (PhotosOffsetImportController,
+ photos_offset_import_controller,
+ PHOTOS,
+ OFFSET_IMPORT_CONTROLLER,
+ PhotosOffsetController);
+
+PhotosOffsetController *photos_offset_import_controller_dup_singleton (void);
+
+G_END_DECLS
+
+#endif /* PHOTOS_OFFSET_IMPORT_CONTROLLER_H */
diff --git a/src/photos-preview-view.c b/src/photos-preview-view.c
index 5dd4b971..82f4bb10 100644
--- a/src/photos-preview-view.c
+++ b/src/photos-preview-view.c
@@ -908,6 +908,9 @@ photos_preview_view_window_mode_changed (PhotosPreviewView *self, PhotosWindowMo
photos_preview_nav_buttons_hide (self->nav_buttons);
break;
+ case PHOTOS_WINDOW_MODE_IMPORT:
+ break;
+
case PHOTOS_WINDOW_MODE_PREVIEW:
gtk_revealer_set_reveal_child (GTK_REVEALER (self->revealer), FALSE);
photos_edit_palette_hide_details (PHOTOS_EDIT_PALETTE (self->palette));
@@ -1427,6 +1430,7 @@ photos_preview_view_set_mode (PhotosPreviewView *self, PhotosWindowMode old_mode
g_return_if_fail (PHOTOS_IS_PREVIEW_VIEW (self));
g_return_if_fail (old_mode != PHOTOS_WINDOW_MODE_NONE);
g_return_if_fail (old_mode != PHOTOS_WINDOW_MODE_EDIT);
+ g_return_if_fail (old_mode != PHOTOS_WINDOW_MODE_IMPORT);
g_return_if_fail (old_mode != PHOTOS_WINDOW_MODE_PREVIEW);
photos_preview_nav_buttons_set_auto_hide (self->nav_buttons, TRUE);
diff --git a/src/photos-query.h b/src/photos-query.h
index c69249b0..95b03cc5 100644
--- a/src/photos-query.h
+++ b/src/photos-query.h
@@ -66,10 +66,11 @@ typedef enum
PHOTOS_QUERY_FLAGS_UNFILTERED = 1 << 0,
PHOTOS_QUERY_FLAGS_COLLECTIONS = 1 << 1,
PHOTOS_QUERY_FLAGS_FAVORITES = 1 << 2,
- PHOTOS_QUERY_FLAGS_LOCAL = 1 << 3,
- PHOTOS_QUERY_FLAGS_OVERVIEW = 1 << 4,
- PHOTOS_QUERY_FLAGS_SEARCH = 1 << 5,
- PHOTOS_QUERY_FLAGS_UNLIMITED = 1 << 6
+ PHOTOS_QUERY_FLAGS_IMPORT = 1 << 3,
+ PHOTOS_QUERY_FLAGS_LOCAL = 1 << 4,
+ PHOTOS_QUERY_FLAGS_OVERVIEW = 1 << 5,
+ PHOTOS_QUERY_FLAGS_SEARCH = 1 << 6,
+ PHOTOS_QUERY_FLAGS_UNLIMITED = 1 << 7
} PhotosQueryFlags;
extern const gchar *PHOTOS_QUERY_COLLECTIONS_IDENTIFIER;
diff --git a/src/photos-search-type-manager.c b/src/photos-search-type-manager.c
index 25f856e9..4afd1b4a 100644
--- a/src/photos-search-type-manager.c
+++ b/src/photos-search-type-manager.c
@@ -58,7 +58,7 @@ photos_search_type_manager_get_filter (PhotosBaseManager *mngr, gint flags)
search_type = photos_base_manager_get_object_by_id (mngr, PHOTOS_SEARCH_TYPE_STOCK_COLLECTIONS);
else if (flags & PHOTOS_QUERY_FLAGS_FAVORITES)
search_type = photos_base_manager_get_object_by_id (mngr, PHOTOS_SEARCH_TYPE_STOCK_FAVORITES);
- else if (flags & PHOTOS_QUERY_FLAGS_OVERVIEW)
+ else if (flags & PHOTOS_QUERY_FLAGS_IMPORT || flags & PHOTOS_QUERY_FLAGS_OVERVIEW)
search_type = photos_base_manager_get_object_by_id (mngr, PHOTOS_SEARCH_TYPE_STOCK_PHOTOS);
else if (flags & PHOTOS_QUERY_FLAGS_SEARCH)
search_type = photos_base_manager_get_active_object (mngr);
@@ -79,7 +79,7 @@ photos_search_type_manager_get_where (PhotosBaseManager *mngr, gint flags)
search_type = photos_base_manager_get_object_by_id (mngr, PHOTOS_SEARCH_TYPE_STOCK_COLLECTIONS);
else if (flags & PHOTOS_QUERY_FLAGS_FAVORITES)
search_type = photos_base_manager_get_object_by_id (mngr, PHOTOS_SEARCH_TYPE_STOCK_FAVORITES);
- else if (flags & PHOTOS_QUERY_FLAGS_OVERVIEW)
+ else if (flags & PHOTOS_QUERY_FLAGS_IMPORT || flags & PHOTOS_QUERY_FLAGS_OVERVIEW)
search_type = photos_base_manager_get_object_by_id (mngr, PHOTOS_SEARCH_TYPE_STOCK_PHOTOS);
else if (flags & PHOTOS_QUERY_FLAGS_SEARCH)
search_type = photos_base_manager_get_active_object (mngr);
diff --git a/src/photos-selection-toolbar.c b/src/photos-selection-toolbar.c
index ff0e6fb7..24931e89 100644
--- a/src/photos-selection-toolbar.c
+++ b/src/photos-selection-toolbar.c
@@ -46,6 +46,7 @@ struct _PhotosSelectionToolbar
GtkWidget *toolbar_collection;
GtkWidget *toolbar_export;
GtkWidget *toolbar_favorite;
+ GtkWidget *toolbar_import;
GtkWidget *toolbar_open;
GtkWidget *toolbar_print;
GtkWidget *toolbar_properties;
@@ -205,6 +206,7 @@ photos_selection_toolbar_set_item_visibility (PhotosSelectionToolbar *self)
gboolean show_collection;
gboolean show_export;
gboolean show_favorite;
+ gboolean show_import;
gboolean show_open;
gboolean show_print;
gboolean show_properties;
@@ -229,6 +231,7 @@ photos_selection_toolbar_set_item_visibility (PhotosSelectionToolbar *self)
show_collection = TRUE;
show_export = TRUE;
show_favorite = TRUE;
+ show_import = FALSE;
show_open = TRUE;
show_print = TRUE;
show_properties = TRUE;
@@ -237,6 +240,19 @@ photos_selection_toolbar_set_item_visibility (PhotosSelectionToolbar *self)
show_trash = TRUE;
break;
+ case PHOTOS_WINDOW_MODE_IMPORT:
+ show_collection = FALSE;
+ show_export = FALSE;
+ show_favorite = FALSE;
+ show_import = TRUE;
+ show_open = FALSE;
+ show_print = FALSE;
+ show_properties = FALSE;
+ show_separator = FALSE;
+ show_share = FALSE;
+ show_trash = FALSE;
+ break;
+
case PHOTOS_WINDOW_MODE_NONE:
case PHOTOS_WINDOW_MODE_EDIT:
case PHOTOS_WINDOW_MODE_PREVIEW:
@@ -307,6 +323,7 @@ photos_selection_toolbar_set_item_visibility (PhotosSelectionToolbar *self)
gtk_widget_set_visible (self->toolbar_collection, show_collection);
gtk_widget_set_visible (self->toolbar_export, show_export);
gtk_widget_set_visible (self->toolbar_favorite, show_favorite);
+ gtk_widget_set_visible (self->toolbar_import, show_import);
gtk_widget_set_visible (self->toolbar_open, show_open);
gtk_widget_set_visible (self->toolbar_print, show_print);
gtk_widget_set_visible (self->toolbar_properties, show_properties);
@@ -433,6 +450,7 @@ photos_selection_toolbar_class_init (PhotosSelectionToolbarClass *class)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Photos/selection-toolbar.ui");
gtk_widget_class_bind_template_child (widget_class, PhotosSelectionToolbar, toolbar_export);
gtk_widget_class_bind_template_child (widget_class, PhotosSelectionToolbar, toolbar_favorite);
+ gtk_widget_class_bind_template_child (widget_class, PhotosSelectionToolbar, toolbar_import);
gtk_widget_class_bind_template_child (widget_class, PhotosSelectionToolbar, toolbar_open);
gtk_widget_class_bind_template_child (widget_class, PhotosSelectionToolbar, toolbar_print);
gtk_widget_class_bind_template_child (widget_class, PhotosSelectionToolbar, toolbar_properties);
diff --git a/src/photos-selection-toolbar.ui b/src/photos-selection-toolbar.ui
index bb7522a5..7e7aa466 100644
--- a/src/photos-selection-toolbar.ui
+++ b/src/photos-selection-toolbar.ui
@@ -106,6 +106,19 @@
<property name="pack_type">end</property>
</packing>
</child>
+ <child>
+ <object class="GtkButton" id="toolbar_import">
+ <property name="label" translatable="yes">Add to Photos</property>
+ <property name="no-show-all">1</property>
+ <property name="action_name">app.import-current</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
<child>
<object class="GtkButton" id="toolbar_collection">
<property name="label" translatable="yes">Add to Album</property>
diff --git a/src/photos-source-manager.c b/src/photos-source-manager.c
index bdd75bf9..c0c7d930 100644
--- a/src/photos-source-manager.c
+++ b/src/photos-source-manager.c
@@ -69,22 +69,44 @@ photos_source_manager_get_filter (PhotosBaseManager *mngr, gint flags)
{
GApplication *app;
GObject *source;
+ const gchar *empty_filter = "(false)";
const gchar *id;
gchar *filter;
app = g_application_get_default ();
if (photos_application_get_empty_results (PHOTOS_APPLICATION (app)))
{
- filter = g_strdup ("(false)");
+ filter = g_strdup (empty_filter);
goto out;
}
- if (flags & PHOTOS_QUERY_FLAGS_LOCAL)
- source = photos_base_manager_get_object_by_id (mngr, PHOTOS_SOURCE_STOCK_LOCAL);
+ if (flags & PHOTOS_QUERY_FLAGS_IMPORT)
+ {
+ GMount *mount;
+
+ source = photos_base_manager_get_active_object (mngr);
+ mount = photos_source_get_mount (PHOTOS_SOURCE (source));
+ if (mount == NULL)
+ source = NULL;
+ }
+ else if (flags & PHOTOS_QUERY_FLAGS_LOCAL)
+ {
+ source = photos_base_manager_get_object_by_id (mngr, PHOTOS_SOURCE_STOCK_LOCAL);
+ }
else if (flags & PHOTOS_QUERY_FLAGS_SEARCH)
- source = photos_base_manager_get_active_object (mngr);
+ {
+ source = photos_base_manager_get_active_object (mngr);
+ }
else
- source = photos_base_manager_get_object_by_id (mngr, PHOTOS_SOURCE_STOCK_ALL);
+ {
+ source = photos_base_manager_get_object_by_id (mngr, PHOTOS_SOURCE_STOCK_ALL);
+ }
+
+ if (source == NULL)
+ {
+ filter = g_strdup (empty_filter);
+ goto out;
+ }
id = photos_filterable_get_id (PHOTOS_FILTERABLE (source));
if (g_strcmp0 (id, PHOTOS_SOURCE_STOCK_ALL) == 0)
diff --git a/src/photos-source-notification.c b/src/photos-source-notification.c
index 26b87c56..02858cb8 100644
--- a/src/photos-source-notification.c
+++ b/src/photos-source-notification.c
@@ -25,6 +25,7 @@
#include "photos-base-manager.h"
#include "photos-filterable.h"
+#include "photos-item-manager.h"
#include "photos-search-context.h"
#include "photos-source-notification.h"
#include "photos-utils.h"
@@ -34,6 +35,7 @@ struct _PhotosSourceNotification
{
GtkGrid parent_instance;
PhotosBaseManager *src_mngr;
+ PhotosModeController *mode_cntrlr;
PhotosSource *source;
};
@@ -126,6 +128,41 @@ photos_source_notification_settings_clicked (PhotosSourceNotification *self)
}
+static void
+photos_source_notification_window_mode_changed (PhotosSourceNotification *self,
+ PhotosWindowMode mode,
+ PhotosWindowMode old_mode)
+{
+ GMount *mount;
+
+ g_return_if_fail (PHOTOS_IS_SOURCE_NOTIFICATION (self));
+
+ mount = photos_source_get_mount (self->source);
+ g_return_if_fail (G_IS_MOUNT (mount));
+
+ switch (mode)
+ {
+ case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
+ case PHOTOS_WINDOW_MODE_COLLECTIONS:
+ case PHOTOS_WINDOW_MODE_EDIT:
+ case PHOTOS_WINDOW_MODE_FAVORITES:
+ case PHOTOS_WINDOW_MODE_OVERVIEW:
+ case PHOTOS_WINDOW_MODE_PREVIEW:
+ case PHOTOS_WINDOW_MODE_SEARCH:
+ break;
+
+ case PHOTOS_WINDOW_MODE_IMPORT:
+ photos_source_notification_close (self);
+ break;
+
+ case PHOTOS_WINDOW_MODE_NONE:
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+
static void
photos_source_notification_constructed (GObject *object)
{
@@ -186,6 +223,12 @@ photos_source_notification_constructed (GObject *object)
"notify::sensitive",
G_CALLBACK (photos_source_notification_import_notify_sensitive),
NULL);
+
+ g_signal_connect_object (self->mode_cntrlr,
+ "window-mode-changed",
+ G_CALLBACK (photos_source_notification_window_mode_changed),
+ self,
+ G_CONNECT_SWAPPED);
}
else if (goa_object != NULL)
{
@@ -232,6 +275,7 @@ photos_source_notification_dispose (GObject *object)
PhotosSourceNotification *self = PHOTOS_SOURCE_NOTIFICATION (object);
g_clear_object (&self->src_mngr);
+ g_clear_object (&self->mode_cntrlr);
g_clear_object (&self->source);
G_OBJECT_CLASS (photos_source_notification_parent_class)->dispose (object);
@@ -284,6 +328,7 @@ photos_source_notification_init (PhotosSourceNotification *self)
state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
self->src_mngr = g_object_ref (state->src_mngr);
+ self->mode_cntrlr = g_object_ref (state->mode_cntrlr);
}
diff --git a/src/photos-tracker-import-controller.c b/src/photos-tracker-import-controller.c
new file mode 100644
index 00000000..c7c32d31
--- /dev/null
+++ b/src/photos-tracker-import-controller.c
@@ -0,0 +1,457 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2018 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Based on code from:
+ * + Documents
+ */
+
+
+#include "config.h"
+
+#include <gio/gio.h>
+#include <libtracker-control/tracker-control.h>
+
+#include "photos-base-manager.h"
+#include "photos-debug.h"
+#include "photos-device-item.h"
+#include "photos-item-manager.h"
+#include "photos-offset-import-controller.h"
+#include "photos-query-builder.h"
+#include "photos-search-context.h"
+#include "photos-tracker-import-controller.h"
+#include "photos-utils.h"
+
+
+struct _PhotosTrackerImportController
+{
+ PhotosTrackerController parent_instance;
+ GCancellable *cancellable;
+ GQueue *pending_directories;
+ PhotosBaseManager *item_mngr;
+ PhotosBaseManager *src_mngr;
+ PhotosOffsetController *offset_cntrlr;
+ TrackerMinerManager *manager;
+};
+
+
+G_DEFINE_TYPE_WITH_CODE (PhotosTrackerImportController,
+ photos_tracker_import_controller,
+ PHOTOS_TYPE_TRACKER_CONTROLLER,
+ photos_utils_ensure_extension_points ();
+ g_io_extension_point_implement (PHOTOS_TRACKER_CONTROLLER_EXTENSION_POINT_NAME,
+ g_define_type_id,
+ "import",
+ 0));
+
+
+static const gchar *IMPORTABLE_MIME_TYPES[] =
+{
+ "image/jpeg",
+ "image/png",
+ "image/x-dcraw"
+};
+
+
+static void photos_tracker_import_controller_enumerate_children (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data);
+
+
+static void
+photos_tracker_import_controller_index (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ g_autoptr (GFile) file = G_FILE (user_data);
+ TrackerMinerManager *manager = TRACKER_MINER_MANAGER (source_object);
+
+ {
+ g_autoptr (GError) error = NULL;
+
+ if (!tracker_miner_manager_index_file_for_process_finish (manager, res, &error))
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_autofree gchar *uri = NULL;
+
+ uri = g_file_get_uri (file);
+ g_warning ("Unable to index %s: %s", uri, error->message);
+ }
+ }
+ }
+}
+
+
+static void
+photos_tracker_import_controller_next_files (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ PhotosTrackerImportController *self;
+ GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
+ GList *infos = NULL;
+ GList *l;
+
+ {
+ g_autoptr (GError) error = NULL;
+
+ infos = g_file_enumerator_next_files_finish (enumerator, res, &error);
+ if (error != NULL)
+ {
+ GFile *directory;
+ g_autofree gchar *uri = NULL;
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ goto out;
+
+ directory = g_file_enumerator_get_container (enumerator);
+ uri = g_file_get_uri (directory);
+ g_warning ("Unable to read files from %s: %s", uri, error->message);
+ }
+ }
+
+ self = PHOTOS_TRACKER_IMPORT_CONTROLLER (user_data);
+
+ if (infos == NULL)
+ {
+ GFile *directory;
+ GFile *queue_head;
+
+ directory = g_file_enumerator_get_container (enumerator);
+ queue_head = G_FILE (g_queue_pop_head (self->pending_directories));
+ g_assert_true (g_file_equal (directory, queue_head));
+
+ if (!g_queue_is_empty (self->pending_directories))
+ {
+ g_autofree gchar *uri = NULL;
+
+ directory = G_FILE (g_queue_peek_head (self->pending_directories));
+
+ uri = g_file_get_uri (directory);
+ photos_debug (PHOTOS_DEBUG_IMPORT, "Enumerating device directory %s", uri);
+
+ g_file_enumerate_children_async (directory,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE","
+ G_FILE_ATTRIBUTE_STANDARD_NAME","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ G_PRIORITY_DEFAULT,
+ self->cancellable,
+ photos_tracker_import_controller_enumerate_children,
+ self);
+ }
+ }
+ else
+ {
+ for (l = infos; l != NULL; l = l->next)
+ {
+ g_autoptr (GFile) file = NULL;
+ GFileInfo *info = G_FILE_INFO (l->data);
+ GFileType file_type;
+ g_autofree gchar *uri = NULL;
+
+ file = g_file_enumerator_get_child (enumerator, info);
+ uri = g_file_get_uri (file);
+
+ file_type = g_file_info_get_file_type (info);
+
+ switch (file_type)
+ {
+ case G_FILE_TYPE_DIRECTORY:
+ photos_debug (PHOTOS_DEBUG_IMPORT, "Queued device directory %s", uri);
+ g_queue_push_tail (self->pending_directories, g_object_ref (file));
+ break;
+
+ case G_FILE_TYPE_REGULAR:
+ {
+ const gchar *mime_type;
+ gboolean indexing = FALSE;
+ guint i;
+ guint n_elements;
+
+ mime_type = g_file_info_get_content_type (info);
+ n_elements = G_N_ELEMENTS (IMPORTABLE_MIME_TYPES);
+ for (i = 0; i < n_elements && !indexing; i++)
+ {
+ if (g_content_type_equals (mime_type, IMPORTABLE_MIME_TYPES[i])
+ || g_content_type_is_a (mime_type, IMPORTABLE_MIME_TYPES[i]))
+ {
+ tracker_miner_manager_index_file_for_process_async (self->manager,
+ file,
+ self->cancellable,
+
photos_tracker_import_controller_index,
+ g_object_ref (file));
+ indexing = TRUE;
+ }
+ }
+
+ photos_debug (PHOTOS_DEBUG_IMPORT, "%s device file %s", indexing ? "Indexing" : "Skipped",
uri);
+ break;
+ }
+
+ case G_FILE_TYPE_UNKNOWN:
+ case G_FILE_TYPE_MOUNTABLE:
+ case G_FILE_TYPE_SHORTCUT:
+ case G_FILE_TYPE_SPECIAL:
+ case G_FILE_TYPE_SYMBOLIC_LINK:
+ default:
+ break;
+ }
+ }
+
+ g_file_enumerator_next_files_async (enumerator,
+ 5,
+ G_PRIORITY_DEFAULT,
+ self->cancellable,
+ photos_tracker_import_controller_next_files,
+ self);
+ }
+
+ out:
+ g_list_free_full (infos, g_object_unref);
+}
+
+
+static void
+photos_tracker_import_controller_enumerate_children (GObject *source_object, GAsyncResult *res, gpointer
user_data)
+{
+ PhotosTrackerImportController *self;
+ GFile *directory = G_FILE (source_object);
+ g_autoptr (GFileEnumerator) enumerator = NULL;
+
+ {
+ g_autoptr (GError) error = NULL;
+
+ enumerator = g_file_enumerate_children_finish (directory, res, &error);
+ if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_autofree gchar *uri = NULL;
+
+ uri = g_file_get_uri (directory);
+ g_warning ("Unable to get an enumerator for %s: %s", uri, error->message);
+ }
+
+ goto out;
+ }
+ }
+
+ self = PHOTOS_TRACKER_IMPORT_CONTROLLER (user_data);
+
+ g_file_enumerator_next_files_async (enumerator,
+ 5,
+ G_PRIORITY_DEFAULT,
+ self->cancellable,
+ photos_tracker_import_controller_next_files,
+ self);
+
+ out:
+ return;
+}
+
+
+static void
+photos_tracker_import_controller_source_active_changed (PhotosTrackerImportController *self, GObject *source)
+{
+ GMount *mount;
+ gboolean frozen;
+
+ g_return_if_fail (PHOTOS_IS_TRACKER_IMPORT_CONTROLLER (self));
+ g_return_if_fail (PHOTOS_IS_SOURCE (source));
+ g_return_if_fail (PHOTOS_IS_ITEM_MANAGER (self->item_mngr));
+
+ mount = photos_source_get_mount (PHOTOS_SOURCE (source));
+ frozen = mount == NULL;
+ photos_tracker_controller_set_frozen (PHOTOS_TRACKER_CONTROLLER (self), frozen);
+
+ if (mount == NULL)
+ {
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+ self->cancellable = g_cancellable_new ();
+
+ g_queue_free_full (self->pending_directories, g_object_unref);
+ self->pending_directories = g_queue_new ();
+
+ photos_item_manager_clear (PHOTOS_ITEM_MANAGER (self->item_mngr), PHOTOS_WINDOW_MODE_IMPORT);
+ }
+ else
+ {
+ g_return_if_fail (g_queue_is_empty (self->pending_directories));
+
+ if (G_LIKELY (self->manager != NULL))
+ {
+ g_autoptr (GFile) root = NULL;
+ g_autofree gchar *uri = NULL;
+
+ root = g_mount_get_root (mount);
+ g_queue_push_tail (self->pending_directories, g_object_ref (root));
+
+ uri = g_file_get_uri (root);
+ photos_debug (PHOTOS_DEBUG_IMPORT, "Enumerating device directory %s", uri);
+
+ g_file_enumerate_children_async (root,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE","
+ G_FILE_ATTRIBUTE_STANDARD_NAME","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ G_PRIORITY_DEFAULT,
+ self->cancellable,
+ photos_tracker_import_controller_enumerate_children,
+ self);
+ }
+
+ photos_tracker_controller_refresh_for_object (PHOTOS_TRACKER_CONTROLLER (self));
+ }
+}
+
+
+static PhotosOffsetController *
+photos_tracker_import_controller_get_offset_controller (PhotosTrackerController *trk_cntrlr)
+{
+ PhotosTrackerImportController *self = PHOTOS_TRACKER_IMPORT_CONTROLLER (trk_cntrlr);
+ return g_object_ref (self->offset_cntrlr);
+}
+
+
+static PhotosQuery *
+photos_tracker_import_controller_get_query (PhotosTrackerController *trk_cntrlr)
+{
+ PhotosTrackerImportController *self = PHOTOS_TRACKER_IMPORT_CONTROLLER (trk_cntrlr);
+ GApplication *app;
+ PhotosSearchContextState *state;
+
+ app = g_application_get_default ();
+ state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
+
+ return photos_query_builder_global_query (state, PHOTOS_QUERY_FLAGS_IMPORT, self->offset_cntrlr);
+}
+
+
+static GObject *
+photos_tracker_import_controller_constructor (GType type,
+ guint n_construct_params,
+ GObjectConstructParam *construct_params)
+{
+ static GObject *self = NULL;
+
+ if (self == NULL)
+ {
+ self = G_OBJECT_CLASS (photos_tracker_import_controller_parent_class)->constructor (type,
+ n_construct_params,
+ construct_params);
+ g_object_add_weak_pointer (self, (gpointer) &self);
+ return self;
+ }
+
+ return g_object_ref (self);
+}
+
+
+static void
+photos_tracker_import_controller_dispose (GObject *object)
+{
+ PhotosTrackerImportController *self = PHOTOS_TRACKER_IMPORT_CONTROLLER (object);
+
+ if (self->cancellable != NULL)
+ {
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+ }
+
+ if (self->pending_directories != NULL)
+ {
+ g_queue_free_full (self->pending_directories, g_object_unref);
+ self->pending_directories = NULL;
+ }
+
+ g_clear_object (&self->src_mngr);
+ g_clear_object (&self->offset_cntrlr);
+ g_clear_object (&self->manager);
+
+ G_OBJECT_CLASS (photos_tracker_import_controller_parent_class)->dispose (object);
+}
+
+
+static void
+photos_tracker_import_controller_finalize (GObject *object)
+{
+ PhotosTrackerImportController *self = PHOTOS_TRACKER_IMPORT_CONTROLLER (object);
+
+ if (self->item_mngr != NULL)
+ g_object_remove_weak_pointer (G_OBJECT (self->item_mngr), (gpointer *) &self->item_mngr);
+
+ G_OBJECT_CLASS (photos_tracker_import_controller_parent_class)->finalize (object);
+}
+
+
+static void
+photos_tracker_import_controller_init (PhotosTrackerImportController *self)
+{
+ GApplication *app;
+ PhotosSearchContextState *state;
+
+ app = g_application_get_default ();
+ state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
+
+ self->cancellable = g_cancellable_new ();
+ self->pending_directories = g_queue_new ();
+
+ self->item_mngr = state->item_mngr;
+ g_object_add_weak_pointer (G_OBJECT (self->item_mngr), (gpointer *) &self->item_mngr);
+
+ self->src_mngr = g_object_ref (state->src_mngr);
+ g_signal_connect_object (self->src_mngr,
+ "active-changed",
+ G_CALLBACK (photos_tracker_import_controller_source_active_changed),
+ self,
+ G_CONNECT_AFTER | G_CONNECT_SWAPPED);
+
+ self->offset_cntrlr = photos_offset_import_controller_dup_singleton ();
+
+ {
+ g_autoptr (GError) error = NULL;
+
+ self->manager = tracker_miner_manager_new_full (FALSE, &error);
+ if (error != NULL)
+ g_warning ("Unable to create a TrackerMinerManager, indexing attached devices won't work: %s",
error->message);
+ }
+}
+
+
+static void
+photos_tracker_import_controller_class_init (PhotosTrackerImportControllerClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PhotosTrackerControllerClass *tracker_controller_class = PHOTOS_TRACKER_CONTROLLER_CLASS (class);
+
+ tracker_controller_class->base_item_type = PHOTOS_TYPE_DEVICE_ITEM;
+
+ object_class->constructor = photos_tracker_import_controller_constructor;
+ object_class->dispose = photos_tracker_import_controller_dispose;
+ object_class->finalize = photos_tracker_import_controller_finalize;
+ tracker_controller_class->get_offset_controller = photos_tracker_import_controller_get_offset_controller;
+ tracker_controller_class->get_query = photos_tracker_import_controller_get_query;
+}
+
+
+PhotosTrackerController *
+photos_tracker_import_controller_dup_singleton (void)
+{
+ return g_object_new (PHOTOS_TYPE_TRACKER_IMPORT_CONTROLLER,
+ "delay-start", TRUE,
+ "mode", PHOTOS_WINDOW_MODE_IMPORT,
+ NULL);
+}
diff --git a/src/photos-tracker-import-controller.h b/src/photos-tracker-import-controller.h
new file mode 100644
index 00000000..3c9ada8a
--- /dev/null
+++ b/src/photos-tracker-import-controller.h
@@ -0,0 +1,41 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2018 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Based on code from:
+ * + Documents
+ */
+
+#ifndef PHOTOS_TRACKER_IMPORT_CONTROLLER_H
+#define PHOTOS_TRACKER_IMPORT_CONTROLLER_H
+
+#include "photos-tracker-controller.h"
+
+G_BEGIN_DECLS
+
+#define PHOTOS_TYPE_TRACKER_IMPORT_CONTROLLER (photos_tracker_import_controller_get_type ())
+G_DECLARE_FINAL_TYPE (PhotosTrackerImportController,
+ photos_tracker_import_controller,
+ PHOTOS,
+ TRACKER_IMPORT_CONTROLLER,
+ PhotosTrackerController);
+
+PhotosTrackerController *photos_tracker_import_controller_dup_singleton (void);
+
+G_END_DECLS
+
+#endif /* PHOTOS_TRACKER_IMPORT_CONTROLLER_H */
diff --git a/src/photos-utils.c b/src/photos-utils.c
index c129ebc5..d6a020a0 100644
--- a/src/photos-utils.c
+++ b/src/photos-utils.c
@@ -44,6 +44,7 @@
#include "photos-offset-collection-view-controller.h"
#include "photos-offset-collections-controller.h"
#include "photos-offset-favorites-controller.h"
+#include "photos-offset-import-controller.h"
#include "photos-offset-overview-controller.h"
#include "photos-offset-search-controller.h"
#include "photos-query.h"
@@ -61,6 +62,7 @@
#include "photos-tracker-collection-view-controller.h"
#include "photos-tracker-collections-controller.h"
#include "photos-tracker-favorites-controller.h"
+#include "photos-tracker-import-controller.h"
#include "photos-tracker-overview-controller.h"
#include "photos-tracker-queue.h"
#include "photos-tracker-search-controller.h"
@@ -709,6 +711,7 @@ photos_utils_ensure_builtins (void)
g_type_ensure (PHOTOS_TYPE_TRACKER_COLLECTION_VIEW_CONTROLLER);
g_type_ensure (PHOTOS_TYPE_TRACKER_COLLECTIONS_CONTROLLER);
g_type_ensure (PHOTOS_TYPE_TRACKER_FAVORITES_CONTROLLER);
+ g_type_ensure (PHOTOS_TYPE_TRACKER_IMPORT_CONTROLLER);
g_type_ensure (PHOTOS_TYPE_TRACKER_OVERVIEW_CONTROLLER);
g_type_ensure (PHOTOS_TYPE_TRACKER_SEARCH_CONTROLLER);
@@ -866,6 +869,11 @@ photos_utils_get_controller (PhotosWindowMode mode,
trk_cntrlr = photos_tracker_favorites_controller_dup_singleton ();
break;
+ case PHOTOS_WINDOW_MODE_IMPORT:
+ offset_cntrlr = photos_offset_import_controller_dup_singleton ();
+ trk_cntrlr = photos_tracker_import_controller_dup_singleton ();
+ break;
+
case PHOTOS_WINDOW_MODE_OVERVIEW:
offset_cntrlr = photos_offset_overview_controller_dup_singleton ();
trk_cntrlr = photos_tracker_overview_controller_dup_singleton ();
diff --git a/src/photos-view-container.c b/src/photos-view-container.c
index 3fccb91a..b2113b12 100644
--- a/src/photos-view-container.c
+++ b/src/photos-view-container.c
@@ -120,6 +120,10 @@ photos_view_container_get_show_primary_text (PhotosViewContainer *self)
ret_val = FALSE;
break;
+ case PHOTOS_WINDOW_MODE_IMPORT:
+ ret_val = FALSE;
+ break;
+
case PHOTOS_WINDOW_MODE_OVERVIEW:
ret_val = FALSE;
break;
@@ -287,6 +291,7 @@ photos_view_container_window_mode_changed (PhotosViewContainer *self,
case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
case PHOTOS_WINDOW_MODE_COLLECTIONS:
case PHOTOS_WINDOW_MODE_FAVORITES:
+ case PHOTOS_WINDOW_MODE_IMPORT:
case PHOTOS_WINDOW_MODE_OVERVIEW:
case PHOTOS_WINDOW_MODE_SEARCH:
photos_view_container_connect_view (self);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]