[gnome-photos/wip/rishi/collection: 4/5] Add a new mode for viewing the contents of a collection



commit 3471fd5f0da0e5152df667c5fb6d9f247f391f6b
Author: Debarshi Ray <debarshir gnome org>
Date:   Thu Jul 27 15:11:41 2017 +0200

    Add a new mode for viewing the contents of a collection
    
    https://bugzilla.gnome.org/show_bug.cgi?id=786936

 src/Makefile.am                                 |    4 +
 src/photos-application.c                        |    3 +-
 src/photos-embed.c                              |  126 ++++++++++-----
 src/photos-empty-results-box.c                  |    8 +
 src/photos-item-manager.c                       |   59 ++++---
 src/photos-item-manager.h                       |    3 +-
 src/photos-main-toolbar.c                       |  133 +++++-----------
 src/photos-main-window.c                        |   14 +-
 src/photos-offset-collection-view-controller.c  |  130 +++++++++++++++
 src/photos-offset-collection-view-controller.h  |   43 +++++
 src/photos-offset-collections-controller.c      |   36 +----
 src/photos-preview-view.c                       |    1 +
 src/photos-tracker-collection-view-controller.c |  196 +++++++++++++++++++++++
 src/photos-tracker-collection-view-controller.h |   39 +++++
 src/photos-tracker-collections-controller.c     |   61 +-------
 src/photos-tracker-search-controller.c          |   43 -----
 src/photos-utils.c                              |    8 +
 src/photos-view-container.c                     |    4 +
 18 files changed, 599 insertions(+), 312 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 392b7d6..8bb7897 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -139,6 +139,8 @@ gnome_photos_SOURCES = \
        photos-media-server-item.h \
        photos-notification-manager.c \
        photos-notification-manager.h \
+       photos-offset-collection-view-controller.c \
+       photos-offset-collection-view-controller.h \
        photos-offset-collections-controller.c \
        photos-offset-collections-controller.h \
        photos-offset-controller.c \
@@ -266,6 +268,8 @@ gnome_photos_SOURCES = \
        photos-tracker-change-event.h \
        photos-tracker-change-monitor.c \
        photos-tracker-change-monitor.h \
+       photos-tracker-collection-view-controller.c \
+       photos-tracker-collection-view-controller.h \
        photos-tracker-collections-controller.c \
        photos-tracker-collections-controller.h \
        photos-tracker-controller.c \
diff --git a/src/photos-application.c b/src/photos-application.c
index e232c73..d064cce 100644
--- a/src/photos-application.c
+++ b/src/photos-application.c
@@ -357,7 +357,8 @@ photos_application_actions_update (PhotosApplication *self)
   g_simple_action_set_enabled (self->sharpen_action, enable);
 
   enable = FALSE;
