1 /*
2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU Lesser General Public License as published by
4 * the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful, but
7 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9 * for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, see <http://www.gnu.org/licenses/>.
13 *
14 *
15 * Authors:
16 * Chris Lahey <clahey@ximian.com>
17 *
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
19 *
20 */
21
22 #include "evolution-config.h"
23
24 #include <string.h>
25
26 #include <libedataserver/libedataserver.h>
27
28 #include "e-marshal.h"
29 #include "e-table-search.h"
30
31 #define d(x)
32
33 struct _ETableSearchPrivate {
34 guint timeout_id;
35
36 gchar *search_string;
37 gunichar last_character;
38 };
39
40 G_DEFINE_TYPE (ETableSearch, e_table_search, G_TYPE_OBJECT)
41
42 enum {
43 SEARCH_SEARCH,
44 SEARCH_ACCEPT,
45 LAST_SIGNAL
46 };
47
48 #define E_TABLE_SEARCH_GET_PRIVATE(obj) \
49 (G_TYPE_INSTANCE_GET_PRIVATE \
50 ((obj), E_TYPE_TABLE_SEARCH, ETableSearchPrivate))
51
52 d (static gint depth = 0)
53
54 static guint e_table_search_signals[LAST_SIGNAL] = { 0, };
55
56 static gboolean
e_table_search_search(ETableSearch * e_table_search,gchar * string,ETableSearchFlags flags)57 e_table_search_search (ETableSearch *e_table_search,
58 gchar *string,
59 ETableSearchFlags flags)
60 {
61 gboolean ret_val;
62 g_return_val_if_fail (E_IS_TABLE_SEARCH (e_table_search), FALSE);
63
64 g_signal_emit (
65 e_table_search,
66 e_table_search_signals[SEARCH_SEARCH], 0,
67 string, flags, &ret_val);
68
69 return ret_val;
70 }
71
72 static void
e_table_search_accept(ETableSearch * e_table_search)73 e_table_search_accept (ETableSearch *e_table_search)
74 {
75 g_return_if_fail (E_IS_TABLE_SEARCH (e_table_search));
76
77 g_signal_emit (
78 e_table_search,
79 e_table_search_signals[SEARCH_ACCEPT], 0);
80 }
81
82 static gboolean
ets_accept(gpointer data)83 ets_accept (gpointer data)
84 {
85 ETableSearch *ets = data;
86 e_table_search_accept (ets);
87 g_free (ets->priv->search_string);
88
89 ets->priv->timeout_id = 0;
90 ets->priv->search_string = g_strdup ("");
91 ets->priv->last_character = 0;
92
93 return FALSE;
94 }
95
96 static void
drop_timeout(ETableSearch * ets)97 drop_timeout (ETableSearch *ets)
98 {
99 if (ets->priv->timeout_id > 0) {
100 g_source_remove (ets->priv->timeout_id);
101 ets->priv->timeout_id = 0;
102 }
103 }
104
105 static void
add_timeout(ETableSearch * ets)106 add_timeout (ETableSearch *ets)
107 {
108 drop_timeout (ets);
109
110 ets->priv->timeout_id =
111 e_named_timeout_add_seconds (1, ets_accept, ets);
112 }
113
114 static void
e_table_search_finalize(GObject * object)115 e_table_search_finalize (GObject *object)
116 {
117 ETableSearchPrivate *priv;
118
119 priv = E_TABLE_SEARCH_GET_PRIVATE (object);
120
121 drop_timeout (E_TABLE_SEARCH (object));
122
123 g_free (priv->search_string);
124
125 /* Chain up to parent's finalize() method. */
126 G_OBJECT_CLASS (e_table_search_parent_class)->finalize (object);
127 }
128
129 static void
e_table_search_class_init(ETableSearchClass * class)130 e_table_search_class_init (ETableSearchClass *class)
131 {
132 GObjectClass *object_class;
133
134 g_type_class_add_private (class, sizeof (ETableSearchPrivate));
135
136 object_class = G_OBJECT_CLASS (class);
137 object_class->finalize = e_table_search_finalize;
138
139 e_table_search_signals[SEARCH_SEARCH] = g_signal_new (
140 "search",
141 G_TYPE_FROM_CLASS (object_class),
142 G_SIGNAL_RUN_LAST,
143 G_STRUCT_OFFSET (ETableSearchClass, search),
144 (GSignalAccumulator) NULL, NULL,
145 e_marshal_BOOLEAN__STRING_INT,
146 G_TYPE_BOOLEAN, 2,
147 G_TYPE_STRING,
148 G_TYPE_INT);
149
150 e_table_search_signals[SEARCH_ACCEPT] = g_signal_new (
151 "accept",
152 G_TYPE_FROM_CLASS (object_class),
153 G_SIGNAL_RUN_LAST,
154 G_STRUCT_OFFSET (ETableSearchClass, accept),
155 (GSignalAccumulator) NULL, NULL,
156 g_cclosure_marshal_VOID__VOID,
157 G_TYPE_NONE, 0);
158
159 class->search = NULL;
160 class->accept = NULL;
161 }
162
163 static void
e_table_search_init(ETableSearch * ets)164 e_table_search_init (ETableSearch *ets)
165 {
166 ets->priv = E_TABLE_SEARCH_GET_PRIVATE (ets);
167
168 ets->priv->search_string = g_strdup ("");
169 }
170
171 ETableSearch *
e_table_search_new(void)172 e_table_search_new (void)
173 {
174 return g_object_new (E_TYPE_TABLE_SEARCH, NULL);
175 }
176
177 /**
178 * e_table_search_column_count:
179 * @e_table_search: The e-table-search to operate on
180 *
181 * Returns: the number of columns in the table search.
182 */
183 void
e_table_search_input_character(ETableSearch * ets,gunichar character)184 e_table_search_input_character (ETableSearch *ets,
185 gunichar character)
186 {
187 gchar character_utf8[7];
188 gchar *temp_string;
189
190 g_return_if_fail (ets != NULL);
191 g_return_if_fail (E_IS_TABLE_SEARCH (ets));
192
193 character_utf8[g_unichar_to_utf8 (character, character_utf8)] = 0;
194
195 temp_string = g_strdup_printf ("%s%s", ets->priv->search_string, character_utf8);
196 if (e_table_search_search (
197 ets, temp_string,
198 ets->priv->last_character != 0 ?
199 E_TABLE_SEARCH_FLAGS_CHECK_CURSOR_FIRST : 0)) {
200 g_free (ets->priv->search_string);
201 ets->priv->search_string = temp_string;
202 add_timeout (ets);
203 ets->priv->last_character = character;
204 return;
205 } else {
206 g_free (temp_string);
207 }
208
209 if (character == ets->priv->last_character) {
210 if (ets->priv->search_string &&
211 e_table_search_search (ets, ets->priv->search_string, 0)) {
212 add_timeout (ets);
213 }
214 }
215 }
216
217 gboolean
e_table_search_backspace(ETableSearch * ets)218 e_table_search_backspace (ETableSearch *ets)
219 {
220 gchar *end;
221
222 g_return_val_if_fail (ets != NULL, FALSE);
223 g_return_val_if_fail (E_IS_TABLE_SEARCH (ets), FALSE);
224
225 if (!ets->priv->search_string ||
226 !*ets->priv->search_string)
227 return FALSE;
228
229 end = ets->priv->search_string + strlen (ets->priv->search_string);
230 end = g_utf8_prev_char (end);
231 *end = 0;
232 ets->priv->last_character = 0;
233 add_timeout (ets);
234 return TRUE;
235 }
236