2017-03-30 15:03:19 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <Eo.h>
|
|
|
|
#include <Eina.h>
|
|
|
|
#include <Elementary.h>
|
2018-06-21 22:40:46 -07:00
|
|
|
#include <Efreet_Mime.h>
|
2017-03-30 15:03:19 -07:00
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include "edi_file.h"
|
|
|
|
#include "edi_searchpanel.h"
|
2018-05-15 08:13:55 -07:00
|
|
|
#include "edi_theme.h"
|
2017-03-30 15:03:19 -07:00
|
|
|
#include "edi_config.h"
|
|
|
|
#include "mainview/edi_mainview.h"
|
|
|
|
|
|
|
|
#include "edi_private.h"
|
|
|
|
|
2017-04-05 11:15:47 -07:00
|
|
|
static Evas_Object *_info_widget, *_tasks_widget;
|
|
|
|
static Elm_Code *_elm_code, *_tasks_code;
|
2017-03-30 15:03:19 -07:00
|
|
|
|
|
|
|
static Ecore_Thread *_search_thread = NULL;
|
|
|
|
static Eina_Bool _searching = EINA_FALSE;
|
|
|
|
static char *_search_text = NULL;
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_edi_searchpanel_config_changed_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
elm_code_widget_font_set(_info_widget, _edi_project_config->font.name, _edi_project_config->font.size);
|
2018-05-15 08:13:55 -07:00
|
|
|
edi_theme_elm_code_set(_info_widget, _edi_project_config->gui.theme);
|
2018-08-06 10:17:35 -07:00
|
|
|
edi_theme_elm_code_alpha_set(_info_widget);
|
2017-03-30 15:03:19 -07:00
|
|
|
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_edi_searchpanel_line_clicked_cb(void *data EINA_UNUSED, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Elm_Code_Line *line;
|
|
|
|
const char *content;
|
|
|
|
unsigned int length;
|
2017-04-05 13:57:06 -07:00
|
|
|
int numlen;
|
|
|
|
char *path, *filename_end;
|
|
|
|
char *line_start, *line_end, *numstr;
|
2017-03-30 15:03:19 -07:00
|
|
|
|
2017-04-05 13:57:06 -07:00
|
|
|
line = (Elm_Code_Line *) event->info;
|
|
|
|
filename_end = line_start = NULL;
|
|
|
|
|
|
|
|
path = strdup(line->data);
|
|
|
|
if (!path) return;
|
2017-03-30 15:03:19 -07:00
|
|
|
|
|
|
|
content = elm_code_line_text_get(line, &length);
|
2017-04-05 13:57:06 -07:00
|
|
|
if (!content)
|
|
|
|
return;
|
2017-03-30 15:03:19 -07:00
|
|
|
|
2017-04-05 13:57:06 -07:00
|
|
|
filename_end = strchr(content, ':');
|
|
|
|
if (!filename_end)
|
|
|
|
return;
|
2017-03-30 15:03:19 -07:00
|
|
|
|
2017-04-05 13:57:06 -07:00
|
|
|
line_start = filename_end + 1;
|
|
|
|
line_end = strchr(line_start, ' ');
|
|
|
|
if (!line_end)
|
|
|
|
return;
|
2017-03-30 15:03:19 -07:00
|
|
|
|
2017-04-05 13:57:06 -07:00
|
|
|
numlen = line_end - line_start;
|
|
|
|
numstr = malloc((numlen + 1) * sizeof(char));
|
|
|
|
strncpy(numstr, line_start, numlen);
|
|
|
|
numstr[numlen] = '\0';
|
|
|
|
|
|
|
|
edi_mainview_open_path(path);
|
|
|
|
edi_mainview_goto(atoi(numstr));
|
|
|
|
|
|
|
|
free(numstr);
|
2017-03-30 15:03:19 -07:00
|
|
|
}
|
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
static char *
|
|
|
|
edi_searchpanel_line_render(const Eina_File_Line *line, const char *path, size_t *length)
|
2017-03-30 15:03:19 -07:00
|
|
|
{
|
2018-06-21 22:40:46 -07:00
|
|
|
Eina_Strbuf *buf = eina_strbuf_new();
|
|
|
|
char *r;
|
|
|
|
const char *text = line->start;
|
|
|
|
const char *end = line->end;
|
2017-03-30 15:03:19 -07:00
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
while (text < end)
|
2017-06-16 03:19:04 -07:00
|
|
|
{
|
2018-06-21 22:40:46 -07:00
|
|
|
if (*text != ' ' && *text != '\t')
|
2017-06-16 03:19:04 -07:00
|
|
|
break;
|
2018-06-21 22:40:46 -07:00
|
|
|
text++;
|
2017-06-16 03:19:04 -07:00
|
|
|
}
|
2017-04-05 13:57:06 -07:00
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
eina_strbuf_append_printf(buf, "%s:%d ->\t", ecore_file_file_get(path), line->index);
|
|
|
|
eina_strbuf_append_length(buf, text, end - text - 1);
|
|
|
|
|
|
|
|
*length = eina_strbuf_length_get(buf);
|
|
|
|
r = eina_strbuf_string_steal(buf);
|
|
|
|
eina_strbuf_free(buf);
|
2017-04-05 13:57:06 -07:00
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
return r;
|
2017-04-05 13:57:06 -07:00
|
|
|
}
|
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
typedef struct _Eina_Iterator_Search Eina_Iterator_Search;
|
|
|
|
|
|
|
|
struct _Eina_Iterator_Search
|
2017-04-05 13:57:06 -07:00
|
|
|
{
|
2018-06-21 22:40:46 -07:00
|
|
|
Eina_Iterator iterator;
|
2017-04-05 13:57:06 -07:00
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
Eina_File *fp;
|
|
|
|
const char *map;
|
|
|
|
const char *end;
|
|
|
|
|
|
|
|
Eina_Stringshare *term;
|
|
|
|
|
|
|
|
Eina_File_Line current;
|
|
|
|
|
|
|
|
int boundary;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Return the starting of the last line found and update the count
|
|
|
|
static inline const char *
|
|
|
|
edi_count_line(const char *start, unsigned int length, const char *line, unsigned int *count)
|
|
|
|
{
|
|
|
|
const char *cr;
|
|
|
|
const char *lf;
|
|
|
|
const char *end;
|
|
|
|
|
|
|
|
if (!length) return line;
|
|
|
|
|
|
|
|
lf = memchr(start, '\r', length);
|
|
|
|
cr = memchr(start, '\n', length);
|
|
|
|
|
|
|
|
if (!cr && !lf) return start;
|
|
|
|
|
|
|
|
end = lf + 1;
|
|
|
|
(*count)++;
|
2017-03-30 15:03:19 -07:00
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
// \r\n
|
|
|
|
if (lf && cr == lf + 1)
|
2017-03-30 15:03:19 -07:00
|
|
|
{
|
2018-06-21 22:40:46 -07:00
|
|
|
end = cr;
|
|
|
|
}
|
|
|
|
// \n
|
|
|
|
else if (cr)
|
|
|
|
{
|
|
|
|
end = cr;
|
|
|
|
}
|
|
|
|
// \r
|
|
|
|
else if (lf)
|
|
|
|
{
|
|
|
|
end = lf;
|
|
|
|
}
|
|
|
|
|
|
|
|
length = length - (end - start);
|
|
|
|
if (length == 0) return start;
|
|
|
|
|
|
|
|
return edi_count_line(end + 1, length - 1, end, count);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline const char *
|
|
|
|
edi_end_of_line(const char *start, int boundary, const char *end)
|
|
|
|
{
|
|
|
|
const char *cr;
|
|
|
|
const char *lf;
|
|
|
|
unsigned long long chunk;
|
|
|
|
|
|
|
|
while (start < end)
|
|
|
|
{
|
|
|
|
chunk = start + boundary < end ? boundary : end - start;
|
|
|
|
lf = memchr(start, '\r', chunk);
|
|
|
|
cr = memchr(start, '\n', chunk);
|
|
|
|
|
|
|
|
// \r\n
|
|
|
|
if (lf && cr == lf + 1)
|
|
|
|
return cr + 1;
|
|
|
|
// \n
|
|
|
|
if (cr)
|
|
|
|
return cr + 1;
|
|
|
|
// \r
|
|
|
|
if (lf)
|
|
|
|
return lf + 1;
|
|
|
|
|
|
|
|
start += chunk;
|
|
|
|
boundary = 4096;
|
|
|
|
}
|
|
|
|
|
|
|
|
return end;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline const char *
|
|
|
|
edi_search_term(const char *start, const char *end, int boundary,
|
|
|
|
Eina_Stringshare *term, Eina_File_Line *line)
|
|
|
|
{
|
|
|
|
char end_of_block = 0;
|
|
|
|
|
|
|
|
while (start < end)
|
|
|
|
{
|
|
|
|
const char *lookup;
|
|
|
|
const char *count;
|
|
|
|
unsigned long long chunk, cchunk;
|
|
|
|
const char *search = start;
|
|
|
|
|
|
|
|
cchunk = chunk = start + boundary < end ? boundary : end - start;
|
|
|
|
do
|
2017-03-30 15:03:19 -07:00
|
|
|
{
|
2018-06-21 22:40:46 -07:00
|
|
|
lookup = memchr(search, *term, cchunk);
|
|
|
|
|
|
|
|
// Did we found the right word or not ?
|
|
|
|
if (lookup && !memcmp(lookup, term, eina_stringshare_strlen(term)))
|
|
|
|
break ;
|
|
|
|
|
|
|
|
if (!lookup)
|
|
|
|
break ;
|
|
|
|
|
|
|
|
// We didn't, start looking from where we are at
|
|
|
|
cchunk -= lookup + 1 - search;
|
|
|
|
search = lookup + 1;
|
2017-03-30 15:03:19 -07:00
|
|
|
}
|
2018-06-21 22:40:46 -07:00
|
|
|
while (cchunk > 0);
|
|
|
|
|
|
|
|
// If not found, we want to count starting from the end all the
|
|
|
|
// line in this chunk.
|
|
|
|
count = lookup ? lookup : start + chunk;
|
|
|
|
|
|
|
|
line->start = edi_count_line(start, count - start, line->start, &line->index);
|
|
|
|
|
|
|
|
// Here we post adjust the counter as we may have double counted a line
|
|
|
|
// if \r\n is exactly at the boundary of a chunk. This also only happen
|
|
|
|
// when we haven't found what we are looking for yet.
|
|
|
|
if (end_of_block == '\r' && *start == '\n')
|
|
|
|
line->index--;
|
|
|
|
|
|
|
|
if (lookup) return lookup;
|
|
|
|
|
|
|
|
end_of_block = *(start + chunk - 1);
|
|
|
|
start += chunk;
|
|
|
|
boundary = 4096;
|
|
|
|
}
|
|
|
|
|
|
|
|
return end;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
edi_search_file_iterator_next(Eina_Iterator_Search *it, void **data)
|
|
|
|
{
|
|
|
|
const char *lookup;
|
|
|
|
int line_boundary;
|
|
|
|
|
|
|
|
if (it->end == it->current.end) return EINA_FALSE;
|
|
|
|
|
|
|
|
// We are starting counting at the end of the line, so we will forget
|
|
|
|
// to account for the line where we found the term we were looking for,
|
|
|
|
// manually adjust for it.
|
|
|
|
// This also work to adjust for the first line as we start at zero
|
|
|
|
it->current.index++;
|
|
|
|
|
|
|
|
// Account for first iteration when end == NULL
|
|
|
|
lookup = edi_search_term(it->current.end ? it->current.end : it->current.start,
|
|
|
|
it->end, it->boundary, it->term, &it->current);
|
|
|
|
|
|
|
|
if (lookup == it->end) return EINA_FALSE;
|
|
|
|
|
|
|
|
line_boundary = (uintptr_t) lookup & 0x3FF;
|
|
|
|
if (!line_boundary) line_boundary = 4096;
|
|
|
|
|
|
|
|
it->current.end = edi_end_of_line(lookup, line_boundary, it->end);
|
|
|
|
// We need to adjust the end position of the line for '\r\n',
|
|
|
|
// in case it is on a cluster boundary.
|
|
|
|
if (*it->current.end == '\r')
|
|
|
|
{
|
|
|
|
if (it->current.end + 1 < it->end &&
|
|
|
|
*(it->current.end + 1) == '\n')
|
|
|
|
it->current.end += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
it->current.length = it->current.end - it->current.start;
|
|
|
|
|
|
|
|
it->boundary = (uintptr_t) it->current.end & 0x3FF;
|
|
|
|
if (!it->boundary) it->boundary = 4096;
|
|
|
|
|
|
|
|
*data = &it->current;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_File *
|
|
|
|
edi_search_file_iterator_container(Eina_Iterator_Search *it)
|
|
|
|
{
|
|
|
|
return it->fp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
edi_search_file_iterator_free(Eina_Iterator_Search *it)
|
|
|
|
{
|
|
|
|
eina_file_map_free(it->fp, (void*) it->map);
|
|
|
|
eina_file_close(it->fp);
|
|
|
|
|
|
|
|
EINA_MAGIC_SET(&it->iterator, 0);
|
|
|
|
free(it);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Iterator *
|
|
|
|
edi_search_file(Eina_File *file, const char *term)
|
|
|
|
{
|
|
|
|
Eina_Iterator_Search *it;
|
|
|
|
size_t length;
|
|
|
|
|
|
|
|
if (!file || !term || strlen(term) == 0) return NULL;
|
|
|
|
|
|
|
|
length = eina_file_size_get(file);
|
|
|
|
|
|
|
|
if (!length) return NULL;
|
|
|
|
|
|
|
|
it = calloc(1, sizeof (Eina_Iterator_Search));
|
|
|
|
if (!it) return NULL;
|
|
|
|
|
|
|
|
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
|
|
|
|
|
|
|
it->map = eina_file_map_all(file, EINA_FILE_SEQUENTIAL);
|
|
|
|
if (!it->map)
|
|
|
|
{
|
|
|
|
free(it);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
it->fp = eina_file_dup(it->fp);
|
|
|
|
it->current.start = it->map;
|
|
|
|
it->current.end = NULL;
|
|
|
|
it->current.index = 0;
|
|
|
|
it->end = it->map + length;
|
|
|
|
it->term = eina_stringshare_add(term);
|
|
|
|
it->boundary = 4096;
|
|
|
|
|
|
|
|
it->iterator.version = EINA_ITERATOR_VERSION;
|
|
|
|
it->iterator.next = FUNC_ITERATOR_NEXT(edi_search_file_iterator_next);
|
|
|
|
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(edi_search_file_iterator_container);
|
|
|
|
it->iterator.free = FUNC_ITERATOR_FREE(edi_search_file_iterator_free);
|
|
|
|
|
|
|
|
return &it->iterator;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
char *text;
|
|
|
|
size_t length;
|
|
|
|
} Async_Item;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
Elm_Code *logger;
|
|
|
|
Eina_File *f;
|
|
|
|
|
|
|
|
Eina_Inarray texts;
|
|
|
|
} Async_Log;
|
|
|
|
|
|
|
|
|
|
|
|
static Eina_Spinlock logs_lock;
|
|
|
|
static unsigned int logs_count = 0;
|
|
|
|
static Eina_Trash *logs = NULL;
|
|
|
|
|
|
|
|
static void
|
|
|
|
main_loop_line_append_async(void *data)
|
|
|
|
{
|
|
|
|
Async_Log *log = data;
|
|
|
|
Async_Item *item;
|
|
|
|
|
|
|
|
while ((item = eina_inarray_pop(&log->texts)))
|
|
|
|
{
|
|
|
|
elm_code_file_line_append(log->logger->file, item->text, item->length,
|
|
|
|
strdup(eina_file_filename_get(log->f)));
|
|
|
|
free(item->text);
|
|
|
|
item->text = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
eina_file_close(log->f);
|
|
|
|
log->f = NULL;
|
|
|
|
log->logger = NULL;
|
|
|
|
// We are keeping the texts array as it won't be touched by Eina_Trash
|
|
|
|
|
|
|
|
eina_spinlock_take(&logs_lock);
|
|
|
|
if (logs_count < 8)
|
|
|
|
{
|
|
|
|
logs_count++;
|
|
|
|
eina_trash_push(&logs, log);
|
|
|
|
log = NULL;
|
2017-03-30 15:03:19 -07:00
|
|
|
}
|
2018-06-21 22:40:46 -07:00
|
|
|
eina_spinlock_release(&logs_lock);
|
2017-03-30 15:03:19 -07:00
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
if (log)
|
|
|
|
{
|
|
|
|
eina_inarray_flush(&log->texts);
|
|
|
|
free(log);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_edi_searchpanel_search_project_file(const char *path, const char *search_term, Elm_Code *logger)
|
|
|
|
{
|
|
|
|
Eina_Iterator *it;
|
|
|
|
Eina_File_Line *l;
|
|
|
|
Async_Log *log;
|
|
|
|
Eina_File *f;
|
|
|
|
|
|
|
|
f = eina_file_open(path, EINA_FALSE);
|
|
|
|
if (!f) return ;
|
|
|
|
|
|
|
|
// If the file looks big, check if it is a text file first.
|
|
|
|
if (eina_file_size_get(f) > 1 * 1024 * 1024 &&
|
|
|
|
strncmp(efreet_mime_type_get(path), "text/", 5))
|
|
|
|
{
|
|
|
|
eina_file_close(f);
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
eina_spinlock_take(&logs_lock);
|
|
|
|
log = eina_trash_pop(&logs);
|
|
|
|
if (log) logs_count--;
|
|
|
|
eina_spinlock_release(&logs_lock);
|
|
|
|
|
|
|
|
if (!log)
|
|
|
|
{
|
|
|
|
log = calloc(1, sizeof (Async_Log));
|
|
|
|
eina_inarray_step_set(&log->texts, sizeof (log->texts),
|
|
|
|
sizeof (Async_Item), 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
log->f = eina_file_dup(f);
|
|
|
|
log->logger = logger;
|
|
|
|
|
|
|
|
it = edi_search_file(f, search_term);
|
|
|
|
EINA_ITERATOR_FOREACH(it, l)
|
|
|
|
{
|
|
|
|
Async_Item *item = eina_inarray_grow(&log->texts, 1);
|
|
|
|
|
|
|
|
item->text = edi_searchpanel_line_render(l, path, &item->length);
|
|
|
|
}
|
|
|
|
eina_iterator_free(it);
|
|
|
|
|
|
|
|
if (eina_inarray_count(&log->texts) == 0)
|
|
|
|
{
|
|
|
|
eina_inarray_flush(&log->texts);
|
|
|
|
eina_file_close(log->f);
|
|
|
|
free(log);
|
|
|
|
log = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (log) ecore_main_loop_thread_safe_call_async(main_loop_line_append_async, log);
|
|
|
|
|
|
|
|
eina_file_close(f);
|
2017-03-30 15:03:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
|
|
|
_file_ignore(const char *filename)
|
|
|
|
{
|
|
|
|
if ((eina_str_has_extension(filename, ".png") ||
|
|
|
|
eina_str_has_extension(filename, ".PNG") ||
|
|
|
|
eina_str_has_extension(filename, ".jpg") ||
|
|
|
|
eina_str_has_extension(filename, ".jpeg") ||
|
|
|
|
eina_str_has_extension(filename, ".JPG") ||
|
2017-05-13 15:31:20 -07:00
|
|
|
eina_str_has_extension(filename, ".JPEG") ||
|
2017-03-30 15:03:19 -07:00
|
|
|
eina_str_has_extension(filename, ".bmp") ||
|
2017-06-16 03:19:04 -07:00
|
|
|
eina_str_has_extension(filename, ".dds") ||
|
2017-04-05 11:15:47 -07:00
|
|
|
eina_str_has_extension(filename, ".tgv") ||
|
2017-03-30 15:03:19 -07:00
|
|
|
eina_str_has_extension(filename, ".eet") ||
|
2017-05-13 15:31:20 -07:00
|
|
|
eina_str_has_extension(filename, ".edj") ||
|
|
|
|
eina_str_has_extension(filename, ".gz") ||
|
|
|
|
eina_str_has_extension(filename, ".bz2") ||
|
2017-05-14 09:53:44 -07:00
|
|
|
eina_str_has_extension(filename, ".xz") ||
|
|
|
|
eina_str_has_extension(filename, ".lzma") ||
|
2017-06-18 14:54:09 -07:00
|
|
|
eina_str_has_extension(filename, ".core") ||
|
2017-05-13 15:31:20 -07:00
|
|
|
eina_str_has_extension(filename, ".zip")
|
2017-03-30 15:03:19 -07:00
|
|
|
))
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-04-05 13:57:06 -07:00
|
|
|
_edi_searchpanel_search_project(const char *directory, const char *search_term, Elm_Code *logger)
|
2017-03-30 15:03:19 -07:00
|
|
|
{
|
2018-06-21 22:40:46 -07:00
|
|
|
Eina_List *dirs;
|
|
|
|
char *dir;
|
2017-03-30 15:03:19 -07:00
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
dirs = eina_list_append(NULL, strdup(directory));
|
2017-03-30 15:03:19 -07:00
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
EINA_LIST_FREE(dirs, dir)
|
2017-03-30 15:03:19 -07:00
|
|
|
{
|
2018-06-21 22:40:46 -07:00
|
|
|
Eina_File_Direct_Info *info;
|
|
|
|
Eina_Iterator *it;
|
2017-03-30 15:03:19 -07:00
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
it = eina_file_stat_ls(dir);
|
|
|
|
EINA_ITERATOR_FOREACH(it, info)
|
2017-03-30 15:03:19 -07:00
|
|
|
{
|
2018-06-21 22:40:46 -07:00
|
|
|
if (_file_ignore(info->path + info->name_start))
|
|
|
|
continue ;
|
|
|
|
|
|
|
|
if (edi_file_path_hidden(info->path))
|
|
|
|
continue ;
|
|
|
|
|
|
|
|
switch (info->type)
|
|
|
|
{
|
|
|
|
case EINA_FILE_REG:
|
|
|
|
{
|
|
|
|
_edi_searchpanel_search_project_file(info->path, search_term, logger);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EINA_FILE_DIR:
|
|
|
|
{
|
|
|
|
dirs = eina_list_append(dirs, strdup(info->path));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
// Ignore all other type
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ecore_thread_check(_search_thread)) break;
|
2017-03-30 15:03:19 -07:00
|
|
|
}
|
2018-06-21 22:40:46 -07:00
|
|
|
eina_iterator_free(it);
|
2017-03-30 15:03:19 -07:00
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
if (ecore_thread_check(_search_thread)) break;
|
|
|
|
free(dir);
|
2017-03-30 15:03:19 -07:00
|
|
|
}
|
2018-06-21 22:40:46 -07:00
|
|
|
|
|
|
|
// Cleanup in case of interuption
|
|
|
|
EINA_LIST_FREE(dirs, dir)
|
|
|
|
free(dir);
|
2017-03-30 15:03:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_search_end_cb(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED)
|
|
|
|
{
|
|
|
|
_search_thread = NULL;
|
|
|
|
_searching = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_search_begin_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
|
|
|
|
{
|
|
|
|
const char *path = data;
|
|
|
|
|
2017-04-05 13:57:06 -07:00
|
|
|
_edi_searchpanel_search_project(path, _search_text, _elm_code);
|
2017-03-30 15:03:19 -07:00
|
|
|
}
|
|
|
|
|
2017-04-05 13:57:06 -07:00
|
|
|
void
|
|
|
|
edi_searchpanel_find(const char *text)
|
2017-03-30 15:03:19 -07:00
|
|
|
{
|
|
|
|
const char *path;
|
|
|
|
|
|
|
|
if (!text || strlen(text) == 0) return;
|
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
if (_searching)
|
|
|
|
{
|
|
|
|
ecore_thread_cancel(_search_thread);
|
|
|
|
while ((ecore_thread_wait(_search_thread, 0.1)) != EINA_TRUE);
|
|
|
|
}
|
2017-03-30 15:03:19 -07:00
|
|
|
|
|
|
|
if (_search_text) free(_search_text);
|
|
|
|
_search_text = strdup(text);
|
|
|
|
|
|
|
|
path = edi_project_get();
|
|
|
|
|
|
|
|
elm_code_file_clear(_elm_code->file);
|
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
_searching = EINA_TRUE;
|
2017-04-05 13:57:06 -07:00
|
|
|
_search_thread = ecore_thread_feedback_run(_search_begin_cb, NULL,
|
2018-06-21 22:40:46 -07:00
|
|
|
_search_end_cb, _search_end_cb,
|
|
|
|
path, EINA_FALSE);
|
2017-03-30 15:03:19 -07:00
|
|
|
}
|
|
|
|
|
2017-04-05 13:57:06 -07:00
|
|
|
void
|
|
|
|
edi_searchpanel_add(Evas_Object *parent)
|
2017-03-30 15:03:19 -07:00
|
|
|
{
|
2018-05-15 05:13:33 -07:00
|
|
|
Evas_Object *frame;
|
2017-03-30 15:03:19 -07:00
|
|
|
Elm_Code_Widget *widget;
|
|
|
|
Elm_Code *code;
|
2018-05-15 05:13:33 -07:00
|
|
|
|
|
|
|
frame = elm_frame_add(parent);
|
|
|
|
elm_object_text_set(frame, _("Search"));
|
|
|
|
evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
|
|
evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
|
|
evas_object_show(frame);
|
|
|
|
|
2017-03-30 15:03:19 -07:00
|
|
|
code = elm_code_create();
|
|
|
|
widget = elm_code_widget_add(parent, code);
|
2018-05-15 08:13:55 -07:00
|
|
|
edi_theme_elm_code_set(widget, _edi_project_config->gui.theme);
|
2017-03-30 15:03:19 -07:00
|
|
|
elm_obj_code_widget_font_set(widget, _edi_project_config->font.name, _edi_project_config->font.size);
|
|
|
|
elm_obj_code_widget_gravity_set(widget, 0.0, 1.0);
|
|
|
|
efl_event_callback_add(widget, ELM_OBJ_CODE_WIDGET_EVENT_LINE_CLICKED, _edi_searchpanel_line_clicked_cb, NULL);
|
|
|
|
evas_object_size_hint_weight_set(widget, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
|
|
evas_object_size_hint_align_set(widget, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
|
|
evas_object_show(widget);
|
|
|
|
|
|
|
|
_elm_code = code;
|
|
|
|
_info_widget = widget;
|
2018-06-21 22:40:46 -07:00
|
|
|
eina_spinlock_new(&logs_lock);
|
2017-03-30 15:03:19 -07:00
|
|
|
|
2018-05-15 05:13:33 -07:00
|
|
|
elm_object_content_set(frame, widget);
|
|
|
|
elm_box_pack_end(parent, frame);
|
|
|
|
|
2017-03-30 15:03:19 -07:00
|
|
|
ecore_event_handler_add(EDI_EVENT_CONFIG_CHANGED, _edi_searchpanel_config_changed_cb, NULL);
|
|
|
|
}
|
|
|
|
|
2017-04-05 11:15:47 -07:00
|
|
|
static void
|
|
|
|
_edi_taskspanel_line_cb(void *data EINA_UNUSED, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Elm_Code_Line *line;
|
|
|
|
|
|
|
|
line = (Elm_Code_Line *)event->info;
|
|
|
|
|
2017-04-05 13:57:06 -07:00
|
|
|
line->status = ELM_CODE_STATUS_TYPE_TODO;
|
2017-04-05 11:15:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_edi_taskspanel_config_changed_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
elm_code_widget_font_set(_tasks_widget, _edi_project_config->font.name, _edi_project_config->font.size);
|
2018-05-15 08:13:55 -07:00
|
|
|
edi_theme_elm_code_set(_tasks_widget, _edi_project_config->gui.theme);
|
2018-08-06 10:17:35 -07:00
|
|
|
edi_theme_elm_code_alpha_set(_tasks_widget);
|
2017-04-05 11:15:47 -07:00
|
|
|
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define _edi_taskspanel_line_clicked_cb _edi_searchpanel_line_clicked_cb
|
|
|
|
|
|
|
|
static void
|
|
|
|
_tasks_begin_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
|
|
|
|
{
|
|
|
|
const char *path = data;
|
|
|
|
|
2017-04-05 13:57:06 -07:00
|
|
|
_edi_searchpanel_search_project(path, "TODO", _tasks_code);
|
2017-04-05 11:15:47 -07:00
|
|
|
if (ecore_thread_check(_search_thread)) return;
|
2017-04-05 13:57:06 -07:00
|
|
|
_edi_searchpanel_search_project(path, "FIXME", _tasks_code);
|
2017-04-05 11:15:47 -07:00
|
|
|
if (ecore_thread_check(_search_thread)) return;
|
|
|
|
}
|
|
|
|
|
2017-04-05 13:57:06 -07:00
|
|
|
void
|
|
|
|
edi_taskspanel_find(void)
|
2017-04-05 11:15:47 -07:00
|
|
|
{
|
|
|
|
const char *path;
|
|
|
|
if (_searching) return;
|
|
|
|
|
|
|
|
elm_code_file_clear(_tasks_code->file);
|
|
|
|
|
|
|
|
path = edi_project_get();
|
|
|
|
|
2018-06-21 22:40:46 -07:00
|
|
|
if (_searching)
|
|
|
|
{
|
|
|
|
ecore_thread_cancel(_search_thread);
|
|
|
|
while ((ecore_thread_wait(_search_thread, 0.1)) != EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
2017-04-05 13:57:06 -07:00
|
|
|
_search_thread = ecore_thread_feedback_run(_tasks_begin_cb, NULL,
|
2018-06-21 22:40:46 -07:00
|
|
|
_search_end_cb, _search_end_cb,
|
2017-04-05 11:15:47 -07:00
|
|
|
path, EINA_FALSE);
|
|
|
|
}
|
|
|
|
|
2017-04-05 13:57:06 -07:00
|
|
|
void
|
|
|
|
edi_taskspanel_add(Evas_Object *parent)
|
2017-04-05 11:15:47 -07:00
|
|
|
{
|
2018-05-15 05:13:33 -07:00
|
|
|
Evas_Object *frame;
|
2017-04-05 11:15:47 -07:00
|
|
|
Elm_Code_Widget *widget;
|
|
|
|
Elm_Code *code;
|
2018-05-15 05:13:33 -07:00
|
|
|
|
|
|
|
frame = elm_frame_add(parent);
|
|
|
|
elm_object_text_set(frame, _("Tasks"));
|
|
|
|
evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
|
|
evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
|
|
evas_object_show(frame);
|
|
|
|
|
2017-04-05 11:15:47 -07:00
|
|
|
code = elm_code_create();
|
|
|
|
widget = elm_code_widget_add(parent, code);
|
2018-05-15 08:13:55 -07:00
|
|
|
edi_theme_elm_code_set(widget, _edi_project_config->gui.theme);
|
2017-04-05 11:15:47 -07:00
|
|
|
elm_obj_code_widget_font_set(widget, _edi_project_config->font.name, _edi_project_config->font.size);
|
|
|
|
elm_obj_code_widget_gravity_set(widget, 0.0, 1.0);
|
|
|
|
efl_event_callback_add(widget, &ELM_CODE_EVENT_LINE_LOAD_DONE, _edi_taskspanel_line_cb, NULL);
|
|
|
|
efl_event_callback_add(widget, ELM_OBJ_CODE_WIDGET_EVENT_LINE_CLICKED, _edi_taskspanel_line_clicked_cb, NULL);
|
|
|
|
evas_object_size_hint_weight_set(widget, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
|
|
|
|
evas_object_size_hint_align_set(widget, EVAS_HINT_FILL, EVAS_HINT_FILL);
|
|
|
|
evas_object_show(widget);
|
|
|
|
|
|
|
|
_tasks_code = code;
|
|
|
|
_tasks_widget = widget;
|
|
|
|
|
2018-05-15 05:13:33 -07:00
|
|
|
elm_object_content_set(frame, widget);
|
|
|
|
elm_box_pack_end(parent, frame);
|
|
|
|
|
2017-04-05 11:15:47 -07:00
|
|
|
ecore_event_handler_add(EDI_EVENT_CONFIG_CHANGED, _edi_taskspanel_config_changed_cb, NULL);
|
|
|
|
|
|
|
|
edi_taskspanel_find();
|
|
|
|
}
|
|
|
|
|