1 /* MDB Tools - A library for reading MS Access database file
2  * Copyright (C) 2000 Brian Bruns
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #include "gmdb.h"
20 
21 #if SQL
22 
23 GList *sql_list;
24 
25 extern MdbHandle *mdb;
26 extern MdbSQL *sql;
27 
28 static void gmdb_sql_tree_populate (MdbHandle*, GtkBuilder*);
29 static void gmdb_sql_load_query (GtkBuilder*, gchar*);
30 static void gmdb_sql_save_query (GtkBuilder*, gchar*);
31 static void gmdb_sql_save_as_cb (GtkWidget*, GtkBuilder*);
32 
33 void
gmdb_sql_close_all()34 gmdb_sql_close_all()
35 {
36 	GtkBuilder *xml;
37 	GtkWidget *win;
38 
39 	while ((xml = g_list_nth_data(sql_list, 0))) {
40 		win = GTK_WIDGET(gtk_builder_get_object (xml, "sql_window"));
41 		sql_list = g_list_remove(sql_list, xml);
42 		if (win) gtk_widget_destroy(win);
43 	}
44 }
45 
46 gchar* gmdb_export_get_filepath (GtkBuilder*);	/* from table_export.c */
47 
48 /* callbacks */
49 static void
gmdb_sql_write_rslt_cb(GtkWidget * w,GtkBuilder * xml)50 gmdb_sql_write_rslt_cb(GtkWidget *w, GtkBuilder *xml)
51 {
52 	/* We need to re-run the whole query because some information is not stored
53 	 * in the TreeStore, such as column types.
54 	 */
55 	gchar *file_path;
56 	GtkBuilder *sql_xml;
57 	GtkWidget *filesel, *dlg;
58 	FILE *outfile;
59 	int i;
60 	int need_headers = 0;
61 	gchar delimiter[11];
62 	gchar quotechar[5];
63 	gchar escape_char[5];
64 	int bin_mode;
65 	gchar lineterm[5];
66 
67 	guint len;
68 	gchar *buf;
69 	GtkTextIter start, end;
70 	GtkTextBuffer *txtbuffer;
71 	GtkWidget *textview;
72 	char **bound_values;
73 	int *bound_lens;
74 	MdbSQLColumn *sqlcol;
75 	long row;
76 	char *value;
77 	size_t length;
78 	MdbTableDef *table;
79 	MdbColumn *col = NULL;
80 
81 	gmdb_export_get_delimiter(xml, delimiter, sizeof(delimiter));
82 	gmdb_export_get_lineterm(xml, lineterm, sizeof(lineterm));
83 	gmdb_export_get_quotechar(xml, quotechar, sizeof(quotechar));
84 	gmdb_export_get_escapechar(xml, escape_char, sizeof(escape_char));
85 	bin_mode = gmdb_export_get_binmode(xml);
86 	need_headers = gmdb_export_get_headers(xml);
87 	file_path = gmdb_export_get_filepath(xml);
88 
89 	if ((outfile=fopen(file_path, "w"))==NULL) {
90 		dlg = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (w)),
91 		    GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE,
92 		    _("Unable to open file."));
93 		gtk_dialog_run (GTK_DIALOG (dlg));
94 		gtk_widget_destroy (dlg);
95 		return;
96 	}
97 
98 	/* Get SQL */
99 	filesel = GTK_WIDGET(gtk_builder_get_object (xml, "export_dialog"));
100 	sql_xml = g_object_get_data(G_OBJECT(filesel), "sql_xml");
101 	//printf("sql_xml %p\n",sql_xml);
102 	textview = GTK_WIDGET(gtk_builder_get_object(sql_xml, "sql_textview"));
103 	txtbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
104 	len = gtk_text_buffer_get_char_count(txtbuffer);
105 	gtk_text_buffer_get_iter_at_offset (txtbuffer, &start, 0);
106 	gtk_text_buffer_get_iter_at_offset (txtbuffer, &end, len);
107 	buf = gtk_text_buffer_get_text(txtbuffer, &start, &end, FALSE);
108 
109 
110 	/* ok now execute it */
111 	mdb_sql_run_query(sql, buf);
112 	if (mdb_sql_has_error(sql)) {
113 		GtkWidget* dlg = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (w)),
114 		    GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE,
115 		    "%s", mdb_sql_last_error(sql));
116 		gtk_dialog_run (GTK_DIALOG (dlg));
117 		gtk_widget_destroy (dlg);
118 		mdb_sql_reset(sql);
119 
120 		fclose(outfile);
121 		gtk_widget_destroy(filesel);
122 		return;
123 	}
124 
125 	bound_values = (char **) g_malloc(sql->num_columns * sizeof(char *));
126 	bound_lens = (int *) g_malloc(sql->num_columns * sizeof(int));
127 
128 	for (i=0; i<sql->num_columns; i++) {
129 		/* bind columns */
130 		bound_values[i] = (char *) g_malloc0(MDB_BIND_SIZE);
131 		mdb_sql_bind_column(sql, i+1, bound_values[i], &bound_lens[i]);
132 
133 		/* display column titles */
134 		if (need_headers) {
135 			if (i>0)
136 				fputs(delimiter, outfile);
137 			sqlcol = g_ptr_array_index(sql->columns,i);
138 			mdb_print_col(outfile, sqlcol->name, quotechar[0]!='\0', MDB_TEXT, 0, quotechar, escape_char, bin_mode);
139 		}
140 	}
141 
142 	row = 0;
143 	while (mdb_fetch_row(sql->cur_table)) {
144 		row++;
145 		for (i=0; i<sql->num_columns; i++) {
146 			if (i>0)
147 				fputs(delimiter, outfile);
148 
149 			sqlcol = g_ptr_array_index(sql->columns, i);
150 
151 			/* Find col matching sqlcol */
152 			table = sql->cur_table;
153 			for (i=0; i<table->num_cols; i++) {
154 				col = g_ptr_array_index(table->columns, i);
155 				if (!g_ascii_strcasecmp(sqlcol->name, col->name))
156 					break;
157 			}
158 			/* assert(i!=table->num_cols). Can't happen, already checked. */
159 
160 			/* Don't quote NULLs */
161 			if (bound_lens[i] && sqlcol->bind_type != MDB_OLE) {
162 				if (col->col_type == MDB_OLE) {
163 					value = mdb_ole_read_full(mdb, col, &length);
164 				} else {
165 					value = bound_values[i];
166 					length = bound_lens[i];
167 				}
168 				mdb_print_col(outfile, value, quotechar[0]!='\0', col->col_type, length, quotechar, escape_char, bin_mode);
169 				if (col->col_type == MDB_OLE)
170 					free(value);
171 			}
172 		}
173 		fputs(lineterm, outfile);
174 	}
175 
176 	/* free the memory used to bind */
177 	for (i=0; i<sql->num_columns; i++) {
178 		g_free(bound_values[i]);
179 	}
180 
181 	mdb_sql_reset(sql);
182 	g_free(buf);
183 
184 	fclose(outfile);
185 
186 	dlg = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (w)),
187 	    GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE,
188 	    _("%ld rows successfully exported."), row);
189 	gtk_dialog_run (GTK_DIALOG (dlg));
190 	gtk_widget_destroy (dlg);
191 
192 	gtk_widget_destroy(filesel);
193 }
194 
195 
196 static void
gmdb_sql_results_cb(GtkWidget * w,GtkBuilder * xml)197 gmdb_sql_results_cb(GtkWidget *w, GtkBuilder *xml)
198 {
199     GError *error = NULL;
200 	GtkBuilder *dialog_xml;
201 	GtkWidget *but;
202 	GtkWidget *filesel;
203 
204 	/* load the interface */
205 	dialog_xml = gtk_builder_new();
206     if (!gtk_builder_add_from_file(dialog_xml, GMDB_UIDIR "gmdb-export.ui", NULL)) {
207         g_warning("Error loading " GMDB_UIDIR "gmdb-export.ui: %s", error->message);
208         g_error_free(error);
209     }
210 	/* connect the signals in the interface */
211 	gtk_builder_connect_signals(dialog_xml, NULL);
212 
213 	filesel = GTK_WIDGET (gtk_builder_get_object(dialog_xml, "export_dialog"));
214 	gtk_window_set_title(GTK_WINDOW(filesel), "Save Results As");
215 
216 	but = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "export_button"));
217 	gtk_widget_hide(but);
218 
219 	but = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "save_button"));
220 	g_signal_connect (G_OBJECT (but), "clicked",
221 		G_CALLBACK (gmdb_sql_write_rslt_cb), dialog_xml);
222 	gtk_widget_show(but);
223 
224 	g_object_set_data(G_OBJECT(filesel), "sql_xml", xml);
225 }
226 static void
gmdb_sql_save_cb(GtkWidget * w,GtkBuilder * xml)227 gmdb_sql_save_cb(GtkWidget *w, GtkBuilder *xml)
228 {
229 	GtkWidget *textview;
230 	gchar *str;
231 
232 	textview = GTK_WIDGET(gtk_builder_get_object (xml, "sql_textview"));
233 	str = g_object_get_data(G_OBJECT(textview), "file_name");
234 	if (!str) {
235 		gmdb_sql_save_as_cb(w, xml);
236 		return;
237 	}
238 	gmdb_sql_save_query(xml, str);
239 }
240 static void
gmdb_sql_save_as_cb(GtkWidget * w,GtkBuilder * xml)241 gmdb_sql_save_as_cb(GtkWidget *w, GtkBuilder *xml)
242 {
243 	GtkWindow *parent_window = GTK_WINDOW(gtk_builder_get_object (xml, "gmdb"));
244 	GtkWidget *dialog = gtk_file_chooser_dialog_new ("Save Query As",
245 					      parent_window,
246 					      GTK_FILE_CHOOSER_ACTION_SAVE,
247 					      "_Cancel", GTK_RESPONSE_CANCEL,
248 					      "_Save", GTK_RESPONSE_ACCEPT,
249 					      NULL);
250 
251 	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
252 	  {
253 	    char *filename;
254 
255 	    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
256 	    gmdb_sql_save_query(xml, filename);
257 	  }
258 
259 	gtk_widget_destroy (dialog);
260 }
261 static void
gmdb_sql_open_cb(GtkWidget * w,GtkBuilder * xml)262 gmdb_sql_open_cb(GtkWidget *w, GtkBuilder *xml)
263 {
264 	GtkWindow *parent_window = GTK_WINDOW(gtk_builder_get_object (xml, "gmdb"));
265 	GtkWidget *dialog = gtk_file_chooser_dialog_new ("Open SQL Query",
266 					      parent_window,
267 					      GTK_FILE_CHOOSER_ACTION_OPEN,
268 					      "_Cancel", GTK_RESPONSE_CANCEL,
269 					      "_Open", GTK_RESPONSE_ACCEPT,
270 					      NULL);
271 
272 	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
273 	  {
274 	    char *filename;
275 
276 	    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
277 	    gmdb_sql_load_query(xml, filename);
278 	  }
279 
280 	gtk_widget_destroy (dialog);
281 
282 }
283 static void
gmdb_sql_copy_cb(GtkWidget * w,GtkBuilder * xml)284 gmdb_sql_copy_cb(GtkWidget *w, GtkBuilder *xml)
285 {
286 	GtkTextBuffer *txtbuffer;
287 	GtkClipboard *clipboard;
288 	GtkWidget *textview;
289 
290 	textview = GTK_WIDGET(gtk_builder_get_object(xml, "sql_textview"));
291 	clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
292 	txtbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
293 	gtk_text_buffer_copy_clipboard(txtbuffer, clipboard);
294 }
295 static void
gmdb_sql_cut_cb(GtkWidget * w,GtkBuilder * xml)296 gmdb_sql_cut_cb(GtkWidget *w, GtkBuilder *xml)
297 {
298 	GtkTextBuffer *txtbuffer;
299 	GtkClipboard *clipboard;
300 	GtkWidget *textview;
301 
302 	textview = GTK_WIDGET(gtk_builder_get_object(xml, "sql_textview"));
303 	clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
304 	txtbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
305 	gtk_text_buffer_cut_clipboard(txtbuffer, clipboard, TRUE);
306 }
307 static void
gmdb_sql_paste_cb(GtkWidget * w,GtkBuilder * xml)308 gmdb_sql_paste_cb(GtkWidget *w, GtkBuilder *xml)
309 {
310 	GtkTextBuffer *txtbuffer;
311 	GtkClipboard *clipboard;
312 	GtkWidget *textview;
313 
314 	textview = GTK_WIDGET(gtk_builder_get_object(xml, "sql_textview"));
315 	clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
316 	txtbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
317 	gtk_text_buffer_paste_clipboard(txtbuffer, clipboard, NULL, TRUE);
318 }
319 static void
gmdb_sql_close_cb(GtkWidget * w,GtkBuilder * xml)320 gmdb_sql_close_cb(GtkWidget *w, GtkBuilder *xml)
321 {
322 	GtkWidget *win;
323 	sql_list = g_list_remove(sql_list, xml);
324 	win = GTK_WIDGET(gtk_builder_get_object (xml, "sql_window"));
325 	if (win) gtk_widget_destroy(win);
326 }
327 
328 static void
gmdb_sql_dnd_dataget_cb(GtkWidget * w,GdkDragContext * dc,GtkSelectionData * selection_data,guint info,guint t,GtkBuilder * xml)329 gmdb_sql_dnd_dataget_cb(
330     GtkWidget *w, GdkDragContext *dc,
331     GtkSelectionData *selection_data, guint info, guint t,
332     GtkBuilder *xml)
333 {
334 gchar tablename[256];
335 //gchar *tablename = "Orders";
336 gchar *name;
337 GtkTreeSelection *select;
338 GtkTreeStore *store;
339 GtkTreeView *tree;
340 GtkTreeIter iter2;
341 
342 	tree = GTK_TREE_VIEW(gtk_builder_get_object(xml, "sql_treeview"));
343 	select = gtk_tree_view_get_selection(GTK_TREE_VIEW (tree));
344 	store = GTK_TREE_STORE(gtk_tree_view_get_model(tree));
345 	gtk_tree_selection_get_selected (select, NULL, &iter2);
346 	gtk_tree_model_get (GTK_TREE_MODEL(store), &iter2, 0, &name, -1);
347 
348 	snprintf(tablename, sizeof(tablename), "%s", name);
349 	g_free(name);
350 	//strcpy(tablename, "Shippers");
351 	gtk_selection_data_set(
352 		selection_data,
353 		GDK_SELECTION_TYPE_STRING,
354 		8,  /* 8 bits per character. */
355 		(guchar*)tablename, strlen(tablename));
356 }
gmdb_sql_dnd_datareceived_cb(GtkWidget * w,GdkDragContext * dc,gint x,gint y,GtkSelectionData * selection_data,guint info,guint t,GtkBuilder * xml)357 static void gmdb_sql_dnd_datareceived_cb(
358         GtkWidget *w,
359         GdkDragContext *dc,
360         gint x, gint y,
361         GtkSelectionData *selection_data,
362         guint info, guint t,
363         GtkBuilder *xml)
364 {
365 GtkTextIter iter;
366 GtkTextBuffer *txtbuffer;
367 GtkWidget *textview;
368 
369 	textview = GTK_WIDGET(gtk_builder_get_object(xml, "sql_textview"));
370 	txtbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
371 	if (gtk_text_buffer_get_char_count(txtbuffer)==0) {
372 		gtk_text_buffer_get_iter_at_offset (txtbuffer, &iter, 0);
373 		gtk_text_buffer_insert(txtbuffer, &iter, "select * from ", 14);
374 	}
375 	gtk_widget_grab_focus(GTK_WIDGET(textview));
376 }
377 
378 static void
gmdb_sql_select_hist_cb(GtkComboBoxText * combobox,GtkBuilder * xml)379 gmdb_sql_select_hist_cb(GtkComboBoxText *combobox, GtkBuilder *xml)
380 {
381 	gchar *buf;
382 	GtkTextBuffer *txtbuffer;
383 	GtkWidget *textview;
384 
385 	buf = gtk_combo_box_text_get_active_text(combobox);
386 	if (!buf) return;
387 	textview = GTK_WIDGET(gtk_builder_get_object(xml, "sql_textview"));
388 	txtbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
389 	gtk_text_buffer_set_text(txtbuffer, buf, strlen(buf));
390 }
391 
392 static void
gmdb_sql_execute_cb(GtkWidget * w,GtkBuilder * xml)393 gmdb_sql_execute_cb(GtkWidget *w, GtkBuilder *xml)
394 {
395 	guint len;
396 	gchar *buf;
397 	gchar *bound_data[256];
398 	int i;
399 	MdbSQLColumn *sqlcol;
400 	GtkTextBuffer *txtbuffer;
401 	GtkTextIter start, end;
402 	GtkWidget *textview, *combobox, *treeview;
403 	GtkTreeModel *store;
404 	/*GtkWidget *window;*/
405 	GType *gtypes;
406 	GtkTreeIter iter;
407 	GtkTreeViewColumn *column;
408 	long row, maxrow;
409 	/* GdkCursor *watch, *pointer; */
410 
411 	/*  need to figure out how to clock during the treeview recalc/redraw
412 	window = GTK_WIDGET(gtk_builder_get_object(xml, "sql_window");
413 	watch = gdk_cursor_new(GDK_WATCH);
414 	gdk_window_set_cursor(GTK_WIDGET(window)->window, watch);
415 	gdk_cursor_unref(watch);
416 	*/
417 
418 	/* stuff this query on the history */
419 	textview = GTK_WIDGET(gtk_builder_get_object(xml, "sql_textview"));
420 	combobox = GTK_WIDGET(gtk_builder_get_object(xml, "sql_combo"));
421 	txtbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
422 	len = gtk_text_buffer_get_char_count(txtbuffer);
423 	gtk_text_buffer_get_iter_at_offset (txtbuffer, &start, 0);
424 	gtk_text_buffer_get_iter_at_offset (txtbuffer, &end, len);
425 	buf = gtk_text_buffer_get_text(txtbuffer, &start, &end, FALSE);
426 
427 	/* add to the history */
428 	gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(combobox), buf);
429 	gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), 0);
430 
431 	/* ok now execute it */
432 	mdb_sql_run_query(sql, buf);
433 	if (mdb_sql_has_error(sql)) {
434 		GtkWidget* dlg = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (w)),
435 		    GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE,
436 		    "%s", mdb_sql_last_error(sql));
437 		gtk_dialog_run (GTK_DIALOG (dlg));
438 		gtk_widget_destroy (dlg);
439 		mdb_sql_reset(sql);
440 		return;
441 	}
442 
443 	treeview = GTK_WIDGET(gtk_builder_get_object(xml, "sql_results"));
444 
445 	gtypes = g_malloc(sizeof(GType) * sql->num_columns);
446 	for (i=0;i<sql->num_columns;i++)
447 		gtypes[i]=G_TYPE_STRING;
448 
449 	store = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
450 	if (store) {
451 		while ((column = gtk_tree_view_get_column(GTK_TREE_VIEW(treeview), 0))) {
452 			gtk_tree_view_remove_column(GTK_TREE_VIEW(treeview), column);
453 		}
454 		g_object_unref(store);
455 	}
456 	store = GTK_TREE_MODEL(gtk_list_store_newv(sql->num_columns, gtypes));
457 	g_free(gtypes);
458 
459 	gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), store);
460 
461 	GtkCellRenderer *renderer;
462 	renderer = gtk_cell_renderer_text_new();
463 
464 	for (i=0;i<sql->num_columns;i++) {
465 		bound_data[i] = (char *) g_malloc0(MDB_BIND_SIZE);
466         	mdb_sql_bind_column(sql, i+1, bound_data[i], NULL);
467 		sqlcol = g_ptr_array_index(sql->columns,i);
468 		column = gtk_tree_view_column_new_with_attributes(sqlcol->name, renderer, "text", i, NULL);
469 		gtk_tree_view_append_column(GTK_TREE_VIEW (treeview), column);
470 	}
471 
472 	maxrow = gmdb_prefs_get_maxrows();
473 
474 	row = 0;
475 	while(mdb_fetch_row(sql->cur_table) &&
476 			(!maxrow || (row < maxrow))) {
477 		row++;
478 		gtk_list_store_append(GTK_LIST_STORE(store), &iter);
479 		for (i=0;i<sql->num_columns;i++) {
480 			gtk_list_store_set(GTK_LIST_STORE(store),
481 				&iter, i, (gchar *) bound_data[i], -1);
482 		}
483 	}
484 
485 	/* free the memory used to bind */
486 	for (i=0;i<sql->num_columns;i++) {
487 		g_free(bound_data[i]);
488 	}
489 
490 	mdb_sql_reset(sql);
491 	g_free(buf);
492 
493 	/*
494 	pointer = gdk_cursor_new(GDK_LEFT_PTR);
495 	gdk_window_set_cursor(GTK_WIDGET(window)->window, pointer);
496 	gdk_cursor_unref(pointer);
497 	*/
498 
499 }
500 
501 void
gmdb_sql_new_cb(GtkWidget * w,gpointer data)502 gmdb_sql_new_cb (GtkWidget *w, gpointer data) {
503 	GtkTargetEntry src = { .target = "table", .info = 1 };
504 	GtkWidget *mi, *but, *combobox;
505 	GtkBuilder *sqlwin_xml;
506     GError *error = NULL;
507 
508 	/* load the interface */
509 	sqlwin_xml = gtk_builder_new();
510     if (!gtk_builder_add_from_file(sqlwin_xml, GMDB_UIDIR "gmdb-sql.ui", &error)) {
511         g_warning("Error loading " GMDB_UIDIR "gmdb-sql.ui: %s", error->message);
512         g_error_free(error);
513     }
514 	/* connect the signals in the interface */
515 	gtk_builder_connect_signals(sqlwin_xml, NULL);
516 
517 	sql_list = g_list_append(sql_list, sqlwin_xml);
518 
519 	mi = GTK_WIDGET(gtk_builder_get_object (sqlwin_xml, "save_menu"));
520 	g_signal_connect (G_OBJECT (mi), "activate",
521 		G_CALLBACK (gmdb_sql_save_cb), sqlwin_xml);
522 
523 	but = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "save_button"));
524 	g_signal_connect (G_OBJECT (but), "clicked",
525 		G_CALLBACK (gmdb_sql_save_cb), sqlwin_xml);
526 
527 	mi = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "save_as_menu"));
528 	g_signal_connect (G_OBJECT (mi), "activate",
529 		G_CALLBACK (gmdb_sql_save_as_cb), sqlwin_xml);
530 
531 	//but = GTK_WIDGET(gtk_builder_get_object (sqlwin_xml, "save_as_button");
532 	//g_signal_connect (G_OBJECT (but), "clicked",
533 	//	G_CALLBACK (gmdb_sql_save_as_cb), sqlwin_xml);
534 
535 	mi = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "results_menu"));
536 	g_signal_connect (G_OBJECT (mi), "activate",
537 		G_CALLBACK (gmdb_sql_results_cb), sqlwin_xml);
538 
539 	but = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "results_button"));
540 	g_signal_connect (G_OBJECT (but), "clicked",
541 		G_CALLBACK (gmdb_sql_results_cb), sqlwin_xml);
542 
543 	mi = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "open_menu"));
544 	g_signal_connect (G_OBJECT (mi), "activate",
545 		G_CALLBACK (gmdb_sql_open_cb), sqlwin_xml);
546 
547 	but = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "open_button"));
548 	g_signal_connect (G_OBJECT (but), "clicked",
549 		G_CALLBACK (gmdb_sql_open_cb), sqlwin_xml);
550 
551 	mi = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "paste_menu"));
552 	g_signal_connect (G_OBJECT (mi), "activate",
553 		G_CALLBACK (gmdb_sql_paste_cb), sqlwin_xml);
554 
555 	mi = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "cut_menu"));
556 	g_signal_connect (G_OBJECT (mi), "activate",
557 		G_CALLBACK (gmdb_sql_cut_cb), sqlwin_xml);
558 
559 	mi = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "copy_menu"));
560 	g_signal_connect (G_OBJECT (mi), "activate",
561 		G_CALLBACK (gmdb_sql_copy_cb), sqlwin_xml);
562 
563 	mi = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "close_menu"));
564 	g_signal_connect (G_OBJECT (mi), "activate",
565 		G_CALLBACK (gmdb_sql_close_cb), sqlwin_xml);
566 
567 	but = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "close_button"));
568 	g_signal_connect (G_OBJECT (but), "clicked",
569 		G_CALLBACK (gmdb_sql_close_cb), sqlwin_xml);
570 
571 	mi = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "execute_menu"));
572 	g_signal_connect (G_OBJECT (mi), "activate",
573 		G_CALLBACK (gmdb_sql_execute_cb), sqlwin_xml);
574 
575 	combobox = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "sql_combo"));
576 	g_signal_connect (G_OBJECT(GTK_COMBO_BOX_TEXT(combobox)), "changed",
577 		G_CALLBACK (gmdb_sql_select_hist_cb), sqlwin_xml);
578 
579 	but = GTK_WIDGET(gtk_builder_get_object (sqlwin_xml, "execute_button"));
580 	g_signal_connect (G_OBJECT (but), "clicked",
581 		G_CALLBACK (gmdb_sql_execute_cb), sqlwin_xml);
582 
583 	/* set up treeview, libglade only gives us the empty widget */
584 	GtkWidget *tree = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "sql_treeview"));
585 	GtkTreeStore *store = gtk_tree_store_new(1, G_TYPE_STRING);
586 	gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store));
587 
588 	GtkCellRenderer *renderer;
589 	GtkTreeViewColumn *column;
590 	renderer = gtk_cell_renderer_text_new();
591 	column = gtk_tree_view_column_new_with_attributes("Name",
592 		renderer, "text", 0, NULL);
593 	gtk_tree_view_append_column(GTK_TREE_VIEW (tree), column);
594 
595 	GtkTreeSelection *select =
596 		gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
597 	gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
598 	//g_signal_connect (G_OBJECT (select), "changed",
599 		//G_CALLBACK (gmdb_sql_select_cb), sqlwin_xml);
600 
601 	/* populate first level of tree */
602 	gmdb_sql_tree_populate(mdb, sqlwin_xml);
603 
604 	GtkWidget *textview = GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "sql_textview"));
605 	gtk_drag_source_set( tree, GDK_BUTTON1_MASK, &src, 1, GDK_ACTION_COPY);
606 	gtk_drag_dest_set( textview,
607 		//GTK_DEST_DEFAULT_MOTION |
608 		GTK_DEST_DEFAULT_HIGHLIGHT ,
609 		// GTK_DEST_DEFAULT_DROP,
610 		&src, 1, GDK_ACTION_COPY | GDK_ACTION_MOVE);
611 	g_signal_connect(tree, "drag_data_get",
612 		G_CALLBACK(gmdb_sql_dnd_dataget_cb), sqlwin_xml);
613 	g_signal_connect(textview, "drag_data_received",
614 		G_CALLBACK(gmdb_sql_dnd_datareceived_cb), sqlwin_xml);
615 
616 	//GValue value = {0, };
617 	//but =  GTK_WIDGET(gtk_builder_get_object(sqlwin_xml, "results_button"));
618 	//g_value_init(&value, G_TYPE_STRING);
619 	//g_value_set_static_string(&value, GMDB_ICONDIR "stock_export.png");
620 	//g_object_set_property(G_OBJECT (but), "file" , &value);
621 	//g_value_unset (&value);
622 
623 	gtk_widget_grab_focus(GTK_WIDGET(textview));
624 }
625 
626 /* functions */
627 static gchar *
gmdb_sql_get_basename(char * file_path)628 gmdb_sql_get_basename(char *file_path)
629 {
630 	int i, len;
631 	gchar *basename;
632 
633 	for (i=strlen(file_path);i>=0 && file_path[i]!='/';i--);
634 	len = strlen(file_path) - i + 2;
635 	basename = g_malloc(len);
636 	if (file_path[i]=='/') {
637 		strncpy(basename,&file_path[i+1],len);
638 	} else {
639 		strncpy(basename,file_path,len);
640 	}
641         basename[len]='\0';
642 
643 	return basename;
644 }
645 
646 static void
gmdb_sql_set_file(GtkBuilder * xml,gchar * file_name)647 gmdb_sql_set_file(GtkBuilder *xml, gchar *file_name)
648 {
649 	GtkWidget *window, *textview;
650 	gchar *title;
651 	gchar *basename;
652 	gchar *suffix = " - MDB Query Tool";
653 
654 	basename = gmdb_sql_get_basename(file_name);
655 	title = g_malloc(strlen(basename) + strlen(suffix) + 1);
656 	sprintf(title,"%s%s", basename, suffix);
657 	g_free(basename);
658 	window = GTK_WIDGET(gtk_builder_get_object(xml, "sql_window"));
659 	gtk_window_set_title(GTK_WINDOW(window), title);
660 	g_free(title);
661 	textview = GTK_WIDGET(gtk_builder_get_object(xml, "sql_textview"));
662 	g_object_set_data(G_OBJECT(textview), "file_name", file_name);
663 }
664 
665 static void
gmdb_sql_save_query(GtkBuilder * xml,gchar * file_path)666 gmdb_sql_save_query (GtkBuilder *xml, gchar *file_path) {
667 	FILE *out;
668 	GtkWidget *textview;
669         GtkTextBuffer *txtbuffer;
670 	GtkTextIter start, end;
671 	gchar *buf;
672 
673 	if (!(out=fopen(file_path, "w"))) {
674 		GtkWidget* dlg = gtk_message_dialog_new (NULL,
675 		    GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE,
676 		    _("Unable to open file."));
677 		gtk_dialog_run (GTK_DIALOG (dlg));
678 		gtk_widget_destroy (dlg);
679 		return;
680 	}
681 	textview = GTK_WIDGET(gtk_builder_get_object(xml, "sql_textview"));
682 	txtbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
683 	gtk_text_buffer_get_start_iter(txtbuffer, &start);
684 	gtk_text_buffer_get_end_iter(txtbuffer, &end);
685 	buf = gtk_text_buffer_get_text(txtbuffer, &start, &end, FALSE);
686 	fprintf(out,"%s\n",buf);
687 	fclose(out);
688 	gmdb_sql_set_file(xml, file_path);
689 }
690 static void
gmdb_sql_load_query(GtkBuilder * xml,gchar * file_path)691 gmdb_sql_load_query(GtkBuilder *xml, gchar *file_path)
692 {
693 	FILE *in;
694 	char buf[256];
695 	GtkWidget *textview;
696         GtkTextBuffer *txtbuffer;
697 	GtkTextIter start, end;
698 
699 	if (!(in=fopen(file_path, "r"))) {
700 		GtkWidget* dlg = gtk_message_dialog_new (NULL,
701 		    GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE,
702 		    _("Unable to open file."));
703 		gtk_dialog_run (GTK_DIALOG (dlg));
704 		gtk_widget_destroy (dlg);
705 		return;
706 	}
707 	textview = GTK_WIDGET(gtk_builder_get_object(xml, "sql_textview"));
708 	txtbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
709 	gtk_text_buffer_get_start_iter(txtbuffer, &start);
710 	gtk_text_buffer_get_end_iter(txtbuffer, &end);
711 	gtk_text_buffer_delete(txtbuffer, &start, &end);
712 	while (fgets(buf, 255, in) && (*buf != '\0')) {
713 		gtk_text_buffer_get_end_iter(txtbuffer, &end);
714 		gtk_text_buffer_insert(txtbuffer, &end, buf, strlen(buf));
715 	}
716 	fclose(in);
717 	gmdb_sql_set_file(xml, file_path);
718 }
719 static void
gmdb_sql_tree_populate(MdbHandle * mdb,GtkBuilder * xml)720 gmdb_sql_tree_populate(MdbHandle *mdb, GtkBuilder *xml)
721 {
722 int   i;
723 MdbCatalogEntry *entry;
724 GtkTreeIter *iter2;
725 
726 	GtkTreeView *tree = GTK_TREE_VIEW(gtk_builder_get_object(xml, "sql_treeview"));
727 	GtkTreeStore *store = GTK_TREE_STORE(gtk_tree_view_get_model(tree));
728 
729 	/* add all user tables in catalog to tab */
730 	for (i=0; i < mdb->num_catalog; i++) {
731 		entry = g_ptr_array_index (mdb->catalog, i);
732 		if (mdb_is_user_table(entry)) {
733 			iter2 = g_malloc(sizeof(GtkTreeIter));
734 			gtk_tree_store_append(store, iter2, NULL);
735 			gtk_tree_store_set(store, iter2, 0, entry->object_name, -1);
736 		}
737 	} /* for */
738 }
739 #else
740 
741 void
gmdb_sql_new_cb(GtkWidget * w,gpointer data)742 gmdb_sql_new_cb (GtkWidget *w, gpointer data) {
743 	GtkWidget* dlg = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (w)),
744 	    GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
745 	    _("SQL support was not built.\nMake sure flex and yacc are installed at build time."));
746 	gtk_dialog_run (GTK_DIALOG (dlg));
747 	gtk_widget_destroy (dlg);
748 }
749 
750 #endif
751