Update called vala api.
[stuffkeeper.git] / src / stuffkeeper-data-item-search.gob
blob0494c8ad53de93b627876f11caa902c9d1e09a07
1 requires 2.0.10
3 %ph{
4 #include <sqlite3.h>
5 %}
6 %h{
7 #include <glib.h>
8 #include <glib/gi18n.h>
10 #include <glib/gstdio.h>
12 #include "stuffkeeper-data-tag.h"
13 #include "stuffkeeper-data-item.h"
14 #include "stuffkeeper-data-schema.h"
18 typedef enum _SearchType {
19     SEARCH_TYPE_NONE = 0,
20     SEARCH_TYPE_IS = 1,
21     SEARCH_TYPE_IS_NOT = 2,
22     SEARCH_TYPE_CONTAINS = 3,
23     SEARCH_TYPE_NOT_CONTAINS = 4,
24     SEARCH_TYPE_NUM_ITEMS = 5
25 }SearchType;
28 typedef enum _SearchFieldType {
29     SEARCH_TITLE            = 0,
30     SEARCH_FIELD_SCHEMA     = 1,
31     SEARCH_FIELD_TAG        = 2,
32     SEARCH_FIELD_TITLE      = 3,
33     SEARCH_FIELD_VALUE      = 4,
34     NUM_SEARCH_FIELD        = 5
35 }SearchFieldType;
37 typedef struct _SearchField
39     int id;
40     int field_id;
41     SearchFieldType field_type;
42     SearchType type;
43     char *value;
44 }SearchField;
47 %ph{
48 #include <config.h>
49 #include "stuffkeeper-data-backend.h"
50     const char *SearchTypesNames[] = 
51     {
52         "Wrong Value",
53         "Is",
54         "Is Not",
55         "Contains",
56         "Does not contain"
57     };
58     const char *SearchFieldTypesNames[] = 
59     {
60         "Title",
61         "Schema",
62         "Tag",
63         "Item title",
64         "Item value"
65     };
69 class Stuffkeeper:Data:Item:Search from G:Object 
71     private int is_dummy = {FALSE};
72     private int id = {-1};
73     private StuffkeeperDataBackend *skdb = {NULL};
74     private sqlite3 *sqlHandle = {NULL};
76     private GtkBuilder *xml = {NULL};
77     private GtkListStore *store = {NULL} destroywith g_object_unref;
78     private GtkListStore *type_store = {NULL} destroywith g_object_unref;
79     private GtkListStore *field_type_store = {NULL} destroywith g_object_unref;
81     private guint title_timeout = {0};
82     /**
83      * Signals
84      */
85    
86     signal last NONE (POINTER)
87     void
88     search_changed(self, const SearchField *field)
89     {
90         if(field && self->_priv->store)
91         {
92             GtkTreeIter iter;
93             GtkTreeModel *model = GTK_TREE_MODEL(self->_priv->store);
94             if(gtk_tree_model_get_iter_first(model, &iter))
95             {
96                 do{
97                     SearchField *field2 = NULL;
98                     gtk_tree_model_get(model, &iter, 0, &field2, -1);
99                     if(field2){   
100                         if(field2->id == field->id)
101                         {
102                             GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
103                             gtk_tree_model_row_changed(model, path, &iter);
104                             gtk_tree_path_free(path);
105                         }
106                     }
107                 }while(gtk_tree_model_iter_next(model, &iter));
108             }
109         }
110     }
113     /**
114      * Utility
115      */
116     private 
117     gchar *
118     get_string(self, int searchtype, int fieldtype)
119     {
120         char *retv = NULL;
121         char *query = sqlite3_mprintf("SELECT value FROM 'SearchFields' WHERE SearchId=%i and SearchType=%i and FieldType=%i", 
122                 self->_priv->id,
123                 searchtype,
124                 fieldtype);
125         sqlite3_stmt *stmt;
126         const char *tail;
127         int r;
128         r = sqlite3_prepare_v2(self->_priv->sqlHandle, query, -1,  &stmt,  &tail);
129         if (r == SQLITE_OK) {
130             if((r = sqlite3_step(stmt)) == SQLITE_ROW) {
131                 retv = g_strdup((gchar *)sqlite3_column_text(stmt, 0));
132             }
133         }
134         sqlite3_finalize(stmt);
136         sqlite3_free(query);
137         return retv; 
138     }
139     public 
140     void
141     set_string(self,int searchtype, int fieldtype, const gchar *title)
142     {
143         int result;
144         char *error;
145         char *query;
146         char *val;
147         val = self_get_string(self, searchtype,fieldtype);
148         /* no field, create it */
149         if(!val)
150         {
151             query = sqlite3_mprintf("INSERT INTO 'SearchFields' ('SearchId','FieldType','SearchType','value')"
152                     "values (%i,%i,%i,%Q);",
153                     self->_priv->id,
154                     fieldtype,
155                     searchtype,
156                     title);
157         }
158         else{
159             /* if they are identical, do nothing */
160             if(strcmp(title, val) == 0)
161             {
162                 g_free(val);
163                 g_debug("not updating\n");
164                 return;
165             }
166             /* update the title */
167             query = sqlite3_mprintf("UPDATE 'SearchFields' SET value=%Q WHERE SearchId=%i and Fieldtype=%i and SearchType=%i", 
168                     title, 
169                     self->_priv->id,
170                     fieldtype,
171                     searchtype);
172             g_free(val);
173         }
174         result = sqlite3_exec(self->_priv->sqlHandle, query, NULL, NULL, &error);
175         if (result != SQLITE_OK) {
176             g_debug("failed: %s\n", error);
177         }
178         sqlite3_free(query);
179     }
182     /**
183      * Constructions
184      */
185     public
186     GObject *
187     new_dummy(void)
188     {
189         Self *self = GET_NEW;
190         self->_priv->is_dummy = TRUE;
191         return G_OBJECT(self);
192     }
194     public
195     GObject *
196     open_from_id(G:Object *skdb, gint id)
197     {
198         Self *self = GET_NEW;
199         self->_priv->skdb = STUFFKEEPER_DATA_BACKEND(skdb);
200         self->_priv->id = id;
201         self->_priv->sqlHandle = stuffkeeper_data_backend_get_handle(self->_priv->skdb);
202         return G_OBJECT(self);
203     }
204     /* Create new StuffkeeperDataBackend */
205     public 
206         StuffkeeperDataItemSearch *
207         new (G:Object *skdb)
208         {
210             Self *obj = GET_NEW;
211             int result = 0;
212             char *error = NULL;
213             char *query  = NULL;
214             obj->_priv->skdb = STUFFKEEPER_DATA_BACKEND(skdb);
215             obj->_priv->sqlHandle = stuffkeeper_data_backend_get_handle(obj->_priv->skdb);
216             /**
217              * Insert the first item in the list
218              */
219             query = sqlite3_mprintf
220                 ("INSERT INTO 'SearchFields' ('SearchType','FieldType','value')"
221                  "values (%i,%i,%Q);",
222                  SEARCH_TYPE_NONE, SEARCH_TITLE, "New Search");
224             result = sqlite3_exec(obj->_priv->sqlHandle, query, NULL, NULL, &error);
225             if (result != SQLITE_OK) {
226                 g_debug("failed: %s\n", error);
227             }
228             sqlite3_free(query);
230             /* Get the id of the insert, this is now the unique id for this field*/
231             obj->_priv->id = sqlite3_last_insert_rowid(obj->_priv->sqlHandle);
233             /* update the last inserted row */
234             query = sqlite3_mprintf
235                 ("UPDATE 'SearchFields' SET SearchId=%i WHERE id=%i",
236                  obj->_priv->id,obj->_priv->id);
237             result = sqlite3_exec(obj->_priv->sqlHandle, query, NULL, NULL, &error);
238             if (result != SQLITE_OK) {
239                 g_debug("failed: %s\n", error);
240             }
241             sqlite3_free(query);
243             
244             return obj;
245         }
246     public
247     void
248     free_search_field(SearchField*field)
249     {
250         if(field->value)
251         {
252             g_free(field->value);
253         }
254         g_free(field);
255     }
258     public
259     int 
260     match(self, StuffkeeperDataItem *item)
261     {
262         GList *node,*list = NULL;
263         int found = TRUE;
264         if(self->_priv->is_dummy == TRUE)
265         {
266             return TRUE;
267         }
269         list = self_get_search_fields(self);
270         for(node = g_list_first(list);node && found;node = g_list_next(node))
271         {
272             SearchField *field = node->data;
273             gchar *comp = NULL;
274             found = FALSE;
276             if(field->field_type== SEARCH_FIELD_TITLE)
277             {
278                 comp = stuffkeeper_data_item_get_title(item);
280             }
281             else if (field->field_type== SEARCH_FIELD_VALUE)
282             {
283                 if(field->type == SEARCH_TYPE_IS || field->type == SEARCH_TYPE_IS_NOT)
284                 {
285                     found = stuffkeeper_data_item_has_value_exact(item, field->value);
286                 }
287                 if(field->type == SEARCH_TYPE_CONTAINS || field->type == SEARCH_TYPE_NOT_CONTAINS )
288                 {
289                     found = stuffkeeper_data_item_has_value(item, field->value);
290                 }
291                 /* invert result for the _NOT_ */
292                 if(field->type == SEARCH_TYPE_NOT_CONTAINS || field->type == SEARCH_TYPE_IS_NOT) {
293                     found = !found;
294                 }
296             }
297             else if (field->field_type== SEARCH_FIELD_TAG)
298             {
299                 GList *list2, *node2;
300                 list2 = stuffkeeper_data_item_get_tags(item);
301                 if(list2)
302                 {
303                     for(node2 = g_list_first(list2);node2 && !found;node2 = g_list_next(node2))
304                     {
305                         comp = stuffkeeper_data_tag_get_title(STUFFKEEPER_DATA_TAG(node2->data));
306                         if(field->type == SEARCH_TYPE_IS || field->type == SEARCH_TYPE_IS_NOT)
307                         {
308                             found = (g_utf8_collate(field->value,comp) == 0); 
309                         }
310                         if(field->type == SEARCH_TYPE_CONTAINS || field->type == SEARCH_TYPE_NOT_CONTAINS )
311                         {
312                             gchar *sb1 = g_utf8_casefold(field->value, -1);
313                             gchar *sb = g_utf8_normalize(sb1,-1,G_NORMALIZE_ALL_COMPOSE);
314                             gchar *sa1 = g_utf8_casefold(comp, -1);
315                             gchar *sa = g_utf8_normalize(sa1,-1,G_NORMALIZE_ALL_COMPOSE);
316                             found =(strstr(sa,sb) != NULL);
317                             g_free(sa1);g_free(sb1);
318                             g_free(sa);g_free(sb);
320                         }
321                         g_free(comp);
322                         comp = NULL;
323                     }
324                     g_list_free(list2);
325                     /* invert result for the _NOT_ */
326                     if(field->type == SEARCH_TYPE_NOT_CONTAINS || field->type == SEARCH_TYPE_IS_NOT) {
327                         found = !found;
328                     }
329                 }
330             }
331             else if (field->field_type== SEARCH_FIELD_SCHEMA)
332             {
333                 comp = stuffkeeper_data_schema_get_title(stuffkeeper_data_item_get_schema(item));
334             }
336             if(comp)
337             {
338                 if(field->type == SEARCH_TYPE_IS || field->type == SEARCH_TYPE_IS_NOT)                   
339                 {
340                     found = (g_utf8_collate(field->value,comp) == 0); 
341                 }
342                 if(field->type == SEARCH_TYPE_CONTAINS || field->type == SEARCH_TYPE_NOT_CONTAINS )
343                 {
344                     gchar *sb1 = g_utf8_casefold(field->value, -1);
345                     gchar *sb = g_utf8_normalize(sb1,-1,G_NORMALIZE_ALL_COMPOSE);
346                     gchar *sa1 = g_utf8_casefold(comp, -1);
347                     gchar *sa = g_utf8_normalize(sa1,-1,G_NORMALIZE_ALL_COMPOSE);
348                     found =(strstr(sa,sb) != NULL);
349                     g_free(sa1);g_free(sb1);
350                     g_free(sa);g_free(sb);
352                 }
353                 g_free(comp);
354                 /* invert result for the _NOT_ */
355                 if(field->type == SEARCH_TYPE_NOT_CONTAINS || field->type == SEARCH_TYPE_IS_NOT) {
356                     found = !found;
357                 }
359             }
361         }
362         if(list)
363         {
364             g_list_foreach(list,(GFunc)self_free_search_field,NULL);
365             g_list_free(list);
366         }
369         return found; 
370     }
371     /**
372      * Get Fields
373      */
374     public
375     GList *
376     get_search_fields(self)
377     {
378         GList *list = NULL;
379         char *query = sqlite3_mprintf("SELECT Id,SearchId,FieldType,SearchType,value FROM 'SearchFields' WHERE SearchId=%i and SearchType!=%i", 
380                 self->_priv->id, SEARCH_TYPE_NONE);
381         sqlite3_stmt *stmt;
382         const char *tail;
383         int found = TRUE;
384         int r;
385         r = sqlite3_prepare_v2(self->_priv->sqlHandle, query, -1,  &stmt,  &tail);
386         if(r == SQLITE_OK ) {
387             while((r = sqlite3_step(stmt)) == SQLITE_ROW && found) {
388                 SearchField *field  = g_malloc0(sizeof(*field));
389                 field->id           = sqlite3_column_int(stmt, 0);
390                 field->field_id     = sqlite3_column_int(stmt, 1);
391                 field->field_type   = sqlite3_column_int(stmt, 2); 
392                 field->type         = sqlite3_column_int(stmt, 3);
393                 field->value        = g_strdup((char *)sqlite3_column_text(stmt, 4));
394                 list = g_list_append(list, field);
395             }
396         }
398         sqlite3_finalize(stmt);
399         return list;
400     }
401     
402     public
403     void
404     edit_search_field(self, SearchField *field)
405     {
406         int result = 0;
407         char *error = NULL;
408         char *query  = NULL;
410         /* update the title */
411         query = sqlite3_mprintf("UPDATE 'SearchFields' SET value=%Q , SearchId=%i , Fieldtype=%i , SearchType=%i WHERE id=%i", 
412                 field->value, 
413                 self->_priv->id,
414                 field->field_type,
415                 field->type,
416                 field->id);
417         result = sqlite3_exec(self->_priv->sqlHandle, query, NULL, NULL, &error);
418         if (result != SQLITE_OK) {
419             g_debug("failed: %s\n", error);
420         }
421         sqlite3_free(query);
422         self_search_changed(self, field);
423     }
424     public
425     void
426     remove_search_field(self, SearchField *field)
427     {
428         int result;
429         char *error;
430         char *query = NULL; 
432         query = sqlite3_mprintf("DELETE FROM 'SearchFields' WHERE id=%i",field->id);
433         result = sqlite3_exec(self->_priv->sqlHandle, query, NULL, NULL, &error);
434         if (result != SQLITE_OK) {
435             g_debug("failed: %s\n", error);
436         }
437         sqlite3_free(query);
438     }
440     public
441     SearchField *
442     new_search_field(self, SearchType searchtype, SearchFieldType fieldtype, const gchar *value)
443     {
444         SearchField *field = g_malloc0(sizeof(*field));
445         int result = 0;
446         char *error = NULL;
447         char *query  = NULL;
450         query = sqlite3_mprintf("INSERT INTO 'SearchFields' ('SearchId','SearchType','FieldType','value')"
451                 "values (%i,%i,%i,%Q);",
452                     self->_priv->id,
453                     searchtype,
454                     fieldtype,
455                     value);
457         result = sqlite3_exec(self->_priv->sqlHandle, query, NULL, NULL, &error);
458         if (result != SQLITE_OK) {
459             g_debug("failed: %s\n", error);
460         }
461         sqlite3_free(query);
463         /* Get the id of the insert, this is now the unique id for this field*/
464         field->id = sqlite3_last_insert_rowid(self->_priv->sqlHandle);
465         field->field_id = self->_priv->id;
466         field->field_type = fieldtype;
467         field->type = searchtype;
468         field->value = g_strdup(value);
471         return field;
472     }
474     /* title */
476     public
477     char *
478     get_title(self)
479     {
480         char *retv;
481         if(self->_priv->is_dummy == TRUE)
482         {
483             return g_strdup(("All the entries"));
484         }
485         retv = self_get_string(self,SEARCH_TYPE_NONE, SEARCH_TITLE);
486         if(!retv)
487             retv = g_strdup("Failed to get title");
488         return retv;
489     }
490     public
491     void 
492     set_title(self, const char *title)
493     {
494         if(self->_priv->is_dummy == TRUE)
495         {
496             return;
497         }
498         self_set_string(self, SEARCH_TYPE_NONE, SEARCH_TITLE, title);
499         self_search_changed(self, NULL);
500     }
502     public
503     int
504     get_id(self)
505     {
506         return self->_priv->id;
507     }
509     public
510     void
511     delete_yourself(self)
512     {
513         int result;
514         char *error;
515         char *query = NULL; 
517         query = sqlite3_mprintf("DELETE FROM 'SearchFields' WHERE SearchId=%i",self->_priv->id);
518         result = sqlite3_exec(self->_priv->sqlHandle, query, NULL, NULL, &error);
519         if (result != SQLITE_OK) {
520             g_debug("failed: %s\n", error);
521         }
522         sqlite3_free(query);
523         
524         self->_priv->id = 0;
525     }
529     /** 
530      * Glade
531      */
532     public
533     void
534     style_set(self, GtkStyle *style, GtkWidget *wid)
535     {
536         g_signal_handlers_block_by_func(G_OBJECT(wid), self_style_set,self);
537         gtk_widget_modify_bg(wid,
538                 GTK_STATE_NORMAL, 
539                 &((wid)->style->bg[GTK_STATE_SELECTED]));
540         gtk_widget_modify_text((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "title_label_search"), 
541                 GTK_STATE_NORMAL, 
542                 &((wid)->style->text[GTK_STATE_SELECTED]));
543         gtk_widget_modify_fg((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "title_label_search"), 
544                 GTK_STATE_NORMAL, 
545                 &((wid)->style->fg[GTK_STATE_SELECTED]));
546         g_signal_handlers_unblock_by_func(G_OBJECT(wid), self_style_set,self);
547     }
549    
550    private
551     gboolean 
552    search_title_changed_real(self)
553    {
554        GtkWidget *entry = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "title_entry");
555        const gchar *title = gtk_entry_get_text(GTK_ENTRY(entry));
556        if(self->_priv->title_timeout)
557             g_source_remove(self->_priv->title_timeout);
558         self->_priv->title_timeout = 0;
559         
560         if(title)
561         {
562             self_set_title(self,title); 
563         }
565         return FALSE;
566     }
568     public
569     void
570     search_title_changed(self, GtkWidget *entry)
571     {
572         if(self->_priv->title_timeout)
573             g_source_remove(self->_priv->title_timeout);
574         self->_priv->title_timeout = g_timeout_add(1000, (GSourceFunc)self_search_title_changed_real, self);
576     }
578     private 
579     void
580     response(self, int response, GtkWidget *dialog )
581     {
582         GtkWidget *dialog = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "edit_search_dialog");
584         if(self->_priv->title_timeout)
585         {
586             self_search_title_changed_real(self);
587         }
589         gtk_widget_destroy(dialog);
590             g_object_unref(self->_priv->xml);
591         self->_priv->xml = NULL;
592     }
594     private
595     void
596     field_get_value(GtkTreeViewColumn *column, GtkCellRenderer *renderer,GtkTreeModel *model, GtkTreeIter *iter,gpointer data)
597     {
598         SearchField *field=NULL;
599         gtk_tree_model_get(model, iter, 0, &field, -1);
600         if(field)
601         {
602             if(field->value)
603             {
604                 g_object_set (GTK_CELL_RENDERER (renderer),
605                         "text", field->value,
606                         NULL);
607             }
608         }
610     }
611     private
612     void
613     field_set_value(self, gchar *path, gchar *new_text, GtkCellRendererText *renderer)
614     {
615         GtkTreeIter iter;
616         GtkTreeModel *model = GTK_TREE_MODEL(self->_priv->store);
617         if(path)
618         {
619             if(gtk_tree_model_get_iter_from_string(model, &iter, path))
620             {
621                 SearchField *field = NULL;
622                 gtk_tree_model_get(model, &iter, 0, &field, -1);
623                 if(field->value) g_free(field->value);
624                 field->value = g_strdup(new_text);
625                 self_edit_search_field(self, field);
626             }
627         }
628     }
629 private
630     void
631     field_type_combo_get_value(GtkTreeViewColumn *column, GtkCellRenderer *renderer,GtkTreeModel *model, GtkTreeIter *iter,gpointer data)
632     {
633         SearchField *field=NULL;
634         gtk_tree_model_get(model, iter, 0, &field, -1);
635         if(field)
636         {
637             if(field->value)
638             {
639                 g_object_set (GTK_CELL_RENDERER (renderer),
640                         "text", SearchFieldTypesNames[field->field_type],
641                         NULL);
642             }
643         }
645     }
647     private
648     void
649     field_combo_set_value( self,
650          gchar               *path,
651          gchar               *new_text,
652          GtkCellRendererCombo *renderer)
653     {
654         GtkTreeIter iter;
655         if(path && new_text){   
656             GtkTreeModel *model = GTK_TREE_MODEL(self->_priv->store);
658             SearchField *field = NULL;
659             int i = 0;
661             for(i=0;strcmp(new_text,SearchTypesNames[i]) && i < SEARCH_TYPE_NUM_ITEMS;i++);
662             if(gtk_tree_model_get_iter_from_string(model, &iter, path))
663             {
664                 gtk_tree_model_get(model, &iter, 0, &field, -1);
665                 field->type = i;
666                 self_edit_search_field(self, field);
667             }
668         }
669     }
670     private
671         void
672     field_type_combo_set_value( self,
673          gchar               *path,
674          gchar               *new_text,
675          GtkCellRendererCombo *renderer)
676     {
677         GtkTreeIter iter;
678         if(path && new_text){   
679             GtkTreeModel *model = GTK_TREE_MODEL(self->_priv->store);
681             SearchField *field = NULL;
682             int i = 0;
684             for(i=0;strcmp(new_text,SearchFieldTypesNames[i]) && i < NUM_SEARCH_FIELD;i++);
685             if(gtk_tree_model_get_iter_from_string(model, &iter, path))
686             {
687                 gtk_tree_model_get(model, &iter, 0, &field, -1);
688                 field->field_type = i;
689                 self_edit_search_field(self, field);
690             }
691         }
692     }
695     private
696     void
697     field_combo_get_value(GtkTreeViewColumn *column, GtkCellRenderer *renderer,GtkTreeModel *model, GtkTreeIter *iter,gpointer data)
698     {
699         SearchField *field=NULL;
700         gtk_tree_model_get(model, iter, 0, &field, -1);
701         if(field)
702         {
703             if(field->value)
704             {
705                 g_object_set (GTK_CELL_RENDERER (renderer),
706                         "text", SearchTypesNames[field->type],
707                         NULL);
708             }
709         }
711     }
712     public
713     void
714     add_field(self,GtkWidget *button)
715     {
716         SearchField *field = NULL;
717         field = self_new_search_field(self,SEARCH_TYPE_IS,SEARCH_FIELD_TITLE ,_("New Search")); 
719         if(self->_priv->store)
720         {
721             GtkTreeIter iter;
722             gtk_list_store_append(self->_priv->store, &iter);
723             gtk_list_store_set(self->_priv->store, &iter,0, field,-1);
724         }
726         self_search_changed(self, field);
728     }
729     public
730         void
731     remove_field(self,GtkWidget *button)
732     {
733         GtkWidget *tree = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "treeview_items");
734         GtkTreeIter iter;
735         GtkTreeModel *model = GTK_TREE_MODEL(self->_priv->store);
736         GtkTreeSelection *selec = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
737         if(gtk_tree_selection_get_selected(selec, &model, &iter))
738         {
739             SearchField *field=NULL;
740             gtk_tree_model_get(model, &iter, 0, &field, -1);
741             self_remove_search_field( self, field);
742             gtk_list_store_remove(self->_priv->store,&iter);
743             self_search_changed(self, NULL);
744         }
745     }
747     public
748     void
749     edit_search_gui(self)
750     {
751         GtkWidget *dialog = NULL;
752         GError *error = NULL;
753         GtkTreeIter iter;
754         char *title;
755         GList *list, *node;
756         if(self->_priv->xml)
757         {
758             GtkWidget *win = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "edit_search_dialog");
759             gtk_window_present(GTK_WINDOW(win));
760             return;
761         }
764         self->_priv->xml = gtk_builder_new();
765         gtk_builder_add_from_file(self->_priv->xml, PACKAGE_DATADIR"/edit-search-dialog.ui",&error);
766         if(error) {
767                 g_error("Failed to open ui file: %s\n", error->message);
768                 g_error_free(error); 
769                 return;
770         }
771         dialog = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "edit_search_dialog");
773         title = self_get_title(self);
774         if(title) {
775             gtk_entry_set_text(GTK_ENTRY( gtk_builder_get_object(self->_priv->xml, "title_entry")), title);
776             g_free(title);
777         }
779         if(self->_priv->store == NULL)
780         {
781             self->_priv->store = gtk_list_store_new(1, G_TYPE_POINTER);
782             list = self_get_search_fields(self);
783             if(list)
784             {
785                 for(node = g_list_first(list);node;node = g_list_next(node))
786                 {
787                     gtk_list_store_append(self->_priv->store, &iter);
788                     gtk_list_store_set(self->_priv->store, &iter,0, node->data,-1);
789                 }
790                 g_list_free(list);
791             }
792         }
793         if(!(self->_priv->type_store))
794         {
795             int i;
796             self->_priv->type_store = gtk_list_store_new(2, G_TYPE_INT,G_TYPE_STRING);
797             for(i=SEARCH_TYPE_IS;i<SEARCH_TYPE_NUM_ITEMS;i++)
798             {
799                 gtk_list_store_append(self->_priv->type_store, &iter);
800                 gtk_list_store_set(self->_priv->type_store, &iter,0,i,1, SearchTypesNames[i],-1);
801             }
802         }
803         if(!(self->_priv->field_type_store))
804         {
805             int i;
806             self->_priv->field_type_store = gtk_list_store_new(2, G_TYPE_INT,G_TYPE_STRING);
807             for(i=SEARCH_FIELD_SCHEMA;i<NUM_SEARCH_FIELD;i++)
808             {
809                 gtk_list_store_append(self->_priv->field_type_store, &iter);
810                 gtk_list_store_set(self->_priv->field_type_store, &iter,0,i,1, SearchFieldTypesNames[i],-1);
811             }
812         }
814         GtkCellRenderer *renderer;
816         renderer = gtk_cell_renderer_combo_new();
817         g_object_set(G_OBJECT(renderer), "model", GTK_TREE_MODEL(self->_priv->field_type_store), NULL);
818         g_object_set(G_OBJECT(renderer), "text-column", 1,"has-entry", FALSE, NULL);
819         g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
820         gtk_tree_view_insert_column_with_data_func(
821                     GTK_TREE_VIEW(gtk_builder_get_object(self->_priv->xml, "treeview_items")),
822                     -1,
823                     "Value",
824                     renderer,
825                     self_field_type_combo_get_value,
826                     NULL,
827                     NULL);
828         g_signal_connect_swapped(G_OBJECT(renderer), "edited", G_CALLBACK(self_field_type_combo_set_value), self);
830         renderer = gtk_cell_renderer_combo_new();
831         g_object_set(G_OBJECT(renderer), "model", GTK_TREE_MODEL(self->_priv->type_store), NULL);
832         g_object_set(G_OBJECT(renderer), "text-column", 1,"has-entry", FALSE, NULL);
833         g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
834         gtk_tree_view_insert_column_with_data_func(
835                     GTK_TREE_VIEW(gtk_builder_get_object(self->_priv->xml, "treeview_items")),
836                     -1,
837                     "Value",
838                     renderer,
839                     self_field_combo_get_value,
840                     NULL,
841                     NULL);
843         g_signal_connect_swapped(G_OBJECT(renderer), "edited", G_CALLBACK(self_field_combo_set_value), self);
848         renderer = gtk_cell_renderer_text_new();
849         gtk_tree_view_insert_column_with_data_func(
850                     GTK_TREE_VIEW(gtk_builder_get_object(self->_priv->xml, "treeview_items")),
851                     -1,
852                     "Value",
853                     renderer,
854                     self_field_get_value,
855                     NULL,
856                     NULL);
858         g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
859         g_signal_connect_swapped(G_OBJECT(renderer), "edited", G_CALLBACK(self_field_set_value), self);
862         /** */
863         gtk_tree_view_set_model(GTK_TREE_VIEW(gtk_builder_get_object(self->_priv->xml, "treeview_items")), GTK_TREE_MODEL(self->_priv->store));
865         gtk_builder_connect_signals_full(self->_priv->xml, (GtkBuilderConnectFunc)self____builder_xml_connect_foreach, (gpointer)self);
866         gtk_widget_show(dialog);
868         g_signal_connect_swapped(G_OBJECT(dialog), "response", G_CALLBACK(self_response), self);
869     }
871     private
872     void
873     ___builder_xml_connect_foreach(
874                     GtkBuilder *builder,
875                     GObject *object,
876                     const gchar *signal_name,
877                     const gchar *handler_name,
878                     GObject *connect_object,
879                     GConnectFlags flags,
880                     gpointer user_data)
881         {
882             static GModule * allsymbols = NULL;
884                 printf("%s - %s\n", signal_name, handler_name);
885             if (!allsymbols) allsymbols = g_module_open(NULL, 0);
886             if (allsymbols) {
887                 gchar * func_name = g_strdup_printf("stuffkeeper_data_item_search_%s", handler_name);
888                 GCallback func;
890                 if (!g_module_symbol(allsymbols, func_name, (gpointer)&func)){
891                     if (!g_module_symbol(allsymbols, handler_name, (gpointer)&func)) {
892                         g_warning("could not find signal handler '%s'.", func_name);
893                         g_free(func_name);
894                         return;
895                     }
896                 }
897                 g_signal_connect_data(object, signal_name, func, user_data, NULL, G_CONNECT_SWAPPED | flags);
898                 g_free(func_name);
899             }
900         }