Compare commits

...

8 Commits

Author SHA1 Message Date
Felipe Magno de Almeida 8374a2eb7f [efl-model] Moved emodel to efl interfaces 2015-03-31 22:54:44 -03:00
Larry Jr 4c42df962f emodel: api change property_get/set and event modelchange 2015-03-20 16:03:47 -03:00
Cedric BAIL cb54407744 eio: fix coding style of Eio_Model. 2015-03-13 02:45:57 +01:00
Cedric BAIL a6730f638d eio: use Eina_Log in Eio_Model. 2015-03-13 02:41:16 +01:00
Cedric BAIL fb145d937d eio: add missing file to release tarball. 2015-03-12 08:33:18 +01:00
Larry Jr ea0a4a94d8 emodel API changes and removed unnecessary eina_values copy and stringshares 2015-03-12 07:54:24 +01:00
Guilherme Lepsch c09422d85e eio: fix mismatch datatypes for internal data model properties. 2015-03-12 07:54:03 +01:00
Larry Jr 79ed644b7b emodel: Created Emodel and Eio_Model. 2015-03-12 07:51:26 +01:00
25 changed files with 1716 additions and 10 deletions

View File

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

View File

@ -4604,6 +4604,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

3
pc/.gitignore vendored
View File

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

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

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

View File

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

View File

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

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@ @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
@ -45,6 +61,8 @@ 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 \
@ -52,16 +70,20 @@ tests_eio_eio_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eio\" \
@CHECK_CFLAGS@ \
@ECORE_FILE_CFLAGS@ \
@EIO_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
EXTRA_DIST += \
tests/eio/eio_suite.h \
lib/eio/eio_model.h

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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. */
}
}

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

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

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

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

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 <Efl.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,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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -19,6 +19,8 @@ struct _Eio_Test_Case
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}
};

View File

@ -4,5 +4,7 @@
#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 */