forked from enlightenment/efl
Another example for eina_model.
Patch by: "Jonas M. Gastal" <jgastal@profusion.mobi> SVN revision: 67832
This commit is contained in:
parent
d5cbba52ef
commit
27f0f4cceb
|
@ -39,7 +39,8 @@ SRCS = \
|
|||
eina_strbuf_01.c \
|
||||
eina_tiler_01.c \
|
||||
eina_model_01.c \
|
||||
eina_model_02.c
|
||||
eina_model_02.c \
|
||||
eina_model_03.c
|
||||
|
||||
examples_PROGRAMS =
|
||||
|
||||
|
@ -77,7 +78,8 @@ examples_PROGRAMS += \
|
|||
eina_str_01 \
|
||||
eina_strbuf_01 \
|
||||
eina_model_01 \
|
||||
eina_model_02
|
||||
eina_model_02 \
|
||||
eina_model_03
|
||||
|
||||
if BUILD_TILER_EXAMPLE
|
||||
AM_CPPFLAGS += @ECORE_EVAS_CFLAGS@
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
Kara Thrace starbuck@bsg.com
|
||||
Sharon Valerii boomer@bsg.com
|
||||
Sharon Aghaton athena@bsg.com
|
||||
Karl Aghaton helo@bsg.com
|
||||
Louanne Katraine kat@bsg.com
|
||||
|
||||
Lee Adama apolo@bsg.com
|
|
@ -0,0 +1,233 @@
|
|||
#include <Eina.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
static Eina_Model_Type *ADDRESS_BOOK_TYPE;
|
||||
static Eina_Model_Type *PERSON_TYPE;
|
||||
|
||||
static void address_book_init(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Eina_Model *address_book;
|
||||
Eina_Value val;
|
||||
int i, count;
|
||||
char *s;
|
||||
|
||||
eina_init();
|
||||
|
||||
address_book_init();
|
||||
|
||||
address_book = eina_model_new(ADDRESS_BOOK_TYPE);
|
||||
|
||||
eina_value_setup(&val, EINA_VALUE_TYPE_STRING);
|
||||
eina_value_set(&val, "addr_book.txt");
|
||||
eina_model_property_set(address_book, "filename", &val);
|
||||
eina_value_flush(&val);
|
||||
|
||||
eina_model_load(address_book);
|
||||
s = eina_model_to_string(address_book);
|
||||
printf("model as string:\n%s\n\n", s);
|
||||
free(s);
|
||||
|
||||
count = eina_model_child_count(address_book);
|
||||
printf("Address Book with %d entries:\n", count);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
Eina_Model *person = eina_model_child_get(address_book, i);
|
||||
Eina_Value nameval, emailval;
|
||||
const char *name, *email;
|
||||
|
||||
eina_model_property_get(person, "name", &nameval);
|
||||
eina_model_property_get(person, "email", &emailval);
|
||||
|
||||
eina_value_get(&nameval, &name);
|
||||
eina_value_get(&emailval, &email);
|
||||
|
||||
printf("%02d \"%s\" <%s>\n", i, name, email);
|
||||
|
||||
// We don't need property values anymore
|
||||
eina_value_flush(&nameval);
|
||||
eina_value_flush(&emailval);
|
||||
|
||||
// We don't need our reference to person anymore
|
||||
eina_model_unref(person);
|
||||
}
|
||||
|
||||
eina_model_unref(address_book);
|
||||
eina_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Structure Descriptions are just used internally in the type constructors:
|
||||
static Eina_Value_Struct_Desc *ADDRESS_BOOK_DESC;
|
||||
static Eina_Value_Struct_Desc *PERSON_DESC;
|
||||
|
||||
static Eina_Bool
|
||||
_person_constructor(Eina_Model *model)
|
||||
{
|
||||
// call parent type constructor, like "super" in other languages:
|
||||
if (!eina_model_type_constructor(EINA_MODEL_TYPE_STRUCT, model))
|
||||
return EINA_FALSE;
|
||||
|
||||
// Do specific setup of our internal structure, letting it know about
|
||||
// our description
|
||||
return eina_model_struct_set(model, PERSON_DESC, NULL);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_address_book_constructor(Eina_Model *model)
|
||||
{
|
||||
// call parent type constructor, like "super" in other languages:
|
||||
if (!eina_model_type_constructor(EINA_MODEL_TYPE_STRUCT, model))
|
||||
return EINA_FALSE;
|
||||
|
||||
// Do specific setup of our internal structure, letting it know about
|
||||
// our description
|
||||
return eina_model_struct_set(model, ADDRESS_BOOK_DESC, NULL);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_address_book_load(Eina_Model *model)
|
||||
{
|
||||
const char *filename;
|
||||
Eina_Value val;
|
||||
char buf[256];
|
||||
FILE *f;
|
||||
|
||||
// We retrieve filename from property of same name:
|
||||
eina_model_property_get(model, "filename", &val);
|
||||
eina_value_get(&val, &filename);
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(filename, EINA_FALSE);
|
||||
|
||||
f = fopen(filename, "r");
|
||||
|
||||
// Now that we have used filename, we must free its memory holder:
|
||||
eina_value_flush(&val);
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(f, EINA_FALSE);
|
||||
|
||||
while (fgets(buf, sizeof(buf), f))
|
||||
{
|
||||
Eina_Model *person;
|
||||
char *name, *email;
|
||||
|
||||
if (strlen(buf) <= 1)
|
||||
continue;
|
||||
|
||||
name = strtok(buf, "\t");
|
||||
email = strtok(NULL, "\n");
|
||||
|
||||
if ((!name) || (!email)) continue;
|
||||
|
||||
// Create person
|
||||
person = eina_model_new(PERSON_TYPE);
|
||||
|
||||
// Setup value type as string, as our properties are strings:
|
||||
eina_value_setup(&val, EINA_VALUE_TYPE_STRING);
|
||||
|
||||
// Set string properties:
|
||||
eina_value_set(&val, name);
|
||||
eina_model_property_set(person, "name", &val);
|
||||
|
||||
eina_value_set(&val, email);
|
||||
eina_model_property_set(person, "email", &val);
|
||||
|
||||
// Flush value, free string
|
||||
eina_value_flush(&val);
|
||||
|
||||
// Add person to the end of model children
|
||||
eina_model_child_append(model, person);
|
||||
|
||||
// Model already holds its reference to person, we release ours
|
||||
eina_model_unref(person);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
address_book_init(void)
|
||||
{
|
||||
// Declare type for internal struct, this is just used to easily
|
||||
// create Eina_Value_Struct_Member array for Eina_Value_Struct_Desc.
|
||||
//
|
||||
// We don't need this structure outside address_book_init()
|
||||
// as it is managed automatically by Eina_Value_Struct, used by
|
||||
// Eina_Model_Struct! Handy! :-)
|
||||
typedef struct _Person Person;
|
||||
struct _Person
|
||||
{
|
||||
const char *name;
|
||||
const char *email;
|
||||
};
|
||||
static Eina_Value_Struct_Member person_members[] = {
|
||||
// no eina_value_type as they are not constant initializers, see below.
|
||||
EINA_VALUE_STRUCT_MEMBER(NULL, Person, name),
|
||||
EINA_VALUE_STRUCT_MEMBER(NULL, Person, email)
|
||||
};
|
||||
// Values that cannot be set on static declarations since they are not
|
||||
// constant initializers. It is a nitpick from C that we need to deal with
|
||||
// here and on all our other declarations.
|
||||
person_members[0].type = EINA_VALUE_TYPE_STRING;
|
||||
person_members[1].type = EINA_VALUE_TYPE_STRING;
|
||||
|
||||
static Eina_Value_Struct_Desc person_desc = {
|
||||
EINA_VALUE_STRUCT_DESC_VERSION,
|
||||
NULL, // no special operations
|
||||
person_members,
|
||||
EINA_C_ARRAY_LENGTH(person_members),
|
||||
sizeof(Person)
|
||||
};
|
||||
static Eina_Model_Type person_type = EINA_MODEL_TYPE_INIT_NOPRIVATE
|
||||
("Person_Type",
|
||||
Eina_Model_Type,
|
||||
NULL, // no type as EINA_MODEL_TYPE_STRUCT is not constant initializer!
|
||||
NULL, // no extra interfaces
|
||||
NULL // no extra events);
|
||||
);
|
||||
person_type.parent = EINA_MODEL_TYPE_STRUCT;
|
||||
// Set our overloaded methods:
|
||||
person_type.constructor = _person_constructor;
|
||||
|
||||
typedef struct _Address_Book Address_Book;
|
||||
struct _Address_Book
|
||||
{
|
||||
const char *filename;
|
||||
};
|
||||
static Eina_Value_Struct_Member address_book_members[] = {
|
||||
// no eina_value_type as they are not constant initializers, see below.
|
||||
EINA_VALUE_STRUCT_MEMBER(NULL, Address_Book, filename)
|
||||
};
|
||||
address_book_members[0].type = EINA_VALUE_TYPE_STRING;
|
||||
static Eina_Value_Struct_Desc address_book_desc = {
|
||||
EINA_VALUE_STRUCT_DESC_VERSION,
|
||||
NULL, // no special operations
|
||||
address_book_members,
|
||||
EINA_C_ARRAY_LENGTH(address_book_members),
|
||||
sizeof(Address_Book)
|
||||
};
|
||||
static Eina_Model_Type address_book_type = EINA_MODEL_TYPE_INIT_NOPRIVATE
|
||||
("Address_Book_Type",
|
||||
Eina_Model_Type,
|
||||
NULL, // no type as EINA_MODEL_TYPE_STRUCT is not constant initializer!
|
||||
NULL, // no extra interfaces
|
||||
NULL // no extra events);
|
||||
);
|
||||
address_book_type.parent = EINA_MODEL_TYPE_STRUCT;
|
||||
// Set our overloaded methods:
|
||||
address_book_type.constructor = _address_book_constructor;
|
||||
address_book_type.load = _address_book_load;
|
||||
|
||||
// Expose the configured pointers to public usage:
|
||||
// NOTE: they are static, so they live after this function returns!
|
||||
PERSON_TYPE = &person_type;
|
||||
PERSON_DESC = &person_desc;
|
||||
|
||||
ADDRESS_BOOK_TYPE = &address_book_type;
|
||||
ADDRESS_BOOK_DESC = &address_book_desc;
|
||||
}
|
|
@ -114,6 +114,128 @@
|
|||
* @example eina_model_02.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page eina_model_03_example_page Using Eina_Model and inheritance
|
||||
* @dontinclude eina_model_03.c
|
||||
*
|
||||
* This example will use two custom defined eina model types: @c PERSON_TYPE to
|
||||
* represent a person and @c ADDRESS_BOOK_TYPE to represent the an address book.
|
||||
* Both our types inherit from EINA_MODEL_TYPE_STRUCT, and, therefore,
|
||||
* store it's data on a struct. Our address book will be very simple it will
|
||||
* only contain one property, the name of the file where we store our address
|
||||
* book. The person type will contain two fields a name and en email. Let's look
|
||||
* at the code.
|
||||
*
|
||||
* We'll start with declaring the variables and functions we'll need to define
|
||||
* our custom type. This will all be explained when the variables get used.
|
||||
* @until address_book_init
|
||||
*
|
||||
* We then jump into our @c main function, declare a couple of variables and
|
||||
* initialize eina:
|
||||
* @until eina_init
|
||||
*
|
||||
* After eina is initialized we'll @c address_book_init() which will initialize
|
||||
* both our @c PERSON_TYPE and our @c ADDRESS_BOOK_TYPE. Details of this will be
|
||||
* shown latter on:
|
||||
* @until address_book_init
|
||||
*
|
||||
* Now that everything is correctly initialized we can create the model that
|
||||
* will represent our address book's
|
||||
* @until eina_model_new
|
||||
*
|
||||
* Before we can load data into our model we need to tell it where to load from,
|
||||
* we do this by setting it's filename property:
|
||||
* @until value_flush
|
||||
*
|
||||
* We then load data into our model and display it as a string:
|
||||
* @until free
|
||||
*
|
||||
* While @c eina_model_to_string allows you to see the contents of the model,
|
||||
* it's display format is not user friendly, it's best used for debugging. So
|
||||
* let's now print our model in a user friendly way.
|
||||
*
|
||||
* First we see how many people are in our address book and print that:
|
||||
* @until printf
|
||||
*
|
||||
* And now we iterate over every child of our address book model, which
|
||||
* represents a person:
|
||||
* @until person
|
||||
*
|
||||
* But again simply calling @c eina_model_to_string would result in not very
|
||||
* user friendly output, so we'll need to get the properties of the person(name
|
||||
* and email) and print them with some formatting:
|
||||
* @until printf
|
||||
*
|
||||
* We then free the resources we allocated to print this person:
|
||||
* @until }
|
||||
*
|
||||
* And that's it for our main function, now just freeing our resources:
|
||||
* @until }
|
||||
*
|
||||
* This however obviously doesn't conclude our example we need to examine how
|
||||
* the the loading of data works to really understand what is happening in the
|
||||
* @c main function.
|
||||
*
|
||||
* Let's start with the constructors(and the variables they use). Both our
|
||||
* constructors do two very important tasks:
|
||||
* @li Calls our parent's constructor, and
|
||||
* @li Sets the description of the struct on our model
|
||||
*
|
||||
* For these constructors that's all we need to do since most of our
|
||||
* functionality is provided by @c EINA_MODEL_TYPE_STRUCT.
|
||||
* @until }
|
||||
* @until }
|
||||
*
|
||||
* And now we have our load function, it opens the file from which we'll
|
||||
* read the address book:
|
||||
* @until EINA_SAFETY_ON_NULL_RETURN_VAL
|
||||
*
|
||||
* Once the file has been opened we read from it line by line and for each
|
||||
* non-blank line we get a name and an email:
|
||||
* @until email
|
||||
* @until email
|
||||
*
|
||||
* Once we have the name and email we create our person model, set it's
|
||||
* properties and make our person a child of the address book:
|
||||
* @until }
|
||||
*
|
||||
* And now that we're done reading the file we close it:
|
||||
* @until }
|
||||
*
|
||||
* This next function is perphaps the most interesting one of our example, it's
|
||||
* the one that creates the definition of our derived types.
|
||||
*
|
||||
* First thing we'll do is the description of the members of our person type.
|
||||
* @until person_members[1].type
|
||||
* Now the description of the struct itself(which uses the members):
|
||||
* @until }
|
||||
* And finally we define the person type itself:
|
||||
* @until person_type.constructor
|
||||
*
|
||||
* With the person now described we'll do the same process for our address book
|
||||
* type:
|
||||
* @until address_book_type.load
|
||||
*
|
||||
* So far everything we created has been in the scope of our function to make
|
||||
* this available outside(such as in the @c main function where we use @c
|
||||
* ADDRESS_BOOK_TYPE and on @c _address_book_load function where we use @c
|
||||
* PERSON_TYPE) we need to assign our descriptions and type to global variables:
|
||||
* @until }
|
||||
*
|
||||
* This concludes this example. A good exercise for the reader is to extend this
|
||||
* example to have the model save the addres book, for example once it's
|
||||
* unloaded, this can be done by overriding the .unload property of @c
|
||||
* ADDRESS_BOOK_TYPE.
|
||||
*
|
||||
* For the full code see: @ref eina_model_03_c
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page eina_model_03_c eina_model_03.c
|
||||
* @include eina_model_03.c
|
||||
* @example eina_model_03.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup Eina_Data_Types_Group Data Types
|
||||
*
|
||||
|
@ -149,6 +271,8 @@
|
|||
*
|
||||
* An inheritance example: @ref eina_model_01_c
|
||||
*
|
||||
* And a explained inheritance example: @ref eina_model_03_example_page
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
|
Loading…
Reference in New Issue