eina_model: new events for load/unload.
authorbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 16 Feb 2012 19:48:13 +0000 (19:48 +0000)
committerbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 16 Feb 2012 19:48:13 +0000 (19:48 +0000)
Added the events: loaded and unloaded to notify eina_model_load() and
eina_model_unload() were called.

To be more specific, the interfaces used by EINA_MODEL_TYPE_MIXIN
(Eina_Model_Interface_Properties and Eina_Model_Interface_Children)
also do:
 * properties,loaded
 * properties,unloaded
 * children,loaded
 * children,unloaded

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eina@68035 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/include/eina_model.h
src/lib/eina_model.c
src/tests/eina_test_model.c

index c634d17..5390ba3 100644 (file)
@@ -534,6 +534,14 @@ EAPI void eina_model_xunref(Eina_Model *model,
  * @li child,inserted: new child was added (eina_model_child_append() or eina_model_child_insert_at())
  * @li child,set: child was replaced (eina_model_child_set())
  * @li child,deleted: eina_model_child_del() was done.
+ * @li loaded: eina_model_load() was done.
+ * @li unloaded: eina_model_unload() was done.
+ *
+ * Mix-in interfaces may emit these:
+ * @li properties,loaded
+ * @li properties,unloaded
+ * @li children,loaded
+ * @li children,unloaded
  *
  * One can be notified of events with eina_model_event_callback_add().
  *
index 70d5fad..8af7a07 100644 (file)
@@ -86,6 +86,12 @@ static const char _eina_model_str_children_changed[] =  "children,changed";
 static const char _eina_model_str_child_inserted[] =  "child,inserted";
 static const char _eina_model_str_child_set[] =  "child,set";
 static const char _eina_model_str_child_del[] =  "child,deleted";
+static const char _eina_model_str_loaded[] = "loaded";
+static const char _eina_model_str_unloaded[] = "unloaded";
+static const char _eina_model_str_properties_loaded[] = "properties,loaded";
+static const char _eina_model_str_properties_unloaded[] = "properties,unloaded";
+static const char _eina_model_str_children_loaded[] = "children,loaded";
+static const char _eina_model_str_children_unloaded[] = "children,unloaded";
 
 #ifdef CRITICAL
 #undef CRITICAL
@@ -1992,6 +1998,8 @@ static const Eina_Model_Event_Description _eina_model_type_base_events[] = {
   EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_child_inserted, "u", "model child was inserted, child position is given."),
   EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_child_set, "u", "model child was set, child position is given."),
   EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_child_del, "u", "model child was deleted, child position is given."),
+  EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_loaded, "", "model was loaded"),
+  EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_unloaded, "", "model was unloaded"),
   EINA_MODEL_EVENT_DESCRIPTION_SENTINEL
 };
 
@@ -2375,6 +2383,12 @@ static const Eina_Model_Type _EINA_MODEL_TYPE_MIXIN = {
 };
 #undef EINA_MODEL_TYPE_MIXIN_GET
 
+/* Events for all Properties interface */
+static const Eina_Model_Event_Description _eina_model_interface_properties_events[] = {
+  EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_properties_loaded, "", "model properties were loaded"),
+  EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_properties_unloaded, "", "model properties were unloaded"),
+  EINA_MODEL_EVENT_DESCRIPTION_SENTINEL
+};
 
 /* EINA_MODEL_INTERFACE_PROPERTIES_HASH ******************************/
 
@@ -2536,7 +2550,7 @@ static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_HA
     sizeof(Eina_Model_Interface_Properties),
     _EINA_MODEL_INTERFACE_NAME_PROPERTIES,
     NULL, /* no parent interfaces */
-    NULL, /* no extra events */
+    _eina_model_interface_properties_events,
     _eina_model_interface_properties_hash_setup,
     _eina_model_interface_properties_hash_flush,
     _eina_model_interface_properties_hash_constructor,
@@ -2686,7 +2700,7 @@ static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_ST
     sizeof(Eina_Model_Interface_Properties),
     _EINA_MODEL_INTERFACE_NAME_PROPERTIES,
     NULL, /* no parent interfaces */
