1 #include <errno.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include <gtk/gtk.h>
7 #include <glib/gstdio.h>
8 #include <glib/gi18n-lib.h>
9
10 #include <libgda-ui/libgda-ui.h>
11 #include <libgda/binreloc/gda-binreloc.h>
12 #include <sql-parser/gda-sql-parser.h>
13
14 #include <demos.h>
15
16 /* to be used by example */
17 GdaConnection *demo_cnc;
18 GdaSqlParser *demo_parser;
19
20
21 static GtkTextBuffer *info_buffer;
22 static GtkTextBuffer *source_buffer;
23
24 static gchar *current_file = NULL;
25
26
27 enum {
28 TITLE_COLUMN,
29 FILENAME_COLUMN,
30 FUNC_COLUMN,
31 STYLE_COLUMN,
32 NUM_COLUMNS
33 };
34
35 typedef struct _CallbackData CallbackData;
36 struct _CallbackData
37 {
38 GtkTreeModel *model;
39 GtkTreePath *path;
40 };
41
42 /**
43 * demo_find_file:
44 * @base: base filename
45 * @err: location to store error, or %NULL.
46 *
47 * Looks for @base first in the current directory, then in the
48 * location GTK+ where it will be installed on make install,
49 * returns the first file found.
50 *
51 * Returns: the filename, if found or %NULL
52 **/
53 gchar *
demo_find_file(const char * base,GError ** err)54 demo_find_file (const char *base, GError **err)
55 {
56 g_return_val_if_fail (err == NULL || *err == NULL, NULL);
57
58 if (g_file_test ("demos.h", G_FILE_TEST_EXISTS) &&
59 g_file_test (base, G_FILE_TEST_EXISTS))
60 return g_strdup (base);
61 else {
62 gchar *filename;
63
64 filename = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, "demo", base, NULL);
65 if (!g_file_test (filename, G_FILE_TEST_EXISTS)) {
66 g_set_error (err, G_FILE_ERROR, G_FILE_ERROR_NOENT,
67 "Cannot find demo data file \"%s\"", base);
68 g_free (filename);
69 return NULL;
70 }
71 return filename;
72 }
73 }
74
75 static void
window_closed_cb(G_GNUC_UNUSED GtkWidget * window,gpointer data)76 window_closed_cb (G_GNUC_UNUSED GtkWidget *window, gpointer data)
77 {
78 CallbackData *cbdata = data;
79 GtkTreeIter iter;
80 PangoStyle style;
81
82 gtk_tree_model_get_iter (cbdata->model, &iter, cbdata->path);
83 gtk_tree_model_get (GTK_TREE_MODEL (cbdata->model), &iter,
84 STYLE_COLUMN, &style,
85 -1);
86 if (style == PANGO_STYLE_ITALIC)
87 gtk_tree_store_set (GTK_TREE_STORE (cbdata->model), &iter,
88 STYLE_COLUMN, PANGO_STYLE_NORMAL,
89 -1);
90
91 gtk_tree_path_free (cbdata->path);
92 g_free (cbdata);
93 }
94
95 gboolean
read_line(FILE * stream,GString * str)96 read_line (FILE *stream, GString *str)
97 {
98 int n_read = 0;
99
100 #ifdef HAVE_FLOCKFILE
101 flockfile (stream);
102 #endif
103
104 g_string_truncate (str, 0);
105
106 while (1) {
107 int c;
108
109 #ifdef HAVE_FLOCKFILE
110 c = getc_unlocked (stream);
111 #else
112 c = getc (stream);
113 #endif
114
115 if (c == EOF)
116 goto done;
117 else
118 n_read++;
119
120 switch (c) {
121 case '\r':
122 case '\n': {
123 #ifdef HAVE_FLOCKFILE
124 int next_c = getc_unlocked (stream);
125 #else
126 int next_c = getc (stream);
127 #endif
128
129 if (!(next_c == EOF ||
130 (c == '\r' && next_c == '\n') ||
131 (c == '\n' && next_c == '\r')))
132 ungetc (next_c, stream);
133
134 goto done;
135 }
136 default:
137 g_string_append_c (str, c);
138 }
139 }
140
141 done:
142
143 #ifdef HAVE_FLOCKFILE
144 funlockfile (stream);
145 #endif
146
147 return n_read > 0;
148 }
149
150
151 /* Stupid syntax highlighting.
152 *
153 * No regex was used in the making of this highlighting.
154 * It should only work for simple cases. This is good, as
155 * that's all we should have in the demos.
156 */
157 /* This code should not be used elsewhere, except perhaps as an example of how
158 * to iterate through a text buffer.
159 */
160 enum {
161 STATE_NORMAL,
162 STATE_IN_COMMENT
163 };
164
165 static gchar *tokens[] =
166 {
167 "/*",
168 "\"",
169 NULL
170 };
171
172 static gchar *types[] =
173 {
174 "static",
175 "const ",
176 "void",
177 "gint",
178 "int ",
179 "char ",
180 "gchar ",
181 "gfloat",
182 "float",
183 "gint8",
184 "gint16",
185 "gint32",
186 "guint",
187 "guint8",
188 "guint16",
189 "guint32",
190 "guchar",
191 "glong",
192 "gboolean" ,
193 "gshort",
194 "gushort",
195 "gulong",
196 "gdouble",
197 "gldouble",
198 "gpointer",
199 "NULL",
200 "GList",
201 "GSList",
202 "FALSE",
203 "TRUE",
204 "FILE ",
205 "GtkObject ",
206 "GtkColorSelection ",
207 "GtkWidget ",
208 "GtkButton ",
209 "GdkColor ",
210 "GdkRectangle ",
211 "GdkEventExpose ",
212 "GdkGC ",
213 "GdkPixbufLoader ",
214 "GdkPixbuf ",
215 "GError",
216 "size_t",
217 NULL
218 };
219
220 static gchar *control[] =
221 {
222 " if ",
223 " while ",
224 " else",
225 " do ",
226 " for ",
227 "?",
228 ":",
229 "return ",
230 "goto ",
231 NULL
232 };
233 void
parse_chars(gchar * text,gchar ** end_ptr,gint * state,gchar ** tag,gboolean start)234 parse_chars (gchar *text,
235 gchar **end_ptr,
236 gint *state,
237 gchar **tag,
238 gboolean start)
239 {
240 gint i;
241 gchar *next_token;
242
243 /* Handle comments first */
244 if (*state == STATE_IN_COMMENT) {
245 *end_ptr = strstr (text, "*/");
246 if (*end_ptr) {
247 *end_ptr += 2;
248 *state = STATE_NORMAL;
249 *tag = "comment";
250 }
251 return;
252 }
253
254 *tag = NULL;
255 *end_ptr = NULL;
256
257 /* check for comment */
258 if (!strncmp (text, "/*", 2)) {
259 *end_ptr = strstr (text, "*/");
260 if (*end_ptr)
261 *end_ptr += 2;
262 else
263 *state = STATE_IN_COMMENT;
264 *tag = "comment";
265 return;
266 }
267
268 /* check for preprocessor defines */
269 if (*text == '#' && start) {
270 *end_ptr = NULL;
271 *tag = "preprocessor";
272 return;
273 }
274
275 /* functions */
276 if (start && * text != '\t' && *text != ' ' && *text != '{' && *text != '}') {
277 if (strstr (text, "(")) {
278 *end_ptr = strstr (text, "(");
279 *tag = "function";
280 return;
281 }
282 }
283 /* check for types */
284 for (i = 0; types[i] != NULL; i++)
285 if (!strncmp (text, types[i], strlen (types[i]))) {
286 *end_ptr = text + strlen (types[i]);
287 *tag = "type";
288 return;
289 }
290
291 /* check for control */
292 for (i = 0; control[i] != NULL; i++)
293 if (!strncmp (text, control[i], strlen (control[i]))) {
294 *end_ptr = text + strlen (control[i]);
295 *tag = "control";
296 return;
297 }
298
299 /* check for string */
300 if (text[0] == '"') {
301 gint maybe_escape = FALSE;
302
303 *end_ptr = text + 1;
304 *tag = "string";
305 while (**end_ptr != '\000') {
306 if (**end_ptr == '\"' && !maybe_escape) {
307 *end_ptr += 1;
308 return;
309 }
310 if (**end_ptr == '\\')
311 maybe_escape = TRUE;
312 else
313 maybe_escape = FALSE;
314 *end_ptr += 1;
315 }
316 return;
317 }
318
319 /* not at the start of a tag. Find the next one. */
320 for (i = 0; tokens[i] != NULL; i++) {
321 next_token = strstr (text, tokens[i]);
322 if (next_token) {
323 if (*end_ptr)
324 *end_ptr = (*end_ptr<next_token)?*end_ptr:next_token;
325 else
326 *end_ptr = next_token;
327 }
328 }
329
330 for (i = 0; types[i] != NULL; i++) {
331 next_token = strstr (text, types[i]);
332 if (next_token) {
333 if (*end_ptr)
334 *end_ptr = (*end_ptr<next_token)?*end_ptr:next_token;
335 else
336 *end_ptr = next_token;
337 }
338 }
339
340 for (i = 0; control[i] != NULL; i++) {
341 next_token = strstr (text, control[i]);
342 if (next_token) {
343 if (*end_ptr)
344 *end_ptr = (*end_ptr<next_token)?*end_ptr:next_token;
345 else
346 *end_ptr = next_token;
347 }
348 }
349 }
350
351 /* While not as cool as c-mode, this will do as a quick attempt at highlighting */
352 static void
fontify(void)353 fontify (void)
354 {
355 GtkTextIter start_iter, next_iter, tmp_iter;
356 gint state;
357 gchar *text;
358 gchar *start_ptr, *end_ptr;
359 gchar *tag;
360
361 state = STATE_NORMAL;
362
363 gtk_text_buffer_get_iter_at_offset (source_buffer, &start_iter, 0);
364
365 next_iter = start_iter;
366 while (gtk_text_iter_forward_line (&next_iter)) {
367 gboolean start = TRUE;
368 start_ptr = text = gtk_text_iter_get_text (&start_iter, &next_iter);
369
370 do {
371 parse_chars (start_ptr, &end_ptr, &state, &tag, start);
372
373 start = FALSE;
374 if (end_ptr) {
375 tmp_iter = start_iter;
376 gtk_text_iter_forward_chars (&tmp_iter, end_ptr - start_ptr);
377 }
378 else
379 tmp_iter = next_iter;
380 if (tag)
381 gtk_text_buffer_apply_tag_by_name (source_buffer, tag, &start_iter, &tmp_iter);
382
383 start_iter = tmp_iter;
384 start_ptr = end_ptr;
385 }
386 while (end_ptr);
387
388 g_free (text);
389 start_iter = next_iter;
390 }
391 }
392
393 void
load_file(const gchar * filename)394 load_file (const gchar *filename)
395 {
396 FILE *file;
397 GtkTextIter start, end;
398 char *full_filename;
399 GError *err = NULL;
400 GString *buffer = g_string_new (NULL);
401 int state = 0;
402 gboolean in_para = 0;
403
404 if (current_file && !strcmp (current_file, filename)) {
405 g_string_free (buffer, TRUE);
406 return;
407 }
408
409 g_free (current_file);
410 current_file = g_strdup (filename);
411
412 gtk_text_buffer_get_bounds (info_buffer, &start, &end);
413 gtk_text_buffer_delete (info_buffer, &start, &end);
414
415 gtk_text_buffer_get_bounds (source_buffer, &start, &end);
416 gtk_text_buffer_delete (source_buffer, &start, &end);
417
418 full_filename = demo_find_file (filename, &err);
419 if (!full_filename) {
420 g_warning ("%s", err->message);
421 g_error_free (err);
422 return;
423 }
424
425 file = g_fopen (full_filename, "r");
426
427 if (!file)
428 g_warning ("Cannot open %s: %s\n", full_filename, g_strerror (errno));
429
430 g_free (full_filename);
431
432 if (!file)
433 return;
434
435 gtk_text_buffer_get_iter_at_offset (info_buffer, &start, 0);
436 while (read_line (file, buffer)) {
437 gchar *p = buffer->str;
438 gchar *q;
439 gchar *r;
440
441 switch (state) {
442 case 0:
443 /* Reading title */
444 while (*p == '/' || *p == '*' || g_ascii_isspace (*p))
445 p++;
446 r = p;
447 while (*r != '/' && strlen (r))
448 r++;
449 if (strlen (r) > 0)
450 p = r + 1;
451 q = p + strlen (p);
452 while (q > p && g_ascii_isspace (*(q - 1)))
453 q--;
454
455 if (q > p) {
456 glong len_chars = g_utf8_pointer_to_offset (p, q);
457
458 end = start;
459
460 g_assert (strlen (p) >= (gsize)(q - p));
461 gtk_text_buffer_insert (info_buffer, &end, p, q - p);
462 start = end;
463
464 gtk_text_iter_backward_chars (&start, len_chars);
465 gtk_text_buffer_apply_tag_by_name (info_buffer, "title", &start, &end);
466
467 start = end;
468
469 state++;
470 }
471 break;
472
473 case 1:
474 /* Reading body of info section */
475 while (g_ascii_isspace (*p))
476 p++;
477 if (*p == '*' && *(p + 1) == '/') {
478 gtk_text_buffer_get_iter_at_offset (source_buffer, &start, 0);
479 state++;
480 }
481 else {
482 gsize len;
483
484 while (*p == '*' || g_ascii_isspace (*p))
485 p++;
486
487 len = strlen (p);
488 while ((len > 0) && g_ascii_isspace (*(p + len - 1)))
489 len--;
490
491 if (len > 0) {
492 if (in_para)
493 gtk_text_buffer_insert (info_buffer, &start, " ", 1);
494
495 g_assert (strlen (p) >= len);
496 gtk_text_buffer_insert (info_buffer, &start, p, len);
497 in_para = 1;
498 }
499 else {
500 gtk_text_buffer_insert (info_buffer, &start, "\n", 1);
501 in_para = 0;
502 }
503 }
504 break;
505
506 case 2:
507 /* Skipping blank lines */
508 while (g_ascii_isspace (*p))
509 p++;
510 if (*p) {
511 p = buffer->str;
512 state++;
513 /* Fall through */
514 }
515 else
516 break;
517
518 case 3:
519 /* Reading program body */
520 gtk_text_buffer_insert (source_buffer, &start, p, -1);
521 gtk_text_buffer_insert (source_buffer, &start, "\n", 1);
522 break;
523 }
524 }
525
526 fontify ();
527
528 g_string_free (buffer, TRUE);
529 }
530
531 void
row_activated_cb(GtkTreeView * tree_view,GtkTreePath * path,G_GNUC_UNUSED GtkTreeViewColumn * column)532 row_activated_cb (GtkTreeView *tree_view,
533 GtkTreePath *path,
534 G_GNUC_UNUSED GtkTreeViewColumn *column)
535 {
536 GtkTreeIter iter;
537 PangoStyle style;
538 GDoDemoFunc func;
539 GtkWidget *window;
540 GtkTreeModel *model;
541
542 model = gtk_tree_view_get_model (tree_view);
543
544 gtk_tree_model_get_iter (model, &iter, path);
545 gtk_tree_model_get (GTK_TREE_MODEL (model),
546 &iter,
547 FUNC_COLUMN, &func,
548 STYLE_COLUMN, &style,
549 -1);
550
551 if (func) {
552 gtk_tree_store_set (GTK_TREE_STORE (model),
553 &iter,
554 STYLE_COLUMN, (style == PANGO_STYLE_ITALIC ? PANGO_STYLE_NORMAL : PANGO_STYLE_ITALIC),
555 -1);
556 window = (func) (gtk_widget_get_toplevel (GTK_WIDGET (tree_view)));
557
558 if (window != NULL) {
559 CallbackData *cbdata;
560
561 cbdata = g_new (CallbackData, 1);
562 cbdata->model = model;
563 cbdata->path = gtk_tree_path_copy (path);
564
565 g_signal_connect (window, "destroy",
566 G_CALLBACK (window_closed_cb), cbdata);
567 }
568 }
569 }
570
571 static void
selection_cb(GtkTreeSelection * selection,GtkTreeModel * model)572 selection_cb (GtkTreeSelection *selection,
573 GtkTreeModel *model)
574 {
575 GtkTreeIter iter;
576 GValue *value;
577
578 if (! gtk_tree_selection_get_selected (selection, NULL, &iter))
579 return;
580
581 value = g_slice_new0(GValue);
582 gtk_tree_model_get_value (model, &iter,
583 FILENAME_COLUMN,
584 value);
585 if (g_value_get_string (value))
586 load_file (g_value_get_string (value));
587 g_value_unset (value);
588 g_slice_free(GValue, value);
589 }
590
591 static GtkWidget *
create_text(GtkTextBuffer ** buffer,gboolean is_source)592 create_text (GtkTextBuffer **buffer,
593 gboolean is_source)
594 {
595 GtkWidget *scrolled_window;
596 GtkWidget *text_view;
597 PangoFontDescription *font_desc;
598
599 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
600 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
601 GTK_POLICY_AUTOMATIC,
602 GTK_POLICY_AUTOMATIC);
603 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
604 GTK_SHADOW_IN);
605
606 text_view = gtk_text_view_new ();
607
608 *buffer = gtk_text_buffer_new (NULL);
609 gtk_text_view_set_buffer (GTK_TEXT_VIEW (text_view), *buffer);
610 gtk_text_view_set_editable (GTK_TEXT_VIEW (text_view), FALSE);
611 gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (text_view), FALSE);
612
613 gtk_container_add (GTK_CONTAINER (scrolled_window), text_view);
614
615 if (is_source) {
616 font_desc = pango_font_description_from_string ("monospace");
617 gtk_widget_override_font (text_view, font_desc);
618 pango_font_description_free (font_desc);
619
620 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text_view),
621 GTK_WRAP_NONE);
622 }
623 else {
624 /* Make it a bit nicer for text. */
625 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text_view),
626 GTK_WRAP_WORD);
627 gtk_text_view_set_pixels_above_lines (GTK_TEXT_VIEW (text_view),
628 2);
629 gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (text_view),
630 2);
631 }
632
633 return scrolled_window;
634 }
635
636 static GtkWidget *
create_tree(void)637 create_tree (void)
638 {
639 GtkTreeSelection *selection;
640 GtkCellRenderer *cell;
641 GtkWidget *tree_view;
642 GtkTreeViewColumn *column;
643 GtkTreeStore *model;
644 GtkTreeIter iter;
645 GtkWidget *box, *label, *scrolled_window;
646
647 Demo *d = gdaui_demos;
648
649 model = gtk_tree_store_new (NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT);
650 tree_view = gtk_tree_view_new ();
651 gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (model));
652 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
653
654 gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection),
655 GTK_SELECTION_BROWSE);
656 gtk_widget_set_size_request (tree_view, 200, -1);
657
658 /* this code only supports 1 level of children. If we
659 * want more we probably have to use a recursing function.
660 */
661 while (d->title) {
662 Demo *children = d->children;
663
664 gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
665
666 gtk_tree_store_set (GTK_TREE_STORE (model),
667 &iter,
668 TITLE_COLUMN, d->title,
669 FILENAME_COLUMN, d->filename,
670 FUNC_COLUMN, d->func,
671 STYLE_COLUMN, PANGO_STYLE_NORMAL,
672 -1);
673
674 d++;
675
676 if (!children)
677 continue;
678
679 while (children->title) {
680 GtkTreeIter child_iter;
681
682 gtk_tree_store_append (GTK_TREE_STORE (model), &child_iter, &iter);
683
684 gtk_tree_store_set (GTK_TREE_STORE (model),
685 &child_iter,
686 TITLE_COLUMN, children->title,
687 FILENAME_COLUMN, children->filename,
688 FUNC_COLUMN, children->func,
689 STYLE_COLUMN, PANGO_STYLE_NORMAL,
690 -1);
691
692 children++;
693 }
694 }
695
696 cell = gtk_cell_renderer_text_new ();
697
698 column = gtk_tree_view_column_new_with_attributes ("Widget (double click for demo)",
699 cell,
700 "text", TITLE_COLUMN,
701 "style", STYLE_COLUMN,
702 NULL);
703
704 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
705 GTK_TREE_VIEW_COLUMN (column));
706
707 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter);
708 gtk_tree_selection_select_iter (GTK_TREE_SELECTION (selection), &iter);
709
710 g_signal_connect (selection, "changed", G_CALLBACK (selection_cb), model);
711 g_signal_connect (tree_view, "row-activated", G_CALLBACK (row_activated_cb), model);
712
713 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
714 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view), FALSE);
715
716 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
717 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
718 GTK_POLICY_NEVER,
719 GTK_POLICY_AUTOMATIC);
720 gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
721
722 label = gtk_label_new ("Widget (double click for demo)");
723
724 box = gtk_notebook_new ();
725 gtk_notebook_append_page (GTK_NOTEBOOK (box), scrolled_window, label);
726
727 gtk_widget_grab_focus (tree_view);
728
729 return box;
730 }
731
732 int
main(int argc,char ** argv)733 main (int argc, char **argv)
734 {
735 GtkWidget *window;
736 GtkWidget *notebook;
737 GtkWidget *hbox;
738 GtkWidget *tree;
739 GtkTextTag *tag;
740 GError *error = NULL;
741 gchar *full_filename, *dirname;
742 gchar *cncstring;
743 GtkWidget *msg;
744 gchar *str;
745 GdaMetaStore *mstore;
746
747 /* Initialize i18n support */
748 str = gda_gbr_get_file_path (GDA_LOCALE_DIR, NULL);
749 bindtextdomain (GETTEXT_PACKAGE, str);
750 g_free (str);
751
752 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
753 textdomain (GETTEXT_PACKAGE);
754
755 /* Initialize libgda-ui & GTK+ */
756 gtk_init (&argc, &argv);
757 gdaui_init ();
758
759 /* Initialize GdaConnection object */
760 full_filename = demo_find_file ("demo_db.db", &error);
761 if (!full_filename) {
762 g_warning (_("Can't find demo database file: %s"), error->message);
763 g_error_free (error);
764 exit (1);
765 }
766
767 dirname = g_path_get_dirname (full_filename);
768 cncstring = g_strdup_printf ("DB_DIR=%s;DB_NAME=demo_db", dirname);
769 g_free (dirname);
770 demo_cnc = gda_connection_open_from_string ("SQLite", cncstring, NULL, 0, &error);
771 if (!demo_cnc) {
772 g_warning (_("Error opening the connection for file '%s':\n%s\n"),
773 full_filename,
774 error && error->message ? error->message : _("No detail"));
775 g_error_free (error);
776 exit (1);
777 }
778 g_free (full_filename);
779 g_free (cncstring);
780
781 /* Initialize meta store */
782 full_filename = demo_find_file ("demo_meta.db", &error);
783 if (full_filename)
784 mstore = gda_meta_store_new_with_file (full_filename);
785 else
786 mstore = gda_meta_store_new (NULL);
787
788 g_free (full_filename);
789 g_object_set (G_OBJECT (demo_cnc), "meta-store", mstore, NULL);
790 g_object_unref (mstore);
791 if (! full_filename)
792 gda_connection_update_meta_store (demo_cnc, NULL, NULL);
793
794 /* Initialize parser object */
795 demo_parser = gda_connection_create_parser (demo_cnc);
796 if (!demo_parser)
797 demo_parser = gda_sql_parser_new ();
798
799 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
800 gtk_window_set_title (GTK_WINDOW (window), _("Libgda-ui Code Demos"));
801 g_signal_connect (window, "destroy",
802 G_CALLBACK (gtk_main_quit), NULL);
803
804 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
805 gtk_container_add (GTK_CONTAINER (window), hbox);
806
807 tree = create_tree ();
808 gtk_box_pack_start (GTK_BOX (hbox), tree, FALSE, FALSE, 0);
809
810 notebook = gtk_notebook_new ();
811 gtk_box_pack_start (GTK_BOX (hbox), notebook, TRUE, TRUE, 0);
812
813 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
814 create_text (&info_buffer, FALSE),
815 gtk_label_new_with_mnemonic ("_Info"));
816
817 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
818 create_text (&source_buffer, TRUE),
819 gtk_label_new_with_mnemonic ("_Source"));
820
821 tag = gtk_text_buffer_create_tag (info_buffer, "title",
822 "font", "Sans 18",
823 NULL);
824
825 tag = gtk_text_buffer_create_tag (source_buffer, "comment",
826 "foreground", "DodgerBlue",
827 NULL);
828 tag = gtk_text_buffer_create_tag (source_buffer, "type",
829 "foreground", "ForestGreen",
830 NULL);
831 tag = gtk_text_buffer_create_tag (source_buffer, "string",
832 "foreground", "RosyBrown",
833 "weight", PANGO_WEIGHT_BOLD,
834 NULL);
835 tag = gtk_text_buffer_create_tag (source_buffer, "control",
836 "foreground", "purple",
837 NULL);
838 tag = gtk_text_buffer_create_tag (source_buffer, "preprocessor",
839 "style", PANGO_STYLE_OBLIQUE,
840 "foreground", "burlywood4",
841 NULL);
842 tag = gtk_text_buffer_create_tag (source_buffer, "function",
843 "weight", PANGO_WEIGHT_BOLD,
844 "foreground", "DarkGoldenrod4",
845 NULL);
846
847 gtk_window_set_default_size (GTK_WINDOW (window), 600, 700);
848 gtk_widget_show_all (window);
849
850 load_file (gdaui_demos[0].filename);
851
852 full_filename = demo_find_file ("demo_db.db", NULL);
853 msg = gtk_message_dialog_new_with_markup (GTK_WINDOW (window), GTK_DIALOG_MODAL,
854 GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
855 _("<b><big>Note:\n</big></b>Many of the demonstrated items use an\n"
856 "opened connection to the SQLite using the\n"
857 "'%s' file.\n\n"
858 "In the source code shown here, the <i>demo_cnc</i> and \n"
859 "<i>demo_parser</i> objects are created by the framework and\n"
860 "made available to all the demonstrated items."), full_filename);
861 g_free (full_filename);
862 g_signal_connect_swapped (msg, "response",
863 G_CALLBACK (gtk_widget_destroy), msg);
864 gtk_widget_show (msg);
865
866 gtk_main ();
867
868 return 0;
869 }
870