Store and compare objects information at every shot
This feature is aimed to provide a new way to debug applications during scenarios playing. When a difference happens between two shots of an application, the investigation can be tough as the cause may be hidden into a tiny change, such as an update of the theme. This feature tries to respond to this problem by storing objects of the application every time a shot is taken. Then during shots comparison, objects information are compared and differences are displayed on the screen. The feature can be used with the -S option. For the moment, only hierarchy, order and geometry are checked.
This commit is contained in:
parent
8e0a638b19
commit
dd4c1caade
|
@ -12,7 +12,7 @@ exactness_SOURCES = \
|
|||
exactness_helper_SOURCES = exactness_helper.c
|
||||
|
||||
exactness_LDADD = \
|
||||
@EFL_LIBS@
|
||||
@EFL_LIBS@ ../lib/libexactness_player.la
|
||||
|
||||
exactness_helper_LDADD = \
|
||||
@EFL_LIBS@ ../lib/libexactness_player.la
|
||||
|
|
|
@ -40,6 +40,7 @@ static const Ecore_Getopt optdesc = {
|
|||
ECORE_GETOPT_STORE_TRUE('p', "play", "Run in play mode."),
|
||||
ECORE_GETOPT_STORE_TRUE('i', "init", "Run in init mode."),
|
||||
ECORE_GETOPT_STORE_TRUE('s', "simulation", "Run in simulation mode."),
|
||||
ECORE_GETOPT_STORE_TRUE('S', "store-objects", "Store information about objects at every screen shot time."),
|
||||
ECORE_GETOPT_STORE_TRUE('v', "verbose", "Turn verbose messages on."),
|
||||
|
||||
ECORE_GETOPT_LICENSE('L', "license"),
|
||||
|
@ -69,6 +70,7 @@ main(int argc, char *argv[])
|
|||
ECORE_GETOPT_VALUE_BOOL(mode_play),
|
||||
ECORE_GETOPT_VALUE_BOOL(mode_init),
|
||||
ECORE_GETOPT_VALUE_BOOL(mode_simulation),
|
||||
ECORE_GETOPT_VALUE_BOOL(exactness_config.store_objects),
|
||||
ECORE_GETOPT_VALUE_BOOL(exactness_config.verbose),
|
||||
|
||||
ECORE_GETOPT_VALUE_BOOL(want_quit),
|
||||
|
|
|
@ -12,6 +12,7 @@ struct _Exactness_Config
|
|||
char *dest_dir;
|
||||
char *wrap_command;
|
||||
Eina_Bool verbose;
|
||||
Eina_Bool store_objects;
|
||||
};
|
||||
|
||||
extern Exactness_Config exactness_config;
|
||||
|
|
|
@ -116,7 +116,7 @@ _event_specific_info_get(const Variant_st *v, char output[1024])
|
|||
}
|
||||
static const Ecore_Getopt optdesc = {
|
||||
"exactness_helper",
|
||||
"%prog [options] <rec file>",
|
||||
"%prog [options] [<rec file> | <file1 file2>]",
|
||||
NULL,
|
||||
"(C) 2016 Enlightenment",
|
||||
"BSD",
|
||||
|
@ -125,7 +125,8 @@ static const Ecore_Getopt optdesc = {
|
|||
{
|
||||
ECORE_GETOPT_STORE_USHORT('d', "delay", "Delay the given recording by a given time (in seconds)."),
|
||||
ECORE_GETOPT_STORE_TRUE('c', "clean", "Clean the given recording from wrong events."),
|
||||
ECORE_GETOPT_STORE_TRUE('l', "list", "List the events of the given recording"),
|
||||
ECORE_GETOPT_STORE_TRUE('l', "list", "List the events of the given recording."),
|
||||
ECORE_GETOPT_STORE_TRUE('C', "compare", "Compare two given files (images files or objects eet files)."),
|
||||
|
||||
ECORE_GETOPT_LICENSE('L', "license"),
|
||||
ECORE_GETOPT_COPYRIGHT('C', "copyright"),
|
||||
|
@ -149,14 +150,15 @@ _is_hook_duplicate(const Variant_st *cur_v, const Variant_st *prev_v)
|
|||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const char *rec_file = NULL;
|
||||
const char *rec_file = NULL, *comp1 = NULL, *comp2 = NULL;
|
||||
int ret = 0, args = 0;
|
||||
unsigned short delay = 0;
|
||||
Eina_Bool want_quit, clean = EINA_FALSE, list_get = EINA_FALSE;
|
||||
Eina_Bool want_quit, clean = EINA_FALSE, list_get = EINA_FALSE, compare_files = EINA_FALSE;
|
||||
Ecore_Getopt_Value values[] = {
|
||||
ECORE_GETOPT_VALUE_USHORT(delay),
|
||||
ECORE_GETOPT_VALUE_BOOL(clean),
|
||||
ECORE_GETOPT_VALUE_BOOL(list_get),
|
||||
ECORE_GETOPT_VALUE_BOOL(compare_files),
|
||||
|
||||
ECORE_GETOPT_VALUE_BOOL(want_quit),
|
||||
ECORE_GETOPT_VALUE_BOOL(want_quit),
|
||||
|
@ -180,17 +182,33 @@ main(int argc, char *argv[])
|
|||
ret = 1;
|
||||
goto end;
|
||||
}
|
||||
else if (args == argc)
|
||||
else if ((clean || delay || list_get) && args == argc)
|
||||
{
|
||||
fprintf(stderr, "Expected rec file as the last argument..\n");
|
||||
ecore_getopt_help(stderr, &optdesc);
|
||||
ret = 1;
|
||||
goto end;
|
||||
}
|
||||
else if (compare_files && argc - args != 2)
|
||||
{
|
||||
fprintf(stderr, "Expected two files to compare as last arguments..\n");
|
||||
ecore_getopt_help(stderr, &optdesc);
|
||||
ret = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
rec_file = argv[args];
|
||||
Timer_Data td;
|
||||
Lists_st *list = read_events(rec_file, &td);
|
||||
Lists_st *list = NULL;
|
||||
if (clean || delay || list_get)
|
||||
{
|
||||
rec_file = argv[args];
|
||||
Timer_Data td;
|
||||
list = read_events(rec_file, &td);
|
||||
}
|
||||
if (compare_files)
|
||||
{
|
||||
comp1 = argv[args];
|
||||
comp2 = argv[args+1];
|
||||
}
|
||||
|
||||
if (clean)
|
||||
{
|
||||
|
@ -243,7 +261,37 @@ main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
write_events(rec_file, list);
|
||||
if (compare_files)
|
||||
{
|
||||
const char *ext = strrchr(comp1, '.');
|
||||
if (!ext)
|
||||
{
|
||||
fprintf(stderr, "Extension required\n");
|
||||
goto end;
|
||||
}
|
||||
if (!strcmp(ext, ".eet"))
|
||||
{
|
||||
if (!objects_files_compare(comp1, comp2, EINA_TRUE))
|
||||
{
|
||||
fprintf(stderr, "Failed objects comparing\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
/* FIXME: Clean up. */
|
||||
snprintf(buf, sizeof(buf),
|
||||
"compare '%s' '%s' 'comp_file%s'",
|
||||
comp1, comp2, ext);
|
||||
if (system(buf))
|
||||
{
|
||||
fprintf(stderr, "Failed image comparing '%s' and '%s'\n", comp1, comp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rec_file) write_events(rec_file, list);
|
||||
|
||||
end:
|
||||
ecore_shutdown();
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "exactness_config.h"
|
||||
#include "exactness_private.h"
|
||||
|
||||
#include "tsuite_file_data.h"
|
||||
|
||||
#define CONFIG "ELM_SCALE=1 ELM_FINGER_SIZE=10"
|
||||
|
||||
typedef enum
|
||||
|
@ -38,6 +40,8 @@ _run_command_prepare(const List_Entry *ent, Run_Mode mode, char *buf)
|
|||
eina_strbuf_append(sbuf, "ELM_ENGINE='buffer' ");
|
||||
eina_strbuf_append_printf(sbuf, "TSUITE_DEST_DIR='%s/%s' ",
|
||||
exactness_config.dest_dir, CURRENT_SUBDIR);
|
||||
if (exactness_config.store_objects)
|
||||
eina_strbuf_append(sbuf, "TSUITE_STORE_OBJECTS=1 ");
|
||||
break;
|
||||
}
|
||||
case RUN_INIT:
|
||||
|
@ -45,6 +49,8 @@ _run_command_prepare(const List_Entry *ent, Run_Mode mode, char *buf)
|
|||
eina_strbuf_append(sbuf, "ELM_ENGINE='buffer' ");
|
||||
eina_strbuf_append_printf(sbuf, "TSUITE_DEST_DIR='%s/%s' ",
|
||||
exactness_config.dest_dir, ORIG_SUBDIR);
|
||||
if (exactness_config.store_objects)
|
||||
eina_strbuf_append(sbuf, "TSUITE_STORE_OBJECTS=1 ");
|
||||
break;
|
||||
}
|
||||
case RUN_RECORD:
|
||||
|
@ -159,24 +165,35 @@ _compare_list_cb(const char *name, const char *path EINA_UNUSED, void *data)
|
|||
if (_check_prefix(prefix, name))
|
||||
{
|
||||
char filename1[EXACTNESS_PATH_MAX], filename2[EXACTNESS_PATH_MAX];
|
||||
snprintf(filename1, EXACTNESS_PATH_MAX, "%s/%s/%s", exactness_config.dest_dir, CURRENT_SUBDIR, name);
|
||||
snprintf(filename2, EXACTNESS_PATH_MAX, "%s/%s/%s", exactness_config.dest_dir, ORIG_SUBDIR, name);
|
||||
snprintf(filename1, EXACTNESS_PATH_MAX, "%s/%s/%s", exactness_config.dest_dir, ORIG_SUBDIR, name);
|
||||
snprintf(filename2, EXACTNESS_PATH_MAX, "%s/%s/%s", exactness_config.dest_dir, CURRENT_SUBDIR, name);
|
||||
if (!_is_equal(filename1, filename2))
|
||||
{
|
||||
char buf[EXACTNESS_PATH_MAX];
|
||||
exactness_ctx.compare_errors =
|
||||
eina_list_append(exactness_ctx.compare_errors,
|
||||
strdup(name));
|
||||
|
||||
/* FIXME: Clean up. */
|
||||
snprintf(buf, EXACTNESS_PATH_MAX,
|
||||
"compare '%s' '%s' '%s/%s/comp_%s'",
|
||||
filename1, filename2,
|
||||
exactness_config.dest_dir,
|
||||
CURRENT_SUBDIR, name);
|
||||
if (system(buf))
|
||||
const char *ext = strrchr(name, '.');
|
||||
if (!strcmp(ext, ".eet"))
|
||||
{
|
||||
fprintf(stderr, "Failed image comparing '%s'\n", name);
|
||||
if (!objects_files_compare(filename1, filename2, EINA_FALSE))
|
||||
{
|
||||
fprintf(stderr, "Failed objects comparing '%s'\n", name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[EXACTNESS_PATH_MAX];
|
||||
exactness_ctx.compare_errors =
|
||||
eina_list_append(exactness_ctx.compare_errors,
|
||||
strdup(name));
|
||||
|
||||
/* FIXME: Clean up. */
|
||||
snprintf(buf, EXACTNESS_PATH_MAX,
|
||||
"compare '%s' '%s' '%s/%s/comp_%s'",
|
||||
filename1, filename2,
|
||||
exactness_config.dest_dir,
|
||||
CURRENT_SUBDIR, name);
|
||||
if (system(buf))
|
||||
{
|
||||
fprintf(stderr, "Failed image comparing '%s'\n", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -728,6 +728,114 @@ multi_move_desc_make(void)
|
|||
return _d;
|
||||
}
|
||||
|
||||
Eet_Data_Descriptor *
|
||||
object_info_desc_make(void)
|
||||
{
|
||||
Eet_Data_Descriptor_Class eddc;
|
||||
static Eet_Data_Descriptor *info_d = NULL;
|
||||
if (!info_d)
|
||||
{
|
||||
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Object_Info);
|
||||
info_d = eet_data_descriptor_stream_new(&eddc);
|
||||
EET_DATA_DESCRIPTOR_ADD_BASIC(info_d, Object_Info, "kl_name", kl_name, EET_T_STRING);
|
||||
EET_DATA_DESCRIPTOR_ADD_BASIC(info_d, Object_Info, "id", id, EET_T_UINT);
|
||||
EET_DATA_DESCRIPTOR_ADD_LIST(info_d, Object_Info, "children", children, info_d);
|
||||
/* Evas stuff */
|
||||
EET_DATA_DESCRIPTOR_ADD_BASIC(info_d, Object_Info, "x", x, EET_T_INT);
|
||||
EET_DATA_DESCRIPTOR_ADD_BASIC(info_d, Object_Info, "y", y, EET_T_INT);
|
||||
EET_DATA_DESCRIPTOR_ADD_BASIC(info_d, Object_Info, "w", w, EET_T_INT);
|
||||
EET_DATA_DESCRIPTOR_ADD_BASIC(info_d, Object_Info, "h", h, EET_T_INT);
|
||||
}
|
||||
|
||||
return info_d;
|
||||
}
|
||||
|
||||
#define INFO_CHECK(i1, i2, obj_path, var) \
|
||||
({ \
|
||||
Eina_Bool _ret = EINA_TRUE; \
|
||||
if (i1->var != i2->var) \
|
||||
{ \
|
||||
if (verbose) fprintf(stderr, "%s value is different for %s: %d-%d\n", #var, obj_path, i1->var, i2->var); \
|
||||
_ret = EINA_FALSE; \
|
||||
} \
|
||||
_ret; \
|
||||
})
|
||||
|
||||
|
||||
static Eina_Bool
|
||||
_object_info_compare(Object_Info *info1, Object_Info *info2, Eina_Bool verbose, const char *path)
|
||||
{
|
||||
/* The caller has to give 2 infos whose kl_name and id are respectively the same */
|
||||
Eina_List *itr1, *itr2;
|
||||
Object_Info *c1, *c2;
|
||||
int cnt1, cnt2;
|
||||
Eina_Bool ret = EINA_TRUE;
|
||||
char fpath[512];
|
||||
if (!info1 || !info2) return EINA_FALSE;
|
||||
if (info1->kl_name)
|
||||
sprintf(fpath, "%s/%s_%d", path, info1->kl_name, info1->id);
|
||||
else
|
||||
*fpath = '\0';
|
||||
|
||||
ret &= INFO_CHECK(info1, info2, fpath, x);
|
||||
ret &= INFO_CHECK(info1, info2, fpath, y);
|
||||
ret &= INFO_CHECK(info1, info2, fpath, w);
|
||||
ret &= INFO_CHECK(info1, info2, fpath, h);
|
||||
|
||||
cnt1 = eina_list_count(info1->children);
|
||||
cnt2 = eina_list_count(info2->children);
|
||||
if (cnt1 != cnt2 && verbose)
|
||||
fprintf(stderr, "Object %s - number of children differs (%d - %d)\n", fpath, cnt1, cnt2);
|
||||
EINA_LIST_FOREACH(info1->children, itr1, c1)
|
||||
{
|
||||
Eina_Bool found = EINA_FALSE;
|
||||
if (!verbose && !ret) goto end;
|
||||
EINA_LIST_FOREACH(info2->children, itr2, c2)
|
||||
{
|
||||
if (!found && c1->id == c2->id && c1->kl_name == c2->kl_name)
|
||||
{
|
||||
found = EINA_TRUE;
|
||||
ret &= _object_info_compare(c1, c2, verbose, fpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
objects_files_compare(const char *filename1, const char *filename2, Eina_Bool verbose)
|
||||
{
|
||||
Eina_Bool ret = EINA_FALSE;
|
||||
Eet_File *f1, *f2;
|
||||
Eet_Data_Descriptor *desc = NULL;
|
||||
Object_Info *lst1 = NULL, *lst2 = NULL;
|
||||
|
||||
f1 = eet_open(filename1, EET_FILE_MODE_READ);
|
||||
f2 = eet_open(filename2, EET_FILE_MODE_READ);
|
||||
desc = object_info_desc_make();
|
||||
if (!f1 || !f2)
|
||||
{
|
||||
if (verbose) fprintf(stderr, "Can't open %s\n", !f1?filename1:filename2);
|
||||
goto end;
|
||||
}
|
||||
|
||||
lst1 = eet_data_read(f1, desc, "entry");
|
||||
lst2 = eet_data_read(f2, desc, "entry");
|
||||
if (!lst1 || !lst2)
|
||||
{
|
||||
if (verbose) fprintf(stderr, "Can't decode %s data\n", !lst1?filename1:filename2);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = _object_info_compare(lst1, lst2, verbose, NULL);
|
||||
end:
|
||||
if (desc) eet_data_descriptor_free(desc);
|
||||
if (f1) eet_close(f1);
|
||||
if (f2) eet_close(f2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* declaring types */
|
||||
data_desc *_data_descriptors_init(void)
|
||||
{
|
||||
|
|
|
@ -245,6 +245,28 @@ data_desc *_data_descriptors_init(void);
|
|||
void _data_descriptors_shutdown(void);
|
||||
/* END Event struct descriptors */
|
||||
|
||||
/* START Objects */
|
||||
typedef struct
|
||||
{
|
||||
Eo *object;
|
||||
Eo *parent;
|
||||
const char *kl_name;
|
||||
Eina_List *children;
|
||||
int id;
|
||||
|
||||
/* Evas stuff */
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
} Object_Info;
|
||||
|
||||
Eet_Data_Descriptor *object_info_desc_make(void);
|
||||
|
||||
EAPI Eina_Bool objects_files_compare(const char *filename1, const char *filename2, Eina_Bool verbose);
|
||||
/* END Objects */
|
||||
|
||||
|
||||
Tsuite_Event_Type tsuite_event_mapping_type_get(const char *name);
|
||||
const char * tsuite_event_mapping_type_str_get(Tsuite_Event_Type t);
|
||||
const char * _variant_type_get(const void *data, Eina_Bool *unknow);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#define TSUITE_MAX_PATH 1024
|
||||
#define IMAGE_FILENAME_EXT ".png"
|
||||
#define OBJECTS_FILENAME_EXT ".eet"
|
||||
|
||||
struct _evas_hook_setting
|
||||
{
|
||||
|
@ -25,6 +26,7 @@ struct _evas_hook_setting
|
|||
char *test_name;
|
||||
char *file_name;
|
||||
Eina_Bool verbose;
|
||||
Eina_Bool store_objects;
|
||||
};
|
||||
typedef struct _evas_hook_setting evas_hook_setting;
|
||||
|
||||
|
@ -34,6 +36,15 @@ static Tsuite_Data ts;
|
|||
static Eina_List *evas_list = NULL; /* List of Evas pointers */
|
||||
static int ignore_evas_new = 0; /* Counter to know if we should ignore evas new or not. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *kl_name;
|
||||
int last;
|
||||
} Main_Widget_Id;
|
||||
static Eina_List *_main_widget_ids = NULL;
|
||||
static Object_Info _widgets_list = {0};
|
||||
static void _objects_snapshot_do();
|
||||
|
||||
static void
|
||||
_tsuite_verbosef(const char *fmt, ...)
|
||||
{
|
||||
|
@ -85,7 +96,6 @@ _shot_do(char *name, Evas *e)
|
|||
filename = malloc(strlen(_hook_setting->test_name) + strlen(IMAGE_FILENAME_EXT) +
|
||||
dir_name_len + 8); /* also space for serial */
|
||||
|
||||
ts.serial++;
|
||||
if (_hook_setting->dest_dir)
|
||||
sprintf(filename, "%s/", _hook_setting->dest_dir);
|
||||
|
||||
|
@ -142,6 +152,7 @@ ecore_init(void)
|
|||
_hook_setting->dest_dir = getenv("TSUITE_DEST_DIR");
|
||||
_hook_setting->test_name = getenv("TSUITE_TEST_NAME");
|
||||
_hook_setting->file_name = getenv("TSUITE_FILE_NAME");
|
||||
_hook_setting->store_objects = !!getenv("TSUITE_STORE_OBJECTS");
|
||||
tmp = getenv("TSUITE_VERBOSE");
|
||||
if (tmp)
|
||||
_hook_setting->verbose = atoi(tmp);
|
||||
|
@ -459,10 +470,12 @@ tsuite_feed_event(void *data)
|
|||
printf("%s take shot timestamp=<%u> t->n_evas=<%d>\n", __func__, t->timestamp, t->n_evas);
|
||||
#endif
|
||||
if (rect) evas_object_color_set(rect, 0, 0, 255, 255);
|
||||
ts.serial++;
|
||||
if (_hook_setting->dest_dir)
|
||||
{
|
||||
_shot_do(NULL,
|
||||
eina_list_nth(evas_list, t->n_evas)); /* Serial name based on test-name */
|
||||
if (_hook_setting->store_objects) _objects_snapshot_do();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -547,3 +560,149 @@ ecore_main_loop_begin(void)
|
|||
|
||||
return _ecore_main_loop_begin();
|
||||
}
|
||||
|
||||
static void
|
||||
_obj_del(void *data EINA_UNUSED, const Efl_Event *event)
|
||||
{
|
||||
Eo *parent = efl_parent_get(event->object);
|
||||
Object_Info *info = efl_key_data_get(event->object, "exactness_info");
|
||||
if (parent)
|
||||
{
|
||||
Object_Info *parent_info = parent ? efl_key_data_get(parent, "exactness_info") : NULL;
|
||||
if (parent_info) parent_info->children = eina_list_remove(parent_info->children, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
_widgets_list.children = eina_list_remove(_widgets_list.children, info);
|
||||
}
|
||||
efl_key_data_set(event->object, "exactness_info", NULL);
|
||||
eina_stringshare_del(info->kl_name);
|
||||
free(info);
|
||||
}
|
||||
|
||||
EAPI Eo *
|
||||
_efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, Eo *parent_id, Eina_Bool ref, Eina_Bool is_fallback)
|
||||
{
|
||||
Eo *(*foo)(const char *, int, const Efl_Class *, Eo *, Eina_Bool, Eina_Bool) =
|
||||
dlsym(RTLD_NEXT, __FUNCTION__);
|
||||
Eo *ret = foo(file, line, klass_id, parent_id, ref, is_fallback);
|
||||
|
||||
if (!efl_isa(ret, EFL_CANVAS_INTERFACE) && !efl_isa(ret, EFL_CANVAS_OBJECT_CLASS)) goto end;
|
||||
|
||||
efl_event_callback_add(ret, EFL_EVENT_DEL, _obj_del, NULL);
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
EOAPI void
|
||||
efl_parent_set(Eo *obj, Efl_Object *new_parent)
|
||||
{
|
||||
void (*foo)(Eo *, Efl_Object *) = dlsym(RTLD_NEXT, __FUNCTION__);
|
||||
Object_Info *info = NULL;
|
||||
if (!efl_isa(obj, EFL_CANVAS_INTERFACE) && !efl_isa(obj, EFL_CANVAS_OBJECT_CLASS)) goto end;
|
||||
|
||||
info = efl_key_data_get(obj, "exactness_info");
|
||||
if (!info)
|
||||
{
|
||||
info = calloc(1, sizeof(*info));
|
||||
info->object = obj;
|
||||
info->kl_name = eina_stringshare_add(efl_class_name_get(obj));
|
||||
efl_key_data_set(obj, "exactness_info", info);
|
||||
}
|
||||
|
||||
Eo *old_parent = efl_parent_get(obj);
|
||||
if (info->id && old_parent == new_parent) goto end;
|
||||
if (old_parent)
|
||||
{
|
||||
Object_Info *old_parent_info = efl_key_data_get(old_parent, "exactness_info");
|
||||
if (old_parent_info)
|
||||
old_parent_info->children = eina_list_remove(old_parent_info->children, info);
|
||||
|
||||
int last_parent_id = (intptr_t)efl_key_data_get(old_parent, info->kl_name);
|
||||
if (info->id && last_parent_id == info->id)
|
||||
efl_key_data_set(old_parent, info->kl_name, (void *)(intptr_t)(last_parent_id - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
Eina_List *itr;
|
||||
Main_Widget_Id *wid;
|
||||
EINA_LIST_FOREACH(_main_widget_ids, itr, wid)
|
||||
{
|
||||
if (info->kl_name == wid->kl_name) goto found_old_parent;
|
||||
}
|
||||
wid = NULL;
|
||||
found_old_parent:
|
||||
if (wid && wid->last == info->id) wid->last--;
|
||||
_widgets_list.children = eina_list_remove(_widgets_list.children, info);
|
||||
}
|
||||
info->id = 0;
|
||||
info->parent = new_parent;
|
||||
if (new_parent)
|
||||
{
|
||||
int last_parent_id = (intptr_t)efl_key_data_get(new_parent, info->kl_name);
|
||||
info->id = ++last_parent_id;
|
||||
efl_key_data_set(new_parent, info->kl_name, (void *)(intptr_t)last_parent_id);
|
||||
|
||||
Object_Info *new_parent_info = efl_key_data_get(new_parent, "exactness_info");
|
||||
if (new_parent_info)
|
||||
new_parent_info->children = eina_list_append(new_parent_info->children, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
Eina_List *itr;
|
||||
Main_Widget_Id *wid;
|
||||
EINA_LIST_FOREACH(_main_widget_ids, itr, wid)
|
||||
{
|
||||
if (info->kl_name == wid->kl_name) goto found_new_parent;
|
||||
}
|
||||
wid = calloc(1, sizeof(*wid));
|
||||
wid->kl_name = info->kl_name;
|
||||
_main_widget_ids = eina_list_append(_main_widget_ids, wid);
|
||||
found_new_parent:
|
||||
info->id = ++wid->last;
|
||||
_widgets_list.children = eina_list_append(_widgets_list.children, info);
|
||||
}
|
||||
end:
|
||||
foo(obj, new_parent);
|
||||
}
|
||||
|
||||
static void
|
||||
_info_fill(Object_Info *info)
|
||||
{
|
||||
Eina_List *itr;
|
||||
if (efl_isa(info->object, EFL_CANVAS_OBJECT_CLASS))
|
||||
evas_object_geometry_get(info->object, &info->x, &info->y, &info->w, &info->h);
|
||||
EINA_LIST_FOREACH(info->children, itr, info)
|
||||
{
|
||||
_info_fill(info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_objects_snapshot_do()
|
||||
{
|
||||
Eina_List *itr;
|
||||
Object_Info *info;
|
||||
int dir_name_len = _hook_setting->dest_dir ? strlen(_hook_setting->dest_dir) + 1 : 0; /* includes space of a '/' */
|
||||
char *filename = malloc(strlen(_hook_setting->test_name) + strlen(OBJECTS_FILENAME_EXT) +
|
||||
dir_name_len + 8); /* also space for serial */
|
||||
|
||||
if (_hook_setting->dest_dir)
|
||||
sprintf(filename, "%s/", _hook_setting->dest_dir);
|
||||
|
||||
sprintf(filename + dir_name_len, "%s%c%03d%s", _hook_setting->test_name,
|
||||
SHOT_DELIMITER, ts.serial, OBJECTS_FILENAME_EXT);
|
||||
|
||||
printf("%d objects saved into %s\n", eina_list_count(_widgets_list.children), filename);
|
||||
|
||||
EINA_LIST_FOREACH(_widgets_list.children, itr, info)
|
||||
{
|
||||
_info_fill(info);
|
||||
}
|
||||
|
||||
Eet_File *file = eet_open(filename, EET_FILE_MODE_WRITE);
|
||||
eet_data_write(file, object_info_desc_make(), "entry", &_widgets_list, EINA_TRUE);
|
||||
eet_close(file);
|
||||
|
||||
free(filename);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue