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

Reply via email to