-    NULL, /* no extra events */
+    _eina_model_interface_properties_events,
     _eina_model_interface_properties_struct_setup,
     _eina_model_interface_properties_struct_flush,
     _eina_model_interface_properties_struct_constructor,
@@ -2708,6 +2722,13 @@ static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_ST
   _eina_model_interface_properties_struct_names_list
 };
 
+/* Events for all Children interface */
+static const Eina_Model_Event_Description _eina_model_interface_children_events[] = {
+  EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_children_loaded, "", "model children were loaded"),
+  EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_children_unloaded, "", "model children were unloaded"),
+  EINA_MODEL_EVENT_DESCRIPTION_SENTINEL
+};
+
 /* EINA_MODEL_INTERFACE_CHILDREN_INARRAY ******************************/
 
 #define EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model)        \
@@ -2864,7 +2885,7 @@ static const Eina_Model_Interface_Children _EINA_MODEL_INTERFACE_CHILDREN_INARRA
     sizeof(Eina_Model_Interface_Children),
     _EINA_MODEL_INTERFACE_NAME_CHILDREN,
     NULL, /* no parent interfaces */
-    NULL, /* no extra events */
+    _eina_model_interface_children_events,
     _eina_model_interface_children_inarray_setup,
     _eina_model_interface_children_inarray_flush,
     _eina_model_interface_children_inarray_constructor,
@@ -3988,15 +4009,52 @@ eina_model_compare(const Eina_Model *a, const Eina_Model *b)
 EAPI Eina_Bool
 eina_model_load(Eina_Model *model)
 {
+   Eina_Bool ret;
+
    EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
-   EINA_MODEL_TYPE_CALL_OPTIONAL_RETURN(model, load, EINA_TRUE);
+
+   eina_error_set(0);
+   if (model->desc->ops.type.load)
+     {
+        ret = model->desc->ops.type.load(model);
+        if (ret)
+          _eina_model_event_callback_call(model, _eina_model_str_loaded, NULL);
+     }
+   else
+     {
+        eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
+        ret = EINA_FALSE;
+        ERR("Method load() not implemented for model %p (%s)",
+            model, model->desc->cache.types[0]->name);
+     }
+
+   return ret;
 }
 
 EAPI Eina_Bool
 eina_model_unload(Eina_Model *model)
 {
+   Eina_Bool ret;
+
    EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
-   EINA_MODEL_TYPE_CALL_OPTIONAL_RETURN(model, unload, EINA_TRUE);
+
+   eina_error_set(0);
+   if (model->desc->ops.type.unload)
+     {
+        ret = model->desc->ops.type.unload(model);
+        if (ret)
+          _eina_model_event_callback_call
+            (model, _eina_model_str_unloaded, NULL);
+     }
+   else
+     {
+        eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
+        ret = EINA_FALSE;
+        ERR("Method unload() not implemented for model %p (%s)",
+            model, model->desc->cache.types[0]->name);
+     }
+
+   return ret;
 }
 
 EAPI Eina_Bool
@@ -5062,26 +5120,40 @@ EAPI Eina_Bool
 eina_model_interface_properties_load(const Eina_Model_Interface *iface, Eina_Model *model)
 {
    Eina_Bool (*load)(Eina_Model *);
+   Eina_Bool ret;
 
    EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
 
    load = _eina_model_interface_find_offset
      (iface, offsetof(Eina_Model_Interface_Properties, load));
    EINA_SAFETY_ON_NULL_RETURN_VAL(load, EINA_FALSE);
-   return load(model);
+   ret = load(model);
+
+   if (ret)
+     _eina_model_event_callback_call
+       (model, _eina_model_str_properties_loaded, NULL);
+
+   return ret;
 }
 
 EAPI Eina_Bool
 eina_model_interface_properties_unload(const Eina_Model_Interface *iface, Eina_Model *model)
 {
    Eina_Bool (*unload)(Eina_Model *);
+   Eina_Bool ret;
 
    EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
 
    unload = _eina_model_interface_find_offset
      (iface, offsetof(Eina_Model_Interface_Properties, unload));
    EINA_SAFETY_ON_NULL_RETURN_VAL(unload, EINA_FALSE);
-   return unload(model);
+   ret = unload(model);
+
+   if (ret)
+     _eina_model_event_callback_call
+       (model, _eina_model_str_properties_unloaded, NULL);
+
+   return ret;
 }
 
 EAPI Eina_Bool
