am-project: Expand variables in source names
[anjuta.git] / plugins / symbol-db / symbol-db-model-project.c
blobc5078403e4bef5865126e3508d1ec1b2f5f1c2a4
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * symbol-db-model-project.c
4 * Copyright (C) Naba Kumar 2010 <naba@gnome.org>
5 *
6 * anjuta is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * anjuta is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "symbol-db-engine.h"
21 #include "symbol-db-model-project.h"
22 #include <libanjuta/anjuta-debug.h>
24 #define SDB_MODEL_PROJECT_SQL " \
25 SELECT \
26 symbol.symbol_id, \
27 symbol.name, \
28 symbol.file_position, \
29 symbol.scope_definition_id, \
30 symbol.signature, \
31 symbol.returntype, \
32 symbol.type_type, \
33 symbol.type_name, \
34 file.file_path, \
35 sym_access.access_name, \
36 sym_kind.is_container \
37 FROM symbol \
38 LEFT JOIN file ON symbol.file_defined_id = file.file_id \
39 LEFT JOIN sym_access ON symbol.access_kind_id = sym_access.access_kind_id \
40 LEFT JOIN sym_kind ON symbol.kind_id = sym_kind.sym_kind_id \
41 WHERE \
42 ( \
43 symbol.scope_id = ## /* name:'parent' type:gint */ \
44 AND symbol.kind_id IN \
45 ( \
46 SELECT sym_kind_id \
47 FROM sym_kind \
48 WHERE \
49 ( \
50 0 = ## /* name:'parent' type:gint */ \
51 AND sym_kind.kind_name IN ('class', 'struct', 'union', 'enum') \
52 ) \
53 OR \
54 ( \
55 0 != ## /* name:'parent' type:gint */ \
56 AND sym_kind.kind_name != 'namespace' \
57 ) \
58 ) \
59 ) \
60 OR \
61 ( \
62 symbol.symbol_id IN \
63 ( \
64 SELECT symbol_id \
65 FROM symbol \
66 WHERE \
67 symbol.scope_id = ## /* name:'parent' type:gint */ \
68 AND symbol.kind_id IN \
69 ( \
70 SELECT sym_kind_id \
71 FROM sym_kind \
72 WHERE sym_kind.kind_name = 'namespace' \
73 ) \
74 GROUP BY symbol.scope_definition_id \
76 ) \
77 ) \
78 ORDER BY symbol.name \
79 LIMIT ## /* name:'limit' type:gint */ \
80 OFFSET ## /* name:'offset' type:gint */ \
83 struct _SymbolDBModelProjectPriv
85 SymbolDBEngine* dbe;
86 GdaStatement *stmt;
87 GdaSet *params;
88 GdaHolder *param_parent_id, *param_limit, *param_offset;
89 gboolean show_file_line;
92 /* this values must map the fields of SDB_MODEL_PROJECT_SQL */
93 enum {
94 DATA_COL_SYMBOL_ID,
95 DATA_COL_SYMBOL_NAME,
96 DATA_COL_SYMBOL_FILE_LINE,
97 DATA_COL_SYMBOL_SCOPE_DEFINITION_ID,
98 DATA_COL_SYMBOL_ARGS,
99 DATA_COL_SYMBOL_RETURNTYPE,
100 DATA_COL_SYMBOL_TYPE,
101 DATA_COL_SYMBOL_TYPE_NAME,
102 DATA_COL_SYMBOL_FILE_PATH,
103 DATA_COL_SYMBOL_ACCESS,
104 DATA_COL_SYMBOL_HAS_CHILD,
105 DATA_N_COLS
108 enum
110 PROP_0,
111 PROP_SYMBOL_DB_ENGINE,
112 PROP_SHOW_FILE_LINE
115 G_DEFINE_TYPE (SymbolDBModelProject, sdb_model_project,
116 SYMBOL_DB_TYPE_MODEL);
118 static void
119 sdb_model_project_update_sql_stmt (SymbolDBModel *model)
121 SymbolDBModelProjectPriv *priv;
123 g_return_if_fail (SYMBOL_DB_IS_MODEL_PROJECT (model));
124 priv = SYMBOL_DB_MODEL_PROJECT (model)->priv;
126 priv->stmt = symbol_db_engine_get_statement (priv->dbe, SDB_MODEL_PROJECT_SQL);
127 gda_statement_get_parameters (priv->stmt, &priv->params, NULL);
128 priv->param_parent_id = gda_set_get_holder (priv->params, "parent");
129 priv->param_limit = gda_set_get_holder (priv->params, "limit");
130 priv->param_offset = gda_set_get_holder (priv->params, "offset");
133 static GdaDataModel*
134 sdb_model_project_get_children (SymbolDBModel *model, gint tree_level,
135 GValue column_values[], gint offset,
136 gint limit)
138 SymbolDBModelProjectPriv *priv;
139 gint parent_id;
140 GValue ival = {0};
142 g_return_val_if_fail (SYMBOL_DB_IS_MODEL_PROJECT (model), 0);
143 priv = SYMBOL_DB_MODEL_PROJECT (model)->priv;
145 /* If engine is not connected, there is nothing we can show */
146 if (!priv->dbe || !symbol_db_engine_is_connected (priv->dbe))
147 return NULL;
149 /* Determin node parent */
150 switch (tree_level)
152 case 0:
153 parent_id = 0;
154 break;
155 default:
156 parent_id = g_value_get_int
157 (&column_values[SYMBOL_DB_MODEL_PROJECT_COL_SCOPE_DEFINITION_ID]);
160 if (!priv->stmt)
161 sdb_model_project_update_sql_stmt (model);
163 /* Initialize parameters */
164 g_value_init (&ival, G_TYPE_INT);
165 g_value_set_int (&ival, parent_id);
166 gda_holder_set_value (priv->param_parent_id, &ival, NULL);
167 g_value_set_int (&ival, limit);
168 gda_holder_set_value (priv->param_limit, &ival, NULL);
169 g_value_set_int (&ival, offset);
170 gda_holder_set_value (priv->param_offset, &ival, NULL);
172 return symbol_db_engine_execute_select (priv->dbe, priv->stmt, priv->params);
175 static gboolean
176 sdb_model_project_get_has_child (SymbolDBModel *model, gint tree_level,
177 GValue column_values[])
179 return (g_value_get_int
180 (&column_values[SYMBOL_DB_MODEL_PROJECT_COL_HAS_CHILD]) > 0);
183 static gint
184 sdb_model_project_get_n_children (SymbolDBModel *model, gint tree_level,
185 GValue column_values[])
187 gint n_children = 0;
188 GdaDataModel *data_model;
190 data_model = sdb_model_project_get_children (model, tree_level,
191 column_values, 0,
192 INT_MAX);
193 if (GDA_IS_DATA_MODEL (data_model))
195 n_children = gda_data_model_get_n_rows (data_model);
196 g_object_unref (data_model);
198 return n_children;
201 static gboolean
202 sdb_model_project_get_query_value (SymbolDBModel *model,
203 GdaDataModel *data_model,
204 GdaDataModelIter *iter,
205 gint column,
206 GValue *value)
208 const GdkPixbuf *pixbuf;
209 const GValue *ret_value;
210 const gchar *name = NULL;
211 const gchar *type = NULL;
212 const gchar *access = NULL;
213 const gchar *args = NULL;
214 GString *label;
216 switch (column)
218 case SYMBOL_DB_MODEL_PROJECT_COL_PIXBUF:
219 ret_value = gda_data_model_iter_get_value_at (iter,
220 DATA_COL_SYMBOL_TYPE);
221 if (ret_value && G_VALUE_HOLDS_STRING (ret_value))
222 type = g_value_get_string (ret_value);
223 ret_value = gda_data_model_iter_get_value_at (iter,
224 DATA_COL_SYMBOL_ACCESS);
225 if (ret_value && G_VALUE_HOLDS_STRING (ret_value))
226 access = g_value_get_string (ret_value);
228 pixbuf = symbol_db_util_get_pixbuf (type, access);
229 g_value_set_object (value, G_OBJECT (pixbuf));
230 return TRUE;
231 break;
232 case SYMBOL_DB_MODEL_PROJECT_COL_LABEL:
233 label = g_string_new_len (NULL, 256);
234 ret_value = gda_data_model_iter_get_value_at (iter,
235 DATA_COL_SYMBOL_NAME);
236 if (ret_value && G_VALUE_HOLDS_STRING (ret_value))
238 gchar* escaped;
239 name = g_value_get_string (ret_value);
240 escaped = g_markup_escape_text (name, -1);
241 g_string_assign (label, escaped);
242 g_free (escaped);
244 ret_value = gda_data_model_iter_get_value_at (iter,
245 DATA_COL_SYMBOL_ARGS);
246 if (ret_value && G_VALUE_HOLDS_STRING (ret_value))
247 args = g_value_get_string (ret_value);
248 /* */
249 if (args)
251 if (strlen (args) == 2)
252 g_string_append (label, "()");
253 else if (strlen (args) > 2)
254 g_string_append (label, "(...)");
255 ret_value =
256 gda_data_model_iter_get_value_at (iter,
257 DATA_COL_SYMBOL_RETURNTYPE);
258 if (ret_value && G_VALUE_HOLDS_STRING (ret_value))
260 gchar *escaped =
261 g_markup_escape_text (g_value_get_string (ret_value), -1);
262 g_string_append (label, "<span style=\"italic\"> : ");
263 g_string_append (label, escaped);
264 g_string_append (label, "</span>");
265 g_free (escaped);
268 else
270 ret_value =
271 gda_data_model_iter_get_value_at (iter,
272 DATA_COL_SYMBOL_TYPE_NAME);
273 if (ret_value && G_VALUE_HOLDS_STRING (ret_value) &&
274 g_strcmp0 (g_value_get_string (ret_value), name) != 0)
276 gchar *escaped =
277 g_markup_escape_text (g_value_get_string (ret_value), -1);
278 g_string_append (label, "<span style=\"italic\"> : ");
279 g_string_append (label, escaped);
280 g_string_append (label, "</span>");
281 g_free (escaped);
284 if (SYMBOL_DB_MODEL_PROJECT (model)->priv->show_file_line)
286 ret_value =
287 gda_data_model_iter_get_value_at (iter,
288 DATA_COL_SYMBOL_FILE_PATH);
289 if (ret_value && G_VALUE_HOLDS_STRING (ret_value))
291 gint file_line = 0;
292 const gchar* file_name = g_value_get_string (ret_value);
294 ret_value =
295 gda_data_model_iter_get_value_at (iter,
296 DATA_COL_SYMBOL_FILE_LINE);
297 file_line = g_value_get_int (ret_value);
298 g_string_append_printf
299 (label,
300 "\n<span font-size=\"x-small\" font-weight=\"ultralight\"><tt>%s:%d</tt></span>",
301 file_name, file_line);
304 /* DEBUG_PRINT ("Output string: %s", label->str);*/
305 g_value_take_string (value, label->str);
306 g_string_free (label, FALSE);
307 return TRUE;
308 break;
309 case SYMBOL_DB_MODEL_PROJECT_COL_ARGS:
310 ret_value = gda_data_model_iter_get_value_at (iter,
311 DATA_COL_SYMBOL_ARGS);
312 if (ret_value && G_VALUE_HOLDS_STRING (ret_value)
313 && strlen (g_value_get_string (ret_value)) > 2)
315 gchar *escaped =
316 g_markup_escape_text (g_value_get_string (ret_value), -1);
317 g_value_take_string (value, escaped);
319 return TRUE;
320 break;
321 default:
322 return SYMBOL_DB_MODEL_CLASS (sdb_model_project_parent_class)->
323 get_query_value (model, data_model, iter, column, value);
327 static void
328 on_sdb_project_dbe_unref (SymbolDBModelProject *model)
330 SymbolDBModelProjectPriv *priv;
332 g_return_if_fail (SYMBOL_DB_IS_MODEL_PROJECT (model));
333 priv = SYMBOL_DB_MODEL_PROJECT (model)->priv;
334 priv->dbe = NULL;
335 symbol_db_model_update (SYMBOL_DB_MODEL (model));
338 static void
339 sdb_model_project_set_property (GObject *object, guint prop_id,
340 const GValue *value, GParamSpec *pspec)
342 SymbolDBModelProjectPriv *priv;
344 g_return_if_fail (SYMBOL_DB_IS_MODEL_PROJECT (object));
345 priv = SYMBOL_DB_MODEL_PROJECT (object)->priv;
347 switch (prop_id)
349 case PROP_SYMBOL_DB_ENGINE:
350 if (priv->dbe)
352 g_object_weak_unref (G_OBJECT (priv->dbe),
353 (GWeakNotify)on_sdb_project_dbe_unref,
354 object);
355 g_signal_handlers_disconnect_by_func (priv->dbe,
356 G_CALLBACK (symbol_db_model_update),
357 object);
358 g_signal_handlers_disconnect_by_func (priv->dbe,
359 G_CALLBACK (symbol_db_model_freeze),
360 object);
361 g_signal_handlers_disconnect_by_func (priv->dbe,
362 G_CALLBACK (symbol_db_model_thaw),
363 object);
365 priv->dbe = g_value_dup_object (value);
366 g_object_weak_ref (G_OBJECT (priv->dbe),
367 (GWeakNotify)on_sdb_project_dbe_unref,
368 object);
369 g_signal_connect_swapped (priv->dbe, "db-connected",
370 G_CALLBACK (symbol_db_model_update),
371 object);
372 g_signal_connect_swapped (priv->dbe, "db-disconnected",
373 G_CALLBACK (symbol_db_model_update),
374 object);
375 g_signal_connect_swapped (priv->dbe, "scan-begin",
376 G_CALLBACK (symbol_db_model_freeze), object);
377 g_signal_connect_swapped (priv->dbe, "scan-end",
378 G_CALLBACK (symbol_db_model_thaw), object);
380 symbol_db_model_update (SYMBOL_DB_MODEL (object));
381 break;
382 case PROP_SHOW_FILE_LINE:
383 priv->show_file_line = g_value_get_boolean (value);
384 break;
385 default:
386 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
387 break;
391 static void
392 sdb_model_project_get_property (GObject *object, guint prop_id,
393 GValue *value, GParamSpec *pspec)
395 SymbolDBModelProjectPriv *priv;
397 g_return_if_fail (SYMBOL_DB_IS_MODEL_PROJECT (object));
398 priv = SYMBOL_DB_MODEL_PROJECT (object)->priv;
400 switch (prop_id)
402 case PROP_SYMBOL_DB_ENGINE:
403 g_value_set_object (value, priv->dbe);
404 break;
405 case PROP_SHOW_FILE_LINE:
406 g_value_set_boolean (value, priv->show_file_line);
407 break;
408 default:
409 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
410 break;
414 static void
415 sdb_model_project_finalize (GObject *object)
417 SymbolDBModelProjectPriv *priv;
419 g_return_if_fail (SYMBOL_DB_IS_MODEL_PROJECT (object));
420 priv = SYMBOL_DB_MODEL_PROJECT (object)->priv;
422 if (priv->dbe)
424 g_object_weak_unref (G_OBJECT (priv->dbe),
425 (GWeakNotify)on_sdb_project_dbe_unref,
426 object);
427 g_signal_handlers_disconnect_by_func (priv->dbe,
428 G_CALLBACK (symbol_db_model_update),
429 object);
430 g_signal_handlers_disconnect_by_func (priv->dbe,
431 G_CALLBACK (symbol_db_model_freeze),
432 object);
433 g_signal_handlers_disconnect_by_func (priv->dbe,
434 G_CALLBACK (symbol_db_model_thaw),
435 object);
438 if (priv->stmt)
440 g_object_unref (priv->stmt);
441 g_object_unref (priv->params);
444 g_free (priv);
446 G_OBJECT_CLASS (sdb_model_project_parent_class)->finalize (object);
449 static void
450 sdb_model_project_init (SymbolDBModelProject *object)
452 SymbolDBModelProjectPriv *priv;
454 GType types[] = {
455 G_TYPE_INT,
456 GDK_TYPE_PIXBUF,
457 G_TYPE_STRING,
458 G_TYPE_STRING,
459 G_TYPE_INT,
460 G_TYPE_STRING,
461 G_TYPE_INT,
462 G_TYPE_INT
465 gint data_cols[] = {
466 DATA_COL_SYMBOL_ID,
469 DATA_COL_SYMBOL_FILE_PATH,
470 DATA_COL_SYMBOL_FILE_LINE,
471 DATA_COL_SYMBOL_ARGS,
472 DATA_COL_SYMBOL_SCOPE_DEFINITION_ID,
473 DATA_COL_SYMBOL_HAS_CHILD
476 g_return_if_fail (SYMBOL_DB_IS_MODEL_PROJECT (object));
478 priv = g_new0 (SymbolDBModelProjectPriv, 1);
479 object->priv = priv;
481 priv->dbe = NULL;
483 g_assert ((sizeof (types) / sizeof (GType)) == (sizeof (data_cols) / sizeof (gint)));
484 symbol_db_model_set_columns (SYMBOL_DB_MODEL (object),
485 (sizeof (types) / sizeof (GType)),
486 types, data_cols);
489 static void
490 sdb_model_project_class_init (SymbolDBModelProjectClass *klass)
492 GObjectClass* object_class = G_OBJECT_CLASS (klass);
493 SymbolDBModelClass* parent_class = SYMBOL_DB_MODEL_CLASS (klass);
495 g_type_class_add_private (klass, sizeof (SymbolDBModelProjectPriv));
497 object_class->finalize = sdb_model_project_finalize;
498 object_class->set_property = sdb_model_project_set_property;
499 object_class->get_property = sdb_model_project_get_property;
501 parent_class->get_query_value = sdb_model_project_get_query_value;
502 parent_class->get_has_child = sdb_model_project_get_has_child;
503 parent_class->get_n_children = sdb_model_project_get_n_children;
504 parent_class->get_children = sdb_model_project_get_children;
506 g_object_class_install_property
507 (object_class, PROP_SYMBOL_DB_ENGINE,
508 g_param_spec_object ("symbol-db-engine",
509 "Symbol DB Engine",
510 "Symbol DB Engine instance used to make queries",
511 SYMBOL_TYPE_DB_ENGINE,
512 G_PARAM_READABLE |
513 G_PARAM_WRITABLE |
514 G_PARAM_CONSTRUCT_ONLY));
515 g_object_class_install_property
516 (object_class, PROP_SHOW_FILE_LINE,
517 g_param_spec_boolean ("show-file-line",
518 "Show file and line",
519 "Show file and line number in labels",
520 FALSE,
521 G_PARAM_READABLE |
522 G_PARAM_WRITABLE));
525 GtkTreeModel*
526 symbol_db_model_project_new (SymbolDBEngine* dbe)
528 return GTK_TREE_MODEL (g_object_new (SYMBOL_DB_TYPE_MODEL_PROJECT,
529 "symbol-db-engine", dbe, NULL));