<commit_before>#include <Elementary.h>
#include "elm_priv.h"

/**
 * @defgroup Thumb Thumb
 *
 * A thumb object is used for displaying the thumbnail of an image or video.
 * You must have compiled Elementary with Ethumb_Client support and the DBus
 * service must be present and auto-activated in order to have thumbnails to
 * be generated.
 *
 * Signals that you can add callbacks for are:
 *
 * clicked - This is called when a user has clicked the thumb without dragging
 * around.
 *
 * clicked,double - This is called when a user has double-clicked the thumb.
 *
 * press - This is called when a user has pressed down the thumb.
 *
 * generate,start - The thumbnail generation started.
 *
 * generate,stop - The generation process stopped.
 *
 * generate,error - The generation failed.
 *
 * load,error - The thumbnail image loading failed.
 */

typedef struct _Widget_Data Widget_Data;

struct _Widget_Data
{
   Evas_Object *self;
   Evas_Object *frame;
   Evas_Object *view;
   const char *file;
   const char *key;
   struct
     {
	int id;
	const char *file;
	const char *key;
     } thumb;
   Ecore_Event_Handler *eeh;
   Elm_Thumb_Animation_Setting anim_setting;
   Eina_Bool on_hold : 1;
   Eina_Bool is_video : 1;
   Eina_Bool was_video : 1;
   Eina_Bool edit : 1;

};

static const char *widtype = NULL;

static const char SIG_CLICKED[] = "clicked";
static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
static const char SIG_GENERATE_ERROR[] = "generate,error";
static const char SIG_GENERATE_START[] = "generate,start";
static const char SIG_GENERATE_STOP[] = "generate,stop";
static const char SIG_LOAD_ERROR[] = "load,error";
static const char SIG_PRESS[]= "press";
static const Evas_Smart_Cb_Description _signals[] = {
  {SIG_CLICKED, ""},
  {SIG_CLICKED_DOUBLE, ""},
  {SIG_GENERATE_ERROR, ""},
  {SIG_GENERATE_START, ""},
  {SIG_GENERATE_STOP, ""},
  {SIG_LOAD_ERROR, ""},
  {SIG_PRESS, ""},
  {NULL, NULL}
};

static const char EDJE_SIGNAL_GENERATE_START[] = "elm,thumb,generate,start";
static const char EDJE_SIGNAL_GENERATE_STOP[] = "elm,thumb,generate,stop";
static const char EDJE_SIGNAL_GENERATE_ERROR[] = "elm,thumb,generate,error";
static const char EDJE_SIGNAL_LOAD_ERROR[] = "elm,thumb,load,error";
static const char EDJE_SIGNAL_PULSE_START[] = "elm,state,pulse,start";
static const char EDJE_SIGNAL_PULSE_STOP[] = "elm,state,pulse,stop";

struct _Ethumb_Client *_elm_ethumb_client = NULL;
Eina_Bool _elm_ethumb_connected = EINA_FALSE;

EAPI int ELM_ECORE_EVENT_ETHUMB_CONNECT = 0;

static void
_del_hook(Evas_Object *obj)
{
   Widget_Data *wd = elm_widget_data_get(obj);

#ifdef HAVE_ELEMENTARY_ETHUMB
   if (wd->thumb.id >= 0)
     ethumb_client_generate_cancel(_elm_ethumb_client, wd->thumb.id,
                                   NULL, NULL, NULL);
#endif

   eina_stringshare_del(wd->file);
   eina_stringshare_del(wd->key);
   if (wd->eeh) ecore_event_handler_del(wd->eeh);
   free(wd);
}

static void
_theme_hook(Evas_Object *obj)
{
   Widget_Data *wd = elm_widget_data_get(obj);
   _elm_theme_object_set(obj, wd->frame, "thumb", "base", elm_widget_style_get(obj));
}

