Set icon name to NULL instead of empty string
[maepad.git] / src / ui / callbacks.c
blobded59b13ba628129cfeef81a4e97f05b7c35b970
1 /*
2 * This file is part of maemopad+
5 * This software is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; either version 2.1 of
8 * the License, or (at your option) any later version.
10 * This software is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this software; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
22 #include <ui/callbacks.h>
23 #include <ui/interface.h>
24 #include <gtk/gtk.h>
25 #include <gdk/gdkkeysyms.h>
26 #include <libintl.h>
28 #include <glib.h>
31 * strlen needed from string.h
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <config.h>
40 #include <time.h>
42 #include <hildon/hildon.h>
43 #include <hildon/hildon-banner.h>
44 #include <hildon/hildon-note.h>
45 #include <hildon/hildon-font-selection-dialog.h>
46 #include <tablet-browser-interface.h>
48 #include <libgnomevfs/gnome-vfs.h>
50 #include "sketchwidget.h"
52 #include "../he/he-about-dialog.h"
53 #include "../he/he-simple-color-dialog.h"
56 * "Busy" status handling
58 * Use "busy_reset" to reset the busy status (turn off)
59 * Use "busy_enter" when starting time-consuming processing
60 * Use "busy_leave" when processing has been finished
62 typedef enum {
63 BUSY_RESET = 0,
64 BUSY_INCREMENT,
65 BUSY_DECREMENT,
66 } SetBusyType;
68 /* Don't use this directly, but make use of the macros defined below */
69 void set_busy(MainView* mainview, SetBusyType update);
71 #define busy_reset(mainview) set_busy(mainview, BUSY_RESET)
72 #define busy_enter(mainview) set_busy(mainview, BUSY_INCREMENT)
73 #define busy_leave(mainview) set_busy(mainview, BUSY_DECREMENT)
77 * Privates:
79 gboolean read_file_to_buffer(MainView * mainview);
80 void write_buffer_to_file(MainView * mainview);
81 void new_node_dialog(nodeType typ, MainView * mainview);
82 gboolean foreach_func_update_ord (GtkTreeModel *model,GtkTreePath *path,GtkTreeIter *iter, MainView *mainview);
83 void move_nodes_up(GtkTreeModel * model, GtkTreeRowReference * topnode, GtkTreeRowReference * newtop);
84 GtkTreeRowReference *iter2ref(GtkTreeModel * model, GtkTreeIter * iter);
85 gboolean exec_command_on_db(MainView *mainview,char sql_string[]);
86 int get_node_id_on_tmp_db(GtkTreeModel *model,GtkTreeIter *iter);
87 gint get_branch_node_index(GtkTreePath *path);
88 gboolean move_node(MainView *mainview,GtkTreeIter *new_parent,GtkTreeIter *item_to_move,GtkTreeIter *item_befor);
89 gboolean tree_model_iter_prev(GtkTreeModel *tree_model,GtkTreeIter *iter);
90 gboolean show_confirmation(MainView* mainview, gchar* question);
94 gboolean callback_node_view_window_state(GtkWidget* window,
95 GdkEventWindowState* event, gpointer user_data)
97 MainView* mainview = (MainView*)user_data;
98 GtkWidget* sketch_scroll = NULL;
100 if (mainview->toolbar == NULL || mainview->sk == NULL) {
101 return FALSE;
104 sketch_scroll = GTK_WIDGET(sketchwidget_get_mainwidget(mainview->sk));
106 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
107 if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) {
108 gtk_widget_hide(mainview->toolbar);
109 gtk_scrolled_window_set_policy(
110 GTK_SCROLLED_WINDOW(sketch_scroll),
111 GTK_POLICY_NEVER,
112 GTK_POLICY_NEVER);
113 } else {
114 gtk_widget_show(mainview->toolbar);
115 gtk_scrolled_window_set_policy(
116 GTK_SCROLLED_WINDOW(sketch_scroll),
117 GTK_POLICY_AUTOMATIC,
118 GTK_POLICY_AUTOMATIC);
122 return FALSE;
125 void set_busy(MainView* mainview, SetBusyType update)
127 switch (update) {
128 case BUSY_RESET:
129 mainview->busyrefcount = 0;
130 break;
131 case BUSY_INCREMENT:
132 mainview->busyrefcount++;
133 break;
134 case BUSY_DECREMENT:
135 if (mainview->busyrefcount > 0) {
136 mainview->busyrefcount--;
138 break;
139 default:
140 g_error("Wrong type in set_busy: %d", update);
141 break;
144 hildon_gtk_window_set_progress_indicator(GTK_WINDOW(mainview->data->main_view), (mainview->busyrefcount > 0));
145 hildon_gtk_window_set_progress_indicator(GTK_WINDOW(mainview->data->node_view), (mainview->busyrefcount > 0));
148 void prepareUIforNodeChange(MainView * mainview, nodeType typ)
150 gtk_widget_set_sensitive(GTK_WIDGET(mainview->undo_tb), TRUE);
151 gtk_widget_set_sensitive(GTK_WIDGET(mainview->redo_tb), TRUE);
153 if (typ == NODE_TEXT)
155 gtk_widget_show(GTK_WIDGET(mainview->font_tb));
156 gtk_widget_show(GTK_WIDGET(mainview->bold_tb));
157 gtk_widget_show(GTK_WIDGET(mainview->italic_tb));
158 gtk_widget_show(GTK_WIDGET(mainview->underline_tb));
159 gtk_widget_show(GTK_WIDGET(mainview->bullet_tb));
160 gtk_widget_show(mainview->tools_font);
161 gtk_widget_show(mainview->tools_wordwrap);
163 else
165 gtk_widget_hide(GTK_WIDGET(mainview->font_tb));
166 gtk_widget_hide(GTK_WIDGET(mainview->bold_tb));
167 gtk_widget_hide(GTK_WIDGET(mainview->italic_tb));
168 gtk_widget_hide(GTK_WIDGET(mainview->underline_tb));
169 gtk_widget_hide(GTK_WIDGET(mainview->bullet_tb));
170 gtk_widget_hide(mainview->tools_font);
171 gtk_widget_hide(mainview->tools_wordwrap);
174 if (typ == NODE_SKETCH)
176 /* gtk_widget_show(GTK_WIDGET(mainview->colorbutton_tb));*/
177 gtk_widget_show(GTK_WIDGET(mainview->eraser_tb));
178 gtk_widget_show(GTK_WIDGET(mainview->brushsize_tb));
179 gtk_widget_show(GTK_WIDGET(mainview->sketchlines_tb));
180 gtk_widget_show(GTK_WIDGET(mainview->shape_tb));
181 gtk_widget_show(mainview->tools_color);
182 gtk_widget_show(mainview->tools_brushsize);
183 gtk_widget_show(mainview->tools_pagestyle);
184 gtk_widget_show(mainview->tools_shape);
185 gtk_widget_show(mainview->tools_pressure);
187 else
189 /* gtk_widget_hide(GTK_WIDGET(mainview->colorbutton_tb));*/
190 gtk_widget_hide(GTK_WIDGET(mainview->eraser_tb));
191 gtk_widget_hide(GTK_WIDGET(mainview->brushsize_tb));
192 gtk_widget_hide(GTK_WIDGET(mainview->sketchlines_tb));
193 gtk_widget_hide(GTK_WIDGET(mainview->shape_tb));
194 gtk_widget_hide(mainview->tools_color);
195 gtk_widget_hide(mainview->tools_brushsize);
196 gtk_widget_hide(mainview->tools_pagestyle);
197 gtk_widget_hide(mainview->tools_shape);
198 gtk_widget_hide(mainview->tools_pressure);
201 if (typ == NODE_CHECKLIST)
203 gtk_widget_show(GTK_WIDGET(mainview->bold_tb));
204 gtk_widget_show(GTK_WIDGET(mainview->strikethru_tb));
205 gtk_widget_show(GTK_WIDGET(mainview->check_tb));
206 gtk_widget_show(GTK_WIDGET(mainview->checkadd_tb));
207 gtk_widget_show(GTK_WIDGET(mainview->checkdel_tb));
208 gtk_widget_hide(GTK_WIDGET(mainview->undo_tb));
209 gtk_widget_hide(GTK_WIDGET(mainview->redo_tb));
211 else
213 gtk_widget_hide(GTK_WIDGET(mainview->strikethru_tb));
214 gtk_widget_hide(GTK_WIDGET(mainview->check_tb));
215 gtk_widget_hide(GTK_WIDGET(mainview->checkadd_tb));
216 gtk_widget_hide(GTK_WIDGET(mainview->checkdel_tb));
217 gtk_widget_show(GTK_WIDGET(mainview->undo_tb));
218 gtk_widget_show(GTK_WIDGET(mainview->redo_tb));
221 if (typ == NODE_TEXT)
223 gtk_widget_hide(GTK_WIDGET(mainview->colorbutton_tb));
224 gtk_widget_hide(sketchwidget_get_mainwidget(mainview->sk));
225 gtk_widget_hide(mainview->listscroll);
226 gtk_widget_show(GTK_WIDGET(mainview->scrolledwindow));
227 gtk_widget_show(mainview->tools_item);
229 else if (typ == NODE_SKETCH)
231 gtk_widget_show(GTK_WIDGET(mainview->colorbutton_tb));
232 gtk_widget_hide(GTK_WIDGET(mainview->scrolledwindow));
233 gtk_widget_hide(mainview->listscroll);
234 gtk_widget_show(sketchwidget_get_mainwidget(mainview->sk));
235 gtk_widget_show(mainview->tools_item);
237 else if (typ == NODE_CHECKLIST)
239 gtk_widget_show(GTK_WIDGET(mainview->colorbutton_tb));
240 gtk_widget_hide(GTK_WIDGET(mainview->scrolledwindow));
241 gtk_widget_hide(sketchwidget_get_mainwidget(mainview->sk));
242 gtk_widget_hide(mainview->tools_item);
243 gtk_widget_show(mainview->listscroll);
245 else
247 gtk_widget_hide(GTK_WIDGET(mainview->colorbutton_tb));
248 gtk_widget_hide(GTK_WIDGET(mainview->scrolledwindow));
249 gtk_widget_hide(sketchwidget_get_mainwidget(mainview->sk));
250 gtk_widget_hide(mainview->tools_item);
251 gtk_widget_hide(mainview->listscroll);
255 nodeData *getSelectedNode(MainView * mainview)
257 GtkTreeIter iter;
258 GtkTreeModel *model;
260 nodeData *nd;
262 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
264 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
265 return (NULL);
267 gtk_tree_model_get(model, &iter, NODE_DATA, &nd, -1);
269 return (nd);
272 void saveCurrentData(MainView * mainview)
274 nodeData *selnode = getSelectedNode(mainview);
275 saveDataToNode(mainview, selnode);
278 void saveDataToNode(MainView * mainview, nodeData *selnode)
280 if (selnode == NULL)
281 return;
283 if (
284 (selnode->typ == NODE_SKETCH && sketchwidget_get_edited(mainview->sk) == FALSE) ||
285 (selnode->typ == NODE_TEXT && wp_text_buffer_is_modified(mainview->buffer)==FALSE) ||
286 (selnode->typ == NODE_CHECKLIST && mainview->checklist_edited==FALSE)
289 maepad_message("node not edited, not saving");
290 return;
293 mainview->file_edited = TRUE;
295 busy_enter(mainview);
296 maepad_debug("saveDataToNode working");
298 gboolean goterr = TRUE;
299 gchar *textdata = NULL;
300 GdkPixbuf *pixbuf = NULL;
301 gchar *sketchdata = NULL;
302 gsize datalen = 0;
303 char tq[512];
305 if (selnode->typ == NODE_TEXT)
307 #if 0
308 GtkTextIter start, end;
309 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(mainview->buffer), &start, &end);
310 textdata = gtk_text_buffer_serialize_rich_text(GTK_TEXT_BUFFER(mainview->buffer), &start, &end, &datalen);
311 #endif
313 GString *gstr=g_string_sized_new(4096);
314 wp_text_buffer_save_document(mainview->buffer, (WPDocumentSaveCallback)(wp_savecallback), gstr);
316 datalen=gstr->len;
317 textdata=g_string_free(gstr, FALSE);
319 /* g_snprintf(tq, sizeof(tq), "UPDATE %s SET bodytype=%d, bodyblob=NULL, body=?, flags=%d WHERE nodeid=%d", datatable_tmpname, selnode->typ, selnode->flags, selnode->sql3id);*/
320 g_snprintf(tq, sizeof(tq), "UPDATE %s SET bodytype=%d, bodyblob=?, body=NULL, flags=%d WHERE nodeid=%d", datatable_tmpname, selnode->typ, selnode->flags, selnode->sql3id);
322 else if (selnode->typ == NODE_SKETCH)
324 GError *err = NULL;
325 GdkPixmap *skpix = sketchwidget_get_Pixmap(mainview->sk);
326 GtkWidget *skdr = sketchwidget_get_drawingarea(mainview->sk);
328 pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(skpix), NULL, 0, 0, 0, 0, skdr->allocation.width, skdr->allocation.height);
329 if (pixbuf == NULL)
331 maepad_warning("error saving: pixbuf is null");
333 else
335 double w, h;
336 GdkPixbuf *pixbuf2 = sketchwidget_trim_image(pixbuf, skdr->allocation.width, skdr->allocation.height, &w, &h, FALSE);
338 if (pixbuf2!=NULL)
340 if (gdk_pixbuf_save_to_buffer(pixbuf2, &sketchdata, &datalen, "png", &err, NULL) == FALSE)
342 sketchdata = NULL;
343 datalen = 0;
344 maepad_warning("Error saving sketch: %s", err->message);
345 g_error_free(err);
347 gdk_pixbuf_unref(pixbuf2);
350 g_snprintf(tq, sizeof(tq), "UPDATE %s SET bodytype=%d, body=NULL, bodyblob=?, flags=%d WHERE nodeid=%d", datatable_tmpname, selnode->typ, selnode->flags, selnode->sql3id);
351 maepad_debug("storing sketch in db: %d bytes", datalen);
352 if (skpix && G_IS_OBJECT(skpix)) g_object_unref(skpix);
354 else if (selnode->typ == NODE_CHECKLIST)
356 g_snprintf(tq, sizeof(tq), "UPDATE %s SET bodytype=%d, body=NULL, bodyblob=NULL, flags=%d WHERE nodeid=%d", datatable_tmpname, selnode->typ, selnode->flags, selnode->sql3id);
361 sqlite3_stmt *stmt = NULL;
362 const char *dum;
363 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
365 if (rc)
367 maepad_warning("Error updating: %s", sqlite3_errmsg(mainview->db));
368 break;
370 if (selnode->typ == NODE_TEXT)
371 sqlite3_bind_text(stmt, 1, textdata, datalen, /*strlen(textdata),*/ SQLITE_TRANSIENT);
372 else if (selnode->typ == NODE_SKETCH)
373 sqlite3_bind_blob(stmt, 1, sketchdata, datalen, SQLITE_TRANSIENT);
375 rc = SQLITE_BUSY;
376 while(rc == SQLITE_BUSY)
378 rc = sqlite3_step(stmt);
379 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
380 break;
382 sqlite3_finalize(stmt);
384 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
386 maepad_warning("Error saving node: %s", sqlite3_errmsg(mainview->db));
388 else
390 if (selnode->typ == NODE_TEXT)
391 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(mainview->buffer), FALSE);
392 else if (selnode->typ == NODE_SKETCH)
393 sketchwidget_set_edited(mainview->sk, FALSE);
394 else if (selnode->typ == NODE_CHECKLIST)
395 mainview->checklist_edited = FALSE;
396 goterr = FALSE;
398 }while(FALSE);
400 while(goterr==FALSE && selnode->typ == NODE_CHECKLIST)
402 GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
404 char tq[512];
405 g_snprintf(tq, sizeof(tq), "DELETE FROM %s WHERE nodeid=%d", checklisttable_tmpname, selnode->sql3id);
406 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
408 GtkTreeIter iter;
409 if (gtk_tree_model_get_iter_first(model, &iter)==FALSE) break;
413 gint styletoset_weight;
414 gboolean styletoset_strike;
415 gboolean ischecked;
416 gchar *text;
417 gchar *color;
418 unsigned long col=0;
420 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHECKNODE_BOLD, &styletoset_weight, CHECKNODE_STRIKE, &styletoset_strike, CHECKNODE_CHECKED, &ischecked, CHECKNODE_TEXT, &text, CHECKNODE_COLOR, &color, -1);
422 GdkColor tmpcol;
423 if (color!=NULL && strcmp(color, "(null)")!=0 && gdk_color_parse(color, &tmpcol))
425 col=((tmpcol.red>>8)<<16)|((tmpcol.green>>8)<<8)|(tmpcol.blue>>8);
428 gint style=0;
429 if (ischecked) style|=CHECKSTYLE_CHECKED;
430 if (styletoset_weight==PANGO_WEIGHT_BOLD) style|=CHECKSTYLE_BOLD;
431 if (styletoset_strike) style|=CHECKSTYLE_STRIKE;
433 g_snprintf(tq, sizeof(tq), "INSERT INTO %s (nodeid, name, style, color, ord) VALUES(%d, ?, %d, %lu, 0)", checklisttable_tmpname, selnode->sql3id, style, col);
434 sqlite3_stmt *stmt = NULL;
435 const char *dum;
436 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
438 if (rc)
440 goterr=TRUE;
441 maepad_warning("Error while saving checklist: %s", sqlite3_errmsg(mainview->db));
442 break;
444 sqlite3_bind_text(stmt, 1, text, strlen(text), SQLITE_TRANSIENT);
446 rc = SQLITE_BUSY;
447 while(rc == SQLITE_BUSY)
449 rc = sqlite3_step(stmt);
450 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
451 break;
453 sqlite3_finalize(stmt);
455 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
457 goterr=TRUE;
458 maepad_warning("Error while saving checklist (2): %s", sqlite3_errmsg(mainview->db));
461 g_free(color);
462 g_free(text);
464 }while(gtk_tree_model_iter_next(model, &iter)==TRUE);
466 break;
469 if (textdata)
470 g_free(textdata);
471 if (sketchdata)
472 g_free(sketchdata);
473 if (goterr == TRUE)
475 show_banner(mainview, _("Error saving memo"));
477 busy_leave(mainview);
480 gboolean callback_treeview_button_press(GtkTreeView* treeview, GdkEventButton* event, gpointer user_data)
482 MainView* mainview = (MainView*)user_data;
484 mainview->can_show_node_view = TRUE;
486 return FALSE;
489 void callback_treeview_celldatafunc(GtkTreeViewColumn * tree_column, GtkCellRenderer * cell, GtkTreeModel * tree_model, GtkTreeIter * iter, gpointer data)
491 MainView *mainview = ( MainView * ) data;
492 g_assert(mainview != NULL && mainview->data != NULL );
494 nodeData *nd;
496 gtk_tree_model_get(tree_model, iter, NODE_DATA, &nd, -1);
497 if (nd == NULL)
498 return;
500 if (nd->namepix == NULL)
502 g_object_set(cell, "visible", FALSE, NULL);
504 else
506 g_object_set(cell, "visible", TRUE, NULL);
507 g_object_set(cell, "width", SKETCHNODE_RX, NULL);
508 g_object_set(cell, "height", SKETCHNODE_RY, NULL);
513 gboolean callback_treeview_testcollapse(GtkTreeView * treeview, GtkTreeIter * arg1, GtkTreePath * arg2, gpointer user_data)
515 return (FALSE);
518 void callback_treeview_change(GtkTreeSelection * selection, gpointer data)
520 MainView *mainview = (MainView *) data;
521 g_assert(mainview != NULL && mainview->data != NULL);
523 nodeData *nd = getSelectedNode(mainview);
525 gchar* nodeName = _("View node");
527 if (nd != NULL && nd->name != NULL) {
528 nodeName = nd->name;
531 /* Show node view with selected node */
532 gtk_window_set_title(GTK_WINDOW(mainview->data->node_view),
533 nodeName);
535 if (mainview->can_show_node_view) {
536 gtk_widget_show(GTK_WIDGET(mainview->data->node_view));
539 /* Make sure we don't accidentally collapse any nodes */
540 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview->treeview));
542 #ifdef NEW_SEL_LOGIC
543 guint tm=time(NULL);
544 if (mainview->cansel_time>0 && mainview->cansel_time+1.0<tm) mainview->cansel_node=NULL;
546 if (nd==NULL)
548 if (mainview->cansel_node!=NULL)
550 maepad_debug("[SELLOGIC] saving %d to unselect all nodes", (mainview->cansel_node)->sql3id);
551 saveDataToNode(mainview, (mainview->cansel_node));
552 mainview->cansel_node=NULL;
554 return;
557 if (mainview->cansel_node!=NULL)
559 if (nd->sql3id == (mainview->cansel_node)->sql3id)
561 mainview->cansel_node=NULL;
562 maepad_debug("[SELLOGIC] doubly selected %d, doing nothing", nd->sql3id);
563 return;
565 else
567 maepad_debug("[SELLOGIC] saving %d to load new node", (mainview->cansel_node)->sql3id);
568 saveDataToNode(mainview, (mainview->cansel_node));
569 mainview->cansel_node=NULL;
572 #endif
574 if (nd == NULL) return;
576 busy_enter(mainview);
578 gboolean goterr = TRUE;
579 char *textdata = NULL;
580 char *blob = NULL;
581 int blobsize = 0, textsize = 0;
583 char tq[512];
585 g_snprintf(tq, sizeof(tq), "SELECT bodytype, body, bodyblob, flags FROM %s WHERE nodeid=%d", datatable_tmpname, nd->sql3id);
586 sqlite3_stmt *stmt = NULL;
587 const char *dum;
588 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
590 if (rc)
592 maepad_warning("Error reading (1): %s", sqlite3_errmsg(mainview->db));
594 else
596 rc = SQLITE_BUSY;
597 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
599 rc = sqlite3_step(stmt);
600 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
601 break;
602 else if (rc == SQLITE_ROW)
604 nd->typ = sqlite3_column_int(stmt, 0);
605 nd->flags = sqlite3_column_int(stmt, 3);
607 prepareUIforNodeChange(mainview, nd->typ);
608 if (nd->typ == NODE_TEXT)
610 gboolean file_edited_backup = mainview->file_edited;
612 blobsize = sqlite3_column_bytes(stmt, 2);
613 blob = (char *)sqlite3_column_blob(stmt, 2);
615 textdata = (char *)sqlite3_column_text(stmt, 1);
616 textsize = sqlite3_column_bytes(stmt, 1);
618 /* gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), "", -1);*/
619 wp_text_buffer_reset_buffer(mainview->buffer, TRUE);
621 gboolean richtext=FALSE;
623 if (blob != NULL)
625 #if 0
626 gboolean oldway=FALSE;
627 if (blobsize>8)
629 char tst[8];
630 strncpy(tst, blob, 8);
631 tst[8]=0;
632 if (strcmp(tst, "RICHTEXT")==0) oldway=TRUE;
634 if (oldway)
636 GError *err = NULL;
637 GtkTextIter iter;
638 gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(mainview->buffer), &iter);
639 gtk_text_buffer_deserialize_rich_text(GTK_TEXT_BUFFER(mainview->buffer), &iter, blob, blobsize, TRUE, &err);
640 if (err != NULL)
642 g_error_free(err);
644 else
646 richtext=TRUE;
649 #endif
651 if (richtext==FALSE)
653 wp_text_buffer_load_document_begin(mainview->buffer, TRUE);
654 wp_text_buffer_load_document_write(mainview->buffer, blob, blobsize);
655 wp_text_buffer_load_document_end(mainview->buffer);
656 richtext=TRUE;
659 if (richtext==FALSE && !(textdata == NULL || g_utf8_validate(textdata, textsize, NULL) == FALSE))
661 /* gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), textdata, textsize);*/
662 wp_text_buffer_load_document_begin(mainview->buffer, FALSE);
663 wp_text_buffer_load_document_write(mainview->buffer, textdata, textsize);
664 wp_text_buffer_load_document_end(mainview->buffer);
667 wp_text_buffer_enable_rich_text(mainview->buffer, TRUE);
668 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->tools_wordwrap), ((nd->flags & NODEFLAG_WORDWRAP) > 0)?TRUE:FALSE);
669 callback_wordwrap(NULL, mainview); /*FIXME:ugly (do we need this? gotta test) */
671 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(mainview->buffer), FALSE); /*we probably don't need this*/
673 callback_undotoggle((gpointer)mainview->buffer, FALSE, mainview); /*we need these*/
674 callback_redotoggle((gpointer)mainview->buffer, FALSE, mainview);
676 if (file_edited_backup==FALSE) mainview->file_edited=FALSE; /*textview changed event toggles this?*/
677 goterr = FALSE;
679 else if (nd->typ == NODE_SKETCH)
681 sketchwidget_wipe_undo(mainview->sk);
682 sketchwidget_set_fillmode(mainview->sk, FALSE);
683 sketchwidget_set_shift(mainview->sk, FALSE);
684 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->shapemenuitems[1]), TRUE);
685 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->shapemenuitems[0]), TRUE);
687 blobsize = sqlite3_column_bytes(stmt, 2);
688 blob = (char *)sqlite3_column_blob(stmt, 2);
689 gboolean clear = TRUE;
691 if (blob == NULL)
692 goterr = FALSE;
693 if (blob != NULL)
695 maepad_debug("blob size: %d", blobsize);
696 GdkPixbufLoader *pl = gdk_pixbuf_loader_new_with_type("png", NULL);
697 GError *err = NULL;
699 gdk_pixbuf_loader_write(pl, (guchar *) blob, blobsize, &err);
700 if (err != NULL)
702 maepad_warning("Error loading sketch: %s", err->message);
703 g_error_free(err);
704 err = NULL;
706 gdk_pixbuf_loader_close(pl, NULL);
707 GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(pl);
709 if (GDK_IS_PIXBUF(pixbuf))
711 GtkWidget *skdr = sketchwidget_get_drawingarea(mainview->sk);
712 GtkPixmap *skpix = (GtkPixmap *) sketchwidget_get_Pixmap(mainview->sk);
714 int w=gdk_pixbuf_get_width(pixbuf);
715 int h=gdk_pixbuf_get_height(pixbuf);
716 if (w!=skdr->allocation.width || h!=skdr->allocation.height)
718 if (w>skdr->allocation.width) w=skdr->allocation.width;
719 if (h>skdr->allocation.height) h=skdr->allocation.height;
720 sketchwidget_clear_real(mainview->sk);
722 gdk_draw_pixbuf(GDK_DRAWABLE(skpix), NULL, pixbuf, 0, 0, 0, 0, w, h, GDK_RGB_DITHER_NONE, 0, 0);
724 clear = FALSE;
725 goterr = FALSE;
727 if (skpix && G_IS_OBJECT(skpix)) g_object_unref(skpix);
729 else
731 maepad_warning("Error loading pixbuf");
733 g_object_unref(pl);
735 if (clear == TRUE)
737 maepad_message("Clearing sketch widget");
738 sketchwidget_clear_real(mainview->sk);
740 gtk_widget_queue_draw(sketchwidget_get_drawingarea(mainview->sk));
742 else if (nd->typ == NODE_CHECKLIST)
744 mainview->checklist_edited = FALSE;
745 GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
746 g_object_ref(model);
747 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->listview), NULL);
748 gtk_list_store_clear(GTK_LIST_STORE(model));
750 g_snprintf(tq, sizeof(tq), "SELECT name, style, color FROM %s WHERE nodeid=%d ORDER BY ord, idx", checklisttable_tmpname, nd->sql3id);
751 sqlite3_stmt *stmt2 = NULL;
752 const char *dum;
753 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt2, &dum);
754 if (rc)
756 maepad_warning("Error reading checklist (1) %s", sqlite3_errmsg(mainview->db));
758 else
760 goterr=FALSE;
761 rc = SQLITE_BUSY;
762 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
764 rc = sqlite3_step(stmt2);
765 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
766 break;
767 else if (rc == SQLITE_ROW)
769 char *textdata = (char *)sqlite3_column_text(stmt2, 0);
770 int style = sqlite3_column_int(stmt2, 1);
771 unsigned long col = sqlite3_column_int(stmt2, 2);
773 GtkTreeIter toplevel;
774 gtk_list_store_append(GTK_LIST_STORE(model), &toplevel);
775 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_TEXT, textdata, CHECKNODE_CHECKED, FALSE, -1);
776 if ((style & CHECKSTYLE_CHECKED)>0) {
777 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_CHECKED, TRUE, -1);
778 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_ICON_NAME, "widgets_tickmark_list", -1);
780 if ((style & CHECKSTYLE_BOLD)>0) gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_BOLD, PANGO_WEIGHT_BOLD, -1);
781 if ((style & CHECKSTYLE_STRIKE)>0) gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_STRIKE, TRUE, -1);
783 if (col>0)
785 char tmp[10];
786 g_snprintf(tmp, sizeof(tmp), "#%02lx%02lx%02lx", ((col & 0xFF0000) >> 16), ((col & 0xFF00) >> 8), (col & 0xFF));
787 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_COLOR, tmp, -1);
792 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
794 maepad_warning("Error reading checklist (2): %s", sqlite3_errmsg(mainview->db));
795 goterr=TRUE;
798 sqlite3_finalize(stmt2);
801 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->listview), model);
802 g_object_unref(model);
805 if ((nd->flags & NODEFLAG_SKETCHLINES) > 0)
806 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->sketchlinesmenuitems[1]), TRUE);
807 else if ((nd->flags & NODEFLAG_SKETCHGRAPH) > 0)
808 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->sketchlinesmenuitems[2]), TRUE);
809 else
811 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->sketchlinesmenuitems[0]), TRUE);
812 callback_sketchlines(NULL, mainview->sketchlinesmenuitems[0]); /*FIXME:ugly */
814 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->tools_pressure), TRUE);
816 break;
819 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE) {
820 maepad_warning("Error reading (2): %s", sqlite3_errmsg(mainview->db));
823 sqlite3_finalize(stmt);
826 busy_leave(mainview);
828 if (goterr == TRUE)
830 show_banner(mainview, _("Error loading memo"));
834 gboolean treeview_canselect(GtkTreeSelection * selection, GtkTreeModel * model, GtkTreePath * path, gboolean path_currently_selected, gpointer userdata)
836 MainView *mainview = (MainView *) userdata;
837 g_assert(mainview != NULL && mainview->data != NULL);
839 if (mainview->loading==FALSE)
841 #ifndef EXPANDING_ROWS
842 if (path_currently_selected)
843 return (FALSE);
844 #endif
846 #ifndef NEW_SEL_LOGIC
847 saveCurrentData(mainview);
848 #else
849 if (path_currently_selected)
851 GtkTreeIter iter;
852 gtk_tree_model_get_iter(model, &iter, path);
854 gtk_tree_model_get(model, &iter, NODE_DATA, &(mainview->cansel_node), -1);
855 mainview->cansel_time=time(NULL);
857 #endif
859 return (TRUE);
862 gboolean newnodedlg_key_press_cb(GtkWidget * widget, GdkEventKey * event, GtkWidget * dlg)
864 SketchWidget *s = gtk_object_get_data(GTK_OBJECT(dlg), "sk");
866 switch (event->keyval)
868 case GDK_F7:
869 sketchwidget_redo(s);
870 return TRUE;
871 case GDK_F8:
872 sketchwidget_undo(s);
873 return TRUE;
875 return FALSE;
879 /* This struct will hold all our toggle buttons, so we can
880 * only allow one to be active at a time (i.e. radio buttons) */
881 typedef struct _newNodeToggleButtons newNodeToggleButtons;
882 struct _newNodeToggleButtons
884 GtkWidget *rbt; /* Text */
885 GtkWidget *rbs; /* Sketch */
886 GtkWidget *rbc; /* Checklist */
889 void show_sketch_widget(GtkWidget *widget, gpointer user_data)
891 GtkWidget *dialog = (GtkWidget*)user_data;
893 /* Show the sketch widget and hide the entry + draw button */
894 gtk_widget_show(gtk_object_get_data(GTK_OBJECT(dialog), "al"));
895 gtk_widget_hide(gtk_object_get_data(GTK_OBJECT(dialog), "draw_button"));
896 gtk_widget_hide(gtk_object_get_user_data(GTK_OBJECT(dialog)));
899 void new_node_dialog(nodeType typ, MainView * mainview)
901 GtkWidget *dialog, *entry, *but_ok, *vbox, *hbox, *al, *cb;
902 GtkWidget *rb1, *rb2, *rb3;
903 GtkWidget *hb;
904 gchar datetime_str[200];
905 time_t t_now;
906 struct tm *tm_now;
907 gboolean datetime_written = FALSE;
909 t_now = time(NULL);
910 tm_now = localtime(&t_now);
912 if (tm_now != NULL) {
913 if (strftime(datetime_str, sizeof(datetime_str), "%y-%m-%d %H:%M", tm_now) != 0) {
914 datetime_written = TRUE;
918 if (datetime_written == FALSE) {
919 /* Was not able to determine a datetime string - use default */
920 maepad_warning("Cannot determine current time");
921 strncpy(datetime_str, _("New memo"), sizeof(datetime_str));
922 datetime_str[sizeof(datetime_str)-1] = '\0';
925 newNodeToggleButtons *nntb = g_malloc(sizeof(newNodeToggleButtons));
927 dialog = gtk_dialog_new();
928 gtk_window_set_title(GTK_WINDOW(dialog), _("Create new memo"));
929 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
931 g_signal_connect(G_OBJECT(dialog), "key_press_event", G_CALLBACK(newnodedlg_key_press_cb), dialog);
933 vbox = gtk_vbox_new(FALSE, 0);
935 hbox = gtk_hbox_new(TRUE, 0);
937 /* Text note toggle button */
938 rb1 = hildon_gtk_radio_button_new(HILDON_SIZE_FINGER_HEIGHT, NULL);
939 gtk_button_set_label(GTK_BUTTON(rb1), _("Rich text"));
940 gtk_button_set_image(GTK_BUTTON(rb1), gtk_image_new_from_file(PIXMAPDIR "/text.png"));
941 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(rb1), TRUE, TRUE, 0);
942 nntb->rbt = rb1;
944 /* Sketch toggle button */
945 rb2 = hildon_gtk_radio_button_new_from_widget(HILDON_SIZE_FINGER_HEIGHT, GTK_RADIO_BUTTON(rb1));
946 gtk_button_set_label(GTK_BUTTON(rb2), _("Sketch"));
947 gtk_button_set_image(GTK_BUTTON(rb2), gtk_image_new_from_file(PIXMAPDIR "/sketch.png"));
948 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(rb2), TRUE, TRUE, 0);
949 nntb->rbs = rb2;
951 /* Checklist toggle button */
952 rb3 = hildon_gtk_radio_button_new_from_widget(HILDON_SIZE_FINGER_HEIGHT, GTK_RADIO_BUTTON(rb1));
953 gtk_button_set_label(GTK_BUTTON(rb3), _("Checklist"));
954 gtk_button_set_image(GTK_BUTTON(rb3), gtk_image_new_from_file(PIXMAPDIR "/checklist.png"));
955 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(rb3), TRUE, TRUE, 0);
956 nntb->rbc = rb3;
958 /* Set mode to 0 to get correct styling */
959 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb1), FALSE);
960 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb2), FALSE);
961 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb3), FALSE);
963 /* Remember "new note toggle buttons" list */
964 gtk_object_set_data(GTK_OBJECT(dialog), "nntb", nntb);
966 if (typ == NODE_TEXT) {
967 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb1), TRUE);
968 } else if (typ == NODE_SKETCH) {
969 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb2), TRUE);
970 } else {
971 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb3), TRUE);
974 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
976 but_ok = gtk_dialog_add_button(GTK_DIALOG(dialog), _("Create"), GTK_RESPONSE_OK);
977 g_signal_connect(G_OBJECT(but_ok), "clicked", G_CALLBACK(callback_new_node_real), dialog);
979 gtk_object_set_data(GTK_OBJECT(dialog), "m", mainview);
981 hb = gtk_hbox_new(FALSE, 10);
982 gtk_box_pack_start(GTK_BOX(hb), gtk_label_new(_("Name:")), FALSE, FALSE, 0);
983 entry = hildon_entry_new(HILDON_SIZE_AUTO);
984 gtk_object_set_user_data(GTK_OBJECT(dialog), entry);
985 gtk_entry_set_text(GTK_ENTRY(entry), datetime_str);
986 gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
987 gtk_box_pack_start(GTK_BOX(hb), entry, TRUE, TRUE, 0);
989 /* Sketch widget, hidden by default */
990 al = gtk_alignment_new(0.5, 0.5, 0, 0);
991 SketchWidget *s = sketchwidget_new(SKETCHNODE_X, SKETCHNODE_Y, TRUE);
992 gtk_object_set_data(GTK_OBJECT(dialog), "sk", s);
993 gtk_object_set_data(GTK_OBJECT(dialog), "al", al);
994 sketchwidget_set_brushsize(s, 2);
995 sketchwidget_set_backstyle(s, SKETCHBACK_GRAPH);
996 gtk_widget_set_size_request(sketchwidget_get_mainwidget(s), SKETCHNODE_X, SKETCHNODE_Y);
997 gtk_container_add(GTK_CONTAINER(al), sketchwidget_get_mainwidget(s));
998 gtk_box_pack_start(GTK_BOX(hb), al, FALSE, FALSE, 0);
1000 /*but_sketch = hildon_button_new_with_text(
1001 HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
1002 HILDON_BUTTON_ARRANGEMENT_VERTICAL,
1003 _("Use sketch label"), NULL);
1005 gtk_object_set_data(GTK_OBJECT(dialog), "draw_button", but_sketch);
1006 gtk_signal_connect(GTK_OBJECT(but_sketch), "clicked", G_CALLBACK(show_sketch_widget), dialog);
1007 gtk_box_pack_start(GTK_BOX(hb), but_sketch, FALSE, TRUE, 0);*/
1008 gtk_box_pack_start(GTK_BOX(vbox), hb, TRUE, FALSE, 0);
1010 cb = hildon_check_button_new(HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
1011 gtk_button_set_label(GTK_BUTTON(cb), _("Create as child of selected memo"));
1012 hildon_check_button_set_active(HILDON_CHECK_BUTTON(cb), mainview->newnodedialog_createchild);
1013 gtk_box_pack_start(GTK_BOX(vbox), cb, FALSE, FALSE, 0);
1015 gtk_object_set_data(GTK_OBJECT(dialog), "cb", cb);
1017 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), vbox);
1019 gtk_widget_grab_focus(entry);
1021 gtk_widget_show_all(dialog);
1023 /* Hide the sketch widget at first */
1024 gtk_widget_hide(al);
1025 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
1028 void add_new_node(nodeData * node, MainView * mainview, gboolean ischild)
1030 GtkTreeIter parentiter, newiter;
1031 GtkTreeModel *model;
1032 void *ptr = NULL;
1034 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1036 if (gtk_tree_selection_get_selected(selection, &model, &parentiter))
1037 ptr = &parentiter;
1039 GtkTreePath *path = NULL;
1041 unsigned int parentnodeid = 0;
1043 if (ptr != NULL)
1045 path = gtk_tree_model_get_path(model, &parentiter);
1047 if (ischild == FALSE)
1049 gtk_tree_path_up(path);
1051 if (gtk_tree_path_get_depth(path) == 0)
1053 /* Selected node is a root node */
1054 ptr = NULL; /* New node can not have a Parent node */
1055 gtk_tree_path_down(path); /*restore path so expand() works */
1057 else if (gtk_tree_path_get_depth(path) > 0)
1059 /* Selected node is a child node */
1060 if (gtk_tree_model_get_iter(model, &parentiter, path))
1061 ptr = &parentiter;
1066 if (ptr != NULL)
1068 nodeData *nd;
1070 gtk_tree_model_get(model, ptr, NODE_DATA, &nd, -1);
1071 if (nd)
1072 parentnodeid = nd->sql3id;
1075 node->sql3id = 0;
1078 sqlite3_stmt *stmt = NULL;
1079 const char *dum;
1080 char tq[512];
1083 * FIXME: ord
1085 g_snprintf(tq, sizeof(tq), "INSERT INTO %s (parent, bodytype, name, nameblob, ord) VALUES (%d, %d, ?, ?, 0);", datatable_tmpname, parentnodeid, node->typ);
1086 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
1088 if (rc)
1090 maepad_warning("Error inserting (1): %s", sqlite3_errmsg(mainview->db));
1091 break;
1093 if (node->name != NULL)
1094 sqlite3_bind_text(stmt, 1, node->name, strlen(node->name), SQLITE_TRANSIENT);
1095 else
1096 sqlite3_bind_text(stmt, 1, NULL, 0, SQLITE_TRANSIENT);
1098 if (node->namepix != NULL)
1100 gchar *namepixdata = NULL;
1101 gsize datalen = 0;
1103 GError *err = NULL;
1105 if (gdk_pixbuf_save_to_buffer(node->namepix, &namepixdata, &datalen, "png", &err, NULL) == FALSE)
1107 namepixdata = NULL;
1108 datalen = 0;
1109 maepad_warning("Error saving name: %s", err->message);
1110 g_error_free(err);
1112 sqlite3_bind_blob(stmt, 2, namepixdata, datalen, SQLITE_TRANSIENT);
1114 else
1115 sqlite3_bind_blob(stmt, 2, NULL, 0, SQLITE_TRANSIENT);
1117 rc = SQLITE_BUSY;
1118 while(rc == SQLITE_BUSY)
1120 rc = sqlite3_step(stmt);
1121 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
1122 break;
1124 sqlite3_finalize(stmt);
1125 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
1127 maepad_warning("Error inserting (2): %s", sqlite3_errmsg(mainview->db));
1128 break;
1130 node->sql3id = sqlite3_last_insert_rowid(mainview->db);
1132 while(FALSE);
1134 if (node->sql3id == 0)
1136 if (node->name)
1137 g_free(node->name);
1138 if (node->namepix)
1139 g_object_unref(node->namepix);
1140 g_free(node);
1141 if (path)
1142 gtk_tree_path_free(path);
1143 show_banner(mainview, _("Error creating node"));
1144 return;
1147 gtk_tree_store_append(GTK_TREE_STORE(model), &newiter, ptr);
1149 gtk_tree_store_set(GTK_TREE_STORE(model), &newiter, NODE_NAME, node->name, NODE_PIXBUF, node->namepix, NODE_DATA, node, -1);
1151 if (path)
1153 mainview->loading=TRUE; /*only when we have a valid parent*/
1154 gtk_tree_view_expand_row(GTK_TREE_VIEW(mainview->treeview), path, FALSE);
1155 gtk_tree_path_free(path);
1158 gtk_tree_selection_select_iter(selection, &newiter);
1160 mainview->loading=FALSE;
1163 void callback_new_node_real(GtkAction * action, gpointer data)
1165 MainView *mainview;
1167 GtkWidget *dialog = data;
1168 GtkWidget *entry = gtk_object_get_user_data(GTK_OBJECT(dialog));
1170 mainview = gtk_object_get_data(GTK_OBJECT(dialog), "m");
1171 SketchWidget *s = gtk_object_get_data(GTK_OBJECT(dialog), "sk");
1172 GtkWidget *cb = gtk_object_get_data(GTK_OBJECT(dialog), "cb");
1173 newNodeToggleButtons *nntb = gtk_object_get_data(GTK_OBJECT(dialog), "nntb");
1175 nodeType typ = NODE_TEXT;
1176 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nntb->rbs))) {
1177 typ = NODE_SKETCH;
1178 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nntb->rbc))) {
1179 typ = NODE_CHECKLIST;
1181 g_free(nntb);
1183 gchar *txt = NULL;
1185 /*if (GTK_WIDGET_VISIBLE(entry))
1187 txt = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
1188 if (strcmp(txt, "") == 0)
1190 g_free(txt);
1191 return;
1194 else
1196 GtkWidget *sdr = sketchwidget_get_drawingarea(s);
1198 GdkPixmap *spix = sketchwidget_get_Pixmap(s);
1200 pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(spix), NULL, 0, 0, 0, 0, sdr->allocation.width, sdr->allocation.height);
1201 g_object_unref(spix);
1202 double w, h;
1203 GdkPixbuf *pixbuf2 = sketchwidget_trim_image(pixbuf, SKETCHNODE_X, SKETCHNODE_Y, &w,
1204 &h, TRUE);
1205 if (pixbuf2==NULL) return;
1207 GdkPixbuf *pixbuf3 = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, SKETCHNODE_RX,
1208 SKETCHNODE_RY);
1210 gdk_pixbuf_fill(pixbuf3, 0xffffffff);
1212 if (w <= SKETCHNODE_RX && h <= SKETCHNODE_RY)
1214 gdk_pixbuf_copy_area(pixbuf2, 0, 0, w, h, pixbuf3, 0, (SKETCHNODE_RY - h) / 2);
1216 else
1218 double neww, newh;
1220 if (w > h)
1222 neww = SKETCHNODE_RX;
1223 newh = (h / w) * SKETCHNODE_RX;
1225 else
1227 newh = SKETCHNODE_RY;
1228 neww = (w / h) * SKETCHNODE_RY;
1230 if (newh > SKETCHNODE_RY)
1231 newh = SKETCHNODE_RY;
1233 GdkPixbuf *tmpbuf = gdk_pixbuf_scale_simple(pixbuf2, neww, newh,
1234 GDK_INTERP_BILINEAR);
1236 gdk_pixbuf_copy_area(tmpbuf, 0, 0, neww, newh, pixbuf3, 0, (SKETCHNODE_RY - newh) / 2);
1238 gdk_pixbuf_unref(tmpbuf);
1241 pixbuf = pixbuf3;
1242 gdk_pixbuf_unref(pixbuf2);
1245 nodeData *node;
1247 node = g_malloc(sizeof(nodeData));
1248 node->typ = typ;
1249 node->name = txt;
1250 node->namepix = NULL;
1252 /*if (GTK_WIDGET_VISIBLE(entry))
1254 node->name = txt;
1256 else
1258 node->namepix = pixbuf;
1261 node->lastMod = 0;
1262 node->flags = 0;
1263 node->sql3id = 0;
1265 mainview->newnodedialog_createchild = hildon_check_button_get_active(HILDON_CHECK_BUTTON(cb));
1266 add_new_node(node, mainview, mainview->newnodedialog_createchild);
1268 sketchwidget_destroy(s);
1269 gtk_widget_destroy(dialog);
1270 mainview->file_edited = TRUE;
1274 * delete node
1276 void callback_file_delete_node(GtkAction * action, gpointer data)
1278 MainView *mainview = (MainView *) data;
1279 g_assert(mainview != NULL && mainview->data != NULL);
1281 if (getSelectedNode(mainview) == NULL) {
1282 show_banner(mainview, _("Select a node first"));
1283 return;
1286 if (show_confirmation(mainview, _("Delete selected memo?"))) {
1287 callback_delete_node_real(mainview);
1288 gtk_widget_hide(GTK_WIDGET(mainview->data->node_view));
1293 * Callback for Rename Menuitem
1295 void callback_file_rename_node(GtkAction * action, gpointer data)
1297 MainView *mainview = (MainView*)data;
1298 g_assert(mainview != NULL && mainview->data != NULL);
1300 /* Get the selected node */
1301 nodeData *sel_node = getSelectedNode(mainview);
1302 if (sel_node == NULL) {
1303 /* Do nothing, if no node has been selected */
1304 show_banner(mainview, _("Select a node first"));
1305 return;
1308 if (sel_node->namepix != NULL) {
1309 /* the memo has a graphical label, cannot edit! */
1310 show_banner(mainview, _("Cannot rename memos with sketch name"));
1311 return;
1314 gchar* new_name = show_line_edit_dialog(mainview, _("Rename memo"), _("New name:"), _("Rename"), sel_node->name);
1316 /* Only rename node when user accepted the new name */
1317 if (new_name != NULL) {
1318 callback_rename_node_real(mainview, new_name);
1319 g_free(new_name);
1323 void callback_rename_node_real(MainView* mainview, gchar* new_name)
1325 GtkTreeIter iter;
1326 GtkTreeModel *model;
1327 nodeData *nd = NULL;
1329 /* Get the selected node */
1330 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1332 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
1333 return;
1336 gtk_tree_model_get (model, &iter, NODE_DATA, &nd, -1);
1338 if (nd == NULL) {
1339 return;
1342 /* Update the database */
1343 sqlite3_stmt *stmt = NULL;
1345 char* sql = sqlite3_mprintf("UPDATE %s SET name='%q' WHERE nodeid=%d", datatable_tmpname, new_name, nd->sql3id);
1347 int rc = sqlite3_prepare(mainview->db, sql, strlen(sql), &stmt, NULL);
1348 if (rc == SQLITE_OK) {
1349 rc = SQLITE_BUSY;
1350 while (rc == SQLITE_BUSY) {
1351 rc = sqlite3_step(stmt);
1352 if (rc == SQLITE_DONE) {
1353 /* Update in the database was successful - now update the rest */
1355 /* Update the noteData */
1356 g_free(nd->name);
1357 nd->name = g_strdup(new_name);
1359 /* Update the window title of node_view */
1360 gtk_window_set_title(GTK_WINDOW(mainview->data->node_view), nd->name);
1362 /* Update the value in the tree store */
1363 gtk_tree_store_set (GTK_TREE_STORE(model), &iter, NODE_NAME, new_name, -1);
1365 break;
1366 } else if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE) {
1367 maepad_warning("Error updating node: %s", sqlite3_errmsg(mainview->db));
1368 break;
1371 sqlite3_finalize(stmt);
1372 } else {
1373 maepad_warning("Error preparing DB update query: %s", sqlite3_errmsg(mainview->db));
1376 sqlite3_free(sql);
1378 mainview->file_edited = TRUE;
1381 void callback_file_export_node(GtkAction * action, gpointer data)
1383 MainView *mainview = (MainView *) data;
1384 g_assert(mainview != NULL && mainview->data != NULL);
1386 nodeData *nd=getSelectedNode(mainview);
1387 if (nd == NULL)
1389 show_banner(mainview, _("Select a memo first"));
1390 return;
1393 gchar *nodename=nd->name;
1394 if (nodename==NULL) nodename=_("saved memo");
1396 if (nd->typ == NODE_TEXT)
1399 GtkTextIter begin, end;
1400 gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER(mainview->buffer), &begin, &end);
1401 gchar *text = gtk_text_buffer_get_slice(GTK_TEXT_BUFFER(mainview->buffer), &begin, &end, TRUE);
1403 GString *gstr=g_string_sized_new(4096);
1404 wp_text_buffer_save_document(mainview->buffer, (WPDocumentSaveCallback)(wp_savecallback), gstr);
1405 gint textlen=gstr->len;
1406 gchar *text=g_string_free(gstr, FALSE);
1408 if (text==NULL || !strcmp(text, ""))
1410 show_banner(mainview, _("Memo is empty"));
1412 else
1414 gchar *fn = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, nodename, "html");
1415 if (fn!=NULL)
1417 GnomeVFSResult vfs_result;
1418 GnomeVFSHandle *handle = NULL;
1419 GnomeVFSFileSize out_bytes;
1420 vfs_result = gnome_vfs_create(&handle, fn, GNOME_VFS_OPEN_WRITE, 0, 0600);
1421 if ( vfs_result != GNOME_VFS_OK ) {
1422 show_banner(mainview, _("Export failed"));
1424 else
1426 gnome_vfs_write(handle, text, textlen, &out_bytes);
1427 gnome_vfs_close(handle);
1428 if (out_bytes==strlen(text)) show_banner(mainview, _("Exported"));
1429 else show_banner(mainview, _("Export incomplete"));
1431 g_free(fn);
1434 g_free(text);
1436 else if (nd->typ == NODE_SKETCH)
1438 GdkPixmap *skpix = sketchwidget_get_Pixmap(mainview->sk);
1439 GtkWidget *skdr = sketchwidget_get_drawingarea(mainview->sk);
1440 GdkPixbuf *pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(skpix), NULL, 0, 0, 0, 0, skdr->allocation.width, skdr->allocation.height);
1441 if (pixbuf==NULL)
1443 show_banner(mainview, _("Memo is empty"));
1445 else
1447 gchar *fn = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, nodename, "png");
1448 if (fn!=NULL)
1450 if (gdk_pixbuf_save(pixbuf, fn, "png", NULL, NULL)==FALSE)
1452 show_banner(mainview, _("Export failed"));
1454 else
1456 show_banner(mainview, _("Exported"));
1458 g_free(fn);
1461 g_object_unref(skpix);
1463 else if (nd->typ == NODE_CHECKLIST)
1465 show_banner(mainview, _("Export of checklists not possible yet"));
1470 * callback from menu item
1471 * move selected node down (switch node with next sibling), don't change level of node
1473 void callback_move_down_node(GtkAction * action, gpointer data)
1475 GtkTreeIter iter;
1476 GtkTreeModel *model;
1478 MainView *mainview = (MainView *) data;
1479 g_assert(mainview != NULL && mainview->data != NULL);
1481 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1482 gtk_tree_selection_get_selected(selection, &model, &iter);
1484 GtkTreeIter old_iter = iter;/*save pointer to old iter, we will need it during swap nodes*/
1486 if (gtk_tree_model_iter_next(model,&iter)==FALSE)/*get next node*/
1487 return;
1489 GtkTreeStore *treeStore = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview)));
1490 gtk_tree_store_swap(treeStore,&iter,&old_iter);
1492 mainview->file_edited = TRUE;/*we have made changes , if required show "save changes?" dialog in future*/
1496 * callback from menu item
1497 * move selected node down (switch node with prev sibling), don't change level of node
1499 void callback_move_up_node(GtkAction * action, gpointer data)
1501 GtkTreeIter iter;
1502 GtkTreeModel *model;
1504 MainView *mainview = (MainView *) data;
1505 g_assert(mainview != NULL && mainview->data != NULL);
1507 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1508 gtk_tree_selection_get_selected(selection, &model, &iter);
1510 GtkTreeIter old_iter=iter;/*save pointer to old iter, we will need it during swap nodes*/
1512 if (tree_model_iter_prev(model,&iter)==FALSE)/*get previous node*/
1513 return;
1515 GtkTreeStore *treeStore = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview)));
1516 gtk_tree_store_swap(treeStore,&old_iter,&iter);/*do move*/
1518 mainview->file_edited = TRUE;/*we have made changes , if required show "save changes?" dialog in future*/
1522 * callback from menu item
1523 * we change level of actual node with direction to top
1525 void callback_move_to_top_level_node(GtkAction * action, gpointer data)
1527 GtkTreeIter iter,new_parent;
1528 GtkTreeIter *p_new_parent;
1529 GtkTreeIter parent;
1530 GtkTreeModel *model;
1532 MainView *mainview = (MainView *) data;
1533 g_assert(mainview != NULL && mainview->data != NULL);
1535 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1536 gtk_tree_selection_get_selected(selection, &model, &iter);
1538 /*at first we need actual parent of selected node*/
1539 if (gtk_tree_model_iter_parent(model,&parent,&iter)==FALSE)
1541 /*if parent of selected node is ROOT we can't go higher*/
1542 return;
1544 /*we need also new parent, it's parent of actual parent*/
1545 if (gtk_tree_model_iter_parent(model,&new_parent,&parent)==FALSE)
1547 /*if our new parent is ROOT we got filled new_parent with invalid value,
1548 so we need set NULL value to p_new_parent (root item)*/
1549 p_new_parent=NULL;
1551 else
1553 p_new_parent=&new_parent;/*we only redirect pointer to treeiter*/
1556 saveCurrentData(mainview);/*we save changes in node befor move*/
1558 /*this move function provide move item with all his children, be careful iter value will change!*/
1559 if (move_node(mainview,p_new_parent,&iter,&parent)==TRUE){
1561 gint id_parent = get_node_id_on_tmp_db(model,p_new_parent);
1562 gint id_node = get_node_id_on_tmp_db(model,&iter);
1563 /*we need also update parent id of moved item*/
1564 char tq[512];
1565 g_snprintf (tq, sizeof(tq), "UPDATE %s SET parent=%d WHERE nodeid=%d",datatable_tmpname,id_parent ,id_node);
1566 exec_command_on_db(mainview,tq);
1568 /*select new created iter*/
1569 gtk_tree_selection_select_iter(selection,&iter);
1571 mainview->file_edited = TRUE;/*we have made changes , if required show "save changes?" dialog in future*/
1576 * callback from menu item
1577 * we change level of actual node with direction to bottom
1578 * previous node will be parent of our actual node
1580 void callback_move_to_bottom_level_node(GtkAction * action, gpointer data)
1582 GtkTreeIter iter;
1583 GtkTreeModel *model;
1585 MainView *mainview = (MainView *) data;
1586 g_assert(mainview != NULL && mainview->data != NULL);
1588 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1589 gtk_tree_selection_get_selected(selection, &model, &iter);
1591 GtkTreeIter move_iter=iter;/*save pointer to old iter*/
1593 /*we try to get previous node*/
1594 if (tree_model_iter_prev(model,&iter)==FALSE)
1595 return;/*if previous node on the same level doesn't exist we will exit*/
1597 saveCurrentData(mainview);/*we save changes in node befor move*/
1599 /*this move function provide move item with all his children, be careful move_iter value will change!*/
1600 if (move_node(mainview,&iter,&move_iter,NULL)==TRUE)
1602 gint id_parent = get_node_id_on_tmp_db(model,&iter);
1603 gint id_node = get_node_id_on_tmp_db(model,&move_iter);
1605 /*we need also update parent id of moved item*/
1606 char tq[512];
1607 g_snprintf (tq, sizeof(tq), "UPDATE %s SET parent=%d WHERE nodeid=%d",datatable_tmpname,id_parent ,id_node);
1608 exec_command_on_db(mainview,tq);
1610 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
1611 gtk_tree_view_expand_row(GTK_TREE_VIEW(mainview->treeview), path, FALSE);/*expand parent node*/
1612 gtk_tree_path_free(path);
1614 /*select new created iter*/
1615 gtk_tree_selection_select_iter(selection,&move_iter);
1617 mainview->file_edited = TRUE;/*we have made changes , if required show "save changes?" dialog in future*/
1622 * move item_to_move to new_parent with his children, this function is designed for change level of node
1623 * we copy item_to_move with his children to new position (after item_befor if is not NULL) and then we
1624 * destroy old node with his children, so ! item_to_move is set with new iter, be careful on this!
1626 gboolean move_node(MainView *mainview,GtkTreeIter *new_parent,GtkTreeIter *item_to_move,GtkTreeIter *item_befor)
1628 GtkTreeModel *model;
1630 model=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview));
1631 GtkTreeStore *treeStore = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview)));
1633 nodeData *node;
1634 gtk_tree_model_get(model, item_to_move, NODE_DATA, &node, -1);/*get data from actual iter*/
1635 if (node)
1637 GtkTreeIter new_iter;/*create new iter*/
1638 gtk_tree_store_append(treeStore,&new_iter,new_parent);/*append new iter to new parent*/
1640 if (item_befor!=NULL)
1641 gtk_tree_store_move_after(treeStore,&new_iter,item_befor);/*sometimes we need set position*/
1643 gtk_tree_store_set(treeStore, &new_iter, NODE_NAME, node->name,NODE_PIXBUF, node->namepix, NODE_DATA, node, -1);/*set data from old iter*/
1645 GtkTreeIter child;
1646 while (gtk_tree_model_iter_children(model, &child, item_to_move)==TRUE)/*move all childrens while some exits*/
1648 if (move_node(mainview,&new_iter,&child,NULL)==FALSE)/*use recursion on children*/
1649 return FALSE;
1652 gtk_tree_store_set(treeStore, item_to_move, NODE_DATA, NULL, -1);
1653 gtk_tree_store_remove(treeStore, item_to_move);/*remove node, data need't remove, they are stored in new node*/
1655 /*we need return new value of moved item, so we need assign new_iter to item_to_move*/
1656 /*this code is ugly : new_iter to path and back to item_to_move*/
1657 GtkTreePath *path=gtk_tree_model_get_path(model,&new_iter);
1658 gtk_tree_model_get_iter(model,item_to_move,path);
1659 gtk_tree_path_free(path);
1661 else
1663 fprintf(stderr,"Get data node failed!\n");
1664 return FALSE;
1667 return TRUE;
1671 * simple execute of sql command which is stored in sql_string[]
1673 gboolean exec_command_on_db(MainView *mainview,char sql_string[])
1675 sqlite3_stmt *stmt = NULL;
1676 const char* dum;
1677 gboolean db_query_result = FALSE;
1679 int rc = sqlite3_prepare (mainview->db, sql_string, strlen(sql_string), &stmt, &dum);
1681 if (rc) {
1682 maepad_warning("Error preparing DB update query: %s", sqlite3_errmsg(mainview->db));
1683 return FALSE;
1686 rc = SQLITE_BUSY;
1687 while (rc == SQLITE_BUSY) {
1688 rc = sqlite3_step (stmt);
1689 if (rc == SQLITE_DONE) {
1690 db_query_result = TRUE;
1691 break;
1693 else if(rc == SQLITE_ERROR || rc== SQLITE_MISUSE) {
1694 maepad_warning("Error updating node: %s", sqlite3_errmsg(mainview->db));
1695 break;
1697 sqlite3_finalize(stmt);
1699 return TRUE;
1703 * it is used in gtk_tree_model_foreach function to update ord value for all nodes (it's usefull for move up, move down node)
1705 gboolean foreach_func_update_ord (GtkTreeModel *model,GtkTreePath *path,GtkTreeIter *iter, MainView *mainview)
1707 nodeData *node;
1708 gtk_tree_model_get(model, iter, NODE_DATA, &node, -1);
1709 /*we need index of node on actual level*/
1710 gint index=get_branch_node_index(path);
1712 /*prepare to execute update command,and exec it*/
1713 char sql_command[512];
1714 g_snprintf (sql_command, sizeof(sql_command), "UPDATE %s SET ord=\"%d\" WHERE nodeid=%d",datatable_tmpname, index, node->sql3id);
1715 exec_command_on_db(mainview,sql_command);
1717 /*we don't want break gtk_tree_model_foreach function,until we call this func on each node - so we return always FALSE*/
1718 return FALSE;
1722 * return id number of iter (id number which is used to identify in sql database of nodes)
1724 int get_node_id_on_tmp_db(GtkTreeModel *model,GtkTreeIter *iter)
1726 if (iter==NULL)
1727 return 0;/*we got ROOT parent here*/
1729 nodeData *node;
1730 gtk_tree_model_get(model, iter, NODE_DATA, &node, -1);
1731 return node->sql3id;
1735 * get index of node in current branch
1737 gint get_branch_node_index(GtkTreePath *path)
1739 int depth=gtk_tree_path_get_depth(path);
1740 gint *indicies = gtk_tree_path_get_indices(path);
1742 return indicies[depth-1];
1746 * similiar with gtk_tree_model_iter_next (), but opposite
1748 gboolean tree_model_iter_prev(GtkTreeModel *tree_model,GtkTreeIter *iter)
1750 GtkTreePath *path = gtk_tree_model_get_path(tree_model, iter);
1752 if (path==NULL){
1753 fprintf(stderr,"Error: path is null\n");
1754 return FALSE;
1757 if (gtk_tree_path_prev(path)==FALSE)
1758 return FALSE;
1760 gtk_tree_model_get_iter(tree_model, iter,path);
1762 return TRUE;
1765 gboolean ref2iter(GtkTreeModel * model, GtkTreeRowReference * ref, GtkTreeIter * iter)
1767 gboolean res = FALSE;
1768 GtkTreePath *path = gtk_tree_row_reference_get_path(ref);
1770 if (gtk_tree_model_get_iter(model, iter, path))
1772 res = TRUE;
1774 gtk_tree_path_free(path);
1775 return (res);
1778 GtkTreeRowReference *iter2ref(GtkTreeModel * model, GtkTreeIter * iter)
1780 GtkTreeRowReference *ref;
1782 GtkTreePath *path = gtk_tree_model_get_path(model, iter);
1784 ref = gtk_tree_row_reference_new(model, path);
1785 gtk_tree_path_free(path);
1786 return (ref);
1789 void move_nodes_up(GtkTreeModel * model, GtkTreeRowReference * topnode, GtkTreeRowReference * newtop)
1791 GtkTreeIter topiter;
1793 if (ref2iter(model, topnode, &topiter) == FALSE)
1794 return;
1796 GtkTreeIter child;
1798 if (gtk_tree_model_iter_children(model, &child, &topiter))
1800 GtkTreeRowReference *ref;
1801 GList *rr_list = NULL, *node;
1805 ref = iter2ref(model, &child);
1806 rr_list = g_list_append(rr_list, ref);
1808 while(gtk_tree_model_iter_next(model, &child));
1811 * got a reflist for all children
1814 for(node = rr_list; node; node = node->next)
1816 ref = (GtkTreeRowReference *) (node->data);
1817 if (ref2iter(model, ref, &child))
1819 GtkTreeIter newtopiter, newiter;
1820 GtkTreeIter *newtopiterptr;
1822 if (ref2iter(model, newtop, &newtopiter))
1823 newtopiterptr = &newtopiter;
1824 else
1825 newtopiterptr = NULL;
1827 nodeData *node;
1829 gtk_tree_model_get(model, &child, NODE_DATA, &node, -1);
1831 gtk_tree_store_append(GTK_TREE_STORE(model), &newiter, newtopiterptr);
1832 gtk_tree_store_set(GTK_TREE_STORE(model), &newiter, NODE_NAME, node->name, NODE_PIXBUF, node->namepix, NODE_DATA, node, -1);
1834 GtkTreeRowReference *newref = iter2ref(model, &newiter);
1836 move_nodes_up(model, ref, newref);
1837 gtk_tree_row_reference_free(newref);
1839 gtk_tree_store_remove(GTK_TREE_STORE(model), &child);
1841 gtk_tree_row_reference_free(ref);
1844 g_list_free(rr_list);
1849 void callback_delete_node_real(MainView* mainview)
1851 GtkTreeIter iter;
1852 GtkTreeModel *model;
1854 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1856 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
1857 return;
1859 nodeData *nd;
1861 gtk_tree_model_get(model, &iter, NODE_DATA, &nd, -1);
1862 if (!nd)
1863 return;
1865 mainview->file_edited = TRUE;
1867 unsigned int sql3id = nd->sql3id;
1869 if (nd->name)
1870 g_free(nd->name);
1873 * g_free(nd->data);
1874 * if (nd->pix) g_object_unref(nd->pix);
1876 g_free(nd);
1878 GtkTreeRowReference *upref = NULL, *ref = NULL;
1880 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
1882 ref = gtk_tree_row_reference_new(model, path);
1883 if (gtk_tree_path_up(path))
1884 upref = gtk_tree_row_reference_new(model, path);
1885 gtk_tree_path_free(path);
1887 g_object_ref(model);
1888 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), NULL);
1890 move_nodes_up(model, ref, upref);
1892 if (ref2iter(model, ref, &iter))
1894 char tq[512];
1896 g_snprintf(tq, sizeof(tq), "SELECT parent FROM %s WHERE nodeid=%d", datatable_tmpname, sql3id);
1897 sqlite3_stmt *stmt = NULL;
1898 const char *dum;
1899 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
1900 unsigned int sql3parentid = 0;
1902 if (rc)
1904 maepad_warning("Error finding children for delete: %s", sqlite3_errmsg(mainview->db));
1906 else
1908 rc = SQLITE_BUSY;
1909 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
1911 rc = sqlite3_step(stmt);
1912 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
1913 break;
1914 else if (rc == SQLITE_ROW)
1916 sql3parentid = sqlite3_column_int(stmt, 0);
1917 break;
1920 sqlite3_finalize(stmt);
1922 g_snprintf(tq, sizeof(tq), "UPDATE %s SET parent=%d WHERE parent=%d;", datatable_tmpname, sql3parentid, sql3id);
1923 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
1924 maepad_warning("Error moving nodes up one level");
1925 } else
1927 g_snprintf(tq, sizeof(tq), "DELETE FROM %s WHERE nodeid=%d;", datatable_tmpname, sql3id);
1928 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
1929 maepad_warning("Error deleting node");
1932 /* Delete all checklist items that do not have
1933 * a node anymore (= orphaned checklist items) */
1934 g_snprintf(tq, sizeof(tq), "DELETE FROM %s WHERE nodeid NOT IN (SELECT nodeid FROM %s);", checklisttable_tmpname, datatable_tmpname);
1935 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
1936 maepad_warning("Error deleting orphaned checklist items");
1940 gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
1943 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), model);
1944 g_object_unref(model);
1946 gtk_tree_row_reference_free(ref);
1947 gtk_tree_row_reference_free(upref);
1949 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview->treeview));
1953 void callback_edit_clear(GtkAction * action, gpointer data)
1955 MainView *mainview = (MainView *) data;
1956 g_assert(mainview != NULL && mainview->data != NULL);
1957 nodeData *nd = getSelectedNode(mainview);
1959 if (show_confirmation(mainview, _("Remove all contents of this memo?"))) {
1960 switch (nd->typ) {
1961 case NODE_TEXT:
1962 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), "", 0);
1963 break;
1964 case NODE_SKETCH:
1965 sketchwidget_clear(mainview->sk);
1966 break;
1967 case NODE_CHECKLIST:
1968 gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview))));
1969 break;
1970 default:
1971 /* Unknown node type */
1972 g_assert(FALSE);
1978 * cut
1980 void callback_edit_cut(GtkAction * action, gpointer data)
1982 MainView *mainview = (MainView *) data;
1983 g_assert(mainview != NULL && mainview->data != NULL);
1985 nodeData *nd = getSelectedNode(mainview);
1987 if (nd->typ == NODE_TEXT)
1988 gtk_text_buffer_cut_clipboard(GTK_TEXT_BUFFER(mainview->buffer), mainview->clipboard, TRUE);
1989 else if (nd->typ == NODE_SKETCH)
1991 if (sketchwidget_cut(mainview->sk, mainview->clipboard)==FALSE)
1992 show_banner(mainview, _("Error cutting"));
1994 else if (nd->typ == NODE_CHECKLIST)
1995 show_banner(mainview, _("Unimplemented"));
2000 * copy
2002 void callback_edit_copy(GtkAction * action, gpointer data)
2004 MainView *mainview = (MainView *) data;
2005 g_assert(mainview != NULL && mainview->data != NULL);
2007 nodeData *nd = getSelectedNode(mainview);
2009 if (nd->typ == NODE_TEXT)
2010 gtk_text_buffer_copy_clipboard(GTK_TEXT_BUFFER(mainview->buffer), mainview->clipboard);
2011 else if (nd->typ == NODE_SKETCH)
2013 if (sketchwidget_copy(mainview->sk, mainview->clipboard)==FALSE)
2014 show_banner(mainview, _("Error copying"));
2016 else if (nd->typ == NODE_CHECKLIST)
2018 /* Copy all selected entries as multiline text (1 line per entry) */
2019 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
2020 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview));
2022 gint selected_rows = gtk_tree_selection_count_selected_rows(selection);
2023 GList* l = gtk_tree_selection_get_selected_rows(selection, NULL);
2025 GtkTreeIter iter;
2026 gchar *str_data;
2028 gchar **entries = g_malloc0(sizeof(gchar*)*selected_rows+1);
2029 gint entries_idx = 0;
2031 GList* cur = l;
2032 while(cur) {
2033 GtkTreePath *path = cur->data;
2035 if (gtk_tree_model_get_iter(model, &iter, path)) {
2036 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHECKNODE_TEXT, &(entries[entries_idx++]), -1);
2038 gtk_tree_path_free(path);
2040 cur = cur->next;
2043 g_list_free(l);
2044 str_data = g_strjoinv("\n", entries);
2045 g_strfreev(entries);
2046 gtk_clipboard_set_text(mainview->clipboard, str_data, -1);
2047 g_free(str_data);
2049 str_data = g_strdup_printf(_("Copied %d entries"), selected_rows);
2050 show_banner(mainview, str_data);
2051 g_free(str_data);
2057 * paste
2059 void callback_edit_paste(GtkAction * action, gpointer data)
2061 MainView *mainview = (MainView *) data;
2062 g_assert(mainview != NULL && mainview->data != NULL);
2064 nodeData *nd = getSelectedNode(mainview);
2066 if (nd->typ == NODE_TEXT)
2067 gtk_text_buffer_paste_clipboard(GTK_TEXT_BUFFER(mainview->buffer), mainview->clipboard, NULL, TRUE);
2068 else if (nd->typ == NODE_SKETCH)
2070 if (sketchwidget_paste(mainview->sk, mainview->clipboard)==FALSE)
2071 show_banner(mainview, _("Error pasting"));
2073 else if (nd->typ == NODE_CHECKLIST) {
2074 /* Paste string from clipboard as new item */
2075 callback_checklist_paste(mainview);
2078 mainview->file_edited = TRUE;
2081 gint cb_popup(GtkWidget * widget, GdkEvent * event)
2083 GtkMenu *menu;
2084 GdkEventButton *event_button;
2087 * The "widget" is the menu that was supplied when
2088 * * g_signal_connect_swapped() was called.
2090 menu = GTK_MENU(widget);
2091 event_button = (GdkEventButton *) event;
2092 if (event->type == GDK_BUTTON_PRESS && event_button->button == 3)
2094 gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event_button->button, event_button->time);
2095 return TRUE;
2097 return FALSE;
2101 * close
2103 gboolean closefile(MainView * mainview)
2105 saveCurrentData(mainview);
2107 if (mainview->file_edited)
2109 HildonNote *hn = HILDON_NOTE(hildon_note_new_confirmation_add_buttons(GTK_WINDOW(mainview->data->main_view), _("Save changes?"), _("Yes"), CONFRESP_YES, _("No"), CONFRESP_NO, _("Cancel"), CONFRESP_CANCEL, NULL, NULL));
2110 gint answer = gtk_dialog_run(GTK_DIALOG(hn));
2111 gtk_widget_destroy(GTK_WIDGET(hn));
2113 if (answer == CONFRESP_CANCEL)
2114 return (FALSE);
2115 else if (answer == CONFRESP_YES)
2117 if (mainview->file_name == NULL)
2119 mainview->file_name = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, "maemopaddata", "db");
2121 write_buffer_to_file(mainview);
2125 if (mainview->db)
2126 sqlite3_close(mainview->db);
2127 mainview->db = NULL;
2128 return (TRUE);
2131 gboolean callback_file_close(GtkAction * action, gpointer data)
2134 MainView *mainview = (MainView *) data;
2135 g_assert(mainview != NULL && mainview->data != NULL);
2136 if (closefile(mainview) == FALSE)
2137 return(FALSE);
2139 gtk_main_quit();
2140 return(TRUE);
2143 void callback_file_new_node(GtkAction * action, gpointer data)
2145 MainView *mainview = (MainView *) data;
2146 g_assert(mainview != NULL && mainview->data != NULL);
2148 nodeType typ = NODE_SKETCH;
2150 nodeData *nd = getSelectedNode(mainview);
2152 if (nd != NULL)
2153 typ = nd->typ;
2155 new_node_dialog(typ, mainview);
2159 * new
2161 void callback_file_new(GtkAction * action, gpointer data)
2163 MainView *mainview = (MainView *) data;
2164 g_assert(mainview != NULL && mainview->data != NULL);
2166 gchar *filename = NULL;
2168 if (closefile(mainview) == FALSE)
2169 return;
2171 filename = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, "memos", "db");
2172 if (filename == NULL)
2173 return;
2175 new_file(mainview);
2179 busy_enter(mainview);
2181 int rc;
2183 rc = sqlite3_open(filename, &mainview->db);
2184 if (rc)
2186 show_banner(mainview, _("Cannot create database"));
2187 maepad_warning("Can't create database %s: %s", filename, sqlite3_errmsg(mainview->db));
2188 break;
2191 sqlite3_exec(mainview->db, "PRAGMA synchronous = OFF;", NULL, NULL, NULL);
2193 char tq[512];
2195 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", misctable_name, misctable);
2196 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
2198 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", datatable_name, datatable);
2199 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
2201 maepad_warning("Cannot create data table");
2202 show_banner(mainview, _("Error creating data table"));
2203 break;
2206 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", checklisttable_name, checklisttable);
2207 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
2209 maepad_warning("Cannot create checklist table");
2210 show_banner(mainview, _("Error creating checklist table"));
2211 break;
2214 if (mainview->db)
2215 sqlite3_close(mainview->db);
2216 mainview->db = NULL;
2218 mainview->file_name = filename;
2219 mainview->file_edited = FALSE;
2220 read_file_to_buffer(mainview);
2222 /*add a starter memo*/
2223 nodeData *node;
2224 node = g_malloc(sizeof(nodeData));
2225 node->typ = NODE_SKETCH;
2226 node->name = _("My first memo");
2227 node->namepix = NULL;
2228 node->lastMod = 0;
2229 node->flags = 0;
2230 node->sql3id = 0;
2231 add_new_node(node, mainview, TRUE);
2232 /*gtk_paned_set_position(GTK_PANED(mainview->hpaned), 180);*/
2233 write_buffer_to_file(mainview);
2235 }while(FALSE);
2236 busy_reset(mainview);
2239 gboolean reset_ctree(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter, gpointer data)
2241 nodeData *node;
2243 gtk_tree_model_get(model, iter, NODE_DATA, &node, -1);
2244 if (node)
2246 if (node->name)
2247 g_free(node->name);
2248 if (node->namepix)
2249 g_object_unref(node->namepix);
2250 g_free(node);
2252 gtk_tree_store_set(GTK_TREE_STORE(model), iter, NODE_DATA, NULL, -1);
2254 return (FALSE);
2257 void new_file(MainView * mainview)
2259 busy_enter(mainview);
2261 * clear buffer, filename and free buffer text
2263 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), "", -1);
2264 mainview->file_name = NULL;
2265 mainview->file_edited = FALSE;
2266 mainview->newnodedialog_createchild = TRUE;
2268 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview));
2270 g_object_ref(model);
2271 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), NULL);
2273 gtk_tree_model_foreach(model, (GtkTreeModelForeachFunc) reset_ctree, (gpointer) mainview);
2276 * crashing bastard
2277 * gtk_tree_store_clear(GTK_TREE_STORE(model));
2279 GtkTreePath *path = gtk_tree_path_new_from_indices(0, -1);
2280 GtkTreeIter iter;
2282 if (gtk_tree_model_get_iter(model, &iter, path))
2286 gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
2288 while(gtk_tree_store_iter_is_valid(GTK_TREE_STORE(model), &iter));
2290 gtk_tree_path_free(path);
2292 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), model);
2293 g_object_unref(model);
2295 prepareUIforNodeChange(mainview, NODE_UNKNOWN);
2296 busy_leave(mainview);
2300 * open
2302 void callback_file_open(GtkAction * action, gpointer data)
2304 gchar *filename = NULL;
2305 MainView *mainview = (MainView *) data;
2306 g_assert(mainview != NULL && mainview->data != NULL);
2308 if (closefile(mainview) == FALSE)
2309 return;
2312 * open new file
2314 filename = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_OPEN, NULL, NULL);
2317 * if we got a file name from chooser -> open file
2319 open_file(filename, mainview);
2320 g_free(filename);
2323 gboolean open_file(gchar * filename, MainView * mainview)
2325 gboolean ret=FALSE;
2327 busy_enter(mainview);
2329 while(filename != NULL)
2331 struct stat s;
2333 if (stat(filename, &s) == -1) break;
2335 mainview->file_name = g_strdup(filename);
2336 gboolean res = read_file_to_buffer(mainview);
2338 if (res == FALSE)
2340 g_free(mainview->file_name);
2341 mainview->file_name = NULL;
2342 break;
2344 mainview->file_edited = FALSE;
2345 ret=TRUE;
2346 break;
2349 busy_leave(mainview);
2350 return(ret);
2353 void callback_about_link(GtkAboutDialog *about, const gchar *link, gpointer data)
2355 MainView *mainview = (MainView *) data;
2356 g_assert(mainview != NULL && mainview->data != NULL);
2357 osso_rpc_run_with_defaults(mainview->data->osso, "osso_browser", OSSO_BROWSER_OPEN_NEW_WINDOW_REQ, NULL,
2358 DBUS_TYPE_STRING, link, DBUS_TYPE_INVALID);
2361 void callback_about(GtkAction * action, gpointer data)
2363 MainView* mainview = (MainView *)data;
2364 he_about_dialog_present(mainview_get_dialog_parent(mainview),
2365 NULL /* auto-detect app name */,
2366 "maepad",
2367 VERSION,
2368 _("A node-based memory pad for Maemo"),
2369 _("(c) 2008-2010 Thomas Perl, (c) 2006-2008 Kemal Hadimli"),
2370 "http://thpinfo.com/2010/maepad/",
2371 NULL /* TODO: Add bug tracker URL */,
2372 "http://thpinfo.com/2010/maepad/donate");
2376 * save
2378 void callback_file_save(GtkAction * action, gpointer data)
2380 gchar *filename = NULL;
2381 MainView *mainview = (MainView *) data;
2382 g_assert(mainview != NULL && mainview->data != NULL);
2385 * check is we had a new file
2387 if (mainview->file_name != NULL)
2389 write_buffer_to_file(mainview);
2391 else
2393 filename = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, "maemopaddata", "db");
2395 * if we got a file name from chooser -> save file
2397 if (filename != NULL)
2399 mainview->file_name = filename;
2400 write_buffer_to_file(mainview);
2401 mainview->file_edited = FALSE;
2406 void callback_shapemenu(GtkAction * action, GtkWidget * wid)
2408 int style = (int)gtk_object_get_user_data(GTK_OBJECT(wid));
2409 MainView *mainview = gtk_object_get_data(GTK_OBJECT(wid), "m");
2411 g_assert(mainview != NULL);
2413 if (style==0) sketchwidget_set_shape(mainview->sk, SKETCHSHAPE_FREEHAND);
2414 else if (style==1) sketchwidget_set_shape(mainview->sk, SKETCHSHAPE_LINE);
2415 else if (style==2) sketchwidget_set_shape(mainview->sk, SKETCHSHAPE_RECT);
2416 else if (style==3) sketchwidget_set_shape(mainview->sk, SKETCHSHAPE_ELLIPSE);
2421 void callback_eraser(GtkAction * action, MainView * mainview)
2423 g_assert(mainview != NULL && mainview->data != NULL);
2425 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mainview->eraser_tb)) == TRUE)
2427 GdkColor c2;
2429 c2.red = 65535;
2430 c2.green = 65535;
2431 c2.blue = 65535;
2433 mainview->sk->pressuresensitivity=FALSE;
2435 sketchwidget_set_brushcolor(mainview->sk, c2);
2436 mainview->brushsize_backup = sketchwidget_get_brushsize(mainview->sk);
2437 guint ers=(mainview->brushsize_backup*4)+4;
2438 sk_set_brushsize(mainview, ers);
2439 sketchwidget_set_brushsize(mainview->sk, ers); /*fixme:to override max brush size, not pretty*/
2441 else
2443 if (mainview->current_color == NULL) {
2444 GdkColor color = {0, 0, 0, 0};
2445 mainview->current_color = gdk_color_copy(&color);
2447 /* pressure sensitivity disabled for now...
2448 mainview->sk->pressuresensitivity=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(mainview->tools_pressure));*/
2450 sketchwidget_set_brushcolor(mainview->sk, *(mainview->current_color));
2451 sk_set_brushsize(mainview, mainview->brushsize_backup);
2455 void callback_menu(GtkAction * action, GtkWidget * menu)
2457 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, GDK_CURRENT_TIME);
2460 void callback_brushsizetb(GtkAction * action, MainView *mainview)
2462 g_assert(mainview != NULL && mainview->data != NULL);
2464 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mainview->eraser_tb)) == TRUE)
2466 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->eraser_tb), FALSE);
2468 else
2470 callback_menu(NULL, mainview->brushsizemenu);
2474 void callback_brushsize(GtkAction * action, GtkWidget * wid)
2476 int bsize = (int)gtk_object_get_user_data(GTK_OBJECT(wid));
2477 MainView *mainview = gtk_object_get_data(GTK_OBJECT(wid), "m");
2479 g_assert(mainview != NULL && mainview->data != NULL);
2481 sketchwidget_set_brushsize(mainview->sk, bsize);
2483 GtkWidget *pix = gtk_object_get_data(GTK_OBJECT(wid), "i");
2485 gtk_widget_show(pix);
2486 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview->brushsize_tb), pix);
2489 void callback_sketchlines(GtkAction * action, GtkWidget * wid)
2491 int style = (int)gtk_object_get_user_data(GTK_OBJECT(wid));
2492 MainView *mainview = gtk_object_get_data(GTK_OBJECT(wid), "m");
2494 g_assert(mainview != NULL);
2496 nodeData *nd = getSelectedNode(mainview);
2497 gboolean doit = FALSE;
2499 if (nd != NULL && nd->typ == NODE_SKETCH)
2501 nd->flags &= ~NODEFLAG_SKETCHLINES;
2502 nd->flags &= ~NODEFLAG_SKETCHGRAPH;
2503 /* sketchwidget_set_edited(mainview->sk, TRUE);*/ /*we call this on openfile, so this messes things up*/
2504 doit = TRUE;
2507 if (style == 0)
2509 sketchwidget_set_backstyle(mainview->sk, SKETCHBACK_NONE);
2511 else if (style == 1)
2513 sketchwidget_set_backstyle(mainview->sk, SKETCHBACK_LINES);
2514 if (doit == TRUE)
2515 nd->flags |= NODEFLAG_SKETCHLINES;
2517 else if (style == 2)
2519 sketchwidget_set_backstyle(mainview->sk, SKETCHBACK_GRAPH);
2520 if (doit == TRUE)
2521 nd->flags |= NODEFLAG_SKETCHGRAPH;
2524 GtkWidget *pix = gtk_object_get_data(GTK_OBJECT(wid), "i");
2526 gtk_widget_show(pix);
2527 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview->sketchlines_tb), pix);
2530 void callback_color(GtkAction* action, MainView* mainview)
2532 g_assert(mainview != NULL && mainview->data != NULL);
2534 nodeData *nd = getSelectedNode(mainview);
2535 if (nd == NULL) return;
2537 HeSimpleColorDialog* dialog = HE_SIMPLE_COLOR_DIALOG(he_simple_color_dialog_new());
2538 gtk_window_set_transient_for(GTK_WINDOW(dialog), mainview_get_dialog_parent(mainview));
2540 if (mainview->current_color) {
2541 he_simple_color_dialog_set_color(dialog, mainview->current_color);
2544 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
2545 gtk_widget_destroy(GTK_WIDGET(dialog));
2546 return;
2549 gdk_color_free(mainview->current_color);
2550 mainview->current_color = he_simple_color_dialog_get_color(dialog);
2552 gtk_widget_destroy(GTK_WIDGET(dialog));
2554 switch (nd->typ) {
2555 case NODE_SKETCH:
2556 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->eraser_tb), FALSE);
2557 sketchwidget_set_brushcolor(mainview->sk, *(mainview->current_color));
2558 break;
2559 case NODE_CHECKLIST:
2560 { /* Put in a separate block to allow new local variables */
2561 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
2562 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview));
2563 GList* selected = gtk_tree_selection_get_selected_rows(selection, NULL);
2565 gchar* color_string = g_strdup_printf("#%02x%02x%02x",
2566 mainview->current_color->red >> 8,
2567 mainview->current_color->green >> 8,
2568 mainview->current_color->blue >> 8);
2570 GList* cur = selected;
2571 while (cur != NULL) {
2572 GtkTreePath* path = cur->data;
2573 GtkTreeIter iter;
2574 if (gtk_tree_model_get_iter(model, &iter, path)) {
2575 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_COLOR, color_string, -1);
2577 gtk_tree_path_free(path);
2578 cur = cur->next;
2581 g_list_free(selected);
2582 g_free(color_string);
2584 break;
2585 default:
2586 g_error("Wrong node type for color selection");
2587 return;
2591 void callback_color_invoke(GtkAction * action, gpointer data)
2593 MainView *mainview = (MainView *) data;
2594 g_assert(mainview != NULL && mainview->data != NULL);
2595 gtk_button_clicked(GTK_BUTTON(mainview->colorbutton_tb));
2600 void callback_pressure(GtkAction * action, MainView *mainview)
2602 g_assert(mainview != NULL && mainview->data != NULL);
2604 nodeData *nd = getSelectedNode(mainview);
2606 if (nd == NULL)
2607 return;
2608 if (nd->typ != NODE_SKETCH)
2609 return;
2611 /* pressure sensitivity disabled for now...
2612 mainview->sk->pressuresensitivity=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(mainview->tools_pressure));*/
2616 void callback_wordwrap(GtkAction * action, MainView *mainview)
2618 g_assert(mainview != NULL && mainview->data != NULL);
2620 nodeData *nd = getSelectedNode(mainview);
2622 if (nd == NULL)
2623 return;
2624 if (nd->typ != NODE_TEXT)
2625 return;
2627 gboolean act=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(mainview->tools_wordwrap));
2628 if (act==TRUE) nd->flags |= NODEFLAG_WORDWRAP;
2629 else nd->flags &= ~NODEFLAG_WORDWRAP;
2631 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(mainview->textview), (act==TRUE)?GTK_WRAP_WORD:GTK_WRAP_NONE);
2635 void callback_font(GtkAction * action, gpointer data)
2637 MainView *mainview = (MainView *) data;
2638 g_assert(mainview != NULL && mainview->data != NULL);
2640 nodeData *nd = getSelectedNode(mainview);
2642 if (nd == NULL)
2643 return;
2644 if (nd->typ != NODE_TEXT)
2645 return;
2647 HildonFontSelectionDialog *dialog = HILDON_FONT_SELECTION_DIALOG(hildon_font_selection_dialog_new(NULL, NULL));
2649 gboolean gotsel=wp_text_buffer_has_selection(mainview->buffer);
2650 /*gotsel=FALSE;*/
2652 WPTextBufferFormat fmt;
2653 wp_text_buffer_get_attributes(mainview->buffer, &fmt, gotsel);
2655 gint ri=0;
2656 if (fmt.text_position==TEXT_POSITION_SUPERSCRIPT) ri=1;
2657 else if (fmt.text_position==TEXT_POSITION_SUBSCRIPT) ri=-1;
2659 g_object_set(G_OBJECT(dialog),
2660 "family-set", fmt.cs.font,
2661 "family", wp_get_font_name(fmt.font),
2662 "size-set", fmt.cs.font_size,
2663 "size", wp_font_size[fmt.font_size],
2664 "color-set", fmt.cs.color,
2665 "color", &fmt.color,
2666 "bold-set", fmt.cs.bold,
2667 "bold", fmt.bold,
2668 "italic-set", fmt.cs.italic,
2669 "italic", fmt.italic,
2670 "underline-set", fmt.cs.underline,
2671 "underline", fmt.underline,
2672 "strikethrough-set", fmt.cs.strikethrough,
2673 "strikethrough", fmt.strikethrough,
2674 "position-set", fmt.cs.text_position,
2675 "position", ri,
2676 NULL);
2678 gtk_widget_show_all(GTK_WIDGET(dialog));
2679 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
2681 gboolean bold, italic, underline, strikethrough;
2682 gchar *family = NULL;
2683 gint size, position;
2684 GdkColor *color=NULL;
2685 gboolean set_family, set_size, set_bold, set_italic, set_underline, set_strikethrough, set_color, set_position;
2687 g_object_get(G_OBJECT(dialog), "family", &family, "size", &size, "bold", &bold, "italic", &italic,
2688 "underline", &underline, "strikethrough", &strikethrough,
2689 "family-set", &set_family, "size-set", &set_size, "bold-set", &set_bold, "italic-set", &set_italic,
2690 "underline-set", &set_underline, "strikethrough-set", &set_strikethrough,
2691 "color", &color, "color-set", &set_color, "position", &position, "position-set", &set_position,
2692 NULL);
2694 wp_text_buffer_get_attributes(mainview->buffer, &fmt, FALSE);
2695 fmt.cs.font=fmt.cs.font_size=fmt.cs.strikethrough=fmt.cs.color=fmt.cs.bold=fmt.cs.italic=fmt.cs.underline=fmt.cs.text_position=0;
2697 if (set_family) { fmt.font=wp_get_font_index(family, 1); fmt.cs.font=1; }
2698 if (set_size) { fmt.font_size=wp_get_font_size_index(size, 16); fmt.cs.font_size=1; }
2700 if (set_strikethrough)
2702 fmt.cs.strikethrough=1;
2703 fmt.strikethrough=strikethrough;
2706 if (set_color)
2709 GLIB WARNING ** GLib-GObject - IA__g_object_set_valist: object class `GtkTextTag' has no property named `'
2711 fmt.cs.color=1;
2712 fmt.color.pixel=color->pixel;
2713 fmt.color.red=color->red;
2714 fmt.color.green=color->green;
2715 fmt.color.blue=color->blue;
2718 if (set_position)
2720 if (position==1) ri=TEXT_POSITION_SUPERSCRIPT;
2721 else if (position==-1) ri=TEXT_POSITION_SUBSCRIPT;
2722 else ri=TEXT_POSITION_NORMAL;
2724 fmt.cs.text_position=1;
2725 fmt.text_position=ri;
2728 if (set_bold)
2730 fmt.cs.bold=1;
2731 fmt.bold=bold;
2733 if (set_italic)
2735 fmt.cs.italic=1;
2736 fmt.italic=italic;
2738 if (set_underline)
2740 fmt.cs.underline=1;
2741 fmt.underline=underline;
2744 wp_text_buffer_set_format(mainview->buffer, &fmt);
2747 gtk_widget_destroy(GTK_WIDGET(dialog));
2750 void callback_fontstyle(GtkAction * action, GtkWidget * wid)
2752 MainView *mainview = gtk_object_get_data(GTK_OBJECT(wid), "m");
2753 g_assert(mainview != NULL && mainview->data != NULL);
2755 nodeData *nd = getSelectedNode(mainview);
2757 if (nd == NULL)
2758 return;
2759 if (nd->typ == NODE_TEXT)
2761 gboolean act=gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(wid));
2763 gint style = (gint)gtk_object_get_data(GTK_OBJECT(wid), "s");
2764 wp_text_buffer_set_attribute(mainview->buffer, style, (gpointer)act);
2766 else if (nd->typ == NODE_CHECKLIST)
2768 gboolean act=gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(wid));
2769 gint style = (gint)gtk_object_get_data(GTK_OBJECT(wid), "s");
2770 if (style!=WPT_BOLD && style!=WPT_STRIKE && style!=WPT_LEFT) return;
2772 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
2773 GList* l=gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview)), NULL);
2775 gint styletoset_weight=PANGO_WEIGHT_NORMAL;
2776 gboolean styletoset_strike=FALSE;
2777 gboolean checkit=FALSE;
2779 if (style==WPT_BOLD && act==TRUE) styletoset_weight=PANGO_WEIGHT_BOLD;
2780 else if (style==WPT_STRIKE && act==TRUE) styletoset_strike=TRUE;
2781 else if (style==WPT_LEFT && act==TRUE) checkit=TRUE;
2783 GList* cur=l;
2784 while(cur)
2786 GtkTreePath *path=cur->data;
2788 GtkTreeIter iter;
2789 if (gtk_tree_model_get_iter(model, &iter, path))
2791 if (style==WPT_BOLD) gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_BOLD, styletoset_weight, -1);
2792 else if (style==WPT_STRIKE) gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_STRIKE, styletoset_strike, -1);
2793 else if (style==WPT_LEFT) {
2794 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_CHECKED, checkit, -1);
2795 if (checkit) {
2796 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_ICON_NAME, "widgets_tickmark_list", -1);
2797 } else {
2798 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_ICON_NAME, NULL, -1);
2802 gtk_tree_path_free(path);
2803 cur=cur->next;
2806 g_list_free(l);
2807 mainview->checklist_edited = TRUE;
2812 void callback_textbuffer_move(WPTextBuffer *textbuffer, MainView *mainview)
2814 g_assert(mainview != NULL && mainview->data != NULL);
2817 gboolean gotsel=wp_text_buffer_has_selection(mainview->buffer);
2819 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), gotsel);
2820 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->italic_tb), gotsel);
2821 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->underline_tb), gotsel);
2822 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->bullet_tb), gotsel);
2824 WPTextBufferFormat fmt;
2825 wp_text_buffer_get_attributes(mainview->buffer, &fmt, FALSE/*gotsel*/);
2827 g_signal_handlers_block_by_func(mainview->bold_tb, callback_fontstyle, mainview->bold_tb);
2828 g_signal_handlers_block_by_func(mainview->italic_tb, callback_fontstyle, mainview->italic_tb);
2829 g_signal_handlers_block_by_func(mainview->underline_tb, callback_fontstyle, mainview->underline_tb);
2830 g_signal_handlers_block_by_func(mainview->bullet_tb, callback_fontstyle, mainview->bullet_tb);
2832 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), fmt.bold);
2833 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->italic_tb), fmt.italic);
2834 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->underline_tb), fmt.underline);
2835 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->bullet_tb), fmt.bullet);
2837 g_signal_handlers_unblock_by_func(mainview->bold_tb, callback_fontstyle, mainview->bold_tb);
2838 g_signal_handlers_unblock_by_func(mainview->italic_tb, callback_fontstyle, mainview->italic_tb);
2839 g_signal_handlers_unblock_by_func(mainview->underline_tb, callback_fontstyle, mainview->underline_tb);
2840 g_signal_handlers_unblock_by_func(mainview->bullet_tb, callback_fontstyle, mainview->bullet_tb);
2843 gint wp_savecallback(const gchar *buffer, GString * gstr)
2845 gstr=g_string_append(gstr, buffer);
2846 return(0);
2849 void callback_undo(GtkAction * action, MainView * mainview)
2851 g_assert(mainview != NULL && mainview->data != NULL);
2853 nodeData *nd = getSelectedNode(mainview);
2855 if (nd == NULL) return;
2857 if (nd->typ == NODE_SKETCH) sketchwidget_undo(mainview->sk);
2858 else if (nd->typ == NODE_TEXT) wp_text_buffer_undo(mainview->buffer);
2861 void callback_redo(GtkAction * action, MainView * mainview)
2863 g_assert(mainview != NULL && mainview->data != NULL);
2865 nodeData *nd = getSelectedNode(mainview);
2867 if (nd == NULL) return;
2869 if (nd->typ == NODE_SKETCH) sketchwidget_redo(mainview->sk);
2870 else if (nd->typ == NODE_TEXT) wp_text_buffer_redo(mainview->buffer);
2873 void callback_undotoggle(gpointer widget, gboolean st, MainView * mainview)
2875 g_assert(mainview != NULL && mainview->data != NULL);
2877 gtk_widget_set_sensitive(GTK_WIDGET(mainview->undo_tb), st);
2880 void callback_redotoggle(gpointer widget, gboolean st, MainView * mainview)
2882 g_assert(mainview != NULL && mainview->data != NULL);
2884 gtk_widget_set_sensitive(GTK_WIDGET(mainview->redo_tb), st);
2887 gboolean close_cb(GtkWidget * widget, GdkEventAny * event, MainView * mainview)
2889 callback_file_close(NULL, mainview);
2890 return (TRUE);
2893 gboolean key_press_cb(GtkWidget * widget, GdkEventKey * event, MainView * mainview)
2895 switch (event->keyval)
2899 * case GDK_Up:
2900 * gtk_infoprint(GTK_WINDOW(app), "Navigation Key Up");
2901 * return TRUE;
2903 * case GDK_Down:
2904 * gtk_infoprint(GTK_WINDOW(app), "Navigation Key Down");
2905 * return TRUE;
2907 * case GDK_Left:
2908 * gtk_infoprint(GTK_WINDOW(app), "Navigation Key Left");
2909 * return TRUE;
2911 * case GDK_Right:
2912 * gtk_infoprint(GTK_WINDOW(app), "Navigation Key Right");
2913 * return TRUE;
2915 * case GDK_Return:
2916 * gtk_infoprint(GTK_WINDOW(app), "Navigation Key select");
2917 * return TRUE;
2919 /*code below messes up when you have a textview*/
2921 case GDK_Left:
2922 case GDK_Right:
2924 gtk_widget_child_focus(widget, event->keyval==GDK_Left?GTK_DIR_TAB_BACKWARD:GTK_DIR_TAB_FORWARD);
2925 return TRUE;
2928 case GDK_Left:
2930 nodeData *selnode = getSelectedNode(mainview);
2931 if (selnode!=NULL && selnode->typ==NODE_SKETCH)
2933 show_banner(mainview, _("Squared shapes ON"));
2934 sketchwidget_set_shift(mainview->sk, TRUE);
2935 return TRUE;
2937 return FALSE;
2939 case GDK_Right:
2941 nodeData *selnode = getSelectedNode(mainview);
2942 if (selnode!=NULL && selnode->typ==NODE_SKETCH)
2944 show_banner(mainview, _("Squared shapes OFF"));
2945 sketchwidget_set_shift(mainview->sk, FALSE);
2946 return TRUE;
2948 return FALSE;
2950 case GDK_Down:
2952 nodeData *selnode = getSelectedNode(mainview);
2953 if (selnode!=NULL && selnode->typ==NODE_SKETCH)
2955 show_banner(mainview, _("Filled shapes OFF"));
2956 sketchwidget_set_fillmode(mainview->sk, FALSE);
2957 return TRUE;
2959 return FALSE;
2961 case GDK_Up:
2963 nodeData *selnode = getSelectedNode(mainview);
2964 if (selnode!=NULL && selnode->typ==NODE_SKETCH)
2966 show_banner(mainview, _("Filled shapes ON"));
2967 sketchwidget_set_fillmode(mainview->sk, TRUE);
2968 return TRUE;
2970 return FALSE;
2972 case GDK_F7:
2974 callback_redo(NULL, mainview);
2975 return TRUE;
2977 case GDK_F8:
2979 callback_undo(NULL, mainview);
2980 return TRUE;
2984 return FALSE;
2987 void callback_fullscreen(GtkToolButton* tool_button, gpointer user_data)
2989 MainView* mainview = (MainView*)user_data;
2990 gtk_window_fullscreen(GTK_WINDOW(mainview->data->node_view));
2993 void callback_buffer_modified(GtkAction * action, gpointer data)
2995 MainView *mainview = (MainView *) data;
2996 g_assert(mainview != NULL && mainview->data != NULL);
2998 mainview->file_edited = TRUE;
3001 GtkTreeRowReference *read_sqlite3_data(MainView * mainview, unsigned int parentid, GtkTreeRowReference * parenttree, unsigned int selected, GtkTreeStore * model)
3003 GtkTreeRowReference *resref = NULL;
3005 char q[256];
3007 g_snprintf(q, sizeof(q), "SELECT nodeid, bodytype, name, nameblob, lastmodified, flags FROM %s WHERE parent=%d ORDER BY ord", datatable_tmpname, parentid);
3009 sqlite3_stmt *stmt = NULL;
3010 const char *dum;
3011 int rc = sqlite3_prepare(mainview->db, q, strlen(q), &stmt, &dum);
3013 if (rc)
3015 maepad_warning("Error reading SQLite3 data: %s", sqlite3_errmsg(mainview->db));
3016 return (NULL);
3019 rc = SQLITE_BUSY;
3020 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
3022 rc = sqlite3_step(stmt);
3023 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
3024 break;
3025 else if (rc == SQLITE_ROW)
3027 int nodeid = sqlite3_column_int(stmt, 0);
3028 int typ = sqlite3_column_int(stmt, 1);
3029 const unsigned char *name = sqlite3_column_text(stmt, 2);
3030 const unsigned char *nameblob = sqlite3_column_text(stmt, 3);
3031 int lastmod = sqlite3_column_int(stmt, 4);
3032 int flags = sqlite3_column_int(stmt, 5);
3034 if ((typ != NODE_TEXT && typ != NODE_SKETCH && typ != NODE_CHECKLIST) || (name == NULL && nameblob == NULL)) {
3035 maepad_warning("Unknown node type in database: %d (skipping)", typ);
3036 continue;
3039 nodeData *node = g_malloc(sizeof(nodeData));
3041 node->sql3id = nodeid;
3042 node->typ = typ;
3043 node->flags = flags;
3044 node->name = NULL;
3045 node->namepix = NULL;
3046 if (name != NULL) {
3047 node->name = g_strdup((char *)name);
3048 } else {
3049 node->name = g_strdup(_("Unnamed node"));
3051 /*if (nameblob != NULL)
3053 int blobsize = sqlite3_column_bytes(stmt, 3);
3055 GdkPixbufLoader *pl = gdk_pixbuf_loader_new_with_type("png", NULL);
3056 GError *err = NULL;
3058 gdk_pixbuf_loader_write(pl, (guchar *) nameblob, blobsize, &err);
3059 if (err != NULL)
3061 fprintf(stderr, "Error loading nodename! %s\n", err->message);
3062 g_error_free(err);
3063 err = NULL;
3065 gdk_pixbuf_loader_close(pl, NULL);
3066 GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(pl);
3068 if (GDK_IS_PIXBUF(pixbuf))
3069 node->namepix = pixbuf;
3071 node->lastMod = lastmod;
3073 GtkTreeIter parentiter, newiter;
3074 void *par = NULL;
3076 if (parenttree != NULL)
3078 GtkTreePath *pa = gtk_tree_row_reference_get_path(parenttree);
3080 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &parentiter, pa);
3081 gtk_tree_path_free(pa);
3082 par = &parentiter;
3085 gtk_tree_store_append(model, &newiter, par);
3086 gtk_tree_store_set(model, &newiter, NODE_NAME, node->name, NODE_PIXBUF, node->namepix, NODE_DATA, node, -1);
3088 GtkTreePath *pa = gtk_tree_model_get_path(GTK_TREE_MODEL(model), &newiter);
3090 GtkTreeRowReference *newref = gtk_tree_row_reference_new(GTK_TREE_MODEL(model), pa);
3092 if (selected == nodeid)
3093 resref = newref;
3095 gtk_tree_path_free(pa);
3096 GtkTreeRowReference *r = read_sqlite3_data(mainview, nodeid, newref, selected,
3097 model);
3099 if (resref != newref)
3100 gtk_tree_row_reference_free(newref);
3102 if (r != NULL)
3104 if (resref == NULL)
3105 resref = r;
3106 else
3107 gtk_tree_row_reference_free(r); /*safeguard */
3112 if (stmt)
3113 sqlite3_finalize(stmt);
3115 return (resref); /*ref to supposed-to-be-selected treeitem */
3119 * read file
3121 gboolean read_file_to_buffer(MainView * mainview)
3123 char tq[512];
3125 g_assert(mainview != NULL);
3126 gboolean res = FALSE;
3128 gchar *filename = mainview->file_name;
3130 new_file(mainview);
3131 mainview->file_name = filename;
3132 mainview->loading=TRUE;
3134 maepad_message("Reading database file: %s", filename);
3136 int rc;
3137 sqlite3_stmt *stmt = NULL;
3139 rc = sqlite3_open(filename, &mainview->db);
3142 if (rc)
3144 maepad_warning("Cannot open database %s: %s", filename, sqlite3_errmsg(mainview->db));
3145 break;
3148 sqlite3_exec(mainview->db, "PRAGMA synchronous = OFF;", NULL, NULL, NULL);
3150 char *q = "SELECT skey, sval FROM settings";
3151 const char *dum;
3153 rc = sqlite3_prepare(mainview->db, q, strlen(q), &stmt, &dum);
3154 if (rc)
3156 maepad_warning("Error reading settings: %s", sqlite3_errmsg(mainview->db));
3157 break;
3160 unsigned int selectedCard = 0;
3161 unsigned int curDataVersion = 0;
3162 unsigned int curChecklistVersion = 0;
3164 rc = SQLITE_BUSY;
3165 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
3167 rc = sqlite3_step(stmt);
3168 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
3169 break;
3170 else if (rc == SQLITE_ROW)
3172 const gchar* col_key = (const gchar*)sqlite3_column_text(stmt, 0);
3173 const gchar* col_val = (const gchar*)sqlite3_column_text(stmt, 1);
3174 if (!strcmp(col_key, "selectedNode"))
3176 gint tmp = atoi((char *)col_val);
3178 if (tmp > 0)
3179 selectedCard = tmp;
3181 if (!strcmp(col_key, "dataVersion"))
3183 gint tmp = atoi((char *)col_val);
3185 if (tmp > 0)
3186 curDataVersion = tmp;
3188 if (!strcmp(col_key, "checklistVersion"))
3190 gint tmp = atoi((char *)col_val);
3192 if (tmp > 0)
3193 curChecklistVersion = tmp;
3195 if (!strcmp(col_key, "newNodeDlgCreateChild"))
3197 gint tmp = atoi((char *)col_val);
3199 mainview->newnodedialog_createchild = TRUE;
3200 if (tmp == 0)
3201 mainview->newnodedialog_createchild = FALSE;
3203 if (!strcmp(col_key, "brushSize"))
3205 gint tmp = atoi((char *)col_val);
3206 if (tmp>0) sk_set_brushsize(mainview, tmp);
3208 if (!strcmp(col_key, "brushColor"))
3210 unsigned long tmp = atol((char *)col_val);
3211 GdkColor c2;
3213 c2.red = ((tmp & 0xFF0000) >> 16) << 8;
3214 c2.green = ((tmp & 0xFF00) >> 8) << 8;
3215 c2.blue = (tmp & 0xFF) << 8;
3216 sketchwidget_set_brushcolor(mainview->sk, c2);
3218 if (mainview->current_color != NULL) {
3219 gdk_color_free(mainview->current_color);
3221 mainview->current_color = gdk_color_copy(&c2);
3226 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
3228 maepad_warning("Error reading data: %s", sqlite3_errmsg(mainview->db));
3229 break;
3232 if (stmt) {
3233 sqlite3_finalize(stmt);
3234 stmt = NULL;
3237 gboolean resback = FALSE;
3239 while(curDataVersion < datatableversion)
3241 if (curDataVersion == 0)
3243 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_backupname);
3244 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3246 g_snprintf(tq, sizeof(tq), "ALTER TABLE %s RENAME TO %s", datatable_name, datatable_backupname);
3247 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3248 maepad_warning("Error backing up table %s to %s", datatable_name, datatable_backupname);
3249 break;
3251 resback = TRUE;
3253 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", datatable_name, datatable);
3254 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3255 maepad_warning("Error creating table: %s", datatable_name);
3256 break;
3258 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT nodeid, parent, bodytype, name, body, nameblob, bodyblob, lastmodified, ord, 0 FROM %s", datatable_name, datatable_backupname);
3259 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3260 maepad_warning("Error copying data from %s to %s", datatable_name, datatable_backupname);
3261 break;
3264 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_backupname);
3265 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3267 curDataVersion = datatableversion;
3269 break;
3272 if (curDataVersion != datatableversion)
3274 maepad_warning("Data table version mismatch: %d <=> %d", curDataVersion, datatableversion);
3276 if (resback == TRUE)
3278 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_name);
3279 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3280 g_snprintf(tq, sizeof(tq), "ALTER TABLE %s RENAME TO %s", datatable_backupname, datatable_name);
3281 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3284 break;
3288 while(curChecklistVersion < checklisttableversion)
3290 if (curChecklistVersion == 0) /*no checklisttable at all*/
3292 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", checklisttable_name, checklisttable);
3293 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3294 maepad_warning("Error creating checklist table during schema upgrade");
3295 break;
3297 curChecklistVersion = checklisttableversion;
3299 break;
3303 GtkTreeStore *model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview)));
3305 g_object_ref(model);
3306 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), NULL);
3310 char tq[512];
3312 g_snprintf(tq, sizeof(tq), "CREATE%s TABLE %s%s", TEMPTABLE_KEYWORD, datatable_tmpname, datatable);
3313 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3314 maepad_warning("Error creating temp table: %s", datatable_tmpname);
3315 break;
3317 g_snprintf(tq, sizeof(tq), "CREATE INDEX %s_index ON %s %s", datatable_tmpname, datatable_tmpname, dataindex);
3318 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3319 maepad_warning("Error creating temp index for %s", datatable_tmpname);
3320 break;
3322 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", datatable_tmpname, datatable_name);
3323 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3324 maepad_warning("Error copying data from %s to %s", datatable_name, datatable_tmpname);
3325 break;
3328 g_snprintf(tq, sizeof(tq), "CREATE%s TABLE %s%s", TEMPTABLE_KEYWORD, checklisttable_tmpname, checklisttable);
3329 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3330 maepad_warning("Error creating temp table: %s", checklisttable_tmpname);
3331 break;
3333 g_snprintf(tq, sizeof(tq), "CREATE INDEX %s_index ON %s %s", checklisttable_tmpname, checklisttable_tmpname, checklistindex);
3334 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3335 maepad_warning("Error creating temp index for %s", checklisttable_tmpname);
3336 break;
3338 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", checklisttable_tmpname, checklisttable_name);
3339 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3340 maepad_warning("Error copying data from %s to %s", checklisttable_name, checklisttable_tmpname);
3341 break;
3344 while(FALSE);
3346 GtkTreeRowReference *selectedRef = read_sqlite3_data(mainview, 0, NULL, selectedCard, model);
3348 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), GTK_TREE_MODEL(model));
3349 g_object_unref(model);
3350 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview->treeview));
3352 if (selectedRef != NULL)
3354 GtkTreeIter seliter;
3356 if (ref2iter(GTK_TREE_MODEL(model), selectedRef, &seliter) == TRUE)
3358 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
3359 gtk_tree_selection_select_iter(selection, &seliter);
3362 gtk_tree_row_reference_free(selectedRef);
3364 res = TRUE;
3366 while(FALSE);
3368 if (stmt) {
3369 sqlite3_finalize(stmt);
3373 mainview->loading=FALSE;
3375 return (res);
3379 * write to file
3381 void write_buffer_to_file(MainView * mainview)
3383 maepad_message("Writing database to file: %s", mainview->file_name);
3384 saveCurrentData(mainview);
3386 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview));
3387 /*update ord value in database for all nodes*/
3388 gtk_tree_model_foreach(GTK_TREE_MODEL(model),(GtkTreeModelForeachFunc) foreach_func_update_ord,mainview);
3390 busy_enter(mainview);
3392 char tq[512];
3394 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", misctable_name);
3395 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3397 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", misctable_name, misctable);
3398 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3400 gint nndcc = 1;
3402 if (mainview->newnodedialog_createchild == FALSE)
3403 nndcc = 0;
3404 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('newNodeDlgCreateChild', '%d');", misctable_name, nndcc);
3405 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3407 nodeData *node = getSelectedNode(mainview);
3409 if (node)
3411 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('selectedNode', '%d');", misctable_name, node->sql3id);
3412 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3415 guint bsize;
3416 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mainview->eraser_tb)) == TRUE)
3418 bsize=mainview->brushsize_backup;
3420 else
3422 bsize=sketchwidget_get_brushsize(mainview->sk);
3424 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('brushSize', '%d');", misctable_name, bsize);
3425 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3427 if (mainview->current_color == NULL) {
3428 GdkColor color = {0, 0, 0, 0};
3429 mainview->current_color = gdk_color_copy(&color);
3431 unsigned long bcol = ((mainview->current_color->red >> 8) << 16) |
3432 ((mainview->current_color->green >> 8) << 8) |
3433 ((mainview->current_color->blue) >> 8);
3435 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('brushColor', '%lu');", misctable_name, bcol);
3436 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3438 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('dataVersion', '%d');", misctable_name, datatableversion);
3439 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3441 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('checklistVersion', '%d');", misctable_name, checklisttableversion);
3442 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3444 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_backupname);
3445 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3446 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", datatable_backupname, datatable);
3447 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3449 maepad_warning("Error creating backup table: %s", datatable_backupname);
3450 show_banner(mainview, _("Error creating backup table"));
3452 busy_leave(mainview);
3453 return;
3455 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", datatable_backupname, datatable_name);
3456 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3458 maepad_warning("Error backing up table %s to %s", datatable_name, datatable_backupname);
3459 show_banner(mainview, _("Error creating backup table"));
3461 busy_leave(mainview);
3462 return;
3464 g_snprintf(tq, sizeof(tq), "DELETE FROM %s", datatable_name);
3465 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3467 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", datatable_name, datatable_tmpname);
3468 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3470 maepad_warning("Error saving table %s to %s", datatable_tmpname, datatable_name);
3471 show_banner(mainview, _("Error saving table"));
3473 g_snprintf(tq, sizeof(tq), "DELETE FROM %s", datatable_name);
3474 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3476 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", datatable_name, datatable_backupname);
3477 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3478 maepad_warning("Error restoring backup. Data lost :(");
3481 busy_leave(mainview);
3482 return;
3485 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_backupname);
3486 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3488 /*checklist*/
3489 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", checklisttable_backupname);
3490 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3491 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", checklisttable_backupname, checklisttable);
3492 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3494 maepad_warning("Error creating backup table: %s", checklisttable_backupname);
3495 show_banner(mainview, _("Error creating checklist backup table"));
3497 busy_leave(mainview);
3498 return;
3501 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", checklisttable_backupname, checklisttable_name);
3502 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3504 maepad_warning("Error backing up table %s to %s", checklisttable_name, checklisttable_backupname);
3505 show_banner(mainview, _("Error creating checklist backup table"));
3507 busy_leave(mainview);
3508 return;
3510 g_snprintf(tq, sizeof(tq), "DELETE FROM %s", checklisttable_name);
3511 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3513 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", checklisttable_name, checklisttable_tmpname);
3514 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3516 maepad_warning("Error saving table %s to %s", checklisttable_tmpname, checklisttable_name);
3517 show_banner(mainview, _("Error saving checklist table"));
3519 g_snprintf(tq, sizeof(tq), "DELETE FROM %s", checklisttable_name);
3520 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3522 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", checklisttable_name, checklisttable_backupname);
3523 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3524 maepad_warning("Error restoring backup. Data lost :(");
3526 busy_leave(mainview);
3527 return;
3530 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", checklisttable_backupname);
3531 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3533 mainview->file_edited = FALSE;
3534 busy_leave(mainview);
3535 show_banner(mainview, _("Changes saved"));
3538 void callback_checklist_change(GtkTreeSelection *selection, MainView *mainview)
3540 g_assert(mainview != NULL && mainview->data != NULL);
3542 g_signal_handlers_block_by_func(mainview->bold_tb, callback_fontstyle, mainview->bold_tb);
3543 g_signal_handlers_block_by_func(mainview->strikethru_tb, callback_fontstyle, mainview->strikethru_tb);
3544 g_signal_handlers_block_by_func(mainview->check_tb, callback_fontstyle, mainview->check_tb);
3546 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), FALSE);
3547 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->strikethru_tb), FALSE);
3548 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->check_tb), FALSE);
3550 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
3551 GList* l=gtk_tree_selection_get_selected_rows(selection, NULL);
3553 gboolean gotit=FALSE;
3555 GList* cur=l;
3556 while(cur)
3558 GtkTreePath *path=cur->data;
3560 if (!gotit)
3562 GtkTreeIter iter;
3563 if (gtk_tree_model_get_iter(model, &iter, path))
3565 gint styletoset_weight;
3566 gboolean styletoset_strike;
3567 gboolean ischecked;
3569 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHECKNODE_BOLD, &styletoset_weight, CHECKNODE_STRIKE, &styletoset_strike, CHECKNODE_CHECKED, &ischecked, -1);
3570 if (styletoset_weight==PANGO_WEIGHT_BOLD) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), TRUE);
3571 if (styletoset_strike==TRUE) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->strikethru_tb), TRUE);
3572 if (ischecked==TRUE) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->check_tb), TRUE);
3573 gotit=TRUE;
3576 gtk_tree_path_free(path);
3577 cur=cur->next;
3580 g_list_free(l);
3582 g_signal_handlers_unblock_by_func(mainview->bold_tb, callback_fontstyle, mainview->bold_tb);
3583 g_signal_handlers_unblock_by_func(mainview->strikethru_tb, callback_fontstyle, mainview->strikethru_tb);
3584 g_signal_handlers_unblock_by_func(mainview->check_tb, callback_fontstyle, mainview->check_tb);
3587 void callback_checklist_paste(MainView *mainview)
3589 g_assert(mainview != NULL && mainview->data != NULL);
3590 gchar **entries;
3591 gint length, i;
3593 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
3594 GtkTreeIter toplevel;
3595 gchar *pasted_text = gtk_clipboard_wait_for_text(mainview->clipboard);
3597 entries = g_strsplit(pasted_text, "\n", 0);
3598 length = g_strv_length(entries);
3600 for (i=0; i<length; i++) {
3601 gtk_list_store_append(GTK_LIST_STORE(model), &toplevel);
3602 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_CHECKED, FALSE, CHECKNODE_TEXT, entries[i], -1);
3605 mainview->checklist_edited = TRUE;
3606 g_free(pasted_text);
3607 g_strfreev(entries);
3610 void callback_checklist_add(GtkAction *action, MainView *mainview)
3612 g_assert(mainview != NULL && mainview->data != NULL);
3614 gchar* text = show_line_edit_dialog(mainview, _("Add new checklist item"), _("Name:"), _("Add"), "");
3616 if (text != NULL) {
3617 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
3618 GtkTreeIter toplevel;
3619 gtk_list_store_append(GTK_LIST_STORE(model), &toplevel);
3621 gtk_list_store_set(GTK_LIST_STORE(model),
3622 &toplevel,
3623 CHECKNODE_CHECKED, FALSE,
3624 CHECKNODE_TEXT, text,
3625 -1);
3627 GtkTreePath *path = gtk_tree_model_get_path(model, &toplevel);
3628 if (path) {
3629 gtk_tree_view_set_cursor(GTK_TREE_VIEW(mainview->listview), path, mainview->listtextcol, FALSE);
3630 gtk_tree_path_free(path);
3633 mainview->checklist_edited = TRUE;
3637 void callback_checklist_edit(GtkAction *action, MainView *mainview)
3639 g_assert(mainview != NULL && mainview->data != NULL);
3641 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview));
3643 if (gtk_tree_selection_count_selected_rows(selection) == 0) {
3644 show_banner(mainview, _("Select items first"));
3645 return;
3648 GtkTreeModel* model;
3649 GtkTreeIter iter;
3651 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
3652 gchar* old_text = NULL;
3653 gtk_tree_model_get(model, &iter, CHECKNODE_TEXT, &old_text, -1);
3655 gchar* new_text = show_line_edit_dialog(mainview, _("Edit checklist item"), _("New name:"), _("Save"), old_text);
3657 if (new_text != NULL) {
3658 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_TEXT, new_text, -1);
3659 g_free(new_text);
3662 g_free(old_text);
3665 mainview->checklist_edited = TRUE;
3668 void callback_checklist_delete(GtkAction *action, MainView *mainview)
3670 g_assert(mainview != NULL && mainview->data != NULL);
3672 if (gtk_tree_selection_count_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview)))==0) {
3673 show_banner(mainview, _("Select items first"));
3674 return;
3677 if (show_confirmation(mainview, _("Delete selected checklist item?"))) {
3678 callback_checklist_delete_real(mainview);
3682 void callback_checklist_delete_real(MainView* mainview)
3684 GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
3685 GList* l=gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview)), NULL);
3687 GList* rowrefs=NULL;
3688 GList* cur=l;
3689 while(cur)
3691 GtkTreePath *path=cur->data;
3693 GtkTreeIter iter;
3694 if (gtk_tree_model_get_iter(model, &iter, path))
3696 GtkTreeRowReference *rowref = gtk_tree_row_reference_new(model, path);
3697 rowrefs=g_list_append(rowrefs, rowref);
3699 gtk_tree_path_free(path);
3700 cur=cur->next;
3702 g_list_free(l);
3704 g_object_ref(model);
3705 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->listview), NULL);
3707 cur=rowrefs;
3708 while(cur)
3710 GtkTreeRowReference *rowref=cur->data;
3711 GtkTreePath *path= gtk_tree_row_reference_get_path(rowref);
3712 if (path)
3714 GtkTreeIter iter;
3715 if (gtk_tree_model_get_iter(model, &iter, path)) gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
3716 gtk_tree_path_free(path);
3718 gtk_tree_row_reference_free(rowref);
3719 cur=cur->next;
3721 g_list_free(rowrefs);
3723 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->listview), model);
3724 g_object_unref(model);
3725 mainview->checklist_edited = TRUE;
3728 /* Ask the user for confirmation of a specific action */
3729 gboolean
3730 show_confirmation(MainView* mainview, gchar* question)
3732 GtkDialog* dialog = GTK_DIALOG(hildon_note_new_confirmation(
3733 GTK_WINDOW(mainview->data->main_view), question));
3734 gtk_window_set_transient_for(GTK_WINDOW(dialog), mainview_get_dialog_parent(mainview));
3736 gint response = gtk_dialog_run(dialog);
3737 gtk_widget_destroy(GTK_WIDGET(dialog));
3739 return (response == GTK_RESPONSE_OK);
3742 /* Show a information banner to the user (non-modal) */
3743 void
3744 show_banner(MainView* mainview, const gchar* text)
3746 hildon_banner_show_information(GTK_WIDGET(mainview_get_dialog_parent(mainview)), NULL, text);
3749 /* Let the user enter or edit a line of text */
3750 gchar*
3751 show_line_edit_dialog(MainView* mainview, const gchar* title, const gchar* label_text, const gchar* action, const gchar* text)
3753 GtkWidget* edit_dialog;
3754 GtkWidget* label;
3755 GtkWidget* entry;
3756 GtkWidget* hbox;
3757 gchar* result = NULL;
3759 edit_dialog = GTK_WIDGET(gtk_dialog_new());
3760 gtk_window_set_title(GTK_WINDOW(edit_dialog), title);
3761 gtk_window_set_transient_for(GTK_WINDOW(edit_dialog), mainview_get_dialog_parent(mainview));
3763 label = GTK_WIDGET(gtk_label_new(label_text));
3765 entry = hildon_entry_new(HILDON_SIZE_AUTO);
3766 gtk_entry_set_text(GTK_ENTRY(entry), text);
3767 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
3768 gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
3770 gtk_dialog_add_button(GTK_DIALOG(edit_dialog), action, GTK_RESPONSE_OK);
3771 gtk_dialog_set_default_response(GTK_DIALOG(edit_dialog), GTK_RESPONSE_OK);
3773 hbox = GTK_WIDGET(gtk_hbox_new(FALSE, 10));
3775 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(edit_dialog))), GTK_WIDGET(hbox));
3776 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
3777 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
3779 gtk_widget_show_all(GTK_WIDGET(hbox));
3781 while (TRUE) {
3782 if (gtk_dialog_run(GTK_DIALOG(edit_dialog)) == GTK_RESPONSE_OK) {
3783 result = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
3784 if (strcmp(result, "") != 0) {
3785 break;
3786 } else {
3787 show_banner(mainview, _("Please enter a non-empty text"));
3788 g_free(result);
3789 result = NULL;
3791 } else {
3792 result = NULL;
3793 break;
3797 gtk_widget_destroy(GTK_WIDGET(edit_dialog));
3798 return result;