[libpanel/wip/chergert/fix-14] save-delegate: add close signal



commit 120af7ac9bec650ef3c253661ac0fbc5fa7207f2
Author: Christian Hergert <chergert redhat com>
Date:   Tue Sep 13 11:20:46 2022 -0700

    save-delegate: add close signal
    
    This is similar to discard but only requests the page be closed, it does
    not request that the contents be dropped.

 src/panel-save-delegate.c | 29 ++++++++++++++
 src/panel-save-delegate.h |  3 ++
 src/panel-save-dialog.c   | 96 ++++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 122 insertions(+), 6 deletions(-)
---
diff --git a/src/panel-save-delegate.c b/src/panel-save-delegate.c
index 1821ac7..9d4a9dd 100644
--- a/src/panel-save-delegate.c
+++ b/src/panel-save-delegate.c
@@ -47,6 +47,7 @@ enum {
 };
 
 enum {
+  CLOSE,
   DISCARD,
   SAVE,
   N_SIGNALS
@@ -330,6 +331,26 @@ panel_save_delegate_class_init (PanelSaveDelegateClass *klass)
                                  NULL,
                                  G_TYPE_BOOLEAN, 1, G_TYPE_TASK);
 
+  /**
+   * PanelSaveDelegate::close:
+   * @self: a #PanelSaveDelegate
+   *
+   * This signal is emitted when the save delegate should close
+   * the widget it is related to. This can happen after saving as
+   * part of a close request and it is now save for the delegate to
+   * close.
+   *
+   * Implementations are encouraged to connect to this signal (or
+   * implement the virtual method) and call panel_widget_force_close().
+   */
+  signals [CLOSE] = g_signal_new ("close",
+                                  G_TYPE_FROM_CLASS (klass),
+                                  G_SIGNAL_RUN_LAST,
+                                  G_STRUCT_OFFSET (PanelSaveDelegateClass, close),
+                                  NULL, NULL,
+                                  NULL,
+                                  G_TYPE_NONE, 0);
+
   /**
    * PanelSaveDelegate::discard:
    * @self: a #PanelSaveDelegate
@@ -593,6 +614,14 @@ panel_save_delegate_set_is_draft (PanelSaveDelegate *self,
     }
 }
 
+void
+panel_save_delegate_close (PanelSaveDelegate *self)
+{
+  g_return_if_fail (PANEL_IS_SAVE_DELEGATE (self));
+
+  g_signal_emit (self, signals [CLOSE], 0);
+}
+
 void
 panel_save_delegate_discard (PanelSaveDelegate *self)
 {
diff --git a/src/panel-save-delegate.h b/src/panel-save-delegate.h
index 2a5d2a3..9242cdb 100644
--- a/src/panel-save-delegate.h
+++ b/src/panel-save-delegate.h
@@ -45,6 +45,7 @@ struct _PanelSaveDelegateClass
   gboolean (*save)        (PanelSaveDelegate  *self,
                            GTask              *task);
   void     (*discard)     (PanelSaveDelegate  *self);
+  void     (*close)       (PanelSaveDelegate  *self);
 
   /*< private >*/
   gpointer _reserved[8];
@@ -92,6 +93,8 @@ gboolean           panel_save_delegate_save_finish   (PanelSaveDelegate    *self
                                                       GAsyncResult         *result,
                                                       GError              **error);
 PANEL_AVAILABLE_IN_ALL
+void               panel_save_delegate_close         (PanelSaveDelegate    *self);
+PANEL_AVAILABLE_IN_ALL
 void               panel_save_delegate_discard       (PanelSaveDelegate    *self);
 
 G_END_DECLS
diff --git a/src/panel-save-dialog.c b/src/panel-save-dialog.c
index d795df7..0ca68cf 100644
--- a/src/panel-save-dialog.c
+++ b/src/panel-save-dialog.c
@@ -37,8 +37,23 @@ struct _PanelSaveDialog
   GTask               *task;
 };
 
+typedef struct
+{
+  GPtrArray *delegates;
+  guint n_active;
+} Save;
+
 G_DEFINE_FINAL_TYPE (PanelSaveDialog, panel_save_dialog, ADW_TYPE_MESSAGE_DIALOG)
 
+static void
+save_free (gpointer data)
+{
+  Save *save = data;
+
+  g_clear_pointer (&save->delegates, g_ptr_array_unref);
+  g_slice_free (Save, save);
+}
+
 /**
  * panel_save_dialog_new:
  *
@@ -95,22 +110,73 @@ panel_save_dialog_response_discard_cb (PanelSaveDialog *self,
   g_clear_object (&task);
 }
 
+static void
+panel_save_dialog_save_cb (GObject      *object,
+                           GAsyncResult *result,
+                           gpointer      user_data)
+{
+  PanelSaveDelegate *delegate = (PanelSaveDelegate *)object;
+  GTask *task = user_data;
+  GError *error = NULL;
+  Save *save;
+
+  g_assert (PANEL_IS_SAVE_DELEGATE (delegate));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (G_IS_TASK (task));
+
+  save = g_task_get_task_data (task);
+  save->n_active--;
+
+  if (!panel_save_delegate_save_finish (delegate, result, &error))
+    {
+      if (!g_task_had_error (task))
+        g_task_return_error (task, g_steal_pointer (&error));
+    }
+
+  if (save->n_active == 0)
+    {
+      if (!g_task_had_error (task))
+        g_task_return_boolean (task, TRUE);
+    }
+
+  g_clear_object (&task);
+  g_clear_error (&error);
+}
+
 static void
 panel_save_dialog_response_save_cb (PanelSaveDialog *self,
                                     const char      *response)
 {
-  GTask *task;
+  Save *save;
 
   g_assert (PANEL_IS_SAVE_DIALOG (self));
+  g_assert (self->task != NULL);
 
-  task = g_steal_pointer (&self->task);
+  adw_message_dialog_set_response_enabled (ADW_MESSAGE_DIALOG (self), "save", FALSE);
+  adw_message_dialog_set_response_enabled (ADW_MESSAGE_DIALOG (self), "discard", FALSE);
 
-  /* TODO: Save using delegates */
-  g_task_return_boolean (task, TRUE);
+  save = g_slice_new0 (Save);
+  save->delegates = g_ptr_array_new_with_free_func (g_object_unref);
+  g_task_set_task_data (self->task, save, save_free);
 
-  gtk_window_destroy (GTK_WINDOW (self));
+  for (guint i = 0; i < self->rows->len; i++)
+    {
+      PanelSaveDialogRow *row = g_ptr_array_index (self->rows, i);
+      PanelSaveDelegate *delegate = panel_save_dialog_row_get_delegate (row);
 
-  g_clear_object (&task);
+      if (!panel_save_dialog_row_get_selected (row))
+        continue;
+
+      g_ptr_array_add (save->delegates, g_object_ref (delegate));
+
+      panel_save_delegate_save_async (delegate,
+                                      g_task_get_cancellable (self->task),
+                                      panel_save_dialog_save_cb,
+                                      g_object_ref (self->task));
+    }
+
+  if (save->delegates->len == 0)
+    g_task_return_boolean (self->task, TRUE);
 }
 
 static void
@@ -328,6 +394,18 @@ panel_save_dialog_add_delegate (PanelSaveDialog   *self,
   panel_save_dialog_update (self);
 }
 
+static void
+task_completed_cb (PanelSaveDialog *self,
+                   GParamSpec      *pspec,
+                   GTask           *task)
+{
+  g_assert (PANEL_IS_SAVE_DIALOG (self));
+  g_assert (G_IS_TASK (task));
+
+  if (self->task == task)
+    g_clear_object (&self->task);
+}
+
 void
 panel_save_dialog_run_async (PanelSaveDialog     *self,
                              GCancellable        *cancellable,
@@ -344,6 +422,12 @@ panel_save_dialog_run_async (PanelSaveDialog     *self,
   task = g_task_new (self, cancellable, callback, user_data);
   g_task_set_source_tag (task, panel_save_dialog_run_async);
 
+  g_signal_connect_object (task,
+                           "notify::complete",
+                           G_CALLBACK (task_completed_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+
   if (self->rows->len == 0)
     {
       gtk_window_destroy (GTK_WINDOW (self));


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