コード例 #1
0
ファイル: feed_list_view.c プロジェクト: lwindolf/liferea
static gboolean
feed_list_view_filter_visible_function (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
{
	gint			count;
	nodePtr			node;

	if (!flv->feedlist_reduced_unread)
		return TRUE;

	gtk_tree_model_get (model, iter, FS_PTR, &node, FS_UNREAD, &count, -1);
	if (!node)
		return FALSE;

	if (IS_FOLDER (node) || IS_NODE_SOURCE (node))
		return FALSE;

	if (IS_VFOLDER (node))
		return TRUE;

	/* Do not hide in any case if the node is selected, otherwise
	   the last unread item of a feed causes the feed to vanish
	   when clicking it */
	if (feedlist_get_selected () == node)
		return TRUE;

	if (count > 0)
		return TRUE;

	return FALSE;
}
コード例 #2
0
ファイル: feedlist.c プロジェクト: dmitryvk/liferea
/* This method tries to find a feed with unread items 
   in two passes. In the first pass it tries to find one
   after the currently selected feed (including the
   selected feed). If there are no such feeds the 
   search is restarted for all feeds. */
static nodePtr
feedlist_unread_scan (nodePtr folder)
{
	nodePtr		childNode;
	GSList		*selectedIter = NULL;

	if (SELECTED)
		selectedIter = g_slist_find(SELECTED->parent->children, SELECTED);
	else
		scanState = UNREAD_SCAN_SECOND_PASS;

	GSList *iter = folder->children;
	while (iter) {
		nodePtr node = iter->data;

		if (node == SELECTED)
			scanState = UNREAD_SCAN_FOUND_SELECTED;

		/* feed match if beyond the selected feed or in second pass... */
		if ((scanState != UNREAD_SCAN_INIT) && (node->unreadCount > 0) &&
		    (NULL == node->children) && !IS_VFOLDER(node)) {
		       return node;
		}

		/* folder traversal if we are searching the selected feed
		   which might be a descendant of the folder and if we
		   are beyond the selected feed and the folder contains
		   feeds with unread items... */
		if (node->children &&
		    (((scanState != UNREAD_SCAN_INIT) && (node->unreadCount > 0)) ||
		     (selectedIter && (node_is_ancestor (node, SELECTED))))) {
			childNode = feedlist_unread_scan (node);
			if (childNode)
				return childNode;
		}

		iter = g_slist_next (iter);
	}

	/* When we come here we didn't find anything from the selected
	   feed down to the end of the feed list. */
	if (folder == ROOTNODE) {
		if (0 == ROOTNODE->unreadCount) {
			/* this may mean there is nothing more to find */
		} else {
			/* or that there are unread items above the selected feed */
			g_assert (scanState != UNREAD_SCAN_SECOND_PASS);
			scanState = UNREAD_SCAN_SECOND_PASS;
			return feedlist_unread_scan (ROOTNODE);
		}
	}

	return NULL;
}
コード例 #3
0
ファイル: node.c プロジェクト: lwindolf/liferea
void
node_mark_all_read (nodePtr node)
{
	if (!node)
		return;

	if ((node->unreadCount > 0) || (IS_VFOLDER (node))) {
		itemset_mark_read (node);
		node->unreadCount = 0;
		node->needsUpdate = TRUE;
	}

	if (node->children)
		node_foreach_child (node, node_mark_all_read);
}
コード例 #4
0
ファイル: itemlist.c プロジェクト: skagedal/liferea
// FIXME: is this an item set method?
static gboolean
itemlist_filter_check_item (itemPtr item)
{
	/* use search folder rule list in case of a search folder */
	if (itemlist->priv->currentNode && IS_VFOLDER (itemlist->priv->currentNode)) {
		vfolderPtr vfolder = (vfolderPtr)itemlist->priv->currentNode->data;
		return itemset_check_item (vfolder->itemset, item);
	}

	/* apply the item list filter if available */
	if (itemlist->priv->filter)
		return itemset_check_item (itemlist->priv->filter, item);
	
	/* otherwise keep the item */
	return TRUE;
}
コード例 #5
0
ファイル: itemlist.c プロジェクト: LMephisto/liferea
/**
 * To be called whenever an itemset was updated. If it is the
 * displayed itemset it will be merged against the item list
 * tree view.
 */
void
itemlist_merge_itemset (itemSetPtr itemSet) 
{
	gint	folder_display_mode;

	debug_enter ("itemlist_merge_itemset");
	
	debug_start_measurement (DEBUG_GUI);
	
	/* No node check when loading search results directly */
	if (!itemlist_priv.isSearchResult) {
		nodePtr node = node_from_id (itemSet->nodeId);

		if (!itemlist_priv.currentNode)
			return; /* Nothing to do if nothing is displayed */
		
		if (!IS_VFOLDER (itemlist_priv.currentNode) &&
		    (itemlist_priv.currentNode != node) && 
		    !node_is_ancestor (itemlist_priv.currentNode, node))
			return; /* Nothing to do if the item set does not belong to this node, or this is a search folder */

		conf_get_int_value (FOLDER_DISPLAY_MODE, &folder_display_mode);
		if (IS_FOLDER (itemlist_priv.currentNode) && !folder_display_mode)
			return; /* Bail out if it is a folder without the recursive display preference set */
			
		debug1 (DEBUG_GUI, "reloading item list with node \"%s\"", node_get_title (node));
	} else {
		/* If we are loading a search result we must never merge 
		   anything besides the search items. In fact if we already
		   have items we just return. */
		if (itemlist_priv.searchResultComplete)
			return;
			
		itemlist_priv.searchResultComplete = TRUE;
	}

	/* merge items into item view */
	itemset_foreach (itemSet, itemlist_merge_item);
	
	itemview_update ();
	
	debug_end_measurement (DEBUG_GUI, "itemlist merge");

	debug_exit ("itemlist_merge_itemset");
}
コード例 #6
0
ファイル: node.c プロジェクト: lwindolf/liferea
void
node_update_counters (nodePtr node)
{
	guint oldUnreadCount = node->unreadCount;
	guint oldItemCount = node->itemCount;

	/* Update the node itself and its children */
	node_calc_counters (node);

	if ((oldUnreadCount != node->unreadCount) ||
	    (oldItemCount != node->itemCount))
		feed_list_view_update_node (node->id);

	/* Update the unread count of the parent nodes,
	   usually they just add all child unread counters */
	if (!IS_VFOLDER (node))
		node_update_parent_counters (node->parent);
}
コード例 #7
0
ファイル: ui_indicator.c プロジェクト: skagedal/liferea
static void
add_node_indicator (nodePtr node)
{
	IndicateIndicator *indicator;
	GdkPixbuf *pixbuf;
	gchar count[10];
	
	if (indicator_priv->indicators->len >= MAX_INDICATORS)
		return;

	if (IS_VFOLDER(node) || g_slist_length (node->children) > 0) {
		/* Not a feed - walk children and do nothing more */
		node_foreach_child (node, add_node_indicator);
		return;
	}
	
	/* Skip feeds with no unread items */
	if (node->unreadCount == 0)
		return;
	
	indicator = indicate_indicator_new_with_server (indicator_priv->server);
	g_signal_connect (indicator, "user-display", G_CALLBACK (on_indicator_clicked), node);

	/* load favicon */
	pixbuf = gdk_pixbuf_new_from_file (node->iconFile, NULL);

	/* display favicon */
	indicate_gtk_indicator_set_property_icon (indicator, "icon", pixbuf);
	g_object_unref (pixbuf);

	sprintf (count, "%u", node->unreadCount);
	indicate_indicator_set_property (indicator, "name", node->title);
	indicate_indicator_set_property (indicator, "count", count);
#if SET_DRAW_ATTENTION
	indicate_indicator_set_property_bool (indicator, "draw-attention", TRUE);
#endif
	g_ptr_array_add (indicator_priv->indicators, indicator);
}
コード例 #8
0
ファイル: itemlist.c プロジェクト: skagedal/liferea
/* Helper method checking if the passed item set is relevant
   for the currently item list content. */
static gboolean
itemlist_itemset_is_valid (itemSetPtr itemSet)
{
	gint	folder_display_mode;
	nodePtr node;

	node = node_from_id (itemSet->nodeId);

	if (!itemlist->priv->currentNode)
		return FALSE; /* Nothing to do if nothing is displayed */
		
	if (!IS_VFOLDER (itemlist->priv->currentNode) &&
	    (itemlist->priv->currentNode != node) && 
	    !node_is_ancestor (itemlist->priv->currentNode, node))
		return FALSE; /* Nothing to do if the item set does not belong to this node, or this is a search folder */

	conf_get_int_value (FOLDER_DISPLAY_MODE, &folder_display_mode);
	if (IS_FOLDER (itemlist->priv->currentNode) && !folder_display_mode)
		return FALSE; /* Bail out if it is a folder without the recursive display preference set */
		
	debug1 (DEBUG_GUI, "reloading item list with node \"%s\"", node_get_title (node));

	return TRUE;
}
コード例 #9
0
ファイル: feed_list_node.c プロジェクト: Hawtom/liferea
void
feed_list_node_update (const gchar *nodeId)
{
	GtkTreeIter	*iter;
	gchar		*label, *count = NULL;
	guint		labeltype;
	nodePtr		node;

	static gchar	*countColor = NULL;

	node = node_from_id (nodeId);
	iter = feed_list_node_to_iter (nodeId);
	if (!iter)
		return;

	/* Initialize unread item color Pango CSS */
	if (!countColor) {
		const gchar *bg = NULL, *fg = NULL;

		bg = render_get_theme_color ("FEEDLIST_UNREAD_BG");
		fg = render_get_theme_color ("FEEDLIST_UNREAD_FG");
		if (fg && bg) {
			countColor = g_strdup_printf ("foreground='#%s' background='#%s'", fg, bg);
			debug1 (DEBUG_HTML, "Feed list unread CSS: %s\n", countColor);
		}
	}

	labeltype = NODE_TYPE (node)->capabilities;
	labeltype &= (NODE_CAPABILITY_SHOW_UNREAD_COUNT |
        	      NODE_CAPABILITY_SHOW_ITEM_COUNT);

	if (node->unreadCount == 0 && (labeltype & NODE_CAPABILITY_SHOW_UNREAD_COUNT))
		labeltype -= NODE_CAPABILITY_SHOW_UNREAD_COUNT;

	label = g_markup_escape_text (node_get_title (node), -1);
	switch (labeltype) {
		case NODE_CAPABILITY_SHOW_UNREAD_COUNT |
		     NODE_CAPABILITY_SHOW_ITEM_COUNT:
	     		/* treat like show unread count */
		case NODE_CAPABILITY_SHOW_UNREAD_COUNT:
			count = g_strdup_printf ("<span weight='bold' %s> %u </span>", countColor?countColor:"", node->unreadCount);
			break;
		case NODE_CAPABILITY_SHOW_ITEM_COUNT:
			count = g_strdup_printf ("<span weight='bold' %s> %u </span>", countColor?countColor:"", node->itemCount);
		     	break;
		default:
			break;
	}

	/* Extra message for search folder rebuilds */
	if (IS_VFOLDER (node) && node->data) {
		if (((vfolderPtr)node->data)->reloading) {
			gchar *tmp = label;
			label = g_strdup_printf (_("%s\n<i>Rebuilding</i>"), label);
			g_free (tmp);
		}
	}

	gtk_tree_store_set (feedstore, iter,
	                    FS_LABEL, label,
	                    FS_UNREAD, node->unreadCount,
	                    FS_ICON, node->available?node_get_icon (node):icon_get (ICON_UNAVAILABLE),
	                    FS_COUNT, count,
	                    -1);
	g_free (label);

	if (node->parent)
		feed_list_node_update (node->parent->id);
}
コード例 #10
0
ファイル: htmlview.c プロジェクト: asl97/liferea
void
htmlview_update (LifereaHtmlView *htmlview, itemViewMode mode) 
{
	GSList		*iter;
	GString		*output;
	itemPtr		item = NULL;
	gchar		*baseURL = NULL;
	gboolean	summaryMode;

	/* determine base URL */
	switch (mode) {
		case ITEMVIEW_SINGLE_ITEM:
			item = itemlist_get_selected ();
			if(item) {
				baseURL = (gchar *)node_get_base_url (node_from_id (item->nodeId));
				item_unload (item);
			}
			break;
		default:
			if (htmlView_priv.node)
				baseURL = (gchar *) node_get_base_url (htmlView_priv.node);
			break;
	}

	if (baseURL)
		baseURL = g_markup_escape_text (baseURL, -1);
		
	output = g_string_new (NULL);
	htmlview_start_output (output, baseURL, TRUE, TRUE);

	/* HTML view updating means checking which items
	   need to be updated, render them and then 
	   concatenate everything from cache and output it */
	switch (mode) {
		case ITEMVIEW_SINGLE_ITEM:
			item = itemlist_get_selected ();
			if (item) {
				gchar *html = htmlview_render_item (item, mode, FALSE);
				if (html) {
					g_string_append (output, html);
					g_free (html);
				}
				
				item_unload (item);
			}
			break;
		case ITEMVIEW_ALL_ITEMS:
			/* Output optimization for feeds without item content. This
			   is not done for folders, because we only support all items
			   in summary mode or all in detailed mode. With folder item 
			   sets displaying everything in summary because of only a
			   single feed without item descriptions would make no sense. */

			summaryMode = (NULL != htmlView_priv.node) &&
			              !IS_FOLDER (htmlView_priv.node) && 
	        		      !IS_VFOLDER (htmlView_priv.node) && 
	        		      (htmlView_priv.missingContent > 3);

			/* concatenate all items */
			iter = htmlView_priv.orderedChunks;
			while (iter) {
				/* try to retrieve item HTML chunk from cache */
				htmlChunkPtr chunk = (htmlChunkPtr)iter->data;
				
				/* if not found: render new item now and add to cache */
				if (!chunk->html) {
					item = item_load (chunk->id);
					if (item) {
						debug1 (DEBUG_HTML, "rendering item to HTML view: >>>%s<<<", item_get_title (item));
						chunk->html = htmlview_render_item (item, mode, summaryMode);
						item_unload (item);
					}
				}
				
				if (chunk->html)
					g_string_append (output, chunk->html);
					
				iter = g_slist_next (iter);
			}
			break;
		case ITEMVIEW_NODE_INFO:
			{
				gchar *html;
				
				if (htmlView_priv.node) {
					html = node_render (htmlView_priv.node);	
					if (html) {
						g_string_append (output, html);
						g_free (html);
					}
				}
			}
			break;
		default:
			g_warning ("HTML view: invalid viewing mode!!!");
			break;
	}
	
	htmlview_finish_output (output);

	debug1 (DEBUG_HTML, "writing %d bytes to HTML view", strlen (output->str));
	liferea_htmlview_write (htmlview, output->str, baseURL);
	
	g_string_free (output, TRUE);
	g_free (baseURL);
}