1 /*
2 * Photos - access, organize and share your photos on GNOME
3 * Copyright © 2012 – 2019 Red Hat, Inc.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /* Based on code from:
20 * + Documents
21 */
22
23
24 #include "config.h"
25
26 #include <dazzle.h>
27 #include <glib.h>
28 #include <glib/gi18n.h>
29
30 #include <gio/gio.h>
31
32 #include "photos-base-manager.h"
33 #include "photos-debug.h"
34 #include "photos-enums.h"
35 #include "photos-filterable.h"
36 #include "photos-item-manager.h"
37 #include "photos-marshalers.h"
38 #include "photos-query-builder.h"
39 #include "photos-search-context.h"
40 #include "photos-tracker-controller.h"
41 #include "photos-tracker-queue.h"
42
43
44 struct _PhotosTrackerControllerPrivate
45 {
46 GCancellable *cancellable;
47 GError *queue_error;
48 PhotosBaseManager *item_mngr;
49 PhotosBaseManager *src_mngr;
50 PhotosModeController *mode_cntrlr;
51 PhotosOffsetController *offset_cntrlr;
52 PhotosQuery *current_query;
53 PhotosTrackerQueue *queue;
54 PhotosWindowMode mode;
55 gboolean delay_start;
56 gboolean is_frozen;
57 gboolean is_started;
58 gboolean query_queued;
59 gboolean querying;
60 gboolean refresh_pending;
61 gint query_queued_flags;
62 gint64 last_query_time;
63 guint reset_count_id;
64 };
65
66 enum
67 {
68 PROP_0,
69 PROP_DELAY_START,
70 PROP_MODE
71 };
72
73 enum
74 {
75 QUERY_ERROR,
76 QUERY_STATUS_CHANGED,
77 LAST_SIGNAL
78 };
79
80 static guint signals[LAST_SIGNAL] = { 0 };
81
82
83 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (PhotosTrackerController, photos_tracker_controller, G_TYPE_OBJECT);
84 DZL_DEFINE_COUNTER (instances,
85 "PhotosTrackerController",
86 "Instances",
87 "Number of PhotosTrackerController instances")
88
89
90 enum
91 {
92 RESET_COUNT_TIMEOUT = 500 /* ms */
93 };
94
95 typedef enum
96 {
97 PHOTOS_TRACKER_REFRESH_FLAGS_NONE = 0,
98 PHOTOS_TRACKER_REFRESH_FLAGS_DONT_SET_QUERY_STATUS = 1 << 0,
99 PHOTOS_TRACKER_REFRESH_FLAGS_RESET_OFFSET = 1 << 1,
100 } PhotosTrackerRefreshFlags;
101
102 static void photos_tracker_controller_refresh_internal (PhotosTrackerController *self, gint flags);
103 static void photos_tracker_controller_set_query_status (PhotosTrackerController *self, gboolean query_status);
104
105
106 static gboolean
photos_tracker_controller_reset_count_timeout(gpointer user_data)107 photos_tracker_controller_reset_count_timeout (gpointer user_data)
108 {
109 PhotosTrackerController *self = PHOTOS_TRACKER_CONTROLLER (user_data);
110 PhotosTrackerControllerPrivate *priv;
111
112 priv = photos_tracker_controller_get_instance_private (self);
113
114 priv->reset_count_id = 0;
115 photos_offset_controller_reset_count (priv->offset_cntrlr);
116 return G_SOURCE_REMOVE;
117 }
118
119
120 static void
photos_tracker_controller_reset_constraint(PhotosTrackerController * self)121 photos_tracker_controller_reset_constraint (PhotosTrackerController *self)
122 {
123 PhotosTrackerControllerPrivate *priv;
124 PhotosBaseManager *item_mngr_chld;
125 gboolean constrain;
126 gint count;
127 gint offset;
128 gint step;
129
130 priv = photos_tracker_controller_get_instance_private (self);
131
132 item_mngr_chld = photos_item_manager_get_for_mode (PHOTOS_ITEM_MANAGER (priv->item_mngr), priv->mode);
133 count = (gint) photos_base_manager_get_objects_count (item_mngr_chld);
134
135 offset = photos_offset_controller_get_offset (priv->offset_cntrlr);
136 step = photos_offset_controller_get_step (priv->offset_cntrlr);
137
138 constrain = (count >= offset + step) ? TRUE : FALSE;
139 photos_item_manager_set_constraints_for_mode (PHOTOS_ITEM_MANAGER (priv->item_mngr), constrain, priv->mode);
140 }
141
142 static void
photos_tracker_controller_item_added_removed(PhotosTrackerController * self)143 photos_tracker_controller_item_added_removed (PhotosTrackerController *self)
144 {
145 PhotosTrackerControllerPrivate *priv;
146
147 priv = photos_tracker_controller_get_instance_private (self);
148
149 /* Update the count so that PhotosOffsetController has the correct
150 * values. Otherwise things like loading more items and "No
151 * Results" page will not work correctly.
152 */
153
154 if (priv->reset_count_id == 0)
155 {
156 priv->reset_count_id = g_timeout_add (RESET_COUNT_TIMEOUT,
157 photos_tracker_controller_reset_count_timeout,
158 self);
159 }
160
161 photos_tracker_controller_reset_constraint (self);
162 }
163
164
165 static void
photos_tracker_controller_query_error(PhotosTrackerController * self,GError * error)166 photos_tracker_controller_query_error (PhotosTrackerController *self, GError *error)
167 {
168 const gchar *primary;
169
170 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
171 return;
172
173 if (g_error_matches (error, TRACKER_SPARQL_ERROR, TRACKER_SPARQL_ERROR_INTERNAL))
174 primary = _("Unable to find Tracker on your operating system");
175 else
176 primary = _("Unable to fetch the list of photos");
177
178 g_signal_emit (self, signals[QUERY_ERROR], 0, primary, error->message);
179 }
180
181
182 static void
photos_tracker_controller_query_finished(PhotosTrackerController * self,GError * error)183 photos_tracker_controller_query_finished (PhotosTrackerController *self, GError *error)
184 {
185 PhotosTrackerControllerPrivate *priv;
186
187 priv = photos_tracker_controller_get_instance_private (self);
188
189 photos_tracker_controller_set_query_status (self, FALSE);
190
191 if (error != NULL)
192 photos_tracker_controller_query_error (self, error);
193 else
194 photos_offset_controller_reset_count (priv->offset_cntrlr);
195
196 if (priv->query_queued)
197 {
198 priv->query_queued = FALSE;
199 photos_tracker_controller_refresh_internal (self, priv->query_queued_flags);
200 }
201 }
202
203
204 static void
photos_tracker_controller_cursor_next(GObject * source_object,GAsyncResult * res,gpointer user_data)205 photos_tracker_controller_cursor_next (GObject *source_object, GAsyncResult *res, gpointer user_data)
206 {
207 g_autoptr (PhotosTrackerController) self = PHOTOS_TRACKER_CONTROLLER (user_data);
208 PhotosTrackerControllerPrivate *priv;
209 TrackerSparqlCursor *cursor = TRACKER_SPARQL_CURSOR (source_object);
210 gboolean success;
211 gint64 now;
212
213 priv = photos_tracker_controller_get_instance_private (self);
214
215 if (priv->item_mngr == NULL)
216 goto out;
217
218 {
219 g_autoptr (GError) error = NULL;
220
221 /* Note that tracker_sparql_cursor_next_finish can return FALSE even
222 * without an error.
223 */
224 success = tracker_sparql_cursor_next_finish (cursor, res, &error);
225 if (error != NULL)
226 {
227 photos_tracker_controller_query_finished (self, error);
228 goto out;
229 }
230 }
231
232 if (!success)
233 {
234 tracker_sparql_cursor_close (cursor);
235 photos_tracker_controller_query_finished (self, NULL);
236 goto out;
237 }
238
239 now = g_get_monotonic_time ();
240 photos_debug (PHOTOS_DEBUG_TRACKER,
241 "Query Cursor: %" G_GINT64_FORMAT " seconds",
242 (now - priv->last_query_time) / 1000000);
243
244 photos_item_manager_add_item_for_mode (PHOTOS_ITEM_MANAGER (priv->item_mngr),
245 PHOTOS_TRACKER_CONTROLLER_GET_CLASS (self)->base_item_type,
246 priv->mode,
247 cursor);
248
249 tracker_sparql_cursor_next_async (cursor,
250 priv->cancellable,
251 photos_tracker_controller_cursor_next,
252 g_object_ref (self));
253
254 out:
255 return;
256 }
257
258
259 static void
photos_tracker_controller_query_executed(GObject * source_object,GAsyncResult * res,gpointer user_data)260 photos_tracker_controller_query_executed (GObject *source_object, GAsyncResult *res, gpointer user_data)
261 {
262 PhotosTrackerController *self = PHOTOS_TRACKER_CONTROLLER (user_data);
263 PhotosTrackerControllerPrivate *priv;
264 TrackerSparqlConnection *connection = TRACKER_SPARQL_CONNECTION (source_object);
265 TrackerSparqlCursor *cursor; /* Use g_autoptr */
266
267 priv = photos_tracker_controller_get_instance_private (self);
268
269 {
270 g_autoptr (GError) error = NULL;
271
272 cursor = tracker_sparql_connection_query_finish (connection, res, &error);
273 if (error != NULL)
274 {
275 photos_tracker_controller_query_finished (self, error);
276 return;
277 }
278 }
279
280 tracker_sparql_cursor_next_async (cursor,
281 priv->cancellable,
282 photos_tracker_controller_cursor_next,
283 g_object_ref (self));
284 g_object_unref (cursor);
285 }
286
287
288 static void
photos_tracker_controller_perform_current_query(PhotosTrackerController * self)289 photos_tracker_controller_perform_current_query (PhotosTrackerController *self)
290 {
291 PhotosTrackerControllerPrivate *priv;
292 const gchar *type_name;
293 g_autofree gchar *tag = NULL;
294
295 priv = photos_tracker_controller_get_instance_private (self);
296
297 g_clear_object (&priv->current_query);
298 priv->current_query = PHOTOS_TRACKER_CONTROLLER_GET_CLASS (self)->get_query (self);
299 g_return_if_fail (priv->current_query != NULL);
300
301 type_name = G_OBJECT_TYPE_NAME (self);
302 tag = g_strdup_printf ("%s: %s", type_name, G_STRFUNC);
303 photos_query_set_tag (priv->current_query, tag);
304
305 g_object_unref (priv->cancellable);
306 priv->cancellable = g_cancellable_new ();
307
308 if (G_UNLIKELY (priv->queue == NULL))
309 {
310 photos_tracker_controller_query_error (self, priv->queue_error);
311 goto out;
312 }
313
314 photos_tracker_queue_select (priv->queue,
315 priv->current_query,
316 priv->cancellable,
317 photos_tracker_controller_query_executed,
318 g_object_ref (self),
319 g_object_unref);
320
321 out:
322 return;
323 }
324
325
326 static void
photos_tracker_controller_offset_changed(PhotosTrackerController * self)327 photos_tracker_controller_offset_changed (PhotosTrackerController *self)
328 {
329 photos_tracker_controller_reset_constraint (self);
330 photos_tracker_controller_refresh_internal (self, PHOTOS_TRACKER_REFRESH_FLAGS_DONT_SET_QUERY_STATUS);
331 }
332
333
334 static void
photos_tracker_controller_set_query_status(PhotosTrackerController * self,gboolean query_status)335 photos_tracker_controller_set_query_status (PhotosTrackerController *self, gboolean query_status)
336 {
337 PhotosTrackerControllerPrivate *priv;
338 gint64 now;
339
340 priv = photos_tracker_controller_get_instance_private (self);
341
342 if (priv->querying == query_status)
343 return;
344
345 now = g_get_monotonic_time ();
346 if (query_status)
347 priv->last_query_time = now;
348 else
349 {
350 photos_debug (PHOTOS_DEBUG_TRACKER,
351 "Query Elapsed: %" G_GINT64_FORMAT " seconds",
352 (now - priv->last_query_time) / 1000000);
353 priv->last_query_time = 0;
354 }
355
356 priv->querying = query_status;
357 g_signal_emit (self, signals[QUERY_STATUS_CHANGED], 0, priv->querying);
358 }
359
360
361 static void
photos_tracker_controller_refresh_internal(PhotosTrackerController * self,gint flags)362 photos_tracker_controller_refresh_internal (PhotosTrackerController *self, gint flags)
363 {
364 PhotosTrackerControllerPrivate *priv;
365
366 priv = photos_tracker_controller_get_instance_private (self);
367
368 priv->is_started = TRUE;
369
370 if (priv->is_frozen)
371 return;
372
373 if (flags & PHOTOS_TRACKER_REFRESH_FLAGS_RESET_OFFSET)
374 photos_offset_controller_reset_offset (priv->offset_cntrlr);
375
376 if (photos_tracker_controller_get_query_status (self))
377 {
378 g_cancellable_cancel (priv->cancellable);
379 priv->query_queued = TRUE;
380 priv->query_queued_flags = flags;
381 return;
382 }
383
384 if (!(flags & PHOTOS_TRACKER_REFRESH_FLAGS_DONT_SET_QUERY_STATUS))
385 {
386 photos_tracker_controller_set_query_status (self, TRUE);
387 photos_item_manager_clear (PHOTOS_ITEM_MANAGER (priv->item_mngr), priv->mode);
388 }
389
390 photos_tracker_controller_perform_current_query (self);
391 }
392
393
394 static void
photos_tracker_controller_refresh_for_source(PhotosTrackerController * self)395 photos_tracker_controller_refresh_for_source (PhotosTrackerController *self)
396 {
397 PhotosTrackerControllerPrivate *priv;
398
399 priv = photos_tracker_controller_get_instance_private (self);
400
401 if (priv->current_query != NULL)
402 {
403 PhotosSource *source;
404
405 source = photos_query_get_source (priv->current_query);
406 if (source != NULL)
407 {
408 const gchar *id;
409
410 id = photos_filterable_get_id (PHOTOS_FILTERABLE (source));
411 if (g_strcmp0 (id, PHOTOS_SOURCE_STOCK_ALL) == 0)
412 photos_tracker_controller_refresh_internal (self, PHOTOS_TRACKER_REFRESH_FLAGS_NONE);
413 }
414 }
415
416 priv->refresh_pending = FALSE;
417 }
418
419
420 static void
photos_tracker_controller_source_object_added_removed(PhotosTrackerController * self,GObject * source)421 photos_tracker_controller_source_object_added_removed (PhotosTrackerController *self, GObject *source)
422 {
423 PhotosTrackerControllerPrivate *priv;
424 PhotosWindowMode mode;
425
426 priv = photos_tracker_controller_get_instance_private (self);
427
428 g_return_if_fail (priv->mode_cntrlr != NULL);
429
430 if (!photos_filterable_is_search_criterion (PHOTOS_FILTERABLE (source)))
431 goto out;
432
433 mode = photos_mode_controller_get_window_mode (priv->mode_cntrlr);
434 if (mode == priv->mode)
435 photos_tracker_controller_refresh_for_source (self);
436 else
437 priv->refresh_pending = TRUE;
438
439 out:
440 return;
441 }
442
443
444 static void
photos_tracker_controller_window_mode_changed(PhotosTrackerController * self,PhotosWindowMode mode,PhotosWindowMode old_mode)445 photos_tracker_controller_window_mode_changed (PhotosTrackerController *self,
446 PhotosWindowMode mode,
447 PhotosWindowMode old_mode)
448 {
449 PhotosTrackerControllerPrivate *priv;
450
451 priv = photos_tracker_controller_get_instance_private (self);
452
453 if (priv->refresh_pending && mode == priv->mode)
454 photos_tracker_controller_refresh_for_source (self);
455 }
456
457
458 static void
photos_tracker_controller_constructed(GObject * object)459 photos_tracker_controller_constructed (GObject *object)
460 {
461 PhotosTrackerController *self = PHOTOS_TRACKER_CONTROLLER (object);
462 PhotosTrackerControllerPrivate *priv;
463 PhotosBaseManager *item_mngr_chld;
464
465 priv = photos_tracker_controller_get_instance_private (self);
466
467 G_OBJECT_CLASS (photos_tracker_controller_parent_class)->constructed (object);
468
469 item_mngr_chld = photos_item_manager_get_for_mode (PHOTOS_ITEM_MANAGER (priv->item_mngr), priv->mode);
470 g_signal_connect_object (item_mngr_chld,
471 "object-added",
472 G_CALLBACK (photos_tracker_controller_item_added_removed),
473 self,
474 G_CONNECT_SWAPPED);
475 g_signal_connect_object (item_mngr_chld,
476 "object-removed",
477 G_CALLBACK (photos_tracker_controller_item_added_removed),
478 self,
479 G_CONNECT_SWAPPED);
480
481 priv->offset_cntrlr = PHOTOS_TRACKER_CONTROLLER_GET_CLASS (self)->get_offset_controller (self);
482 g_signal_connect_swapped (priv->offset_cntrlr,
483 "offset-changed",
484 G_CALLBACK (photos_tracker_controller_offset_changed),
485 self);
486 }
487
488
489 static void
photos_tracker_controller_dispose(GObject * object)490 photos_tracker_controller_dispose (GObject *object)
491 {
492 PhotosTrackerController *self = PHOTOS_TRACKER_CONTROLLER (object);
493 PhotosTrackerControllerPrivate *priv;
494
495 priv = photos_tracker_controller_get_instance_private (self);
496
497 if (priv->reset_count_id != 0)
498 {
499 g_source_remove (priv->reset_count_id);
500 priv->reset_count_id = 0;
501 }
502
503 g_clear_object (&priv->src_mngr);
504 g_clear_object (&priv->offset_cntrlr);
505 g_clear_object (&priv->current_query);
506 g_clear_object (&priv->queue);
507
508 G_OBJECT_CLASS (photos_tracker_controller_parent_class)->dispose (object);
509 }
510
511
512 static void
photos_tracker_controller_finalize(GObject * object)513 photos_tracker_controller_finalize (GObject *object)
514 {
515 PhotosTrackerController *self = PHOTOS_TRACKER_CONTROLLER (object);
516 PhotosTrackerControllerPrivate *priv;
517
518 priv = photos_tracker_controller_get_instance_private (self);
519
520 if (priv->item_mngr != NULL)
521 g_object_remove_weak_pointer (G_OBJECT (priv->item_mngr), (gpointer *) &priv->item_mngr);
522
523 if (priv->mode_cntrlr != NULL)
524 g_object_remove_weak_pointer (G_OBJECT (priv->mode_cntrlr), (gpointer *) &priv->mode_cntrlr);
525
526 g_clear_error (&priv->queue_error);
527
528 G_OBJECT_CLASS (photos_tracker_controller_parent_class)->finalize (object);
529
530 DZL_COUNTER_DEC (instances);
531 }
532
533
534 static void
photos_tracker_controller_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)535 photos_tracker_controller_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
536 {
537 PhotosTrackerController *self = PHOTOS_TRACKER_CONTROLLER (object);
538 PhotosTrackerControllerPrivate *priv;
539
540 priv = photos_tracker_controller_get_instance_private (self);
541
542 switch (prop_id)
543 {
544 case PROP_DELAY_START:
545 priv->delay_start = g_value_get_boolean (value);
546 break;
547
548 case PROP_MODE:
549 priv->mode = (PhotosWindowMode) g_value_get_enum (value);
550 break;
551
552 default:
553 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
554 break;
555 }
556 }
557
558
559 static void
photos_tracker_controller_init(PhotosTrackerController * self)560 photos_tracker_controller_init (PhotosTrackerController *self)
561 {
562 PhotosTrackerControllerPrivate *priv;
563 GApplication *app;
564 PhotosSearchContextState *state;
565
566 DZL_COUNTER_INC (instances);
567
568 priv = photos_tracker_controller_get_instance_private (self);
569
570 app = g_application_get_default ();
571 state = photos_search_context_get_state (PHOTOS_SEARCH_CONTEXT (app));
572
573 priv->cancellable = g_cancellable_new ();
574
575 priv->item_mngr = state->item_mngr;
576 g_object_add_weak_pointer (G_OBJECT (priv->item_mngr), (gpointer *) &priv->item_mngr);
577
578 priv->src_mngr = g_object_ref (state->src_mngr);
579 g_signal_connect_swapped (priv->src_mngr,
580 "object-added",
581 G_CALLBACK (photos_tracker_controller_source_object_added_removed),
582 self);
583 g_signal_connect_swapped (priv->src_mngr,
584 "object-removed",
585 G_CALLBACK (photos_tracker_controller_source_object_added_removed),
586 self);
587
588 priv->mode_cntrlr = state->mode_cntrlr;
589 g_object_add_weak_pointer (G_OBJECT (priv->mode_cntrlr), (gpointer *) &priv->mode_cntrlr);
590 g_signal_connect_swapped (priv->mode_cntrlr,
591 "window-mode-changed",
592 G_CALLBACK (photos_tracker_controller_window_mode_changed),
593 self);
594
595 priv->queue = photos_tracker_queue_dup_singleton (NULL, &priv->queue_error);
596 }
597
598
599 static void
photos_tracker_controller_class_init(PhotosTrackerControllerClass * class)600 photos_tracker_controller_class_init (PhotosTrackerControllerClass *class)
601 {
602 GObjectClass *object_class = G_OBJECT_CLASS (class);
603
604 class->base_item_type = G_TYPE_NONE;
605
606 object_class->constructed = photos_tracker_controller_constructed;
607 object_class->dispose = photos_tracker_controller_dispose;
608 object_class->set_property = photos_tracker_controller_set_property;
609 object_class->finalize = photos_tracker_controller_finalize;
610
611 g_object_class_install_property (object_class,
612 PROP_DELAY_START,
613 g_param_spec_boolean ("delay-start",
614 "Delay start",
615 "Don't start issuing queries immediately on startup",
616 FALSE,
617 G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
618
619 g_object_class_install_property (object_class,
620 PROP_MODE,
621 g_param_spec_enum ("mode",
622 "PhotosWindowMode enum",
623 "The mode handled by this controller",
624 PHOTOS_TYPE_WINDOW_MODE,
625 PHOTOS_WINDOW_MODE_NONE,
626 G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
627
628 signals[QUERY_ERROR] = g_signal_new ("query-error",
629 G_TYPE_FROM_CLASS (class),
630 G_SIGNAL_RUN_LAST,
631 G_STRUCT_OFFSET (PhotosTrackerControllerClass,
632 query_error),
633 NULL, /*accumulator */
634 NULL, /*accu_data */
635 _photos_marshal_VOID__STRING_STRING,
636 G_TYPE_NONE,
637 2,
638 G_TYPE_STRING,
639 G_TYPE_STRING);
640
641 signals[QUERY_STATUS_CHANGED] = g_signal_new ("query-status-changed",
642 G_TYPE_FROM_CLASS (class),
643 G_SIGNAL_RUN_LAST,
644 G_STRUCT_OFFSET (PhotosTrackerControllerClass,
645 query_status_changed),
646 NULL, /*accumulator */
647 NULL, /*accu_data */
648 g_cclosure_marshal_VOID__BOOLEAN,
649 G_TYPE_NONE,
650 1,
651 G_TYPE_BOOLEAN);
652 }
653
654
655 void
photos_tracker_controller_refresh_for_object(PhotosTrackerController * self)656 photos_tracker_controller_refresh_for_object (PhotosTrackerController *self)
657 {
658 photos_tracker_controller_refresh_internal (self, PHOTOS_TRACKER_REFRESH_FLAGS_RESET_OFFSET);
659 }
660
661
662 void
photos_tracker_controller_set_frozen(PhotosTrackerController * self,gboolean frozen)663 photos_tracker_controller_set_frozen (PhotosTrackerController *self, gboolean frozen)
664 {
665 PhotosTrackerControllerPrivate *priv;
666
667 priv = photos_tracker_controller_get_instance_private (self);
668 priv->is_frozen = frozen;
669 }
670
671
672 void
photos_tracker_controller_start(PhotosTrackerController * self)673 photos_tracker_controller_start (PhotosTrackerController *self)
674 {
675 PhotosTrackerControllerPrivate *priv;
676
677 priv = photos_tracker_controller_get_instance_private (self);
678
679 if (priv->delay_start)
680 return;
681
682 if (priv->is_started)
683 return;
684
685 photos_tracker_controller_refresh_internal (self, PHOTOS_TRACKER_REFRESH_FLAGS_NONE);
686 }
687
688
689 gboolean
photos_tracker_controller_get_query_status(PhotosTrackerController * self)690 photos_tracker_controller_get_query_status (PhotosTrackerController *self)
691 {
692 PhotosTrackerControllerPrivate *priv;
693
694 priv = photos_tracker_controller_get_instance_private (self);
695 return priv->querying;
696 }
697