emodel: Created Emodel and Eio_Model.

This commit is contained in:
Larry Jr 2015-04-05 15:19:45 +02:00 committed by Cedric BAIL
parent c8a9769665
commit 05eecf5c8f
25 changed files with 2217 additions and 7 deletions

View File

@ -143,6 +143,7 @@ pc/ecore-evas.pc \
pc/ecore-avahi.pc \
pc/ector.pc \
pc/embryo.pc \
pc/emodel.pc \
pc/eio.pc \
pc/eldbus.pc \
pc/efreet.pc \
@ -162,7 +163,9 @@ 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/emodel-cxx.pc \
pc/eio-cxx.pc
endif
if HAVE_ELUA

View File

@ -3944,6 +3944,14 @@ EFL_EVAL_PKGS([ECORE_EVAS])
EFL_LIB_END([Ecore_Evas])
#### End of Ecore_Evas
#### Emodel
EFL_LIB_START([Emodel])
EFL_ADD_LIBS([EMODEL], [])
EFL_INTERNAL_DEPEND_PKG([EMODEL], [eo])
EFL_INTERNAL_DEPEND_PKG([EMODEL], [eina])
EFL_LIB_END([Emodel])
#### End of Emodel
#### Eio
EFL_LIB_START([Eio])
@ -3957,6 +3965,7 @@ EFL_LIB_START([Eio])
EFL_PLATFORM_DEPEND([EIO], [evil])
### Checks for libraries
EFL_INTERNAL_DEPEND_PKG([EIO], [emodel])
EFL_INTERNAL_DEPEND_PKG([EIO], [ecore])
EFL_INTERNAL_DEPEND_PKG([EIO], [eet])
EFL_INTERNAL_DEPEND_PKG([EIO], [eo])
@ -4534,6 +4543,8 @@ pc/eolian.pc
pc/eolian-cxx.pc
pc/efl.pc
pc/efl-cxx.pc
pc/emodel.pc
pc/emodel-cxx.pc
pc/evas-fb.pc
pc/evas-opengl-x11.pc
pc/evas-opengl-sdl.pc
@ -4573,6 +4584,7 @@ pc/ecore-avahi.pc
pc/ector.pc
pc/embryo.pc
pc/eio.pc
pc/eio-cxx.pc
pc/eldbus.pc
pc/efreet.pc
pc/efreet-mime.pc

3
pc/.gitignore vendored
View File

@ -28,9 +28,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

12
pc/eio-cxx.pc.in Normal file
View File

@ -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@

12
pc/emodel-cxx.pc.in Normal file
View File

@ -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@

12
pc/emodel.pc.in Normal file
View File

@ -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@

View File

@ -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')

View File

@ -10,7 +10,9 @@ 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/emodel \
-I$(srcdir)/lib/eio
DIST_SUBDIRS =
SUBDIRS =
@ -65,6 +67,7 @@ include Makefile_Eeze.am
include Makefile_EPhysics.am
include Makefile_Edje.am
include Makefile_Emotion.am
include Makefile_Emodel.am
include Makefile_Ethumb.am
include Makefile_Ethumb_Client.am
@ -77,6 +80,8 @@ include Makefile_Eo_Cxx.am
include Makefile_Efl_Cxx.am
include Makefile_Edje_Cxx.am
include Makefile_Evas_Cxx.am
include Makefile_Emodel_Cxx.am
include Makefile_Eio_Cxx.am
include Makefile_Elua.am
include Makefile_Elocation.am

View File

@ -19,7 +19,7 @@ generated_efl_cxx_bindings = \
lib/efl/interfaces/efl_gfx_gradient_radial.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

View File

@ -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
@ -30,9 +46,9 @@ endif
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@ @EMODEL_CFLAGS@
lib_eio_libeio_la_LIBADD = @EIO_LIBS@ @EMODEL_LIBS@
lib_eio_libeio_la_DEPENDENCIES = @EIO_INTERNAL_LIBS@ @EMODEL_INTERNAL_LIBS@
lib_eio_libeio_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
if HAVE_NOTIFY_COCOA
lib_eio_libeio_la_LDFLAGS += -framework CoreServices

22
src/Makefile_Eio_Cxx.am Normal file
View File

@ -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

78
src/Makefile_Emodel.am Normal file
View File

@ -0,0 +1,78 @@
### Library
EMODEL_EOS = lib/emodel/emodel.eo
EMODEL_EOS_H = $(EMODEL_EOS:%.eo=%.eo.h)
EMODEL_EOS_C = $(EMODEL_EOS:%.eo=%.eo.c)
BUILT_SOURCES += $(EMODEL_EOS_C) $(EMODEL_EOS_H)
dist_installed_emodelmainheaders_DATA = \
lib/emodel/Emodel.h \
lib/emodel/Emodel_Common.h
nodist_installed_emodelmainheaders_DATA = $(EMODEL_EOS_H)
emodeleolianfilesdir = $(datadir)/eolian/include/emodel-@VMAJ@
emodeleolianfiles_DATA = $(EMODEL_EOS)
lib_LTLIBRARIES += lib/emodel/libemodel.la
EXTRA_DIST += $(emodeleolianfiles_DATA)
installed_emodelmainheadersdir = $(includedir)/emodel-@VMAJ@
lib_emodel_libemodel_la_SOURCES = \
lib/emodel/emodel.c
lib_emodel_libemodel_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-I$(top_builddir)/src/lib/emodel \
-I$(top_srcdir)/src/lib/emodel \
-I$(top_builddir)/src/lib/eo \
-I$(top_srcdir)/src/lib/eo \
-I$(top_builddir)/src/lib/ecore \
-I$(top_srcdir)/src/lib/ecore \
-I$(top_builddir)/src/lib/eina \
-I$(top_srcdir)/src/lib/eina \
-DPACKAGE_BIN_DIR=\"$(bindir)\" \
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
-DPACKAGE_DATA_DIR=\"$(datadir)/edje\" \
-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)\" \
-DPACKAGE_SRC_DIR=\"`pwd`/$(top_srcdir)\" \
@EMODEL_CFLAGS@
lib_emodel_libemodel_la_LIBADD = @EMODEL_LIBS@
lib_emodel_libemodel_la_DEPENDENCIES = @EMODEL_INTERNAL_LIBS@ @EINA_INTERNAL_LIBS@ @EO_INTERNAL_LIBS@ @ECORE_INTERNAL_LIBS@
if EFL_ENABLE_TESTS
EXTRA_DIST += $(emodeleolianfiles_DATA)
check_PROGRAMS += tests/emodel/emodel_suite
TESTS += tests/emodel/emodel_suite
tests_emodel_emodel_suite_SOURCES = \
tests/emodel/emodel_suite.c \
tests/emodel/emodel_test_file.c \
tests/emodel/emodel_test_monitor_add.c
tests_emodel_emodel_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-I$(top_builddir)/src/lib/emodel \
-I$(top_srcdir)/src/lib/emodel \
-I$(top_builddir)/src/lib/ecore \
-I$(top_srcdir)/src/lib/ecore \
-I$(top_builddir)/src/lib/eio \
-I$(top_srcdir)/src/lib/eio \
-I$(top_builddir)/src/lib/eina \
-I$(top_srcdir)/src/lib/eina \
-DTESTS_WD=\"`pwd`\" \
-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/emodel\" \
-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)/src/tests/emodel\" \
-DTESTS_BUILD_DIR=PACKAGE_BUILD_DIR \
@CHECK_CFLAGS@ \
@EINA_CFLAGS@ \
@EMODEL_CFLAGS@ \
@EO_CFLAGS@ \
@EIO_CFLAGS@
tests_emodel_emodel_suite_LDADD = @CHECK_LIBS@ @USE_EMODEL_LIBS@ @USE_EINA_LIBS@ @USE_EO_LIBS@ @USE_EIO_LIBS@ @USE_ECORE_LIBS@
tests_emodel_emodel_suite_DEPENDENCIES = @USE_EMODEL_INTERNAL_LIBS@ @USE_EINA_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@ @USE_EIO_INTERNAL_LIBS@ @USE_ECORE_INTERNAL_LIBS@
endif

