fix genlist/grid search item patch to be simpler and just better

better - why?

1. no reliance on fnmatrch headers - have special enums for this so
fnmatch is an internal detail (casefole may not exist)
2. don't leak strduped strings - free them when done
3. have the same code for genlist and grid (dup for now until an
interface makes it the same search interface)
4. improve docs
5. get right @since version
6. use label get func in item class - providing a func won't work when
multiple items of multiple classes exist in the list
This commit is contained in:
Carsten Haitzler 2014-07-24 12:41:33 +09:00
parent e455a0f640
commit e741a19b21
7 changed files with 105 additions and 93 deletions

View File

@ -1380,21 +1380,12 @@ static const char *_grid5_items_text[] = {
"Topeka", "Trenton"
};
static char *
_grid5_search_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED)
{
char buf[32];
Item_Data *id = data;
snprintf(buf, sizeof(buf), "%s", _grid5_items_text[id->mode]);
return strdup(buf);
}
static char *
_grid5_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED)
{
Item_Data *id = data;
char buf[64];
snprintf(buf, sizeof(buf), "%s", _grid5_search_text_get(data, NULL, NULL));
snprintf(buf, sizeof(buf), "%s", _grid5_items_text[id->mode]);
return strdup(buf);
}
@ -1405,7 +1396,8 @@ _grid5_search_item(grid5_Event_Data *event_data, Elm_Object_Item * it)
if (!str || !strlen(str)) return;
printf("Looking for \"%s\". ", str);
event_data->last_item_found = elm_gengrid_search_by_text_item_get(event_data->grid_obj, it, _grid5_search_text_get, NULL, str, 0);
event_data->last_item_found = elm_gengrid_search_by_text_item_get
(event_data->grid_obj, it, NULL, str, 0);
if (event_data->last_item_found)
{

View File

@ -3508,8 +3508,8 @@ static const char *_gl20_items_text[] = {
"Topeka", "Trenton" };
static char *
_gl20_search_text_get(void *data, Evas_Object *obj EINA_UNUSED,
const char *part EINA_UNUSED)
_gl20_text_get(void *data, Evas_Object *obj EINA_UNUSED,
const char *part EINA_UNUSED)
{
char buf[32];
int item_index = (int)(uintptr_t)data;
@ -3530,29 +3530,18 @@ _gl20_search_text_get(void *data, Evas_Object *obj EINA_UNUSED,
return NULL;
}
static char *
_gl20_text_get(void *data, Evas_Object *obj EINA_UNUSED,
const char *part EINA_UNUSED)
{
char buf[64];
snprintf(buf, sizeof(buf), "(this text is not uset for search) %s",
_gl20_search_text_get(data, NULL, NULL));
return strdup(buf);
}
static void
_gl20_searsh_item(gl20_Event_Data *event_data, Elm_Object_Item * it)
_gl20_search_item(gl20_Event_Data *event_data, Elm_Object_Item * it)
{
const char *str = elm_entry_entry_get(event_data->en_obj);
if (!str || !strlen(str)) return;
int flag = 0;
if (!elm_check_state_get(event_data->tg_obj))
flag = FNM_CASEFOLD;
Elm_Glob_Match_Flags flag = 0;
if (!elm_check_state_get(event_data->tg_obj)) flag = ELM_GLOB_MATCH_NOCASE;
printf("Looking for \"%s\". ", str);
event_data->last_item_found = elm_genlist_search_by_text_item_get(event_data->gl_obj,
it, _gl20_search_text_get, NULL, str, flag);
event_data->last_item_found = elm_genlist_search_by_text_item_get
(event_data->gl_obj, it, NULL, str, flag);
if (event_data->last_item_found)
{
@ -3570,7 +3559,7 @@ static void
_gl20_search_settings_changed_cb(void *data, Evas_Object *obj EINA_UNUSED,
void *einfo EINA_UNUSED)
{
_gl20_searsh_item(data, NULL);
_gl20_search_item(data, NULL);
}
static Elm_Genlist_Item_Class *
@ -3616,7 +3605,7 @@ static void _gl20_on_keydown(void *data, Evas *evas EINA_UNUSED,
if (!strcmp(ev->key, "Return"))
{
printf("Looking for next item\n");
_gl20_searsh_item(data, event_data->last_item_found);
_gl20_search_item(data, event_data->last_item_found);
}
}

View File

@ -61,3 +61,11 @@ struct _Elm_Gen_Item_Class
#define ELM_GEN_ITEM_CLASS_VERSION 2
#define ELM_GEN_ITEM_CLASS_HEADER ELM_GEN_ITEM_CLASS_VERSION, 0, 0
typedef enum
{
ELM_GLOB_MATCH_NO_ESCAPE = (1 << 0), /**< Treat backslash as an ordinary character instead of escape */
ELM_GLOB_MATCH_PATH = (1 << 1), /**< Match a slash in string only with a slash in pattern and not by an asterisk (*) or a question mark (?) metacharacter, nor by a bracket expression ([]) containing a slash. */
ELM_GLOB_MATCH_PERIOD = (1 << 2), /**< Leading period in string has to be matched exactly by a period in pattern. A period is considered to be leading if it is the first character in string, or if both ELM_GLOB_MATCH_PATH is set and the period immediately follows a slash. */
ELM_GLOB_MATCH_NOCASE = (1 << 3) /**< The pattern is matched case-insensitively. */
} Elm_Glob_Match_Flags; /**< Glob matching bitfiled flags. @since 1.11 */

View File

@ -105,24 +105,41 @@ static const Elm_Action key_actions[] = {
EOLIAN static Elm_Object_Item *
_elm_gengrid_search_by_text_item_get(Eo *obj EINA_UNUSED,
Elm_Gengrid_Data *sd,
Elm_Object_Item * item_to_search_from,
Elm_Gen_Item_Text_Get_Cb _text_get,
const char * part_name,
const char * pattern,
int flags)
Elm_Object_Item *item_to_search_from,
const char *part_name,
const char *pattern,
Elm_Glob_Match_Flags flags)
{
Elm_Gen_Item *it = NULL;
const char * str = NULL;
Eina_Inlist * start = NULL;
char *str = NULL;
Eina_Inlist *start = NULL;
int fnflags = 0;
if (!_text_get || !pattern) return NULL;
if (!pattern) return NULL;
if (!sd->items) return NULL;
start = (item_to_search_from) ? EINA_INLIST_GET((Elm_Gen_Item *)item_to_search_from) : sd->items;
if (flags & ELM_GLOB_MATCH_NO_ESCAPE) fnflags |= FNM_NOESCAPE;
if (flags & ELM_GLOB_MATCH_PATH) fnflags |= FNM_PATHNAME;
if (flags & ELM_GLOB_MATCH_PERIOD) fnflags |= FNM_PERIOD;
#ifdef FNM_CASEFOLD
if (flags & ELM_GLOB_MATCH_NOCASE) fnflags |= FNM_CASEFOLD;
#endif
start = (item_to_search_from) ?
EINA_INLIST_GET((Elm_Gen_Item *)item_to_search_from) :
sd->items;
EINA_INLIST_FOREACH(start, it)
{
str = _text_get((void *)it->base.data, VIEW(it), part_name);
if (!fnmatch(pattern, str, flags)) return (Elm_Object_Item *)it;
if (!it->itc->func.text_get) continue;
str = it->itc->func.text_get((void *)it->base.data,
VIEW(it), part_name);
if (!str) continue;
if (!fnmatch(pattern, str, fnflags))
{
free(str);
return (Elm_Object_Item *)it;
}
free(str);
}
return NULL;
}

View File

@ -656,14 +656,28 @@ class Elm_Gengrid (Elm_Layout, Elm_Interface_Scrollable, Evas.Clickable_Interfac
@in const(void)* func_data; /*@ Data to be passed to @p func. */
}
}
search_by_text_item_get {
search_by_text_item_get {
/*@
Get gengrid item by given string.
@return Pointer to the gengrid item which matches search_string in case of success, otherwise returns NULL.
It takes pointer to the gengrid item that will be used to start
search from it.
This function uses globs (like "*.jpg") for searching and takes
search flags as last parameter That is a bitfield with values
to be ored together or 0 for no flags.
@ingroup Gengrid
@since 1.11 */
return Elm_Object_Item *;
params {
@in Elm_Object_Item * item_to_search_from; /*@ Pointer to item to start search from. If NULL search will be started from the first item of the genlist. */
@in Elm_Gen_Item_Text_Get_Cb _text_get; /*@ Pointer to Elm_Gen_Item_Text_Get_Cb function to get text for comparison. */
@in const(char)* part_name; /*@ Name of the TEXT part of genlist item to search string in. */
@in const(char)* pattern; /*@ The search pattern. */
@in int flags; /*@ fnmatch search flags */
@in Elm_Object_Item *item_to_search_from; /*@ Pointer to item to start search from. If NULL search will be started from the first item of the gengrid. */
@in const(char) *part_name; /*@ Name of the TEXT part of gengrid item to search string in. */
@in const(char) *pattern; /*@ The search pattern. */
@in Elm_Glob_Match_Flags flags; /*@ Search flags */
}
}
}

View File

@ -7547,28 +7547,41 @@ _elm_genlist_elm_widget_focus_highlight_geometry_get(Eo *obj EINA_UNUSED, Elm_Ge
EOLIAN static Elm_Object_Item *
_elm_genlist_search_by_text_item_get(Eo *obj EINA_UNUSED,
Elm_Genlist_Data *sd,
Elm_Object_Item * item_to_search_from,
Elm_Gen_Item_Text_Get_Cb _text_get,
const char * part_name,
const char * pattern,
int flags)
Elm_Object_Item *item_to_search_from,
const char *part_name,
const char *pattern,
Elm_Glob_Match_Flags flags)
{
Elm_Gen_Item *it = NULL;
const char * str = NULL;
Eina_Bool search_flag = (item_to_search_from) ? EINA_FALSE : EINA_TRUE;
char *str = NULL;
Eina_Inlist *start = NULL;
int fnflags = 0;
if (!_text_get || !pattern) return NULL;
if (!pattern) return NULL;
if (!sd->items) return NULL;
EINA_INLIST_FOREACH(sd->items, it)
if (flags & ELM_GLOB_MATCH_NO_ESCAPE) fnflags |= FNM_NOESCAPE;
if (flags & ELM_GLOB_MATCH_PATH) fnflags |= FNM_PATHNAME;
if (flags & ELM_GLOB_MATCH_PERIOD) fnflags |= FNM_PERIOD;
#ifdef FNM_CASEFOLD
if (flags & ELM_GLOB_MATCH_NOCASE) fnflags |= FNM_CASEFOLD;
#endif
start = (item_to_search_from) ?
EINA_INLIST_GET((Elm_Gen_Item *)item_to_search_from) :
sd->items;
EINA_INLIST_FOREACH(start, it)
{
if (search_flag)
if (!it->itc->func.text_get) continue;
str = it->itc->func.text_get((void *)it->base.data,
VIEW(it), part_name);
if (!str) continue;
if (!fnmatch(pattern, str, fnflags))
{
str = _text_get((void *)it->base.data, VIEW(it), part_name);
if (!fnmatch(pattern, str, flags)) return (Elm_Object_Item *)it;
free(str);
return (Elm_Object_Item *)it;
}
else if (item_to_search_from == (Elm_Object_Item *)it)
search_flag = EINA_TRUE;
free(str);
}
return NULL;
}

View File

@ -683,43 +683,22 @@ class Elm_Genlist (Elm_Layout, Elm_Interface_Scrollable, Evas.Clickable_Interfac
@return Pointer to the genlist item which matches search_string in case of success, otherwise returns NULL.
This function takes pointer to the function that returns
comparison string for item (it could be the same function as used for setting text for labels).
Also it takes pointer to the genlist item that will be used to start search from it.
It takes pointer to the genlist item that will be used to start
search from it.
This function uses fnmatch() for searching and takes it's seatcing flags as last parameter.
The list of available flags:
<dl>
<dt>FNM_NOESCAPE</dt>
<dd>If this flag is set, treat backslash as an ordinary character, instead of an escape character.</dd>
<dt>FNM_PATHNAME</dt>
<dd>If this flag is set, match a slash in string only with a slash in pattern and not by an asterisk (*)
or a question mark (?) metacharacter, nor by a bracket expression ([]) containing a slash.</dd>
<dt>FNM_PERIOD</dt>
<dd>If this flag is set, a leading period in string has to be matched exactly by a period in pattern.
A period is considered to be leading if it is the first character in string, or if both
FNM_PATHNAME is set and the period immediately follows a slash.</dd>
<dt>FNM_FILE_NAME</dt>
<dd>This is a GNU synonym for FNM_PATHNAME.</dd>
<dt>FNM_LEADING_DIR</dt>
<dd>If this flag (a GNU extension) is set, the pattern is considered to be matched if it matches an
initial segment of string which is followed by a slash. This flag is mainly for the internal
use of glibc and is only implemented in certain cases.</dd>
<dt>FNM_CASEFOLD</dt>
<dd>If this flag (a GNU extension) is set, the pattern is matched case-insensitively.</dd>
</dl>
For more details see <a href=http://man7.org/linux/man-pages/man3/fnmatch.3.html>Linux Programmer's Manual. FNMATCH()</a>
This function uses globs (like "*.jpg") for searching and takes
search flags as last parameter That is a bitfield with values
to be ored together or 0 for no flags.
@ingroup Genlist
@since 1.10 */
@since 1.11 */
return Elm_Object_Item *;
params {
@in Elm_Object_Item * item_to_search_from; /*@ Pointer to item to start search from. If NULL search will be started from the first item of the genlist. */
@in Elm_Gen_Item_Text_Get_Cb _text_get; /*@ Pointer to Elm_Gen_Item_Text_Get_Cb function to get text for comparison. */
@in const(char)* part_name; /*@ Name of the TEXT part of genlist item to search string in. */
@in const(char)* pattern; /*@ The search pattern. */
@in int flags; /*@ fnmatch search flags */
@in const(char)* part_name; /*@ Name of the TEXT part of genlist item to search string in. */
@in const(char)* pattern; /*@ The search pattern. */
@in Elm_Glob_Match_Flags flags; /*@ Search flags */
}
}
}