@@ -5166,26 +5238,40 @@ EAPI Eina_Bool
 eina_model_interface_children_load(const Eina_Model_Interface *iface, Eina_Model *model)
 {
    Eina_Bool (*load)(Eina_Model *);
+   Eina_Bool ret;
 
    EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
 
    load = _eina_model_interface_find_offset
      (iface, offsetof(Eina_Model_Interface_Children, load));
    EINA_SAFETY_ON_NULL_RETURN_VAL(load, EINA_FALSE);
-   return load(model);
+   ret = load(model);
+
+   if (ret)
+     _eina_model_event_callback_call
+       (model, _eina_model_str_children_loaded, NULL);
+
+   return ret;
 }
 
 EAPI Eina_Bool
 eina_model_interface_children_unload(const Eina_Model_Interface *iface, Eina_Model *model)
 {
    Eina_Bool (*unload)(Eina_Model *);
+   Eina_Bool ret;
 
    EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
 
    unload = _eina_model_interface_find_offset
      (iface, offsetof(Eina_Model_Interface_Children, unload));
    EINA_SAFETY_ON_NULL_RETURN_VAL(unload, EINA_FALSE);
-   return unload(model);
+   ret = unload(model);
+
+   if (ret)
+     _eina_model_event_callback_call
+       (model, _eina_model_str_children_unloaded, NULL);
+
+   return ret;
 }
 
 EAPI int
index 97a69db..54a2258 100644 (file)
@@ -1112,6 +1112,164 @@ START_TEST(eina_model_test_inheritance)
 }
 END_TEST
 
+static Eina_Bool
+_myproperties_load(Eina_Model *m)
+{
+   Eina_Value v;
+   Eina_Bool ret;
+   int count;
+
+   if (!eina_model_property_get(m, "load_count", &v))
+     return EINA_FALSE;
+
+   eina_value_get(&v, &count);
+   count++;
+   eina_value_set(&v, count);
+
+   ret = eina_model_property_set(m, "load_count", &v);
+   eina_value_flush(&v);
+
+   return ret;
+}
+
+static Eina_Bool
+_myproperties_unload(Eina_Model *m)
+{
+   Eina_Value v;
+   Eina_Bool ret;
+   int count;
+
+   if (!eina_model_property_get(m, "load_count", &v))
+     return EINA_FALSE;
+
+   eina_value_get(&v, &count);
+   count--;
+   eina_value_set(&v, count);
+
+   ret = eina_model_property_set(m, "load_count", &v);
+   eina_value_flush(&v);
+
+   return ret;
+}
+
+static Eina_Bool
+_mychildren_load(Eina_Model *m)
+{
+   Eina_Model *c = eina_model_new(EINA_MODEL_TYPE_GENERIC);
+   int ret = eina_model_child_append(m, c);
+   eina_model_unref(c);
+   return ret >= 0;
+}
+
+static Eina_Bool
+_mychildren_unload(Eina_Model *m)
+{
+   int count = eina_model_child_count(m);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(count > 0, EINA_FALSE);
+   return eina_model_child_del(m, count - 1);
+}
+
+START_TEST(eina_model_test_ifaces_load_unload)
+{
+   unsigned int count_loaded = 0, count_unloaded = 0;
+   unsigned int count_ploaded = 0, count_punloaded = 0;
+   unsigned int count_cloaded = 0, count_cunloaded = 0;
+   static Eina_Model_Interface_Properties piface;
+   static Eina_Model_Interface_Children ciface;
+   static const Eina_Model_Interface *piface_parents[2] = {NULL, NULL};
+   static const Eina_Model_Interface *ciface_parents[2] = {NULL, NULL};
+   static const Eina_Model_Interface *type_ifaces[3] = {
+     &piface.base, &ciface.base, NULL
+   };
+   static Eina_Model_Type type;
+   Eina_Model *m;
+   Eina_Value v;
+   int count;
+
+   eina_init();
+
+   /* do after eina_init() otherwise interfaces are not set */
+   piface_parents[0] = EINA_MODEL_INTERFACE_PROPERTIES_HASH;
+   ciface_parents[0] = EINA_MODEL_INTERFACE_CHILDREN_INARRAY;
+
+   memset(&piface, 0, sizeof(piface));
+   piface.base.version = EINA_MODEL_INTERFACE_VERSION;
+   piface.base.interface_size = sizeof(piface);
+   piface.base.name = EINA_MODEL_INTERFACE_NAME_PROPERTIES;
+   piface.base.interfaces = piface_parents;
+   piface.load = _myproperties_load;
+   piface.unload = _myproperties_unload;
+
+   memset(&ciface, 0, sizeof(ciface));
+   ciface.base.version = EINA_MODEL_INTERFACE_VERSION;
+   ciface.base.interface_size = sizeof(ciface);
+   ciface.base.name = EINA_MODEL_INTERFACE_NAME_CHILDREN;
+   ciface.base.interfaces = ciface_parents;
+   ciface.load = _mychildren_load;
+   ciface.unload = _mychildren_unload;
+
+   type.version = EINA_MODEL_TYPE_VERSION;
+   type.private_size = 0;
+   type.name = "MyType";
+   eina_model_type_subclass_setup(&type,  EINA_MODEL_TYPE_GENERIC);
+   type.interfaces = type_ifaces;
+
+   m = eina_model_new(&type);
+   fail_unless(m != NULL);
+
+   eina_model_event_callback_add
+     (m, "loaded", _eina_test_model_cb_count, &count_loaded);
+   eina_model_event_callback_add
+     (m, "unloaded", _eina_test_model_cb_count, &count_unloaded);
+
+   eina_model_event_callback_add
+     (m, "properties,loaded", _eina_test_model_cb_count, &count_ploaded);
+   eina_model_event_callback_add
+     (m, "properties,unloaded", _eina_test_model_cb_count, &count_punloaded);
+
+   eina_model_event_callback_add
+     (m, "children,loaded", _eina_test_model_cb_count, &count_cloaded);
+   eina_model_event_callback_add
+     (m, "children,unloaded", _eina_test_model_cb_count, &count_cunloaded);
+
+   fail_unless(eina_value_setup(&v, EINA_VALUE_TYPE_INT));
+   fail_unless(eina_value_set(&v, 0));
+   fail_unless(eina_model_property_set(m, "load_count", &v));
+   eina_value_flush(&v);
+
+   fail_unless(eina_model_load(m));
+   fail_unless(eina_model_load(m));
+   fail_unless(eina_model_load(m));
+
+   /* each load increments one for load_count property */
+   fail_unless(eina_model_property_get(m, "load_count", &v));
+   fail_unless(eina_value_pget(&v, &count));
+   ck_assert_int_eq(count, 3);
+   eina_value_flush(&v);
+
+   /* each load adds one child */
+   ck_assert_int_eq(eina_model_child_count(m), 3);
+
+   fail_unless(eina_model_unload(m));
+   fail_unless(eina_model_unload(m));
+   fail_unless(eina_model_unload(m));
+
+   ck_assert_int_eq(count_loaded, 3);
+   ck_assert_int_eq(count_unloaded, 3);
+
+   ck_assert_int_eq(count_ploaded, 3);
+   ck_assert_int_eq(count_punloaded, 3);
+
+   ck_assert_int_eq(count_cloaded, 3);
+   ck_assert_int_eq(count_cunloaded, 3);
+
+   ck_assert_int_eq(eina_model_refcount(m), 1);
+   eina_model_unref(m);
+
+   eina_shutdown();
+}
+END_TEST
+
 void
 eina_test_model(TCase *tc)
 {
@@ -1126,4 +1284,5 @@ eina_test_model(TCase *tc)
    tcase_add_test(tc, eina_model_test_struct);
    tcase_add_test(tc, eina_model_test_struct_complex_members);
    tcase_add_test(tc, eina_model_test_inheritance);
+   tcase_add_test(tc, eina_model_test_ifaces_load_unload);
 }