1385 lines
36 KiB
C
1385 lines
36 KiB
C
#include "News.h"
|
|
|
|
#define CFG_CAT_ADD(id, icon) \
|
|
{ \
|
|
snprintf(buf, sizeof(buf), "%s/%s", \
|
|
e_module_dir_get(news->module), icon); \
|
|
cat = news_feed_category_new(id, buf); \
|
|
c->feed.categories = eina_list_append(c->feed.categories, cat); \
|
|
}
|
|
#define CFG_FEED_ADD(id, icon) \
|
|
{ \
|
|
snprintf(buf, sizeof(buf), "%s/%s", \
|
|
e_module_dir_get(news->module), icon); \
|
|
feed = news_feed_new(id, buf, 1, 0, cat); \
|
|
cat->feeds = eina_list_append(cat->feeds, feed); \
|
|
}
|
|
|
|
static int _feed_activate(News_Feed *f);
|
|
static void _feed_deactivate(News_Feed *f);
|
|
static News_Feed *_feed_find(News_Feed_Category *cat, char *name);
|
|
static News_Feed_Category *_feed_category_find(char *name);
|
|
static char *_get_host_from_url(const char *url);
|
|
static char *_get_file_from_url(const char *url);
|
|
static void _cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
|
|
static void _cb_mouse_out(void *data, Evas *e, Evas_Object *obj, void *event_info);
|
|
static void _cb_feed_open(void *data, Evas_Object *obj, const char *emission, const char *source);
|
|
static Eina_Bool _cb_feed_server_add(void *data, int type, void *event);
|
|
static Eina_Bool _cb_feed_server_del(void *data, int type, void *event);
|
|
static Eina_Bool _cb_feed_server_data(void *data, int type, void *event);
|
|
static void _cb_feed_parse(News_Feed_Document *doc, News_Parse_Error error, int changes);
|
|
static Eina_Bool _cb_feeds_timer(void *data);
|
|
static int _cb_sort_cats(const void *d1, const void *d2);
|
|
static int _cb_sort_feeds(const void *d1, const void *d2);
|
|
|
|
static const News_Feed_Lang _feed_langs[] = {
|
|
{"ca", "Catalan"},
|
|
{"zh", "Chinese"},
|
|
{"cs", "Czech"},
|
|
{"nl", "Dutch"},
|
|
{"da", "Danish"},
|
|
{"de", "German"},
|
|
{"en", "English"},
|
|
{"fi", "Finnish"},
|
|
{"fr", "French"},
|
|
{"hu", "Hungarian"},
|
|
{"it", "Italian"},
|
|
{"ja", "Japanese"},
|
|
{"ko", "Korean"},
|
|
{"pl", "Polish"},
|
|
{"pt", "Portuguese"},
|
|
{"ru", "Russian"},
|
|
{"sk", "Slovak"},
|
|
{"sl", "Slovenian"},
|
|
{"es", "Spanish"},
|
|
{"sv", "Swedish"},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
/*
|
|
* Public functions
|
|
*/
|
|
|
|
int
|
|
news_feed_init(void)
|
|
{
|
|
News_Feed_Lang *lang;
|
|
Eina_List *l;
|
|
int i;
|
|
|
|
/* create dynamic languages list from static one
|
|
we create this list so language are accessible from everywhere */
|
|
l = NULL;
|
|
i = 0;
|
|
while (_feed_langs[i].key)
|
|
{
|
|
lang = E_NEW(News_Feed_Lang, 1);
|
|
lang->key = eina_stringshare_add(_feed_langs[i].key);
|
|
lang->name = eina_stringshare_add(_feed_langs[i].name);
|
|
l = eina_list_append(l, lang);
|
|
i++;
|
|
}
|
|
news->langs = l;
|
|
|
|
/* validate each feed and create host and file strings + attach to category */
|
|
NEWS_FEED_FOREACH_BEG();
|
|
if (!news_feed_edit(_feed,
|
|
(char *)_feed->name, _feed->name_ovrw,
|
|
(char *)_feed->language, _feed->language_ovrw,
|
|
(char *)_feed->description, _feed->description_ovrw,
|
|
(char *)_feed->url_home, _feed->url_home_ovrw,
|
|
(char *)_feed->url_feed,
|
|
(char *)_feed->icon, _feed->icon_ovrw,
|
|
_feed->important,
|
|
_cat, 1))
|
|
_cat->feeds = eina_list_remove_list(_cat->feeds, _l_cats);
|
|
NEWS_FEED_FOREACH_END();
|
|
|
|
/* create 'feeds_visible' lists in categories */
|
|
news_feed_lists_refresh(0);
|
|
|
|
/* set the update timer */
|
|
news_feed_timer_set(news->config->feed.timer_m);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
news_feed_shutdown(void)
|
|
{
|
|
/* destroy dynamic languages list */
|
|
news_feed_lang_list_free(news->langs);
|
|
|
|
/* delete the update timer */
|
|
news_feed_timer_set(0);
|
|
}
|
|
|
|
void
|
|
news_feed_all_delete(void)
|
|
{
|
|
News_Config *c;
|
|
News_Feed *f;
|
|
News_Feed_Category *cat;
|
|
|
|
c = news->config;
|
|
while (c->feed.categories)
|
|
{
|
|
cat = c->feed.categories->data;
|
|
while (cat->feeds)
|
|
{
|
|
f = cat->feeds->data;
|
|
cat->feeds = eina_list_remove_list(cat->feeds, cat->feeds);
|
|
news_feed_free(f);
|
|
}
|
|
c->feed.categories = eina_list_remove_list(c->feed.categories,
|
|
c->feed.categories);
|
|
news_feed_category_free(cat);
|
|
}
|
|
|
|
news_feed_lists_refresh(0);
|
|
}
|
|
|
|
void
|
|
news_feed_all_restore(void)
|
|
{
|
|
News_Config *c;
|
|
News_Feed_Category *cat;
|
|
News_Feed *feed;
|
|
char buf[4096];
|
|
|
|
c = news->config;
|
|
news_feed_all_delete();
|
|
|
|
/* FEED_ADD uses the cat created by CAT_ADD */
|
|
CFG_CAT_ADD( NEWS_FEED_ITEM_CAT_COMICS, NEWS_FEED_ITEM_CAT_ICON_COMICS );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_BOULETCORP, NEWS_FEED_ITEM_FEED_ICON_BOULETCORP );
|
|
CFG_CAT_ADD( NEWS_FEED_ITEM_CAT_COMPUTERS, NEWS_FEED_ITEM_CAT_ICON_COMPUTERS );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_FRESHMEAT, NEWS_FEED_ITEM_FEED_ICON_FRESHMEAT );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_OSNEWS, NEWS_FEED_ITEM_FEED_ICON_OSNEWS );
|
|
CFG_CAT_ADD( NEWS_FEED_ITEM_CAT_ENLIGHTENMENT, NEWS_FEED_ITEM_CAT_ICON_ENLIGHTENMENT );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_E_CVS, NEWS_FEED_ITEM_FEED_ICON_E_CVS );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_E_FR, NEWS_FEED_ITEM_FEED_ICON_E_FR );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_NEWS, NEWS_FEED_ITEM_FEED_ICON_NEWS );
|
|
CFG_CAT_ADD( NEWS_FEED_ITEM_CAT_NEWS, NEWS_FEED_ITEM_CAT_ICON_NEWS );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_AFP_EN, NEWS_FEED_ITEM_FEED_ICON_AFP_EN );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_BBC_WORLD, NEWS_FEED_ITEM_FEED_ICON_BBC_WORLD );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_CNN, NEWS_FEED_ITEM_FEED_ICON_CNN );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_COURRIERINTERNATIONAL, NEWS_FEED_ITEM_FEED_ICON_COURRIERINTERNATIONAL );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_GOOGLE, NEWS_FEED_ITEM_FEED_ICON_GOOGLE );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_GOOGLE_FR, NEWS_FEED_ITEM_FEED_ICON_GOOGLE_FR );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_LEMONDE_UNE, NEWS_FEED_ITEM_FEED_ICON_LEMONDE );
|
|
CFG_CAT_ADD( NEWS_FEED_ITEM_CAT_SCIENCES, NEWS_FEED_ITEM_CAT_ICON_SCIENCES );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_FUTURASCIENCES, NEWS_FEED_ITEM_FEED_ICON_FUTURASCIENCES );
|
|
CFG_CAT_ADD( NEWS_FEED_ITEM_CAT_TEST, NEWS_FEED_ITEM_CAT_ICON_TEST );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_TEST, NEWS_FEED_ITEM_FEED_ICON_TEST );
|
|
CFG_CAT_ADD( NEWS_FEED_ITEM_CAT_VARIOUS, NEWS_FEED_ITEM_CAT_ICON_VARIOUS );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_BARRAPUNTO, NEWS_FEED_ITEM_FEED_ICON_BARRAPUNTO );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_DIGG, NEWS_FEED_ITEM_FEED_ICON_DIGG );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_MENEAME, NEWS_FEED_ITEM_FEED_ICON_MENEAME );
|
|
CFG_FEED_ADD( NEWS_FEED_ITEM_FEED_SLASHDOT, NEWS_FEED_ITEM_FEED_ICON_SLASHDOT );
|
|
|
|
news_feed_lists_refresh(0);
|
|
}
|
|
|
|
void
|
|
news_feed_lists_refresh(int sort)
|
|
{
|
|
Eina_List *l, *l2, *list;
|
|
News_Feed_Category *cat;
|
|
News_Feed *f;
|
|
int list_free;
|
|
|
|
/* 1. sort by name */
|
|
|
|
if (sort && news->config->feed.sort_name)
|
|
{
|
|
list = news->config->feed.categories;
|
|
list = eina_list_sort(list, eina_list_count(list), _cb_sort_cats);
|
|
news->config->feed.categories = list;
|
|
|
|
for (l=news->config->feed.categories; l; l=eina_list_next(l))
|
|
{
|
|
cat = l->data;
|
|
list = cat->feeds;
|
|
list = eina_list_sort(list, eina_list_count(list), _cb_sort_feeds);
|
|
cat->feeds = list;
|
|
}
|
|
}
|
|
|
|
/* 2. create "feeds_visible" in categories */
|
|
|
|
for (l=news->config->feed.categories; l; l=eina_list_next(l))
|
|
{
|
|
cat = l->data;
|
|
list = NULL;
|
|
list_free = 0;
|
|
if (news->config->feed.langs_all)
|
|
{
|
|
list = cat->feeds;
|
|
}
|
|
else
|
|
{
|
|
for (l2=cat->feeds; l2; l2=eina_list_next(l2))
|
|
{
|
|
f = l2->data;
|
|
if (news_feed_lang_selected_is(f->language))
|
|
list = eina_list_append(list, f);
|
|
}
|
|
list_free = 1;
|
|
}
|
|
|
|
if (cat->feeds_visible_free && cat->feeds_visible)
|
|
eina_list_free(cat->feeds_visible);
|
|
|
|
cat->feeds_visible = list;
|
|
cat->feeds_visible_free = list_free;
|
|
}
|
|
|
|
/* 3. refresh ui */
|
|
|
|
news_feed_category_list_ui_refresh();
|
|
}
|
|
|
|
void
|
|
news_feed_timer_set(int time)
|
|
{
|
|
if (news->feeds_timer)
|
|
{
|
|
ecore_timer_del(news->feeds_timer);
|
|
news->feeds_timer = NULL;
|
|
}
|
|
if (!time) return;
|
|
|
|
news->config->feed.timer_m = time;
|
|
news->feeds_timer = ecore_timer_add(time * 60,
|
|
_cb_feeds_timer, NULL);
|
|
}
|
|
|
|
News_Feed *
|
|
news_feed_new(char *name, int name_ovrw, char *language, int language_ovrw, char *description, int description_ovrw, char *url_home, int url_home_ovrw, char *url_feed, char *icon, int icon_ovrw, int important, News_Feed_Category *category)
|
|
{
|
|
News_Feed *f;
|
|
|
|
f = E_NEW(News_Feed, 1);
|
|
|
|
if (!news_feed_edit(f,
|
|
name, name_ovrw,
|
|
language, language_ovrw,
|
|
description, description_ovrw,
|
|
url_home, url_home_ovrw,
|
|
url_feed,
|
|
icon, icon_ovrw,
|
|
important,
|
|
category, 0))
|
|
{
|
|
free(f);
|
|
return NULL;
|
|
}
|
|
|
|
return f;
|
|
}
|
|
|
|
int
|
|
news_feed_edit(News_Feed *f, char *name, int name_ovrw, char *language, int language_ovrw, char *description, int description_ovrw, char *url_home, int url_home_ovrw, char *url_feed, char *icon, int icon_ovrw, int important, News_Feed_Category *category, int check_only)
|
|
{
|
|
News_Feed *f2;
|
|
char *host, *file;
|
|
int update = 0;
|
|
|
|
if ( !name || !name[0] )
|
|
{
|
|
news_util_message_error_show(D_("The <hilight>name</hilight> you entered is not correct"));
|
|
return 0;
|
|
}
|
|
if (!category)
|
|
{
|
|
news_util_message_error_show(D_("The need to <hilight>select a category</hilight>."));
|
|
return 0;
|
|
}
|
|
f2 = _feed_find(category, name);
|
|
if ( f2 && (f != f2) )
|
|
{
|
|
news_util_message_error_show(D_("A feed with the <hilight>name</hilight> %s <hilight>already exists</hilight><br>"
|
|
"in the %s category<br><br>"
|
|
"Its not possible to have feeds with the same name<br>"
|
|
"in one category."),
|
|
name, category->name);
|
|
return 0;
|
|
}
|
|
if (!language || !language[0])
|
|
{
|
|
news_util_message_error_show(D_("You need to select a <hilight>language</hilight>."));
|
|
return 0;
|
|
}
|
|
if ( !url_feed || !url_feed[0] ||
|
|
!(host = _get_host_from_url(url_feed)) ||
|
|
!(file = _get_file_from_url(url_feed)) )
|
|
{
|
|
news_util_message_error_show(D_("The <hilight>url</hilight> you specified is not correct"));
|
|
if (host) free(host);
|
|
return 0;
|
|
}
|
|
|
|
if (!check_only)
|
|
{
|
|
if (f->name != name)
|
|
{
|
|
if (f->name) eina_stringshare_del(f->name);
|
|
f->name = eina_stringshare_add(name);
|
|
}
|
|
f->name_ovrw = name_ovrw;
|
|
|
|
if (f->language != language)
|
|
{
|
|
char lang[3];
|
|
|
|
if (f->language) eina_stringshare_del(f->language);
|
|
snprintf(lang, sizeof(lang), "%2s", language);
|
|
if (language) f->language = eina_stringshare_add(lang);
|
|
}
|
|
f->language_ovrw = language_ovrw;
|
|
|
|
if (f->description != description)
|
|
{
|
|
if (f->description) eina_stringshare_del(f->description);
|
|
if (description) f->description = eina_stringshare_add(description);
|
|
}
|
|
f->description_ovrw = description_ovrw;
|
|
|
|
if (f->url_home != url_home)
|
|
{
|
|
if (f->url_home) eina_stringshare_del(f->url_home);
|
|
if (url_home) f->url_home = eina_stringshare_add(url_home);
|
|
}
|
|
f->url_home_ovrw = url_home_ovrw;
|
|
|
|
if ( (f->url_feed != url_feed) &&
|
|
(!f->url_feed || strcmp(f->url_feed, url_feed)) )
|
|
{
|
|
if (f->url_feed) eina_stringshare_del(f->url_feed);
|
|
f->url_feed = eina_stringshare_add(url_feed);
|
|
update = 1;
|
|
}
|
|
|
|
if (f->icon != icon)
|
|
{
|
|
if ( f->icon &&
|
|
!(icon && !strcmp(f->icon, icon)) )
|
|
{
|
|
eina_stringshare_del(f->icon);
|
|
f->icon = NULL;
|
|
if (f->obj_icon)
|
|
{
|
|
evas_object_del(f->obj_icon);
|
|
f->obj_icon = NULL;
|
|
}
|
|
}
|
|
if (icon && !f->icon) f->icon = eina_stringshare_add(icon);
|
|
}
|
|
f->icon_ovrw = icon_ovrw;
|
|
|
|
if (f->important != important)
|
|
{
|
|
f->important = important;
|
|
if (f->item
|
|
&& ( (f->item->config->view_mode == NEWS_ITEM_VIEW_MODE_FEED_IMPORTANT)
|
|
||
|
|
((f->item->config->view_mode == NEWS_ITEM_VIEW_MODE_FEED_IMPORTANT_UNREAD)
|
|
&& f->doc && f->doc->unread_count)))
|
|
news_item_refresh(f->item, 1, 0, 1);
|
|
}
|
|
|
|
f->category = category;
|
|
|
|
if (f->item)
|
|
{
|
|
News_Feed_Ref *ref;
|
|
|
|
if (f->icon && !f->obj_icon)
|
|
news_feed_obj_refresh(f, 1, 1);
|
|
|
|
/* Feed Ref update */
|
|
ref = news_feed_ref_find(f, f->item);
|
|
if (ref)
|
|
{
|
|
if (ref->name) eina_stringshare_del(ref->name);
|
|
ref->name = eina_stringshare_add(f->name);
|
|
if (ref->category) eina_stringshare_del(ref->category);
|
|
ref->category = eina_stringshare_add(f->category->name);
|
|
}
|
|
}
|
|
|
|
news_config_save();
|
|
}
|
|
else
|
|
{
|
|
f->category = category;
|
|
}
|
|
|
|
E_FREE(f->host);
|
|
f->host = host;
|
|
E_FREE(f->file);
|
|
f->file = file;
|
|
|
|
if (update && f->item) news_feed_update(f);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
news_feed_free(News_Feed *f)
|
|
{
|
|
News_Item *ni;
|
|
|
|
ni = f->item;
|
|
if (ni)
|
|
{
|
|
news_feed_detach(f, 1);
|
|
news_item_refresh(ni, 1, 0, 0);
|
|
news_viewer_refresh(ni->viewer);
|
|
}
|
|
if (f->doc) _feed_deactivate(f);
|
|
|
|
if (f->config_dialog) news_config_dialog_feed_hide(f);
|
|
if (f->menu) news_menu_feed_hide(f);
|
|
if (f->obj_icon) evas_object_del(f->obj_icon);
|
|
|
|
if (f->name) eina_stringshare_del(f->name);
|
|
if (f->language) eina_stringshare_del(f->language);
|
|
if (f->description) eina_stringshare_del(f->description);
|
|
if (f->url_home) eina_stringshare_del(f->url_home);
|
|
if (f->url_feed) eina_stringshare_del(f->url_feed);
|
|
if (f->icon) eina_stringshare_del(f->icon);
|
|
|
|
if (f->host) free(f->host);
|
|
if (f->file) free(f->file);
|
|
|
|
free(f);
|
|
}
|
|
|
|
/*
|
|
* Attach a feed to an item
|
|
*
|
|
* You can give the feed or the feed ref
|
|
*/
|
|
int
|
|
news_feed_attach(News_Feed *f, News_Feed_Ref *ref, News_Item *ni)
|
|
{
|
|
if (!f)
|
|
{
|
|
News_Feed_Category *cat;
|
|
News_Feed *f_look;
|
|
Eina_List *l, *l2;
|
|
|
|
for (l=news->config->feed.categories; l; l=eina_list_next(l))
|
|
{
|
|
cat = eina_list_data_get(l);
|
|
if (!strcmp(cat->name, ref->category))
|
|
{
|
|
for (l2=cat->feeds; l2; l2=eina_list_next(l2))
|
|
{
|
|
f_look = eina_list_data_get(l2);
|
|
if (!strcmp(f_look->name, ref->name))
|
|
{
|
|
f = f_look;
|
|
l = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!f) return 0;
|
|
}
|
|
|
|
if (!ref)
|
|
{
|
|
ref = E_NEW(News_Feed_Ref, 1);
|
|
ref->category = eina_stringshare_add(f->category->name);
|
|
ref->name = eina_stringshare_add(f->name);
|
|
ref->feed = f;
|
|
ni->config->feed_refs = eina_list_append(ni->config->feed_refs, ref);
|
|
}
|
|
else
|
|
{
|
|
ref->feed = f;
|
|
}
|
|
|
|
f->item = ni;
|
|
if (f->doc)
|
|
{
|
|
if (f->doc->unread_count)
|
|
news_item_unread_count_change(f->item, +1);
|
|
}
|
|
else
|
|
{
|
|
_feed_activate(f);
|
|
news_feed_update(f);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Detach a feed from the item wich its attached to
|
|
*
|
|
* If @p really is 0, only detach the feed from the item, but keep feed ref
|
|
* If @p really is 1, remove the feed ref too
|
|
*/
|
|
void
|
|
news_feed_detach(News_Feed *f, int really)
|
|
{
|
|
News_Item *ni;
|
|
|
|
/* 1. delete the feed reference from items to feed */
|
|
ni = f->item;
|
|
if (ni)
|
|
{
|
|
News_Feed_Ref *ref;
|
|
|
|
ref = news_feed_ref_find(f, ni);
|
|
if (ref)
|
|
{
|
|
if (really)
|
|
{
|
|
DITEM(("feed detach : delete feed ref (%s)", ref->feed->name));
|
|
ni->config->feed_refs = eina_list_remove(ni->config->feed_refs, ref);
|
|
eina_stringshare_del(ref->category);
|
|
eina_stringshare_del(ref->name);
|
|
free(ref);
|
|
}
|
|
else
|
|
ref->feed = NULL;
|
|
}
|
|
}
|
|
|
|
/* 2. gui items */
|
|
if (f->obj)
|
|
{
|
|
evas_object_del(f->obj);
|
|
f->obj = NULL;
|
|
}
|
|
if (f->obj_icon)
|
|
{
|
|
evas_object_del(f->obj_icon);
|
|
f->obj_icon = NULL;
|
|
}
|
|
|
|
/* 3. unread count */
|
|
if (f->doc && f->doc->unread_count)
|
|
news_item_unread_count_change(f->item, -1);
|
|
|
|
/* 4. misc cleanups */
|
|
if (ni && ni->viewer)
|
|
{
|
|
if (ni->viewer->vfeeds.selected == f)
|
|
ni->viewer->vfeeds.selected = NULL;
|
|
}
|
|
|
|
/* 5. delete reference from feed to item */
|
|
f->item = NULL;
|
|
|
|
/* 6. the feed will be deactivated on next feed_update :)
|
|
we wait until that because _detach is also called when there
|
|
is a gadcon change (like size) */
|
|
}
|
|
|
|
int
|
|
news_feed_update(News_Feed *f)
|
|
{
|
|
News_Feed_Document *doc;
|
|
|
|
/* if the feed is not attached to an item
|
|
it means that it was detached and never reattached,
|
|
so deactivate the feed */
|
|
if (!f->item)
|
|
{
|
|
_feed_deactivate(f);
|
|
return 0;
|
|
}
|
|
|
|
doc = f->doc;
|
|
|
|
if (doc->server.buffer)
|
|
{
|
|
free(doc->server.buffer);
|
|
doc->server.buffer = NULL;
|
|
}
|
|
doc->server.buffer_size = 0;
|
|
|
|
if (doc->server.conn)
|
|
{
|
|
//FIXME: segfault appears if i delete the server when connection has not been created yet (needs e patch)
|
|
if (doc->server.waiting_reply)
|
|
{
|
|
//news_util_debug("Forced feed dl with waiting_replay of 1 !<br>ecore_con_server_del !<br>(%d tries)", doc->server.nb_tries);
|
|
ecore_con_server_del(doc->server.conn);
|
|
doc->server.waiting_reply = 0;
|
|
}
|
|
if (doc->server.nb_tries >= NEWS_FEED_NB_TRIES_MAX)
|
|
return 0;
|
|
doc->server.nb_tries++;
|
|
doc->server.conn = NULL;
|
|
//TODO: popup to warn that we are at at the nb_tries try =)
|
|
}
|
|
else
|
|
doc->server.nb_tries = 1;
|
|
|
|
if (news->config->proxy.enable &&
|
|
news->config->proxy.port &&
|
|
news->config->proxy.host && news->config->proxy.host[0])
|
|
doc->server.conn = ecore_con_server_connect(ECORE_CON_REMOTE_NODELAY,
|
|
news->config->proxy.host,
|
|
news->config->proxy.port,
|
|
doc);
|
|
else
|
|
doc->server.conn = ecore_con_server_connect(ECORE_CON_REMOTE_NODELAY,
|
|
f->host,
|
|
80,
|
|
doc);
|
|
|
|
if (!doc->server.conn)
|
|
{
|
|
//TODO: popup, if proxy, tell it
|
|
DFEED(("Could not start connection to %s",
|
|
f->host));
|
|
return 0;
|
|
}
|
|
DFEED(("Trying to update feed %s", f->host));
|
|
|
|
if (f->item && !f->item->loading_state)
|
|
news_item_loadingstate_refresh(f->item);
|
|
|
|
if (f->item && f->item->viewer &&
|
|
(f->item->viewer->vfeeds.selected == f))
|
|
news_viewer_feed_selected_infos_refresh(f->item->viewer);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Refresh the object showed in item
|
|
*/
|
|
void
|
|
news_feed_obj_refresh(News_Feed *f, int changed_content, int changed_state)
|
|
{
|
|
News_Item *ni;
|
|
Evas_Object *obj;
|
|
|
|
obj = f->obj;
|
|
ni = f->item;
|
|
|
|
if (!ni) return;
|
|
|
|
/* base obj */
|
|
|
|
if (!f->obj)
|
|
{
|
|
obj = edje_object_add(ni->gcc->gadcon->evas);
|
|
news_theme_edje_set(obj, NEWS_THEME_FEED);
|
|
evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
|
|
_cb_mouse_down, f);
|
|
evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_OUT,
|
|
_cb_mouse_out, f);
|
|
edje_object_signal_callback_add(obj, "e,action,open", "e",
|
|
_cb_feed_open, f);
|
|
evas_object_propagate_events_set(obj, 0);
|
|
evas_object_show(obj);
|
|
}
|
|
|
|
if (!f->obj || changed_state)
|
|
{
|
|
if (f->doc && f->doc->unread_count)
|
|
edje_object_signal_emit(obj, "e,state,new,set", "e");
|
|
else
|
|
edje_object_signal_emit(obj, "e,state,new,unset", "e");
|
|
}
|
|
|
|
if (!f->obj || changed_content)
|
|
{
|
|
edje_object_part_text_set(obj, "name", f->name);
|
|
}
|
|
|
|
/* icon */
|
|
|
|
if (f->obj_icon && changed_content)
|
|
{
|
|
evas_object_del(f->obj_icon);
|
|
f->obj_icon = NULL;
|
|
}
|
|
|
|
if (!f->obj_icon && f->icon && f->icon[0])
|
|
{
|
|
Evas_Object *icon;
|
|
|
|
DFEED(("Refresh view obj icon of feed %s : %s", f->name, f->icon));
|
|
icon = e_icon_add(ni->gcc->gadcon->evas);
|
|
e_icon_file_set(icon, f->icon);
|
|
e_icon_fill_inside_set(icon, 1);
|
|
edje_object_part_swallow(obj, "icon", icon);
|
|
evas_object_show(icon);
|
|
f->obj_icon = icon;
|
|
}
|
|
|
|
f->obj = obj;
|
|
}
|
|
|
|
|
|
News_Feed_Ref *
|
|
news_feed_ref_find(News_Feed *f, News_Item *ni)
|
|
{
|
|
NEWS_ITEM_FEEDS_FOREACH_BEG(ni);
|
|
if (_feed == f)
|
|
return _ref;
|
|
NEWS_ITEM_FEEDS_FOREACH_END();
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
news_feed_read_set(News_Feed *feed)
|
|
{
|
|
Eina_List *l;
|
|
News_Feed_Article *art;
|
|
|
|
if (!feed->doc) return;
|
|
if (!feed->doc->unread_count) return;
|
|
|
|
for (l=feed->doc->articles; l; l=eina_list_next(l))
|
|
{
|
|
art = l->data;
|
|
if (art->unread)
|
|
news_feed_article_unread_set(art, 0);
|
|
}
|
|
}
|
|
|
|
void
|
|
news_feed_unread_count_change(News_Feed *feed, int nb)
|
|
{
|
|
int was_empty = 0;
|
|
|
|
if (!nb) return;
|
|
if (!feed->doc->unread_count)
|
|
was_empty = 1;
|
|
feed->doc->unread_count += nb;
|
|
if (was_empty || !feed->doc->unread_count)
|
|
{
|
|
if (nb > 0)
|
|
news_item_unread_count_change(feed->item, 1);
|
|
else
|
|
news_item_unread_count_change(feed->item, -1);
|
|
|
|
switch ((News_Item_View_Mode)feed->item->config->view_mode)
|
|
{
|
|
case NEWS_ITEM_VIEW_MODE_ONE:
|
|
break;
|
|
case NEWS_ITEM_VIEW_MODE_FEED:
|
|
case NEWS_ITEM_VIEW_MODE_FEED_IMPORTANT:
|
|
news_feed_obj_refresh(feed, 0, 1);
|
|
break;
|
|
case NEWS_ITEM_VIEW_MODE_FEED_UNREAD:
|
|
news_item_refresh(feed->item, 1, 0, 1);
|
|
break;
|
|
case NEWS_ITEM_VIEW_MODE_FEED_IMPORTANT_UNREAD:
|
|
if (feed->important)
|
|
news_item_refresh(feed->item, 1, 0, 1);
|
|
break;
|
|
}
|
|
|
|
if (feed->item->viewer)
|
|
news_viewer_refresh(feed->item->viewer);
|
|
}
|
|
|
|
DFEED(("%s: UNREADcount = %d", feed->name, feed->doc->unread_count));
|
|
}
|
|
|
|
void
|
|
news_feed_list_ui_refresh(void)
|
|
{
|
|
Eina_List *l;
|
|
|
|
if (news->config_dialog_feeds)
|
|
news_config_dialog_feeds_refresh_feeds();
|
|
|
|
for (l=news->items; l; l=eina_list_next(l))
|
|
{
|
|
News_Item *ni;
|
|
|
|
ni = eina_list_data_get(l);
|
|
if (ni->config_dialog_content)
|
|
{
|
|
news_config_dialog_item_content_refresh_feeds(ni);
|
|
news_config_dialog_item_content_refresh_selected_feeds(ni);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
news_feed_article_del(News_Feed_Article *art)
|
|
{
|
|
News_Feed_Document *doc;
|
|
|
|
doc = art->doc;
|
|
if (art->title) free(art->title);
|
|
if (art->url) free(art->url);
|
|
if (art->description) free(art->description);
|
|
if (art->image) evas_object_del(art->image);
|
|
|
|
if (doc->feed->item && doc->feed->item->viewer)
|
|
{
|
|
if (doc->feed->item->viewer->varticles.selected == art)
|
|
doc->feed->item->viewer->varticles.selected = NULL;
|
|
}
|
|
|
|
if (doc->feed->item && art->unread)
|
|
news_feed_unread_count_change(doc->feed, -1);
|
|
|
|
doc->articles = eina_list_remove(doc->articles, art);
|
|
|
|
free(art);
|
|
}
|
|
|
|
void
|
|
news_feed_article_unread_set(News_Feed_Article *art, int unread)
|
|
{
|
|
/* check already in that state */
|
|
if (unread == art->unread) return;
|
|
|
|
art->unread = unread;
|
|
if (art->doc->feed->item->viewer)
|
|
news_viewer_article_state_refresh(art->doc->feed->item->viewer, art);
|
|
|
|
if (unread)
|
|
news_feed_unread_count_change(art->doc->feed, 1);
|
|
else
|
|
news_feed_unread_count_change(art->doc->feed, -1);
|
|
}
|
|
|
|
News_Feed_Category *
|
|
news_feed_category_new(char *name, char *icon)
|
|
{
|
|
News_Feed_Category *cat;
|
|
|
|
cat = E_NEW(News_Feed_Category, 1);
|
|
|
|
if (!news_feed_category_edit(cat, name, icon))
|
|
{
|
|
free(cat);
|
|
return NULL;
|
|
}
|
|
|
|
return cat;
|
|
}
|
|
|
|
int
|
|
news_feed_category_edit(News_Feed_Category *cat, char *name, char *icon)
|
|
{
|
|
News_Feed_Category *cat2;
|
|
|
|
if (!name || !name[0])
|
|
{
|
|
news_util_message_error_show(D_("You need to enter a <hilight>name</hilight> !"));
|
|
return 0;
|
|
}
|
|
|
|
/* that name already exists ? */
|
|
cat2 = _feed_category_find(name);
|
|
if (cat2 && (cat2 != cat))
|
|
{
|
|
news_util_message_error_show(D_("The <hilight>name</hilight> you entered is <hilight>already used</hilight><br>"
|
|
"by another category"));
|
|
return 0;
|
|
}
|
|
|
|
if (cat->name != name)
|
|
{
|
|
if (cat->name) eina_stringshare_del(cat->name);
|
|
cat->name = eina_stringshare_add(name);
|
|
}
|
|
|
|
if (cat->icon != icon)
|
|
{
|
|
if (cat->icon) eina_stringshare_del(cat->icon);
|
|
if (icon) cat->icon = eina_stringshare_add(icon);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
news_feed_category_free(News_Feed_Category *cat)
|
|
{
|
|
if (cat->feeds && eina_list_count(cat->feeds)) return;
|
|
|
|
if (cat->name) eina_stringshare_del(cat->name);
|
|
if (cat->icon) eina_stringshare_del(cat->icon);
|
|
if (cat->feeds_visible_free && cat->feeds_visible)
|
|
eina_list_free(cat->feeds_visible);
|
|
if (cat->config_dialog) news_config_dialog_category_hide(cat);
|
|
|
|
free(cat);
|
|
}
|
|
|
|
void
|
|
news_feed_category_list_ui_refresh(void)
|
|
{
|
|
if (news->config_dialog_feeds)
|
|
news_config_dialog_feeds_refresh_categories();
|
|
if (news->config_dialog_feed_new)
|
|
news_config_dialog_feed_refresh_categories(NULL);
|
|
|
|
NEWS_FEED_FOREACH_BEG();
|
|
if (_feed->config_dialog)
|
|
news_config_dialog_feed_refresh_categories(_feed);
|
|
NEWS_FEED_FOREACH_END();
|
|
|
|
news_feed_list_ui_refresh();
|
|
}
|
|
|
|
void
|
|
news_feed_lang_list_refresh(void)
|
|
{
|
|
if (news->config_dialog_feed_new)
|
|
news_config_dialog_feed_refresh_langs(NULL);
|
|
|
|
NEWS_FEED_FOREACH_BEG();
|
|
if (_feed->config_dialog)
|
|
news_config_dialog_feed_refresh_langs(_feed);
|
|
NEWS_FEED_FOREACH_END();
|
|
}
|
|
|
|
void
|
|
news_feed_lang_list_free(Eina_List *list)
|
|
{
|
|
News_Feed_Lang *lang;
|
|
|
|
while ((lang = eina_list_data_get(list)))
|
|
{
|
|
if (lang->key) eina_stringshare_del(lang->key);
|
|
if (lang->name) eina_stringshare_del(lang->name);
|
|
list = eina_list_remove_list(list, list);
|
|
free(lang);
|
|
}
|
|
}
|
|
|
|
const char *
|
|
news_feed_lang_name_get(const char *key)
|
|
{
|
|
int i;
|
|
|
|
i = 0;
|
|
while (_feed_langs[i].key)
|
|
{
|
|
if (!strncmp(_feed_langs[i].key, key, 2))
|
|
return _feed_langs[i].name;
|
|
i++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int
|
|
news_feed_lang_selected_is(const char *key)
|
|
{
|
|
News_Feed_Lang *lang;
|
|
Eina_List *l;
|
|
|
|
for (l=news->config->feed.langs; l; l=eina_list_next(l))
|
|
{
|
|
lang = l->data;
|
|
if (!strncmp(lang->key, key, 2))
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Private functions
|
|
*
|
|
*/
|
|
|
|
static int
|
|
_feed_activate(News_Feed *f)
|
|
{
|
|
News_Feed_Document *doc;
|
|
|
|
doc = E_NEW(News_Feed_Document, 1);
|
|
|
|
doc->feed = f;
|
|
f->doc = doc;
|
|
|
|
doc->ui_needrefresh = 1;
|
|
|
|
doc->server.handler_add = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD,
|
|
_cb_feed_server_add, doc);
|
|
doc->server.handler_del = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL,
|
|
_cb_feed_server_del, doc);
|
|
doc->server.handler_data = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA,
|
|
_cb_feed_server_data, doc);
|
|
|
|
doc->parse.type = NEWS_FEED_TYPE_UNKNOWN;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void
|
|
_feed_deactivate(News_Feed *f)
|
|
{
|
|
News_Feed_Document *doc;
|
|
|
|
doc = f->doc;
|
|
if (!doc) return;
|
|
|
|
DFEED(("Feed %s deactivate", f->name));
|
|
|
|
if (doc->parse.parser) news_parse_stop(doc);
|
|
|
|
if (doc->parse.meta_article) eina_stringshare_del(doc->parse.meta_article);
|
|
if (doc->parse.meta_channel) eina_stringshare_del(doc->parse.meta_channel);
|
|
if (doc->parse.meta_date) eina_stringshare_del(doc->parse.meta_date);
|
|
if (doc->parse.charset) eina_stringshare_del(doc->parse.charset);
|
|
|
|
//FIXME: waiting ecore_con patch to be able to delete the server in all cases
|
|
if (doc->server.conn && doc->server.waiting_reply) ecore_con_server_del(doc->server.conn);
|
|
ecore_event_handler_del(doc->server.handler_add);
|
|
ecore_event_handler_del(doc->server.handler_del);
|
|
ecore_event_handler_del(doc->server.handler_data);
|
|
if (doc->server.buffer) free(doc->server.buffer);
|
|
|
|
if (doc->articles)
|
|
{
|
|
News_Feed_Article *article;
|
|
|
|
while(doc->articles)
|
|
{
|
|
article = doc->articles->data;
|
|
news_feed_article_del(article);
|
|
}
|
|
}
|
|
|
|
if (doc->popw) news_popup_del(doc->popw);
|
|
|
|
f->doc = NULL;
|
|
free(doc);
|
|
}
|
|
|
|
static News_Feed *
|
|
_feed_find(News_Feed_Category *cat, char *name)
|
|
{
|
|
News_Feed *f;
|
|
Eina_List *l;
|
|
|
|
for (l=cat->feeds; l; l=eina_list_next(l))
|
|
{
|
|
f = l->data;
|
|
if (!strcmp(f->name, name))
|
|
return f;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static News_Feed_Category *
|
|
_feed_category_find(char *name)
|
|
{
|
|
Eina_List *l;
|
|
|
|
for (l=news->config->feed.categories; l; l=eina_list_next(l))
|
|
{
|
|
News_Feed_Category *cat;
|
|
|
|
cat = eina_list_data_get(l);
|
|
if (!strcmp(cat->name, name))
|
|
return cat;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static char *
|
|
_get_host_from_url(const char *url)
|
|
{
|
|
char *host, *p;
|
|
char buf[4096];
|
|
|
|
strncpy(buf, url, sizeof(buf));
|
|
if (strncmp(buf, "http://", 7))
|
|
return NULL;
|
|
if (*(buf+7) == '\0')
|
|
return NULL;
|
|
p = strchr(buf+7, '/');
|
|
if (p) *p = '\0';
|
|
host = strdup(buf+7);
|
|
|
|
return host;
|
|
}
|
|
|
|
static char *
|
|
_get_file_from_url(const char *url)
|
|
{
|
|
char *file, *p;
|
|
|
|
p = strstr(url, "://");
|
|
if (!p)
|
|
return NULL;
|
|
p += 3;
|
|
p = strstr(p, "/");
|
|
if (!p)
|
|
file = strdup("/");
|
|
else
|
|
file = strdup(p);
|
|
|
|
return file;
|
|
}
|
|
|
|
static void
|
|
_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
|
|
{
|
|
News_Feed *f;
|
|
Evas_Event_Mouse_Down *ev;
|
|
|
|
f = data;
|
|
ev = event_info;
|
|
|
|
DFEED(("Mouse down %d", ev->button));
|
|
|
|
switch(ev->button)
|
|
{
|
|
int cx, cy, cw, ch;
|
|
|
|
case 3:
|
|
if (f->menu) break;
|
|
|
|
news_menu_feed_show(f);
|
|
|
|
e_gadcon_canvas_zone_geometry_get(f->item->gcc->gadcon,
|
|
&cx, &cy, &cw, &ch);
|
|
e_menu_activate_mouse(f->menu,
|
|
e_util_zone_current_get(e_manager_current_get()),
|
|
cx + ev->output.x, cy + ev->output.y, 1, 1,
|
|
E_MENU_POP_DIRECTION_DOWN, ev->timestamp);
|
|
evas_event_feed_mouse_up(f->item->gcc->gadcon->evas, ev->button,
|
|
EVAS_BUTTON_NONE, ev->timestamp, NULL);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_cb_mouse_out(void *data, Evas *e, Evas_Object *obj, void *event_info)
|
|
{
|
|
News_Item *ni;
|
|
Evas_Event_Mouse_Out *ev;
|
|
|
|
ni = data;
|
|
ev = event_info;
|
|
|
|
DITEM(("Mouse out"));
|
|
|
|
}
|
|
|
|
static void
|
|
_cb_feed_open(void *data, Evas_Object *obj, const char *emission, const char *source)
|
|
{
|
|
News_Item *ni;
|
|
News_Feed *f;
|
|
|
|
f = data;
|
|
ni = f->item;
|
|
|
|
DITEM(("Cb feed %s open", f->name));
|
|
|
|
/* if the object is not loaded yet, abort */
|
|
if (!f->doc) return;
|
|
|
|
switch (f->doc->feed->item->config->openmethod)
|
|
{
|
|
case NEWS_ITEM_OPENMETHOD_VIEWER:
|
|
if (ni->viewer)
|
|
{
|
|
if (ni->viewer->vfeeds.selected == f)
|
|
news_viewer_destroy(ni->viewer);
|
|
else
|
|
news_viewer_feed_select(ni->viewer, f);
|
|
}
|
|
else
|
|
{
|
|
news_viewer_create(ni);
|
|
news_viewer_feed_select(ni->viewer, f);
|
|
}
|
|
break;
|
|
case NEWS_ITEM_OPENMETHOD_BROWSER:
|
|
if (ni->config->browser_open_home)
|
|
news_util_browser_open(f->url_home);
|
|
else
|
|
news_util_browser_open(f->url_feed);
|
|
news_feed_read_set(f);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_feed_server_add(void *data, int type, void *event)
|
|
{
|
|
News_Feed_Document *doc;
|
|
Ecore_Con_Event_Server_Add *ev;
|
|
char buf[4096];
|
|
|
|
doc = data;
|
|
ev = event;
|
|
|
|
/* check if the event is our event */
|
|
if (doc->server.conn != ev->server)
|
|
return EINA_TRUE;
|
|
|
|
DFEED(("Connection established after %d tries, sending request", doc->server.nb_tries));
|
|
|
|
snprintf(buf, sizeof(buf), "GET %s HTTP/1.0\r\n", doc->feed->file);
|
|
ecore_con_server_send(doc->server.conn, buf, strlen(buf));
|
|
snprintf(buf, sizeof(buf), "Host: %s\r\n", doc->feed->host);
|
|
ecore_con_server_send(doc->server.conn, buf, strlen(buf));
|
|
snprintf(buf, sizeof(buf), "User-Agent: %s/v%d\r\n\r\n", "Enlightenment News module", news->config->version);
|
|
ecore_con_server_send(doc->server.conn, buf, strlen(buf));
|
|
|
|
doc->server.waiting_reply = 1;
|
|
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_feed_server_del(void *data, int type, void *event)
|
|
{
|
|
News_Feed_Document *doc;
|
|
Ecore_Con_Event_Server_Del *ev;
|
|
|
|
ev = event;
|
|
doc = data;
|
|
|
|
/* check if the event is our event */
|
|
if (doc->server.conn != ev->server)
|
|
return EINA_TRUE;
|
|
|
|
doc->server.conn = NULL;
|
|
|
|
DFEED(("Connection end"));
|
|
|
|
if (!doc->server.buffer || !doc->server.buffer_size)
|
|
{
|
|
// TODO: error popup
|
|
if (doc->feed->item)
|
|
news_item_loadingstate_refresh(doc->feed->item);
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
doc->server.buffer_size++;
|
|
doc->server.buffer = realloc(doc->server.buffer,
|
|
doc->server.buffer_size);
|
|
doc->server.buffer[doc->server.buffer_size - 1] = '\0';
|
|
|
|
doc->server.waiting_reply = 0;
|
|
|
|
news_parse_go(doc, _cb_feed_parse);
|
|
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_feed_server_data(void *data, int type, void *event)
|
|
{
|
|
News_Feed_Document *doc;
|
|
Ecore_Con_Event_Server_Data *ev;
|
|
|
|
ev = event;
|
|
doc = data;
|
|
|
|
DFEED(("Received %d octets !", ev->size));
|
|
|
|
/* check if the event is our event */
|
|
if (doc->server.conn != ev->server)
|
|
return EINA_TRUE;
|
|
|
|
doc->server.buffer = realloc(doc->server.buffer,
|
|
doc->server.buffer_size + ev->size);
|
|
memcpy(doc->server.buffer + doc->server.buffer_size, ev->data, ev->size);
|
|
doc->server.buffer_size += ev->size;
|
|
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static void
|
|
_cb_feed_parse(News_Feed_Document *doc, News_Parse_Error error, int changes)
|
|
{
|
|
News_Item *ni;
|
|
|
|
ni = doc->feed->item;
|
|
|
|
free(doc->server.buffer);
|
|
doc->server.nb_tries = 0;
|
|
doc->server.buffer = NULL;
|
|
doc->server.buffer_size = 0;
|
|
doc->parse.last_time = ecore_time_unix_get();
|
|
|
|
//TODO with popups
|
|
doc->parse.error = error;
|
|
switch(error)
|
|
{
|
|
case NEWS_PARSE_ERROR_NO:
|
|
break;
|
|
case NEWS_PARSE_ERROR_BROKEN_FEED:
|
|
break;
|
|
case NEWS_PARSE_ERROR_TYPE_UNKNOWN:
|
|
break;
|
|
case NEWS_PARSE_ERROR_NOT_IMPLEMENTED:
|
|
break;
|
|
}
|
|
|
|
if (changes)
|
|
{
|
|
//TODO: popup
|
|
|
|
doc->ui_needrefresh = 1;
|
|
|
|
if (ni)
|
|
{
|
|
if (ni->viewer)
|
|
news_viewer_refresh(ni->viewer);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ni && ni->viewer &&
|
|
(ni->viewer->vfeeds.selected == doc->feed))
|
|
news_viewer_feed_selected_infos_refresh(ni->viewer);
|
|
}
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_feeds_timer(void *data)
|
|
{
|
|
NEWS_FEED_FOREACH_BEG();
|
|
if (_feed->doc)
|
|
news_feed_update(_feed);
|
|
NEWS_FEED_FOREACH_END();
|
|
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static int
|
|
_cb_sort_cats(const void *d1, const void *d2)
|
|
{
|
|
const News_Feed_Category *c1, *c2;
|
|
|
|
c1 = d1;
|
|
c2 = d2;
|
|
|
|
return strcmp(c1->name, c2->name);
|
|
}
|
|
|
|
static int
|
|
_cb_sort_feeds(const void *d1, const void *d2)
|
|
{
|
|
const News_Feed *f1, *f2;
|
|
|
|
f1 = d1;
|
|
f2 = d2;
|
|
|
|
return strcmp(f1->name, f2->name);
|
|
}
|