Commit a343889b authored by Julien Bonjean's avatar Julien Bonjean
Browse files

Improved contacts list

 - Performance : now handle only last search
 - Added waiting image
 - Optimized query (only get contacts with at least one phone number)
parent 54d9c5a0
......@@ -31,6 +31,7 @@
#include "eds.h"
typedef struct _Handler_And_Data {
int search_id;
SearchAsyncHandler handler;
gpointer user_data;
GList *hits;
......@@ -95,6 +96,7 @@ create_query (const char* s)
GArray *parts = split_query_string (s);
EBookQuery ***field_queries;
EBookQuery **q;
EBookQuery **phone;
guint j;
int i;
......@@ -110,13 +112,19 @@ create_query (const char* s)
}
g_array_free (parts, TRUE);
query = e_book_query_or (n_search_fields, q, TRUE);
phone = g_new0 (EBookQuery *, 3);
phone[0] = e_book_query_field_exists (E_CONTACT_PHONE_BUSINESS);
phone[1] = e_book_query_field_exists (E_CONTACT_PHONE_HOME);
phone[2] = e_book_query_field_exists (E_CONTACT_PHONE_MOBILE);
query = e_book_query_andv (e_book_query_or (n_search_fields, q, FALSE), e_book_query_or (3, phone, FALSE));
for (i = 0; i < n_search_fields; i++) {
g_free (field_queries[i]);
}
g_free (field_queries);
g_free (q);
g_free (phone);
return query;
}
......@@ -188,30 +196,66 @@ init (void)
}
}
current_search_id = 0;
g_object_unref (source_list);
}
/**
* Final callback after all books have been processed.
*/
static void
view_finish (EBookView *book_view, Handler_And_Data *had)
{
GList *i;
SearchAsyncHandler had_handler = had->handler;
GList *had_hits = had->hits;
gpointer had_user_data = had->user_data;
int search_id = had->search_id;
g_free (had);
g_return_if_fail (book_view != NULL);
g_object_unref (book_view);
had_handler (had_hits, had_user_data);
if(search_id == current_search_id)
{
// Reinitialize search id to prevent overflow
if(current_search_id > 5000)
current_search_id = 0;
// Call display callback
had_handler (had_hits, had_user_data);
}
else
{
// Some hits could have been processed but will not be used
for (i = had_hits; i != NULL; i = i->next)
{
Hit *entry;
entry = i->data;
free_hit(entry);
}
g_list_free(had_hits);
}
}
/**
* Callback called after each ebook search completed.
* Used to store book search results.
*/
static void
view_contacts_added_cb (EBookView *book_view, GList *contacts, gpointer user_data)
{
GdkPixbuf *photo;
Handler_And_Data *had = (Handler_And_Data *) user_data;
if(had->search_id != current_search_id)
{
e_book_view_stop (book_view);
return;
}
if (had->max_results_remaining <= 0) {
e_book_view_stop (book_view);
had->book_views_remaining--;
......@@ -261,6 +305,10 @@ view_contacts_added_cb (EBookView *book_view, GList *contacts, gpointer user_dat
}
}
/**
* Callback called after each ebook search completed.
* Used to call final callback when all books have been read.
*/
static void
view_completed_cb (EBookView *book_view, EBookViewStatus status, gpointer user_data)
{
......@@ -271,17 +319,30 @@ view_completed_cb (EBookView *book_view, EBookViewStatus status, gpointer user_d
}
}
void
search_async (const char *query,
int max_results,
SearchAsyncHandler handler,
gpointer user_data)
{
GSList *iter;
// Increment search id
current_search_id++;
EBookQuery* book_query = create_query (query);
// If query is null
if(strlen(query) < 1)
{
// If data displayed (from previous search), directly call callback
handler(NULL, user_data);
return;
}
GSList *iter;
EBookQuery* book_query = create_query (query);
Handler_And_Data *had = g_new (Handler_And_Data, 1);
had->search_id = current_search_id;
had->handler = handler;
had->user_data = user_data;
had->hits = NULL;
......
......@@ -35,8 +35,10 @@
G_BEGIN_DECLS
int current_search_id;
/**
* Reprsent a contact entry
* Reprsent a contact entry
*/
typedef struct _Hit
{
......@@ -48,7 +50,7 @@ typedef struct _Hit
} Hit;
/**
* Free a contact entry
* Free a contact entry
*/
void free_hit (Hit *h);
......
......@@ -31,7 +31,7 @@ static void handler_async_search (GList *hits, gpointer user_data UNUSED);
GtkTreeModel* create_filter (GtkTreeModel* child) {
GtkTreeModel* ret;
ret = gtk_tree_model_filter_new(child, NULL);
gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(ret), is_visible, NULL, NULL);
return GTK_TREE_MODEL(ret);
......@@ -76,7 +76,7 @@ static void handler_async_search (GList *hits, gpointer user_data) {
// Retrieve the address book parameters
addressbook_config = (AddressBook_Config*) user_data;
// reset previous results
reset_call_tree(contacts);
call_list_reset(contacts);
......@@ -104,12 +104,14 @@ static void handler_async_search (GList *hits, gpointer user_data) {
}
g_list_free(hits);
// Deactivate waiting image
deactivateWaitingLayer();
}
void filter_entry_changed (GtkEntry* entry UNUSED, gchar* arg1 UNUSED, gpointer data UNUSED) {
AddressBook_Config *addressbook_config;
/* Switch to the address book when the focus is on the search bar */
if (active_calltree == current_calls)
display_calltree (contacts);
......@@ -117,10 +119,14 @@ void filter_entry_changed (GtkEntry* entry UNUSED, gchar* arg1 UNUSED, gpointer
/* We want to search in the contact list */
if (active_calltree == contacts) {
// Activate waiting layer
activateWaitingLayer();
// Load the address book parameters
addressbook_load_parameters (&addressbook_config);
// Start the asynchronous search as soon as we have an entry */
search_async (gtk_entry_get_text (GTK_ENTRY (filter_entry)), addressbook_config->max_results, &handler_async_search, addressbook_config);
// Start the asynchronous search as soon as we have an entry */
search_async (gtk_entry_get_text (GTK_ENTRY (filter_entry)), addressbook_config->max_results, &handler_async_search, addressbook_config);
}
}
......@@ -147,6 +153,22 @@ GtkWidget* create_filter_entry() {
g_signal_connect(GTK_ENTRY(filter_entry), "grab-focus", G_CALLBACK(clear_filter_entry_if_default), NULL);
gtk_box_pack_start(GTK_BOX(ret), filter_entry, TRUE, TRUE, 0);
// Create waiting icon
waitingPixOn = gdk_pixbuf_animation_new_from_file(ICONS_DIR "/throbber.gif", NULL);
waitingPixOff = gdk_pixbuf_new_from_file(ICONS_DIR "/throbber.png", NULL);
waitingLayer = gtk_image_new_from_pixbuf(waitingPixOff);
gtk_box_pack_end(GTK_BOX(ret), waitingLayer, TRUE, TRUE, 0);
return ret;
}
void activateWaitingLayer() {
gtk_image_set_from_animation(GTK_IMAGE(waitingLayer),waitingPixOn);
}
void deactivateWaitingLayer() {
gtk_image_set_from_pixbuf (GTK_IMAGE(waitingLayer),waitingPixOff);
}
......@@ -3,22 +3,22 @@
*
* Author: Antoine Reversat <antoine.reversat@savoirfairelinux.com>
* Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __SEARCH_FILTER_H__
#define __SEARCH_FILTER_H__
......@@ -26,10 +26,20 @@
#include <gtk/gtk.h>
#include <libsexy/sexy-icon-entry.h>
GtkWidget *waitingLayer;
GdkPixbufAnimation *waitingPixOn;
GdkPixbuf *waitingPixOff;
GtkTreeModel* create_filter(GtkTreeModel* child);
gboolean is_visible(GtkTreeModel* model, GtkTreeIter* iter, gpointer data);
GtkWidget* create_filter_entry();
void activateWaitingLayer();
void deactivateWaitingLayer();
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment