/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright (C) 2012 Red Hat * * 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, see . * * Written by: * Jasper St. Pierre */ #include "config.h" #include #include "gis-page.h" struct _GisPagePrivate { char *title; gboolean applying; GCancellable *apply_cancel; GisPageApplyCallback apply_cb; gpointer apply_data; guint complete : 1; guint skippable : 1; guint needs_accept : 1; guint has_forward : 1; guint padding : 5; }; typedef struct _GisPagePrivate GisPagePrivate; G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GisPage, gis_page, ADW_TYPE_BIN); enum { PROP_0, PROP_DRIVER, PROP_TITLE, PROP_COMPLETE, PROP_SKIPPABLE, PROP_NEEDS_ACCEPT, PROP_APPLYING, PROP_SMALL_SCREEN, PROP_HAS_FORWARD, PROP_LAST, }; static GParamSpec *obj_props[PROP_LAST]; static void gis_page_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GisPage *page = GIS_PAGE (object); GisPagePrivate *priv = gis_page_get_instance_private (page); switch (prop_id) { case PROP_DRIVER: g_value_set_object (value, page->driver); break; case PROP_TITLE: g_value_set_string (value, priv->title); break; case PROP_COMPLETE: g_value_set_boolean (value, priv->complete); break; case PROP_SKIPPABLE: g_value_set_boolean (value, priv->skippable); break; case PROP_NEEDS_ACCEPT: g_value_set_boolean (value, priv->needs_accept); break; case PROP_HAS_FORWARD: g_value_set_boolean (value, priv->has_forward); break; case PROP_APPLYING: g_value_set_boolean (value, gis_page_get_applying (page)); break; case PROP_SMALL_SCREEN: if (page->driver) g_object_get_property (G_OBJECT (page->driver), "small-screen", value); else g_value_set_boolean (value, FALSE); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void small_screen_changed (GisPage *page) { g_object_notify_by_pspec (G_OBJECT (page), obj_props[PROP_SMALL_SCREEN]); } static void gis_page_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GisPage *page = GIS_PAGE (object); GisPagePrivate *priv = gis_page_get_instance_private (page); switch (prop_id) { case PROP_DRIVER: page->driver = g_value_dup_object (value); g_signal_connect_swapped (page->driver, "notify::small-screen", G_CALLBACK (small_screen_changed), page); small_screen_changed (page); break; case PROP_TITLE: gis_page_set_title (page, (char *) g_value_get_string (value)); break; case PROP_SKIPPABLE: priv->skippable = g_value_get_boolean (value); break; case PROP_NEEDS_ACCEPT: priv->needs_accept = g_value_get_boolean (value); break; case PROP_HAS_FORWARD: priv->has_forward = g_value_get_boolean (value); break; case PROP_COMPLETE: priv->complete = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gis_page_finalize (GObject *object) { GisPage *page = GIS_PAGE (object); GisPagePrivate *priv = gis_page_get_instance_private (page); g_free (priv->title); g_assert (!priv->applying); g_assert (priv->apply_cb == NULL); g_assert (priv->apply_cancel == NULL); G_OBJECT_CLASS (gis_page_parent_class)->finalize (object); } static void gis_page_dispose (GObject *object) { GisPage *page = GIS_PAGE (object); GisPagePrivate *priv = gis_page_get_instance_private (page); if (priv->apply_cancel) g_cancellable_cancel (priv->apply_cancel); if (page->driver) g_signal_handlers_disconnect_by_func (page->driver, small_screen_changed, page); g_clear_object (&page->driver); G_OBJECT_CLASS (gis_page_parent_class)->dispose (object); } static void gis_page_constructed (GObject *object) { GisPage *page = GIS_PAGE (object); gis_page_locale_changed (page); G_OBJECT_CLASS (gis_page_parent_class)->constructed (object); } static gboolean gis_page_real_apply (GisPage *page, GCancellable *cancellable) { return FALSE; } static void gis_page_class_init (GisPageClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructed = gis_page_constructed; object_class->dispose = gis_page_dispose; object_class->finalize = gis_page_finalize; object_class->get_property = gis_page_get_property; object_class->set_property = gis_page_set_property; klass->apply = gis_page_real_apply; obj_props[PROP_DRIVER] = g_param_spec_object ("driver", "", "", GIS_TYPE_DRIVER, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); obj_props[PROP_TITLE] = g_param_spec_string ("title", "", "", "", G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); obj_props[PROP_COMPLETE] = g_param_spec_boolean ("complete", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); obj_props[PROP_SKIPPABLE] = g_param_spec_boolean ("skippable", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); obj_props[PROP_NEEDS_ACCEPT] = g_param_spec_boolean ("needs-accept", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); obj_props[PROP_HAS_FORWARD] = g_param_spec_boolean ("has-forward", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); obj_props[PROP_APPLYING] = g_param_spec_boolean ("applying", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); obj_props[PROP_SMALL_SCREEN] = g_param_spec_boolean ("small-screen", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); g_object_class_install_properties (object_class, PROP_LAST, obj_props); } static void gis_page_init (GisPage *page) { } char * gis_page_get_title (GisPage *page) { GisPagePrivate *priv = gis_page_get_instance_private (page); if (priv->title != NULL) return priv->title; else return ""; } void gis_page_set_title (GisPage *page, char *title) { GisPagePrivate *priv = gis_page_get_instance_private (page); g_clear_pointer (&priv->title, g_free); priv->title = g_strdup (title); g_object_notify_by_pspec (G_OBJECT (page), obj_props[PROP_TITLE]); } gboolean gis_page_get_complete (GisPage *page) { GisPagePrivate *priv = gis_page_get_instance_private (page); return priv->complete; } void gis_page_set_complete (GisPage *page, gboolean complete) { GisPagePrivate *priv = gis_page_get_instance_private (page); priv->complete = complete; g_object_notify_by_pspec (G_OBJECT (page), obj_props[PROP_COMPLETE]); } gboolean gis_page_get_skippable (GisPage *page) { GisPagePrivate *priv = gis_page_get_instance_private (page); return priv->skippable; } void gis_page_set_skippable (GisPage *page, gboolean skippable) { GisPagePrivate *priv = gis_page_get_instance_private (page); priv->skippable = skippable; g_object_notify_by_pspec (G_OBJECT (page), obj_props[PROP_SKIPPABLE]); } gboolean gis_page_get_needs_accept (GisPage *page) { GisPagePrivate *priv = gis_page_get_instance_private (page); return priv->needs_accept; } void gis_page_set_needs_accept (GisPage *page, gboolean needs_accept) { GisPagePrivate *priv = gis_page_get_instance_private (page); priv->needs_accept = needs_accept; g_object_notify_by_pspec (G_OBJECT (page), obj_props[PROP_NEEDS_ACCEPT]); } gboolean gis_page_get_has_forward (GisPage *page) { GisPagePrivate *priv = gis_page_get_instance_private (page); return priv->has_forward; } void gis_page_set_has_forward (GisPage *page, gboolean has_forward) { GisPagePrivate *priv = gis_page_get_instance_private (page); if (priv->has_forward != has_forward) { priv->has_forward = has_forward; g_object_notify_by_pspec (G_OBJECT (page), obj_props[PROP_HAS_FORWARD]); } } void gis_page_locale_changed (GisPage *page) { if (GIS_PAGE_GET_CLASS (page)->locale_changed) return GIS_PAGE_GET_CLASS (page)->locale_changed (page); } void gis_page_apply_begin (GisPage *page, GisPageApplyCallback callback, gpointer user_data) { GisPageClass *klass; GisPagePrivate *priv = gis_page_get_instance_private (page); g_return_if_fail (GIS_IS_PAGE (page)); g_return_if_fail (priv->applying == FALSE); klass = GIS_PAGE_GET_CLASS (page); priv->apply_cb = callback; priv->apply_data = user_data; priv->apply_cancel = g_cancellable_new (); priv->applying = TRUE; if (!klass->apply (page, priv->apply_cancel)) { /* Shortcut case where we don't want apply, to avoid flicker */ gis_page_apply_complete (page, TRUE); } g_object_notify_by_pspec (G_OBJECT (page), obj_props[PROP_APPLYING]); } void gis_page_apply_complete (GisPage *page, gboolean valid) { GisPageApplyCallback callback; gpointer user_data; GisPagePrivate *priv = gis_page_get_instance_private (page); g_return_if_fail (GIS_IS_PAGE (page)); g_return_if_fail (priv->applying == TRUE); callback = priv->apply_cb; priv->apply_cb = NULL; user_data = priv->apply_data; priv->apply_data = NULL; g_clear_object (&priv->apply_cancel); priv->applying = FALSE; g_object_notify_by_pspec (G_OBJECT (page), obj_props[PROP_APPLYING]); if (callback) (callback) (page, valid, user_data); } gboolean gis_page_get_applying (GisPage *page) { GisPagePrivate *priv = gis_page_get_instance_private (page); return priv->applying; } void gis_page_apply_cancel (GisPage *page) { GisPagePrivate *priv = gis_page_get_instance_private (page); g_cancellable_cancel (priv->apply_cancel); } gboolean gis_page_save_data (GisPage *page, GError **error) { if (GIS_PAGE_GET_CLASS (page)->save_data == NULL) { /* Not implemented, which presumably means the page has nothing to save. */ return TRUE; } return GIS_PAGE_GET_CLASS (page)->save_data (page, error); } void gis_page_shown (GisPage *page) { if (GIS_PAGE_GET_CLASS (page)->shown) GIS_PAGE_GET_CLASS (page)->shown (page); } void gis_page_skip (GisPage *page) { if (GIS_PAGE_GET_CLASS (page)->skip) GIS_PAGE_GET_CLASS (page)->skip (page); }