Version bump (2.5-2)
[ukeyboard.git] / ukbdcreator / ukbdcreator.c
blob083252c15306f7a1d020a73feef5732ceee1b2dd
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;
235 update_app_title();
239 static gboolean file_ask_save(void)
241 GtkWidget *note;
242 gint res;
244 if (!is_modified)
245 return TRUE;
246 note = hildon_note_new_confirmation_add_buttons(GTK_WINDOW(window_main),
247 "Save the file before closing?", "Yes", 1, "No", 2, "Cancel", 0, NULL);
248 res = gtk_dialog_run(GTK_DIALOG(note));
249 gtk_widget_destroy(note);
250 if (res == 1) {
251 file_save_as();
252 return !is_modified;
254 if (res == 2)
255 return TRUE;
256 return FALSE;
259 static void file_open(void)
261 gchar *fname;
263 if (!file_ask_save())
264 return;
265 fname = file_chooser(TRUE);
266 if (fname) {
267 if (read_file(fname)) {
268 set_filename(fname);
269 is_modified = FALSE;
270 update_app_title();
271 g_free(last_error_msg);
272 last_error_msg = NULL;
273 } else
274 g_free(fname);
278 static void file_new(void)
280 if (!file_ask_save())
281 return;
283 if (!read_file("/usr/share/ukbdcreator/template.def"))
284 gtk_text_buffer_set_text(buffer, "", -1);
286 set_filename(NULL);
287 is_modified = FALSE;
288 update_app_title();
289 g_free(last_error_msg);
290 last_error_msg = NULL;
293 static gboolean file_quit(void)
295 if (!file_ask_save())
296 return TRUE;
297 restore_layout(conf, FALSE);
298 gtk_main_quit();
299 return FALSE;
302 static void run_about(void)
304 gtk_show_about_dialog(GTK_WINDOW(window_main),
305 "version", UKBD_VERSION,
306 "comments", "Licensed under GPLv2. Please send bug reports and feature requests to roman.moravcik@gmail.com.",
307 "copyright", "(c) 2008 Jiri Benc\n(c) 2009 Roman Moravcik",
308 "website", "http://upir.cz/maemo/keyboards/",
309 NULL);
312 static void run_help(void)
314 osso_rpc_run(osso_context,
315 "com.nokia.osso_browser",
316 "/com/nokia/osso_browser",
317 "com.nokia.osso_browser",
318 "open_new_window",
319 NULL,
320 DBUS_TYPE_STRING, "/usr/share/ukbdcreator/howto.txt",
321 DBUS_TYPE_INVALID);
324 static gboolean compile_and_test(void)
326 gchar *buf, *fname, *lang;
327 gboolean res;
329 buf = get_buffer();
330 res = compile_layout(buf, &fname, &lang);
331 g_free(buf);
332 if (res) {
333 res = test_layout(conf, fname, lang);
334 g_free(fname);
335 g_free(lang);
336 if (res)
337 return TRUE;
338 else
339 return FALSE;
340 } else {
341 return FALSE;
345 static gboolean untest(void)
347 return restore_layout(conf, TRUE);
350 static void toggle_activate(GtkToggleToolButton *toggle_tool_button, gpointer data)
352 (void)data;
354 if (!gtk_toggle_tool_button_get_active(toggle_tool_button)) {
355 untest();
356 } else {
357 compile_and_test();
361 static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event)
363 (void)widget;
364 switch (event->keyval) {
365 case GDK_F6:
366 toggle_fullscreen();
367 return TRUE;
369 return FALSE;
372 static GtkWidget *main_layout(void)
374 GtkWidget *pannable;
376 view = HILDON_TEXT_VIEW(hildon_text_view_new());
378 pannable = hildon_pannable_area_new();
379 gtk_container_add(GTK_CONTAINER(pannable), GTK_WIDGET(view));
381 buffer = hildon_text_view_get_buffer(view);
382 g_signal_connect(G_OBJECT(buffer), "changed", G_CALLBACK(set_modified), NULL);
383 g_signal_connect(G_OBJECT(buffer), "modified-changed", G_CALLBACK(set_modified), NULL);
385 file_new();
387 return pannable;
390 static GtkWidget *main_menu(void)
392 GtkWidget *menu, *item;
394 menu = hildon_app_menu_new();
396 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
397 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "New", NULL);
398 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(file_new), NULL);
399 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
401 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
402 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Open", NULL);
403 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(file_open), NULL);
404 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
406 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
407 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Save", NULL);
408 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(file_save), NULL);
409 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
411 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
412 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Save as...", NULL);
413 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(file_save_as), NULL);
414 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
416 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
417 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Activate layout", NULL);
418 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(compile_and_test), NULL);
419 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
421 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
422 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Restore original layout", NULL);
423 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(untest), NULL);
424 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
426 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
427 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Show error", NULL);
428 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(__disp_compile_error), NULL);
429 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
431 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
432 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Help", NULL);
433 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(run_help), NULL);
434 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
436 item = hildon_button_new_with_text (HILDON_SIZE_AUTO,
437 HILDON_BUTTON_ARRANGEMENT_VERTICAL, "About", NULL);
438 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(run_about), NULL);
439 hildon_app_menu_append(HILDON_APP_MENU (menu), GTK_BUTTON(item));
441 gtk_widget_show_all(menu);
442 return menu;
445 static GtkToolbar *main_toolbar(void)
447 GtkToolbar *bar;
448 GtkToolItem *item;
450 bar = GTK_TOOLBAR(gtk_toolbar_new());
451 gtk_toolbar_set_orientation(bar, GTK_ORIENTATION_HORIZONTAL);
452 gtk_toolbar_set_style(bar, GTK_TOOLBAR_BOTH_HORIZ);
454 item = gtk_tool_button_new(NULL, NULL);
455 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), "general_toolbar_folder");
456 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(file_open), NULL);
457 gtk_toolbar_insert(bar, item, -1);
459 item = gtk_tool_button_new(NULL, NULL);
460 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), "notes_save");
461 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(file_save), NULL);
462 gtk_toolbar_insert(bar, item, -1);
464 item = gtk_toggle_tool_button_new();
465 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), "location_applet_on");
466 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(item), FALSE);
467 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(toggle_activate), NULL);
468 gtk_toolbar_insert(bar, item, -1);
470 item = gtk_toggle_tool_button_new();
471 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), "general_fullsize");
472 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(item), FALSE);
473 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(toggle_fullscreen), NULL);
474 gtk_toolbar_insert(bar, item, -1);
476 return bar;
479 int main(int argc, char **argv)
481 HildonProgram *program;
483 hildon_gtk_init(&argc, &argv);
484 program = hildon_program_get_instance();
485 g_set_prgname("ukbdcreator");
486 g_set_application_name("Ukeyboard Creator");
487 osso_context = osso_initialize("cz.upir.ukbdcreator", UKBD_VERSION, TRUE, NULL);
488 gnome_vfs_init();
489 conf = gconf_client_get_default();
490 gconf_client_add_dir(conf, "/apps/osso/inputmethod/hildon-im-languages",
491 GCONF_CLIENT_PRELOAD_NONE, NULL);
493 if (access("/targets/links/scratchbox.config", F_OK) == 0)
494 inside_scratchbox = TRUE;
495 else
496 inside_scratchbox = FALSE;
498 window_main = HILDON_WINDOW(hildon_window_new());
499 hildon_program_add_window(program, window_main);
500 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
501 gtk_clipboard_set_can_store(clipboard, NULL, 0);
503 gtk_container_add(GTK_CONTAINER(window_main), main_layout());
504 hildon_window_set_app_menu(window_main, HILDON_APP_MENU (main_menu()));
505 hildon_window_add_toolbar(window_main, main_toolbar());
506 update_app_title();
508 g_signal_connect(G_OBJECT(window_main), "key_press_event", G_CALLBACK(key_pressed), NULL);
509 g_signal_connect(G_OBJECT(window_main), "delete_event", G_CALLBACK(file_quit), NULL);
511 gtk_widget_show_all(GTK_WIDGET(window_main));
512 gtk_main();
513 return 0;