#ifdef HAVE_ELEMENTARY_ETHUMB
static void
_mouse_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
{
   Widget_Data *wd = data;
   Evas_Event_Mouse_Down *ev = event_info;
   if (ev->button != 1)
     return;
   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
     wd->on_hold = EINA_TRUE;
   else
     wd->on_hold = EINA_FALSE;
   if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
     evas_object_smart_callback_call(wd->self, SIG_CLICKED_DOUBLE, NULL);
   else
     evas_object_smart_callback_call(wd->self, SIG_PRESS, NULL);
}

static void
_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
{

   Widget_Data *wd = data;
   Evas_Event_Mouse_Up *ev = event_info;
   if (ev->button != 1)
     return;
   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
     wd->on_hold = EINA_TRUE;
   else
     wd->on_hold = EINA_FALSE;
   if (!wd->on_hold)
     evas_object_smart_callback_call(wd->self, SIG_CLICKED, NULL);
   wd->on_hold = EINA_FALSE;
}

static void
_finished_thumb(Widget_Data *wd, const char *thumb_path, const char *thumb_key)
{
   Eina_Bool new_view = EINA_FALSE;
   int r;
   Evas_Coord mw, mh;
   Evas *evas;

   evas = evas_object_evas_get(wd->self);
   if ((wd->view) && (wd->is_video ^ wd->was_video))
     {
	evas_object_del(wd->view);
	wd->view = NULL;
     }
   wd->was_video = wd->is_video;

   if ((wd->is_video) &&
       (ethumb_client_format_get(_elm_ethumb_client) == ETHUMB_THUMB_EET))
     {
	if (!wd->view)
	  {
	     wd->view = edje_object_add(evas);
	     if (!wd->view)
	       {
		  ERR("could not create edje object");
		  goto err;
	       }
	     new_view = EINA_TRUE;
	  }

	if (!edje_object_file_set(wd->view, thumb_path, "movie/thumb"))
	  {
	     ERR("could not set file=%s key=%s for %s", thumb_path, thumb_key,
	         wd->file);
	     goto view_err;
	  }
     }
   else
     {
	if (!wd->view)
	  {
	     wd->view = evas_object_image_filled_add(evas);
	     if (!wd->view)
	       {
		  ERR("could not create image object");
		  goto err;
	       }
	     new_view = EINA_TRUE;
	  }

	evas_object_image_file_set(wd->view, thumb_path, thumb_key);
	r = evas_object_image_load_error_get(wd->view);
	if (r != EVAS_LOAD_ERROR_NONE)
	  {
	     ERR("%s: %s", thumb_path, evas_load_error_str(r));
	     goto view_err;
	  }
     }

   if (new_view) elm_widget_sub_object_add(wd->self, wd->view);
   edje_object_part_swallow(wd->frame, "elm.swallow.content", wd->view);
   edje_object_size_min_get(wd->frame, &mw, &mh);
   edje_object_size_min_restricted_calc(wd->frame, &mw, &mh, mw, mh);
   evas_object_size_hint_min_set(wd->self, mw, mh);
   eina_stringshare_replace(&(wd->thumb.file), thumb_path);
   eina_stringshare_replace(&(wd->thumb.key), thumb_key);
   edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_STOP, "elm");
   evas_object_smart_callback_call(wd->self, SIG_GENERATE_STOP, NULL);
   return;

view_err:
   evas_object_del(wd->view);
   wd->view = NULL;
err:
   edje_object_signal_emit(wd->frame, EDJE_SIGNAL_LOAD_ERROR, "elm");
   evas_object_smart_callback_call(wd->self, SIG_LOAD_ERROR, NULL);
}