View File

@ -0,0 +1,22 @@
if HAVE_CXX11
### Generated headers
generated_emodel_cxx_bindings = lib/emodel/emodel.eo.hh
lib/emodel/Emodel.hh: $(generated_emodel_cxx_bindings)
@echo @ECHO_E@ "#ifndef EFL_CXX_EMODEL_HH\n#define EFL_CXX_EMODEL_HH\n" > $(top_builddir)/src/lib/emodel/Emodel.hh
@echo @ECHO_E@ "#ifdef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/emodel/Emodel.hh
@for i in $(generated_emodel_cxx_bindings); do echo "#include <$$(basename $$i)>" >> $(top_builddir)/src/lib/emodel/Emodel.hh; done
@echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/emodel/Emodel.hh
generated_emodel_cxx_all = \
$(generated_emodel_cxx_bindings) \
lib/emodel/Emodel.hh
CLEANFILES += $(generated_emodel_cxx_all)
installed_emodelcxxmainheadersdir = $(includedir)/emodel-cxx-@VMAJ@/
nodist_installed_emodelcxxmainheaders_DATA = $(generated_emodel_cxx_all)
endif

View File

@ -22,6 +22,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 \
@ -32,6 +33,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 \

774
src/lib/eio/eio_model.c Normal file
View File

