1 /*
2  * Copyright (C) 2009 - 2011 Vivien Malerba <malerba@gnome-db.org>
3  * Copyright (C) 2010 David King <davidk@openismus.com>
4  * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 
21 #include <glib/gi18n-lib.h>
22 #include <string.h>
23 #include <gtk/gtk.h>
24 #include <libgda-ui/libgda-ui.h>
25 #include <libgda/binreloc/gda-binreloc.h>
26 #include "dsn-config.h"
27 #include "provider-config.h"
28 #include "gdaui-dsn-assistant.h"
29 
30 GtkApplication *app;
31 GtkWindow *main_window;
32 GtkActionGroup *actions;
33 
34 #define DSN_PAGE      "DSN_Page"
35 #define PROVIDER_PAGE "Provider_Page"
36 static GtkWidget *create_main_notebook (void);
37 
38 static void
show_error(GtkWindow * parent,const gchar * format,...)39 show_error (GtkWindow *parent, const gchar *format, ...)
40 {
41         va_list args;
42         gchar sz[2048];
43         GtkWidget *dialog;
44 
45         /* build the message string */
46         va_start (args, format);
47         vsnprintf (sz, sizeof sz, format, args);
48         va_end (args);
49 
50         /* create the error message dialog */
51 	gchar *str;
52 	str = g_strconcat ("<span weight=\"bold\">",
53                            _("Error:"),
54                            "</span>\n",
55                            sz,
56                            NULL);
57 
58 	dialog = gtk_message_dialog_new_with_markup (parent,
59                                                      GTK_DIALOG_DESTROY_WITH_PARENT |
60                                                      GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
61                                                      GTK_BUTTONS_CLOSE, "%s", str);
62         gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
63                                       gtk_button_new_from_stock (GTK_STOCK_OK),
64                                       GTK_RESPONSE_OK);
65         gtk_widget_show_all (dialog);
66         gtk_dialog_run (GTK_DIALOG (dialog));
67         gtk_widget_destroy (dialog);
68 }
69 
70 static void
assistant_finished_cb(GdauiDsnAssistant * assistant,gboolean error,G_GNUC_UNUSED gpointer user_data)71 assistant_finished_cb (GdauiDsnAssistant *assistant, gboolean error, G_GNUC_UNUSED gpointer user_data)
72 {
73 	const GdaDsnInfo *dsn_info;
74 
75 	if (!error) {
76 		dsn_info = gdaui_dsn_assistant_get_dsn (assistant);
77 		if (dsn_info) {
78 			if (! gda_config_define_dsn (dsn_info, NULL))
79 				show_error (NULL, _("Could not declare new data source"));
80 		}
81 		else
82 			show_error (NULL, _("No valid data source info was created"));
83 	}
84 }
85 
86 static void
assistant_closed_cb(GdauiDsnAssistant * assistant,G_GNUC_UNUSED gpointer user_data)87 assistant_closed_cb (GdauiDsnAssistant *assistant, G_GNUC_UNUSED gpointer user_data)
88 {
89 	gtk_widget_destroy (GTK_WIDGET (assistant));
90 }
91 
92 static void
file_new_cb(G_GNUC_UNUSED GtkAction * action,G_GNUC_UNUSED gpointer user_data)93 file_new_cb (G_GNUC_UNUSED GtkAction *action, G_GNUC_UNUSED gpointer user_data)
94 {
95 	GtkWidget *assistant;
96 
97 	assistant = gdaui_dsn_assistant_new ();
98 	g_signal_connect (G_OBJECT (assistant), "finished",
99 			  G_CALLBACK (assistant_finished_cb), NULL);
100 	g_signal_connect (G_OBJECT (assistant), "close",
101 			  G_CALLBACK (assistant_closed_cb), NULL);
102 	gtk_widget_show (assistant);
103 }
104 
105 static void
file_properties_cb(G_GNUC_UNUSED GtkAction * action,gpointer user_data)106 file_properties_cb (G_GNUC_UNUSED GtkAction *action, gpointer user_data)
107 {
108 	GtkWidget *nb = GTK_WIDGET (user_data);
109 	GtkWidget *dsn, *provider, *current_widget;
110 	gint current;
111 
112 	dsn = g_object_get_data (G_OBJECT (nb), DSN_PAGE);
113 	provider = g_object_get_data (G_OBJECT (nb), PROVIDER_PAGE);
114 
115 	current = gtk_notebook_get_current_page (GTK_NOTEBOOK (nb));
116 	if (current == -1)
117 		return;
118 
119 	current_widget = gtk_notebook_get_nth_page (GTK_NOTEBOOK (nb), current);
120 	if (current_widget == dsn)
121 		dsn_config_edit_properties (dsn);
122 }
123 
124 static void
file_delete_cb(G_GNUC_UNUSED GtkAction * action,gpointer user_data)125 file_delete_cb (G_GNUC_UNUSED GtkAction *action, gpointer user_data)
126 {
127 	GtkWidget *nb = GTK_WIDGET (user_data);
128 	GtkWidget *dsn, *provider, *current_widget;
129 	gint current;
130 
131 	dsn = g_object_get_data (G_OBJECT (nb), DSN_PAGE);
132 	provider = g_object_get_data (G_OBJECT (nb), PROVIDER_PAGE);
133 
134 	current = gtk_notebook_get_current_page (GTK_NOTEBOOK (nb));
135 	if (current == -1)
136 		return;
137 
138 	current_widget = gtk_notebook_get_nth_page (GTK_NOTEBOOK (nb), current);
139 	if (current_widget == dsn)
140 		dsn_config_delete (dsn);
141 }
142 
143 static void
window_closed_cb(G_GNUC_UNUSED GtkAction * action,G_GNUC_UNUSED gpointer user_data)144 window_closed_cb (G_GNUC_UNUSED GtkAction *action, G_GNUC_UNUSED gpointer user_data)
145 {
146 	g_application_quit (G_APPLICATION (app));
147 }
148 
149 static void
about_cb(G_GNUC_UNUSED GtkAction * action,G_GNUC_UNUSED gpointer user_data)150 about_cb (G_GNUC_UNUSED GtkAction *action, G_GNUC_UNUSED gpointer user_data)
151 {
152 	GdkPixbuf *icon;
153 	GtkWidget *dialog;
154 	const gchar *authors[] = {
155 		"Vivien Malerba <malerba@gnome-db.org> (current maintainer)",
156 		"Rodrigo Moya <rodrigo@gnome-db.org>",
157 		"Carlos Perello Marin <carlos@gnome-db.org>",
158 		"Gonzalo Paniagua Javier <gonzalo@gnome-db.org>",
159 		"Laurent Sansonetti <lrz@gnome.org>",
160 		"Daniel Espinosa <esodan@gmail.com>",
161 		NULL
162 	};
163 	const gchar *documenters[] = {
164 		"Rodrigo Moya <rodrigo@gnome-db.org>",
165 		NULL
166 	};
167 	const gchar *translator_credits =
168 		"Christian Rose <menthos@menthos.com> Swedish translations\n" \
169 		"Kjartan Maraas <kmaraas@online.no> Norwegian translation\n";
170 
171 	gchar *path;
172 	path = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, "pixmaps", "gda-control-center.png", NULL);
173 	icon = gdk_pixbuf_new_from_file (path, NULL);
174 	g_free (path);
175 
176 	dialog = gtk_about_dialog_new ();
177 	gtk_about_dialog_set_program_name (GTK_ABOUT_DIALOG (dialog), _("Database access control center"));
178 	gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (dialog), PACKAGE_VERSION);
179 	gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG (dialog), "(C) 1998 - 2011 GNOME Foundation");
180 	gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG (dialog), _("Database access services for the GNOME Desktop"));
181 	gtk_about_dialog_set_license (GTK_ABOUT_DIALOG (dialog), "GNU Lesser General Public License");
182 	gtk_about_dialog_set_website (GTK_ABOUT_DIALOG (dialog), "http://www.gnome-db.org");
183 	gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG (dialog), authors);
184 	gtk_about_dialog_set_documenters (GTK_ABOUT_DIALOG (dialog), documenters);
185 	gtk_about_dialog_set_translator_credits (GTK_ABOUT_DIALOG (dialog), translator_credits);
186 	gtk_about_dialog_set_logo (GTK_ABOUT_DIALOG (dialog), icon);
187 	g_signal_connect (G_OBJECT (dialog), "response",
188 			  G_CALLBACK (gtk_widget_destroy),
189 			  dialog);
190 	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window));
191 	gtk_widget_show (dialog);
192 
193 }
194 
195 static GtkActionEntry ui_actions[] = {
196 	{ "Database", NULL, N_("_Data source"), NULL, N_("Database"), NULL },
197 	{ "DatabaseClose", GTK_STOCK_CLOSE, N_("_Close"), NULL, N_("Close this window"), G_CALLBACK (window_closed_cb) },
198 	{ "DatabaseNew", GTK_STOCK_NEW, N_("_New datasource"), NULL, N_("Create new data source"), G_CALLBACK (file_new_cb) },
199 	{ "DatabaseDelete", GTK_STOCK_DELETE, N_("_Delete datasource"), NULL, N_("Delete selected data source"), G_CALLBACK (file_delete_cb) },
200 	{ "DatabaseProperties", GTK_STOCK_PROPERTIES, N_("_Properties"), NULL, N_("Edit properties for selected data source"), G_CALLBACK (file_properties_cb) },
201 	{ "About", NULL, N_("_About"), NULL, N_("About"), NULL },
202 	{ "HelpAbout", GTK_STOCK_ABOUT, N_("_About"), NULL, N_("About GNOME-DB"), G_CALLBACK (about_cb) }
203 };
204 
205 static const gchar *ui_actions_info =
206         "<ui>"
207 	"  <menubar name='MenuBar'>"
208 	"    <menu name='Database' action='Database'>"
209 	"      <menuitem name='DatabaseNew' action= 'DatabaseNew'/>"
210 	"      <menuitem name='DatabaseProperties' action= 'DatabaseProperties'/>"
211 	"      <menuitem name='DatabaseDelete' action= 'DatabaseDelete'/>"
212 	"      <separator/>"
213 	"      <menuitem name='DatabaseClose' action= 'DatabaseClose'/>"
214 	"    </menu>"
215 	"    <menu name='About' action='About'>"
216 	"      <menuitem name='HelpAbout' action= 'HelpAbout'/>"
217 	"    </menu>"
218 	"  </menubar>"
219         "  <toolbar  name='ToolBar'>"
220         "    <toolitem action='DatabaseNew'/>"
221         "    <toolitem action='DatabaseProperties'/>"
222         "    <toolitem action='DatabaseDelete'/>"
223         "  </toolbar>"
224         "</ui>";
225 
226 static void
prepare_menu(GtkBox * vbox,GtkWidget * nb)227 prepare_menu (GtkBox *vbox, GtkWidget *nb)
228 {
229         GtkWidget *menubar;
230 	GtkWidget *toolbar;
231 	GtkUIManager *ui;
232 
233         actions = gtk_action_group_new ("Actions");
234 	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
235         gtk_action_group_add_actions (actions, ui_actions, G_N_ELEMENTS (ui_actions), nb);
236 
237         ui = gtk_ui_manager_new ();
238         gtk_ui_manager_insert_action_group (ui, actions, 0);
239         gtk_ui_manager_add_ui_from_string (ui, ui_actions_info, -1, NULL);
240 
241         menubar = gtk_ui_manager_get_widget (ui, "/MenuBar");
242         gtk_box_pack_start (vbox, menubar, FALSE, FALSE, 0);
243 	gtk_widget_show (menubar);
244 
245 	toolbar = gtk_ui_manager_get_widget (ui, "/ToolBar");
246         gtk_box_pack_start (vbox, toolbar, FALSE, FALSE, 0);
247 	gtk_widget_show (toolbar);
248 
249 	GtkAction *action;
250 	action = gtk_action_group_get_action (actions, "DatabaseProperties");
251 	g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
252 	action = gtk_action_group_get_action (actions, "DatabaseDelete");
253 	g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
254 }
255 
256 
257 static GtkWidget *
create_main_window(void)258 create_main_window (void)
259 {
260 	GtkWidget *window, *vbox;
261 	GtkWidget *nb;
262 	GdkPixbuf *icon;
263 
264 	/* create the main window */
265 	window = gtk_application_window_new (app);
266 	main_window = GTK_WINDOW (window);
267 	gtk_window_set_title (GTK_WINDOW (window), _("Database access control center"));
268 	gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
269 	gtk_window_set_default_size (GTK_WINDOW (window), 650, 600);
270 	g_signal_connect (G_OBJECT (window), "destroy",
271 			  G_CALLBACK (window_closed_cb), NULL);
272 
273 	/* icon */
274 	gchar *path;
275 	path = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, "pixmaps", "gda-control-center.png", NULL);
276 	icon = gdk_pixbuf_new_from_file (path, NULL);
277 	g_free (path);
278 	if (icon) {
279 		gtk_window_set_icon (GTK_WINDOW (window), icon);
280 		g_object_unref (icon);
281 	}
282 
283 	/* menu and contents */
284 	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
285 	gtk_container_add (GTK_CONTAINER (window), vbox);
286 	gtk_widget_show (vbox);
287 
288 	nb = create_main_notebook ();
289 	prepare_menu (GTK_BOX (vbox), nb);
290 
291         gtk_container_set_border_width (GTK_CONTAINER (nb), 6);
292 	gtk_box_pack_start (GTK_BOX (vbox), nb, TRUE, TRUE, 0);
293 	gtk_widget_show (nb);
294 
295 	gtk_widget_show (window);
296 	return window;
297 }
298 
299 static void
activate(GtkApplication * app)300 activate (GtkApplication *app)
301 {
302 	static GtkWidget *window = NULL;
303 
304 	if (! window) {
305 		gdaui_init ();
306 		window = create_main_window ();
307 		gtk_window_set_application (GTK_WINDOW (window), app);
308 		gtk_widget_show (window);
309 	}
310 }
311 
312 int
main(int argc,char * argv[])313 main (int argc, char *argv[])
314 {
315 	gint status;
316 
317 	app = gtk_application_new ("org.GnomeDb.GdaBrowser", G_APPLICATION_FLAGS_NONE);
318 	g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
319 
320 	status = g_application_run (G_APPLICATION (app), argc, argv);
321 
322 	g_object_unref (app);
323 
324 	return status;
325 }
326 
327 static void
dsn_selection_changed_cb(GdauiRawGrid * dbrawgrid,G_GNUC_UNUSED gboolean row_selected,G_GNUC_UNUSED gpointer data)328 dsn_selection_changed_cb (GdauiRawGrid *dbrawgrid, G_GNUC_UNUSED gboolean row_selected, G_GNUC_UNUSED gpointer data)
329 {
330 	GtkAction *action;
331 	GArray *selection;
332 
333 	selection = gdaui_data_selector_get_selected_rows (GDAUI_DATA_SELECTOR (dbrawgrid));
334 
335 	action = gtk_action_group_get_action (actions, "DatabaseProperties");
336 	g_object_set (G_OBJECT (action), "sensitive", selection ? TRUE : FALSE, NULL);
337 
338 	action = gtk_action_group_get_action (actions, "DatabaseDelete");
339 	g_object_set (G_OBJECT (action), "sensitive", selection ? TRUE : FALSE, NULL);
340 	if (selection)
341 		g_array_free (selection, TRUE);
342 }
343 
344 static void
main_nb_page_switched_cb(G_GNUC_UNUSED GtkNotebook * notebook,G_GNUC_UNUSED GtkWidget * page,guint page_num,G_GNUC_UNUSED gpointer data)345 main_nb_page_switched_cb (G_GNUC_UNUSED GtkNotebook *notebook, G_GNUC_UNUSED GtkWidget *page, guint page_num, G_GNUC_UNUSED gpointer data)
346 {
347 	gboolean show;
348 	GtkAction *action;
349 
350 	if (!actions)
351 		return;
352 
353 	show = page_num == 0 ? TRUE : FALSE;
354 	action = gtk_action_group_get_action (actions, "DatabaseProperties");
355 	g_object_set (G_OBJECT (action), "visible", show, NULL);
356 	action = gtk_action_group_get_action (actions, "DatabaseDelete");
357 	g_object_set (G_OBJECT (action), "visible", show, NULL);
358 }
359 
360 static GtkWidget *
create_main_notebook(void)361 create_main_notebook (void)
362 {
363 	GtkWidget *nb;
364 	GtkWidget *dsn;
365 	GtkWidget *provider;
366 	GdauiRawGrid *grid;
367 
368 	nb = gtk_notebook_new ();
369         gtk_notebook_set_show_tabs (GTK_NOTEBOOK (nb), TRUE);
370         gtk_notebook_set_scrollable (GTK_NOTEBOOK (nb), TRUE);
371         gtk_notebook_popup_enable (GTK_NOTEBOOK (nb));
372         gtk_widget_show (nb);
373 	g_signal_connect (G_OBJECT (nb), "switch-page",
374 			  G_CALLBACK (main_nb_page_switched_cb), NULL);
375 
376 	/* data source configuration page */
377 	dsn = dsn_config_new ();
378 	g_object_set_data (G_OBJECT (nb), DSN_PAGE, dsn);
379 	gtk_notebook_append_page (GTK_NOTEBOOK (nb), dsn,
380 				  gtk_label_new (_("Data Sources")));
381 
382 	grid = g_object_get_data (G_OBJECT (dsn), "grid");
383 	g_signal_connect (G_OBJECT (grid), "selection-changed",
384 			  G_CALLBACK (dsn_selection_changed_cb), NULL);
385 
386 	/* providers configuration page */
387 	provider = provider_config_new ();
388 	g_object_set_data (G_OBJECT (nb), PROVIDER_PAGE, provider);
389 	gtk_notebook_append_page (GTK_NOTEBOOK (nb), provider,
390 				  gtk_label_new (_("Providers")));
391 
392 	return nb;
393 }
394