static void
_finished_thumb_cb(void *data, Ethumb_Client *c __UNUSED__, int id, const char *file, const char *key, const char *thumb_path, const char *thumb_key, Eina_Bool success)
{
   Widget_Data *wd = data;

   EINA_SAFETY_ON_FALSE_RETURN(wd->thumb.id == id);
   wd->thumb.id = -1;

   edje_object_signal_emit(wd->frame, EDJE_SIGNAL_PULSE_STOP, "elm");

   if (success)
     {
	_finished_thumb(wd, thumb_path, thumb_key);
	return;
     }

   ERR("could not generate thumbnail for %s (key: %s)", file, key ? key : "");
   edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_ERROR, "elm");
   evas_object_smart_callback_call(wd->self, SIG_GENERATE_ERROR, NULL);
}

static void
_thumb_apply(Widget_Data *wd)
{
   ethumb_client_file_set(_elm_ethumb_client, wd->file, wd->key);
   if (ethumb_client_thumb_exists(_elm_ethumb_client))
     {
	const char *thumb_path, *thumb_key;
	wd->thumb.id = -1;
	ethumb_client_thumb_path_get(_elm_ethumb_client, &thumb_path,
				     &thumb_key);
	_finished_thumb(wd, thumb_path, thumb_key);
	return;
     }
   else if ((wd->thumb.id = ethumb_client_generate
	     (_elm_ethumb_client, _finished_thumb_cb, wd, NULL)) != -1)
     {
	edje_object_signal_emit(wd->frame, EDJE_SIGNAL_PULSE_START,
				"elm");
	edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_START,
				"elm");
	evas_object_smart_callback_call(wd->self, SIG_GENERATE_START, NULL);
     }
   else
     {
	wd->thumb.id = -1;
	edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_ERROR,
				"elm");
	evas_object_smart_callback_call(wd->self, SIG_GENERATE_ERROR, NULL);
     }
}

static Eina_Bool
_thumb_apply_cb(void *data, int type __UNUSED__, void *ev __UNUSED__)<commit_msg>cancel previous request, if any.<commit_after>#include <Elementary.h>
#include "elm_priv.h"

/**
 * @defgroup Thumb Thumb
 *
 * A thumb object is used for displaying the thumbnail of an image or video.
 * You must have compiled Elementary with Ethumb_Client support and the DBus
 * service must be present and auto-activated in order to have thumbnails to
 * be generated.
 *
 * Signals that you can add callbacks for are:
 *
 * clicked - This is called when a user has clicked the thumb without dragging
 * around.
 *
 * clicked,double - This is called when a user has double-clicked the thumb.
 *
 * press - This is called when a user has pressed down the thumb.
 *
 * generate,start - The thumbnail generation started.
 *
 * generate,stop - The generation process stopped.
 *
 * generate,error - The generation failed.
 *
 * load,error - The thumbnail image loading failed.
 */

typedef struct _Widget_Data Widget_Data;

struct _Widget_Data
{
   Evas_Object *self;
   Evas_Object *frame;
   Evas_Object *view;
   const char *file;
   const char *key;
   struct
     {
	int id;
	const char *file;
	const char *key;
     } thumb;
   Ecore_Event_Handler *eeh;
   Elm_Thumb_Animation_Setting anim_setting;
   Eina_Bool on_hold : 1;
   Eina_Bool is_video : 1;
   Eina_Bool was_video : 1;
   Eina_Bool edit : 1;

};

static const char *widtype = NULL;

static const char SIG_CLICKED[] = "clicked";
static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
static const char SIG_GENERATE_ERROR[] = "generate,error";
static const char SIG_GENERATE_START[] = "generate,start";
static const char SIG_GENERATE_STOP[] = "generate,stop";
static const char SIG_LOAD_ERROR[] = "load,error";
static const char SIG_PRESS[]= "press";
static const Evas_Smart_Cb_Description _signals[] = {
  {SIG_CLICKED, ""},
  {SIG_CLICKED_DOUBLE, ""},
  {SIG_GENERATE_ERROR, ""},
  {SIG_GENERATE_START, ""},
  {SIG_GENERATE_STOP, ""},
  {SIG_LOAD_ERROR, ""},
  {SIG_PRESS, ""},
  {NULL, NULL}
};