@ -0,0 +1,774 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Emodel.h>
#include <Eina.h>
#include <eio_model.h>
#include <Eio.h>
#include <Ecore.h>
#include <Eo.h>
#include "eio_model_private.h"
#define MY_CLASS EIO_MODEL_CLASS
#define MY_CLASS_NAME "Eio_Model"
static Eina_Value_Struct_Desc *EIO_MODEL_PROPERTIES_DESC = NULL;
static void _eio_prop_set_error_cb(void *, Eio_File *, int);
static void _eio_model_emodel_properties_load(Eo *, Eio_Model_Data *);
static void _eio_model_emodel_children_load(Eo *, Eio_Model_Data *);
static void
_load_set(Eio_Model_Data *priv, Emodel_Load load)
{
if ((priv->load.status & (EMODEL_LOAD_STATUS_LOADED | EMODEL_LOAD_STATUS_LOADING)) &&
(load.status & (EMODEL_LOAD_STATUS_LOADED | EMODEL_LOAD_STATUS_LOADING)))
{
load.status = priv->load.status | load.status;
switch (load.status)
{
case EMODEL_LOAD_STATUS_LOADED_PROPERTIES:
load.status &= ~EMODEL_LOAD_STATUS_LOADING_PROPERTIES;
break;
case EMODEL_LOAD_STATUS_LOADING_PROPERTIES:
load.status &= ~EMODEL_LOAD_STATUS_LOADED_PROPERTIES;
break;
case EMODEL_LOAD_STATUS_LOADED_CHILDREN:
load.status &= ~EMODEL_LOAD_STATUS_LOADING_CHILDREN;
break;
case EMODEL_LOAD_STATUS_LOADING_CHILDREN:
load.status &= ~EMODEL_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(EMODEL_EVENT_LOAD_STATUS, &load));
}
}
static void
_stat_pro_set(Eio_Model_Data *priv, int prop_id, const Eina_Value *value, Emodel_Property_Event *evt)
{
Eina_Value old_value;
int changed;
Emodel_Property_Pair *pair = NULL;
const char *prop = EIO_MODEL_PROPERTIES_DESC->members[prop_id].name;
eina_value_struct_value_get(priv->properties, prop, &old_value);
changed = eina_value_compare(&old_value, value);
if(changed) eina_value_struct_value_set(priv->properties, prop, value);
eina_value_flush(&old_value);
if(!changed) return;
pair = calloc(1, sizeof(Emodel_Property_Pair));
EINA_SAFETY_ON_NULL_RETURN(pair);
if(!eina_value_copy((Eina_Value*)value, &pair->value))
{
free(pair);
return;
}
pair->property = eina_stringshare_add(prop);
evt->changed_properties = eina_list_append(evt->changed_properties, pair);
}
/**
* Callbacks
* Property
*/
static void
_eio_stat_done_cb(void *data, Eio_File *handler EINA_UNUSED, const Eina_Stat *stat)
{
Emodel_Property_Event evt;
Eina_Value value;
Eio_Model_Data *priv = data;
Emodel_Load load;
EINA_SAFETY_ON_FALSE_RETURN(eo_ref_get(priv->obj));
priv->stat = stat;
memset(&evt, 0, sizeof(Emodel_Property_Event));
// Setup for Eina_Bool
eina_value_setup(&value, EINA_VALUE_TYPE_INT);
eina_value_set(&value, eio_file_is_dir(stat));
_stat_pro_set(priv, EIO_MODEL_PROP_IS_DIR, (const Eina_Value*)&value, &evt);
eina_value_flush(&value);
// Setup for Eina_Bool
eina_value_setup(&value, EINA_VALUE_TYPE_INT);
eina_value_set(&value, eio_file_is_lnk(stat));
_stat_pro_set(priv, EIO_MODEL_PROP_IS_LNK, (const Eina_Value*)&value, &evt);
eina_value_flush(&value);
// Setup for double
eina_value_setup(&value, EINA_VALUE_TYPE_TIMEVAL);
eina_value_set(&value, eio_file_mtime(stat));
_stat_pro_set(priv, EIO_MODEL_PROP_MTIME, (const Eina_Value*)&value, &evt);
eina_value_flush(&value);
// Setup for long long
eina_value_setup(&value, EINA_VALUE_TYPE_INT64);
eina_value_set(&value, eio_file_size(stat));
_stat_pro_set(priv, EIO_MODEL_PROP_SIZE, (const Eina_Value*)&value, &evt);
eina_value_flush(&value);
if (evt.changed_properties != NULL)
{
Emodel_Property_Pair *pair;
eo_do(priv->obj, eo_event_callback_call(EMODEL_EVENT_PROPERTIES_CHANGED, &evt));
EINA_LIST_FREE(evt.changed_properties, pair)
{
eina_stringshare_del(pair->property);
eina_value_flush(&pair->value);
free(pair);
}
}
load.status = EMODEL_LOAD_STATUS_LOADED_PROPERTIES;
_load_set(priv, load);
if (priv->load_pending & EMODEL_LOAD_STATUS_LOADED_CHILDREN)
_eio_model_emodel_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)
{
Emodel_Property_Event evt;
Emodel_Property_Pair pair_path, pair_filename;
Eio_Model_Data *priv = data;
Eina_Value_Struct_Desc *desc = EIO_MODEL_PROPERTIES_DESC;
EINA_SAFETY_ON_FALSE_RETURN(eo_ref_get(priv->obj));
memset(&evt, 0, sizeof(Emodel_Property_Event));
/**
* When mv is executed we update our values and
* notify both path and filename properties listeners.
*/
pair_path.property = eina_stringshare_add(desc->members[EIO_MODEL_PROP_PATH].name);
eina_value_struct_set(priv->properties, pair_path.property, priv->path);
eina_value_struct_value_get(priv->properties, pair_path.property, &pair_path.value);
evt.changed_properties = eina_list_append(evt.changed_properties, &pair_path);
pair_filename.property = eina_stringshare_add(desc->members[EIO_MODEL_PROP_FILENAME].name);
eina_value_struct_set(priv->properties, pair_filename.property, basename(priv->path));
eina_value_struct_value_get(priv->properties, pair_filename.property, &pair_filename.value);
evt.changed_properties = eina_list_append(evt.changed_properties, &pair_filename);
eo_do(priv->obj, eo_event_callback_call(EMODEL_EVENT_PROPERTIES_CHANGED, &evt));
eina_stringshare_del(pair_path.property);
eina_stringshare_del(pair_filename.property);
eina_value_flush(&pair_filename.value);
eina_value_flush(&pair_path.value);
eina_list_free(evt.changed_properties);
}
static void
_eio_error_cb(void *data EINA_UNUSED, Eio_File *handler EINA_UNUSED, int error)
{
if(error != 0)
{
fprintf(stderr, "Error: %s : %d: %s\n", __FUNCTION__, error, strerror(errno));
EINA_SAFETY_ON_FALSE_RETURN(EINA_FALSE); /**< force check error only to be more verbose */
}
fprintf(stdout, "%s : %d\n", __FUNCTION__, error);
}
static void
_eio_prop_set_error_cb(void *data EINA_UNUSED, Eio_File *handler EINA_UNUSED, int error EINA_UNUSED)
{
fprintf(stdout, "%s : %d\n", __FUNCTION__, error);
}
/**
* Callbacks
* Ecore Events
*/
static Eina_Bool
_emodel_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;
Emodel_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(EMODEL_EVENT_CHILD_ADDED, &cevt));
}
return EINA_TRUE;
}
static Eina_Bool
_emodel_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)
{
Emodel_Children_Event cevt;
cevt.index = i;
cevt.child = cur->data;
eo_do(priv->obj, eo_event_callback_call(EMODEL_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;
fprintf(stdout, "%s : %d\n", __FUNCTION__, error);
eo_unref(priv->obj);
}
/**
* Interfaces impl.
*/
static Emodel_Load_Status
_eio_model_emodel_properties_list_get(Eo *obj EINA_UNUSED,
Eio_Model_Data *_pd, Eina_List * const* properties_list)
{
Eio_Model_Data *priv = _pd;
unsigned int i;
EINA_SAFETY_ON_NULL_RETURN_VAL(priv, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(priv->obj, EINA_FALSE);
if(priv->properties_list == NULL)
{
Eina_Value_Struct_Desc *desc = EIO_MODEL_PROPERTIES_DESC;
for(i = 0; i < desc->member_count; ++i)
priv->properties_list = eina_list_append(priv->properties_list, desc->members[i].name);
}
*(Eina_List **)properties_list = priv->properties_list;
return priv->load.status;
}
/**
* Property Fetch //carlos
*/
static Emodel_Load_Status
_eio_model_emodel_property_get(Eo *obj EINA_UNUSED, Eio_Model_Data *priv, const char *property, Eina_Value *value)
{
Eina_Value _v;
EINA_SAFETY_ON_NULL_RETURN_VAL(property, EMODEL_LOAD_STATUS_ERROR);
EINA_SAFETY_ON_NULL_RETURN_VAL(priv, EMODEL_LOAD_STATUS_ERROR);
EINA_SAFETY_ON_NULL_RETURN_VAL(priv->obj, EMODEL_LOAD_STATUS_ERROR);
if (eina_value_struct_value_get(priv->properties, property, &_v) == EINA_TRUE)
{
eina_value_copy(&_v, value);
}
return priv->load.status;
}
/**
* Property Set
*/
static Emodel_Load_Status
_eio_model_emodel_property_set(Eo *obj EINA_UNUSED, Eio_Model_Data *priv, const char * property, Eina_Value value)
{
char *dest;
Eina_Value v = value;
EINA_SAFETY_ON_NULL_RETURN_VAL(property, EINA_FALSE);
if (strcmp(property, "path") != 0)
return EINA_FALSE;
dest = eina_value_to_string(&v);
if (priv->path == NULL)
{
priv->path = dest;
fprintf(stdout, " path %s filename %s\n", priv->path, basename(priv->path));
eina_value_struct_set(priv->properties, "path", priv->path);
eina_value_struct_set(priv->properties, "filename", eina_stringshare_add(basename(priv->path)));
_eio_monitors_list_load(priv);
_eio_move_done_cb(priv, NULL);
if (priv->load_pending & EMODEL_LOAD_STATUS_LOADED_PROPERTIES)
_eio_model_emodel_properties_load(obj, priv);
if (priv->load_pending & EMODEL_LOAD_STATUS_LOADED_CHILDREN)
_eio_model_emodel_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 Emodel_Load_Status
_eio_model_emodel_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_emodel_properties_load(Eo *obj EINA_UNUSED, Eio_Model_Data *priv)
{
Emodel_Load load;
if (priv->path == NULL)
{
priv->load_pending |= EMODEL_LOAD_STATUS_LOADED_PROPERTIES;
return;
}
priv->load_pending &= ~EMODEL_LOAD_STATUS_LOADED_PROPERTIES;
if (!(priv->load.status & (EMODEL_LOAD_STATUS_LOADED_PROPERTIES | EMODEL_LOAD_STATUS_LOADING_PROPERTIES)))
{
load.status = EMODEL_LOAD_STATUS_LOADING_PROPERTIES;
_load_set(priv, load);
priv->file = eio_file_direct_stat(priv->path, _eio_stat_done_cb, _eio_error_cb, priv);
}
}
static void
_eio_model_emodel_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], _emodel_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], _emodel_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_ref(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;
Emodel_Load load;
EINA_SAFETY_ON_NULL_RETURN(priv);
count = eina_list_count(priv->children_list);
load.status = EMODEL_LOAD_STATUS_LOADED_CHILDREN;
_load_set(priv, load);
eo_do(priv->obj, eo_event_callback_call(EMODEL_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;
Emodel_Load load;
fprintf(stderr, "%s: err=%d\n", __FUNCTION__, error);
EINA_LIST_FREE(priv->children_list, child)
eo_unref(child);
load.status = EMODEL_LOAD_STATUS_LOADED_CHILDREN;
_load_set(priv, load);
}
/**
* Children Load
*/
static void
_eio_model_emodel_children_load(Eo *obj EINA_UNUSED, Eio_Model_Data *priv)
{
Emodel_Load load;
if (priv->path == NULL)
{
priv->load_pending |= EMODEL_LOAD_STATUS_LOADED_CHILDREN;
return;
}
priv->load_pending &= ~EMODEL_LOAD_STATUS_LOADED_CHILDREN;
if (!(priv->load.status & (EMODEL_LOAD_STATUS_LOADED_CHILDREN | EMODEL_LOAD_STATUS_LOADING_CHILDREN)))
{
_eio_model_emodel_monitor_add(priv);
load.status = EMODEL_LOAD_STATUS_LOADING_CHILDREN;
_load_set(priv, load);
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_emodel_load(Eo *obj, Eio_Model_Data *priv)
{
priv->load_pending |= EMODEL_LOAD_STATUS_LOADED_CHILDREN;
_eio_model_emodel_properties_load(obj, priv);
}
/**
* Load status get
*/
static Emodel_Load_Status
_eio_model_emodel_load_status_get(Eo *obj EINA_UNUSED, Eio_Model_Data *priv)
{
return priv->load.status;
}
/**
* Unload
*/
static void
_eio_model_emodel_unload(Eo *obj EINA_UNUSED, Eio_Model_Data *priv)
{
Emodel_Load load;
if (!(priv->load.status & EMODEL_LOAD_STATUS_UNLOADED))
{
Eo *child;
EINA_LIST_FREE(priv->children_list, child)
{
eo_unref(child);
}
load.status = EMODEL_LOAD_STATUS_UNLOADED;
_load_set(priv, load);
}
}
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_emodel_child_add(Eo *obj EINA_UNUSED, Eio_Model_Data *priv EINA_UNUSED)
{
return eo_add(EIO_MODEL_CLASS, obj);
}
static void
_eio_model_emodel_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 Emodel_Load_Status
_eio_model_emodel_child_del(Eo *obj EINA_UNUSED, Eio_Model_Data *priv, Eo *child)
{
Eio_Model_Data *child_priv;
EINA_SAFETY_ON_NULL_RETURN_VAL(child, EMODEL_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, EMODEL_LOAD_STATUS_ERROR);
eio_file_direct_stat(child_priv->path, &_eio_model_emodel_child_del_stat
, &_eio_error_unlink_cb, child);
eo_ref(child);
return priv->load.status;
}
/**
* Children Slice Get
* TODO/XXX/FIXME: Untested code - validate this implementation
*/
static Emodel_Load_Status
_eio_model_emodel_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 & EMODEL_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)
{
/**
* In error, we make it more verbose
* by forcing warning to be displayed on terminal.
*/
*children_accessor = NULL;
EINA_SAFETY_ON_NULL_RETURN_VAL(NULL, 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;
}
*children_accessor = eina_list_accessor_new(lr);
}
return priv->load.status;
}
static void
_struct_properties_init(void)
{
typedef struct _This_Eio_Properties
{
const char *filename;
const char *path;
double mtime;
int is_dir;
int is_lnk;
int size;
} This_Eio_Properties;
static Eina_Value_Struct_Member prop_members[] = {
EINA_VALUE_STRUCT_MEMBER(NULL, This_Eio_Properties, filename),
EINA_VALUE_STRUCT_MEMBER(NULL, This_Eio_Properties, path),
EINA_VALUE_STRUCT_MEMBER(NULL, This_Eio_Properties, mtime),
EINA_VALUE_STRUCT_MEMBER(NULL, This_Eio_Properties, is_dir),
EINA_VALUE_STRUCT_MEMBER(NULL, This_Eio_Properties, is_lnk),
EINA_VALUE_STRUCT_MEMBER(NULL, This_Eio_Properties, size)
};
//XXX: Check data types
prop_members[EIO_MODEL_PROP_FILENAME].type = EINA_VALUE_TYPE_STRING;
prop_members[EIO_MODEL_PROP_PATH].type = EINA_VALUE_TYPE_STRING;
prop_members[EIO_MODEL_PROP_MTIME].type = EINA_VALUE_TYPE_TIMEVAL;
prop_members[EIO_MODEL_PROP_IS_DIR].type = EINA_VALUE_TYPE_INT;
prop_members[EIO_MODEL_PROP_IS_LNK].type = EINA_VALUE_TYPE_INT;
prop_members[EIO_MODEL_PROP_SIZE].type = EINA_VALUE_TYPE_INT64;
static Eina_Value_Struct_Desc prop_desc = {
EINA_VALUE_STRUCT_DESC_VERSION,
NULL, // no special operations
prop_members,
EINA_C_ARRAY_LENGTH(prop_members),
sizeof(This_Eio_Properties)
};
EIO_MODEL_PROPERTIES_DESC = &prop_desc;
}
/**
* Class definitions
*/
static void
_eio_model_eo_base_constructor(Eo *obj, Eio_Model_Data *priv)
{
eo_do_super(obj, MY_CLASS, eo_constructor());
priv->obj = obj;
_struct_properties_init();
priv->properties = eina_value_struct_new(EIO_MODEL_PROPERTIES_DESC);
EINA_SAFETY_ON_NULL_RETURN(priv->properties);
priv->load.status = EMODEL_LOAD_STATUS_UNLOADED;
priv->monitor = NULL;
}
static void
_eio_model_path_set(Eo *obj EINA_UNUSED, Eio_Model_Data *priv, const char *path)
{
//_eio_model_eo_base_constructor(obj, priv);
priv->path = strdup(path);
eina_value_struct_set(priv->properties, "path", priv->path);
eina_value_struct_set(priv->properties, "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;
if(priv->monitor)
eio_monitor_del(priv->monitor);
eina_list_free(priv->properties_list);
eina_value_free(priv->properties);
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"

49
src/lib/eio/eio_model.eo Normal file
View File

@ -0,0 +1,49 @@
class Eio.Model (Eo.Base, Emodel)
{
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;
Emodel.properties_list.get;
Emodel.properties_load;
Emodel.property.set;
Emodel.property.get;
Emodel.load;
Emodel.load_status.get;
Emodel.unload;
Emodel.child_add;
Emodel.child_del;
Emodel.children_slice.get;
Emodel.children_count.get;
Emodel.children_load;
}
}

45
src/lib/eio/eio_model.h Normal file
View File

@ -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 <Emodel.h>
#include <Eio.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <eio_model.eo.h>
#ifdef __cplusplus
}
#endif
#endif //_EMODEL_EIO_H

View File

@ -0,0 +1,62 @@
#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_Child_Add Eio_Model_Child_Add;
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 */
};
/**
* !! Warning: Do not change enum's order
* before checking _eio_model_constructor.
* @see Eina_Value_Struct_Member.
*/
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
};
struct _Eio_Model_Data
{
Eo *obj;
char *path;
Eina_List *properties_list;
Eina_Value *properties;
Emodel_Load load;
int load_pending;
Eina_List *children_list;
/**< EIO data */
Eio_File *file;
const Eina_Stat *stat;
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;
};
/*
struct _Eio_Model_Child_Add
{
Eo *child;
Eio_Model_Data *priv;
char* fullpath;
char *name;
};
*/
#endif

127
src/lib/emodel/Emodel.h Normal file
View File

@ -0,0 +1,127 @@
/**
@brief Emodel Library Public API Calls
These routines are used for MVC (Model View Controller) Library interaction.
*/
/**
* @page emodel_main Emodel
*
* @date 2014 (created)
* @section toc Table of Contents
*
* @li @ref emodel_main_intro
* @li @ref emodel_main_intro_example
*
* @section emodel_main_intro Introduction
*
* The Emodel(model) generic object system for Emodel View Controller.
*
* @section emodel_main_work How does Emodel work?
*
* The Model notifies Views and Controllers when there is a change in its state.
* The other way around is also true and the Model can be passive and be poolled
* for update rather than generating output representations.
*
* Concrete objects can implement functionalities by overriding Emodel's API, abstracting its complexities from
* applications that can keep focus on higher level implementation.
*
* Examples of concrete implementations that can make use Emodel:
*
* Filesystem and I/O operations;
* Database management;
* GUI forms, lists and trees.
*
* Application code tends to be small in number of lines,
* more simple and code readability is improved.
*
* Emodel use EO Events. Views and Controllers must register
* in events to be able to recieve notifications about state changes in Emodel.
* Some of currently available events are:
*
* EMODEL_EVENT_LOAD_STATUS
* EMODEL_EVENT_PROPERTIES_CHANGED
* EMODEL_EVENT_CHILD_ADDED
* EMODEL_EVENT_CHILD_REMOVED
* EMODEL_EVENT_CHILDREN_COUNT_CHANGED
*
* Example code using Emodel_Eio that returns the number of files in '/tmp' directory:
*
* @code
* static Eina_Bool
* _children_count_cb(void *data EINA_UNUSED, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
* {
* size_t *len = event_info;
* fprintf(stdout, "Children count len=%lu\n", *len);
* return EINA_TRUE;
* }
*
* int
* main(int argc, const char **argv)
* {
* size_t total;
* Eo *model;
* if(!ecore_init())
* {
* fprintf(stderr, "ERROR: Cannot init Ecore!\n");
* return 1;
* }
* if(!eio_init())
* {
* fprintf(stderr, "ERROR: Cannot init Eio!\n");
* return 1;
* }
*
* model = eo_add_custom(EIO_MODEL_CLASS, NULL, eio_model_constructor("/tmp"));
* eo_do(model, eo_event_callback_add(EMODEL_EVENT_CHILDREN_COUNT_CHANGED, _children_count_cb, NULL));
* eo_do(model, emodel_children_count_get(&total));
* fprintf(stdout, "total=%lu\n", total);
*
* ecore_main_loop_begin();
* eo_unref(model);
* eio_shutdown();
* ecore_shutdown();
* return 0;
* }
* @endcode
*
* In previous example the concrete Emodel_Eio counts, asynchronously, the number of files in given directory,
* emodel_children_count_get() returns into 'total' pointer the last known number of children. In the meantime
* when background count is finished _children_count_cb() is invoked receiving the number of files as event_info data.
* This is achieved by registering the Model as EMODEL_EVENT_CHILDREN_COUNT_CHANGED event listener and every time
* the count (number of children) changes, the event is disptached to listeners.
*
* The principles may remain the same for different events and the logic remains.
*
* @li @ref emodel_main_intro_example
*
* @include emodel_test_file.c
*
* Recommended reading:
*
* @li @ref Eo, where you'll understand how Eo Events work.
* @li @ref Eio, where you'll find EFL Eio implementation and interfaces.
* @li @ref Emodel_Eio, the concrete EIO implementation using both Emodel and Eio.
* @li @ref Ecore, You'll get more information about I/O filesystem events.
*
* @defgroup Emodel
*
* @addtogroup Emodel
* @{
*/
#ifndef _EMODEL_H
#define _EMODEL_H
#include <Efl_Config.h>
#include <Eo.h>
#include <Emodel_Common.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <emodel.eo.h>
#ifdef __cplusplus
}
#endif
#endif //_EMODEL_H

View File

@ -0,0 +1,106 @@
#ifndef _EMODEL_COMMON_H
#define _EMODEL_COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @enum _Emodel_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 _Emodel_Load_Status
{
EMODEL_LOAD_STATUS_ERROR = 0,
EMODEL_LOAD_STATUS_LOADING_PROPERTIES = (1 << 0),
EMODEL_LOAD_STATUS_LOADING_CHILDREN = (1 << 1),
EMODEL_LOAD_STATUS_LOADING = (1 << 0) | (1 << 1),
EMODEL_LOAD_STATUS_LOADED_PROPERTIES = (1 << 2),
EMODEL_LOAD_STATUS_LOADED_CHILDREN = (1 << 3),
EMODEL_LOAD_STATUS_LOADED = (1 << 2) | (1 << 3),
EMODEL_LOAD_STATUS_UNLOADING = (1 << 4),
EMODEL_LOAD_STATUS_UNLOADED = (1 << 5)
};
/**
* @typedef Emodel_Load_Status
*/
typedef enum _Emodel_Load_Status Emodel_Load_Status;
/**
* @struct _Emodel_Load
* Structure to hold Emodel_Load_Status enum
* (and possible other data) to avoid ABI break.
*/
struct _Emodel_Load
{
Emodel_Load_Status status;
/* add more data below here if necessary */
};
/**
* @typedef Emodel_Load
*/
typedef struct _Emodel_Load Emodel_Load;
/**
* @struct _Emodel_Property_Pair
*/
struct _Emodel_Property_Pair
{
Eina_Value value; /**< the property value */
Eina_Stringshare *property; /**< the property name */
};
/**
* @typedef Emodel_Property_Pair
*/
typedef struct _Emodel_Property_Pair Emodel_Property_Pair;
/**
* @struct _Emodel_Property_Event
*/
struct _Emodel_Property_Event
{
Eina_List *changed_properties; /**< the property value */
Eina_List *invalidated_properties; /**< the property name */
};
/**
* @typedef Emodel_Property_Event
*/
typedef struct _Emodel_Property_Event Emodel_Property_Event;
/**
* @struct _Emodel_Children_Event
* Every time a child id added the event
* EMODEL_EVENT_CHILD_ADDED is dispatched
* passing along this structure.
*/
struct _Emodel_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 Emodel_Children_Event
*/
typedef struct _Emodel_Children_Event Emodel_Children_Event;
#ifdef __cplusplus
}
#endif
#endif

6
src/lib/emodel/emodel.c Normal file
View File

@ -0,0 +1,6 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "Emodel.h"
#include "emodel.eo.c"

326
src/lib/emodel/emodel.eo Normal file
View File

@ -0,0 +1,326 @@
/*
* type Emodel_Load_Status: enum _Emodel_Load_Status
* {
* EMODEL_LOAD_STATUS_ERROR = 0, /*@ Error in Load Model *
* EMODEL_LOAD_STATUS_LOADING_PROPERTIES = (1 << 0), /*@ properties load in progress *
* EMODEL_LOAD_STATUS_LOADING_CHILDREN = (1 << 1), /*@ children load in progress *
* EMODEL_LOAD_STATUS_LOADING = (1 << 0) | (1 << 1), /*@ children and properties load in progress *
*
* EMODEL_LOAD_STATUS_LOADED_PROPERTIES = (1 << 2), /*@ Model as ready to fetch properties *
* EMODEL_LOAD_STATUS_LOADED_CHILDREN = (1 << 3), /*@ Model as ready to fetch children *
* EMODEL_LOAD_STATUS_LOADED = (1 << 2) | (1 << 3), /*@ Model as ready to fetch properties and children *
*
* EMODEL_LOAD_STATUS_UNLOADING = (1 << 4), /*@ Model Unload in progress *
* EMODEL_LOAD_STATUS_UNLOADED = (1 << 5) /*@ Model Unloaded *
* }
*
* type Emodel_Property_Pair: struct _Emodel_Property_Pair
* {
* value: Eina_Value; /*@ the new property value *
* property: const(char)*; /*@ the property name that has been changed *
* }
*
* type Emodel_Property_Event: struct _Emodel_Property_Event
* {
* changed_properties: Eina_List* <Emodel_Property_Pair*>; /*@ List of changed properties *
* invalidated_properties: Eina_List* <const(char)*>; /*@ Removed properties identified by name *
* }
*/
interface Emodel ()
{
legacy_prefix: null;
properties {
load_status {
get {
/*@
Get a load emodel current status.
@return: @c Emodel_Load_Status
By convention this means get the current model status.
Possible values are defined Emodel_Load_Status enumerator.
@see Emodel_Load_Status
@see emodel_load
@since 1.11 */
return: Emodel_Load_Status;
}
}
properties_list {
get {
/*@
Get properties list from model.
@return: @c Emodel_Load_Status
properties_list_get is due to provide callers a way the fetch the current
properties implemented/used by the model.
The event EMODEL_EVENT_PROPERTIES_CHANGE will be raised to notify listeners
of any modifications in the properties list.
@see EMODEL_EVENT_PROPERTIES_CHANGE
@since 1.11 */
return: Emodel_Load_Status;
}
values {
const(list<const(char*)>*) properties_list; /*@ list 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 emodel_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
EMODEL_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 emodel_property_get
@see EMODEL_EVENT_PROPERTIES_CHANGE
@since 1.11 */
return: Emodel_Load_Status;
}
get {
/*@
Retrieve the value of a given property name.
@return: @c Load Status, on success, @c EMODEL_LOAD_STATUS_ERROR otherwise
property_get will only be available when load status is equal to
EMODEL_LOAD_STATUS_LOADED.
At this point the caller is free to get values from properties.
The event EMODEL_EVENT_PROPERTIES_CHANGE may be raised to notify
listeners of the property/value.
@see emodel_properties_list_get
@see EMODEL_EVENT_PROPERTIES_CHANGE
@since 1.11 */
return: Emodel_Load_Status;
}
keys {
const(char)* property; /*@ Property name */
}
values {
Eina_Value value; /*@ New value */
}
}
children_slice {
get {
/*@
Get children slice OR full range.
@return: @c Emodel_Load_Status. See below for more info.
Before being able to get the children list the model status must be
on loaded status (EMODEL_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 EMODEL_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, emodel_children_slice_get(0, 0, &children_accessor));
// Returns 5 items, counting from item #5
eo_do(obj, emodel_children_slice_get(5, 5, &children_accessor));
@endcode
@see emodel_children_get
@see emodel_children_count_get
@see emodel_load
@see emodel_load_status_get
@since 1.11 */
return: Emodel_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 emodel_load is completed emodel_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 EMODEL_CHILDREN_COUNT_CHANGED is emitted when count is finished.
@see emodel_children_get
@see emodel_children_slice_get
@see emodel_load
@see emodel_load_status_get
@since 1.11 */
return: Emodel_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 EMODEL_EVENT_LOAD_STATUS after end with Emodel_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 emodel_load is called then
calling properties_load and/or children_load is not necessary.
@see Emodel_Load_Status
@see emodel_properties_load
@see emodel_children_load
@see emodel_unload
@see emodel_load_status_get
@since 1.11 */
}
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 EMODEL_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 Emodel_Load_Status
@see emodel_load
@see emodel_load_status_get
@since 1.11 */
}
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 emodel_load, meaning that
it won't load children, it is a hint.
For loadind both properties and children use emodel_load
instead.
@see emodel_load
@since 1.11 */
}
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 emodel_load, meaning that
it won't load properties. For loadind both properties and children use emodel_load
instead.
@see emodel_load
@since 1.11 */
}
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 EMODEL_EVENT_CHILD_ADD is then raised and the new child
is kept along with other children.
@see EMODEL_EVENT_CHILD_ADD
@see load_status_get
@since 1.11 */
return: Eo *;
}
child_del {
/*@
Remove a child.
@return: @c Emodel_Load_Status on success, @c EMODEL_LOAD_STATUS_ERROR otherwise.
Remove a child of a internal keeping. When the child is effectively
removed the event EMODEL_EVENT_CHILD_REMOVED is then raised to give a
chance for listeners to perform any cleanup and/or update references.
@see EMODEL_EVENT_CHILD_REMOVED
@since 1.11 */
return: Emodel_Load_Status;
params {
@in Eo* child; /*@ Child to be removed */
}
}
}
events {
load,status: Emodel_Load_Status; /*@ Event dispatch when load status changes */
properties,changed: Emodel_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. */
}
}

