summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLarry Jr <larry.olj@gmail.com>2014-09-24 11:48:43 -0300
committerLarry Jr <larry.olj@gmail.com>2015-05-15 17:31:56 -0300
commita988885f2fcc797033cce5c75f9fe617b8976e77 (patch)
tree6d0d27cca803fc040d4e6f8eff1be49d6b6ca1b8
parent5550b595c913465951042bbe68a2f01c2543bdf3 (diff)
downloadefl-a988885f2fcc797033cce5c75f9fe617b8976e77.tar.gz
EFL_Model: Created EFL_Model and Eio_Model.
Conflicts: src/Makefile_Eio.am src/tests/eio/eio_suite.c src/tests/eio/eio_suite.h
-rw-r--r--Makefile.am3
-rw-r--r--configure.ac1
-rw-r--r--pc/.gitignore3
-rw-r--r--pc/eio-cxx.pc.in12
-rw-r--r--pc/emodel-cxx.pc.in12
-rw-r--r--pc/emodel.pc.in12
-rw-r--r--pkgbuild/PKGBUILD2
-rw-r--r--src/Makefile.am5
-rw-r--r--src/Makefile_Efl.am5
-rw-r--r--src/Makefile_Efl_Cxx.am2
-rw-r--r--src/Makefile_Eio.am59
-rw-r--r--src/Makefile_Eio_Cxx.am22
-rw-r--r--src/examples/eio/Makefile.am2
-rw-r--r--src/lib/efl/Efl.h3
-rw-r--r--src/lib/efl/Efl_Model_Common.h92
-rw-r--r--src/lib/efl/interfaces/efl_interfaces_main.c1
-rw-r--r--src/lib/efl/interfaces/efl_model_base.eo322
-rw-r--r--src/lib/eio/eio_model.c683
-rw-r--r--src/lib/eio/eio_model.eo49
-rw-r--r--src/lib/eio/eio_model.h45
-rw-r--r--src/lib/eio/eio_model_private.h57
-rw-r--r--src/tests/eio/eio_model_test_file.c232
-rw-r--r--src/tests/eio/eio_model_test_monitor_add.c125
-rw-r--r--src/tests/eio/eio_suite.c109
-rw-r--r--src/tests/eio/eio_suite.h10
25 files changed, 1860 insertions, 8 deletions
diff --git a/Makefile.am b/Makefile.am
index 2b00391aac..cdcfca5730 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -160,7 +160,8 @@ pc/ecore-cxx.pc \
pc/eolian-cxx.pc \
pc/edje-cxx.pc \
pc/eet-cxx.pc \
-pc/eo-cxx.pc
+pc/eo-cxx.pc \
+pc/eio-cxx.pc
endif
if HAVE_ELUA
diff --git a/configure.ac b/configure.ac
index 96ccd7ab5d..e017625988 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4567,6 +4567,7 @@ pc/ecore-audio-cxx.pc
pc/ecore-avahi.pc
pc/embryo.pc
pc/eio.pc
+pc/eio-cxx.pc
pc/eldbus.pc
pc/efreet.pc
pc/efreet-mime.pc
diff --git a/pc/.gitignore b/pc/.gitignore
index db9bc3f3cc..9d11ef3977 100644
--- a/pc/.gitignore
+++ b/pc/.gitignore
@@ -27,9 +27,12 @@
/eina-cxx.pc
/eet-cxx.pc
/eio.pc
+/eio-cxx.pc
/eldbus.pc
/elocation.pc
/embryo.pc
+/emodel.pc
+/emodel-cxx.pc
/emotion.pc
/eo.pc
/ephysics.pc
diff --git a/pc/eio-cxx.pc.in b/pc/eio-cxx.pc.in
new file mode 100644
index 0000000000..82c6cfa84e
--- /dev/null
+++ b/pc/eio-cxx.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: eio C++ API
+Description: Enlightenned Asynchronous Input Output library C++ API.
+Requires.private: @requirements_pc_eio@
+Version: @VERSION@
+Libs: -L${libdir} -leio
+Libs.private: @requirements_libs_eio@
+Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/eio-@VMAJ@ -I${includedir}/eio-cxx-@VMAJ@
diff --git a/pc/emodel-cxx.pc.in b/pc/emodel-cxx.pc.in
new file mode 100644
index 0000000000..dce37642ad
--- /dev/null
+++ b/pc/emodel-cxx.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: emodel C++ API
+Description: MVC Library C++ API.
+Version: @PACKAGE_VERSION@
+Requires.private: @requirements_pc_emodel@
+Libs: -L${libdir} -lemodel
+Libs.private: @requirements_libs_emodel@
+Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/emodel-@VMAJ@ -I${includedir}/emodel-cxx-@VMAJ@
diff --git a/pc/emodel.pc.in b/pc/emodel.pc.in
new file mode 100644
index 0000000000..0d68f11152
--- /dev/null
+++ b/pc/emodel.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: emodel
+Description: MVC Library
+Version: @PACKAGE_VERSION@
+Requires.private: @requirements_pc_emodel@
+Libs: -L${libdir} -lemodel
+Libs.private: @requirements_libs_emodel@
+Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/emodel-@VMAJ@
diff --git a/pkgbuild/PKGBUILD b/pkgbuild/PKGBUILD
index afa8ae2d7d..6a17c0b951 100644
--- a/pkgbuild/PKGBUILD
+++ b/pkgbuild/PKGBUILD
@@ -60,7 +60,7 @@ build() {
package_efl() {
provides+=("ecore=$pkgver" "eldbus=$pkgver" "edje=$pkgver"
"eet=$pkgver" "eeze=$pkgver" "efreet=$pkgver"
- "eina=$pkgver" "eio=$pkgver" "embryo=$pkgver" "emotion=$pkgver"
+ "eina=$pkgver" "eio=$pkgver" "embryo=$pkgver" "emotion=$pkgver" "emodel=$pkgver"
"ephysics=$pkgver" "ethumb=$pkgver" "evas=$pkgver")
conflicts+=('ecore' 'edje' 'eet' 'eeze' 'efreet' 'eina' 'eio' 'embryo' 'emotion'
'ethumb' 'evas')
diff --git a/src/Makefile.am b/src/Makefile.am
index b0b48848fb..fda99070f4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,7 +9,8 @@ EOLIAN_FLAGS = -I$(srcdir)\
-I$(srcdir)/lib/efl/interfaces \
-I$(srcdir)/lib/ecore_audio \
-I$(srcdir)/lib/ecore \
- -I$(srcdir)/lib/ecore_con
+ -I$(srcdir)/lib/ecore_con \
+ -I$(srcdir)/lib/eio
DIST_SUBDIRS =
SUBDIRS =
@@ -78,6 +79,8 @@ include Makefile_Eolian_Cxx.am
include Makefile_Eet_Cxx.am
include Makefile_Eo_Cxx.am
include Makefile_Efl_Cxx.am
+include Makefile_Eio_Cxx.am
+
include Makefile_Elua.am
include Makefile_Elocation.am
diff --git a/src/Makefile_Efl.am b/src/Makefile_Efl.am
index 5533dce961..709a5ee83e 100644
--- a/src/Makefile_Efl.am
+++ b/src/Makefile_Efl.am
@@ -4,7 +4,8 @@ efl_eolian_files = \
lib/efl/interfaces/efl_image.eo \
lib/efl/interfaces/efl_player.eo \
lib/efl/interfaces/efl_text.eo \
- lib/efl/interfaces/efl_text_properties.eo
+ lib/efl/interfaces/efl_text_properties.eo \
+ lib/efl/interfaces/efl_model_base.eo
efl_eolian_files_h = $(efl_eolian_files:%.eo=%.eo.h)
efl_eolian_files_c = $(efl_eolian_files:%.eo=%.eo.c)
@@ -20,6 +21,8 @@ CLEANFILES += \
EXTRA_DIST += \
lib/efl/Efl_Config.h \
lib/efl/Efl.h \
+ lib/efl/Efl_Model.h \
+ lib/efl/Efl_Model_Common.h \
$(efl_eolian_files)
efleolianfilesdir = $(datadir)/eolian/include/efl-@VMAJ@
diff --git a/src/Makefile_Efl_Cxx.am b/src/Makefile_Efl_Cxx.am
index 1ddd25dc49..538d4beda1 100644
--- a/src/Makefile_Efl_Cxx.am
+++ b/src/Makefile_Efl_Cxx.am
@@ -11,7 +11,7 @@ generated_efl_cxx_bindings = \
lib/efl/interfaces/efl_text_properties.eo.hh
lib/efl/Efl.hh: $(generated_efl_cxx_bindings)
- @echo @ECHO_E@ "#ifndef EFL_CXX_EDJE_HH\n#define EFL_CXX_EDJE_HH\n" > $(top_builddir)/src/lib/efl/Efl.hh
+ @echo @ECHO_E@ "#ifndef EFL_CXX_HH\n#define EFL_CXX_HH\n" > $(top_builddir)/src/lib/efl/Efl.hh
@echo @ECHO_E@ "#ifdef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/efl/Efl.hh
@for i in $(generated_efl_cxx_bindings); do echo "#include <$$(basename $$i)>" >> $(top_builddir)/src/lib/efl/Efl.hh; done
@echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/efl/Efl.hh
diff --git a/src/Makefile_Eio.am b/src/Makefile_Eio.am
index ff0f442be6..531d285a37 100644
--- a/src/Makefile_Eio.am
+++ b/src/Makefile_Eio.am
@@ -1,10 +1,24 @@
### Library
+EIO_EOS = \
+ lib/eio/eio_model.eo
+
+EIO_EOS_H = $(EIO_EOS:%.eo=%.eo.h)
+EIO_EOS_C = $(EIO_EOS:%.eo=%.eo.c)
+
+BUILT_SOURCES += $(EIO_EOS_C) $(EIO_EOS_H)
+
+eioeolianfilesdir = $(datadir)/eolian/include/eio-@VMAJ@
+eioeolianfiles_DATA = $(EIO_EOS)
+
lib_LTLIBRARIES += lib/eio/libeio.la
+EXTRA_DIST += $(eioeolianfiles_DATA)
installed_eiomainheadersdir = $(includedir)/eio-@VMAJ@
+
dist_installed_eiomainheaders_DATA = lib/eio/Eio.h lib/eio/eio_inline_helper.x
+nodist_installed_eiomainheaders_DATA = $(EIO_EOS_H)
lib_eio_libeio_la_SOURCES = \
lib/eio/eio_dir.c \
@@ -16,6 +30,8 @@ lib/eio/eio_monitor.c \
lib/eio/eio_monitor_poll.c \
lib/eio/eio_single.c \
lib/eio/eio_xattr.c \
+lib/eio/eio_model.c \
+lib/eio/eio_model_private.h \
lib/eio/eio_private.h
if HAVE_INOTIFY
@@ -26,7 +42,44 @@ lib_eio_libeio_la_SOURCES += lib/eio/eio_monitor_win32.c
endif
endif
-lib_eio_libeio_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @EIO_CFLAGS@
-lib_eio_libeio_la_LIBADD = @EIO_LIBS@
-lib_eio_libeio_la_DEPENDENCIES = @EIO_INTERNAL_LIBS@
+lib_eio_libeio_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @EIO_CFLAGS@ @EFL_CFLAGS@
+lib_eio_libeio_la_LIBADD = @EIO_LIBS@ @EFL_LIBS@
+lib_eio_libeio_la_DEPENDENCIES = @EIO_INTERNAL_LIBS@ @EFL_INTERNAL_LIBS@
lib_eio_libeio_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
+if HAVE_NOTIFY_COCOA
+lib_eio_libeio_la_LDFLAGS += -framework CoreServices
+endif
+
+if EFL_ENABLE_TESTS
+
+check_PROGRAMS += tests/eio/eio_suite
+TESTS += tests/eio/eio_suite
+
+tests_eio_eio_suite_SOURCES = \
+tests/eio/eio_suite.c \
+tests/eio/eio_model_test_file.c \
+tests/eio/eio_model_test_monitor_add.c \
+tests/eio/eio_test_monitor.c
+
+tests_eio_eio_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
+-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/eio\" \
+-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eio\" \
+@CHECK_CFLAGS@ \
+@ECORE_FILE_CFLAGS@ \
+@EIO_CFLAGS@ @EFL_CFLAGS@
+
+tests_eio_eio_suite_LDADD = \
+@CHECK_LIBS@ \
+@USE_ECORE_FILE_LIBS@ \
+@USE_EIO_LIBS@
+@USE_EFL_LIBS@
+
+tests_eio_eio_suite_DEPENDENCIES = \
+@USE_EIO_INTERNAL_LIBS@
+
+endif
+
+EXTRA_DIST += \
+tests/eio/eio_suite.h \
+lib/eio/eio_model.h
+
diff --git a/src/Makefile_Eio_Cxx.am b/src/Makefile_Eio_Cxx.am
new file mode 100644
index 0000000000..3f5237169c
--- /dev/null
+++ b/src/Makefile_Eio_Cxx.am
@@ -0,0 +1,22 @@
+if HAVE_CXX11
+
+### Generated headers
+
+generated_eio_cxx_bindings = lib/eio/eio_model.eo.hh
+
+lib/eio/Eio.hh: $(generated_eio_cxx_bindings)
+ @echo @ECHO_E@ "#ifndef EFL_CXX_EIO_HH\n#define EFL_CXX_EIO_HH\n" > $(top_builddir)/src/lib/eio/Eio.hh
+ @echo @ECHO_E@ "#ifdef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/eio/Eio.hh
+ @for i in $(generated_eio_cxx_bindings); do echo "#include <$$(basename $$i)>" >> $(top_builddir)/src/lib/eio/Eio.hh; done
+ @echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/eio/Eio.hh
+
+generated_eio_cxx_all = \
+ $(generated_eio_cxx_bindings) \
+ lib/eio/Eio.hh
+
+CLEANFILES += $(generated_eio_cxx_all)
+
+installed_eiocxxmainheadersdir = $(includedir)/eio-cxx-@VMAJ@/
+nodist_installed_eiocxxmainheaders_DATA = $(generated_eio_cxx_all)
+
+endif
diff --git a/src/examples/eio/Makefile.am b/src/examples/eio/Makefile.am
index 9754369396..ed07ea291e 100644
--- a/src/examples/eio/Makefile.am
+++ b/src/examples/eio/Makefile.am
@@ -20,6 +20,7 @@ eio_file_copy
eio_file_ls_SOURCES = eio_file_ls.c
eio_file_ls_LDADD = \
$(top_builddir)/src/lib/eio/libeio.la \
+$(top_builddir)/src/lib/emodel/libemodel.la \
$(top_builddir)/src/lib/eo/libeo.la \
$(top_builddir)/src/lib/ecore/libecore.la \
$(top_builddir)/src/lib/eet/libeet.la \
@@ -29,6 +30,7 @@ $(top_builddir)/src/lib/eina/libeina.la \
eio_file_copy_SOURCES = eio_file_copy.c
eio_file_copy_LDADD = \
$(top_builddir)/src/lib/eio/libeio.la \
+$(top_builddir)/src/lib/emodel/libemodel.la \
$(top_builddir)/src/lib/eo/libeo.la \
$(top_builddir)/src/lib/ecore/libecore.la \
$(top_builddir)/src/lib/eet/libeet.la \
diff --git a/src/lib/efl/Efl.h b/src/lib/efl/Efl.h
index f4cdedcf99..336e2a8c0b 100644
--- a/src/lib/efl/Efl.h
+++ b/src/lib/efl/Efl.h
@@ -36,6 +36,8 @@ extern "C"
#ifdef EFL_BETA_API_SUPPORT
+#include <Efl_Model_Common.h>
+
/* Interfaces */
#include "interfaces/efl_control.eo.h"
#include "interfaces/efl_file.eo.h"
@@ -43,6 +45,7 @@ extern "C"
#include "interfaces/efl_player.eo.h"
#include "interfaces/efl_text.eo.h"
#include "interfaces/efl_text_properties.eo.h"
+#include "interfaces/efl_model_base.eo.h"
#endif
diff --git a/src/lib/efl/Efl_Model_Common.h b/src/lib/efl/Efl_Model_Common.h
new file mode 100644
index 0000000000..bd9ab62e5f
--- /dev/null
+++ b/src/lib/efl/Efl_Model_Common.h
@@ -0,0 +1,92 @@
+#ifndef _EFL_MODEL_COMMON_H
+#define _EFL_MODEL_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @enum _Efl_Model_Load_Status
+ * XXX/TODO/FIXME: Remove this enum (and possibly other data) from here
+ * as soon as eolian translates these data types in .eo's.
+ */
+enum _Efl_Model_Load_Status
+ {
+ EFL_MODEL_LOAD_STATUS_ERROR = 0,
+ EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES = (1 << 0),
+ EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN = (1 << 1),
+ EFL_MODEL_LOAD_STATUS_LOADING = (1 << 0) | (1 << 1),
+
+ EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES = (1 << 2),
+ EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN = (1 << 3),
+ EFL_MODEL_LOAD_STATUS_LOADED = (1 << 2) | (1 << 3),
+
+ EFL_MODEL_LOAD_STATUS_UNLOADING = (1 << 4),
+ EFL_MODEL_LOAD_STATUS_UNLOADED = (1 << 5)
+ };
+/**
+ * @typedef Efl_Model_Load_Status
+ */
+typedef enum _Efl_Model_Load_Status Efl_Model_Load_Status;
+
+/**
+ * @struct _Efl_Model_Load
+ * Structure to hold Efl_Model_Load_Status enum
+ * (and possible other data) to avoid ABI break.
+ */
+struct _Efl_Model_Load
+ {
+ Efl_Model_Load_Status status;
+ /* add more data below here if necessary */
+ };
+
+/**
+ * @typedef Efl_Model_Load
+ */
+typedef struct _Efl_Model_Load Efl_Model_Load;
+
+/**
+ * @struct _Efl_Model_Property_Event
+ */
+struct _Efl_Model_Property_Event
+{
+ const Eina_Array *changed_properties; /**< array of property name */
+ const Eina_Array *invalidated_properties; /**< array of property name */
+};
+
+/**
+ * @typedef Efl_Model_Property_Event
+ */
+typedef struct _Efl_Model_Property_Event Efl_Model_Property_Event;
+
+/**
+ * @struct _Efl_Model_Children_Event
+ * Every time a child id added the event
+ * EFL_MODEL_EVENT_CHILD_ADDED is dispatched
+ * passing along this structure.
+ */
+struct _Efl_Model_Children_Event
+{
+ Eo *child; /**< child, for child_add */
+ /**
+ * index is a hint and is intended
+ * to provide a way for applications
+ * to control/know children relative
+ * positions through listings.
+ *
+ * NOTE: If listing is performed asynchronously
+ * exact order may not be guaranteed.
+ */
+ unsigned int index;
+};
+
+/**
+ * @struct Efl_Model_Children_Event
+ */
+typedef struct _Efl_Model_Children_Event Efl_Model_Children_Event;
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/lib/efl/interfaces/efl_interfaces_main.c b/src/lib/efl/interfaces/efl_interfaces_main.c
index c490636a3d..16b9423c71 100644
--- a/src/lib/efl/interfaces/efl_interfaces_main.c
+++ b/src/lib/efl/interfaces/efl_interfaces_main.c
@@ -10,3 +10,4 @@
#include "interfaces/efl_player.eo.c"
#include "interfaces/efl_text.eo.c"
#include "interfaces/efl_text_properties.eo.c"
+#include "interfaces/efl_model_base.eo.c"
diff --git a/src/lib/efl/interfaces/efl_model_base.eo b/src/lib/efl/interfaces/efl_model_base.eo
new file mode 100644
index 0000000000..75e280ebd4
--- /dev/null
+++ b/src/lib/efl/interfaces/efl_model_base.eo
@@ -0,0 +1,322 @@
+/*
+ * type Efl_Model_Load_Status: enum _Efl_Model_Load_Status
+ * {
+ * EFL_MODEL_LOAD_STATUS_ERROR = 0, /*@ Error in Load Model *
+ * EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES = (1 << 0), /*@ properties load in progress *
+ * EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN = (1 << 1), /*@ children load in progress *
+ * EFL_MODEL_LOAD_STATUS_LOADING = (1 << 0) | (1 << 1), /*@ children and properties load in progress *
+ *
+ * EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES = (1 << 2), /*@ Model as ready to fetch properties *
+ * EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN = (1 << 3), /*@ Model as ready to fetch children *
+ * EFL_MODEL_LOAD_STATUS_LOADED = (1 << 2) | (1 << 3), /*@ Model as ready to fetch properties and children *
+ *
+ * EFL_MODEL_LOAD_STATUS_UNLOADING = (1 << 4), /*@ Model Unload in progress *
+ * EFL_MODEL_LOAD_STATUS_UNLOADED = (1 << 5) /*@ Model Unloaded *
+ * }
+ *
+ *
+ * type Efl_Model_Property_Event: struct _Efl_Model_Property_Event
+ * {
+ * changed_properties: Eina_Array* <const(char)*>; /*@ List of changed properties *
+ * invalidated_properties: Eina_Array* <const(char)*>; /*@ Removed properties identified by name *
+ * }
+ */
+
+interface Efl.Model.Base ()
+{
+ legacy_prefix: null;
+ eo_prefix: efl_model;
+ properties {
+ load_status {
+ get {
+ /*@
+ Get a load emodel current status.
+
+ @return: @c Efl_Model_Load_Status
+
+ By convention this means get the current model status.
+ Possible values are defined Efl_Model_Load_Status enumerator.
+
+ @see Efl_Model_Load_Status
+ @see efl_model_load
+
+ @since 1.14 */
+ return: Efl_Model_Load_Status;
+ }
+ }
+ properties {
+ get {
+ /*@
+ Get properties from model.
+
+ @return: @c Efl_Model_Load_Status
+
+ properties_get is due to provide callers a way the fetch the current
+ properties implemented/used by the model.
+ The event EFL_MODEL_EVENT_PROPERTIES_CHANGE will be raised to notify listeners
+ of any modifications in the properties.
+
+ @see EFL_MODEL_EVENT_PROPERTIES_CHANGE
+ @since 1.14 */
+
+ return: Efl_Model_Load_Status;
+ }
+ values {
+ const(array<const(char*)>*) properties; /*@ array of current properties */
+ }
+ }
+ property {
+ set {
+ /*@
+ Set a property value of a given property name.
+
+ @return: @c EINA_TRUE, on success, @c EINA_FALSE in readonly property or error
+
+ The caller must ensure to call at least efl_model_prop_list before being
+ able to see/set properties.
+ This function sets a new property value into given property name. Once
+ the operation is completed the concrete implementation should raise
+ EFL_MODEL_EVENT_PROPERTIES_CHANGE event in order to notify listeners of the
+ new value of the property.
+
+ If the model doesn't have the property then there are two possibilities,
+ either raise an error or create the new property in model
+
+ @see efl_model_property_get
+ @see EFL_MODEL_EVENT_PROPERTIES_CHANGE
+ @since 1.14 */
+
+ return: Efl_Model_Load_Status;
+ }
+ get {
+ /*@
+ Retrieve the value of a given property name.
+
+ @return: @c Load Status, on success, @c EFL_MODEL_LOAD_STATUS_ERROR otherwise
+
+ property_get will only be available when load status is equal to
+ EFL_MODEL_LOAD_STATUS_LOADED.
+
+ At this point the caller is free to get values from properties.
+ The event EFL_MODEL_EVENT_PROPERTIES_CHANGE may be raised to notify
+ listeners of the property/value.
+
+ @see efl_model_properties_get
+ @see EFL_MODEL_EVENT_PROPERTIES_CHANGE
+
+ @since 1.14 */
+ return: Efl_Model_Load_Status;
+ }
+ keys {
+ const(char)* property; /*@ Property name */
+ }
+ values {
+ const(Eina_Value)* value; /*@ New value */
+ }
+ }
+ children_slice {
+ get {
+ /*@
+ Get children slice OR full range.
+
+ @return: @c Efl_Model_Load_Status. See below for more info.
+
+ Before being able to get the children list the model status must be
+ on loaded status (EFL_MODEL_LOAD_STATUS_LOADED).
+ However there may be circunstancies where the model could be
+ in a different state, in such cases it is advisable
+ to simply return: its current state, which will be
+ of course, different than @c EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN.
+ When children accessor is return:ed as NULL one should then
+ test the current load status return:ed by @children_slice_get
+ in order to check against an empty list or real error.
+
+ children_slice_get behaves in two different ways, it may provide
+ the slice if both @c start AND @c count are non-zero OR full range otherwise.
+
+ The return:ed Eina_Accessor must be freed when it is no longer needed and
+ eo_unref() must be invoked for children if caller wants a copy.
+
+ Since 'slice' is a range, for example if we have 20 childs a slice could be
+ the range from 3(start) to 4(count), see:
+ child 0 [no]
+ child 1 [no]
+ child 2 [yes]
+ child 3 [yes]
+ child 4 [yes]
+ child 5 [yes]
+ child 6 [no]
+ child 7 [no]
+
+ Optionally the user can call children_count_get to know
+ the number of children so a valid range can be known in advance.
+
+ Below are examples of both usage types: slices and full ranges.
+ @code
+
+ // Returns full list
+ eo_do(obj, efl_model_children_slice_get(0, 0, &children_accessor));
+
+ // Returns 5 items, counting from item #5
+ eo_do(obj, efl_model_children_slice_get(5, 5, &children_accessor));
+
+ @endcode
+
+ @see efl_model_children_get
+ @see efl_model_children_count_get
+ @see efl_model_load
+ @see efl_model_load_status_get
+ @since 1.14 */
+
+ return: Efl_Model_Load_Status;
+ }
+ keys {
+ unsigned start; /*@ Range begin - start from here. If start and count are 0 slice is ignored.*/
+ unsigned count; /*@ Range size. If count and start are 0 slice is ignored.*/
+ }
+ values {
+ accessor<list*>* children_accessor;
+ }
+ }
+ children_count {
+ get {
+ /*@
+ Get children count.
+
+ @return: @c EINA_TRUE, on success, @c EINA_FALSE otherwise
+
+ When efl_model_load is completed efl_model_coildren_count_get can be use
+ to get the number of children. children_count_get can also be used
+ before calling children_slice_get so a valid range is known.
+ Event EFL_MODEL_CHILDREN_COUNT_CHANGED is emitted when count is finished.
+
+ @see efl_model_children_get
+ @see efl_model_children_slice_get
+ @see efl_model_load
+ @see efl_model_load_status_get
+ @since 1.14 */
+
+ return: Efl_Model_Load_Status;
+ }
+ values {
+ unsigned children_count;
+ }
+ }
+ }
+ methods {
+ load {
+ /*@
+ Load emodel.
+
+ By convention this means loading data from an external source and populating
+ the models properties and children with it. For example in the case of file
+ system backed model, this means opening the relevant files and reading the
+ data from them(creating the properties and children from it).
+ the model emit EFL_MODEL_EVENT_LOAD_STATUS after end with Efl_Model_Load_Status
+ @warning This convention should be followed, but no guarantees of behaviour
+ by user defined types can be given.
+
+ Alternatively is possible to use properties_load to load only properties
+ and children_load to load only children. If efl_model_load is called then
+ calling properties_load and/or children_load is not necessary.
+
+ @see Efl_Model_Load_Status
+ @see efl_model_properties_load
+ @see efl_model_children_load
+ @see efl_model_unload
+ @see efl_model_load_status_get
+
+ @since 1.14 */
+ }
+ unload {
+ /*@
+ Unload emodel.
+
+ By convention this means releasing data received/read from an external source. For
+ example of a database backed model this might mean releasing the iterator for
+ the currently loaded data or deleting a temporary table.
+ the model emit EFL_MODEL_EVENT_LOAD_STATUS after end with model load status
+ @warning This convention should be followed, but no guarantees of behaviour
+ by user defined types can be given.
+
+ @see Efl_Model_Load_Status
+ @see efl_model_load
+ @see efl_model_load_status_get
+
+ @since 1.14 */
+ }
+ properties_load {
+ /*@
+ Properties emodel load.
+
+ By convention this means loading data from an external source and populating
+ the models properties only. This method is a subset of efl_model_load, meaning that
+ it won't load children, it is a hint.
+ For loadind both properties and children use efl_model_load
+ instead.
+
+ @see efl_model_load
+
+ @since 1.14 */
+ }
+ children_load {
+ /*@
+ Children emodel load.
+
+ By convention this means loading data from an external source and populating
+ the models children only. This method is a subset of efl_model_load, meaning that
+ it won't load properties. For loadind both properties and children use efl_model_load
+ instead.
+
+ @see efl_model_load
+
+ @since 1.14 */
+ }
+ child_add {
+ /*@
+ Add a new child.
+
+ @return: @c Emodel* on success, @c NULL otherwise
+
+ Add a new child, possibly dummy, depending on the implementation,
+ of a internal keeping. When the child is effectively
+ added the event EFL_MODEL_EVENT_CHILD_ADD is then raised and the new child
+ is kept along with other children.
+
+ @see EFL_MODEL_EVENT_CHILD_ADD
+ @see load_status_get
+
+ @since 1.14 */
+
+ return: Eo *;
+ }
+ child_del {
+ /*@
+ Remove a child.
+
+ @return: @c Efl_Model_Load_Status on success, @c EFL_MODEL_LOAD_STATUS_ERROR otherwise.
+
+ Remove a child of a internal keeping. When the child is effectively
+ removed the event EFL_MODEL_EVENT_CHILD_REMOVED is then raised to give a
+ chance for listeners to perform any cleanup and/or update references.
+
+ @see EFL_MODEL_EVENT_CHILD_REMOVED
+ @since 1.14 */
+
+ return: Efl_Model_Load_Status;
+
+ params {
+ @in Eo* child; /*@ Child to be removed */
+ }
+ }
+ }
+
+ events {
+ load,status: Efl_Model_Load_Status; /*@ Event dispatch when load status changes */
+ properties,changed: Efl_Model_Properties_Evt; /*@ Event dispatched when properties list is available. */
+ child,added; /*@ Event dispatched when new child is added. */
+ child,removed; /*@ Event dispatched when child is removed. */
+ children,count,changed; /*@ Event dispatched when children count is finished. */
+ }
+}
+
diff --git a/src/lib/eio/eio_model.c b/src/lib/eio/eio_model.c
new file mode 100644
index 0000000000..0a93658331
--- /dev/null
+++ b/src/lib/eio/eio_model.c
@@ -0,0 +1,683 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdint.h>
+
+#include <Efl.h>
+#include <Eina.h>
+#include <eio_model.h>
+#include <Eio.h>
+#include <Ecore.h>
+#include <Eo.h>
+
+#include "eio_private.h"
+#include "eio_model_private.h"
+
+#define MY_CLASS EIO_MODEL_CLASS
+#define MY_CLASS_NAME "Eio_Model"
+
+static void _eio_prop_set_error_cb(void *, Eio_File *, int);
+static void _eio_model_efl_model_base_properties_load(Eo *, Eio_Model_Data *);
+static void _eio_model_efl_model_base_children_load(Eo *, Eio_Model_Data *);
+
+static void
+_load_set(Eio_Model_Data *priv, Efl_Model_Load_Status status)
+{
+ Efl_Model_Load load;
+
+ load.status = status;
+ if ((priv->load.status & (EFL_MODEL_LOAD_STATUS_LOADED | EFL_MODEL_LOAD_STATUS_LOADING)) &&
+ (load.status & (EFL_MODEL_LOAD_STATUS_LOADED | EFL_MODEL_LOAD_STATUS_LOADING)))
+ {
+ load.status = priv->load.status | status;
+ switch (status)
+ {
+ case EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES:
+ load.status &= ~EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES;
+ break;
+ case EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES:
+ load.status &= ~EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES;
+ break;
+ case EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN:
+ load.status &= ~EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN;
+ break;
+ case EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN:
+ load.status &= ~EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN;
+ break;
+ default: break;
+ }
+ }
+
+ if (priv->load.status != load.status)
+ {
+ priv->load.status = load.status;
+ eo_do(priv->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_LOAD_STATUS, &load));
+ }
+}
+
+/**
+ * Callbacks
+ * Property
+ */
+static void
+_eio_stat_done_cb(void *data, Eio_File *handler EINA_UNUSED, const Eina_Stat *stat)
+{
+ Efl_Model_Property_Event evt;
+ Eio_Model_Data *priv = data;
+ EINA_SAFETY_ON_FALSE_RETURN(eo_ref_get(priv->obj));
+
+ priv->is_dir = eio_file_is_dir(stat);
+ memset(&evt, 0, sizeof(Efl_Model_Property_Event));
+
+ eina_value_set(priv->properties_value[EIO_MODEL_PROP_IS_DIR], eio_file_is_dir(stat));
+ eina_value_set(priv->properties_value[EIO_MODEL_PROP_IS_LNK], eio_file_is_lnk(stat));
+ eina_value_set(priv->properties_value[EIO_MODEL_PROP_MTIME], eio_file_mtime(stat));
+ eina_value_set(priv->properties_value[EIO_MODEL_PROP_SIZE], eio_file_size(stat));
+
+ evt.changed_properties = priv->properties_name;
+ eo_do(priv->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
+
+ _load_set(priv, EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES);
+
+ if (priv->load_pending & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
+ _eio_model_efl_model_base_children_load(priv->obj, priv);
+}
+
+static void
+_eio_progress_cb(void *data EINA_UNUSED, Eio_File *handler EINA_UNUSED, const Eio_Progress *info EINA_UNUSED)
+{
+ //TODO: implement
+}
+
+static void
+_eio_move_done_cb(void *data, Eio_File *handler EINA_UNUSED)
+{
+ Efl_Model_Property_Event evt;
+ Eio_Model_Data *priv = data;
+ Eina_Array *properties;
+
+ EINA_SAFETY_ON_FALSE_RETURN(eo_ref_get(priv->obj));
+
+ memset(&evt, 0, sizeof(Efl_Model_Property_Event));
+
+ /**
+ * When mv is executed we update our values and
+ * notify both path and filename properties listeners.
+ */
+ eina_value_set(priv->properties_value[EIO_MODEL_PROP_PATH], priv->path);
+ eina_value_set(priv->properties_value[EIO_MODEL_PROP_FILENAME], basename(priv->path));
+
+ properties = eina_array_new(2);
+ eina_array_push(properties, _eio_model_prop_names[EIO_MODEL_PROP_PATH]);
+ eina_array_push(properties, _eio_model_prop_names[EIO_MODEL_PROP_FILENAME]);
+ evt.changed_properties = properties;
+
+ eo_do(priv->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, &evt));
+ eina_array_free(properties);
+}
+
+static void
+_eio_error_cb(void *data EINA_UNUSED, Eio_File *handler EINA_UNUSED, int error)
+{
+ if (error != 0)
+ {
+ ERR("%d: %s.", error, strerror(error));
+ }
+}
+
+static void
+_eio_prop_set_error_cb(void *data EINA_UNUSED, Eio_File *handler EINA_UNUSED, int error)
+{
+ if (error != 0)
+ {
+ ERR("%d: %s.", error, strerror(error));
+ }
+}
+
+
+/**
+ * Callbacks
+ * Ecore Events
+ */
+static Eina_Bool
+_efl_model_evt_added_ecore_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
+{
+ Eio_Monitor_Event *evt = (Eio_Monitor_Event*)event;
+ Eio_Model_Data *priv = data;
+ Efl_Model_Children_Event cevt;
+ Eina_Value path;
+
+ if (priv->children_list)
+ {
+ cevt.child = eo_add_ref(EIO_MODEL_CLASS, priv->obj, eio_model_path_set(evt->filename));
+ priv->children_list = eina_list_append(priv->children_list, cevt.child);
+ cevt.index = eina_list_count(priv->children_list);
+
+ eina_value_setup(&path, EINA_VALUE_TYPE_STRING);
+ eina_value_set(&path, evt->filename);
+ eo_do(cevt.child, eio_model_children_filter_set(priv->filter_cb, priv->filter_userdata));
+ eina_value_flush(&path);
+
+ eo_do(priv->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILD_ADDED, &cevt));
+ }
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_efl_model_evt_deleted_ecore_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
+{
+ Eio_Monitor_Event *evt = (Eio_Monitor_Event*)event;
+ Eio_Model_Data *priv = data;
+
+ if (priv->children_list)
+ {
+ Eina_List* cur = priv->children_list;
+ int i;
+
+ for (i = 0; cur; ++i, cur = cur->next)
+ {
+ Eio_Model_Data *cur_priv = eo_data_scope_get(cur->data, MY_CLASS);
+ if(strcmp(cur_priv->path, evt->filename) == 0)
+ break;
+ }
+
+ if (cur)
+ {
+ Efl_Model_Children_Event cevt;
+ cevt.index = i;
+ cevt.child = cur->data;
+
+ eo_do(priv->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILD_REMOVED, &cevt));
+
+ priv->children_list = eina_list_remove_list(priv->children_list, cur);
+ eo_unref(cevt.child);
+ }
+ }
+
+ return EINA_TRUE;
+}
+
+static void
+_eio_monitors_list_load(Eio_Model_Data *priv)
+{
+ priv->mon.mon_event_child_add[0] = EIO_MONITOR_DIRECTORY_CREATED;
+ priv->mon.mon_event_child_add[1] = EIO_MONITOR_FILE_CREATED;
+ priv->mon.mon_event_child_add[2] = EIO_MONITOR_ERROR;
+ priv->mon.mon_event_child_del[0] = EIO_MONITOR_DIRECTORY_DELETED;
+ priv->mon.mon_event_child_del[1] = EIO_MONITOR_FILE_DELETED;
+ priv->mon.mon_event_child_del[2] = EIO_MONITOR_ERROR;
+}
+
+/**
+ * Callbacks
+ * Child Del
+ */
+static Eina_Bool
+_eio_filter_child_del_cb(void *data EINA_UNUSED, Eio_File *handler EINA_UNUSED, const Eina_File_Direct_Info *info EINA_UNUSED)
+{
+ return EINA_TRUE;
+}
+
+static void
+_eio_progress_child_del_cb(void *data EINA_UNUSED, Eio_File *handler EINA_UNUSED, const Eio_Progress *info EINA_UNUSED)
+{}
+
+static void
+_eio_done_unlink_cb(void *data, Eio_File *handler EINA_UNUSED)
+{
+ Eio_Model_Data *priv = data;
+
+ EINA_SAFETY_ON_NULL_RETURN(priv);
+ EINA_SAFETY_ON_NULL_RETURN(priv->obj);
+
+ eo_unref(priv->obj);
+}
+
+static void
+_eio_error_unlink_cb(void *data EINA_UNUSED, Eio_File *handler EINA_UNUSED, int error)
+{
+ Eio_Model_Data *priv = data;
+
+ ERR("%d: %s.", error, strerror(error));
+
+ eo_unref(priv->obj);
+}
+
+
+/**
+ * Interfaces impl.
+ */
+static Efl_Model_Load_Status
+_eio_model_efl_model_base_properties_get(Eo *obj EINA_UNUSED,
+ Eio_Model_Data *_pd, Eina_Array * const* properties)
+{
+ Eio_Model_Data *priv = _pd;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(priv, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(priv->obj, EINA_FALSE);
+
+ *(Eina_Array **)properties = priv->properties_name;
+
+ return priv->load.status;
+}
+
+/**
+ * Property Get
+ */
+static Efl_Model_Load_Status
+_eio_model_efl_model_base_property_get(Eo *obj EINA_UNUSED, Eio_Model_Data *priv, const char *property, const Eina_Value **value)
+{
+ unsigned int i;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(property, EFL_MODEL_LOAD_STATUS_ERROR);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(priv, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ *value = NULL;
+ if (priv->load.status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
+ {
+ for (i = 0; i < EIO_MODEL_PROP_LAST; ++i)
+ {
+ if (!strcmp(property, _eio_model_prop_names[i]))
+ break;
+ }
+
+ if ( i < EIO_MODEL_PROP_LAST)
+ {
+ *value = priv->properties_value[i];
+ }
+ }
+
+ return priv->load.status;
+}
+
+/**
+ * Property Set
+ */
+static Efl_Model_Load_Status
+_eio_model_efl_model_base_property_set(Eo *obj EINA_UNUSED, Eio_Model_Data *priv, const char * property, const Eina_Value *value)
+{
+ char *dest;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(property, EINA_FALSE);
+
+ if (strcmp(property, "path") != 0)
+ return EINA_FALSE;
+
+ dest = eina_value_to_string(value);
+ if (priv->path == NULL)
+ {
+ priv->path = dest;
+
+ INF("path '%s' with filename '%s'.", priv->path, basename(priv->path));
+
+ eina_value_set(priv->properties_value[EIO_MODEL_PROP_PATH], priv->path);
+ eina_value_set(priv->properties_value[EIO_MODEL_PROP_FILENAME], basename(priv->path));
+
+ _eio_monitors_list_load(priv);
+
+ _eio_move_done_cb(priv, NULL);
+
+ if (priv->load_pending & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
+ _eio_model_efl_model_base_properties_load(obj, priv);
+ else if (priv->load_pending & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
+ _eio_model_efl_model_base_children_load(obj, priv);
+
+ return priv->load.status;
+ }
+
+ priv->file = eio_file_move(priv->path, dest, _eio_progress_cb, _eio_move_done_cb, _eio_prop_set_error_cb, priv);
+ free(priv->path);
+ priv->path = dest;
+
+ return priv->load.status;
+}
+/**
+ * Children Count Get
+ */
+static Efl_Model_Load_Status
+_eio_model_efl_model_base_children_count_get(Eo *obj EINA_UNUSED, Eio_Model_Data *priv, unsigned int *children_count)
+{
+ /**< eina_list_count returns 'unsigned int' */
+ *children_count = eina_list_count(priv->children_list);
+ return priv->load.status;
+}
+
+/**
+ * Properties Load
+ */
+static void
+_eio_model_efl_model_base_properties_load(Eo *obj EINA_UNUSED, Eio_Model_Data *priv)
+{
+ if (priv->path == NULL)
+ {
+ priv->load_pending |= EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES;
+ return;
+ }
+ priv->load_pending &= ~EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES;
+
+ if (!(priv->load.status & (EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES | EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES)))
+ {
+ _load_set(priv, EFL_MODEL_LOAD_STATUS_LOADING_PROPERTIES);
+ priv->file = eio_file_direct_stat(priv->path, _eio_stat_done_cb, _eio_error_cb, priv);
+ }
+}
+
+static void
+_eio_model_efl_model_base_monitor_add(Eio_Model_Data *priv)
+{
+ if (!priv->monitor)
+ {
+ priv->monitor = eio_monitor_add(priv->path);
+ int i = 0;
+
+ for (i = 0; priv->mon.mon_event_child_add[i] != EIO_MONITOR_ERROR ; ++i)
+ priv->mon.ecore_child_add_handler[i] =
+ ecore_event_handler_add(priv->mon.mon_event_child_add[i], _efl_model_evt_added_ecore_cb, priv);
+
+ for (i = 0; priv->mon.mon_event_child_del[i] != EIO_MONITOR_ERROR ; ++i)
+ priv->mon.ecore_child_add_handler[i] =
+ ecore_event_handler_add(priv->mon.mon_event_child_del[i], _efl_model_evt_deleted_ecore_cb, priv);
+ }
+}
+
+/*
+ * Callbacks
+ * Children Load
+ */
+static Eina_Bool
+_eio_filter_children_load_cb(void *data, Eio_File *handler, const Eina_File_Direct_Info *info)
+{
+ Eio_Model_Data *priv = data;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(priv, EINA_FALSE);
+
+ if (priv->filter_cb)
+ {
+ return priv->filter_cb(priv->filter_userdata, handler, info);
+ }
+
+ return EINA_TRUE;
+}
+
+static void
+_eio_main_children_load_cb(void *data, Eio_File *handler EINA_UNUSED, const Eina_File_Direct_Info *info)
+{
+ Eo *child;
+ Eio_Model_Data *priv = data;
+ EINA_SAFETY_ON_NULL_RETURN(priv);
+
+ child = eo_add(MY_CLASS, NULL, eio_model_path_set(info->path));
+ if (priv->filter_cb)
+ eo_do(child, eio_model_children_filter_set(priv->filter_cb, priv->filter_userdata));
+
+ priv->children_list = eina_list_append(priv->children_list, child);
+}
+
+static void
+_eio_done_children_load_cb(void *data, Eio_File *handler EINA_UNUSED)
+{
+ unsigned long count;
+ Eio_Model_Data *priv = data;
+ EINA_SAFETY_ON_NULL_RETURN(priv);
+
+ count = eina_list_count(priv->children_list);
+ _load_set(priv, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+
+ eo_do(priv->obj, eo_event_callback_call(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, &count));
+}
+
+static void
+_eio_error_children_load_cb(void *data, Eio_File *handler EINA_UNUSED, int error)
+{
+ Eio_Model_Data *priv = data;
+ Eo *child;
+
+ ERR("%d: %s.", error, strerror(error));
+
+ EINA_LIST_FREE(priv->children_list, child)
+ eo_unref(child);
+
+ _load_set(priv, EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN);
+}
+
+/**
+ * Children Load
+ */
+static void
+_eio_model_efl_model_base_children_load(Eo *obj EINA_UNUSED, Eio_Model_Data *priv)
+{
+ if (priv->path == NULL)
+ {
+ priv->load_pending |= EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN;
+ return;
+ }
+
+ priv->load_pending &= ~EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN;
+
+ if (priv->children_list == NULL && priv->is_dir &&
+ !(priv->load.status & (EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN | EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN)))
+ {
+ _eio_model_efl_model_base_monitor_add(priv);
+
+ _load_set(priv, EFL_MODEL_LOAD_STATUS_LOADING_CHILDREN);
+ eio_file_direct_ls(priv->path, _eio_filter_children_load_cb,
+ _eio_main_children_load_cb, _eio_done_children_load_cb,
+ _eio_error_children_load_cb, priv);
+ }
+}
+
+/**
+ * Load
+ */
+static void
+_eio_model_efl_model_base_load(Eo *obj, Eio_Model_Data *priv)
+{
+ priv->load_pending |= EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN;
+ _eio_model_efl_model_base_properties_load(obj, priv);
+}
+
+/**
+ * Load status get
+ */
+static Efl_Model_Load_Status
+_eio_model_efl_model_base_load_status_get(Eo *obj EINA_UNUSED, Eio_Model_Data *priv)
+{
+ return priv->load.status;
+}
+
+/**
+ * Unload
+ */
+static void
+_eio_model_efl_model_base_unload(Eo *obj EINA_UNUSED, Eio_Model_Data *priv)
+{
+ if (!(priv->load.status & EFL_MODEL_LOAD_STATUS_UNLOADED))
+ {
+ Eo *child;
+ EINA_LIST_FREE(priv->children_list, child)
+ {
+ eo_unref(child);
+ }
+
+ _load_set(priv, EFL_MODEL_LOAD_STATUS_UNLOADED);
+ }
+}
+
+static void
+_eio_model_children_filter_set(Eo *obj EINA_UNUSED, Eio_Model_Data *priv, Eio_Filter_Direct_Cb filter_cb, void *data)
+{
+ priv->filter_cb = filter_cb;
+ priv->filter_userdata = data;
+}
+
+/**
+ * Child Add
+ */
+static Eo *
+_eio_model_efl_model_base_child_add(Eo *obj EINA_UNUSED, Eio_Model_Data *priv EINA_UNUSED)
+{
+ return eo_add(EIO_MODEL_CLASS, obj);
+}
+
+static void
+_eio_model_efl_model_base_child_del_stat(void* data, Eio_File* handler EINA_UNUSED, const Eina_Stat* stat)
+{
+ Eo* child = data;
+ Eio_Model_Data *child_priv = eo_data_scope_get(child, MY_CLASS);
+
+ if(eio_file_is_dir(stat))
+ eio_dir_unlink(child_priv->path,
+ _eio_filter_child_del_cb,
+ _eio_progress_child_del_cb,
+ _eio_done_unlink_cb,
+ _eio_error_unlink_cb,
+ child_priv);
+ else
+ eio_file_unlink(child_priv->path, _eio_done_unlink_cb, _eio_error_unlink_cb, child_priv);
+}
+
+/**
+ * Child Remove
+ */
+static Efl_Model_Load_Status
+_eio_model_efl_model_base_child_del(Eo *obj EINA_UNUSED, Eio_Model_Data *priv, Eo *child)
+{
+ Eio_Model_Data *child_priv;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(child, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ if (priv->children_list != NULL)
+ {
+ priv->children_list = eina_list_remove(priv->children_list, child);
+ }
+
+ child_priv = eo_data_scope_get(child, MY_CLASS);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(child_priv, EFL_MODEL_LOAD_STATUS_ERROR);
+
+ eio_file_direct_stat(child_priv->path,
+ &_eio_model_efl_model_base_child_del_stat,
+ &_eio_error_unlink_cb,
+ child);
+ eo_ref(child);
+ return priv->load.status;
+}
+
+/**
+ * Children Slice Get
+ */
+static Efl_Model_Load_Status
+_eio_model_efl_model_base_children_slice_get(Eo *obj EINA_UNUSED, Eio_Model_Data *priv,
+ unsigned start, unsigned count, Eina_Accessor **children_accessor)
+{
+ Eo *child;
+ Eina_List *l, *ln, *lr = NULL;
+
+ /**
+ * children must be already loaded otherwise we do nothing
+ * and parameter is set to NULL.
+ */
+
+ if (!(priv->load.status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN))
+ {
+ /**
+ * Status should be in either unloaded state or unitialized
+ * so we simply return without much alarm.
+ */
+ *children_accessor = NULL;
+ return priv->load.status;
+ }
+
+ if ((start == 0) && (count == 0)) /* this is full data */
+ {
+ /*
+ * children_accessor will be set to NULL by
+ * eina_list_accessor_new if the later fails.
+ */
+ *children_accessor = eina_list_accessor_new(priv->children_list);
+ }
+ else /* this is only slice */
+ {
+ ln = eina_list_nth_list(priv->children_list, (start-1));
+ if (!ln)
+ {
+ *children_accessor = NULL;
+ ERR("children not found !");
+ return priv->load.status;
+ }
+
+ EINA_LIST_FOREACH(ln, l, child)
+ {
+ eo_ref(child);
+ lr = eina_list_append(lr, child);
+ if (eina_list_count(lr) == count)
+ break;
+ }
+ // This may leak the children Eina_List.
+ *children_accessor = eina_list_accessor_new(lr);
+ }
+
+ return priv->load.status;
+}
+
+/**
+ * Class definitions
+ */
+static void
+_eio_model_eo_base_constructor(Eo *obj, Eio_Model_Data *priv)
+{
+ eo_do_super(obj, MY_CLASS, eo_constructor());
+ unsigned int i;
+ priv->obj = obj;
+
+ priv->properties_name = eina_array_new(EIO_MODEL_PROP_LAST);
+ EINA_SAFETY_ON_NULL_RETURN(priv->properties_name);
+ for (i = 0; i < EIO_MODEL_PROP_LAST; ++i)
+ eina_array_push(priv->properties_name, _eio_model_prop_names[i]);
+
+ priv->properties_value[EIO_MODEL_PROP_FILENAME] = eina_value_new(EINA_VALUE_TYPE_STRING);
+ priv->properties_value[EIO_MODEL_PROP_PATH] = eina_value_new(EINA_VALUE_TYPE_STRING);
+ priv->properties_value[EIO_MODEL_PROP_MTIME] = eina_value_new(EINA_VALUE_TYPE_TIMEVAL);
+ priv->properties_value[EIO_MODEL_PROP_IS_DIR] = eina_value_new(EINA_VALUE_TYPE_INT);
+ priv->properties_value[EIO_MODEL_PROP_IS_LNK] = eina_value_new(EINA_VALUE_TYPE_INT);
+ priv->properties_value[EIO_MODEL_PROP_SIZE] = eina_value_new(EINA_VALUE_TYPE_INT64);
+
+ priv->load.status = EFL_MODEL_LOAD_STATUS_UNLOADED;
+ priv->monitor = NULL;
+}
+
+static void
+_eio_model_path_set(Eo *obj EINA_UNUSED, Eio_Model_Data *priv, const char *path)
+{
+ priv->path = strdup(path);
+
+ eina_value_set(priv->properties_value[EIO_MODEL_PROP_PATH], priv->path);
+ eina_value_set(priv->properties_value[EIO_MODEL_PROP_FILENAME], basename(priv->path));
+
+ priv->monitor = NULL;
+ _eio_monitors_list_load(priv);
+}
+
+static void
+_eio_model_eo_base_destructor(Eo *obj , Eio_Model_Data *priv)
+{
+ Eo *child;
+ unsigned int i;
+
+ if (priv->monitor)
+ eio_monitor_del(priv->monitor);
+
+ if (priv->properties_name)
+ eina_array_free(priv->properties_name);
+
+ for (i = 0; i < EIO_MODEL_PROP_LAST; ++i)
+ {
+ eina_value_free(priv->properties_value[i]);
+ }
+
+ EINA_LIST_FREE(priv->children_list, child)
+ eo_unref(child);
+
+ free(priv->path);
+ eo_do_super(obj, MY_CLASS, eo_destructor());
+}
+
+#include "eio_model.eo.c"
diff --git a/src/lib/eio/eio_model.eo b/src/lib/eio/eio_model.eo
new file mode 100644
index 0000000000..67890fa1a2
--- /dev/null
+++ b/src/lib/eio/eio_model.eo
@@ -0,0 +1,49 @@
+class Eio.Model (Eo.Base, Efl.Model.Base)
+{
+ legacy_prefix: null;
+ methods {
+ children_filter_set {
+ /*@ Set children filter callback.
+ This function sets, along with user's private data userdata,
+ the Eio's Eio_Filter_Direct_Cb which is a mid-step
+ before receiving the real data. Once in filter
+ callback we can decide, by returning either EINA_FALSE, to abort
+ the notification or EINA_TRUE to keep it.
+ @see Eio.h
+ @see emodel_children_slice_fetch
+ @def emodel_children_filter_set
+ @since 1.11
+ @in filter_cb
+ @in userdata */
+ params {
+ Eio_Filter_Direct_Cb filter_cb; /*@ Filter callback */
+ void *userdata; /*@ User's private data */
+ }
+ }
+ path_set {
+ /*@ Custom Eio_Model constructor.
+ @def eio_model_constructor
+ @since 1.11
+ @in path */
+ params {
+ @in const(char)* path; /*@ Root path provided by caller */
+ }
+ }
+ }
+ implements {
+ Eo.Base.constructor;
+ Eo.Base.destructor;
+ Efl.Model.Base.properties.get;
+ Efl.Model.Base.properties_load;
+ Efl.Model.Base.property.set;
+ Efl.Model.Base.property.get;
+ Efl.Model.Base.load;
+ Efl.Model.Base.load_status.get;
+ Efl.Model.Base.unload;
+ Efl.Model.Base.child_add;
+ Efl.Model.Base.child_del;
+ Efl.Model.Base.children_slice.get;
+ Efl.Model.Base.children_count.get;
+ Efl.Model.Base.children_load;
+ }
+}
diff --git a/src/lib/eio/eio_model.h b/src/lib/eio/eio_model.h
new file mode 100644
index 0000000000..1c46d77c45
--- /dev/null
+++ b/src/lib/eio/eio_model.h
@@ -0,0 +1,45 @@
+/**
+ * @page emodel_eio_main Emodel_Eio
+ *
+ * @date 2014 (created)
+ *
+ * @brief Emodel_Eio Library Public API Calls
+ *
+ * @section toc Table of Contents
+ *
+ * @li @ref emodel_eio_main_intro
+ *
+ * @section eo_main_intro Introduction
+ *
+ * This module targets file operations using Emodel.
+
+ *
+ * Recommended reading:
+ *
+ * @li @ref Emodel
+ * @li @ref Eo
+ * @li @ref Eina
+ *
+ * @defgroup Emodel_Eio EIO implementation wrapper for Emodel
+ *
+ * @addtogroup Emodel_Eio
+ * @{
+ */
+
+#ifndef _EMODEL_EIO_H
+#define _EMODEL_EIO_H
+
+#include <Eo.h>
+#include <Efl.h>
+#include <Eio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <eio_model.eo.h>
+
+#ifdef __cplusplus
+}
+#endif
+#endif //_EMODEL_EIO_H
diff --git a/src/lib/eio/eio_model_private.h b/src/lib/eio/eio_model_private.h
new file mode 100644
index 0000000000..0aed0d6a4a
--- /dev/null
+++ b/src/lib/eio/eio_model_private.h
@@ -0,0 +1,57 @@
+#ifndef _EIO_MODEL_PRIVATE_H
+#define _EIO_MODEL_PRIVATE_H
+
+#define PROP_LIST_SIZE 7
+
+typedef struct _Eio_Model_Data Eio_Model_Data;
+typedef struct _Eio_Model_Monitor_Data Eio_Model_Monitor_Data;
+
+struct _Eio_Model_Monitor_Data
+{
+ Ecore_Event_Handler *ecore_child_add_handler[3];
+ Ecore_Event_Handler *ecore_child_del_handler[3];
+ int mon_event_child_add[3]; /**< plus EIO_MONITOR_ERROR */
+ int mon_event_child_del[3]; /**< plus EIO_MONITOR_ERROR */
+};
+
+enum {
+ EIO_MODEL_PROP_FILENAME = 0,
+ EIO_MODEL_PROP_PATH,
+ EIO_MODEL_PROP_MTIME,
+ EIO_MODEL_PROP_IS_DIR,
+ EIO_MODEL_PROP_IS_LNK,
+ EIO_MODEL_PROP_SIZE,
+ EIO_MODEL_PROP_LAST
+};
+
+static const char* _eio_model_prop_names[] =
+{
+ [EIO_MODEL_PROP_FILENAME] = "filename",
+ [EIO_MODEL_PROP_PATH] = "path",
+ [EIO_MODEL_PROP_MTIME] = "mtime",
+ [EIO_MODEL_PROP_IS_DIR] = "is_dir",
+ [EIO_MODEL_PROP_IS_LNK] = "is_lnk",
+ [EIO_MODEL_PROP_SIZE] = "size"
+};
+
+struct _Eio_Model_Data
+{
+ Eo *obj;
+ char *path;
+ Eina_Array *properties_name;
+ Eina_Value *properties_value[EIO_MODEL_PROP_LAST];
+ Efl_Model_Load load;
+ int load_pending;
+ Eina_List *children_list;
+ /**< EIO data */
+ Eio_File *file;
+ Eina_Bool is_dir;
+ Eio_Monitor *monitor;
+ Eio_Model_Monitor_Data mon;
+ int cb_count_child_add; /**< monitor reference counter for child add event */
+ int cb_count_child_del; /**< monitor reference counter for child del event*/
+ Eio_Filter_Direct_Cb filter_cb;
+ void *filter_userdata;
+};
+
+#endif
diff --git a/src/tests/eio/eio_model_test_file.c b/src/tests/eio/eio_model_test_file.c
new file mode 100644
index 0000000000..af5269d033
--- /dev/null
+++ b/src/tests/eio/eio_model_test_file.c
@@ -0,0 +1,232 @@
+//Compile with:
+// gcc -o emodel_test_file emodel_test_file.c `pkg-config --cflags --libs emodel`
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Eo.h>
+#include <Eio.h>
+#include <Ecore.h>
+#include <Efl.h>
+#include <eio_model.h>
+#include <stdio.h>
+
+#include <check.h>
+
+#define EFL_MODEL_TEST_FILENAME_PATH "/tmp"
+#define EFL_MODEL_MAX_TEST_CHILDS 16
+
+/**
+ * The following test works however
+ * it is going to rename (move) the original directory to
+ * new one so '/tmp' as root dir doesn't work , you'll need to use
+ * '/tmp/some_other_dir' as root instead.
+ */
+//#define _RUN_LOCAL_TEST
+
+struct reqs_t {
+ /* property change */
+ int changed_is_dir;
+ int changed_is_lnk;
+ int changed_size;
+ int changed_mtime;
+
+ /* properties list */
+ int proplist_filename;
+ int proplist_path;
+ int proplist_mtime;
+ int proplist_is_dir;
+ int proplist_is_lnk;
+ int proplist_size;
+
+ /* misc tests for data or propeties */
+ int properties;
+ int children;
+ int child_add;
+ int child_del;
+};
+
+static struct reqs_t reqs;
+static Ecore_Event_Handler *handler;
+
+static Eina_Bool
+ exit_func(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev)
+ {
+ Ecore_Event_Signal_Exit *e;
+
+ e = (Ecore_Event_Signal_Exit *)ev;
+ if (e->interrupt) fprintf(stdout, "Exit: interrupt\n");
+ else if (e->quit) fprintf(stdout, "Exit: quit\n");
+ else if (e->terminate) fprintf(stdout, "Exit: terminate\n");
+ ecore_main_loop_quit();
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+static Eina_Bool
+_load_status_cb(void *data EINA_UNUSED, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
+{
+ Efl_Model_Load *st = event_info;
+ printf("Load CHANGE\n");
+
+ if (st->status & EFL_MODEL_LOAD_STATUS_LOADED_CHILDREN)
+ printf("Children is Loaded\n");
+
+ if (st->status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES)
+ printf("Properties is Loaded\n");
+
+ if ((st->status & EFL_MODEL_LOAD_STATUS_LOADED) == EFL_MODEL_LOAD_STATUS_LOADED)
+ {
+ Eina_Accessor *accessor;
+ const Eina_Value *value_prop;
+ Efl_Model_Load_Status status;
+ unsigned int total;
+ char *str;
+
+ printf("Model is Loaded\n");
+ eo_do(obj, status = efl_model_property_get("filename", &value_prop));
+ str = eina_value_to_string(value_prop);
+ printf("efl_model_loaded filename %s, status=%d\n", str, status);
+ free(str);
+
+ eo_do(obj, status = efl_model_property_get("size", &value_prop));
+ str = eina_value_to_string(value_prop);
+ printf("efl_model_loaded size %s, status=%d\n", str, status);
+ free(str);
+
+ eo_do(obj, status = efl_model_property_get("mtime", &value_prop));
+ str = eina_value_to_string(value_prop);
+ printf("efl_model_loaded mtime %s, status=%d\n", str, status);
+ free(str);
+
+ eo_do(obj, efl_model_children_count_get(&total));
+ printf("efl_model_test count %d\n", (int)total);
+
+ /**< get full list */
+ eo_do(obj, status = efl_model_children_slice_get(0 ,0 ,(Eina_Accessor **)&accessor));
+ eina_accessor_free(accessor);
+ eo_do(obj, status = efl_model_children_slice_get(5 ,5 ,(Eina_Accessor **)&accessor));
+ eina_accessor_free(accessor);
+ ecore_main_loop_quit();
+ }
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_properties_change_cb(void *data EINA_UNUSED, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
+{
+ const Efl_Model_Property_Event *evt = (Efl_Model_Property_Event *)event_info;
+ const char *prop;
+ Eina_Array_Iterator it;
+ unsigned int i;
+
+ EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it)
+ {
+ if (!strcmp(prop, "is_dir"))
+ reqs.changed_is_dir = 1;
+ else if (!strcmp(prop, "is_lnk"))
+ reqs.changed_is_lnk = 1;
+ else if (!strcmp(prop, "size"))
+ reqs.changed_size = 1;
+ else if (!strcmp(prop, "mtime"))
+ reqs.changed_mtime = 1;
+ }
+
+ reqs.properties = 1;
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_children_count_cb(void *data EINA_UNUSED, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
+{
+ unsigned int *len = (unsigned int *)event_info;
+ unsigned int total;
+
+ fprintf(stdout, "Children count number=%d\n", *len);
+ reqs.children = *len;
+
+ eo_do(obj, efl_model_children_count_get(&total));
+ fprintf(stdout, "New total children count number=%d\n", *len);
+
+ return EINA_TRUE;
+}
+
+START_TEST(eio_model_test_test_file)
+{
+ Eo *filemodel = NULL;
+ const Eina_Value *value_prop;
+ Efl_Model_Load_Status status;
+#ifdef _RUN_LOCAL_TEST
+ Eina_Value nameset_value;
+#endif
+ Eina_Array *properties_list;
+ Eina_Array_Iterator iterator;
+ char *str;
+ unsigned int i;
+
+ memset(&reqs, -1, sizeof(struct reqs_t));
+
+ fail_if(!eina_init(), "ERROR: Cannot init Eina!\n");
+ fail_if(!ecore_init(), "ERROR: Cannot init Ecore!\n");
+ fail_if(!eio_init(), "ERROR: Cannot init EIO!\n");
+
+ filemodel = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(EFL_MODEL_TEST_FILENAME_PATH));
+ fail_if(!filemodel, "ERROR: Cannot init model!\n");
+
+ eo_do(filemodel, eo_event_callback_add(EFL_MODEL_BASE_EVENT_LOAD_STATUS, _load_status_cb, NULL));
+ eo_do(filemodel, eo_event_callback_add(EFL_MODEL_BASE_EVENT_PROPERTIES_CHANGED, _properties_change_cb, NULL));
+ eo_do(filemodel, eo_event_callback_add(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, _children_count_cb, NULL));
+
+ eo_do(filemodel, efl_model_load());
+
+ handler = ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, exit_func, NULL);
+
+ eo_do(filemodel, status = efl_model_property_get("filename", &value_prop));
+ str = eina_value_to_string(value_prop);
+ printf("efl_model_test filename %s, load status %d\n", str, status);
+
+ free(str);
+
+ i = 0;
+ eo_do(filemodel, efl_model_properties_get(&properties_list));
+ EINA_ARRAY_ITER_NEXT(properties_list, i, str, iterator)
+ {
+ fprintf(stdout, "Returned property list %d: %s\n", i, str);
+ if(!strcmp(str, "filename"))
+ reqs.proplist_filename = 1;
+ else if(!strcmp(str, "path"))
+ reqs.proplist_path = 1;
+ else if(!strcmp(str, "mtime"))
+ reqs.proplist_mtime = 1;
+ else if(!strcmp(str, "is_dir"))
+ reqs.proplist_is_dir = 1;
+ else if(!strcmp(str, "is_lnk"))
+ reqs.proplist_is_lnk = 1;
+ else if(!strcmp(str, "size"))
+ reqs.proplist_size = 1;
+ }
+
+ ecore_main_loop_begin();
+
+#ifdef _RUN_LOCAL_TEST
+ eina_value_setup(&nameset_value, EINA_VALUE_TYPE_STRING);
+ eina_value_setup(&value_prop, EINA_VALUE_TYPE_STRING);
+ eina_value_set(&nameset_value, "/tmp/efl_model_test");
+ eo_do(filemodel, efl_model_property_set("path", &nameset_value));
+ eina_value_flush(&nameset_value);
+ eo_do(filemodel, status = efl_model_property_get("path", &value_prop));
+#endif
+
+ sleep(1); /**< EIO is asynchrounous so I must give some time for deletions to execute */
+ eo_unref(filemodel);
+ ecore_shutdown();
+ eina_shutdown();
+ eio_shutdown();
+}
+END_TEST
+
+void
+eio_model_test_file(TCase *tc)
+{
+ tcase_add_test(tc, eio_model_test_test_file);
+}
+
diff --git a/src/tests/eio/eio_model_test_monitor_add.c b/src/tests/eio/eio_model_test_monitor_add.c
new file mode 100644
index 0000000000..af95ae8f75
--- /dev/null
+++ b/src/tests/eio/eio_model_test_monitor_add.c
@@ -0,0 +1,125 @@
+//Compile with:
+// gcc -o emodel_test_file emodel_test_file.c `pkg-config --cflags --libs emodel`
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Eo.h>
+#include <Eio.h>
+#include <Ecore.h>
+#include <Efl.h>
+#include <eio_model.h>
+#include <stdio.h>
+
+#include <check.h>
+
+#define EFL_MODEL_TEST_FILENAME_PATH "/tmp"
+
+Eina_Bool children_added = EINA_FALSE;
+
+static Eina_Bool
+_load_monitor_status_cb(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
+{
+ Efl_Model_Load* st = event_info;
+ Eo* parent = data;
+ const Eina_Value* value_prop = NULL;
+ const char* str = NULL;
+
+ if (!(st->status & EFL_MODEL_LOAD_STATUS_LOADED_PROPERTIES))
+ return EINA_TRUE;
+
+ eo_do(obj, efl_model_property_get("filename", &value_prop));
+ fail_if(!value_prop, "ERROR: Cannot get property!\n");
+
+ str = eina_value_to_string(value_prop);
+ fail_if(!str, "ERROR: Cannot convert value to string!\n");
+ fprintf(stderr, "new children filename %s\n", str);
+ if(strcmp(str, "test_file_monitor_add") == 0)
+ {
+ fprintf(stderr, "is child that we want\n");
+ eo_do(obj, eo_event_callback_del(EFL_MODEL_BASE_EVENT_LOAD_STATUS, _load_monitor_status_cb, data));
+ children_added = EINA_TRUE;
+ eo_do(parent, efl_model_child_del(obj));
+ ecore_main_loop_quit();
+ }
+
+ return EINA_FALSE;
+}
+
+static Eina_Bool
+_children_added_cb(void *data EINA_UNUSED, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
+{
+ Efl_Model_Children_Event* evt = event_info;
+ if (evt == NULL)
+ return EINA_TRUE;
+
+ eo_do(evt->child, eo_event_callback_add(EFL_MODEL_BASE_EVENT_LOAD_STATUS, _load_monitor_status_cb, obj));
+ eo_do(evt->child, efl_model_load());
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_children_count_cb(void *data EINA_UNUSED, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
+{
+ unsigned int *len = event_info;
+ Eina_Accessor *accessor;
+ Efl_Model_Load_Status status;
+ Eo *child;
+ unsigned int i = 0;
+
+ fprintf(stderr, "Children count number=%d\n", *len);
+
+ /**< get full list */
+ eo_do(obj, status = efl_model_children_slice_get(0 ,0 ,(Eina_Accessor **)&accessor));
+ if(accessor != NULL)
+ {
+ EINA_ACCESSOR_FOREACH(accessor, i, child) {}
+ fprintf(stdout, "Got %d childs from Accessor. status=%d\n", i, status);
+ }
+
+ fclose(fopen(EFL_MODEL_TEST_FILENAME_PATH "/test_file_monitor_add", "w+"));
+
+ return EINA_TRUE;
+}
+
+START_TEST(eio_model_test_test_monitor_add)
+{
+ Eo *filemodel = NULL;
+
+ fprintf(stderr, "efl_model_test_test_monitor_add\n");
+
+ fail_if(!eina_init(), "ERROR: Cannot init Eina!\n");
+ fail_if(!ecore_init(), "ERROR: Cannot init Ecore!\n");
+ fail_if(!eio_init(), "ERROR: Cannot init EIO!\n");
+
+ filemodel = eo_add(EIO_MODEL_CLASS, NULL, eio_model_path_set(EFL_MODEL_TEST_FILENAME_PATH));
+ fail_if(!filemodel, "ERROR: Cannot init model!\n");
+
+ eo_do(filemodel, eo_event_callback_add(EFL_MODEL_BASE_EVENT_CHILD_ADDED, _children_added_cb, NULL));
+ eo_do(filemodel, eo_event_callback_add(EFL_MODEL_BASE_EVENT_CHILDREN_COUNT_CHANGED, _children_count_cb, NULL));
+
+ eo_do(filemodel, efl_model_load());
+
+ ecore_main_loop_begin();
+
+ sleep(1); /**< EIO is asynchrounous so I must give some time for deletions to execute */
+
+ ecore_main_loop_iterate(); /**< Give time to unlink file */
+
+ eo_unref(filemodel);
+
+ eio_shutdown();
+ ecore_shutdown();
+ eina_shutdown();
+
+ fail_if(!children_added);
+}
+END_TEST
+
+void
+eio_model_test_monitor_add(TCase *tc)
+{
+ tcase_add_test(tc, eio_model_test_test_monitor_add);
+}
+
diff --git a/src/tests/eio/eio_suite.c b/src/tests/eio/eio_suite.c
new file mode 100644
index 0000000000..ecc52247b3
--- /dev/null
+++ b/src/tests/eio/eio_suite.c
@@ -0,0 +1,109 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <Eio.h>
+
+#include "eio_suite.h"
+
+typedef struct _Eio_Test_Case Eio_Test_Case;
+
+struct _Eio_Test_Case
+{
+ const char *test_case;
+ void (*build)(TCase *tc);
+};
+
+static const Eio_Test_Case etc[] = {
+ {"Eio_Monitor", eio_test_monitor},
+ {"Eio Model", eio_model_test_file},
+ {"Eio Model Monitor", eio_model_test_monitor_add},
+ {NULL, NULL}
+};
+
+static void
+_list_tests(void)
+{
+ const Eio_Test_Case *itr;
+
+ itr = etc;
+ fputs("Available Test Cases:\n", stderr);
+ for (; itr->test_case; itr++)
+ fprintf(stderr, "\t%s\n", itr->test_case);
+}
+
+static Eina_Bool
+_use_test(int argc, const char **argv, const char *test_case)
+{
+ if (argc < 1)
+ return 1;
+
+ for (; argc > 0; argc--, argv++)
+ if (strcmp(test_case, *argv) == 0)
+ return 1;
+ return 0;
+}
+
+static Suite *
+eio_suite_build(int argc, const char **argv)
+{
+ TCase *tc;
+ Suite *s;
+ int i;
+
+ s = suite_create("Eio");
+
+ for (i = 0; etc[i].test_case; ++i)
+ {
+ if (!_use_test(argc, argv, etc[i].test_case)) continue;
+ tc = tcase_create(etc[i].test_case);
+
+ etc[i].build(tc);
+
+ suite_add_tcase(s, tc);
+ tcase_set_timeout(tc, 0);
+ }
+
+ return s;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ Suite *s;
+ SRunner *sr;
+ int i, failed_count;
+
+ for (i = 1; i < argc; i++)
+ if ((strcmp(argv[i], "-h") == 0) ||
+ (strcmp(argv[i], "--help") == 0))
+ {
+ fprintf(stderr, "Usage:\n\t%s [test_case1 .. [test_caseN]]\n",
+ argv[0]);
+ _list_tests();
+ return 0;
+ }
+ else if ((strcmp(argv[i], "-l") == 0) ||
+ (strcmp(argv[i], "--list") == 0))
+ {
+ _list_tests();
+ return 0;
+ }
+
+ putenv("EFL_RUN_IN_TREE=1");
+
+ s = eio_suite_build(argc - 1, (const char **)argv + 1);
+ sr = srunner_create(s);
+
+ srunner_set_xml(sr, TESTS_BUILD_DIR "/check-results.xml");
+
+ srunner_run_all(sr, CK_ENV);
+ failed_count = srunner_ntests_failed(sr);
+ srunner_free(sr);
+
+ return (failed_count == 0) ? 0 : 255;
+}
diff --git a/src/tests/eio/eio_suite.h b/src/tests/eio/eio_suite.h
new file mode 100644
index 0000000000..d59a2ab6c0
--- /dev/null
+++ b/src/tests/eio/eio_suite.h
@@ -0,0 +1,10 @@
+#ifndef _EIO_SUITE_H
+#define _EIO_SUITE_H
+
+#include <check.h>
+
+void eio_test_monitor(TCase *tc);
+void eio_model_test_file(TCase *tc);
+void eio_model_test_monitor_add(TCase *tc);
+
+#endif /* _EIO_SUITE_H */