-  if (mode == PHOTOS_WINDOW_MODE_COLLECTIONS
+  if (mode == PHOTOS_WINDOW_MODE_COLLECTION_VIEW
+      || mode == PHOTOS_WINDOW_MODE_COLLECTIONS
       || mode == PHOTOS_WINDOW_MODE_FAVORITES
       || mode == PHOTOS_WINDOW_MODE_OVERVIEW
       || mode == PHOTOS_WINDOW_MODE_SEARCH)
diff --git a/src/photos-embed.c b/src/photos-embed.c
index 4e687a7..57bca3c 100644
--- a/src/photos-embed.c
+++ b/src/photos-embed.c
@@ -68,6 +68,7 @@ struct _PhotosEmbed
   GAction *search_action;
   GHashTable *notifications;
   GIOExtensionPoint *extension_point;
+  GtkWidget *collection_view;
   GtkWidget *collections;
   GtkWidget *favorites;
   GtkWidget *no_results;
@@ -142,6 +143,10 @@ photos_embed_get_view_container_from_mode (PhotosEmbed *self, PhotosWindowMode m
 
   switch (mode)
     {
+    case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
+      view_container = self->collection_view;
+      break;
+
     case PHOTOS_WINDOW_MODE_COLLECTIONS:
       view_container = self->collections;
       break;
@@ -256,7 +261,6 @@ photos_embed_tracker_controllers_set_frozen (PhotosEmbed *self, gboolean frozen)
 static void
 photos_embed_prepare_for_preview (PhotosEmbed *self, PhotosWindowMode old_mode)
 {
-  PhotosBaseItem *active_collection;
   PhotosBaseItem *item;
 
   /* TODO: SearchController,
@@ -269,16 +273,12 @@ photos_embed_prepare_for_preview (PhotosEmbed *self, PhotosWindowMode old_mode)
   /* We want to freeze before saving the search state and to thaw
    * after restoring it. We could thaw it earlier too, but that would
    * lead to a bunch of needless queries from the TrackerControllers.
-   *
-   * Note that we don't want to freeze when showing a collection.
    */
   photos_embed_tracker_controllers_set_frozen (self, TRUE);
 
-  active_collection = photos_item_manager_get_active_collection (PHOTOS_ITEM_MANAGER (self->item_mngr));
   if (old_mode == PHOTOS_WINDOW_MODE_SEARCH)
     {
-      if (active_collection == NULL)
-        photos_embed_save_search (self);
+      photos_embed_save_search (self);
     }
   else
     {
@@ -340,23 +340,6 @@ photos_embed_load_started (PhotosEmbed *self, PhotosBaseItem *item)
 
 
 static void
-photos_embed_active_collection_changed (PhotosBaseManager *manager, PhotosBaseItem *collection, gpointer 
user_data)
-{
-  PhotosEmbed *self = PHOTOS_EMBED (user_data);
-  PhotosWindowMode mode;
-
-  mode = photos_mode_controller_get_window_mode (self->mode_cntrlr);
-  if (mode != PHOTOS_WINDOW_MODE_SEARCH)
-    return;
-
-  if (collection == NULL)
-    photos_embed_restore_search (self);
-  else
-    photos_embed_save_search (self);
-}
-
-
-static void
 photos_embed_fullscreen_changed (PhotosModeController *mode_cntrlr, gboolean fullscreen, gpointer user_data)
 {
 }
@@ -395,6 +378,48 @@ photos_embed_notify_visible_child (PhotosEmbed *self)
 
 
 static void
+photos_embed_prepare_for_collection_view (PhotosEmbed *self, PhotosWindowMode old_mode)
+{
+  switch (old_mode)
+    {
+    case PHOTOS_WINDOW_MODE_COLLECTIONS:
+      {
+        GVariant *state;
+
+        /* Hide any empty search bars that might have been floating
+         * around.
+         */
+        state = g_variant_new ("b", FALSE);
+        g_action_change_state (self->search_action, state);
+        break;
+      }
+
+    case PHOTOS_WINDOW_MODE_PREVIEW:
+      photos_embed_tracker_controllers_set_frozen (self, FALSE);
+      break;
+
+    case PHOTOS_WINDOW_MODE_SEARCH:
+      photos_embed_save_search (self);
+      break;
+
+    case PHOTOS_WINDOW_MODE_NONE:
+      break;
+
+    case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
+    case PHOTOS_WINDOW_MODE_EDIT:
+    case PHOTOS_WINDOW_MODE_FAVORITES:
+    case PHOTOS_WINDOW_MODE_OVERVIEW:
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  photos_spinner_box_stop (PHOTOS_SPINNER_BOX (self->spinner_box));
+  gtk_stack_set_visible_child_name (GTK_STACK (self->stack), "collection-view");
+}
+
+
+static void
 photos_embed_prepare_for_collections (PhotosEmbed *self, PhotosWindowMode old_mode)
 {
   if (old_mode == PHOTOS_WINDOW_MODE_PREVIEW)
@@ -430,16 +455,10 @@ photos_embed_prepare_for_overview (PhotosEmbed *self, PhotosWindowMode old_mode)
 static void
 photos_embed_prepare_for_search (PhotosEmbed *self, PhotosWindowMode old_mode)
 {
-  if (old_mode == PHOTOS_WINDOW_MODE_PREVIEW)
-    {
-      PhotosBaseItem *active_collection;
-
-      active_collection = photos_item_manager_get_active_collection (PHOTOS_ITEM_MANAGER (self->item_mngr));
-      if (active_collection == NULL)
-        photos_embed_restore_search (self);
+  photos_embed_restore_search (self);
 
-      photos_embed_tracker_controllers_set_frozen (self, FALSE);
-    }
+  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), "search");
@@ -464,10 +483,18 @@ photos_embed_search_changed (PhotosEmbed *self)
   const gchar *source_id;
   const gchar *str;
 
-  /* Whenever a search constraint is specified we want to switch to
-   * the search mode, and when all constraints have been lifted we
-   * want to go back to the previous mode which can be either
-   * collections, favorites or overview.
+  /* 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;
@@ -483,9 +510,19 @@ photos_embed_search_changed (PhotosEmbed *self)
   if (g_strcmp0 (search_type_id, PHOTOS_SEARCH_TYPE_STOCK_ALL) == 0
       && g_strcmp0 (source_id, PHOTOS_SOURCE_STOCK_ALL) == 0
       && (str == NULL || str [0] == '\0'))
-    photos_mode_controller_go_back (self->mode_cntrlr);
+    {
+      photos_mode_controller_go_back (self->mode_cntrlr);
+    }
   else
-    photos_mode_controller_set_window_mode (self->mode_cntrlr, PHOTOS_WINDOW_MODE_SEARCH);
+    {
+      PhotosWindowMode mode;
+
+      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);
+    }
 
   self->search_changed = FALSE;
 }
@@ -580,6 +617,7 @@ photos_embed_window_mode_changed (PhotosModeController *mode_cntrlr,
         }
       break;
 
+    case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
     case PHOTOS_WINDOW_MODE_EDIT:
     case PHOTOS_WINDOW_MODE_PREVIEW:
     case PHOTOS_WINDOW_MODE_SEARCH:
@@ -598,6 +636,10 @@ photos_embed_window_mode_changed (PhotosModeController *mode_cntrlr,
     case PHOTOS_WINDOW_MODE_EDIT:
       break;
 
+    case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
+      photos_embed_prepare_for_collection_view (self, old_mode);
+      break;
+
     case PHOTOS_WINDOW_MODE_COLLECTIONS:
       photos_embed_prepare_for_collections (self, old_mode);
       break;
@@ -683,6 +725,9 @@ photos_embed_init (PhotosEmbed *self)
   name = photos_view_container_get_name (PHOTOS_VIEW_CONTAINER (self->overview));
   gtk_stack_add_titled (GTK_STACK (self->stack), self->overview, "overview", name);
 
+  self->collection_view = photos_view_container_new (PHOTOS_WINDOW_MODE_COLLECTION_VIEW, _("Collection 
View"));
+  gtk_stack_add_named (GTK_STACK (self->stack), self->collection_view, "collection-view");
+
   self->collections = photos_view_container_new (PHOTOS_WINDOW_MODE_COLLECTIONS, _("Albums"));
   name = photos_view_container_get_name (PHOTOS_VIEW_CONTAINER (self->collections));
   gtk_stack_add_titled (GTK_STACK (self->stack), self->collections, "collections", name);
@@ -727,11 +772,6 @@ photos_embed_init (PhotosEmbed *self)
 
   self->item_mngr = g_object_ref (state->item_mngr);
   g_signal_connect_object (self->item_mngr,
-                           "active-collection-changed",
-                           G_CALLBACK (photos_embed_active_collection_changed),
-                           self,
-                           0);
-  g_signal_connect_object (self->item_mngr,
                            "load-finished",
                            G_CALLBACK (photos_embed_load_finished),
                            self,
diff --git a/src/photos-empty-results-box.c b/src/photos-empty-results-box.c
index ee9ed8a..d2c9451 100644
--- a/src/photos-empty-results-box.c
+++ b/src/photos-empty-results-box.c
@@ -186,6 +186,10 @@ photos_empty_results_box_constructed (GObject *object)
       label = g_strconcat ("<b><span size=\"large\">", _("Starred photos will appear here"), "</span></b>", 
NULL);
       break;
 
+    /* TODO: Don't show a collection if there are no screenshots in
+     * the relevant locations.
+     */
+    case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
     case PHOTOS_WINDOW_MODE_OVERVIEW:
     case PHOTOS_WINDOW_MODE_SEARCH:
       image = gtk_image_new_from_icon_name (PHOTOS_ICON_PHOTOS_SYMBOLIC, GTK_ICON_SIZE_INVALID);
@@ -222,6 +226,10 @@ photos_empty_results_box_constructed (GObject *object)
       photos_empty_results_box_add_collections_label (self);
       break;
 
+    /* TODO: Don't show a collection if there are no screenshots in
+     * the relevant locations.
+     */
+    case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
     case PHOTOS_WINDOW_MODE_FAVORITES:
     case PHOTOS_WINDOW_MODE_SEARCH:
       gtk_widget_set_valign (title_label, GTK_ALIGN_CENTER);
diff --git a/src/photos-item-manager.c b/src/photos-item-manager.c
index 7d896fe..ab7bf63 100644
--- a/src/photos-item-manager.c
+++ b/src/photos-item-manager.c
@@ -245,8 +245,7 @@ photos_item_manager_info_updated (PhotosBaseItem *item, gpointer user_data)
 
   if (is_collection)
     {
-      if (self->active_collection == NULL)
-        photos_item_manager_try_to_add_item_for_mode (self, item, PHOTOS_WINDOW_MODE_COLLECTIONS);
+      photos_item_manager_try_to_add_item_for_mode (self, item, PHOTOS_WINDOW_MODE_COLLECTIONS);
     }
   else
     {
@@ -258,13 +257,14 @@ photos_item_manager_info_updated (PhotosBaseItem *item, gpointer user_data)
 
   if (is_collection)
     {
+      photos_base_manager_remove_object (self->item_mngr_chldrn[PHOTOS_WINDOW_MODE_COLLECTION_VIEW],
+                                         G_OBJECT (item));
       photos_base_manager_remove_object (self->item_mngr_chldrn[PHOTOS_WINDOW_MODE_FAVORITES], G_OBJECT 
(item));
       photos_base_manager_remove_object (self->item_mngr_chldrn[PHOTOS_WINDOW_MODE_OVERVIEW], G_OBJECT 
(item));
     }
   else
     {
-      if (self->active_collection == NULL)
-        photos_base_manager_remove_object (self->item_mngr_chldrn[PHOTOS_WINDOW_MODE_COLLECTIONS], G_OBJECT 
(item));
+      photos_base_manager_remove_object (self->item_mngr_chldrn[PHOTOS_WINDOW_MODE_COLLECTIONS], G_OBJECT 
(item));
 
       if (!is_favorite)
         photos_base_manager_remove_object (self->item_mngr_chldrn[PHOTOS_WINDOW_MODE_FAVORITES], G_OBJECT 
(item));
@@ -292,8 +292,7 @@ photos_item_manager_add_cursor_for_mode (PhotosItemManager *self,
   is_collection = photos_item_manager_cursor_is_collection (cursor);
   g_return_if_fail ((is_collection
                      && (mode == PHOTOS_WINDOW_MODE_COLLECTIONS || mode == PHOTOS_WINDOW_MODE_SEARCH))
-                    || (!is_collection
-                        && (mode != PHOTOS_WINDOW_MODE_COLLECTIONS || self->active_collection != NULL)));
+                    || (!is_collection && mode != PHOTOS_WINDOW_MODE_COLLECTIONS));
 
   if (!force && !photos_item_manager_can_add_cursor_for_mode (self, cursor, mode))
     goto out;
@@ -686,6 +685,11 @@ photos_item_manager_set_active_object (PhotosBaseManager *manager, GObject *obje
 
   if (is_collection)
     {
+      window_mode_changed = photos_item_manager_set_window_mode_internal (self,
+                                                                          PHOTOS_WINDOW_MODE_COLLECTION_VIEW,
+                                                                          &old_mode);
+      g_assert_true (window_mode_changed);
+
       g_assert_null (self->active_collection);
       self->active_collection = g_object_ref (PHOTOS_BASE_ITEM (object));
       self->load_state = PHOTOS_LOAD_STATE_NONE;
@@ -729,12 +733,12 @@ photos_item_manager_set_active_object (PhotosBaseManager *manager, GObject *obje
 
       g_signal_emit (self, signals[LOAD_STARTED], 0, PHOTOS_BASE_ITEM (object));
 
-      if (window_mode_changed)
-        g_signal_emit (self, signals[WINDOW_MODE_CHANGED], 0, PHOTOS_WINDOW_MODE_PREVIEW, old_mode);
-
       g_assert (self->active_object != (GObject *) self->active_collection);
     }
 
+  if (window_mode_changed)
+    g_signal_emit (self, signals[WINDOW_MODE_CHANGED], 0, self->mode, old_mode);
+
  out:
   return ret_val;
 }
@@ -955,22 +959,6 @@ photos_item_manager_new (void)
 
 
 void
-photos_item_manager_activate_previous_collection (PhotosItemManager *self)
-{
-  g_return_if_fail (PHOTOS_IS_ITEM_MANAGER (self));
-  g_return_if_fail (PHOTOS_IS_BASE_ITEM (self->active_collection));
-
-  photos_item_manager_clear_active_item_load (self);
-
-  g_clear_object (&self->active_collection);
-  g_clear_object (&self->active_object);
-
-  g_signal_emit_by_name (self, "active-changed", self->active_object);
-  g_signal_emit (self, signals[ACTIVE_COLLECTION_CHANGED], 0, self->active_collection);
-}
-
-
-void
 photos_item_manager_add_item (PhotosItemManager *self, TrackerSparqlCursor *cursor, gboolean force)
 {
   g_return_if_fail (PHOTOS_IS_ITEM_MANAGER (self));
@@ -979,7 +967,7 @@ photos_item_manager_add_item (PhotosItemManager *self, TrackerSparqlCursor *curs
   if (photos_item_manager_cursor_is_collection (cursor))
     {
       if (self->active_collection != NULL && force)
-        photos_item_manager_activate_previous_collection (self);
+        photos_mode_controller_go_back (self);
 
       if (self->active_collection == NULL)
         photos_item_manager_add_cursor_for_mode (self, cursor, PHOTOS_WINDOW_MODE_COLLECTIONS, force);
@@ -1328,6 +1316,13 @@ photos_mode_controller_go_back (PhotosModeController *self)
       g_return_if_fail (old_mode == PHOTOS_WINDOW_MODE_PREVIEW);
       break;
 
+    case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
+      g_return_if_fail (self->load_state == PHOTOS_LOAD_STATE_NONE);
+      g_return_if_fail (PHOTOS_IS_BASE_ITEM (self->active_collection));
+      g_return_if_fail (self->active_object == (GObject *) self->active_collection);
+      g_return_if_fail (old_mode == PHOTOS_WINDOW_MODE_COLLECTIONS || old_mode == PHOTOS_WINDOW_MODE_SEARCH);
+      break;
+
     case PHOTOS_WINDOW_MODE_COLLECTIONS:
     case PHOTOS_WINDOW_MODE_FAVORITES:
     case PHOTOS_WINDOW_MODE_OVERVIEW:
@@ -1339,6 +1334,10 @@ photos_mode_controller_go_back (PhotosModeController *self)
       g_return_if_fail (PHOTOS_IS_BASE_ITEM (self->active_object));
       g_return_if_fail (self->active_object != (GObject *) self->active_collection);
       g_return_if_fail (old_mode != PHOTOS_WINDOW_MODE_PREVIEW);
+      g_return_if_fail ((old_mode == PHOTOS_WINDOW_MODE_COLLECTION_VIEW
+                         && PHOTOS_IS_BASE_ITEM (self->active_collection))
+                        || (old_mode != PHOTOS_WINDOW_MODE_COLLECTION_VIEW
+                            && !PHOTOS_IS_BASE_ITEM (self->active_collection)));
       break;
 
     case PHOTOS_WINDOW_MODE_NONE:
@@ -1359,6 +1358,13 @@ photos_mode_controller_go_back (PhotosModeController *self)
 
   switch (old_mode)
     {
+    case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
+      g_clear_object (&self->active_collection);
+      g_clear_object (&self->active_object);
+      active_changed = TRUE;
+      active_collection_changed = TRUE;
+      break;
+
     case PHOTOS_WINDOW_MODE_EDIT:
       break;
 
@@ -1429,6 +1435,7 @@ photos_mode_controller_set_window_mode (PhotosModeController *self, PhotosWindow
 
   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);
 
   if (mode == PHOTOS_WINDOW_MODE_EDIT)
diff --git a/src/photos-item-manager.h b/src/photos-item-manager.h
index e95314e..22fa342 100644
--- a/src/photos-item-manager.h
+++ b/src/photos-item-manager.h
@@ -58,6 +58,7 @@ typedef enum
 typedef enum
 {
   PHOTOS_WINDOW_MODE_NONE,
+  PHOTOS_WINDOW_MODE_COLLECTION_VIEW,
   PHOTOS_WINDOW_MODE_COLLECTIONS,
   PHOTOS_WINDOW_MODE_EDIT,
   PHOTOS_WINDOW_MODE_FAVORITES,
@@ -71,8 +72,6 @@ typedef struct _PhotosItemManagerClass PhotosModeControllerClass;
 
 PhotosBaseManager        *photos_item_manager_new                          (void);
 
-void                      photos_item_manager_activate_previous_collection (PhotosItemManager *self);
-
 void                      photos_item_manager_add_item                     (PhotosItemManager *self,
                                                                             TrackerSparqlCursor *cursor,
                                                                             gboolean force);
diff --git a/src/photos-main-toolbar.c b/src/photos-main-toolbar.c
index a1135db..55f4be0 100644
--- a/src/photos-main-toolbar.c
+++ b/src/photos-main-toolbar.c
@@ -48,7 +48,6 @@ struct _PhotosMainToolbar
   GtkBox parent_instance;
   GAction *search;
   GSimpleAction *gear_menu;
-  GtkWidget *coll_back_button;
   GtkWidget *favorite_button;
   GtkWidget *header_bar;
   GtkWidget *overlay;
@@ -117,7 +116,8 @@ photos_main_toolbar_set_toolbar_title (PhotosMainToolbar *self)
 
   if (selection_mode)
     {
-      g_return_if_fail (window_mode == PHOTOS_WINDOW_MODE_COLLECTIONS
+      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_OVERVIEW
                         || window_mode == PHOTOS_WINDOW_MODE_SEARCH);
@@ -127,20 +127,21 @@ 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));
-  if (window_mode == PHOTOS_WINDOW_MODE_OVERVIEW
-      || window_mode == PHOTOS_WINDOW_MODE_COLLECTIONS
-      || window_mode == PHOTOS_WINDOW_MODE_FAVORITES
-      || window_mode == PHOTOS_WINDOW_MODE_SEARCH)
+
+  if (window_mode == PHOTOS_WINDOW_MODE_COLLECTION_VIEW)
     {
-      if (!selection_mode)
-        {
-          if (active_collection != NULL)
-            primary = g_strdup (photos_base_item_get_name (active_collection));
-        }
+      if (selection_mode)
+        primary = photos_main_toolbar_create_selection_mode_label (self, active_collection);
       else
-        {
-          primary = photos_main_toolbar_create_selection_mode_label (self, active_collection);
-        }
+        primary = g_strdup (photos_base_item_get_name (active_collection));
+    }
+  else if (window_mode == PHOTOS_WINDOW_MODE_OVERVIEW
+           || window_mode == PHOTOS_WINDOW_MODE_COLLECTIONS
+           || window_mode == PHOTOS_WINDOW_MODE_FAVORITES
+           || window_mode == PHOTOS_WINDOW_MODE_SEARCH)
+    {
+      if (selection_mode)
+        primary = photos_main_toolbar_create_selection_mode_label (self, NULL);
     }
   else if (window_mode == PHOTOS_WINDOW_MODE_EDIT || window_mode == PHOTOS_WINDOW_MODE_PREVIEW)
     {
@@ -169,6 +170,13 @@ photos_main_toolbar_set_toolbar_title (PhotosMainToolbar *self)
 }
 
 
+static void
+photos_main_toolbar_back_button_clicked (PhotosMainToolbar *self)
+{
+  photos_mode_controller_go_back (self->mode_cntrlr);
+}
+
+
 static GtkWidget *
 photos_main_toolbar_add_back_button (PhotosMainToolbar *self)
 {
@@ -177,6 +185,7 @@ photos_main_toolbar_add_back_button (PhotosMainToolbar *self)
   back_button = gtk_button_new_from_icon_name (PHOTOS_ICON_GO_PREVIOUS_SYMBOLIC, GTK_ICON_SIZE_BUTTON);
   gtk_widget_set_tooltip_text (back_button, _("Back"));
   gtk_header_bar_pack_start (GTK_HEADER_BAR (self->header_bar), back_button);
+  g_signal_connect_swapped (back_button, "clicked", G_CALLBACK (photos_main_toolbar_back_button_clicked), 
self);
 
   return back_button;
 }
@@ -237,44 +246,6 @@ photos_main_toolbar_update_remote_display_button (PhotosMainToolbar *self)
 
 
 static void
-photos_main_toolbar_coll_back_button_clicked (PhotosMainToolbar *self)
-{
-  photos_item_manager_activate_previous_collection (PHOTOS_ITEM_MANAGER (self->item_mngr));
-}
-
-
-static void
-photos_main_toolbar_col_active_changed (PhotosMainToolbar *self, PhotosBaseItem *collection)
-{
-  PhotosHeaderBarMode mode;
-
-  if (collection != NULL)
-    {
-      mode = PHOTOS_HEADER_BAR_MODE_STANDALONE;
-      if (self->coll_back_button == NULL)
-        {
-          self->coll_back_button = photos_main_toolbar_add_back_button (self);
-          gtk_widget_show (self->coll_back_button);
-
-          g_signal_connect_swapped (self->coll_back_button,
-                                    "clicked",
-                                    G_CALLBACK (photos_main_toolbar_coll_back_button_clicked),
-                                    self);
-        }
-    }
-  else
-    {
-      mode = PHOTOS_HEADER_BAR_MODE_NORMAL;
-      g_clear_pointer (&self->coll_back_button, (GDestroyNotify) gtk_widget_destroy);
-    }
-
-  photos_header_bar_set_mode (PHOTOS_HEADER_BAR (self->header_bar), mode);
-  photos_main_toolbar_update_remote_display_button (self);
-  photos_main_toolbar_set_toolbar_title (self);
-}
-
-
-static void
 photos_main_toolbar_item_active_changed (PhotosMainToolbar *self, GObject *object)
 {
   PhotosWindowMode window_mode;
@@ -321,34 +292,17 @@ photos_main_toolbar_add_selection_button (PhotosMainToolbar *self)
   gtk_actionable_set_action_name (GTK_ACTIONABLE (selection_button), "app.selection-mode");
   gtk_header_bar_pack_end (GTK_HEADER_BAR (self->header_bar), selection_button);
 
-  g_signal_connect_object (self->item_mngr,
-                           "active-collection-changed",
-                           G_CALLBACK (photos_main_toolbar_col_active_changed),
-                           self,
-                           G_CONNECT_SWAPPED);
-
   return selection_button;
 }
 
 
 static void
-photos_main_toolbar_back_button_clicked (PhotosMainToolbar *self)
-{
-  photos_mode_controller_go_back (self->mode_cntrlr);
-}
-
-
-static void
 photos_main_toolbar_clear_state_data (PhotosMainToolbar *self)
 {
-  g_clear_pointer (&self->coll_back_button, (GDestroyNotify) gtk_widget_destroy);
   g_clear_pointer (&self->remote_display_button, (GDestroyNotify) gtk_widget_destroy);
 
   if (self->item_mngr != NULL)
-    {
-      g_signal_handlers_disconnect_by_func (self->item_mngr, photos_main_toolbar_col_active_changed, self);
-      g_signal_handlers_disconnect_by_func (self->item_mngr, photos_main_toolbar_item_active_changed, self);
-    }
+    g_signal_handlers_disconnect_by_func (self->item_mngr, photos_main_toolbar_item_active_changed, self);
 
   if (self->sel_cntrlr != NULL)
     g_signal_handlers_disconnect_by_func (self->sel_cntrlr, photos_main_toolbar_set_toolbar_title, self);
@@ -438,17 +392,23 @@ photos_main_toolbar_favorite_button_update (PhotosMainToolbar *self, gboolean fa
 
 
 static void
-photos_main_toolbar_populate_for_collections (PhotosMainToolbar *self)
+photos_main_toolbar_populate_for_collection_view (PhotosMainToolbar *self)
 {
-  PhotosBaseItem *collection;
+  gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (self->header_bar), TRUE);
+  photos_header_bar_set_mode (PHOTOS_HEADER_BAR (self->header_bar), PHOTOS_HEADER_BAR_MODE_STANDALONE);
+  photos_main_toolbar_add_back_button (self);
+  photos_main_toolbar_add_selection_button (self);
+  photos_main_toolbar_add_search_button (self);
+}
+
 
+static void
+photos_main_toolbar_populate_for_collections (PhotosMainToolbar *self)
+{
   gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (self->header_bar), TRUE);
   photos_header_bar_set_mode (PHOTOS_HEADER_BAR (self->header_bar), PHOTOS_HEADER_BAR_MODE_NORMAL);
   photos_main_toolbar_add_selection_button (self);
   photos_main_toolbar_add_search_button (self);
-
-  collection = photos_item_manager_get_active_collection (PHOTOS_ITEM_MANAGER (self->item_mngr));
-  photos_main_toolbar_col_active_changed (self, collection);
 }
 
 
@@ -476,30 +436,20 @@ photos_main_toolbar_populate_for_edit (PhotosMainToolbar *self)
 static void
 photos_main_toolbar_populate_for_favorites (PhotosMainToolbar *self)
 {
-  PhotosBaseItem *collection;
-
   gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (self->header_bar), TRUE);
   photos_header_bar_set_mode (PHOTOS_HEADER_BAR (self->header_bar), PHOTOS_HEADER_BAR_MODE_NORMAL);
   photos_main_toolbar_add_selection_button (self);
   photos_main_toolbar_add_search_button (self);
-
-  collection = photos_item_manager_get_active_collection (PHOTOS_ITEM_MANAGER (self->item_mngr));
-  photos_main_toolbar_col_active_changed (self, collection);
 }
 
 
 static void
 photos_main_toolbar_populate_for_overview (PhotosMainToolbar *self)
 {
-  PhotosBaseItem *collection;
-
   gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (self->header_bar), TRUE);
   photos_header_bar_set_mode (PHOTOS_HEADER_BAR (self->header_bar), PHOTOS_HEADER_BAR_MODE_NORMAL);
   photos_main_toolbar_add_selection_button (self);
   photos_main_toolbar_add_search_button (self);
-
-  collection = photos_item_manager_get_active_collection (PHOTOS_ITEM_MANAGER (self->item_mngr));
-  photos_main_toolbar_col_active_changed (self, collection);
 }
 
 
@@ -507,7 +457,6 @@ static void
 photos_main_toolbar_populate_for_preview (PhotosMainToolbar *self)
 {
   GMenu *preview_menu;
-  GtkWidget *back_button;
   GtkWidget *edit_button;
   GtkWidget *image;
   GtkWidget *menu_button;
@@ -521,8 +470,7 @@ photos_main_toolbar_populate_for_preview (PhotosMainToolbar *self)
   gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (self->header_bar), TRUE);
   photos_header_bar_set_mode (PHOTOS_HEADER_BAR (self->header_bar), PHOTOS_HEADER_BAR_MODE_STANDALONE);
 
-  back_button = photos_main_toolbar_add_back_button (self);
-  g_signal_connect_swapped (back_button, "clicked", G_CALLBACK (photos_main_toolbar_back_button_clicked), 
self);
+  photos_main_toolbar_add_back_button (self);
 
   preview_menu = photos_main_toolbar_create_preview_menu (self);
   image = gtk_image_new_from_icon_name (PHOTOS_ICON_SYSTEM_SYMBOLIC, GTK_ICON_SIZE_BUTTON);
@@ -571,15 +519,10 @@ photos_main_toolbar_populate_for_preview (PhotosMainToolbar *self)
 static void
 photos_main_toolbar_populate_for_search (PhotosMainToolbar *self)
 {
-  PhotosBaseItem *collection;
-
   gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (self->header_bar), TRUE);
   photos_header_bar_set_mode (PHOTOS_HEADER_BAR (self->header_bar), PHOTOS_HEADER_BAR_MODE_NORMAL);
   photos_main_toolbar_add_selection_button (self);
   photos_main_toolbar_add_search_button (self);
-
-  collection = photos_item_manager_get_active_collection (PHOTOS_ITEM_MANAGER (self->item_mngr));
-  photos_main_toolbar_col_active_changed (self, collection);
 }
 
 
@@ -806,6 +749,10 @@ photos_main_toolbar_reset_toolbar_mode (PhotosMainToolbar *self)
 
       switch (window_mode)
         {
+        case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
+          photos_main_toolbar_populate_for_collection_view (self);
+          break;
+
         case PHOTOS_WINDOW_MODE_COLLECTIONS:
           photos_main_toolbar_populate_for_collections (self);
           break;
diff --git a/src/photos-main-window.c b/src/photos-main-window.c
index c789763..9153b4d 100644
--- a/src/photos-main-window.c
+++ b/src/photos-main-window.c
@@ -152,29 +152,24 @@ photos_main_window_fullscreen_changed (PhotosMainWindow *self, gboolean fullscre
 static gboolean
 photos_main_window_go_back (PhotosMainWindow *self)
 {
-  PhotosBaseItem *active_collection;
   PhotosWindowMode mode;
   gboolean handled = TRUE;
 
   mode = photos_mode_controller_get_window_mode (self->mode_cntrlr);
-  active_collection = photos_item_manager_get_active_collection (PHOTOS_ITEM_MANAGER (self->item_mngr));
 
   switch (mode)
     {
+    case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
     case PHOTOS_WINDOW_MODE_PREVIEW:
       photos_mode_controller_go_back (self->mode_cntrlr);
       break;
 
-    case PHOTOS_WINDOW_MODE_COLLECTIONS:
-    case PHOTOS_WINDOW_MODE_FAVORITES:
-    case PHOTOS_WINDOW_MODE_SEARCH:
-      if (active_collection != NULL)
-        photos_item_manager_activate_previous_collection (PHOTOS_ITEM_MANAGER (self->item_mngr));
-      break;
-
     case PHOTOS_WINDOW_MODE_NONE:
+    case PHOTOS_WINDOW_MODE_COLLECTIONS:
     case PHOTOS_WINDOW_MODE_EDIT:
+    case PHOTOS_WINDOW_MODE_FAVORITES:
     case PHOTOS_WINDOW_MODE_OVERVIEW:
+    case PHOTOS_WINDOW_MODE_SEARCH:
     default:
       handled = FALSE;
       break;
@@ -280,6 +275,7 @@ photos_main_window_key_press_event (GtkWidget *widget, GdkEventKey *event)
   switch (mode)
     {
     case PHOTOS_WINDOW_MODE_NONE:
+    case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
     case PHOTOS_WINDOW_MODE_COLLECTIONS:
     case PHOTOS_WINDOW_MODE_FAVORITES:
     case PHOTOS_WINDOW_MODE_OVERVIEW:
diff --git a/src/photos-offset-collection-view-controller.c b/src/photos-offset-collection-view-controller.c
new file mode 100644
index 0000000..95790aa
--- /dev/null
+++ b/src/photos-offset-collection-view-controller.c
@@ -0,0 +1,130 @@
+/*
+ * 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Based on code from:
+ *   + Documents
+ */
+
+
+#include "config.h"
+
+#include <gio/gio.h>
+
+#include "photos-item-manager.h"
+#include "photos-offset-collection-view-controller.h"
+#include "photos-query-builder.h"
+#include "photos-search-context.h"
+
+
+struct _PhotosOffsetCollectionViewController
+{
+  PhotosOffsetController parent_instance;
+  PhotosBaseManager *item_mngr;
+};
+
+
+G_DEFINE_TYPE (PhotosOffsetCollectionViewController,
+               photos_offset_collection_view_controller,
+               PHOTOS_TYPE_OFFSET_CONTROLLER);
+
+
+static PhotosQuery *
+photos_offset_collection_view_controller_get_query (PhotosOffsetController *offset_cntrlr)
+{
+  PhotosOffsetCollectionViewController *self = PHOTOS_OFFSET_COLLECTION_VIEW_CONTROLLER (offset_cntrlr);
+  GApplication *app;
+  PhotosBaseItem *collection;
+  PhotosSearchContextState *state;
+
+  g_return_val_if_fail (self->item_mngr != NULL, NULL);
+
+  collection = photos_item_manager_get_active_collection (PHOTOS_ITEM_MANAGER (self->item_mngr));
+  g_return_val_if_fail (PHOTOS_IS_BASE_ITEM (collection), NULL);
+
+  app = g_application_get_default ();
+  state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
+
+  return photos_query_builder_count_query (state, PHOTOS_QUERY_FLAGS_NONE);
+}
+
+
+static GObject *
+photos_offset_collection_view_controller_constructor (GType type,
+                                                      guint n_construct_params,
+                                                      GObjectConstructParam *construct_params)
+{
+  static GObject *self = NULL;
+
+  if (self == NULL)
+    {
+      self = G_OBJECT_CLASS (photos_offset_collection_view_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_collection_view_controller_finalize (GObject *object)
+{
+  PhotosOffsetCollectionViewController *self = PHOTOS_OFFSET_COLLECTION_VIEW_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_offset_collection_view_controller_parent_class)->finalize (object);
+}
+
+
+static void
+photos_offset_collection_view_controller_init (PhotosOffsetCollectionViewController *self)
+{
+  GApplication *app;
+  PhotosSearchContextState *state;
+
+  app = g_application_get_default ();
+  state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
+
+  self->item_mngr = state->item_mngr;
+  g_object_add_weak_pointer (G_OBJECT (self->item_mngr), (gpointer *) &self->item_mngr);
+}
+
+
+static void
+photos_offset_collection_view_controller_class_init (PhotosOffsetCollectionViewControllerClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  PhotosOffsetControllerClass *offset_controller_class = PHOTOS_OFFSET_CONTROLLER_CLASS (class);
+
+  object_class->constructor = photos_offset_collection_view_controller_constructor;
+  object_class->finalize = photos_offset_collection_view_controller_finalize;
+  offset_controller_class->get_query = photos_offset_collection_view_controller_get_query;
+}
+
+
+PhotosOffsetController *
+photos_offset_collection_view_controller_dup_singleton (void)
+{
+  return g_object_new (PHOTOS_TYPE_OFFSET_COLLECTION_VIEW_CONTROLLER, NULL);
+}
diff --git a/src/photos-offset-collection-view-controller.h b/src/photos-offset-collection-view-controller.h
new file mode 100644
index 0000000..d51dbf4
--- /dev/null
+++ b/src/photos-offset-collection-view-controller.h
@@ -0,0 +1,43 @@
+/*
+ * 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Based on code from:
+ *   + Documents
+ */
+
+#ifndef PHOTOS_OFFSET_COLLECTION_VIEW_CONTROLLER_H
+#define PHOTOS_OFFSET_COLLECTION_VIEW_CONTROLLER_H
+
+#include "photos-offset-controller.h"
+
+G_BEGIN_DECLS
+
+#define PHOTOS_TYPE_OFFSET_COLLECTION_VIEW_CONTROLLER (photos_offset_collection_view_controller_get_type ())
+G_DECLARE_FINAL_TYPE (PhotosOffsetCollectionViewController,
+                      photos_offset_collection_view_controller,
+                      PHOTOS,
+                      OFFSET_COLLECTION_VIEW_CONTROLLER,
+                      PhotosOffsetController);
+
+PhotosOffsetController  *photos_offset_collection_view_controller_dup_singleton     (void);
+
+G_END_DECLS
+
+#endif /* PHOTOS_OFFSET_COLLECTION_VIEW_CONTROLLER_H */
diff --git a/src/photos-offset-collections-controller.c b/src/photos-offset-collections-controller.c
index 12bfcb8..a860696 100644
--- a/src/photos-offset-collections-controller.c
+++ b/src/photos-offset-collections-controller.c
@@ -27,7 +27,6 @@
 
 #include <gio/gio.h>
 
-#include "photos-item-manager.h"
 #include "photos-query-builder.h"
 #include "photos-offset-collections-controller.h"
 #include "photos-search-context.h"
@@ -36,7 +35,6 @@
 struct _PhotosOffsetCollectionsController
 {
   PhotosOffsetController parent_instance;
-  PhotosBaseManager *item_mngr;
 };
 
 
@@ -48,24 +46,13 @@ G_DEFINE_TYPE (PhotosOffsetCollectionsController,
 static PhotosQuery *
 photos_offset_collections_controller_get_query (PhotosOffsetController *offset_cntrlr)
 {
-  PhotosOffsetCollectionsController *self = PHOTOS_OFFSET_COLLECTIONS_CONTROLLER (offset_cntrlr);
   GApplication *app;
-  PhotosBaseItem *collection;
   PhotosSearchContextState *state;
-  gint flags;
-
-  g_return_val_if_fail (self->item_mngr != NULL, NULL);
-
-  collection = photos_item_manager_get_active_collection (PHOTOS_ITEM_MANAGER (self->item_mngr));
-  if (collection != NULL)
-    flags = PHOTOS_QUERY_FLAGS_NONE;
-  else
-    flags = PHOTOS_QUERY_FLAGS_COLLECTIONS;
 
   app = g_application_get_default ();
   state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
 
-  return photos_query_builder_count_query (state, flags);
+  return photos_query_builder_count_query (state, PHOTOS_QUERY_FLAGS_COLLECTIONS);
 }
 
 
@@ -90,28 +77,8 @@ photos_offset_collections_controller_constructor (GType type,
 
 
 static void
-photos_offset_collections_controller_finalize (GObject *object)
-{
-  PhotosOffsetCollectionsController *self = PHOTOS_OFFSET_COLLECTIONS_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_offset_collections_controller_parent_class)->finalize (object);
-}
-
-
-static void
 photos_offset_collections_controller_init (PhotosOffsetCollectionsController *self)
 {
-  GApplication *app;
-  PhotosSearchContextState *state;
-
-  app = g_application_get_default ();
-  state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
-
-  self->item_mngr = state->item_mngr;
-  g_object_add_weak_pointer (G_OBJECT (self->item_mngr), (gpointer *) &self->item_mngr);
 }
 
 
@@ -122,7 +89,6 @@ photos_offset_collections_controller_class_init (PhotosOffsetCollectionsControll
   PhotosOffsetControllerClass *offset_controller_class = PHOTOS_OFFSET_CONTROLLER_CLASS (class);
 
   object_class->constructor = photos_offset_collections_controller_constructor;
-  object_class->finalize = photos_offset_collections_controller_finalize;
   offset_controller_class->get_query = photos_offset_collections_controller_get_query;
 }
 
diff --git a/src/photos-preview-view.c b/src/photos-preview-view.c
index 5c862af..a12dd70 100644
--- a/src/photos-preview-view.c
+++ b/src/photos-preview-view.c
@@ -807,6 +807,7 @@ photos_preview_view_window_mode_changed (PhotosPreviewView *self, PhotosWindowMo
 {
   switch (mode)
     {
+    case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
     case PHOTOS_WINDOW_MODE_COLLECTIONS:
     case PHOTOS_WINDOW_MODE_FAVORITES:
     case PHOTOS_WINDOW_MODE_OVERVIEW:
diff --git a/src/photos-tracker-collection-view-controller.c b/src/photos-tracker-collection-view-controller.c
new file mode 100644
index 0000000..179d661
--- /dev/null
+++ b/src/photos-tracker-collection-view-controller.c
@@ -0,0 +1,196 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2013 – 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Based on code from:
+ *   + Documents
+ */
+
+
+#include "config.h"
+
+#include <gio/gio.h>
+
+#include "photos-item-manager.h"
+#include "photos-offset-collection-view-controller.h"
+#include "photos-query-builder.h"
+#include "photos-search-context.h"
+#include "photos-tracker-collection-view-controller.h"
+#include "photos-utils.h"
+
+
+struct _PhotosTrackerCollectionViewController
+{
+  PhotosTrackerController parent_instance;
+  PhotosBaseManager *item_mngr;
+  PhotosOffsetController *offset_cntrlr;
+};
+
+
+G_DEFINE_TYPE_WITH_CODE (PhotosTrackerCollectionViewController,
+                         photos_tracker_collection_view_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,
+                                                         "collection-view",
+                                                         0));
+
+
+static void
+photos_tracker_collection_view_controller_active_collection_changed (PhotosTrackerCollectionViewController 
*self,
+                                                                     PhotosBaseItem *active_collection)
+{
+  PhotosBaseManager *item_mngr_chld;
+  gboolean frozen;
+  guint n_items;
+
+  g_return_if_fail (PHOTOS_IS_TRACKER_COLLECTION_VIEW_CONTROLLER (self));
+  g_return_if_fail (active_collection == NULL || PHOTOS_IS_BASE_ITEM (active_collection));
+  g_return_if_fail (self->item_mngr != NULL);
+
+  item_mngr_chld = photos_item_manager_get_for_mode (PHOTOS_ITEM_MANAGER (self->item_mngr),
+                                                     PHOTOS_WINDOW_MODE_COLLECTION_VIEW);
+  n_items = g_list_model_get_n_items (G_LIST_MODEL (item_mngr_chld));
+  g_return_if_fail ((PHOTOS_BASE_ITEM (active_collection) && n_items == 0)
+                    || (active_collection == NULL && n_items > 0));
+
+  frozen = active_collection == NULL;
+  photos_tracker_controller_set_frozen (PHOTOS_TRACKER_CONTROLLER (self), frozen);
+
+  if (active_collection == NULL)
+    photos_item_manager_clear (PHOTOS_ITEM_MANAGER (self->item_mngr), PHOTOS_WINDOW_MODE_COLLECTION_VIEW);
+  else
+    photos_tracker_controller_refresh_for_object (PHOTOS_TRACKER_CONTROLLER (self));
+}
+
+
+static PhotosOffsetController *
+photos_tracker_collection_view_controller_get_offset_controller (PhotosTrackerController *trk_cntrlr)
+{
+  PhotosTrackerCollectionViewController *self = PHOTOS_TRACKER_COLLECTION_VIEW_CONTROLLER (trk_cntrlr);
+  return g_object_ref (self->offset_cntrlr);
+}
+
+
+static PhotosQuery *
+photos_tracker_collection_view_controller_get_query (PhotosTrackerController *trk_cntrlr)
+{
+  PhotosTrackerCollectionViewController *self = PHOTOS_TRACKER_COLLECTION_VIEW_CONTROLLER (trk_cntrlr);
+  GApplication *app;
+  PhotosBaseItem *collection;
+  PhotosSearchContextState *state;
+
+  g_return_val_if_fail (self->item_mngr != NULL, NULL);
+
+  collection = photos_item_manager_get_active_collection (PHOTOS_ITEM_MANAGER (self->item_mngr));
+  g_return_val_if_fail (PHOTOS_IS_BASE_ITEM (collection), NULL);
+
+  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_NONE, self->offset_cntrlr);
+}
+
+
+static GObject *
+photos_tracker_collection_view_controller_constructor (GType type,
+                                                       guint n_construct_params,
+                                                       GObjectConstructParam *construct_params)
+{
+  static GObject *self = NULL;
+
+  if (self == NULL)
+    {
+      self = G_OBJECT_CLASS (photos_tracker_collection_view_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_collection_view_controller_dispose (GObject *object)
+{
+  PhotosTrackerCollectionViewController *self = PHOTOS_TRACKER_COLLECTION_VIEW_CONTROLLER (object);
+
+  g_clear_object (&self->offset_cntrlr);
+
+  G_OBJECT_CLASS (photos_tracker_collection_view_controller_parent_class)->dispose (object);
+}
+
+
+static void
+photos_tracker_collection_view_controller_finalize (GObject *object)
+{
+  PhotosTrackerCollectionViewController *self = PHOTOS_TRACKER_COLLECTION_VIEW_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_collection_view_controller_parent_class)->finalize (object);
+}
+
+
+static void
+photos_tracker_collection_view_controller_init (PhotosTrackerCollectionViewController *self)
+{
+  GApplication *app;
+  PhotosSearchContextState *state;
+
+  app = g_application_get_default ();
+  state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
+
+  self->item_mngr = state->item_mngr;
+  g_object_add_weak_pointer (G_OBJECT (self->item_mngr), (gpointer *) &self->item_mngr);
+  g_signal_connect_swapped (self->item_mngr,
+                            "active-collection-changed",
+                            G_CALLBACK (photos_tracker_collection_view_controller_active_collection_changed),
+                            self);
+
+  self->offset_cntrlr = photos_offset_collection_view_controller_dup_singleton ();
+
+  photos_tracker_controller_set_frozen (PHOTOS_TRACKER_CONTROLLER (self), TRUE);
+}
+
+
+static void
+photos_tracker_collection_view_controller_class_init (PhotosTrackerCollectionViewControllerClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  PhotosTrackerControllerClass *tracker_controller_class = PHOTOS_TRACKER_CONTROLLER_CLASS (class);
+
+  object_class->constructor = photos_tracker_collection_view_controller_constructor;
+  object_class->dispose = photos_tracker_collection_view_controller_dispose;
+  object_class->finalize = photos_tracker_collection_view_controller_finalize;
+  tracker_controller_class->get_offset_controller = 
photos_tracker_collection_view_controller_get_offset_controller;
+  tracker_controller_class->get_query = photos_tracker_collection_view_controller_get_query;
+}
+
+
+PhotosTrackerController *
+photos_tracker_collection_view_controller_dup_singleton (void)
+{
+  return g_object_new (PHOTOS_TYPE_TRACKER_COLLECTION_VIEW_CONTROLLER,
+                       "mode", PHOTOS_WINDOW_MODE_COLLECTION_VIEW,
+                       NULL);
+}
diff --git a/src/photos-tracker-collection-view-controller.h b/src/photos-tracker-collection-view-controller.h
new file mode 100644
index 0000000..17d15db
--- /dev/null
+++ b/src/photos-tracker-collection-view-controller.h
@@ -0,0 +1,39 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2013 – 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef PHOTOS_TRACKER_COLLECTION_VIEW_CONTROLLER_H
+#define PHOTOS_TRACKER_COLLECTION_VIEW_CONTROLLER_H
+
+#include "photos-tracker-controller.h"
+
+G_BEGIN_DECLS
+
+#define PHOTOS_TYPE_TRACKER_COLLECTION_VIEW_CONTROLLER (photos_tracker_collection_view_controller_get_type 
())
+G_DECLARE_FINAL_TYPE (PhotosTrackerCollectionViewController,
+                      photos_tracker_collection_view_controller,
+                      PHOTOS,
+                      TRACKER_COLLECTION_VIEW_CONTROLLER,
+                      PhotosTrackerController);
+
+PhotosTrackerController  *photos_tracker_collection_view_controller_dup_singleton     (void);
+
+G_END_DECLS
+
+#endif /* PHOTOS_TRACKER_COLLECTION_VIEW_CONTROLLER_H */
diff --git a/src/photos-tracker-collections-controller.c b/src/photos-tracker-collections-controller.c
index e1456d4..8571f58 100644
--- a/src/photos-tracker-collections-controller.c
+++ b/src/photos-tracker-collections-controller.c
@@ -34,8 +34,6 @@
 struct _PhotosTrackerCollectionsController
 {
   PhotosTrackerController parent_instance;
-  PhotosBaseManager *item_mngr;
-  PhotosModeController *mode_cntrlr;
   PhotosOffsetController *offset_cntrlr;
 };
 
@@ -55,21 +53,6 @@ G_DEFINE_TYPE_WITH_CODE (PhotosTrackerCollectionsController,
                                                          0));
 
 
-static void
-photos_tracker_collections_controller_col_active_changed (PhotosTrackerCollectionsController *self)
-{
-  PhotosWindowMode mode;
-
-  g_return_if_fail (self->mode_cntrlr != NULL);
-
-  mode = photos_mode_controller_get_window_mode (self->mode_cntrlr);
-  if (mode != PHOTOS_WINDOW_MODE_COLLECTIONS)
-    return;
-
-  photos_tracker_controller_refresh_for_object (PHOTOS_TRACKER_CONTROLLER (self));
-}
-
-
 static PhotosOffsetController *
 photos_tracker_collections_controller_get_offset_controller (PhotosTrackerController *trk_cntrlr)
 {
@@ -83,22 +66,12 @@ photos_tracker_collections_controller_get_query (PhotosTrackerController *trk_cn
 {
   PhotosTrackerCollectionsController *self = PHOTOS_TRACKER_COLLECTIONS_CONTROLLER (trk_cntrlr);
   GApplication *app;
-  PhotosBaseItem *collection;
   PhotosSearchContextState *state;
-  gint flags;
-
-  g_return_val_if_fail (self->item_mngr != NULL, NULL);
-
-  collection = photos_item_manager_get_active_collection (PHOTOS_ITEM_MANAGER (self->item_mngr));
-  if (collection != NULL)
-    flags = PHOTOS_QUERY_FLAGS_NONE;
-  else
-    flags = PHOTOS_QUERY_FLAGS_COLLECTIONS;
 
   app = g_application_get_default ();
   state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
 
-  return photos_query_builder_global_query (state, flags, self->offset_cntrlr);
+  return photos_query_builder_global_query (state, PHOTOS_QUERY_FLAGS_COLLECTIONS, self->offset_cntrlr);
 }
 
 
@@ -134,39 +107,8 @@ photos_tracker_collections_controller_dispose (GObject *object)
 
 
 static void
-photos_tracker_collections_controller_finalize (GObject *object)
-{
-  PhotosTrackerCollectionsController *self = PHOTOS_TRACKER_COLLECTIONS_CONTROLLER (object);
-
-  if (self->item_mngr != NULL)
-    g_object_remove_weak_pointer (G_OBJECT (self->item_mngr), (gpointer *) &self->item_mngr);
-
-  if (self->mode_cntrlr != NULL)
-    g_object_remove_weak_pointer (G_OBJECT (self->mode_cntrlr), (gpointer *) &self->mode_cntrlr);
-
-  G_OBJECT_CLASS (photos_tracker_collections_controller_parent_class)->finalize (object);
-}
-
-
-static void
 photos_tracker_collections_controller_init (PhotosTrackerCollectionsController *self)
 {
-  GApplication *app;
-  PhotosSearchContextState *state;
-
-  app = g_application_get_default ();
-  state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
-
-  self->item_mngr = state->item_mngr;
-  g_object_add_weak_pointer (G_OBJECT (self->item_mngr), (gpointer *) &self->item_mngr);
-  g_signal_connect_swapped (self->item_mngr,
-                            "active-collection-changed",
-                            G_CALLBACK (photos_tracker_collections_controller_col_active_changed),
-                            self);
-
-  self->mode_cntrlr = state->mode_cntrlr;
-  g_object_add_weak_pointer (G_OBJECT (self->mode_cntrlr), (gpointer *) &self->mode_cntrlr);
-
   self->offset_cntrlr = photos_offset_collections_controller_dup_singleton ();
 }
 
@@ -179,7 +121,6 @@ photos_tracker_collections_controller_class_init (PhotosTrackerCollectionsContro
 
   object_class->constructor = photos_tracker_collections_controller_constructor;
   object_class->dispose = photos_tracker_collections_controller_dispose;
-  object_class->finalize = photos_tracker_collections_controller_finalize;
   tracker_controller_class->get_offset_controller = 
photos_tracker_collections_controller_get_offset_controller;
   tracker_controller_class->get_query = photos_tracker_collections_controller_get_query;
 }
diff --git a/src/photos-tracker-search-controller.c b/src/photos-tracker-search-controller.c
index 5e6fae9..352b83c 100644
--- a/src/photos-tracker-search-controller.c
+++ b/src/photos-tracker-search-controller.c
@@ -40,11 +40,9 @@
 struct _PhotosTrackerSearchController
 {
   PhotosTrackerController parent_instance;
-  PhotosBaseManager *item_mngr;
   PhotosBaseManager *src_mngr;
   PhotosBaseManager *srch_mtch_mngr;
   PhotosBaseManager *srch_typ_mngr;
-  PhotosModeController *mode_cntrlr;
   PhotosOffsetController *offset_cntrlr;
   PhotosSearchController *srch_cntrlr;
 };
@@ -60,21 +58,6 @@ G_DEFINE_TYPE_WITH_CODE (PhotosTrackerSearchController,
                                                          0));
 
 
-static void
-photos_tracker_search_controller_col_active_changed (PhotosTrackerSearchController *self)
-{
-  PhotosWindowMode mode;
-
-  g_return_if_fail (self->mode_cntrlr != NULL);
-
-  mode = photos_mode_controller_get_window_mode (self->mode_cntrlr);
-  if (mode != PHOTOS_WINDOW_MODE_SEARCH)
-    return;
-
-  photos_tracker_controller_refresh_for_object (PHOTOS_TRACKER_CONTROLLER (self));
-}
-
-
 static PhotosOffsetController *
 photos_tracker_search_controller_get_offset_controller (PhotosTrackerController *trk_cntrlr)
 {
@@ -146,21 +129,6 @@ photos_tracker_search_controller_dispose (GObject *object)
 
 
 static void
-photos_tracker_search_controller_finalize (GObject *object)
-{
-  PhotosTrackerSearchController *self = PHOTOS_TRACKER_SEARCH_CONTROLLER (object);
-
-  if (self->item_mngr != NULL)
-    g_object_remove_weak_pointer (G_OBJECT (self->item_mngr), (gpointer *) &self->item_mngr);
-
-  if (self->mode_cntrlr != NULL)
-    g_object_remove_weak_pointer (G_OBJECT (self->mode_cntrlr), (gpointer *) &self->mode_cntrlr);
-
-  G_OBJECT_CLASS (photos_tracker_search_controller_parent_class)->finalize (object);
-}
-
-
-static void
 photos_tracker_search_controller_init (PhotosTrackerSearchController *self)
 {
   GApplication *app;
@@ -169,13 +137,6 @@ photos_tracker_search_controller_init (PhotosTrackerSearchController *self)
   app = g_application_get_default ();
   state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
 
-  self->item_mngr = state->item_mngr;
-  g_object_add_weak_pointer (G_OBJECT (self->item_mngr), (gpointer *) &self->item_mngr);
-  g_signal_connect_swapped (self->item_mngr,
-                            "active-collection-changed",
-                            G_CALLBACK (photos_tracker_search_controller_col_active_changed),
-                            self);
-
   self->src_mngr = g_object_ref (state->src_mngr);
   g_signal_connect_swapped (self->src_mngr,
                             "active-changed",
@@ -194,9 +155,6 @@ photos_tracker_search_controller_init (PhotosTrackerSearchController *self)
                             G_CALLBACK (photos_tracker_controller_refresh_for_object),
                             self);
 
-  self->mode_cntrlr = state->mode_cntrlr;
-  g_object_add_weak_pointer (G_OBJECT (self->mode_cntrlr), (gpointer *) &self->mode_cntrlr);
-
   self->offset_cntrlr = photos_offset_search_controller_dup_singleton ();
 
   self->srch_cntrlr = g_object_ref (state->srch_cntrlr);
@@ -215,7 +173,6 @@ photos_tracker_search_controller_class_init (PhotosTrackerSearchControllerClass
 
   object_class->constructor = photos_tracker_search_controller_constructor;
   object_class->dispose = photos_tracker_search_controller_dispose;
-  object_class->finalize = photos_tracker_search_controller_finalize;
   tracker_controller_class->get_offset_controller = photos_tracker_search_controller_get_offset_controller;
   tracker_controller_class->get_query = photos_tracker_search_controller_get_query;
 }
diff --git a/src/photos-utils.c b/src/photos-utils.c
index 1c1c231..0d8de9e 100644
--- a/src/photos-utils.c
+++ b/src/photos-utils.c
@@ -42,6 +42,7 @@
 #include "photos-google-item.h"
 #include "photos-local-item.h"
 #include "photos-media-server-item.h"
+#include "photos-offset-collection-view-controller.h"
 #include "photos-offset-collections-controller.h"
 #include "photos-offset-favorites-controller.h"
 #include "photos-offset-overview-controller.h"
@@ -58,6 +59,7 @@
 #include "photos-tool-crop.h"
 #include "photos-tool-enhance.h"
 #include "photos-tool-filters.h"
+#include "photos-tracker-collection-view-controller.h"
 #include "photos-tracker-collections-controller.h"
 #include "photos-tracker-favorites-controller.h"
 #include "photos-tracker-overview-controller.h"
@@ -640,6 +642,7 @@ photos_utils_ensure_builtins (void)
       g_type_ensure (PHOTOS_TYPE_TOOL_ENHANCE);
       g_type_ensure (PHOTOS_TYPE_TOOL_FILTERS);
 
+      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_OVERVIEW_CONTROLLER);
@@ -932,6 +935,11 @@ photos_utils_get_controller (PhotosWindowMode mode,
 
   switch (mode)
     {
+    case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
+      offset_cntrlr = photos_offset_collection_view_controller_dup_singleton ();
+      trk_cntrlr = photos_tracker_collection_view_controller_dup_singleton ();
+      break;
+
     case PHOTOS_WINDOW_MODE_COLLECTIONS:
       offset_cntrlr = photos_offset_collections_controller_dup_singleton ();
       trk_cntrlr = photos_tracker_collections_controller_dup_singleton ();
diff --git a/src/photos-view-container.c b/src/photos-view-container.c
index 871f7b9..1e681cf 100644
--- a/src/photos-view-container.c
+++ b/src/photos-view-container.c
@@ -109,6 +109,10 @@ photos_view_container_get_show_primary_text (PhotosViewContainer *self)
 
   switch (self->mode)
     {
+    case PHOTOS_WINDOW_MODE_COLLECTION_VIEW:
+      ret_val = FALSE;
+      break;
+
     case PHOTOS_WINDOW_MODE_COLLECTIONS:
       ret_val = TRUE;
       break;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]