static const char EDJE_SIGNAL_GENERATE_START[] = "elm,thumb,generate,start";
static const char EDJE_SIGNAL_GENERATE_STOP[] = "elm,thumb,generate,stop";
static const char EDJE_SIGNAL_GENERATE_ERROR[] = "elm,thumb,generate,error";
static const char EDJE_SIGNAL_LOAD_ERROR[] = "elm,thumb,load,error";
static const char EDJE_SIGNAL_PULSE_START[] = "elm,state,pulse,start";
static const char EDJE_SIGNAL_PULSE_STOP[] = "elm,state,pulse,stop";

struct _Ethumb_Client *_elm_ethumb_client = NULL;
Eina_Bool _elm_ethumb_connected = EINA_FALSE;

EAPI int ELM_ECORE_EVENT_ETHUMB_CONNECT = 0;

static void
_del_hook(Evas_Object *obj)
{
   Widget_Data *wd = elm_widget_data_get(obj);

#ifdef HAVE_ELEMENTARY_ETHUMB
   if (wd->thumb.id >= 0)
     ethumb_client_generate_cancel(_elm_ethumb_client, wd->thumb.id,
                                   NULL, NULL, NULL);
#endif

   eina_stringshare_del(wd->file);
   eina_stringshare_del(wd->key);
   if (wd->eeh) ecore_event_handler_del(wd->eeh);
   free(wd);
}

static void
_theme_hook(Evas_Object *obj)
{
   Widget_Data *wd = elm_widget_data_get(obj);
   _elm_theme_object_set(obj, wd->frame, "thumb", "base", elm_widget_style_get(obj));
}

#ifdef HAVE_ELEMENTARY_ETHUMB
static void
_mouse_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
{
   Widget_Data *wd = data;
   Evas_Event_Mouse_Down *ev = event_info;
   if (ev->button != 1)
     return;
   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
     wd->on_hold = EINA_TRUE;
   else
     wd->on_hold = EINA_FALSE;
   if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
     evas_object_smart_callback_call(wd->self, SIG_CLICKED_DOUBLE, NULL);
   else
     evas_object_smart_callback_call(wd->self, SIG_PRESS, NULL);
}

static void
_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
{

   Widget_Data *wd = data;
   Evas_Event_Mouse_Up *ev = event_info;
   if (ev->button != 1)
     return;
   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
     wd->on_hold = EINA_TRUE;
   else
     wd->on_hold = EINA_FALSE;
   if (!wd->on_hold)
     evas_object_smart_callback_call(wd->self, SIG_CLICKED, NULL);
   wd->on_hold = EINA_FALSE;
}

static void
_finished_thumb(Widget_Data *wd, const char *thumb_path, const char *thumb_key)
{
   Eina_Bool new_view = EINA_FALSE;
   int r;
   Evas_Coord mw, mh;
   Evas *evas;

   evas = evas_object_evas_get(wd->self);
   if ((wd->view) && (wd->is_video ^ wd->was_video))
     {
	evas_object_del(wd->view);
	wd->view = NULL;
     }
   wd->was_video = wd->is_video;

   if ((wd->is_video) &&
       (ethumb_client_format_get(_elm_ethumb_client) == ETHUMB_THUMB_EET))
     {
	if (!wd->view)
	  {
	     wd->view = edje_object_add(evas);
	     if (!wd->view)
	       {
		  ERR("could not create edje object");
		  goto err;
	       }
	     new_view = EINA_TRUE;
	  }

	if (!edje_object_file_set(wd->view, thumb_path, "movie/thumb"))
	  {
	     ERR("could not set file=%s key=%s for %s", thumb_path, thumb_key,
	         wd->file);
	     goto view_err;
	  }
     }
   else
     {
	if (!wd->view)
	  {
	     wd->view = evas_object_image_filled_add(evas);
	     if (!wd->view)
	       {
		  ERR("could not create image object");
		  goto err;
	       }
	     new_view = EINA_TRUE;
	  }

	evas_object_image_file_set(wd->view, thumb_path, thumb_key);
	r = evas_object_image_load_error_get(wd->view);
	if (r != EVAS_LOAD_ERROR_NONE)
	  {
	     ERR("%s: %s", thumb_path, evas_load_error_str(r));
	     goto view_err;
	  }
     }

   if (new_view) elm_widget_sub_object_add(wd->self, wd->view);
   edje_object_part_swallow(wd->frame, "elm.swallow.content", wd->view);
   edje_object_size_min_get(wd->frame, &mw, &mh);
   edje_object_size_min_restricted_calc(wd->frame, &mw, &mh, mw, mh);
   evas_object_size_hint_min_set(wd->self, mw, mh);
   eina_stringshare_replace(&(wd->thumb.file), thumb_path);
   eina_stringshare_replace(&(wd->thumb.key), thumb_key);
   edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_STOP, "elm");
   evas_object_smart_callback_call(wd->self, SIG_GENERATE_STOP, NULL);
   return;

