summaryrefslogtreecommitdiff
path: root/src/core/gtd-object.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/gtd-object.c')
-rw-r--r--src/core/gtd-object.c313
1 files changed, 313 insertions, 0 deletions
diff --git a/src/core/gtd-object.c b/src/core/gtd-object.c
new file mode 100644
index 0000000..c1157fc
--- /dev/null
+++ b/src/core/gtd-object.c
@@ -0,0 +1,313 @@
+/* gtd-object.c
+ *
+ * Copyright © 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * 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 3 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 <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "GtdObject"
+
+#include "gtd-object.h"
+
+#include <glib/gi18n.h>
+
+/**
+ * SECTION:gtd-object
+ * @Short_description: base class for loadable and uniquely identifiable objects
+ * @Title: GtdObject
+ *
+ * #GtdObject is the base class of many object in Endeavour, and it useful for
+ * when a given object is loadable and/or uniquely identifiable. Some examples of
+ * it are #GtdTask, #GtdTaskList and #GtdNotification.
+ *
+ */
+
+typedef struct
+{
+ guint64 loading;
+ gchar *uid;
+} GtdObjectPrivate;
+
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtdObject, gtd_object, G_TYPE_OBJECT)
+
+
+enum
+{
+ PROP_0,
+ PROP_LOADING,
+ PROP_UID,
+ N_PROPS
+};
+
+
+static GParamSpec *properties[N_PROPS] = { NULL, };
+
+
+static const gchar*
+gtd_object_real_get_uid (GtdObject *object)
+{
+ GtdObjectPrivate *priv;
+
+ g_return_val_if_fail (GTD_IS_OBJECT (object), NULL);
+
+ priv = gtd_object_get_instance_private (object);
+
+ return priv->uid;
+}
+
+static void
+gtd_object_real_set_uid (GtdObject *object,
+ const gchar *uid)
+{
+ GtdObjectPrivate *priv;
+
+ g_assert (GTD_IS_OBJECT (object));
+
+ priv = gtd_object_get_instance_private (object);
+
+ if (g_strcmp0 (priv->uid, uid) == 0)
+ return;
+
+ g_clear_pointer (&priv->uid, g_free);
+ priv->uid = g_strdup (uid);
+
+ g_object_notify_by_pspec (G_OBJECT (object), properties[PROP_UID]);
+}
+
+
+/*
+ * GObject overrides
+ */
+
+static void
+gtd_object_finalize (GObject *object)
+{
+ GtdObject *self = GTD_OBJECT (object);
+ GtdObjectPrivate *priv = gtd_object_get_instance_private (self);
+
+ g_clear_pointer (&priv->uid, g_free);
+
+ G_OBJECT_CLASS (gtd_object_parent_class)->finalize (object);
+}
+
+static void
+gtd_object_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtdObject *self = GTD_OBJECT (object);
+ GtdObjectPrivate *priv = gtd_object_get_instance_private (self);
+
+ switch (prop_id)
+ {
+ case PROP_LOADING:
+ g_value_set_boolean (value, priv->loading > 0);
+ break;
+
+ case PROP_UID:
+ g_value_set_string (value, GTD_OBJECT_GET_CLASS (self)->get_uid (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtd_object_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtdObject *self = GTD_OBJECT (object);
+
+ switch (prop_id)
+ {
+ case PROP_UID:
+ GTD_OBJECT_GET_CLASS (self)->set_uid (self, g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtd_object_class_init (GtdObjectClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ klass->get_uid = gtd_object_real_get_uid;
+ klass->set_uid = gtd_object_real_set_uid;
+
+ object_class->finalize = gtd_object_finalize;
+ object_class->get_property = gtd_object_get_property;
+ object_class->set_property = gtd_object_set_property;
+
+ /**
+ * GtdObject::uid:
+ *
+ * The unique identified of the object, set by the backend.
+ */
+ properties[PROP_UID] = g_param_spec_string ("uid",
+ "Unique identifier of the object",
+ "The unique identifier of the object, defined by the backend",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GtdObject::loading:
+ *
+ * Whether the object is loading or not.
+ */
+ properties[PROP_LOADING] = g_param_spec_boolean ("loading",
+ "Loading state of the object",
+ "Whether the object is loading or not",
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gtd_object_init (GtdObject *self)
+{
+}
+
+/**
+ * gtd_object_new:
+ * @uid: unique identifier of the object
+ *
+ * Creates a new #GtdObject object.
+ *
+ * Returns: (transfer full): a new #GtdObject
+ */
+GtdObject*
+gtd_object_new (const gchar *uid)
+{
+ return g_object_new (GTD_TYPE_OBJECT, "uid", uid, NULL);
+}
+
+/**
+ * gtd_object_get_uid:
+ * @object: a #GtdObject
+ *
+ * Retrieves the internal unique identifier of @object.
+ *
+ * Returns: (transfer none): the unique identifier of @object. Do
+ * not free after usage.
+ */
+const gchar*
+gtd_object_get_uid (GtdObject *object)
+{
+ GtdObjectClass *class;
+
+ g_return_val_if_fail (GTD_IS_OBJECT (object), NULL);
+
+ class = GTD_OBJECT_GET_CLASS (object);
+
+ g_assert (class);
+ return class->get_uid (object);
+}
+
+/**
+ * gtd_object_set_uid:
+ * @object: a #GtdObject
+ * @uid: the unique identifier of @object
+ *
+ * Sets the unique identifier of @object to @uid. Only
+ * a #GtdBackend should do it.
+ */
+void
+gtd_object_set_uid (GtdObject *object,
+ const gchar *uid)
+{
+ GtdObjectClass *class;
+
+ g_return_if_fail (GTD_IS_OBJECT (object));
+
+ class = GTD_OBJECT_GET_CLASS (object);
+
+ g_assert (class);
+ class->set_uid (object, uid);
+}
+
+/**
+ * gtd_object_get_loading:
+ * @object: a #GtdObject
+ *
+ * Whether @object is loading or not.
+ *
+ * Returns: %TRUE if @object is loading, %FALSE otherwise.
+ */
+gboolean
+gtd_object_get_loading (GtdObject *object)
+{
+ GtdObjectPrivate *priv;
+
+ g_return_val_if_fail (GTD_IS_OBJECT (object), FALSE);
+
+ priv = gtd_object_get_instance_private (object);
+
+ return priv->loading > 0;
+}
+
+/**
+ * gtd_object_push_loading:
+ * @object: a #GtdObject
+ *
+ * Increases the loading counter of @object by one. The object is marked
+ * as loading while the loading counter is greater than zero.
+ */
+void
+gtd_object_push_loading (GtdObject *object)
+{
+ GtdObjectPrivate *priv;
+
+ g_return_if_fail (GTD_IS_OBJECT (object));
+
+ priv = gtd_object_get_instance_private (object);
+
+ priv->loading++;
+
+ if (priv->loading == 1)
+ g_object_notify_by_pspec (G_OBJECT (object), properties[PROP_LOADING]);
+}
+
+/**
+ * gtd_object_pop_loading:
+ * @object: a #GtdObject
+ *
+ * Decreases the loading counter of @object by one. The object is marked
+ * as loading while the loading counter is greater than zero.
+ *
+ * It is a programming error to pop more times then push the loading the
+ * counter.
+ */
+void
+gtd_object_pop_loading (GtdObject *object)
+{
+ GtdObjectPrivate *priv;
+
+ g_return_if_fail (GTD_IS_OBJECT (object));
+
+ priv = gtd_object_get_instance_private (object);
+
+ priv->loading--;
+
+ if (priv->loading == 0)
+ g_object_notify_by_pspec (G_OBJECT (object), properties[PROP_LOADING]);
+}