Hello community, here is the log from the commit of package liferea for openSUSE:Factory checked in at 2012-11-16 13:39:54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/liferea (Old) and /work/SRC/openSUSE:Factory/.liferea.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "liferea", Maintainer is "gnome-maintain...@suse.de" Changes: -------- --- /work/SRC/openSUSE:Factory/liferea/liferea.changes 2012-10-16 12:02:40.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.liferea.new/liferea.changes 2012-11-16 13:39:57.000000000 +0100 @@ -1,0 +2,13 @@ +Wed Oct 31 12:06:15 UTC 2012 - dims...@opensuse.org + +- Update to version 1.8.10: + + Fix crash in google_source_remove_node (sf#3572660). + + Prevents adding folders/search folders/newsbins to Google + Reader. + + Prevents sorting subscriptions in Google Reader + + Fixes items not removed from search folder count when feed is + removed. + + Fixes search folder rebuilding (do not include comment items). + + Fixes SELECT offset handling when rebuilding search folders. + +------------------------------------------------------------------- Old: ---- liferea-1.8.9.tar.gz New: ---- liferea-1.8.10.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ liferea.spec ++++++ --- /var/tmp/diff_new_pack.igklBg/_old 2012-11-16 13:39:59.000000000 +0100 +++ /var/tmp/diff_new_pack.igklBg/_new 2012-11-16 13:39:59.000000000 +0100 @@ -17,13 +17,13 @@ Name: liferea -Version: 1.8.9 +Version: 1.8.10 Release: 0 Summary: Linux Feed Reader License: GPL-2.0+ Group: Productivity/Other Url: http://liferea.sourceforge.net/ -Source: http://downloads.sourceforge.net/project/liferea/Liferea%20Stable/1.8.9/%{name}-%{version}.tar.gz +Source: http://downloads.sourceforge.net/project/liferea/Liferea%20Stable/1.8.10/%{name}-%{version}.tar.bz2 # PATCH-FEATURE-OPENSUSE liferea-opensuse-feeds.patch -- Add openSUSE feeds to default feeds Patch0: liferea-opensuse-feeds.patch BuildRequires: fdupes ++++++ liferea-1.8.9.tar.gz -> liferea-1.8.10.tar.bz2 ++++++ ++++ 2870 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/ChangeLog new/liferea-1.8.10/ChangeLog --- old/liferea-1.8.9/ChangeLog 2012-10-04 22:10:04.000000000 +0200 +++ new/liferea-1.8.10/ChangeLog 2012-10-30 21:01:26.000000000 +0100 @@ -1,3 +1,16 @@ +2012-10-30 Lars Windolf <lars.lind...@gmail.com> + + Version 1.8.10 + + * Fixes SF #3572660: crash in google_source_remove_node + (reported by Yanko Kaneti) + * Prevents adding folders/search folders/newsbins to Google Reader + * Prevents sorting subscriptions in Google Reader + * Fixes items not removed from search folder count when feed is removed. + * Fixes search folder rebuilding (do not include comment items). + * Fixes SELECT offset handling when rebuilding search folders. + + 2012-10-04 Lars Windolf <lars.lind...@gmail.com> Version 1.8.9 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/configure.ac new/liferea-1.8.10/configure.ac --- old/liferea-1.8.9/configure.ac 2012-10-04 22:10:28.000000000 +0200 +++ new/liferea-1.8.10/configure.ac 2012-10-30 20:41:30.000000000 +0100 @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT([liferea],[1.8.9],[liferea-de...@lists.sourceforge.net]) +AC_INIT([liferea],[1.8.10],[liferea-de...@lists.sourceforge.net]) AC_CANONICAL_HOST AC_CONFIG_SRCDIR([src/feedlist.c]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/db.c new/liferea-1.8.10/src/db.c --- old/liferea-1.8.9/src/db.c 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/db.c 2012-10-30 22:01:24.000000000 +0100 @@ -35,6 +35,7 @@ http://lzone.de/wiki/doku.php?id=liferea:v1.8:db_schema */ static sqlite3 *db = NULL; +gboolean searchFolderRebuild = FALSE; /** hash of all prepared statements */ static GHashTable *statements = NULL; @@ -247,7 +248,7 @@ db_exec("PRAGMA synchronous=NORMAL"); } -#define SCHEMA_TARGET_VERSION 9 +#define SCHEMA_TARGET_VERSION 10 /* opening or creation of database */ void @@ -417,6 +418,22 @@ sqlite3_finalize (stmt); } } + + if (db_get_schema_version () == 9) { + /* A parent node id to search folder relation to allow cleanups */ + db_exec ("BEGIN; " + "DROP TABLE search_folder_items; " + "CREATE TABLE search_folder_items (" + " node_id STRING," + " parent_node_id STRING," + " item_id INTEGER," + " PRIMARY KEY (node_id, item_id)" + ");" + "REPLACE INTO info (name, value) VALUES ('schemaVersion',10); " + "END;" ); + + searchFolderRebuild = TRUE; + } } if (SCHEMA_TARGET_VERSION != db_get_schema_version ()) @@ -505,6 +522,7 @@ db_exec ("CREATE TABLE search_folder_items (" " node_id STRING," + " parent_node_id STRING," " item_id INTEGER," " PRIMARY KEY (node_id, item_id)" ");"); @@ -534,10 +552,17 @@ " DELETE FROM items WHERE item_id IN (SELECT id FROM tmp_id LIMIT 1000);" " DROP TABLE tmp_id;" "END;"); + + debug0 (DEBUG_DB, "Checking for search folder items without a feed list node...\n"); + db_exec ("DELETE FROM search_folder_items WHERE parent_node_id NOT IN " + "(SELECT node_id FROM node);"); - debug0 (DEBUG_DB, "Checking for search folder items without a feed list node...\n"); + debug0 (DEBUG_DB, "Checking for search folder items without a search folder...\n"); db_exec ("DELETE FROM search_folder_items WHERE node_id NOT IN " - "(SELECT node_id FROM node);"); + "(SELECT node_id FROM node);"); + + debug0 (DEBUG_DB, "Checking for search folder with comments...\n"); + db_exec ("DELETE FROM search_folder_items WHERE comment = 1;"); debug0 (DEBUG_DB, "DB cleanup finished. Continuing startup."); @@ -554,6 +579,7 @@ "BEGIN " " DELETE FROM node WHERE node_id = old.node_id; " " DELETE FROM subscription_metadata WHERE node_id = old.node_id; " + " DELETE FROM search_folder_items WHERE parent_node_id = old.node_id; " "END;"); /* Note: view counting triggers are set up in the view preparation code (see db_view_create()) */ @@ -563,7 +589,7 @@ "SELECT item_id FROM items WHERE node_id = ?"); db_new_statement ("itemsetLoadOffsetStmt", - "SELECT item_id FROM items WHERE item_id >= ? limit ?"); + "SELECT item_id FROM items WHERE comment = 0 LIMIT ? OFFSET ?"); db_new_statement ("itemsetReadCountStmt", "SELECT COUNT(item_id) FROM items " @@ -679,10 +705,22 @@ "REPLACE INTO node (node_id,parent_id,title,type,expanded,view_mode,sort_column,sort_reversed) VALUES (?,?,?,?,?,?,?,?)"); db_new_statement ("itemUpdateSearchFoldersStmt", - "REPLACE INTO search_folder_items (node_id, item_id) VALUES (?,?)"); + "REPLACE INTO search_folder_items (node_id, parent_node_id, item_id) VALUES (?,?,?)"); + + db_new_statement ("itemRemoveFromSearchFolderStmt", + "DELETE FROM search_folder_items WHERE node_id =? AND item_id = ?;"); db_new_statement ("searchFolderLoadStmt", "SELECT item_id FROM search_folder_items WHERE node_id = ?;"); + + db_new_statement ("searchFolderCountStmt", + "SELECT count(item_id) FROM search_folder_items WHERE node_id = ?;"); + + db_new_statement ("nodeIdListStmt", + "SELECT node_id FROM node;"); + + db_new_statement ("nodeRemoveStmt", + "DELETE FROM node WHERE node_id = ?;"); g_assert (sqlite3_get_autocommit (db)); @@ -921,27 +959,49 @@ gint res; GSList *iter, *list; - // FIXME: also remove from search folders + /* Add item to all search folders it now belongs to */ stmt = db_get_statement ("itemUpdateSearchFoldersStmt"); - iter = list = vfolder_get_all_with_item_id (item->id); + iter = list = vfolder_get_all_with_item_id (item); while (iter) { vfolderPtr vfolder = (vfolderPtr)iter->data; sqlite3_reset (stmt); sqlite3_bind_text (stmt, 1, vfolder->node->id, -1, SQLITE_TRANSIENT); - sqlite3_bind_int (stmt, 2, item->id); - res = sqlite3_step (stmt); + sqlite3_bind_text (stmt, 2, item->nodeId, -1, SQLITE_TRANSIENT); + sqlite3_bind_int (stmt, 3, item->id); + res = sqlite3_step (stmt); if (SQLITE_DONE != res) - g_warning ("item update of search folders failed (error code=%d, %s)", res, sqlite3_errmsg (db)); - iter = g_slist_next (iter); + g_warning ("item add to search folder failed (error code=%d, %s)", res, sqlite3_errmsg (db)); + iter = g_slist_next (iter); } - g_slist_free (iter); + g_slist_free (list); sqlite3_finalize (stmt); + /* Remove item from all search folders it does not belong + (we do not check if it is in there, just remove it) */ + + stmt = db_get_statement ("itemRemoveFromSearchFolderStmt"); + iter = list = vfolder_get_all_without_item_id (item); + while (iter) { + vfolderPtr vfolder = (vfolderPtr)iter->data; + + sqlite3_reset (stmt); + sqlite3_bind_text (stmt, 1, vfolder->node->id, -1, SQLITE_TRANSIENT); + sqlite3_bind_int (stmt, 2, item->id); + res = sqlite3_step (stmt); + + if (SQLITE_DONE != res) + g_warning ("item remove from search folder failed (error code=%d, %s)", res, sqlite3_errmsg (db)); + + iter = g_slist_next (iter); + } + g_slist_free (list); + + sqlite3_finalize (stmt); } void @@ -971,7 +1031,7 @@ sqlite3_bind_text (stmt, 6, item->source, -1, SQLITE_TRANSIENT); sqlite3_bind_text (stmt, 7, item->sourceId, -1, SQLITE_TRANSIENT); sqlite3_bind_int (stmt, 8, item->validGuid?1:0); - sqlite3_bind_text (stmt, 9, item->description, -1, SQLITE_TRANSIENT); + sqlite3_bind_text (stmt, 9, item->description, -1, SQLITE_TRANSIENT); sqlite3_bind_int (stmt, 10, item->time); sqlite3_bind_text (stmt, 11, item->commentFeedId, -1, SQLITE_TRANSIENT); sqlite3_bind_int (stmt, 12, item->isComment?1:0); @@ -1137,16 +1197,16 @@ } gboolean -db_itemset_get (itemSetPtr itemSet, gulong id, guint limit) +db_itemset_get (itemSetPtr itemSet, gulong offset, guint limit) { sqlite3_stmt *stmt; gboolean success = FALSE; - debug2 (DEBUG_DB, "loading %d items starting with %lu", limit, id); + debug2 (DEBUG_DB, "loading %d items offset %lu", limit, offset); stmt = db_get_statement ("itemsetLoadOffsetStmt"); - sqlite3_bind_int (stmt, 1, id); - sqlite3_bind_int (stmt, 2, limit); + sqlite3_bind_int (stmt, 1, limit); + sqlite3_bind_int (stmt, 2, offset); while (sqlite3_step (stmt) == SQLITE_ROW) { itemSet->ids = g_list_append (itemSet->ids, GUINT_TO_POINTER (sqlite3_column_int (stmt, 0))); @@ -1346,7 +1406,8 @@ sqlite3_reset (stmt); sqlite3_bind_text (stmt, 1, id, -1, SQLITE_TRANSIENT); - sqlite3_bind_int (stmt, 2, item->id); + sqlite3_bind_text (stmt, 2, item->nodeId, -1, SQLITE_TRANSIENT); + sqlite3_bind_int (stmt, 3, item->id); res = sqlite3_step (stmt); if (SQLITE_DONE != res) g_error ("db_search_folder_add_items: sqlite3_step (error code %d)!", res); @@ -1360,6 +1421,31 @@ debug0 (DEBUG_DB, "adding items to search folder finished"); } +guint +db_search_folder_get_item_count (const gchar *id) +{ + sqlite3_stmt *stmt; + gint res; + guint count = 0; + + debug_start_measurement (DEBUG_DB); + + stmt = db_get_statement ("searchFolderCountStmt"); + sqlite3_bind_text (stmt, 1, id, -1, SQLITE_TRANSIENT); + res = sqlite3_step (stmt); + + if (SQLITE_ROW == res) + count = sqlite3_column_int (stmt, 0); + else + g_warning("item read counting failed (error code=%d, %s)", res, sqlite3_errmsg (db)); + + sqlite3_finalize (stmt); + + debug_end_measurement (DEBUG_DB, "counting unread items"); + + return count; +} + static GSList * db_subscription_metadata_load(const gchar *id) { @@ -1497,3 +1583,59 @@ debug_end_measurement (DEBUG_DB, "subscription_update"); } + +static gboolean +db_node_find (nodePtr node, gpointer id) +{ + GSList *iter; + + if (g_str_equal (node->id, (gchar *)id)) + return TRUE; + + iter = node->children; + while (iter) { + if (db_node_find ((nodePtr)iter->data, id)) + return TRUE; + iter = g_slist_next (iter); + } + + return FALSE; +} + +static void +db_node_remove (const gchar *id) +{ + sqlite3_stmt *stmt; + gint res; + + stmt = db_get_statement ("nodeRemoveStmt"); + sqlite3_bind_text (stmt, 1, id, -1, SQLITE_TRANSIENT); + + res = sqlite3_step (stmt); + if (SQLITE_DONE != res) + g_warning ("Could not remove node %s in DB (error code %d)!", id, res); + + sqlite3_finalize (stmt); +} + +void +db_node_cleanup (nodePtr root) +{ + sqlite3_stmt *stmt; + gint res; + + debug0 (DEBUG_DB, "Cleaning node ids..."); + + /* Fetch all node ids */ + stmt = db_get_statement ("nodeIdListStmt"); + while (sqlite3_step (stmt) == SQLITE_ROW) { + /* Drop node ids not in feed list anymore */ + const gchar *id = sqlite3_column_text (stmt, 0); + if (!db_node_find (root, (gpointer)id)) { + db_subscription_remove (id); /* in case it is a subscription */ + db_node_remove (id); /* in case it is a folder */ + } + } + + sqlite3_finalize (stmt); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/db.h new/liferea-1.8.10/src/db.h --- old/liferea-1.8.9/src/db.h 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/db.h 2012-10-30 20:49:05.000000000 +0100 @@ -84,18 +84,17 @@ /** * Returns a batch of items starting with the given - * id and no more than the given limit. If ids are not - * consecutive less ids than limit might be returned. + * offset and no more than the given limit. * * To be used for batched item loading (search folder loaders) * * @param itemSet an itemset to add the items to - * @param id the first id to fetch + * @param offset the current offset * @param limit maximum number of items to fetch * * @returns FALSE if no more items to fetch */ -gboolean db_itemset_get (itemSetPtr itemSet, gulong id, guint limit); +gboolean db_itemset_get (itemSetPtr itemSet, gulong offset, guint limit); /* item access (note: items are identified by the numeric item id) */ @@ -172,6 +171,15 @@ void db_search_folder_add_items (const gchar *id, GSList *items); /** + * Returns the number of items for the given search folder. + * + * @param id the node id + * + * @returns the number of items + */ +guint db_search_folder_get_item_count (const gchar *id); + +/** * Load the metadata and update state of the given subscription. * * @param subscription the subscription whose info to load @@ -199,4 +207,13 @@ */ void db_node_update (nodePtr node); + +/** + * Clean old nodes from the DB by comparing all DB nodes + * against the OPML feed list. + * + * @param root the root node + */ +void db_node_cleanup (nodePtr root); + #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/feedlist.c new/liferea-1.8.10/src/feedlist.c --- old/liferea-1.8.9/src/feedlist.c 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/feedlist.c 2012-10-30 22:05:59.000000000 +0100 @@ -185,11 +185,14 @@ feedlist_reset_update_counters (NULL); } - /* 5. Start automatic updating */ + /* 5. Purge old nodes from the database */ + db_node_cleanup (feedlist_get_root ()); + + /* 6. Start automatic updating */ feedlist->priv->autoUpdateTimer = g_timeout_add_seconds (10, feedlist_auto_update, NULL); g_signal_connect (network_monitor_get (), "online-status-changed", G_CALLBACK (on_network_status_changed), NULL); - /* 6. Finally save the new feed list state */ + /* 7. Finally save the new feed list state */ feedlist->priv->loading = FALSE; feedlist_schedule_save (); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/fl_sources/default_source.c new/liferea-1.8.10/src/fl_sources/default_source.c --- old/liferea-1.8.9/src/fl_sources/default_source.c 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/fl_sources/default_source.c 2012-10-30 20:41:30.000000000 +0100 @@ -1,7 +1,7 @@ /** * @file default_source.c default static feed list source * - * Copyright (C) 2005-2010 Lars Lindner <lars.lind...@gmail.com> + * Copyright (C) 2005-2012 Lars Lindner <lars.lind...@gmail.com> * Copyright (C) 2005-2006 Nathan J. Conrad <t98...@users.sourceforge.net> * * This program is free software; you can redistribute it and/or modify @@ -210,6 +210,8 @@ .description = "The default feed list source. Should never be added manually. If you see this then something went wrong!", .capabilities = NODE_SOURCE_CAPABILITY_IS_ROOT | NODE_SOURCE_CAPABILITY_HIERARCHIC_FEEDLIST | + NODE_SOURCE_CAPABILITY_ADD_FEED | + NODE_SOURCE_CAPABILITY_ADD_FOLDER | NODE_SOURCE_CAPABILITY_WRITABLE_FEEDLIST, .source_type_init = default_source_init, .source_type_deinit = default_source_deinit, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/fl_sources/google_source.c new/liferea-1.8.10/src/fl_sources/google_source.c --- old/liferea-1.8.9/src/fl_sources/google_source.c 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/fl_sources/google_source.c 2012-10-30 20:41:30.000000000 +0100 @@ -373,9 +373,10 @@ .id = "fl_google", .name = N_("Google Reader"), .description = N_("Integrate the feed list of your Google Reader account. Liferea will " - "present your Google Reader subscriptions, and will synchronize your feed list and reading lists."), + "present your Google Reader subscriptions, and will synchronize your feed list and reading lists."), .capabilities = NODE_SOURCE_CAPABILITY_DYNAMIC_CREATION | NODE_SOURCE_CAPABILITY_WRITABLE_FEEDLIST | + NODE_SOURCE_CAPABILITY_ADD_FEED | NODE_SOURCE_CAPABILITY_ITEM_STATE_SYNC, .source_type_init = google_source_init, .source_type_deinit = google_source_deinit, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/fl_sources/node_source.h new/liferea-1.8.10/src/fl_sources/node_source.h --- old/liferea-1.8.9/src/fl_sources/node_source.h 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/fl_sources/node_source.h 2012-10-30 20:41:30.000000000 +0100 @@ -1,7 +1,7 @@ /** * @file node_source.h generic node source interface * - * Copyright (C) 2005-2010 Lars Lindner <lars.lind...@gmail.com> + * Copyright (C) 2005-2012 Lars Lindner <lars.lind...@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -50,11 +50,12 @@ enum { NODE_SOURCE_CAPABILITY_IS_ROOT = (1<<0), /**< flag only for default feed list source */ - NODE_SOURCE_CAPABILITY_MULTI_INSTANCES = (1<<1), /**< allows multiple source instances */ - NODE_SOURCE_CAPABILITY_DYNAMIC_CREATION = (1<<2), /**< feed list source is user created */ - NODE_SOURCE_CAPABILITY_WRITABLE_FEEDLIST = (1<<3), /**< the feed list tree of the source can be changed */ - NODE_SOURCE_CAPABILITY_HIERARCHIC_FEEDLIST = (1<<4), /**< the feed list tree of the source can have hierarchic folders */ - NODE_SOURCE_CAPABILITY_ITEM_STATE_SYNC = (1<<5) /**< the item state can and should be sync'ed with remote */ + NODE_SOURCE_CAPABILITY_DYNAMIC_CREATION = (1<<1), /**< feed list source is user created */ + NODE_SOURCE_CAPABILITY_WRITABLE_FEEDLIST = (1<<2), /**< the feed list tree of the source can be changed */ + NODE_SOURCE_CAPABILITY_ADD_FEED = (1<<3), /**< feeds can be added to the source */ + NODE_SOURCE_CAPABILITY_ADD_FOLDER = (1<<4), /**< folders can be added to the source */ + NODE_SOURCE_CAPABILITY_HIERARCHIC_FEEDLIST = (1<<5), /**< the feed list tree of the source can have hierarchic folders */ + NODE_SOURCE_CAPABILITY_ITEM_STATE_SYNC = (1<<6) /**< the item state can and should be sync'ed with remote */ }; /** feed list node source type */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/fl_sources/ttrss_source.c new/liferea-1.8.10/src/fl_sources/ttrss_source.c --- old/liferea-1.8.9/src/fl_sources/ttrss_source.c 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/fl_sources/ttrss_source.c 2012-10-30 20:41:30.000000000 +0100 @@ -1,7 +1,7 @@ /** * @file ttrss_source.c tt-rss feed list source support * - * Copyright (C) 2010-2011 Lars Lindner <lars.lind...@gmail.com> + * Copyright (C) 2010-2012 Lars Lindner <lars.lind...@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -364,7 +364,7 @@ .name = N_("Tiny Tiny RSS"), .description = N_("Integrate the feed list of your Tiny Tiny RSS 1.5+ account. Liferea will " "present your tt-rss subscriptions, and will synchronize your feed list and reading lists."), - .capabilities = NODE_SOURCE_CAPABILITY_DYNAMIC_CREATION | + .capabilities = NODE_SOURCE_CAPABILITY_DYNAMIC_CREATION | NODE_SOURCE_CAPABILITY_ITEM_STATE_SYNC, .source_type_init = ttrss_source_init, .source_type_deinit = ttrss_source_deinit, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/item_state.c new/liferea-1.8.10/src/item_state.c --- old/liferea-1.8.9/src/item_state.c 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/item_state.c 2012-10-30 20:49:05.000000000 +0100 @@ -51,13 +51,12 @@ /* 1. set value in memory */ item->flagStatus = newState; - /* 2. propagate to vfolders */ - vfolder_foreach_data (vfolder_merge_item, item); - vfolder_foreach (node_update_counters); - - /* 3. save state to DB */ + /* 2. save state to DB */ db_item_state_update (item); + /* 3. update vfolder counters */ + vfolder_foreach (node_update_counters); + /* 4. update item list GUI state */ itemlist_update_item (item); @@ -93,13 +92,12 @@ item->readStatus = newState; item->updateStatus = FALSE; - /* 2. propagate to vfolders */ - vfolder_foreach_data (vfolder_merge_item, item); - vfolder_foreach (node_update_counters); - - /* 3. apply to DB */ + /* 2. apply to DB */ db_item_state_update (item); + /* 3. propagate to vfolders */ + vfolder_foreach (node_update_counters); + /* 4. update item list GUI state */ itemlist_update_item (item); @@ -147,10 +145,7 @@ itemset_mark_read (nodePtr node) { itemSetPtr itemSet; - - if (!node->unreadCount) - return; - + itemSet = node_get_itemset (node); GList *iter = itemSet->ids; while (iter) { @@ -158,14 +153,10 @@ itemPtr item = item_load (id); if (item) { if (!item->readStatus) { - nodePtr node; - - node = node_from_id (item->nodeId); + nodePtr node = node_from_id (item->nodeId); if (node) { item_state_set_recount_flag (node); node_source_item_mark_read (node, item, TRUE); - } else { - g_warning ("itemset_mark_read() on lost item (id=%lu, node id=%s)!", item->id, item->nodeId); } debug_start_measurement (DEBUG_GUI); @@ -188,6 +179,8 @@ } iter = g_list_next (iter); } + + // FIXME: why not call itemset_free (itemSet); here? Crashes! } void diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/itemlist.c new/liferea-1.8.10/src/itemlist.c --- old/liferea-1.8.9/src/itemlist.c 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/itemlist.c 2012-10-30 20:49:05.000000000 +0100 @@ -456,9 +456,6 @@ void itemlist_remove_item (itemPtr item) { - /* update search folder counters */ - vfolder_foreach_data (vfolder_remove_item, item); - if (itemlist->priv->selectedId == item->id) { itemlist_set_selected (NULL); itemlist->priv->deferredFilter = FALSE; @@ -471,8 +468,9 @@ itemview_update (); db_item_remove (item->id); - - /* update feed list */ + + /* update feed list counters*/ + vfolder_foreach (node_update_counters); node_update_counters (node_from_id (item->nodeId)); item_unload (item); @@ -502,8 +500,6 @@ while (iter) { itemPtr item = (itemPtr) iter->data; - vfolder_foreach_data (vfolder_remove_item, item); - if (itemlist->priv->selectedId != item->id) { /* don't call itemlist_remove_item() here, because it's to slow */ itemview_remove_item (item); @@ -517,6 +513,7 @@ } itemview_update (); + vfolder_foreach (node_update_counters); node_update_counters (node_from_id (itemSet->nodeId)); } @@ -528,16 +525,6 @@ if (node == itemlist->priv->currentNode) itemview_clear (); - - itemset = db_itemset_load (node->id); - iter = itemset->ids; - while (iter) { - itemPtr item = item_load ((gulong)iter->data); - vfolder_foreach_data (vfolder_remove_item, item); - item_unload (item); - iter = g_list_next (iter); - } - itemset_free (itemset); db_itemset_remove_all (node->id); @@ -546,6 +533,7 @@ itemlist_duplicate_list_free (); } + vfolder_foreach (node_update_counters); node_update_counters (node); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/itemset.c new/liferea-1.8.10/src/itemset.c --- old/liferea-1.8.9/src/itemset.c 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/itemset.c 2012-10-30 20:49:05.000000000 +0100 @@ -375,7 +375,6 @@ item->readStatus = TRUE; if (itemset_merge_item (itemSet, items, item, length, allowUpdates)) { - vfolder_foreach_data (vfolder_merge_item, item); newCount++; items = g_list_prepend (items, iter->data); } @@ -396,13 +395,6 @@ toBeDropped = g_list_length (items) - max; else toBeDropped = 0; - - /* Let's never drop more than 50 items at one time to avoid - long duration migrations. It is ok to drop only some of the - items here, because we can drop the rest during future - feed updates. */ - //if(toBeDropped > 50) - // toBeDropped = 50; debug3 (DEBUG_UPDATE, "%u new items, cache limit is %u -> dropping %u items", newCount, max, toBeDropped); items = g_list_sort (items, itemset_sort_by_date); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/node.c new/liferea-1.8.10/src/node.c --- old/liferea-1.8.9/src/node.c 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/node.c 2012-10-30 20:49:05.000000000 +0100 @@ -1,7 +1,7 @@ /** * @file node.c hierarchic feed list node handling * - * Copyright (C) 2003-2011 Lars Lindner <lars.lind...@gmail.com> + * Copyright (C) 2003-2012 Lars Lindner <lars.lind...@gmail.com> * Copyright (C) 2004-2006 Nathan J. Conrad <t98...@users.sourceforge.net> * * This program is free software; you can redistribute it and/or modify @@ -276,7 +276,7 @@ if (!node) return; - if (0 != node->unreadCount) { + if ((node->unreadCount > 0) || (IS_VFOLDER (node))) { itemset_mark_read (node); node->unreadCount = 0; node->needsUpdate = TRUE; @@ -494,6 +494,28 @@ return baseUrl; } +gboolean +node_can_add_child_feed (nodePtr node) +{ + g_assert (node->source->root); + + if (!(NODE_TYPE (node->source->root)->capabilities & NODE_CAPABILITY_ADD_CHILDS)) + return FALSE; + + return (NODE_SOURCE_TYPE (node)->capabilities & NODE_SOURCE_CAPABILITY_ADD_FEED); +} + +gboolean +node_can_add_child_folder (nodePtr node) +{ + g_assert (node->source->root); + + if (!(NODE_TYPE (node->source->root)->capabilities & NODE_CAPABILITY_ADD_CHILDS)) + return FALSE; + + return (NODE_SOURCE_TYPE (node)->capabilities & NODE_SOURCE_CAPABILITY_ADD_FOLDER); +} + /* node children iterating interface */ void diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/node.h new/liferea-1.8.10/src/node.h --- old/liferea-1.8.9/src/node.h 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/node.h 2012-10-30 20:41:30.000000000 +0100 @@ -1,7 +1,7 @@ /** * @file node.h hierarchic feed list node interface * - * Copyright (C) 2003-2010 Lars Lindner <lars.lind...@gmail.com> + * Copyright (C) 2003-2012 Lars Lindner <lars.lind...@gmail.com> * Copyright (C) 2004-2006 Nathan J. Conrad <t98...@users.sourceforge.net> * * This program is free software; you can redistribute it and/or modify @@ -355,6 +355,24 @@ */ const gchar * node_get_base_url(nodePtr node); +/** + * Query wether a feed be added to the given node. + * + * @param node the node + * + * @returns TRUE if a feed can be added + */ +gboolean node_can_add_child_feed (nodePtr node); + +/** + * Query wether a folder be added to the given node. + * + * @param node the node + * + * @returns TRUE if a folder can be added + */ +gboolean node_can_add_child_folder (nodePtr node); + /* child nodes iterating interface */ typedef void (*nodeActionFunc) (nodePtr node); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/ui/liferea_shell.c new/liferea-1.8.10/src/ui/liferea_shell.c --- old/liferea-1.8.9/src/ui/liferea_shell.c 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/ui/liferea_shell.c 2012-10-30 22:06:17.000000000 +0100 @@ -37,6 +37,7 @@ #include "htmlview.h" #include "itemlist.h" #include "net_monitor.h" +#include "vfolder.h" #include "ui/browser_tabs.h" #include "ui/feed_list_view.h" #include "ui/icons.h" @@ -50,6 +51,8 @@ #include "ui/ui_tray.h" #include "ui/ui_update.h" +extern gboolean searchFolderRebuild; /* db.c */ + #define LIFEREA_SHELL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), LIFEREA_SHELL_TYPE, LifereaShellPrivate)) struct LifereaShellPrivate { @@ -1264,6 +1267,10 @@ liferea_shell_set_online_icon (network_monitor_is_online ()); + /* 11. Rebuild search folders if needed */ + if (searchFolderRebuild) + vfolder_foreach (vfolder_rebuild); + debug_exit ("liferea_shell_create"); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/ui/popup_menu.c new/liferea-1.8.10/src/ui/popup_menu.c --- old/liferea-1.8.9/src/ui/popup_menu.c 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/ui/popup_menu.c 2012-10-30 20:41:30.000000000 +0100 @@ -262,14 +262,15 @@ ui_popup_node_menu (nodePtr node, gboolean validSelection, guint button, guint32 activate_time) { GtkWidget *menu; - gboolean writeableFeedlist, isRoot, isHierarchic; + gboolean writeableFeedlist, isRoot, isHierarchic, addChildren; menu = gtk_menu_new (); if (node->parent) { writeableFeedlist = NODE_SOURCE_TYPE (node->parent->source->root)->capabilities & NODE_SOURCE_CAPABILITY_WRITABLE_FEEDLIST; - isRoot = NODE_SOURCE_TYPE (node->parent->source->root)->capabilities & NODE_SOURCE_CAPABILITY_IS_ROOT; + isRoot = NODE_SOURCE_TYPE (node->source->root)->capabilities & NODE_SOURCE_CAPABILITY_IS_ROOT; isHierarchic = NODE_SOURCE_TYPE (node->parent->source->root)->capabilities & NODE_SOURCE_CAPABILITY_HIERARCHIC_FEEDLIST; + addChildren = NODE_TYPE (node->source->root)->capabilities & NODE_CAPABILITY_ADD_CHILDS; } else { /* if we have no parent then we have the root node... */ writeableFeedlist = TRUE; @@ -287,7 +288,7 @@ } if (writeableFeedlist) { - if (NODE_TYPE (node->source->root)->capabilities & NODE_CAPABILITY_ADD_CHILDS) { + if (addChildren) { GtkWidget *item; GtkWidget *submenu; @@ -295,9 +296,10 @@ item = ui_popup_add_menuitem (menu, _("_New"), NULL, NULL, NULL, 0); - ui_popup_add_menuitem (submenu, _("New _Subscription..."), ui_popup_add_feed, NULL, NULL, 0); + if (node_can_add_child_feed (node)) + ui_popup_add_menuitem (submenu, _("New _Subscription..."), ui_popup_add_feed, NULL, NULL, 0); - if (isHierarchic) + if (node_can_add_child_folder (node)) ui_popup_add_menuitem (submenu, _("New _Folder..."), ui_popup_add_folder, NULL, NULL, 0); if (isRoot) { @@ -309,7 +311,7 @@ gtk_menu_item_set_submenu (GTK_MENU_ITEM(item), submenu); } - if (node->children) { + if (isRoot && node->children) { gtk_menu_shell_append (GTK_MENU_SHELL(menu), gtk_separator_menu_item_new()); ui_popup_add_menuitem (menu, _("Sort Feeds"), ui_popup_sort_feeds, node, GTK_STOCK_SORT_ASCENDING, 0); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/ui/ui_node.c new/liferea-1.8.10/src/ui/ui_node.c --- old/liferea-1.8.9/src/ui/ui_node.c 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/ui/ui_node.c 2012-10-30 20:49:05.000000000 +0100 @@ -26,6 +26,7 @@ #include "feedlist.h" #include "fl_sources/node_source.h" #include "folder.h" +#include "vfolder.h" #include "ui/icons.h" #include "ui/liferea_dialog.h" #include "ui/liferea_shell.h" @@ -313,6 +314,15 @@ 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), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/vfolder.c new/liferea-1.8.10/src/vfolder.c --- old/liferea-1.8.9/src/vfolder.c 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/vfolder.c 2012-10-30 20:49:05.000000000 +0100 @@ -111,9 +111,7 @@ static itemSetPtr vfolder_load (nodePtr node) { - vfolderPtr vfolder = (vfolderPtr)node->data; - - return vfolder->itemset; + return db_search_folder_load (node->id); } void @@ -142,46 +140,31 @@ } } -void -vfolder_remove_item (vfolderPtr vfolder, itemPtr item) -{ - if (!vfolder->itemset->ids) - return; - - vfolder->itemset->ids = g_list_remove (vfolder->itemset->ids, GUINT_TO_POINTER (item->id)); - vfolder->node->needsUpdate = TRUE; -} - -void -vfolder_add_item (vfolderPtr vfolder, itemPtr item) -{ - vfolder->itemset->ids = g_list_append (vfolder->itemset->ids, GUINT_TO_POINTER (item->id)); - vfolder->node->needsUpdate = TRUE; -} - -void -vfolder_merge_item (vfolderPtr vfolder, itemPtr item) +GSList * +vfolder_get_all_with_item_id (itemPtr item) { - gboolean found = itemset_has_item_id (vfolder->itemset, item->id); - - if (itemset_check_item (vfolder->itemset, item)) { - if (!found) - vfolder_add_item (vfolder, item); - } else { - if (found) - vfolder_remove_item (vfolder, item); + GSList *result = NULL; + GSList *iter = vfolders; + + while (iter) { + vfolderPtr vfolder = (vfolderPtr)iter->data; + if (itemset_check_item (vfolder->itemset, item)) + result = g_slist_append (result, vfolder); + iter = g_slist_next (iter); } + + return result; } GSList * -vfolder_get_all_with_item_id (gulong id) +vfolder_get_all_without_item_id (itemPtr item) { GSList *result = NULL; GSList *iter = vfolders; while (iter) { vfolderPtr vfolder = (vfolderPtr)iter->data; - if (g_list_find (vfolder->itemset->ids, GUINT_TO_POINTER (id))) + if (!itemset_check_item (vfolder->itemset, item)) result = g_slist_append (result, vfolder); iter = g_slist_next (iter); } @@ -200,7 +183,11 @@ debug1 (DEBUG_CACHE, "import vfolder: title=%s", node_get_title (node)); vfolder = vfolder_new (node); - vfolder->itemset = db_search_folder_load (node->id); + + /* We use the itemset only to keep itemset rules, not to + have the items in memory! Maybe the itemset<->filtering + dependency is not a good idea... */ + vfolder->itemset = g_new0 (struct itemSet, 1); vfolder_import_rules (cur, vfolder); } @@ -258,7 +245,7 @@ vfolderPtr vfolder = (vfolderPtr)node->data; vfolder_reset (vfolder); - itemlist_add_loader (vfolder_loader_new (node)); + itemlist_add_search_result (vfolder_loader_new (node)); } static void @@ -281,14 +268,12 @@ static void vfolder_update_counters (nodePtr node) { - vfolderPtr vfolder = (vfolderPtr) node->data; - /* There is no unread handling for search folders for performance reasons. So set everything to 0 here and don't bother with GUI updates... */ - vfolder->node->needsUpdate = TRUE; - vfolder->node->unreadCount = 0; - vfolder->node->itemCount = g_list_length (vfolder->itemset->ids); + node->needsUpdate = TRUE; + node->unreadCount = 0; + node->itemCount = db_search_folder_get_item_count (node->id); } static void diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/vfolder.h new/liferea-1.8.10/src/vfolder.h --- old/liferea-1.8.9/src/vfolder.h 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/vfolder.h 2012-10-30 20:49:05.000000000 +0100 @@ -42,7 +42,7 @@ itemSetPtr itemset; /**< the itemset with the rules and matching items */ gboolean reloading; /**< if the search folder is in async reloading */ - gulong maxLoadedId; /**< when in reloading maximum scanned id so far */ + gulong loadOffset; /**< when in reloading: current offset */ } *vfolderPtr; /** @@ -72,39 +72,22 @@ void vfolder_foreach_data (vfolderActionDataFunc func, itemPtr item); /** - * Method to remove an item from a search folder. + * Returns a list of all search folders currently matching the given item. * - * @param vfolder search folder * @param item the item - */ -void vfolder_remove_item (vfolderPtr vfolder, itemPtr item); - -/** - * Method to add an item to a search folder. * - * @param vfolder search folder - * @param item the item + * @returns a list of vfolderPtr (to be free'd using g_slist_free()) */ -void vfolder_add_item (vfolderPtr vfolder, itemPtr item); +GSList * vfolder_get_all_with_item_id (itemPtr item); /** - * Method to merge an item to a search folder if - * it matches the search folder rules. + * Returns a list of all search folders currently not matching the given item. * - * @param vfolder search folder * @param item the item - */ -void vfolder_merge_item (vfolderPtr vfolder, itemPtr item); - -/** - * Returns a list of all search folders currently matching - * the given item id. - * - * @param id the item id * * @returns a list of vfolderPtr (to be free'd using g_slist_free()) */ -GSList * vfolder_get_all_with_item_id (gulong id); +GSList * vfolder_get_all_without_item_id (itemPtr item); /** * Resets vfolder state. Drops all items from it. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/liferea-1.8.9/src/vfolder_loader.c new/liferea-1.8.10/src/vfolder_loader.c --- old/liferea-1.8.9/src/vfolder_loader.c 2012-10-04 22:05:59.000000000 +0200 +++ new/liferea-1.8.10/src/vfolder_loader.c 2012-10-30 20:49:05.000000000 +0100 @@ -37,8 +37,8 @@ gboolean result; /* 1. Fetch a batch of items */ - result = db_itemset_get (items, vfolder->maxLoadedId, VFOLDER_LOADER_BATCH_SIZE); - vfolder->maxLoadedId += VFOLDER_LOADER_BATCH_SIZE; + result = db_itemset_get (items, vfolder->loadOffset, VFOLDER_LOADER_BATCH_SIZE); + vfolder->loadOffset += VFOLDER_LOADER_BATCH_SIZE; if (result) { /* 2. Match all items against search folder */ @@ -61,9 +61,12 @@ itemset_free (items); - /* 3. Save items to DB (except for search results) */ - if (vfolder->node) + /* 3. Save items to DB and update UI (except for search results) */ + if (vfolder->node) { db_search_folder_add_items (vfolder->node->id, *resultItems); + node_update_counters (vfolder->node); + ui_node_update (vfolder->node->id); + } return result; /* FALSE on last fetch */ } @@ -81,7 +84,7 @@ debug1 (DEBUG_CACHE, "search folder '%s' reload started", node->title); vfolder_reset (vfolder); vfolder->reloading = TRUE; - vfolder->maxLoadedId = 0; + vfolder->loadOffset = 0; return item_loader_new (vfolder_loader_fetch_cb, node, vfolder); } -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org