aboutsummaryrefslogblamecommitdiffstats
path: root/calendar/pcs/query.c
blob: 453c1cc4ce784753ed827a0b061aa5a001dc1530 (plain) (tree)
1
2
3
4
5
6
7
8
9





                                                        


                                                                   














                                                                            
                 
                                    
                                        
                                        








                                           


                                                        

                                         
                                   

  
 


                                                 

                                                         
 
                                       


 



                                                      
 






                      
 
 




                                                        
 
                           
 




                                                           

 
           
                                                                        
 
                     

                           

                                                             
 
                                                       

 
           
                                                                                               
 














                                                                                           
 










                                                                                        

 
           
                                                                                         


                           
        


                               











                                                                               
         
 
 








                                                                   
 
                                                        
 


                                                        
 
                                      
 









                                                                                                    
 




                                                              
 

                                        
 




                                        
 





                                                
 

                                             
 

                               
 

                                               
 

                                                                   
 

                                                          
 

                                            

                      
 

                                                                     

 













                                                                      
 
                     
 

                                                                             
 
                     

 


                           
  
                                               
  
                                                
   

                             
 
                                                      
 
                                                                

 

                                    
 
                                                      
 

                                 
 



                                                       
        


                                                       
 


                                                                                        

 

                                                               
 







                                                     
 



                                                              
 



                                                                                   
 

                                                                 
 
                                                                                                   
 
                                      
 

                                                                                          
 
                                   
 
 

                                                               
 
                           



                                            
 
                           
                                                              
 

                                           
 

                                                     
 










                                                                  
 



                                                              
 



                                                                                   
 

                                                                 
 
                                                                                                      
 
                                      
 

                                                                                              
 
                                   

 

                                                                  
 




                                            
 

                                                              
 



                                                        

 

                                                              
 
                           






                                                       
 
                           


                                                              
 



                                                                                     
 

                                                                 
 
                                                                                                     
 
                                      
 

                                                                                         
 
 
                                   

 

                                                              
 




                                            
 

                                                              
 


                                     
                                                    

 

                                                                            
 

                                
 

                                            
 



                                                              
 
                                                                                                           
 

                                                                                         
 
                                   

 

                                                                                  
 

                                
 

                                            
 



                                                              
 
                                                                                             
 

                                                                                           


                                   
/* Evolution calendar - Live search query implementation
 *
 * Copyright (C) 2001 Ximian, Inc.
 *
 * Author: Federico Mena-Quintero <federico@ximian.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <glib.h>
#include <bonobo/bonobo-exception.h>
#include <e-util/e-component-listener.h>
#include <pcs/cal-backend-object-sexp.h>
#include "query.h"



/* Private part of the Query structure */
struct _QueryPrivate {
    /* The backend we are monitoring */
    CalBackend *backend;

    /* The listener we report to */
    GNOME_Evolution_Calendar_QueryListener listener;
    EComponentListener *component_listener;

    /* Sexp that defines the query */
    CalBackendObjectSExp *sexp;
};




static void query_class_init (QueryClass *class);
static void query_init (Query *query, QueryClass *class);
static void query_finalize (GObject *object);

static BonoboObjectClass *parent_class;



BONOBO_TYPE_FUNC_FULL (Query,
               GNOME_Evolution_Calendar_Query,
               BONOBO_TYPE_OBJECT,
               query);

/* Property IDs */
enum props {
    PROP_0,
    PROP_BACKEND,
    PROP_LISTENER,
    PROP_SEXP
};


static void
listener_died_cb (EComponentListener *cl, gpointer data)
{
    Query *query = QUERY (data);
    QueryPrivate *priv;

    priv = query->priv;

    g_object_unref (priv->component_listener);
    priv->component_listener = NULL;
    
    bonobo_object_release_unref (priv->listener, NULL);
    priv->listener = NULL;
}

static void
impl_Query_start (PortableServer_Servant servant, CORBA_Environment *ev)
{
    Query *query;
    QueryPrivate *priv;

    query = QUERY (bonobo_object_from_servant (servant));
    priv = query->priv;

    cal_backend_start_query (priv->backend, query);
}

static void
query_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
{
    Query *query;
    QueryPrivate *priv;
    CORBA_Environment ev;

    query = QUERY (object);
    priv = query->priv;
    
    switch (property_id) {
    case PROP_BACKEND:
        priv->backend = CAL_BACKEND (g_value_dup_object (value));
        break;
    case PROP_LISTENER:
        CORBA_exception_init (&ev);
        priv->listener = CORBA_Object_duplicate (g_value_get_pointer (value), &ev);
        CORBA_exception_free (&ev);

        priv->component_listener = e_component_listener_new (priv->listener);
        g_signal_connect (G_OBJECT (priv->component_listener), "component_died",
                  G_CALLBACK (listener_died_cb), query);
        break;
    case PROP_SEXP:
        priv->sexp = CAL_BACKEND_OBJECT_SEXP (g_value_dup_object (value));
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
        break;
    }
}

