Version bump (2.3-6)
[ukeyboard.git] / ukbdcreator / ukbdcreator.c
blobfcbf4f417505321258ba5f5a6e1f87bf4256e486
1 /*
2 * Copyright (c) 2008 Jiri Benc <jbenc@upir.cz>
3 * Copyright (c) 2009 Roman Moravcik <roman.moravcik@gmail.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <string.h>
20 #include <glib.h>
21 #include <gtk/gtk.h>
22 #include <hildon/hildon.h>
23 #include <hildon/hildon-file-chooser-dialog.h>
24 #include <libosso.h>
25 #include <libgnomevfs/gnome-vfs.h>
26 #include <gconf/gconf.h>
27 #include <gconf/gconf-client.h>
28 #include "version.h"
29 #include "ukbdcreator.h"
31 gboolean inside_scratchbox;
33 static osso_context_t *osso_context;
34 static HildonWindow *window_main;
35 static GtkClipboard *clipboard;
36 static HildonTextView *view;
37 static GtkTextBuffer *buffer;
38 static gchar *filename = NULL;
39 static gboolean is_fullscreen = FALSE;
40 static gboolean is_modified = FALSE;
42 static int last_error_line = 0;
43 static gchar *last_error_msg = NULL;
45 static GConfClient *conf;
47 static void update_app_title(void)
49 gchar *title = NULL;
50 gchar *basename = NULL;
52 if (filename)
53 basename = g_filename_display_basename(filename);
55 if (is_modified) {
56 title = g_strdup_printf("*%s", basename ? basename : "Ukeyboard Creator");
57 } else {
58 title = g_strdup_printf("%s", basename ? basename : "Ukeyboard Creator");
61 if (title) {
62 gtk_window_set_title(GTK_WINDOW(window_main), title);
63 g_free(title);
66 if (basename)
67 g_free(basename);
70 static void toggle_fullscreen(void)
72 if (is_fullscreen)
73 gtk_window_unfullscreen(GTK_WINDOW(window_main));
74 else
75 gtk_window_fullscreen(GTK_WINDOW(window_main));
76 is_fullscreen = !is_fullscreen;
79 static void set_modified(void)
81 is_modified = TRUE;
82 update_app_title();
85 static void set_filename(gchar *fname)
87 if (filename)
88 g_free(filename);
89 filename = fname;
92 void disp_error(gchar *msg)
94 hildon_banner_show_information(GTK_WIDGET(window_main), GTK_STOCK_DIALOG_ERROR, msg);
97 void disp_info(gchar *msg)
99 hildon_banner_show_information(GTK_WIDGET(window_main), GTK_STOCK_DIALOG_INFO, msg);
102 static void __disp_compile_error(void)
104 GtkTextIter iter;
106 if (!last_error_msg)
107 return;
108 if (last_error_line > 0) {
109 gtk_text_buffer_get_iter_at_line(buffer, &iter, last_error_line - 1);
110 gtk_text_buffer_place_cursor(buffer, &iter);
111 gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(view), gtk_text_buffer_get_mark(buffer, "insert"));
113 hildon_banner_show_information(GTK_WIDGET(window_main), GTK_STOCK_DIALOG_ERROR, last_error_msg);
116 void disp_compile_error(int line, gchar *msg)
118 g_free(last_error_msg);
119 last_error_msg = g_strdup(msg);
120 last_error_line = line;
121 __disp_compile_error();
124 static gboolean read_file(gchar *fname)
126 GnomeVFSFileInfo finfo;
127 GnomeVFSHandle *handle = NULL;
128 GnomeVFSFileSize bytes;
129 gchar *buf;
131 if (gnome_vfs_get_file_info(fname, &finfo, GNOME_VFS_FILE_INFO_DEFAULT) != GNOME_VFS_OK ||
132 gnome_vfs_open(&handle, fname, GNOME_VFS_OPEN_READ) != GNOME_VFS_OK) {
133 disp_error("Error opening file");
134 return FALSE;
136 buf = g_malloc0(finfo.size + 1);
137 if (!buf) {
138 gnome_vfs_close(handle);
139 disp_error("Not enough memory");
140 return FALSE;
142 if (gnome_vfs_read(handle, buf, finfo.size, &bytes) != GNOME_VFS_OK || bytes != finfo.size) {
143 gnome_vfs_close(handle);
144 g_free(buf);
145 disp_error("Error reading file");
146 return FALSE;
148 gnome_vfs_close(handle);
150 gtk_text_buffer_set_text(buffer, buf, -1);
151 g_free(buf);
152 return TRUE;
155 static gchar *get_buffer(void)
157 GtkTextIter start, end;
159 gtk_text_buffer_get_bounds(buffer, &start, &end);
160 return gtk_text_buffer_get_slice(buffer, &start, &end, TRUE);
163 static gboolean write_file(gchar *fname)
165 GnomeVFSHandle *handle = NULL;
166 GnomeVFSFileSize bytes;
167 gchar *buf;
168 size_t size;
170 if (gnome_vfs_create(&handle, fname, GNOME_VFS_OPEN_WRITE, FALSE, 0644) != GNOME_VFS_OK) {
171 disp_error("Error creating file");
172 return FALSE;
174 buf = get_buffer();
175 size = strlen(buf);
176 if (gnome_vfs_write(handle, buf, size, &bytes) != GNOME_VFS_OK || bytes != size) {
177 gnome_vfs_close(handle);
178 g_free(buf);
179 disp_error("Error writing file");
180 return FALSE;
182 gnome_vfs_close(handle);
183 g_free(buf);
184 disp_info("Saved");
185 return TRUE;
188 static gchar *file_chooser(gboolean open)
190 GtkWidget *chooser;
191 GtkFileFilter *filter;
192 gchar *result = NULL;
194 chooser = hildon_file_chooser_dialog_new(GTK_WINDOW(window_main),
195 open ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE);
196 filter = gtk_file_filter_new();
197 gtk_file_filter_add_pattern(filter, "*.def");
198 gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(chooser), filter);
199 gtk_widget_show_all(chooser);
200 if (gtk_dialog_run(GTK_DIALOG(chooser)) == GTK_RESPONSE_OK)
201 result = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser));
202 gtk_widget_destroy(chooser);
203 if (!open && result && !g_str_has_suffix(result, ".def")) {
204 gchar *tmp = result;
206 result = g_strconcat(result, ".def", NULL);
207 g_free(tmp);
209 return result;
212 static void file_save_as(void)
214 gchar *fname;
216 fname = file_chooser(FALSE);
217 if (fname) {
218 if (write_file(fname)) {
219 set_filename(fname);
220 is_modified = FALSE;
221 update_app_title();
222 } else
223 g_free(fname);
227 static void file_save(void)
229 if (!filename) {
230 file_save_as();
231 return;
233 if (write_file(filename))
234 is_modified = FALSE;
237 static gboolean file_ask_save(void)
239 GtkWidget *note;
240 gint res;
242 if (!is_modified)
243 return TRUE;
244 note = hildon_note_new_confirmation_add_buttons(GTK_WINDOW(window_main),
245 "Save the file before closing?", "Yes", 1, "No", 2, "Cancel", 0, NULL);
246 res = gtk_dialog_run(GTK_DIALOG(note));
247 gtk_widget_destroy(note);
248 if (res == 1) {
249 file_save_as();
250 return !is_modified;
252 if (res == 2)
253 return TRUE;
254 return FALSE;
257 static void file_open(void)
259 gchar *fname;
261 if (!file_ask_save())
262 return;
263 fname = file_chooser(TRUE);
264 if (fname) {
265 if (read_file(fname)) {
266 set_filename(fname);
267 is_modified = FALSE;
268 update_app_title();
269 g_free(last_error_msg);
270 last_error_msg = NULL;
271 } else
272 g_free(fname);
276 static void file_new(void)
278 if (!file_ask_save())
279 return;
281 if (!read_file("/usr/share/ukbdcreator/template.def"))
282 gtk_text_buffer_set_text(buffer, "", -1);
284 set_filename(NULL);
285 is_modified = FALSE;
286 update_app_title();
287 g_free(last_error_msg);
288 last_error_msg = NULL;
291 static gboolean file_quit(void)
293 if (!file_ask_save())
294 return TRUE;
295 restore_layout(conf, FALSE);
296 gtk_main_quit();
297 return FALSE;
300 static void run_about(void)
302 gtk_show_about_dialog(GTK_WINDOW(window_main),
303 "version", UKBD_VERSION,
304 "comments", "Licensed under GPLv2. Please send bug reports and feature requests to roman.moravcik@gmail.com.",
305 "copyright", "(c) 2008 Jiri Benc\n(c) 2009 Roman Moravcik",
306 "website", "http://upir.cz/maemo/keyboards/",
307 NULL);
310 static void run_help(void)
312 osso_rpc_run(osso_context,
313 "com.nokia.osso_browser",
314 "/com/nokia/osso_browser",
315 "com.nokia.osso_browser",
316 "open_new_window",
317 NULL,
318 DBUS_TYPE_STRING, "/usr/share/ukbdcreator/howto.txt",
319 DBUS_TYPE_INVALID);
322 static gboolean compile_and_test(void)
324 gchar *buf, *fname, *lang;
325 gboolean res;
327 buf = get_buffer();
328 res = compile_layout(buf, &fname, &lang);
329 g_free(buf);
330 if (res) {
331 res = test_layout(conf, fname, lang);
332 g_free(fname);
333 g_free(lang);
334 if (res)
335 return TRUE;
336 else
337 return FALSE;
338 } else {
339 return FALSE;
343 static gboolean untest(void)
345 return restore_layout(conf, TRUE);
348 static void toggle_activate(GtkToggleToolButton *toggle_tool_button, gpointer data)
350 (void)data;
352 if (!gtk_toggle_tool_button_get_active(toggle_tool_button)) {
353 untest();
354 } else {
355 compile_and_test();
359 static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event)
361 (void)widget;
362 switch (event->keyval) {
363 case GDK_F6:
364 toggle_fullscreen();
365 return TRUE;
367 return FALSE;
370 static GtkWidget *main_layout(void)
372 GtkWidget *pannable;
374 view = HILDON_TEXT_VIEW(hildon_text_view_new());
376 pannable = hildon_pannable_area_new();
377 gtk_container_add(GTK_CONTAINER(pannable), GTK_WIDGET(view));
379 buffer = hildon_text_view_get_buffer(view);
380 g_signal_connect(G_OBJECT(buffer), "changed", G_CALLBACK(set_modified), NULL);
381 g_signal_connect(G_OBJECT(buffer), "modified-changed", G_CALLBACK(set_modified), NULL);
383 file_new();
385 return pannable;
388 static GtkWidget *main_menu(void)
390 GtkWidget *menu, *item;
392 menu = hildon_app_menu_new();
394 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
395 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "New", NULL);
396 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(file_new), NULL);
397 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
399 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
400 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Open", NULL);
401 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(file_open), NULL);
402 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
404 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
405 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Save", NULL);
406 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(file_save), NULL);
407 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
409 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
410 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Save as...", NULL);
411 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(file_save_as), NULL);
412 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
414 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
415 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Activate layout", NULL);
416 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(compile_and_test), NULL);
417 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
419 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
420 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Restore original layout", NULL);
421 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(untest), NULL);
422 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
424 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
425 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Show error", NULL);
426 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(__disp_compile_error), NULL);
427 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
429 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
430 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Help", NULL);
431 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(run_help), NULL);
432 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
434 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
435 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "About", NULL);
436 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(run_about), NULL);
437 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
439 gtk_widget_show_all(menu);
440 return menu;
443 static GtkToolbar *main_toolbar(void)
445 GtkToolbar *bar;
446 GtkToolItem *item;
448 bar = GTK_TOOLBAR(gtk_toolbar_new());
449 gtk_toolbar_set_orientation(bar, GTK_ORIENTATION_HORIZONTAL);
450 gtk_toolbar_set_style(bar, GTK_TOOLBAR_BOTH_HORIZ);
452 item = gtk_tool_button_new(NULL, NULL);
453 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), "general_toolbar_folder");
454 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(file_open), NULL);
455 gtk_toolbar_insert(bar, item, -1);
457 item = gtk_tool_button_new(NULL, NULL);
458 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), "notes_save");
459 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(file_save), NULL);
460 gtk_toolbar_insert(bar, item, -1);
462 item = gtk_toggle_tool_button_new();
463 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), "location_applet_on");
464 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(item), FALSE);
465 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(toggle_activate), NULL);
466 gtk_toolbar_insert(bar, item, -1);
468 item = gtk_toggle_tool_button_new();
469 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), "general_fullsize");
470 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(item), FALSE);
471 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(toggle_fullscreen), NULL);
472 gtk_toolbar_insert(bar, item, -1);
474 return bar;
477 int main(int argc, char **argv)
479 HildonProgram *program;
481 hildon_gtk_init(&argc, &argv);
482 program = hildon_program_get_instance();
483 g_set_prgname("ukbdcreator");
484 g_set_application_name("Ukeyboard Creator");
485 osso_context = osso_initialize("cz.upir.ukbdcreator", UKBD_VERSION, TRUE, NULL);
486 gnome_vfs_init();
487 conf = gconf_client_get_default();
488 gconf_client_add_dir(conf, "/apps/osso/inputmethod/hildon-im-languages",
489 GCONF_CLIENT_PRELOAD_NONE, NULL);
491 if (access("/targets/links/scratchbox.config", F_OK) == 0)
492 inside_scratchbox = TRUE;
493 else
494 inside_scratchbox = FALSE;
496 window_main = HILDON_WINDOW(hildon_window_new());
497 hildon_program_add_window(program, window_main);
498 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
499 gtk_clipboard_set_can_store(clipboard, NULL, 0);
501 gtk_container_add(GTK_CONTAINER(window_main), main_layout());
502 hildon_window_set_app_menu(window_main, HILDON_APP_MENU (main_menu()));
503 hildon_window_add_toolbar(window_main, main_toolbar());
504 update_app_title();
506 g_signal_connect(G_OBJECT(window_main), "key_press_event", G_CALLBACK(key_pressed), NULL);
507 g_signal_connect(G_OBJECT(window_main), "delete_event", G_CALLBACK(file_quit), NULL);
509 gtk_widget_show_all(GTK_WIDGET(window_main));
510 gtk_main();
511 return 0;