[gnome-software/wip/rancell/paid: 63/63] Purchase dialog WIP
- From: Robert Ancell <rancell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/wip/rancell/paid: 63/63] Purchase dialog WIP
- Date: Fri, 12 Aug 2016 03:14:11 +0000 (UTC)
commit f1cebf3f615a478e6bd8e861ee0d2251f5a3c947
Author: Robert Ancell <robert ancell canonical com>
Date: Fri Aug 12 15:11:47 2016 +1200
Purchase dialog WIP
src/Makefile.am | 3 -
src/gs-page.c | 137 +++++++++++++++++++++++++++++-----------
src/gs-payment-method-list.c | 128 --------------------------------------
src/gs-payment-method-list.h | 46 --------------
src/gs-plugin-loader.c | 17 ++++--
src/gs-plugin-loader.h | 8 +-
src/gs-plugin-vfuncs.h | 6 +-
src/gs-purchase-dialog.c | 49 +++++++++++++++
src/gs-purchase-dialog.h | 16 +++++-
src/gs-purchase-dialog.ui | 42 +++++++++++++
src/plugins/gs-plugin-dummy.c | 4 +-
11 files changed, 226 insertions(+), 230 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 8d581c2..333cada 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -119,7 +119,6 @@ gnome_software_cmd_SOURCES = \
gs-utils.c \
gs-os-release.c \
gs-payment-method.c \
- gs-payment-method-list.c \
gs-plugin-loader.c \
gs-plugin-loader-sync.c \
gs-category.c \
@@ -197,8 +196,6 @@ gnome_software_SOURCES = \
gs-page.h \
gs-payment-method.c \
gs-payment-method.h \
- gs-payment-method-list.c \
- gs-payment-method-list.h \
gs-plugin.c \
gs-plugin.h \
gs-plugin-private.h \
diff --git a/src/gs-page.c b/src/gs-page.c
index cd2f8ef..ce08ea7 100644
--- a/src/gs-page.c
+++ b/src/gs-page.c
@@ -30,6 +30,7 @@
#include "gs-common.h"
#include "gs-auth-dialog.h"
#include "gs-price.h"
+#include "gs-purchase-dialog.h"
typedef struct
{
@@ -80,10 +81,10 @@ gs_page_app_purchased_cb (GObject *source,
g_warning ("failed to purchase %s: %s",
gs_app_get_id (helper->app),
error->message);
- //gs_app_notify_failed_modal (helper->app,
- // gs_shell_get_window (priv->shell),
- // GS_PLUGIN_LOADER_ACTION_PURCHASE,
- // error);
+ gs_app_notify_failed_modal (helper->app,
+ gs_shell_get_window (priv->shell),
+ GS_PLUGIN_LOADER_ACTION_PURCHASE,
+ error);
return;
}
}
@@ -320,6 +321,31 @@ gs_page_set_header_end_widget (GsPage *page, GtkWidget *widget)
}
static void
+gs_page_payment_methods_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data);
+
+static void
+gs_page_payment_methods_authenticate_cb (GtkDialog *dialog,
+ GtkResponseType response_type,
+ GsPageHelper *helper)
+{
+ GsPagePrivate *priv = gs_page_get_instance_private (helper->page);
+
+ /* unmap the dialog */
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+
+ if (response_type != GTK_RESPONSE_OK) {
+ gs_page_helper_free (helper);
+ return;
+ }
+ gs_plugin_loader_get_payment_methods_async (priv->plugin_loader,
+ helper->cancellable,
+ gs_page_payment_methods_cb,
+ helper);
+}
+
+static void
gs_page_purchase_app_response_cb (GtkDialog *dialog,
gint response,
GsPageHelper *helper)
@@ -342,54 +368,89 @@ gs_page_purchase_app_response_cb (GtkDialog *dialog,
helper);
}
-void
-gs_page_purchase_app (GsPage *page, GsApp *app, GCancellable *cancellable)
+static void
+gs_page_payment_methods_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
{
+ g_autoptr(GsPageHelper) helper = (GsPageHelper *) user_data;
+ GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source);
+ GsPage *page = helper->page;
GsPagePrivate *priv = gs_page_get_instance_private (page);
- GsPageHelper *helper;
+ g_autoptr(GPtrArray) payment_methods = NULL;
+ g_autoptr(GError) error = NULL;
GtkWidget *dialog;
- GPtrArray *prices;
- g_autofree gchar *price_text = NULL, *escaped = NULL;
- helper = g_slice_new0 (GsPageHelper);
- helper->app = g_object_ref (app);
- helper->page = g_object_ref (page);
- helper->cancellable = g_object_ref (cancellable);
+ payment_methods = gs_plugin_loader_get_payment_methods_finish (plugin_loader,
+ res,
+ &error);
+ if (g_error_matches (error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED)) {
+ g_debug ("%s", error->message);
+ return;
+ }
+ if (payment_methods == NULL) {
+ /* try to authenticate then retry */
+ if (g_error_matches (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_AUTH_REQUIRED)) {
+ g_autoptr(GError) error_local = NULL;
+ GtkWidget *auth_dialog;
+ auth_dialog = gs_auth_dialog_new (priv->plugin_loader,
+ helper->app,
+ gs_utils_get_error_value (error),
+ &error_local);
+ if (auth_dialog == NULL) {
+ g_warning ("%s", error_local->message);
+ return;
+ }
+ gs_shell_modal_dialog_present (priv->shell, GTK_DIALOG (auth_dialog));
+ g_signal_connect (auth_dialog, "response",
+ G_CALLBACK (gs_page_payment_methods_authenticate_cb),
+ g_steal_pointer (&helper));
+ return;
+ }
- /* ask for confirmation */
- dialog = gtk_message_dialog_new (gs_shell_get_window (priv->shell),
- GTK_DIALOG_MODAL,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_CANCEL,
- /* TRANSLATORS: this is a prompt message, and
- * '%s' is an application summary, e.g. 'GNOME Clocks' */
- _("Are you sure you want to purchase %s?"),
- gs_app_get_name (app));
- prices = gs_app_get_prices (app);
- if (prices->len > 0) {
- GsPrice *price = g_ptr_array_index (prices, 0); // FIXME: Give option of price to choose
- g_autofree gchar *text = NULL;
- price_text = gs_price_to_string (price);
- } else {
- price_text = g_strdup ("nothing"); // FIXME
+ g_warning ("failed to get payment methods: %s",
+ error->message);
+ gs_app_notify_failed_modal (helper->app,
+ gs_shell_get_window (priv->shell),
+ GS_PLUGIN_LOADER_ACTION_PURCHASE,
+ error);
+ return;
}
- escaped = g_markup_escape_text (gs_app_get_name (app), -1);
- gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
- /* TRANSLATORS: Describing what will be purchased */
- _("You will be charged %s and %s will be installed."),
- price_text,
- escaped);
- /* TRANSLATORS: this is button text to purchase the application */
- gtk_dialog_add_button (GTK_DIALOG (dialog), _("Purchase"), GTK_RESPONSE_OK);
+ /* ask for confirmation */
+ dialog = gs_purchase_dialog_new ();
+ gs_purchase_dialog_set_app (GS_PURCHASE_DIALOG (dialog), helper->app);
+ gs_purchase_dialog_set_payment_methods (GS_PURCHASE_DIALOG (dialog), payment_methods);
/* handle this async */
g_signal_connect (dialog, "response",
- G_CALLBACK (gs_page_purchase_app_response_cb), helper);
+ G_CALLBACK (gs_page_purchase_app_response_cb), g_steal_pointer (&helper));
gs_shell_modal_dialog_present (priv->shell, GTK_DIALOG (dialog));
}
void
+gs_page_purchase_app (GsPage *page, GsApp *app, GCancellable *cancellable)
+{
+ GsPagePrivate *priv = gs_page_get_instance_private (page);
+ GsPageHelper *helper;
+
+ helper = g_slice_new0 (GsPageHelper);
+ helper->app = g_object_ref (app);
+ helper->page = g_object_ref (page);
+ helper->cancellable = g_object_ref (cancellable);
+
+ /* load payment methods */
+ gs_plugin_loader_get_payment_methods_async (priv->plugin_loader,
+ helper->cancellable,
+ gs_page_payment_methods_cb,
+ helper);
+}
+
+void
gs_page_install_app (GsPage *page, GsApp *app, GCancellable *cancellable)
{
GsPagePrivate *priv = gs_page_get_instance_private (page);
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index 731bac5..9377fde 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -108,7 +108,7 @@ typedef gboolean (*GsPluginAuthFunc) (GsPlugin *plugin,
GCancellable *cancellable,
GError **error);
typedef gboolean (*GsPluginPaymentMethodFunc) (GsPlugin *plugin,
- GsPaymentMethodList *payment_methods,
+ GPtrArray *payment_methods,
GCancellable *cancellable,
GError **error);
typedef gboolean (*GsPluginPurchaseFunc) (GsPlugin *plugin,
@@ -156,7 +156,7 @@ typedef struct {
GsApp *app;
AsReview *review;
GsAuth *auth;
- GsPaymentMethodList *payment_methods;
+ GPtrArray *payment_methods;
GsPrice *price;
} GsPluginLoaderAsyncState;
@@ -172,7 +172,7 @@ gs_plugin_loader_free_async_state (GsPluginLoaderAsyncState *state)
if (state->review != NULL)
g_object_unref (state->review);
if (state->payment_methods != NULL)
- g_object_unref (state->payment_methods);
+ g_ptr_array_unref (state->payment_methods);
if (state->price != NULL)
g_object_unref (state->price);
if (state->file != NULL)
@@ -2887,6 +2887,13 @@ gs_plugin_loader_add_payment_methods_thread_cb (GTask *task,
cancellable, &error_local);
gs_plugin_loader_action_stop (plugin_loader, plugin);
if (!ret) {
+ /* abort early to allow main thread to process */
+ if (gs_plugin_loader_is_auth_error (error_local)) {
+ g_task_return_error (task, error_local);
+ error_local = NULL;
+ return;
+ }
+
g_warning ("failed to call %s on %s: %s",
state->function_name,
gs_plugin_get_name (plugin),
@@ -3230,7 +3237,7 @@ gs_plugin_loader_get_payment_methods_async (GsPluginLoader *plugin_loader,
/* save state */
state = g_slice_new0 (GsPluginLoaderAsyncState);
- state->payment_methods = gs_payment_method_list_new ();
+ state->payment_methods = g_ptr_array_new_with_free_func (g_object_unref);
state->function_name = "gs_plugin_add_payment_methods";
/* run in a thread */
@@ -3244,7 +3251,7 @@ gs_plugin_loader_get_payment_methods_async (GsPluginLoader *plugin_loader,
*
* Return value: (element-type GsPaymentMethod) (transfer full): A list of payment methods.
**/
-GsPaymentMethodList *
+GPtrArray *
gs_plugin_loader_get_payment_methods_finish (GsPluginLoader *plugin_loader,
GAsyncResult *res,
GError **error)
diff --git a/src/gs-plugin-loader.h b/src/gs-plugin-loader.h
index 2b7f8cf..8e5a74c 100644
--- a/src/gs-plugin-loader.h
+++ b/src/gs-plugin-loader.h
@@ -28,7 +28,6 @@
#include "gs-auth.h"
#include "gs-category.h"
#include "gs-plugin.h"
-#include "gs-payment-method-list.h"
G_BEGIN_DECLS
@@ -48,6 +47,7 @@ struct _GsPluginLoaderClass
};
typedef enum {
+ GS_PLUGIN_LOADER_ACTION_PURCHASE,
GS_PLUGIN_LOADER_ACTION_INSTALL,
GS_PLUGIN_LOADER_ACTION_REMOVE,
GS_PLUGIN_LOADER_ACTION_UPDATE,
@@ -244,9 +244,9 @@ void gs_plugin_loader_get_payment_methods_async (GsPluginLoader
*plugin_loader
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
-GsPaymentMethodList *gs_plugin_loader_get_payment_methods_finish (GsPluginLoader *plugin_loader,
- GAsyncResult *res,
- GError **error);
+GPtrArray *gs_plugin_loader_get_payment_methods_finish (GsPluginLoader *plugin_loader,
+ GAsyncResult *res,
+ GError **error);
void gs_plugin_loader_app_purchase_async (GsPluginLoader *plugin_loader,
GsApp *app,
GsPrice *price,
diff --git a/src/gs-plugin-vfuncs.h b/src/gs-plugin-vfuncs.h
index c38192c..5fef056 100644
--- a/src/gs-plugin-vfuncs.h
+++ b/src/gs-plugin-vfuncs.h
@@ -40,8 +40,8 @@
#include "gs-app.h"
#include "gs-app-list.h"
#include "gs-category.h"
-#include "gs-payment-method-list.h"
#include "gs-price.h"
+#include "gs-payment-method.h"
G_BEGIN_DECLS
@@ -501,7 +501,7 @@ gboolean gs_plugin_update_cancel (GsPlugin *plugin,
/**
* gs_plugin_add_payment_methods:
* @plugin: a #GsPlugin
- * @payment_methods: A #GsPaymentMethodList
+ * @payment_methods: (element-type GsPaymentMethod): a #GPtrArray
* @cancellable: a #GCancellable, or %NULL
* @error: a #GError, or %NULL
*
@@ -510,7 +510,7 @@ gboolean gs_plugin_update_cancel (GsPlugin *plugin,
* Returns: %TRUE for success or if not relevant
**/
gboolean gs_plugin_add_payment_methods (GsPlugin *plugin,
- GsPaymentMethodList *payment_methods,
+ GPtrArray *payment_methods,
GCancellable *cancellable,
GError **error);
diff --git a/src/gs-purchase-dialog.c b/src/gs-purchase-dialog.c
index 2e332a1..58d799f 100644
--- a/src/gs-purchase-dialog.c
+++ b/src/gs-purchase-dialog.c
@@ -29,10 +29,55 @@
struct _GsPurchaseDialog
{
GtkDialog parent_instance;
+
+ GtkWidget *label_title;
+ GtkWidget *combo_payment_method;
+ GtkListStore *model_payment_method;
};
G_DEFINE_TYPE (GsPurchaseDialog, gs_purchase_dialog, GTK_TYPE_DIALOG)
+void
+gs_purchase_dialog_set_app (GsPurchaseDialog *dialog, GsApp *app)
+{
+ g_return_if_fail (GS_IS_PURCHASE_DIALOG (dialog));
+}
+
+void
+gs_purchase_dialog_set_payment_methods (GsPurchaseDialog *dialog, GPtrArray *payment_methods)
+{
+ guint i;
+
+ g_return_if_fail (GS_IS_PURCHASE_DIALOG (dialog));
+
+ gtk_list_store_clear (dialog->model_payment_method);
+ for (i = 0; i < payment_methods->len; i++) {
+ GtkTreeIter iter;
+ GsPaymentMethod *method = payment_methods->pdata[i];
+
+ gtk_list_store_append (dialog->model_payment_method, &iter);
+ gtk_list_store_set (dialog->model_payment_method, &iter,
+ 0, gs_payment_method_get_description (method),
+ 1, method,
+ -1);
+ }
+}
+
+
+GsPrice *
+gs_purchase_dialog_get_price (GsPurchaseDialog *dialog)
+{
+ g_return_val_if_fail (GS_IS_PURCHASE_DIALOG (dialog), NULL);
+ return NULL;
+}
+
+GsPaymentMethod *
+gs_purchase_dialog_get_payment_method (GsPurchaseDialog *dialog)
+{
+ g_return_val_if_fail (GS_IS_PURCHASE_DIALOG (dialog), NULL);
+ return NULL;
+}
+
static void
gs_purchase_dialog_init (GsPurchaseDialog *dialog)
{
@@ -45,6 +90,10 @@ gs_purchase_dialog_class_init (GsPurchaseDialogClass *klass)
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/Software/gs-purchase-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, GsPurchaseDialog, label_title);
+ gtk_widget_class_bind_template_child (widget_class, GsPurchaseDialog, combo_payment_method);
+ gtk_widget_class_bind_template_child (widget_class, GsPurchaseDialog, model_payment_method);
}
GtkWidget *
diff --git a/src/gs-purchase-dialog.h b/src/gs-purchase-dialog.h
index e91ff21..9ef63a1 100644
--- a/src/gs-purchase-dialog.h
+++ b/src/gs-purchase-dialog.h
@@ -24,13 +24,27 @@
#include <gtk/gtk.h>
+#include "gs-app.h"
+#include "gs-price.h"
+#include "gs-payment-method.h"
+
G_BEGIN_DECLS
#define GS_TYPE_PURCHASE_DIALOG (gs_purchase_dialog_get_type ())
G_DECLARE_FINAL_TYPE (GsPurchaseDialog, gs_purchase_dialog, GS, PURCHASE_DIALOG, GtkDialog)
-GtkWidget *gs_purchase_dialog_new (void);
+GtkWidget *gs_purchase_dialog_new (void);
+
+void gs_purchase_dialog_set_app (GsPurchaseDialog *dialog,
+ GsApp *app);
+
+void gs_purchase_dialog_set_payment_methods (GsPurchaseDialog *dialog,
+ GPtrArray *payment_methods);
+
+GsPrice *gs_purchase_dialog_get_price (GsPurchaseDialog *dialog);
+
+GsPaymentMethod *gs_purchase_dialog_get_payment_method (GsPurchaseDialog *dialog);
G_END_DECLS
diff --git a/src/gs-purchase-dialog.ui b/src/gs-purchase-dialog.ui
index 6dafab6..0d993a6 100644
--- a/src/gs-purchase-dialog.ui
+++ b/src/gs-purchase-dialog.ui
@@ -66,6 +66,40 @@
<property name="position">0</property>
</packing>
</child>
+ <child>
+ <object class="GtkGrid">
+ <property name="name">intro</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="row_spacing">9</property>
+ <property name="column_spacing">9</property>
+ <child>
+ <object class="GtkLabel" id="label_title">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label">Are you sure you want to purchase %NAME% for %PRICE%?</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combo_payment_method">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">model_payment_method</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
</object>
</child>
</template>
@@ -77,4 +111,12 @@
<widget name="purchase_button"/>
</widgets>
</object>
+ <object class="GtkListStore" id="model_payment_method">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchar"/>
+ <!-- column-name object -->
+ <column type="GObject"/>
+ </columns>
+ </object>
</interface>
diff --git a/src/plugins/gs-plugin-dummy.c b/src/plugins/gs-plugin-dummy.c
index 5b94b1d..a9290f1 100644
--- a/src/plugins/gs-plugin-dummy.c
+++ b/src/plugins/gs-plugin-dummy.c
@@ -656,7 +656,7 @@ gs_plugin_update_cancel (GsPlugin *plugin, GsApp *app,
*/
gboolean
gs_plugin_add_payment_methods (GsPlugin *plugin,
- GsPaymentMethodList *payment_methods,
+ GPtrArray *payment_methods,
GCancellable *cancellable,
GError **error)
{
@@ -665,7 +665,7 @@ gs_plugin_add_payment_methods (GsPlugin *plugin,
method = gs_payment_method_new ();
gs_payment_method_set_description (method, "Test Payment Method");
gs_payment_method_add_metadata (method, "card-number", "0000 0000 0000 0000");
- gs_payment_method_list_add (payment_methods, method);
+ g_ptr_array_add (payment_methods, method);
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]