static void
query_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
{
    Query *query;
    QueryPrivate *priv;
    
    query = QUERY (object);
    priv = query->priv;

    switch (property_id) {
    case PROP_BACKEND:
        g_value_set_object (value, priv->backend);
    case PROP_LISTENER:
        g_value_set_pointer (value, priv->listener);
        break;
    case PROP_SEXP:
        g_value_set_object (value, priv->sexp);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
        break;
    }
}

/* Class initialization function for the live search query */
static void
query_class_init (QueryClass *klass)
{
    GObjectClass *object_class;
    POA_GNOME_Evolution_Calendar_Query__epv *epv = &klass->epv;
    GParamSpec *param;
    
    object_class = (GObjectClass *) klass;

    parent_class = g_type_class_peek_parent (klass);

    object_class->set_property = query_set_property;
    object_class->get_property = query_get_property;
    object_class->finalize = query_finalize;

    epv->start = impl_Query_start;

    param =  g_param_spec_object ("backend", NULL, NULL, CAL_BACKEND_TYPE,
                      G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
    g_object_class_install_property (object_class, PROP_BACKEND, param);
    param =  g_param_spec_pointer ("listener", NULL, NULL,
                      G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
    g_object_class_install_property (object_class, PROP_LISTENER, param);
    param =  g_param_spec_object ("sexp", NULL, NULL, CAL_TYPE_BACKEND_OBJECT_SEXP,
                      G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
    g_object_class_install_property (object_class, PROP_SEXP, param);
}

/* Object initialization function for the live search query */
static void
query_init (Query *query, QueryClass *class)
{
    QueryPrivate *priv;

    priv = g_new0 (QueryPrivate, 1);
    query->priv = priv;

    priv->backend = NULL;
    priv->listener = NULL;
    priv->component_listener = NULL;
    priv->sexp = NULL;
}

/* Finalize handler for the live search query */
static void
query_finalize (GObject *object)
{
    Query *query;
    QueryPrivate *priv;

    g_return_if_fail (object != NULL);
    g_return_if_fail (IS_QUERY (object));

    query = QUERY (object);
    priv = query->priv;

    if (priv->backend)
        g_object_unref (priv->backend);

    if (priv->listener != NULL)
        bonobo_object_release_unref (priv->listener, NULL);

    if (priv->component_listener != NULL)
        g_object_unref (priv->component_listener);

    if (priv->sexp)
        g_object_unref (priv->sexp);

    g_free (priv);

    if (G_OBJECT_CLASS (parent_class)->finalize)
        (* G_OBJECT_CLASS (parent_class)->finalize) (object);
}

/**
 * query_new:
 * @backend: Calendar backend that the query object will monitor.
 * @ql: Listener for query results.
 * @sexp: Sexp that defines the query.
 * 
 * Creates a new query engine object that monitors a calendar backend.
 * 
 * Return value: A newly-created query object, or NULL on failure.
 **/
Query *
query_new (CalBackend *backend,
       GNOME_Evolution_Calendar_QueryListener ql,
       CalBackendObjectSExp *sexp)
{
    Query *query;

    query = g_object_new (QUERY_TYPE, "backend", backend, "listener", ql,
                  "sexp", sexp, NULL);

    return query;
}

/**
 * query_get_sexp
 * @query: A #Query object.
 *
 * Get the expression used for the given query.
 *
 * Returns: the query expression used to search.
 */
const char *
query_get_text (Query *query)
{
    g_return_val_if_fail (IS_QUERY (query), NULL);

    return cal_backend_object_sexp_text (query->priv->sexp);
}

CalBackendObjectSExp *
query_get_object_sexp (Query *query)
{
    g_return_val_if_fail (IS_QUERY (query), NULL);

    return query->priv->sexp;
}

gboolean
query_object_matches (Query *query, const char *object)
{
    QueryPrivate *priv;
    
    g_return_val_if_fail (query != NULL, FALSE);
    g_return_val_if_fail (IS_QUERY (query), FALSE);
    g_return_val_if_fail (object != NULL, FALSE);

    priv = query->priv;
    
    return cal_backend_object_sexp_match_object (priv->sexp, object, priv->backend);
}

void
query_notify_objects_added (Query *query, const GList *objects)
{
    QueryPrivate *priv;
    GNOME_Evolution_Calendar_stringlist obj_list;
    CORBA_Environment ev;
    const GList *l;
    int num_objs, i;
    
    g_return_if_fail (query != NULL);
    g_return_if_fail (IS_QUERY (query));

    priv = query->priv;
    g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
    
    CORBA_exception_init (&ev);

    num_objs = g_list_length ((GList*)objects);
    obj_list._buffer = GNOME_Evolution_Calendar_stringlist_allocbuf (num_objs);
    obj_list._maximum = num_objs;
    obj_list._length = num_objs;

    for (l = objects, i = 0; l; l = l->next, i++)
        obj_list._buffer[i] = CORBA_string_dup (l->data);

    GNOME_Evolution_Calendar_QueryListener_notifyObjectsAdded (priv->listener, &obj_list, &ev);

    CORBA_free (obj_list._buffer);

    if (BONOBO_EX (&ev))
        g_warning (G_STRLOC ": could not notify the listener of object addition");

    CORBA_exception_free (&ev);
}

void
query_notify_objects_added_1 (Query *query, const char *object)
{
    QueryPrivate *priv;
    GList objects;
    
    g_return_if_fail (query != NULL);
    g_return_if_fail (IS_QUERY (query));

    priv = query->priv;
    g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);

    objects.next = objects.prev = NULL;
    objects.data = (gpointer)object;

    query_notify_objects_added (query, &objects);
}

void
query_notify_objects_modified (Query *query, const GList *objects)
{
    QueryPrivate *priv;
    GNOME_Evolution_Calendar_CalObjUIDSeq obj_list;
    CORBA_Environment ev;
    const GList *l;
    int num_objs, i;
    
    g_return_if_fail (query != NULL);
    g_return_if_fail (IS_QUERY (query));

    priv = query->priv;
    g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
    
    CORBA_exception_init (&ev);

    num_objs = g_list_length ((GList*)objects);
    obj_list._buffer = GNOME_Evolution_Calendar_stringlist_allocbuf (num_objs);
    obj_list._maximum = num_objs;
    obj_list._length = num_objs;

    for (l = objects, i = 0; l; l = l->next, i++)
        obj_list._buffer[i] = CORBA_string_dup (l->data);

    GNOME_Evolution_Calendar_QueryListener_notifyObjectsModified (priv->listener, &obj_list, &ev);

    CORBA_free (obj_list._buffer);

    if (BONOBO_EX (&ev))
        g_warning (G_STRLOC ": could not notify the listener of object modification");

    CORBA_exception_free (&ev);
}

void
query_notify_objects_modified_1 (Query *query, const char *object)
{
    QueryPrivate *priv;
    GList objects;
    
    g_return_if_fail (query != NULL);
    g_return_if_fail (IS_QUERY (query));

    priv = query->priv;
    g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);

    objects.next = objects.prev = NULL;
    objects.data = (gpointer)object;
    
    query_notify_objects_modified (query, &objects);
}

void
query_notify_objects_removed (Query *query, const GList *uids)
{
    QueryPrivate *priv;
    GNOME_Evolution_Calendar_CalObjUIDSeq uid_list;
    CORBA_Environment ev;
    const GList *l;
    int num_uids, i;
    
    g_return_if_fail (query != NULL);
    g_return_if_fail (IS_QUERY (query));

    priv = query->priv;
    g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
    
    CORBA_exception_init (&ev);

    num_uids = g_list_length ((GList*)uids);
    uid_list._buffer = GNOME_Evolution_Calendar_CalObjUIDSeq_allocbuf (num_uids);
    uid_list._maximum = num_uids;
    uid_list._length = num_uids;

    for (l = uids, i = 0; l; l = l->next, i ++)
        uid_list._buffer[i] = CORBA_string_dup (l->data);

    GNOME_Evolution_Calendar_QueryListener_notifyObjectsRemoved (priv->listener, &uid_list, &ev);

    CORBA_free (uid_list._buffer);

    if (BONOBO_EX (&ev))
        g_warning (G_STRLOC ": could not notify the listener of object removal");


    CORBA_exception_free (&ev);
}

void
query_notify_objects_removed_1 (Query *query, const char *uid)
{
    QueryPrivate *priv;
    GList uids;
    
    g_return_if_fail (query != NULL);
    g_return_if_fail (IS_QUERY (query));

    priv = query->priv;
    g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);

    uids.next = uids.prev = NULL;
    uids.data = (gpointer)uid;
    
    query_notify_objects_removed (query, &uids);
}

void
query_notify_query_progress (Query *query, const char *message, int percent)
{
    QueryPrivate *priv; 
    CORBA_Environment ev;

    g_return_if_fail (query != NULL);
    g_return_if_fail (IS_QUERY (query));

    priv = query->priv;
    g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
    
    CORBA_exception_init (&ev);

    GNOME_Evolution_Calendar_QueryListener_notifyQueryProgress (priv->listener, message, percent, &ev);

    if (BONOBO_EX (&ev))
        g_warning (G_STRLOC ": could not notify the listener of query progress");

    CORBA_exception_free (&ev);
}

void
query_notify_query_done (Query *query, GNOME_Evolution_Calendar_CallStatus status)
{
    QueryPrivate *priv; 
    CORBA_Environment ev;

    g_return_if_fail (query != NULL);
    g_return_if_fail (IS_QUERY (query));

    priv = query->priv;
    g_return_if_fail (priv->listener != CORBA_OBJECT_NIL);
    
    CORBA_exception_init (&ev);

    GNOME_Evolution_Calendar_QueryListener_notifyQueryDone (priv->listener, status, &ev);

    if (BONOBO_EX (&ev))
        g_warning (G_STRLOC ": could not notify the listener of query completion");

    CORBA_exception_free (&ev);
}