/* * Copyright (C) 2014 Juan Pablo Ugarte. * * 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. * * Authors: * Juan Pablo Ugarte */ #include "config.h" #include "glade-registration.h" #include "glade-http.h" #include "glade-logo.h" #include #include #define CONFIG_GROUP "User & Survey" /* translators: Email subject sent to the user after completing the survey */ #define MAIL_SUBJECT _("Glade User Survey") /* translators: Email body sent to the user after completing the survey */ #define MAIL_BODY _("Thank you for taking Glade Users survey, we appreciate it!\n\nTo validate this email address open the folowing link\n\nhttps://people.gnome.org/~jpu/glade/registration.php?email=$email&validation_token=$new_validation_token\n\nIn case you want to change or update the survey, your current update token is:\n$new_token\n\nCheers\n\n The Glade team\n") /* translators: Email subject sent to the user after updating the survey */ #define UPDATE_MAIL_SUBJECT _("Glade User Survey (update)") /* translators: Email body sent to the user after updating the survey */ #define UPDATE_MAIL_BODY _("Thank you for updating your Glade Users survey data, we appreciate it!\n\nIn case you want to change something again, your current update token is:\n$new_token\n\nCheers\n\n The Glade team\n") struct _GladeRegistrationPrivate { GtkWidget *infobar; GtkWidget *net_spinner; GtkLabel *infobar_label; GtkLabel *status_label; GladeHTTP *http; GladeHTTP *sub_http; GCancellable *cancellable; /* Form widgets */ GtkWidget *name; GtkWidget *email; GtkWidget *country_id; GtkWidget *city; GtkWidget *contact_type; GtkWidget *contact_name; GtkWidget *contact_website; GtkWidget *subscribe; GtkWidget *update_token_checkbutton; GtkWidget *update_token; GtkWidget *experience; GtkWidget *experience_unit; GtkWidget *experience_not_programmer; GtkWidget *lang_c; GtkWidget *lang_cpp; GtkWidget *lang_csharp; GtkWidget *lang_java; GtkWidget *lang_python; GtkWidget *lang_javascript; GtkWidget *lang_vala; GtkWidget *lang_perl; GtkWidget *lang_other; GtkWidget *start_using; GtkWidget *start_using_unit; GtkWidget *version; GtkWidget *version_other; GtkWidget *os; GtkWidget *os_linux; GtkWidget *os_bsd; GtkWidget *os_windows; GtkWidget *os_osx; GtkWidget *os_solaris; GtkWidget *os_other; GtkWidget *freq; GtkWidget *user_level; GtkWidget *soft_free; GtkWidget *soft_open; GtkWidget *soft_commercial; GtkWidget *soft_none; GtkWidget *field_academic; GtkWidget *field_accounting; GtkWidget *field_desktop; GtkWidget *field_educational; GtkWidget *field_embedded; GtkWidget *field_medical; GtkWidget *field_industrial; GtkWidget *field_scientific; GtkWidget *field_other; GtkWidget *improvement; GtkWidget *problem; GtkWidget *problem_other; GtkWidget *bug; GtkWidget *bugzilla; GtkWidget *contributing; GtkWidget *contributing_whynot; GtkWidget *comments; }; G_DEFINE_TYPE_WITH_PRIVATE (GladeRegistration, glade_registration, GTK_TYPE_DIALOG); enum { PROP_0, PROP_COMPLETED, PROP_SKIP_REMINDER }; static void string_append_input_key_value_tuple (GString *string, const gchar *name, GtkWidget *input) { if (string->len) g_string_append_c (string, '&'); g_string_append (string, name); g_string_append_c (string, '='); if (GTK_IS_ENTRY (input)) g_string_append_uri_escaped (string, gtk_entry_get_text (GTK_ENTRY (input)), NULL, FALSE); else if (GTK_IS_TEXT_VIEW (input)) { GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (input)); GtkTextIter start, end; gchar *text; gtk_text_buffer_get_bounds (buffer, &start, &end); text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); g_string_append_uri_escaped (string, text ? text : "", NULL, FALSE); g_free (text); } else if (GTK_IS_COMBO_BOX (input)) g_string_append_uri_escaped (string, gtk_combo_box_get_active_id (GTK_COMBO_BOX (input)), NULL, FALSE); else if (GTK_IS_RADIO_BUTTON (input)) { GSList *group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (input)); for (; group; group = g_slist_next (group)) { if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (group->data))) g_string_append (string, gtk_widget_get_name (group->data)); } } else if (GTK_IS_TOGGLE_BUTTON (input)) g_string_append_printf (string, "%d", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (input)) ? 1 : 0); } static void glade_registration_show_message (GladeRegistration *registration, GtkMessageType type, const gchar *format, ...) G_GNUC_PRINTF (3, 4); static void glade_registration_show_message (GladeRegistration *registration, GtkMessageType type, const gchar *format, ...) { GladeRegistrationPrivate *priv = registration->priv; gtk_info_bar_set_message_type (GTK_INFO_BAR (priv->infobar), type); if (format) { va_list args; gchar *string; va_start (args, format); string = g_strdup_vprintf (format, args); va_end (args); gtk_label_set_text (priv->infobar_label, string); g_free (string); } else gtk_label_set_text (priv->infobar_label, ""); /* Only show the infobar if the dialog is visible */ if (gtk_widget_is_visible (GTK_WIDGET (registration))) gtk_widget_show (priv->infobar); } #ifdef GDK_WINDOWING_X11 #include "gdk/gdkx.h" #endif #ifdef GDK_WINDOWING_QUARTZ #include "gdk/gdkquartz.h" #endif #ifdef GDK_WINDOWING_WIN32 #include "gdk/gdkwin32.h" #endif #ifdef GDK_WINDOWING_WAYLAND #include "gdk/gdkwayland.h" #endif #ifdef GDK_WINDOWING_BROADWAY #include "gdk/gdkbroadway.h" #endif static const gchar * get_gdk_backend (GtkWidget *widget) { GdkDisplay *display = gtk_widget_get_display (widget); #ifdef GDK_WINDOWING_X11 if (GDK_IS_X11_DISPLAY (display)) return "X11"; else #endif #ifdef GDK_WINDOWING_QUARTZ if (GDK_IS_QUARTZ_DISPLAY (display)) return "Quartz"; else #endif #ifdef GDK_WINDOWING_WIN32 if (GDK_IS_WIN32_DISPLAY (display)) return "Win32"; else #endif #ifdef GDK_WINDOWING_WAYLAND if (GDK_IS_WAYLAND_DISPLAY (display)) return "Wayland"; else #endif #ifdef GDK_WINDOWING_BROADWAY if (GDK_IS_BROADWAY_DISPLAY (display)) return "Broadway"; else #endif { return "Unknown"; } } static void glade_registration_http_post (GladeRegistration *registration, GladeHTTP *http, GCancellable *cancellable, const gchar *url, GString *content) { const gchar *lang = pango_language_to_string (pango_language_get_default ()); glade_http_request_send_async (http, cancellable, "POST %s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: Glade/"PACKAGE_VERSION" (%s; Gtk+ %d.%d.%d; glib %d.%d.%d; %s)\r\n" "Connection: close\r\n" "Accept: text/plain\r\n" "Accept-Language: %s\r\n" "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Length: %"G_GSIZE_FORMAT"\r\n" "\r\n%s", url, /* POST url */ glade_http_get_host (http), /* Host */ get_gdk_backend (GTK_WIDGET (registration)), /* User-Agent backend */ GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION, /* User-Agent gtk version */ glib_major_version, glib_minor_version, glib_micro_version,/* User-Agent glib version */ lang, /* User-Agent language */ lang, /* Accept-Language */ content->len, /* Content-length */ content->str); /* content */ } #define append_input_tuple(s,i) string_append_input_key_value_tuple (s, #i, priv->i) static void on_http_status (GladeHTTP *http, GladeHTTPStatus status, GError *error, GladeRegistration *registration) { gchar *text = NULL; switch (status) { case GLADE_HTTP_READY: break; case GLADE_HTTP_CONNECTING: text = g_strdup_printf (_("Connecting to %s"), glade_http_get_host (http)); break; case GLADE_HTTP_SENDING: text = g_strdup_printf (_("Sending data to %s"), glade_http_get_host (http)); break; case GLADE_HTTP_WAITING: text = g_strdup_printf (_("Waiting for %s"), glade_http_get_host (http)); break; case GLADE_HTTP_RECEIVING: text = g_strdup_printf (_("Receiving data from %s"), glade_http_get_host (http)); break; case GLADE_HTTP_ERROR: glade_registration_show_message (registration, GTK_MESSAGE_WARNING, "%s", error->message); break; } gtk_label_set_text (registration->priv->status_label, text ? text : ""); gtk_widget_set_visible (registration->priv->net_spinner, text != NULL); g_free (text); } static void on_subscribe_http_request_done (GladeHTTP *http, gint code, const gchar **headers, const gchar **values, const gchar *response, GladeRegistration *registration) { GtkDialog *dialog; GtkWidget *button; if (code == 200) return; dialog = GTK_DIALOG (gtk_message_dialog_new (GTK_WINDOW (registration), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "%s", _("Sorry, automatic subscription to Glade Users mailing list failed"))); button = gtk_link_button_new_with_label ("http://lists.ximian.com/mailman/listinfo/glade-users", _("Open Glade Users Website")); gtk_widget_show (button); gtk_dialog_add_action_widget (dialog, button, GTK_RESPONSE_CANCEL); gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (gtk_dialog_get_action_area (dialog)), button, TRUE); gtk_dialog_run (dialog); gtk_widget_destroy (GTK_WIDGET (dialog)); } static void glade_registration_subscribe_email (GladeRegistration *registration) { GladeRegistrationPrivate *priv = registration->priv; GString *post; if (!priv->sub_http) { priv->sub_http = glade_http_new ("lists.ximian.com", 80, FALSE); g_signal_connect_object (priv->sub_http, "request-done", G_CALLBACK (on_subscribe_http_request_done), registration, 0); } post = g_string_new (""); string_append_input_key_value_tuple (post, "email", priv->email); string_append_input_key_value_tuple (post, "fullname", priv->name); glade_registration_http_post (registration, priv->sub_http, NULL, "/mailman/subscribe/glade-users", post); g_string_free (post, TRUE); } #define append_input_tuple(s,i) string_append_input_key_value_tuple (s, #i, priv->i) static void on_http_request_done (GladeHTTP *http, gint code, const gchar **headers, const gchar **values, const gchar *response, GladeRegistration *registration) { switch (code) { case 100: /* Ignore Continue HTTP response */ break; case 200: { const gchar *status = NULL, *message = _("Internal server error"); GladeRegistrationPrivate *priv = registration->priv; gint i; for (i = 0; headers[i]; i++) { if (g_strcmp0 (headers[i], "X-Glade-Status") == 0) status = values[i]; else if (g_strcmp0 (headers[i], "X-Glade-Message") == 0) message = values[i]; } if (status == NULL) glade_registration_show_message (registration, GTK_MESSAGE_WARNING, "%s", message); else if (g_strcmp0 (status, "ok") == 0) { gtk_label_set_text (priv->status_label, ""); gtk_widget_hide (priv->net_spinner); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->subscribe))) glade_registration_subscribe_email (registration); glade_util_ui_message (GTK_WIDGET (registration), GLADE_UI_INFO, NULL, "%s", _("Thank you for taking the time to complete the survey, we appreciate it!")); gtk_widget_hide (GTK_WIDGET (registration)); g_object_set (registration, "completed", TRUE, NULL); glade_app_config_save (); } else if (g_strcmp0 (status, "error_required_field") == 0) glade_registration_show_message (registration, GTK_MESSAGE_INFO, "%s", _("Name and Email fields are required")); else if (g_strcmp0 (status, "error_email_in_use") == 0) glade_registration_show_message (registration, GTK_MESSAGE_WARNING, "%s", _("Oops! Email address is already in use!\nTo update information you need to provide the token that was sent to your inbox.")); else if (g_strcmp0 (status, "error_db_user_info") == 0) glade_registration_show_message (registration, GTK_MESSAGE_WARNING, _("Oops! Error saving user information: %s"), message); else if (g_strcmp0 (status, "error_db_survey_data") == 0) glade_registration_show_message (registration, GTK_MESSAGE_WARNING, _("Oops! Error saving survey data: %s"), message); else if (g_strcmp0 (status, "error_db") == 0) glade_registration_show_message (registration, GTK_MESSAGE_WARNING, _("Oops! Error accessing DB: %s"), message); else glade_registration_show_message (registration, GTK_MESSAGE_WARNING, "%s", message); } break; default: glade_registration_show_message (registration, GTK_MESSAGE_WARNING, "%s", response ? response : ""); break; } } static void glade_registration_clear_cancellable (GladeRegistrationPrivate *priv) { if (priv->cancellable) { g_cancellable_cancel (priv->cancellable); g_clear_object (&priv->cancellable); } } static void on_registration_dialog_response (GtkDialog *dialog, gint response_id) { GladeRegistrationPrivate *priv = GLADE_REGISTRATION (dialog)->priv; GString *post; gtk_widget_hide (priv->infobar); if (response_id != GTK_RESPONSE_APPLY) { gtk_widget_hide (GTK_WIDGET (dialog)); glade_registration_clear_cancellable (priv); return; } glade_registration_clear_cancellable (priv); priv->cancellable = g_cancellable_new (); post = g_string_new (""); append_input_tuple (post, name); append_input_tuple (post, email); append_input_tuple (post, country_id); append_input_tuple (post, city); append_input_tuple (post, contact_type); append_input_tuple (post, contact_name); append_input_tuple (post, contact_website); append_input_tuple (post, update_token_checkbutton); append_input_tuple (post, update_token); append_input_tuple (post, experience); append_input_tuple (post, experience_unit); append_input_tuple (post, experience_not_programmer); append_input_tuple (post, lang_c); append_input_tuple (post, lang_cpp); append_input_tuple (post, lang_csharp); append_input_tuple (post, lang_java); append_input_tuple (post, lang_python); append_input_tuple (post, lang_javascript); append_input_tuple (post, lang_vala); append_input_tuple (post, lang_perl); append_input_tuple (post, lang_other); append_input_tuple (post, start_using); append_input_tuple (post, start_using_unit); append_input_tuple (post, version); append_input_tuple (post, version_other); append_input_tuple (post, os); string_append_input_key_value_tuple (post, "linux", priv->os_linux); string_append_input_key_value_tuple (post, "bsd", priv->os_bsd); string_append_input_key_value_tuple (post, "windows", priv->os_windows); string_append_input_key_value_tuple (post, "osx", priv->os_osx); string_append_input_key_value_tuple (post, "solaris", priv->os_solaris); append_input_tuple (post, os_other); append_input_tuple (post, freq); append_input_tuple (post, user_level); append_input_tuple (post, soft_free); append_input_tuple (post, soft_open); append_input_tuple (post, soft_commercial); append_input_tuple (post, soft_none); append_input_tuple (post, field_academic); append_input_tuple (post, field_accounting); append_input_tuple (post, field_desktop); append_input_tuple (post, field_educational); append_input_tuple (post, field_embedded); append_input_tuple (post, field_medical); append_input_tuple (post, field_industrial); append_input_tuple (post, field_scientific); append_input_tuple (post, field_other); append_input_tuple (post, improvement); append_input_tuple (post, problem); append_input_tuple (post, problem_other); append_input_tuple (post, bug); append_input_tuple (post, bugzilla); append_input_tuple (post, contributing); append_input_tuple (post, contributing_whynot); append_input_tuple (post, comments); glade_registration_http_post (GLADE_REGISTRATION (dialog), priv->http, priv->cancellable, "/~jpu/glade/registration.php", post); g_string_free (post, TRUE); } static void toggle_button_set_visible_on_toggle (GtkToggleButton *button, GtkWidget *widget) { gtk_widget_set_visible (widget, gtk_toggle_button_get_active (button)); } static void toggle_button_set_sensitive_on_toggle (GtkToggleButton *button, GtkWidget *widget) { gtk_widget_set_sensitive (widget, gtk_toggle_button_get_active (button)); } static gboolean on_viewport_draw (GtkWidget *viewport, cairo_t *cr, GladeRegistration *widget) { GtkStyleContext *context = gtk_widget_get_style_context (viewport); GtkAllocation alloc; gdouble scale; GdkRGBA c; gtk_style_context_get_color (context, gtk_style_context_get_state (context), &c); gtk_widget_get_allocation (viewport, &alloc); scale = MIN (alloc.width/GLADE_LOGO_WIDTH, alloc.height/GLADE_LOGO_HEIGHT) - .1; cairo_save (cr); cairo_set_source_rgba (cr, c.red, c.green, c.blue, .04); cairo_scale (cr, scale, scale); cairo_translate (cr, (alloc.width / scale) - GLADE_LOGO_WIDTH*.95, (alloc.height / scale) - GLADE_LOGO_HEIGHT); cairo_append_path (cr, &glade_logo_path); cairo_fill (cr); cairo_restore (cr); return FALSE; } static void glade_registration_init (GladeRegistration *registration) { GladeRegistrationPrivate *priv = glade_registration_get_instance_private (registration); registration->priv = priv; /* HTTPS default port is 443 */ priv->http = glade_http_new ("people.gnome.org", 443, TRUE); g_signal_connect_object (priv->http, "request-done", G_CALLBACK (on_http_request_done), registration, 0); g_signal_connect_object (priv->http, "status", G_CALLBACK (on_http_status), registration, 0); gtk_widget_init_template (GTK_WIDGET (registration)); if (GTK_IS_COMBO_BOX_TEXT (priv->version_other)) { GtkComboBoxText *combo = GTK_COMBO_BOX_TEXT (priv->version_other); gchar id[16], text[18]; gint minor; for (minor = 0; minor <= GLADE_MINOR_VERSION; minor+=2) { g_snprintf (id, 16, "%d", minor); g_snprintf (text, 18, "3.%d", minor); gtk_combo_box_text_append (combo, id, text); } gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0); } } static void glade_registration_finalize (GObject *object) { GladeRegistrationPrivate *priv = GLADE_REGISTRATION (object)->priv; g_clear_object (&priv->http); g_clear_object (&priv->sub_http); g_clear_object (&priv->cancellable); G_OBJECT_CLASS (glade_registration_parent_class)->finalize (object); } static void glade_registration_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GKeyFile *config = glade_app_get_config (); g_return_if_fail (GLADE_IS_REGISTRATION (object)); switch (prop_id) { case PROP_SKIP_REMINDER: case PROP_COMPLETED: g_key_file_set_boolean (config, CONFIG_GROUP, pspec->name, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void glade_registration_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GKeyFile *config = glade_app_get_config (); g_return_if_fail (GLADE_IS_REGISTRATION (object)); switch (prop_id) { case PROP_SKIP_REMINDER: case PROP_COMPLETED: g_value_set_boolean (value, g_key_file_get_boolean (config, CONFIG_GROUP, pspec->name, NULL)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void glade_registration_class_init (GladeRegistrationClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkCssProvider *css_provider; gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/glade/glade-registration.glade"); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, infobar); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, net_spinner); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, infobar_label); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, status_label); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, name); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, email); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, country_id); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, city); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, contact_type); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, contact_name); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, contact_website); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, subscribe); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, update_token_checkbutton); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, update_token); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, experience); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, experience_unit); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, experience_not_programmer); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_c); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_cpp); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_csharp); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_java); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_python); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_javascript); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_vala); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_perl); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, lang_other); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, start_using); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, start_using_unit); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, version); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, version_other); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, os); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, os_linux); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, os_bsd); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, os_windows); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, os_osx); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, os_solaris); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, os_other); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, freq); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, user_level); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, soft_free); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, soft_open); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, soft_commercial); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, soft_none); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_academic); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_accounting); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_desktop); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_educational); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_embedded); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_medical); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_industrial); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_scientific); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, field_other); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, improvement); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, problem); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, problem_other); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, bug); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, bugzilla); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, contributing); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, contributing_whynot); gtk_widget_class_bind_template_child_private (widget_class, GladeRegistration, comments); gtk_widget_class_bind_template_callback (widget_class, on_registration_dialog_response); gtk_widget_class_bind_template_callback (widget_class, toggle_button_set_visible_on_toggle); gtk_widget_class_bind_template_callback (widget_class, toggle_button_set_sensitive_on_toggle); gtk_widget_class_bind_template_callback (widget_class, on_viewport_draw); object_class->finalize = glade_registration_finalize; object_class->set_property = glade_registration_set_property; object_class->get_property = glade_registration_get_property; g_object_class_install_property (object_class, PROP_COMPLETED, g_param_spec_boolean ("completed", "Completed", "Registration was completed successfully", FALSE, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_SKIP_REMINDER, g_param_spec_boolean ("skip-reminder", "Skip reminder", "Skip registration reminder dialog", FALSE, G_PARAM_READWRITE)); /* Setup Custom CSS */ css_provider = gtk_css_provider_new (); gtk_css_provider_load_from_resource (css_provider, "/org/gnome/glade/glade-registration.css"); gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), GTK_STYLE_PROVIDER (css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); g_object_unref (css_provider); } GtkWidget* glade_registration_new (void) { return GTK_WIDGET (g_object_new (GLADE_TYPE_REGISTRATION, NULL)); }