view_err:
   evas_object_del(wd->view);
   wd->view = NULL;
err:
   edje_object_signal_emit(wd->frame, EDJE_SIGNAL_LOAD_ERROR, "elm");
   evas_object_smart_callback_call(wd->self, SIG_LOAD_ERROR, NULL);
}

static void
_finished_thumb_cb(void *data, Ethumb_Client *c __UNUSED__, int id, const char *file, const char *key, const char *thumb_path, const char *thumb_key, Eina_Bool success)
{
   Widget_Data *wd = data;

   EINA_SAFETY_ON_FALSE_RETURN(wd->thumb.id == id);
   wd->thumb.id = -1;

   edje_object_signal_emit(wd->frame, EDJE_SIGNAL_PULSE_STOP, "elm");

   if (success)
     {
	_finished_thumb(wd, thumb_path, thumb_key);
	return;
     }

   ERR("could not generate thumbnail for %s (key: %s)", file, key ? key : "");
   edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_ERROR, "elm");
   evas_object_smart_callback_call(wd->self, SIG_GENERATE_ERROR, NULL);
}

static void
_thumb_apply(Widget_Data *wd)
{
   if (wd->thumb.id > 0)
     {
        ethumb_client_generate_cancel
          (_elm_ethumb_client, wd->thumb.id, NULL, NULL, NULL);
        wd->thumb.id = -1;
     }

   ethumb_client_file_set(_elm_ethumb_client, wd->file, wd->key);
   if (ethumb_client_thumb_exists(_elm_ethumb_client))
     {
	const char *thumb_path, *thumb_key;
	wd->thumb.id = -1;
	ethumb_client_thumb_path_get(_elm_ethumb_client, &thumb_path,
				     &thumb_key);
	_finished_thumb(wd, thumb_path, thumb_key);
	return;
     }
   else if ((wd->thumb.id = ethumb_client_generate
	     (_elm_ethumb_client, _finished_thumb_cb, wd, NULL)) != -1)
     {
	edje_object_signal_emit(wd->frame, EDJE_SIGNAL_PULSE_START,
				"elm");
	edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_START,
				"elm");
	evas_object_smart_callback_call(wd->self, SIG_GENERATE_START, NULL);
     }
   else
     {
	wd->thumb.id = -1;
	edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_ERROR,
				"elm");
	evas_object_smart_callback_call(wd->self, SIG_GENERATE_ERROR, NULL);
     }
}

static Eina_Bool
_thumb_apply_cb(void *data, int type __UNUSED__, void *ev __UNUSED__)
{'fraction_non_alphanumeric': 0.12026976395653803, 'fraction_numerical': 0.0016235793680529536, 'mean_word_length': 4.179495472186288, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 151, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '725595', 'n_tokens_mistral': 6241, 'n_tokens_neox': 6039, 'n_words': 1244}