View File

@ -0,0 +1,138 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <Eina.h>
#include <stdio.h>
#include <string.h>
#include <check.h>
void emodel_test_file(TCase* tc);
void emodel_test_monitor_add(TCase* tc);
typedef struct _Emodel_Test_Case Emodel_Test_Case;
struct _Emodel_Test_Case
{
const char *test_case;
void (*build)(TCase *tc);
};
static const Emodel_Test_Case etc[] = {
{ "File", emodel_test_file },
{ "Monitor Add", emodel_test_monitor_add },
{ NULL, NULL }
};
static void
_list_tests(void)
{
const Emodel_Test_Case *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;
}
Suite *
emodel_build_suite(int argc, const char **argv)
{
TCase *tc;
Suite *s;
int i;
s = suite_create("Emodel");
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);
tcase_set_timeout(tc, 0);
etc[i].build(tc);
suite_add_tcase(s, tc);
}
return s;
}
/* FIXME this is a copy from eina_test_mempool
* we should remove the duplication
*/
static Eina_Array *_modules;
static void _mempool_init(void)
{
eina_init();
/* force modules to be loaded in case they are not installed */
_modules = eina_module_list_get(NULL,
PACKAGE_BUILD_DIR "/src/modules",
EINA_TRUE,
NULL,
NULL);
eina_module_list_load(_modules);
}
static void _mempool_shutdown(void)
{
eina_module_list_free(_modules);
if (_modules)
eina_array_free(_modules);
/* TODO delete the list */
eina_shutdown();
}
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 = emodel_build_suite(argc - 1, (const char **)argv + 1);
sr = srunner_create(s);
srunner_set_xml(sr, TESTS_BUILD_DIR "/check-results.xml");
_mempool_init();
srunner_run_all(sr, CK_ENV);
failed_count = srunner_ntests_failed(sr);
srunner_free(sr);
_mempool_shutdown();
return (failed_count == 0) ? 0 : 255;
}

View File

@ -0,0 +1,273 @@
//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 <Emodel.h>
#include <eio_model.h>
#include <stdio.h>
#include <check.h>
#define EMODEL_TEST_FILENAME_PATH "/tmp"
#define EMODEL_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;
int changed_icon;
/* properties list */
int proplist_filename;
int proplist_path;
int proplist_icon;
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)
{
Emodel_Load *st = event_info;
printf("Load CHANGE\n");
if (st->status & EMODEL_LOAD_STATUS_LOADED_CHILDREN)
printf("Children is Loaded\n");
if (st->status & EMODEL_LOAD_STATUS_LOADED_PROPERTIES)
printf("Properties is Loaded\n");
if ((st->status & EMODEL_LOAD_STATUS_LOADED) == EMODEL_LOAD_STATUS_LOADED)
{
Eina_Accessor *accessor;
Eina_Value value_prop;
Eo *child;
Emodel_Load_Status status;
unsigned int total, i;
char *str;
printf("Model is Loaded\n");
eo_do(obj, status = emodel_property_get("filename", &value_prop));
str = eina_value_to_string(&value_prop);
printf("emodel_loaded filename %s, status=%d\n", str, status);
eina_value_flush(&value_prop);
free(str);
eo_do(obj, status = emodel_property_get("size", &value_prop));
str = eina_value_to_string(&value_prop);
printf("emodel_loaded size %s, status=%d\n", str, status);
eina_value_flush(&value_prop);
free(str);
eo_do(obj, status = emodel_property_get("mtime", &value_prop));
str = eina_value_to_string(&value_prop);
printf("emodel_loaded mtime %s, status=%d\n", str, status);
eina_value_flush(&value_prop);
free(str);
eo_do(obj, emodel_children_count_get(&total));
printf("emodel_test count %d\n", (int)total);
/**< get full list */
eo_do(obj, status = emodel_children_slice_get(0 ,0 ,(Eina_Accessor **)&accessor));
EINA_ACCESSOR_FOREACH(accessor, i, child)
{
//XXX: check if there is memleak
eo_do(child, status = emodel_property_get("filename", &value_prop));
str = eina_value_to_string(&value_prop);
printf("(full) %d emodel_children_get filename %s\n", i, str);
eina_value_flush(&value_prop);
free(str);
}
i = 0;
eina_accessor_free(accessor);
eo_do(obj, status = emodel_children_slice_get(5 ,5 ,(Eina_Accessor **)&accessor));
EINA_ACCESSOR_FOREACH(accessor, i, child)
{
//XXX: check if there is memleak
eo_do(child, status = emodel_property_get("filename", &value_prop));
str = eina_value_to_string(&value_prop);
printf("(slice) %d emodel_chidlren_property_set filename %s\n", i, str);
eina_value_flush(&value_prop);
free(str);
eo_unref(child);
}
eina_accessor_free(accessor);
ecore_main_loop_quit();
}
return EINA_TRUE;
}
static Eina_Bool
_properties_cb(void *data EINA_UNUSED, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
{
const Emodel_Property_Event *evt = (Emodel_Property_Event *)event_info;
Emodel_Property_Pair *pair = NULL;
Eina_List *l = NULL;
EINA_LIST_FOREACH(evt->changed_properties, l, pair)
{
char *str;
str = eina_value_to_string(&pair->value);
fprintf(stdout, "Received changed property=%s, value=%s\n",
pair->property, str);
free(str);
if(!strcmp(pair->property, "is_dir"))
reqs.changed_is_dir = 1;
if(!strcmp(pair->property, "is_lnk"))
reqs.changed_is_lnk = 1;
if(!strcmp(pair->property, "size"))
reqs.changed_size = 1;
if(!strcmp(pair->property, "mtime"))
reqs.changed_mtime = 1;
if(!strcmp(pair->property, "icon"))
reqs.changed_icon = 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, emodel_children_count_get(&total));
fprintf(stdout, "New total children count number=%d\n", *len);
return EINA_TRUE;
}
START_TEST(emodel_test_test_file)
{
Eo *filemodel = NULL;
Eina_Value value_prop;
Emodel_Load_Status status;
#ifdef _RUN_LOCAL_TEST
Eina_Value nameset_value;
#endif
Eina_List *properties_list;
Eina_List *l;
char *str;
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(EMODEL_TEST_FILENAME_PATH));
fail_if(!filemodel, "ERROR: Cannot init model!\n");
eo_do(filemodel, eo_event_callback_add(EMODEL_EVENT_LOAD_STATUS, _load_status_cb, NULL));
eo_do(filemodel, eo_event_callback_add(EMODEL_EVENT_PROPERTIES_CHANGED, _properties_cb, NULL));
eo_do(filemodel, eo_event_callback_add(EMODEL_EVENT_CHILDREN_COUNT_CHANGED, _children_count_cb, NULL));
eo_do(filemodel, emodel_load());
handler = ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, exit_func, NULL);
eina_value_setup(&value_prop, EINA_VALUE_TYPE_STRING);
eo_do(filemodel, status = emodel_property_get("filename", &value_prop));
str = eina_value_to_string(&value_prop);
printf("emodel_test filename %s, load status %d\n", str, status);
eina_value_flush(&value_prop);
free(str);
i = 0;
eo_do(filemodel, emodel_properties_list_get(&properties_list));
EINA_LIST_FOREACH((Eina_List *)properties_list, l, str)
{
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, "icon"))
reqs.proplist_icon = 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/emodel_test");
eo_do(filemodel, emodel_property_set("path", nameset_value));
eina_value_flush(&nameset_value);
//emodel_property_get("path", &value_prop);
eo_do(filemodel, status = emodel_property_get("path", &value_prop));
eina_value_flush(&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
emodel_test_file(TCase *tc)
{
/* tcase_add_test(tc, emodel_test_test_file); */
}

View File

@ -0,0 +1,105 @@
//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 <Emodel.h>
#include <eio_model.h>
#include <stdio.h>
#include <check.h>
#define EMODEL_TEST_FILENAME_PATH "/tmp"
Eina_Bool children_added = 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)
{
Emodel_Children_Event* evt = event_info;
Eo* child = evt->child;
Eina_Value value_prop;
const char* str;
eo_do(child, emodel_property_get("filename", &value_prop));
str = eina_value_to_string(&value_prop);
fprintf(stderr, "new children filename %s\n", str);
if(strcmp(str, "test_file_monitor_add") == 0)
{
fprintf(stderr, "is child that we want\n");
children_added = EINA_TRUE;
eo_do(obj, emodel_child_del(child));
ecore_main_loop_quit();
}
eina_value_flush(&value_prop);
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;
Emodel_Load_Status status;
Eo *child;
unsigned int i = 0;
fprintf(stderr, "Children count number=%d\n", *len);
/**< get full list */
eo_do(obj, status = emodel_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(EMODEL_TEST_FILENAME_PATH "/test_file_monitor_add", "w+"));
return EINA_TRUE;
}
START_TEST(emodel_test_test_monitor_add)
{
Eo *filemodel = NULL;
fprintf(stderr, "emodel_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(EMODEL_TEST_FILENAME_PATH));
fail_if(!filemodel, "ERROR: Cannot init model!\n");
eo_do(filemodel, eo_event_callback_add(EMODEL_EVENT_CHILDREN_COUNT_CHANGED, _children_count_cb, NULL));
eo_do(filemodel, eo_event_callback_add(EMODEL_EVENT_CHILD_ADDED, _children_added_cb, NULL));
eo_do(filemodel, emodel_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
emodel_test_monitor_add(TCase *tc)
{
tcase_add_test(tc, emodel_test_test_monitor_add);
}