1 Return-Path: <meskio@sindominio.net>
\r
2 X-Original-To: notmuch@notmuchmail.org
\r
3 Delivered-To: notmuch@notmuchmail.org
\r
4 Received: from localhost (localhost [127.0.0.1])
\r
5 by olra.theworths.org (Postfix) with ESMTP id 35759431FC1
\r
6 for <notmuch@notmuchmail.org>; Sun, 21 Mar 2010 14:30:21 -0700 (PDT)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=-1.9 tagged_above=-999 required=5
\r
12 tests=[BAYES_00=-1.9] autolearn=ham
\r
13 Received: from olra.theworths.org ([127.0.0.1])
\r
14 by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)
\r
15 with ESMTP id ltOgh+LzfcdW for <notmuch@notmuchmail.org>;
\r
16 Sun, 21 Mar 2010 14:30:19 -0700 (PDT)
\r
17 Received: from flatline.sindominio.net (flatline.sindominio.net [82.144.4.26])
\r
18 by olra.theworths.org (Postfix) with ESMTP id D11A44196F0
\r
19 for <notmuch@notmuchmail.org>; Sun, 21 Mar 2010 14:30:16 -0700 (PDT)
\r
20 Received: from localhost (localhost.localdomain [127.0.0.1])
\r
21 by flatline.sindominio.net (Postfix) with ESMTP id E98DC348046;
\r
22 Sun, 21 Mar 2010 22:30:15 +0100 (CET)
\r
23 X-Virus-Scanned: Debian amavisd-new at sindominio.net
\r
24 Received: from flatline.sindominio.net ([127.0.0.1])
\r
25 by localhost (flatline.sindominio.net [127.0.0.1]) (amavisd-new,
\r
27 with ESMTP id CoFItUAt1ChR; Sun, 21 Mar 2010 22:30:13 +0100 (CET)
\r
28 Received: from blackspot (heal.cauterized.net [89.140.131.167])
\r
29 by flatline.sindominio.net (Postfix) with ESMTPA id BBABF348095;
\r
30 Sun, 21 Mar 2010 22:29:28 +0100 (CET)
\r
31 Received: by blackspot (Postfix, from userid 1000)
\r
32 id 78F448BDFD; Sun, 21 Mar 2010 22:32:42 +0100 (CET)
\r
33 From: Ruben Pollan <meskio@sindominio.net>
\r
34 To: notmuch@notmuchmail.org
\r
35 Date: Sun, 21 Mar 2010 22:32:33 +0100
\r
36 Message-Id: <1269207153-3687-3-git-send-email-meskio@sindominio.net>
\r
37 X-Mailer: git-send-email 1.7.0
\r
38 In-Reply-To: <1269080605-5617-1-git-send-email-meskio@sindominio.net>
\r
39 References: <1269080605-5617-1-git-send-email-meskio@sindominio.net>
\r
40 Subject: [notmuch] [PATCH 2/2] Added backwards iterator to threads
\r
41 X-BeenThere: notmuch@notmuchmail.org
\r
42 X-Mailman-Version: 2.1.13
\r
44 List-Id: "Use and development of the notmuch mail system."
\r
45 <notmuch.notmuchmail.org>
\r
46 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
47 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
48 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
49 List-Post: <mailto:notmuch@notmuchmail.org>
\r
50 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
51 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
52 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
53 X-List-Received-Date: Sun, 21 Mar 2010 21:30:21 -0000
\r
55 Added the functions notmuch_threads_move_to_prevoius,
\r
56 notmuch_threads_move_to_last and notmuch_threads_move_to_first to
\r
57 notmuch library. With them is possible to iterate backwards on threads.
\r
59 * notmuch_threads_move_to_prevoius do the opposite than
\r
60 notmuch_threads_move_to_next, getting the threads iterator one
\r
63 * notmuch_threads_move_to_last move the iterator to the first last
\r
66 * notmuch_threads_move_to_first move the iterator to the first valid
\r
69 For it has been implemented notmuch_thread_list_t structur that stores
\r
70 the thread_ids so the backwards iteration gets the thread_id in the same
\r
71 order that was show on forward iteration.
\r
73 lib/notmuch.h | 28 ++++++++
\r
74 lib/query.cc | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
\r
75 2 files changed, 222 insertions(+), 15 deletions(-)
\r
77 diff --git a/lib/notmuch.h b/lib/notmuch.h
\r
78 index 0d9cb0f..62f4ad4 100644
\r
81 @@ -466,6 +466,15 @@ notmuch_threads_valid (notmuch_threads_t *threads);
\r
83 notmuch_threads_get (notmuch_threads_t *threads);
\r
85 +/* Move the 'threads' iterator to the first thread.
\r
87 + * After that the 'threads' iterator will be set to the first valid
\r
88 + * thread, so it can be use to iterate with
\r
89 + * notmuch_threads_move_to_next.
\r
92 +notmuch_threads_move_to_first (notmuch_threads_t *threads);
\r
94 /* Move the 'threads' iterator to the next thread.
\r
96 * If 'threads' is already pointing at the last thread then the
\r
97 @@ -479,6 +488,25 @@ notmuch_threads_get (notmuch_threads_t *threads);
\r
99 notmuch_threads_move_to_next (notmuch_threads_t *threads);
\r
101 +/* Move the 'threads' iterator to the last thread.
\r
103 + * After that the 'threads' iterator will be set to the last valid
\r
104 + * thread, so it can be use to iterate with
\r
105 + * notmuch_threads_move_to_previous.
\r
108 +notmuch_threads_move_to_last (notmuch_threads_t *threads);
\r
110 +/* Move the 'threads' iterator to the previous thread.
\r
112 + * If 'threads' is already pointing at the first thread then the
\r
113 + * iterator will be moved to a point just beyond that first thread,
\r
114 + * (where notmuch_threads_valid will return FALSE and
\r
115 + * notmuch_threads_get will return NULL).
\r
118 +notmuch_threads_move_to_previous (notmuch_threads_t *threads);
\r
120 /* Destroy a notmuch_threads_t object.
\r
122 * It's not strictly necessary to call this function. All memory from
\r
123 diff --git a/lib/query.cc b/lib/query.cc
\r
124 index 514a156..727f449 100644
\r
127 @@ -35,16 +35,29 @@ typedef struct _notmuch_mset_messages {
\r
128 notmuch_messages_t base;
\r
129 notmuch_database_t *notmuch;
\r
130 Xapian::MSetIterator iterator;
\r
131 + Xapian::MSetIterator iterator_begin;
\r
132 Xapian::MSetIterator iterator_end;
\r
133 } notmuch_mset_messages_t;
\r
135 +typedef struct _notmuch_thread_node {
\r
136 + const char *thread_id;
\r
137 + struct _notmuch_thread_node *next;
\r
138 + struct _notmuch_thread_node *prev;
\r
139 +} notmuch_thread_node_t;
\r
141 +typedef struct _notmuch_thread_list {
\r
142 + notmuch_thread_node_t *head;
\r
143 + notmuch_thread_node_t *tail;
\r
144 + notmuch_thread_node_t *iterator;
\r
145 +} notmuch_thread_list_t;
\r
147 struct _notmuch_threads {
\r
148 notmuch_query_t *query;
\r
149 GHashTable *threads;
\r
150 notmuch_messages_t *messages;
\r
152 - /* This thread ID is our iterator state. */
\r
153 - const char *thread_id;
\r
154 + /* thread list with the thread_id of the showed messages */
\r
155 + notmuch_thread_list_t *list;
\r
159 @@ -86,6 +99,7 @@ static int
\r
160 _notmuch_messages_destructor (notmuch_mset_messages_t *messages)
\r
162 messages->iterator.~MSetIterator ();
\r
163 + messages->iterator_begin.~MSetIterator ();
\r
164 messages->iterator_end.~MSetIterator ();
\r
167 @@ -108,6 +122,7 @@ notmuch_query_search_messages (notmuch_query_t *query)
\r
168 messages->base.iterator = NULL;
\r
169 messages->notmuch = notmuch;
\r
170 new (&messages->iterator) Xapian::MSetIterator ();
\r
171 + new (&messages->iterator_begin) Xapian::MSetIterator ();
\r
172 new (&messages->iterator_end) Xapian::MSetIterator ();
\r
174 talloc_set_destructor (messages, _notmuch_messages_destructor);
\r
175 @@ -157,6 +172,7 @@ notmuch_query_search_messages (notmuch_query_t *query)
\r
176 mset = enquire.get_mset (0, notmuch->xapian_db->get_doccount ());
\r
178 messages->iterator = mset.begin ();
\r
179 + messages->iterator_begin = mset.begin ();
\r
180 messages->iterator_end = mset.end ();
\r
182 } catch (const Xapian::Error &error) {
\r
183 @@ -208,6 +224,16 @@ _notmuch_mset_messages_get (notmuch_messages_t *messages)
\r
187 +_notmuch_mset_messages_move_to_first (notmuch_messages_t *messages)
\r
189 + notmuch_mset_messages_t *mset_messages;
\r
191 + mset_messages = (notmuch_mset_messages_t *) messages;
\r
193 + mset_messages->iterator = mset_messages->iterator_begin;
\r
197 _notmuch_mset_messages_move_to_next (notmuch_messages_t *messages)
\r
199 notmuch_mset_messages_t *mset_messages;
\r
200 @@ -217,6 +243,113 @@ _notmuch_mset_messages_move_to_next (notmuch_messages_t *messages)
\r
201 mset_messages->iterator++;
\r
205 +_notmuch_mset_messages_move_to_last (notmuch_messages_t *messages)
\r
207 + notmuch_mset_messages_t *mset_messages;
\r
209 + mset_messages = (notmuch_mset_messages_t *) messages;
\r
211 + mset_messages->iterator = mset_messages->iterator_end;
\r
212 + mset_messages->iterator--;
\r
216 +_notmuch_mset_messages_move_to_previous (notmuch_messages_t *messages)
\r
218 + notmuch_mset_messages_t *mset_messages;
\r
220 + mset_messages = (notmuch_mset_messages_t *) messages;
\r
222 + if (mset_messages->iterator == mset_messages->iterator_begin)
\r
225 + * Xapian iterators can not be beyond the first element, so we
\r
226 + * assign the iterator_end to mark the iterator as invalid in case
\r
227 + * of move_to_previous with the iterator at the beginning
\r
229 + mset_messages->iterator = mset_messages->iterator_end;
\r
231 + else if (_notmuch_mset_messages_valid (messages))
\r
234 + * If is valid move the iterator. To emulate the same behavior
\r
235 + * than notmuch_messages_t the iterator won't be updated if is
\r
238 + mset_messages->iterator--;
\r
242 +static notmuch_thread_list_t *
\r
243 +_notmuch_thread_list_create (void *ctx)
\r
245 + notmuch_thread_list_t *list;
\r
247 + list = talloc (ctx, notmuch_thread_list_t);
\r
248 + list->tail = NULL;
\r
249 + list->head = NULL;
\r
250 + list->iterator = NULL;
\r
256 +_notmuch_thread_list_append (notmuch_thread_list_t *list, const char *thread_id)
\r
258 + list->iterator = talloc (list, notmuch_thread_node_t);
\r
259 + if (list->head == NULL)
\r
261 + list->head = list->iterator;
\r
262 + list->iterator->prev = NULL;
\r
266 + list->tail->next = list->iterator;
\r
267 + list->iterator->prev = list->tail;
\r
270 + list->iterator->thread_id = thread_id;
\r
271 + list->iterator->next = NULL;
\r
272 + list->tail = list->iterator;
\r
275 +static const char *
\r
276 +_notmuch_thread_list_get_id (notmuch_thread_list_t *list)
\r
278 + return list->iterator->thread_id;
\r
281 +static notmuch_bool_t
\r
282 +_notmuch_thread_list_valid (notmuch_thread_list_t *list)
\r
284 + return (list->iterator != NULL);
\r
288 +_notmuch_thread_list_move_to_first (notmuch_thread_list_t *list)
\r
290 + list->iterator = list->head;
\r
294 +_notmuch_thread_list_move_to_next (notmuch_thread_list_t *list)
\r
296 + list->iterator = list->iterator->next;
\r
300 +_notmuch_thread_list_move_to_last (notmuch_thread_list_t *list)
\r
302 + list->iterator = list->tail;
\r
306 +_notmuch_thread_list_move_to_previous (notmuch_thread_list_t *list)
\r
308 + list->iterator = list->iterator->prev;
\r
311 /* Glib objects force use to use a talloc destructor as well, (but not
\r
312 * nearly as ugly as the for messages due to C++ objects). At
\r
313 * this point, I'd really like to have some talloc-friendly
\r
314 @@ -244,16 +377,15 @@ notmuch_query_search_threads (notmuch_query_t *query)
\r
317 threads->messages = notmuch_query_search_messages (query);
\r
318 + threads->list = _notmuch_thread_list_create (threads);
\r
319 if (!notmuch_messages_valid (threads->messages))
\r
321 - threads->thread_id = NULL;
\r
325 message = notmuch_messages_get (threads->messages);
\r
326 - threads->thread_id = notmuch_message_get_thread_id (message);
\r
327 + _notmuch_thread_list_append (threads->list,
\r
328 + notmuch_message_get_thread_id (message));
\r
329 g_hash_table_insert (threads->threads,
\r
330 - xstrdup (threads->thread_id),
\r
331 + xstrdup (_notmuch_thread_list_get_id (threads->list)),
\r
334 talloc_set_destructor (threads, _notmuch_threads_destructor);
\r
335 @@ -270,7 +402,7 @@ notmuch_query_destroy (notmuch_query_t *query)
\r
337 notmuch_threads_valid (notmuch_threads_t *threads)
\r
339 - return (threads->thread_id != NULL);
\r
340 + return _notmuch_thread_list_valid (threads->list);
\r
344 @@ -281,35 +413,82 @@ notmuch_threads_get (notmuch_threads_t *threads)
\r
346 return _notmuch_thread_create (threads->query,
\r
347 threads->query->notmuch,
\r
348 - threads->thread_id,
\r
349 + _notmuch_thread_list_get_id (threads->list),
\r
350 threads->query->query_string);
\r
354 +notmuch_threads_move_to_first (notmuch_threads_t *threads)
\r
356 + _notmuch_thread_list_move_to_first (threads->list);
\r
360 notmuch_threads_move_to_next (notmuch_threads_t *threads)
\r
362 - notmuch_message_t *message;
\r
363 + if (!_notmuch_thread_list_valid (threads->list))
\r
366 + _notmuch_thread_list_move_to_next (threads->list);
\r
367 + if (_notmuch_thread_list_valid (threads->list))
\r
370 while (notmuch_messages_valid (threads->messages))
\r
372 - message = notmuch_messages_get (threads->messages);
\r
373 + notmuch_message_t *message;
\r
374 + const char *thread_id;
\r
376 - threads->thread_id = notmuch_message_get_thread_id (message);
\r
377 + message = notmuch_messages_get (threads->messages);
\r
378 + thread_id = notmuch_message_get_thread_id (message);
\r
380 if (! g_hash_table_lookup_extended (threads->threads,
\r
381 - threads->thread_id,
\r
385 g_hash_table_insert (threads->threads,
\r
386 - xstrdup (threads->thread_id), NULL);
\r
387 + xstrdup (thread_id), NULL);
\r
388 + _notmuch_thread_list_append (threads->list, thread_id);
\r
389 notmuch_messages_move_to_next (threads->messages);
\r
393 notmuch_messages_move_to_next (threads->messages);
\r
398 +notmuch_threads_move_to_last (notmuch_threads_t *threads)
\r
400 + _notmuch_thread_list_move_to_last (threads->list);
\r
402 + while (notmuch_messages_valid (threads->messages))
\r
404 + notmuch_message_t *message;
\r
405 + const char *thread_id;
\r
407 + message = notmuch_messages_get (threads->messages);
\r
408 + thread_id = notmuch_message_get_thread_id (message);
\r
410 + if (! g_hash_table_lookup_extended (threads->threads,
\r
414 + g_hash_table_insert (threads->threads,
\r
415 + xstrdup (thread_id), NULL);
\r
416 + _notmuch_thread_list_append (threads->list, thread_id);
\r
419 + notmuch_messages_move_to_next (threads->messages);
\r
424 +notmuch_threads_move_to_previous (notmuch_threads_t *threads)
\r
426 + if (!_notmuch_thread_list_valid (threads->list))
\r
429 - threads->thread_id = NULL;
\r
430 + _notmuch_thread_list_move_to_previous (threads->list);
\r