static void
photos_export_dialog_guess_sizes (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
  PhotosExportDialog *self;
  PhotosBaseItem *item = PHOTOS_BASE_ITEM (source_object);
  GError *error;
  gchar *size_str;
  gsize sizes[2];

  error = NULL;
  if (!photos_base_item_save_guess_sizes_finish (item, res, &sizes[0], &sizes[1], &error))
    {
      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
        g_warning ("Unable to guess sizes: %s", error->message);
      g_error_free (error);
      return;
    }

  self = PHOTOS_EXPORT_DIALOG (user_data);

  size_str = g_format_size ((guint64) sizes[0]);
  gtk_label_set_text (GTK_LABEL (self->full_label), size_str);
  g_free (size_str);

  if (self->reduced_zoom > 0.0)
    {
      gsize reduced_size;

      reduced_size = (gsize) (sizes[1] + (sizes[0] - sizes[1]) * (self->reduced_zoom - 0.5) / (1.0 - 0.5) + 0.5);
      size_str = g_format_size ((guint64) reduced_size);
      gtk_label_set_text (GTK_LABEL (self->reduced_label), size_str);
      g_free (size_str);
    }
}
static void
photos_export_dialog_constructed (GObject *object)
{
  PhotosExportDialog *self = PHOTOS_EXPORT_DIALOG (object);

  G_OBJECT_CLASS (photos_export_dialog_parent_class)->constructed (object);

  if (photos_base_item_is_collection (self->item))
    {
      const gchar *name;

      name = photos_base_item_get_name_with_fallback (self->item);
      gtk_entry_set_text (GTK_ENTRY (self->dir_entry), name);
    }
  else
    {
      GDateTime *now;
      GeglRectangle bbox;
      gboolean got_bbox_edited;
      gchar *now_str;
      gint max_dimension;
      guint i;

      got_bbox_edited = photos_base_item_get_bbox_edited (self->item, &bbox);
      g_return_if_fail (got_bbox_edited);

      max_dimension = MAX (bbox.height, bbox.width);
      for (i = 0; i < G_N_ELEMENTS (PIXEL_SIZES); i++)
        {
          if (max_dimension > PIXEL_SIZES[i])
            {
              self->reduced_zoom = (gdouble) PIXEL_SIZES[i] / (gdouble) max_dimension;
              photos_export_dialog_show_size_options (self);
              photos_base_item_save_guess_sizes_async (self->item,
                                                       self->cancellable,
                                                       photos_export_dialog_guess_sizes,
                                                       self);
              break;
            }
        }

      now = g_date_time_new_now_local ();

      /* Translators: this is the default sub-directory where photos
       *  will be exported.
       */
      now_str = g_date_time_format (now, _("%e %B %Y"));

      gtk_entry_set_text (GTK_ENTRY (self->dir_entry), now_str);

      g_free (now_str);
      g_date_time_unref (now);
    }
}
static void
photos_export_dialog_guess_sizes (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
  PhotosExportDialog *self;
  PhotosBaseItem *item = PHOTOS_BASE_ITEM (source_object);
  PhotosBaseItemSize full;
  PhotosBaseItemSize reduced;
  gboolean success;

  {
    g_autoptr (GError) error = NULL;

    success = photos_base_item_guess_save_sizes_finish (item, res, &full, &reduced, &error);
    if (error != NULL)
      {
        if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
          goto out;

        g_warning ("Unable to guess sizes: %s", error->message);
      }
  }

  self = PHOTOS_EXPORT_DIALOG (user_data);

  if (success)
    {
      {
        g_autofree gchar *size_str = NULL;
        g_autofree gchar *size_str_markup = NULL;

        size_str = photos_export_dialog_create_size_str (full.height, full.width, (guint64) full.bytes);
        size_str_markup = g_strdup_printf ("<small>%s</small>", size_str);
        gtk_label_set_markup (GTK_LABEL (self->full_label), size_str_markup);
      }

      self->reduced_zoom = reduced.zoom;
      if (self->reduced_zoom > 0.0)
        {
          g_autofree gchar *size_str = NULL;
          g_autofree gchar *size_str_markup = NULL;

          size_str = photos_export_dialog_create_size_str (reduced.height, reduced.width, (guint64) reduced.bytes);
          size_str_markup = g_strdup_printf ("<small>%s</small>", size_str);
          gtk_label_set_markup (GTK_LABEL (self->reduced_label), size_str_markup);
        }
    }

  photos_export_dialog_show_size_options (self, self->reduced_zoom > 0.0, FALSE);

 out:
  return;
}
static void
photos_export_dialog_dispose (GObject *object)
{
  PhotosExportDialog *self = PHOTOS_EXPORT_DIALOG (object);

  if (self->cancellable != NULL)
    g_cancellable_cancel (self->cancellable);

  g_clear_object (&self->cancellable);
  g_clear_object (&self->item);

  G_OBJECT_CLASS (photos_export_dialog_parent_class)->dispose (object);
}
static void
photos_export_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
  PhotosExportDialog *self = PHOTOS_EXPORT_DIALOG (object);

  switch (prop_id)
    {
    case PROP_ITEM:
      self->item = PHOTOS_BASE_ITEM (g_value_dup_object (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}
static void
photos_export_dialog_constructed (GObject *object)
{
  PhotosExportDialog *self = PHOTOS_EXPORT_DIALOG (object);

  G_OBJECT_CLASS (photos_export_dialog_parent_class)->constructed (object);

  if (photos_base_item_is_collection (self->item))
    {
      const gchar *name;

      name = photos_base_item_get_name_with_fallback (self->item);
      gtk_entry_set_text (GTK_ENTRY (self->dir_entry), name);
    }
  else
    {
      g_autoptr (GDateTime) now = NULL;
      g_autofree gchar *now_str = NULL;

      now = g_date_time_new_now_local ();

      /* Translators: this is the default sub-directory where photos
       * will be exported.
       */
      now_str = g_date_time_format (now, _("%-d %B %Y"));

      gtk_entry_set_text (GTK_ENTRY (self->dir_entry), now_str);

      photos_export_dialog_show_size_options (self, FALSE, TRUE);
      photos_base_item_guess_save_sizes_async (self->item,
                                               self->cancellable,
                                               photos_export_dialog_guess_sizes,
                                               self);
    }

  gtk_widget_grab_focus (self->dir_entry);
}