Hide checklist edit tool button in non-checklist views
[maepad.git] / src / ui / callbacks.c
blobebf116283f178c008719f3cadf45b99ca0c0ffc3
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->checkedit_tb));
208 gtk_widget_show(GTK_WIDGET(mainview->checkdel_tb));
209 gtk_widget_hide(GTK_WIDGET(mainview->undo_tb));
210 gtk_widget_hide(GTK_WIDGET(mainview->redo_tb));
212 else
214 gtk_widget_hide(GTK_WIDGET(mainview->strikethru_tb));
215 gtk_widget_hide(GTK_WIDGET(mainview->check_tb));
216 gtk_widget_hide(GTK_WIDGET(mainview->checkadd_tb));
217 gtk_widget_hide(GTK_WIDGET(mainview->checkedit_tb));
218 gtk_widget_hide(GTK_WIDGET(mainview->checkdel_tb));
219 gtk_widget_show(GTK_WIDGET(mainview->undo_tb));
220 gtk_widget_show(GTK_WIDGET(mainview->redo_tb));
223 if (typ == NODE_TEXT)
225 gtk_widget_hide(GTK_WIDGET(mainview->colorbutton_tb));
226 gtk_widget_hide(sketchwidget_get_mainwidget(mainview->sk));
227 gtk_widget_hide(mainview->listscroll);
228 gtk_widget_show(GTK_WIDGET(mainview->scrolledwindow));
229 gtk_widget_show(mainview->tools_item);
231 else if (typ == NODE_SKETCH)
233 gtk_widget_show(GTK_WIDGET(mainview->colorbutton_tb));
234 gtk_widget_hide(GTK_WIDGET(mainview->scrolledwindow));
235 gtk_widget_hide(mainview->listscroll);
236 gtk_widget_show(sketchwidget_get_mainwidget(mainview->sk));
237 gtk_widget_show(mainview->tools_item);
239 else if (typ == NODE_CHECKLIST)
241 gtk_widget_show(GTK_WIDGET(mainview->colorbutton_tb));
242 gtk_widget_hide(GTK_WIDGET(mainview->scrolledwindow));
243 gtk_widget_hide(sketchwidget_get_mainwidget(mainview->sk));
244 gtk_widget_hide(mainview->tools_item);
245 gtk_widget_show(mainview->listscroll);
247 else
249 gtk_widget_hide(GTK_WIDGET(mainview->colorbutton_tb));
250 gtk_widget_hide(GTK_WIDGET(mainview->scrolledwindow));
251 gtk_widget_hide(sketchwidget_get_mainwidget(mainview->sk));
252 gtk_widget_hide(mainview->tools_item);
253 gtk_widget_hide(mainview->listscroll);
257 nodeData *getSelectedNode(MainView * mainview)
259 GtkTreeIter iter;
260 GtkTreeModel *model;
262 nodeData *nd;
264 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
266 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
267 return (NULL);
269 gtk_tree_model_get(model, &iter, NODE_DATA, &nd, -1);
271 return (nd);
274 void saveCurrentData(MainView * mainview)
276 nodeData *selnode = getSelectedNode(mainview);
277 saveDataToNode(mainview, selnode);
280 void saveDataToNode(MainView * mainview, nodeData *selnode)
282 if (selnode == NULL)
283 return;
285 if (
286 (selnode->typ == NODE_SKETCH && sketchwidget_get_edited(mainview->sk) == FALSE) ||
287 (selnode->typ == NODE_TEXT && wp_text_buffer_is_modified(mainview->buffer)==FALSE) ||
288 (selnode->typ == NODE_CHECKLIST && mainview->checklist_edited==FALSE)
291 maepad_message("node not edited, not saving");
292 return;
295 mainview->file_edited = TRUE;
297 busy_enter(mainview);
298 maepad_debug("saveDataToNode working");
300 gboolean goterr = TRUE;
301 gchar *textdata = NULL;
302 GdkPixbuf *pixbuf = NULL;
303 gchar *sketchdata = NULL;
304 gsize datalen = 0;
305 char tq[512];
307 if (selnode->typ == NODE_TEXT)
309 #if 0
310 GtkTextIter start, end;
311 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(mainview->buffer), &start, &end);
312 textdata = gtk_text_buffer_serialize_rich_text(GTK_TEXT_BUFFER(mainview->buffer), &start, &end, &datalen);
313 #endif
315 GString *gstr=g_string_sized_new(4096);
316 wp_text_buffer_save_document(mainview->buffer, (WPDocumentSaveCallback)(wp_savecallback), gstr);
318 datalen=gstr->len;
319 textdata=g_string_free(gstr, FALSE);
321 /* 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);*/
322 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);
324 else if (selnode->typ == NODE_SKETCH)
326 GError *err = NULL;
327 GdkPixmap *skpix = sketchwidget_get_Pixmap(mainview->sk);
328 GtkWidget *skdr = sketchwidget_get_drawingarea(mainview->sk);
330 pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(skpix), NULL, 0, 0, 0, 0, skdr->allocation.width, skdr->allocation.height);
331 if (pixbuf == NULL)
333 maepad_warning("error saving: pixbuf is null");
335 else
337 double w, h;
338 GdkPixbuf *pixbuf2 = sketchwidget_trim_image(pixbuf, skdr->allocation.width, skdr->allocation.height, &w, &h, FALSE);
340 if (pixbuf2!=NULL)
342 if (gdk_pixbuf_save_to_buffer(pixbuf2, &sketchdata, &datalen, "png", &err, NULL) == FALSE)
344 sketchdata = NULL;
345 datalen = 0;
346 maepad_warning("Error saving sketch: %s", err->message);
347 g_error_free(err);
349 gdk_pixbuf_unref(pixbuf2);
352 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);
353 maepad_debug("storing sketch in db: %d bytes", datalen);
354 if (skpix && G_IS_OBJECT(skpix)) g_object_unref(skpix);
356 else if (selnode->typ == NODE_CHECKLIST)
358 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);
363 sqlite3_stmt *stmt = NULL;
364 const char *dum;
365 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
367 if (rc)
369 maepad_warning("Error updating: %s", sqlite3_errmsg(mainview->db));
370 break;
372 if (selnode->typ == NODE_TEXT)
373 sqlite3_bind_text(stmt, 1, textdata, datalen, /*strlen(textdata),*/ SQLITE_TRANSIENT);
374 else if (selnode->typ == NODE_SKETCH)
375 sqlite3_bind_blob(stmt, 1, sketchdata, datalen, SQLITE_TRANSIENT);
377 rc = SQLITE_BUSY;
378 while(rc == SQLITE_BUSY)
380 rc = sqlite3_step(stmt);
381 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
382 break;
384 sqlite3_finalize(stmt);
386 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
388 maepad_warning("Error saving node: %s", sqlite3_errmsg(mainview->db));
390 else
392 if (selnode->typ == NODE_TEXT)
393 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(mainview->buffer), FALSE);
394 else if (selnode->typ == NODE_SKETCH)
395 sketchwidget_set_edited(mainview->sk, FALSE);
396 else if (selnode->typ == NODE_CHECKLIST)
397 mainview->checklist_edited = FALSE;
398 goterr = FALSE;
400 }while(FALSE);
402 while(goterr==FALSE && selnode->typ == NODE_CHECKLIST)
404 GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
406 char tq[512];
407 g_snprintf(tq, sizeof(tq), "DELETE FROM %s WHERE nodeid=%d", checklisttable_tmpname, selnode->sql3id);
408 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
410 GtkTreeIter iter;
411 if (gtk_tree_model_get_iter_first(model, &iter)==FALSE) break;
415 gint styletoset_weight;
416 gboolean styletoset_strike;
417 gboolean ischecked;
418 gchar *text;
419 gchar *color;
420 unsigned long col=0;
422 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);
424 GdkColor tmpcol;
425 if (color!=NULL && strcmp(color, "(null)")!=0 && gdk_color_parse(color, &tmpcol))
427 col=((tmpcol.red>>8)<<16)|((tmpcol.green>>8)<<8)|(tmpcol.blue>>8);
430 gint style=0;
431 if (ischecked) style|=CHECKSTYLE_CHECKED;
432 if (styletoset_weight==PANGO_WEIGHT_BOLD) style|=CHECKSTYLE_BOLD;
433 if (styletoset_strike) style|=CHECKSTYLE_STRIKE;
435 g_snprintf(tq, sizeof(tq), "INSERT INTO %s (nodeid, name, style, color, ord) VALUES(%d, ?, %d, %lu, 0)", checklisttable_tmpname, selnode->sql3id, style, col);
436 sqlite3_stmt *stmt = NULL;
437 const char *dum;
438 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
440 if (rc)
442 goterr=TRUE;
443 maepad_warning("Error while saving checklist: %s", sqlite3_errmsg(mainview->db));
444 break;
446 sqlite3_bind_text(stmt, 1, text, strlen(text), SQLITE_TRANSIENT);
448 rc = SQLITE_BUSY;
449 while(rc == SQLITE_BUSY)
451 rc = sqlite3_step(stmt);
452 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
453 break;
455 sqlite3_finalize(stmt);
457 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
459 goterr=TRUE;
460 maepad_warning("Error while saving checklist (2): %s", sqlite3_errmsg(mainview->db));
463 g_free(color);
464 g_free(text);
466 }while(gtk_tree_model_iter_next(model, &iter)==TRUE);
468 break;
471 if (textdata)
472 g_free(textdata);
473 if (sketchdata)
474 g_free(sketchdata);
475 if (goterr == TRUE)
477 show_banner(mainview, _("Error saving memo"));
479 busy_leave(mainview);
482 gboolean callback_treeview_button_press(GtkTreeView* treeview, GdkEventButton* event, gpointer user_data)
484 MainView* mainview = (MainView*)user_data;
486 mainview->can_show_node_view = TRUE;
488 return FALSE;
491 void callback_treeview_celldatafunc(GtkTreeViewColumn * tree_column, GtkCellRenderer * cell, GtkTreeModel * tree_model, GtkTreeIter * iter, gpointer data)
493 MainView *mainview = ( MainView * ) data;
494 g_assert(mainview != NULL && mainview->data != NULL );
496 nodeData *nd;
498 gtk_tree_model_get(tree_model, iter, NODE_DATA, &nd, -1);
499 if (nd == NULL)
500 return;
502 if (nd->namepix == NULL)
504 g_object_set(cell, "visible", FALSE, NULL);
506 else
508 g_object_set(cell, "visible", TRUE, NULL);
509 g_object_set(cell, "width", SKETCHNODE_RX, NULL);
510 g_object_set(cell, "height", SKETCHNODE_RY, NULL);
515 gboolean callback_treeview_testcollapse(GtkTreeView * treeview, GtkTreeIter * arg1, GtkTreePath * arg2, gpointer user_data)
517 return (FALSE);
520 void callback_treeview_change(GtkTreeSelection * selection, gpointer data)
522 MainView *mainview = (MainView *) data;
523 g_assert(mainview != NULL && mainview->data != NULL);
525 nodeData *nd = getSelectedNode(mainview);
527 gchar* nodeName = _("View node");
529 if (nd != NULL && nd->name != NULL) {
530 nodeName = nd->name;
533 /* Show node view with selected node */
534 gtk_window_set_title(GTK_WINDOW(mainview->data->node_view),
535 nodeName);
537 if (mainview->can_show_node_view) {
538 gtk_widget_show(GTK_WIDGET(mainview->data->node_view));
541 /* Make sure we don't accidentally collapse any nodes */
542 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview->treeview));
544 #ifdef NEW_SEL_LOGIC
545 guint tm=time(NULL);
546 if (mainview->cansel_time>0 && mainview->cansel_time+1.0<tm) mainview->cansel_node=NULL;
548 if (nd==NULL)
550 if (mainview->cansel_node!=NULL)
552 maepad_debug("[SELLOGIC] saving %d to unselect all nodes", (mainview->cansel_node)->sql3id);
553 saveDataToNode(mainview, (mainview->cansel_node));
554 mainview->cansel_node=NULL;
556 return;
559 if (mainview->cansel_node!=NULL)
561 if (nd->sql3id == (mainview->cansel_node)->sql3id)
563 mainview->cansel_node=NULL;
564 maepad_debug("[SELLOGIC] doubly selected %d, doing nothing", nd->sql3id);
565 return;
567 else
569 maepad_debug("[SELLOGIC] saving %d to load new node", (mainview->cansel_node)->sql3id);
570 saveDataToNode(mainview, (mainview->cansel_node));
571 mainview->cansel_node=NULL;
574 #endif
576 if (nd == NULL) return;
578 busy_enter(mainview);
580 gboolean goterr = TRUE;
581 char *textdata = NULL;
582 char *blob = NULL;
583 int blobsize = 0, textsize = 0;
585 char tq[512];
587 g_snprintf(tq, sizeof(tq), "SELECT bodytype, body, bodyblob, flags FROM %s WHERE nodeid=%d", datatable_tmpname, nd->sql3id);
588 sqlite3_stmt *stmt = NULL;
589 const char *dum;
590 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
592 if (rc)
594 maepad_warning("Error reading (1): %s", sqlite3_errmsg(mainview->db));
596 else
598 rc = SQLITE_BUSY;
599 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
601 rc = sqlite3_step(stmt);
602 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
603 break;
604 else if (rc == SQLITE_ROW)
606 nd->typ = sqlite3_column_int(stmt, 0);
607 nd->flags = sqlite3_column_int(stmt, 3);
609 prepareUIforNodeChange(mainview, nd->typ);
610 if (nd->typ == NODE_TEXT)
612 gboolean file_edited_backup = mainview->file_edited;
614 blobsize = sqlite3_column_bytes(stmt, 2);
615 blob = (char *)sqlite3_column_blob(stmt, 2);
617 textdata = (char *)sqlite3_column_text(stmt, 1);
618 textsize = sqlite3_column_bytes(stmt, 1);
620 /* gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), "", -1);*/
621 wp_text_buffer_reset_buffer(mainview->buffer, TRUE);
623 gboolean richtext=FALSE;
625 if (blob != NULL)
627 #if 0
628 gboolean oldway=FALSE;
629 if (blobsize>8)
631 char tst[8];
632 strncpy(tst, blob, 8);
633 tst[8]=0;
634 if (strcmp(tst, "RICHTEXT")==0) oldway=TRUE;
636 if (oldway)
638 GError *err = NULL;
639 GtkTextIter iter;
640 gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(mainview->buffer), &iter);
641 gtk_text_buffer_deserialize_rich_text(GTK_TEXT_BUFFER(mainview->buffer), &iter, blob, blobsize, TRUE, &err);
642 if (err != NULL)
644 g_error_free(err);
646 else
648 richtext=TRUE;
651 #endif
653 if (richtext==FALSE)
655 wp_text_buffer_load_document_begin(mainview->buffer, TRUE);
656 wp_text_buffer_load_document_write(mainview->buffer, blob, blobsize);
657 wp_text_buffer_load_document_end(mainview->buffer);
658 richtext=TRUE;
661 if (richtext==FALSE && !(textdata == NULL || g_utf8_validate(textdata, textsize, NULL) == FALSE))
663 /* gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), textdata, textsize);*/
664 wp_text_buffer_load_document_begin(mainview->buffer, FALSE);
665 wp_text_buffer_load_document_write(mainview->buffer, textdata, textsize);
666 wp_text_buffer_load_document_end(mainview->buffer);
669 wp_text_buffer_enable_rich_text(mainview->buffer, TRUE);
670 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->tools_wordwrap), ((nd->flags & NODEFLAG_WORDWRAP) > 0)?TRUE:FALSE);
671 callback_wordwrap(NULL, mainview); /*FIXME:ugly (do we need this? gotta test) */
673 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(mainview->buffer), FALSE); /*we probably don't need this*/
675 callback_undotoggle((gpointer)mainview->buffer, FALSE, mainview); /*we need these*/
676 callback_redotoggle((gpointer)mainview->buffer, FALSE, mainview);
678 if (file_edited_backup==FALSE) mainview->file_edited=FALSE; /*textview changed event toggles this?*/
679 goterr = FALSE;
681 else if (nd->typ == NODE_SKETCH)
683 sketchwidget_wipe_undo(mainview->sk);
684 sketchwidget_set_fillmode(mainview->sk, FALSE);
685 sketchwidget_set_shift(mainview->sk, FALSE);
686 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->shapemenuitems[1]), TRUE);
687 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->shapemenuitems[0]), TRUE);
689 blobsize = sqlite3_column_bytes(stmt, 2);
690 blob = (char *)sqlite3_column_blob(stmt, 2);
691 gboolean clear = TRUE;
693 if (blob == NULL)
694 goterr = FALSE;
695 if (blob != NULL)
697 maepad_debug("blob size: %d", blobsize);
698 GdkPixbufLoader *pl = gdk_pixbuf_loader_new_with_type("png", NULL);
699 GError *err = NULL;
701 gdk_pixbuf_loader_write(pl, (guchar *) blob, blobsize, &err);
702 if (err != NULL)
704 maepad_warning("Error loading sketch: %s", err->message);
705 g_error_free(err);
706 err = NULL;
708 gdk_pixbuf_loader_close(pl, NULL);
709 GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(pl);
711 if (GDK_IS_PIXBUF(pixbuf))
713 GtkWidget *skdr = sketchwidget_get_drawingarea(mainview->sk);
714 GtkPixmap *skpix = (GtkPixmap *) sketchwidget_get_Pixmap(mainview->sk);
716 int w=gdk_pixbuf_get_width(pixbuf);
717 int h=gdk_pixbuf_get_height(pixbuf);
718 if (w!=skdr->allocation.width || h!=skdr->allocation.height)
720 if (w>skdr->allocation.width) w=skdr->allocation.width;
721 if (h>skdr->allocation.height) h=skdr->allocation.height;
722 sketchwidget_clear_real(mainview->sk);
724 gdk_draw_pixbuf(GDK_DRAWABLE(skpix), NULL, pixbuf, 0, 0, 0, 0, w, h, GDK_RGB_DITHER_NONE, 0, 0);
726 clear = FALSE;
727 goterr = FALSE;
729 if (skpix && G_IS_OBJECT(skpix)) g_object_unref(skpix);
731 else
733 maepad_warning("Error loading pixbuf");
735 g_object_unref(pl);
737 if (clear == TRUE)
739 maepad_message("Clearing sketch widget");
740 sketchwidget_clear_real(mainview->sk);
742 gtk_widget_queue_draw(sketchwidget_get_drawingarea(mainview->sk));
744 else if (nd->typ == NODE_CHECKLIST)
746 mainview->checklist_edited = FALSE;
747 GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
748 g_object_ref(model);
749 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->listview), NULL);
750 gtk_list_store_clear(GTK_LIST_STORE(model));
752 g_snprintf(tq, sizeof(tq), "SELECT name, style, color FROM %s WHERE nodeid=%d ORDER BY ord, idx", checklisttable_tmpname, nd->sql3id);
753 sqlite3_stmt *stmt2 = NULL;
754 const char *dum;
755 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt2, &dum);
756 if (rc)
758 maepad_warning("Error reading checklist (1) %s", sqlite3_errmsg(mainview->db));
760 else
762 goterr=FALSE;
763 rc = SQLITE_BUSY;
764 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
766 rc = sqlite3_step(stmt2);
767 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
768 break;
769 else if (rc == SQLITE_ROW)
771 char *textdata = (char *)sqlite3_column_text(stmt2, 0);
772 int style = sqlite3_column_int(stmt2, 1);
773 unsigned long col = sqlite3_column_int(stmt2, 2);
775 GtkTreeIter toplevel;
776 gtk_list_store_append(GTK_LIST_STORE(model), &toplevel);
777 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_TEXT, textdata, CHECKNODE_CHECKED, FALSE, -1);
778 if ((style & CHECKSTYLE_CHECKED)>0) {
779 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_CHECKED, TRUE, -1);
780 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_ICON_NAME, "widgets_tickmark_list", -1);
782 if ((style & CHECKSTYLE_BOLD)>0) gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_BOLD, PANGO_WEIGHT_BOLD, -1);
783 if ((style & CHECKSTYLE_STRIKE)>0) gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_STRIKE, TRUE, -1);
785 if (col>0)
787 char tmp[10];
788 g_snprintf(tmp, sizeof(tmp), "#%02lx%02lx%02lx", ((col & 0xFF0000) >> 16), ((col & 0xFF00) >> 8), (col & 0xFF));
789 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_COLOR, tmp, -1);
794 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
796 maepad_warning("Error reading checklist (2): %s", sqlite3_errmsg(mainview->db));
797 goterr=TRUE;
800 sqlite3_finalize(stmt2);
803 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->listview), model);
804 g_object_unref(model);
807 if ((nd->flags & NODEFLAG_SKETCHLINES) > 0)
808 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->sketchlinesmenuitems[1]), TRUE);
809 else if ((nd->flags & NODEFLAG_SKETCHGRAPH) > 0)
810 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->sketchlinesmenuitems[2]), TRUE);
811 else
813 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->sketchlinesmenuitems[0]), TRUE);
814 callback_sketchlines(NULL, mainview->sketchlinesmenuitems[0]); /*FIXME:ugly */
816 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->tools_pressure), TRUE);
818 break;
821 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE) {
822 maepad_warning("Error reading (2): %s", sqlite3_errmsg(mainview->db));
825 sqlite3_finalize(stmt);
828 busy_leave(mainview);
830 if (goterr == TRUE)
832 show_banner(mainview, _("Error loading memo"));
836 gboolean treeview_canselect(GtkTreeSelection * selection, GtkTreeModel * model, GtkTreePath * path, gboolean path_currently_selected, gpointer userdata)
838 MainView *mainview = (MainView *) userdata;
839 g_assert(mainview != NULL && mainview->data != NULL);
841 if (mainview->loading==FALSE)
843 #ifndef EXPANDING_ROWS
844 if (path_currently_selected)
845 return (FALSE);
846 #endif
848 #ifndef NEW_SEL_LOGIC
849 saveCurrentData(mainview);
850 #else
851 if (path_currently_selected)
853 GtkTreeIter iter;
854 gtk_tree_model_get_iter(model, &iter, path);
856 gtk_tree_model_get(model, &iter, NODE_DATA, &(mainview->cansel_node), -1);
857 mainview->cansel_time=time(NULL);
859 #endif
861 return (TRUE);
864 gboolean newnodedlg_key_press_cb(GtkWidget * widget, GdkEventKey * event, GtkWidget * dlg)
866 SketchWidget *s = gtk_object_get_data(GTK_OBJECT(dlg), "sk");
868 switch (event->keyval)
870 case GDK_F7:
871 sketchwidget_redo(s);
872 return TRUE;
873 case GDK_F8:
874 sketchwidget_undo(s);
875 return TRUE;
877 return FALSE;
881 /* This struct will hold all our toggle buttons, so we can
882 * only allow one to be active at a time (i.e. radio buttons) */
883 typedef struct _newNodeToggleButtons newNodeToggleButtons;
884 struct _newNodeToggleButtons
886 GtkWidget *rbt; /* Text */
887 GtkWidget *rbs; /* Sketch */
888 GtkWidget *rbc; /* Checklist */
891 void show_sketch_widget(GtkWidget *widget, gpointer user_data)
893 GtkWidget *dialog = (GtkWidget*)user_data;
895 /* Show the sketch widget and hide the entry + draw button */
896 gtk_widget_show(gtk_object_get_data(GTK_OBJECT(dialog), "al"));
897 gtk_widget_hide(gtk_object_get_data(GTK_OBJECT(dialog), "draw_button"));
898 gtk_widget_hide(gtk_object_get_user_data(GTK_OBJECT(dialog)));
901 void new_node_dialog(nodeType typ, MainView * mainview)
903 GtkWidget *dialog, *entry, *but_ok, *vbox, *hbox, *al, *cb;
904 GtkWidget *rb1, *rb2, *rb3;
905 GtkWidget *hb;
906 gchar datetime_str[200];
907 time_t t_now;
908 struct tm *tm_now;
909 gboolean datetime_written = FALSE;
911 t_now = time(NULL);
912 tm_now = localtime(&t_now);
914 if (tm_now != NULL) {
915 if (strftime(datetime_str, sizeof(datetime_str), "%y-%m-%d %H:%M", tm_now) != 0) {
916 datetime_written = TRUE;
920 if (datetime_written == FALSE) {
921 /* Was not able to determine a datetime string - use default */
922 maepad_warning("Cannot determine current time");
923 strncpy(datetime_str, _("New memo"), sizeof(datetime_str));
924 datetime_str[sizeof(datetime_str)-1] = '\0';
927 newNodeToggleButtons *nntb = g_malloc(sizeof(newNodeToggleButtons));
929 dialog = gtk_dialog_new();
930 gtk_window_set_title(GTK_WINDOW(dialog), _("Create new memo"));
931 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
933 g_signal_connect(G_OBJECT(dialog), "key_press_event", G_CALLBACK(newnodedlg_key_press_cb), dialog);
935 vbox = gtk_vbox_new(FALSE, 0);
937 hbox = gtk_hbox_new(TRUE, 0);
939 /* Text note toggle button */
940 rb1 = hildon_gtk_radio_button_new(HILDON_SIZE_FINGER_HEIGHT, NULL);
941 gtk_button_set_label(GTK_BUTTON(rb1), _("Rich text"));
942 gtk_button_set_image(GTK_BUTTON(rb1), gtk_image_new_from_file(PIXMAPDIR "/text.png"));
943 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(rb1), TRUE, TRUE, 0);
944 nntb->rbt = rb1;
946 /* Sketch toggle button */
947 rb2 = hildon_gtk_radio_button_new_from_widget(HILDON_SIZE_FINGER_HEIGHT, GTK_RADIO_BUTTON(rb1));
948 gtk_button_set_label(GTK_BUTTON(rb2), _("Sketch"));
949 gtk_button_set_image(GTK_BUTTON(rb2), gtk_image_new_from_file(PIXMAPDIR "/sketch.png"));
950 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(rb2), TRUE, TRUE, 0);
951 nntb->rbs = rb2;
953 /* Checklist toggle button */
954 rb3 = hildon_gtk_radio_button_new_from_widget(HILDON_SIZE_FINGER_HEIGHT, GTK_RADIO_BUTTON(rb1));
955 gtk_button_set_label(GTK_BUTTON(rb3), _("Checklist"));
956 gtk_button_set_image(GTK_BUTTON(rb3), gtk_image_new_from_file(PIXMAPDIR "/checklist.png"));
957 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(rb3), TRUE, TRUE, 0);
958 nntb->rbc = rb3;
960 /* Set mode to 0 to get correct styling */
961 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb1), FALSE);
962 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb2), FALSE);
963 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb3), FALSE);
965 /* Remember "new note toggle buttons" list */
966 gtk_object_set_data(GTK_OBJECT(dialog), "nntb", nntb);
968 if (typ == NODE_TEXT) {
969 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb1), TRUE);
970 } else if (typ == NODE_SKETCH) {
971 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb2), TRUE);
972 } else {
973 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb3), TRUE);
976 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
978 but_ok = gtk_dialog_add_button(GTK_DIALOG(dialog), _("Create"), GTK_RESPONSE_OK);
979 g_signal_connect(G_OBJECT(but_ok), "clicked", G_CALLBACK(callback_new_node_real), dialog);
981 gtk_object_set_data(GTK_OBJECT(dialog), "m", mainview);
983 hb = gtk_hbox_new(FALSE, 10);
984 gtk_box_pack_start(GTK_BOX(hb), gtk_label_new(_("Name:")), FALSE, FALSE, 0);
985 entry = hildon_entry_new(HILDON_SIZE_AUTO);
986 gtk_object_set_user_data(GTK_OBJECT(dialog), entry);
987 gtk_entry_set_text(GTK_ENTRY(entry), datetime_str);
988 gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
989 gtk_box_pack_start(GTK_BOX(hb), entry, TRUE, TRUE, 0);
991 /* Sketch widget, hidden by default */
992 al = gtk_alignment_new(0.5, 0.5, 0, 0);
993 SketchWidget *s = sketchwidget_new(SKETCHNODE_X, SKETCHNODE_Y, TRUE);
994 gtk_object_set_data(GTK_OBJECT(dialog), "sk", s);
995 gtk_object_set_data(GTK_OBJECT(dialog), "al", al);
996 sketchwidget_set_brushsize(s, 2);
997 sketchwidget_set_backstyle(s, SKETCHBACK_GRAPH);
998 gtk_widget_set_size_request(sketchwidget_get_mainwidget(s), SKETCHNODE_X, SKETCHNODE_Y);
999 gtk_container_add(GTK_CONTAINER(al), sketchwidget_get_mainwidget(s));
1000 gtk_box_pack_start(GTK_BOX(hb), al, FALSE, FALSE, 0);
1002 /*but_sketch = hildon_button_new_with_text(
1003 HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
1004 HILDON_BUTTON_ARRANGEMENT_VERTICAL,
1005 _("Use sketch label"), NULL);
1007 gtk_object_set_data(GTK_OBJECT(dialog), "draw_button", but_sketch);
1008 gtk_signal_connect(GTK_OBJECT(but_sketch), "clicked", G_CALLBACK(show_sketch_widget), dialog);
1009 gtk_box_pack_start(GTK_BOX(hb), but_sketch, FALSE, TRUE, 0);*/
1010 gtk_box_pack_start(GTK_BOX(vbox), hb, TRUE, FALSE, 0);
1012 cb = hildon_check_button_new(HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
1013 gtk_button_set_label(GTK_BUTTON(cb), _("Create as child of selected memo"));
1014 hildon_check_button_set_active(HILDON_CHECK_BUTTON(cb), mainview->newnodedialog_createchild);
1015 gtk_box_pack_start(GTK_BOX(vbox), cb, FALSE, FALSE, 0);
1017 gtk_object_set_data(GTK_OBJECT(dialog), "cb", cb);
1019 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), vbox);
1021 gtk_widget_grab_focus(entry);
1023 gtk_widget_show_all(dialog);
1025 /* Hide the sketch widget at first */
1026 gtk_widget_hide(al);
1027 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
1030 void add_new_node(nodeData * node, MainView * mainview, gboolean ischild)
1032 GtkTreeIter parentiter, newiter;
1033 GtkTreeModel *model;
1034 void *ptr = NULL;
1036 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1038 if (gtk_tree_selection_get_selected(selection, &model, &parentiter))
1039 ptr = &parentiter;
1041 GtkTreePath *path = NULL;
1043 unsigned int parentnodeid = 0;
1045 if (ptr != NULL)
1047 path = gtk_tree_model_get_path(model, &parentiter);
1049 if (ischild == FALSE)
1051 gtk_tree_path_up(path);
1053 if (gtk_tree_path_get_depth(path) == 0)
1055 /* Selected node is a root node */
1056 ptr = NULL; /* New node can not have a Parent node */
1057 gtk_tree_path_down(path); /*restore path so expand() works */
1059 else if (gtk_tree_path_get_depth(path) > 0)
1061 /* Selected node is a child node */
1062 if (gtk_tree_model_get_iter(model, &parentiter, path))
1063 ptr = &parentiter;
1068 if (ptr != NULL)
1070 nodeData *nd;
1072 gtk_tree_model_get(model, ptr, NODE_DATA, &nd, -1);
1073 if (nd)
1074 parentnodeid = nd->sql3id;
1077 node->sql3id = 0;
1080 sqlite3_stmt *stmt = NULL;
1081 const char *dum;
1082 char tq[512];
1085 * FIXME: ord
1087 g_snprintf(tq, sizeof(tq), "INSERT INTO %s (parent, bodytype, name, nameblob, ord) VALUES (%d, %d, ?, ?, 0);", datatable_tmpname, parentnodeid, node->typ);
1088 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
1090 if (rc)
1092 maepad_warning("Error inserting (1): %s", sqlite3_errmsg(mainview->db));
1093 break;
1095 if (node->name != NULL)
1096 sqlite3_bind_text(stmt, 1, node->name, strlen(node->name), SQLITE_TRANSIENT);
1097 else
1098 sqlite3_bind_text(stmt, 1, NULL, 0, SQLITE_TRANSIENT);
1100 if (node->namepix != NULL)
1102 gchar *namepixdata = NULL;
1103 gsize datalen = 0;
1105 GError *err = NULL;
1107 if (gdk_pixbuf_save_to_buffer(node->namepix, &namepixdata, &datalen, "png", &err, NULL) == FALSE)
1109 namepixdata = NULL;
1110 datalen = 0;
1111 maepad_warning("Error saving name: %s", err->message);
1112 g_error_free(err);
1114 sqlite3_bind_blob(stmt, 2, namepixdata, datalen, SQLITE_TRANSIENT);
1116 else
1117 sqlite3_bind_blob(stmt, 2, NULL, 0, SQLITE_TRANSIENT);
1119 rc = SQLITE_BUSY;
1120 while(rc == SQLITE_BUSY)
1122 rc = sqlite3_step(stmt);
1123 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
1124 break;
1126 sqlite3_finalize(stmt);
1127 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
1129 maepad_warning("Error inserting (2): %s", sqlite3_errmsg(mainview->db));
1130 break;
1132 node->sql3id = sqlite3_last_insert_rowid(mainview->db);
1134 while(FALSE);
1136 if (node->sql3id == 0)
1138 if (node->name)
1139 g_free(node->name);
1140 if (node->namepix)
1141 g_object_unref(node->namepix);
1142 g_free(node);
1143 if (path)
1144 gtk_tree_path_free(path);
1145 show_banner(mainview, _("Error creating node"));
1146 return;
1149 gtk_tree_store_append(GTK_TREE_STORE(model), &newiter, ptr);
1151 gtk_tree_store_set(GTK_TREE_STORE(model), &newiter, NODE_NAME, node->name, NODE_PIXBUF, node->namepix, NODE_DATA, node, -1);
1153 if (path)
1155 mainview->loading=TRUE; /*only when we have a valid parent*/
1156 gtk_tree_view_expand_row(GTK_TREE_VIEW(mainview->treeview), path, FALSE);
1157 gtk_tree_path_free(path);
1160 gtk_tree_selection_select_iter(selection, &newiter);
1162 mainview->loading=FALSE;
1165 void callback_new_node_real(GtkAction * action, gpointer data)
1167 MainView *mainview;
1169 GtkWidget *dialog = data;
1170 GtkWidget *entry = gtk_object_get_user_data(GTK_OBJECT(dialog));
1172 mainview = gtk_object_get_data(GTK_OBJECT(dialog), "m");
1173 SketchWidget *s = gtk_object_get_data(GTK_OBJECT(dialog), "sk");
1174 GtkWidget *cb = gtk_object_get_data(GTK_OBJECT(dialog), "cb");
1175 newNodeToggleButtons *nntb = gtk_object_get_data(GTK_OBJECT(dialog), "nntb");
1177 nodeType typ = NODE_TEXT;
1178 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nntb->rbs))) {
1179 typ = NODE_SKETCH;
1180 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nntb->rbc))) {
1181 typ = NODE_CHECKLIST;
1183 g_free(nntb);
1185 gchar *txt = NULL;
1187 /*if (GTK_WIDGET_VISIBLE(entry))
1189 txt = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
1190 if (strcmp(txt, "") == 0)
1192 g_free(txt);
1193 return;
1196 else
1198 GtkWidget *sdr = sketchwidget_get_drawingarea(s);
1200 GdkPixmap *spix = sketchwidget_get_Pixmap(s);
1202 pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(spix), NULL, 0, 0, 0, 0, sdr->allocation.width, sdr->allocation.height);
1203 g_object_unref(spix);
1204 double w, h;
1205 GdkPixbuf *pixbuf2 = sketchwidget_trim_image(pixbuf, SKETCHNODE_X, SKETCHNODE_Y, &w,
1206 &h, TRUE);
1207 if (pixbuf2==NULL) return;
1209 GdkPixbuf *pixbuf3 = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, SKETCHNODE_RX,
1210 SKETCHNODE_RY);
1212 gdk_pixbuf_fill(pixbuf3, 0xffffffff);
1214 if (w <= SKETCHNODE_RX && h <= SKETCHNODE_RY)
1216 gdk_pixbuf_copy_area(pixbuf2, 0, 0, w, h, pixbuf3, 0, (SKETCHNODE_RY - h) / 2);
1218 else
1220 double neww, newh;
1222 if (w > h)
1224 neww = SKETCHNODE_RX;
1225 newh = (h / w) * SKETCHNODE_RX;
1227 else
1229 newh = SKETCHNODE_RY;
1230 neww = (w / h) * SKETCHNODE_RY;
1232 if (newh > SKETCHNODE_RY)
1233 newh = SKETCHNODE_RY;
1235 GdkPixbuf *tmpbuf = gdk_pixbuf_scale_simple(pixbuf2, neww, newh,
1236 GDK_INTERP_BILINEAR);
1238 gdk_pixbuf_copy_area(tmpbuf, 0, 0, neww, newh, pixbuf3, 0, (SKETCHNODE_RY - newh) / 2);
1240 gdk_pixbuf_unref(tmpbuf);
1243 pixbuf = pixbuf3;
1244 gdk_pixbuf_unref(pixbuf2);
1247 nodeData *node;
1249 node = g_malloc(sizeof(nodeData));
1250 node->typ = typ;
1251 node->name = txt;
1252 node->namepix = NULL;
1254 /*if (GTK_WIDGET_VISIBLE(entry))
1256 node->name = txt;
1258 else
1260 node->namepix = pixbuf;
1263 node->lastMod = 0;
1264 node->flags = 0;
1265 node->sql3id = 0;
1267 mainview->newnodedialog_createchild = hildon_check_button_get_active(HILDON_CHECK_BUTTON(cb));
1268 add_new_node(node, mainview, mainview->newnodedialog_createchild);
1270 sketchwidget_destroy(s);
1271 gtk_widget_destroy(dialog);
1272 mainview->file_edited = TRUE;
1276 * delete node
1278 void callback_file_delete_node(GtkAction * action, gpointer data)
1280 MainView *mainview = (MainView *) data;
1281 g_assert(mainview != NULL && mainview->data != NULL);
1283 if (getSelectedNode(mainview) == NULL) {
1284 show_banner(mainview, _("Select a node first"));
1285 return;
1288 if (show_confirmation(mainview, _("Delete selected memo?"))) {
1289 callback_delete_node_real(mainview);
1290 gtk_widget_hide(GTK_WIDGET(mainview->data->node_view));
1295 * Callback for Rename Menuitem
1297 void callback_file_rename_node(GtkAction * action, gpointer data)
1299 MainView *mainview = (MainView*)data;
1300 g_assert(mainview != NULL && mainview->data != NULL);
1302 /* Get the selected node */
1303 nodeData *sel_node = getSelectedNode(mainview);
1304 if (sel_node == NULL) {
1305 /* Do nothing, if no node has been selected */
1306 show_banner(mainview, _("Select a node first"));
1307 return;
1310 if (sel_node->namepix != NULL) {
1311 /* the memo has a graphical label, cannot edit! */
1312 show_banner(mainview, _("Cannot rename memos with sketch name"));
1313 return;
1316 gchar* new_name = show_line_edit_dialog(mainview, _("Rename memo"), _("New name:"), _("Rename"), sel_node->name);
1318 /* Only rename node when user accepted the new name */
1319 if (new_name != NULL) {
1320 callback_rename_node_real(mainview, new_name);
1321 g_free(new_name);
1325 void callback_rename_node_real(MainView* mainview, gchar* new_name)
1327 GtkTreeIter iter;
1328 GtkTreeModel *model;
1329 nodeData *nd = NULL;
1331 /* Get the selected node */
1332 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1334 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
1335 return;
1338 gtk_tree_model_get (model, &iter, NODE_DATA, &nd, -1);
1340 if (nd == NULL) {
1341 return;
1344 /* Update the database */
1345 sqlite3_stmt *stmt = NULL;
1347 char* sql = sqlite3_mprintf("UPDATE %s SET name='%q' WHERE nodeid=%d", datatable_tmpname, new_name, nd->sql3id);
1349 int rc = sqlite3_prepare(mainview->db, sql, strlen(sql), &stmt, NULL);
1350 if (rc == SQLITE_OK) {
1351 rc = SQLITE_BUSY;
1352 while (rc == SQLITE_BUSY) {
1353 rc = sqlite3_step(stmt);
1354 if (rc == SQLITE_DONE) {
1355 /* Update in the database was successful - now update the rest */
1357 /* Update the noteData */
1358 g_free(nd->name);
1359 nd->name = g_strdup(new_name);
1361 /* Update the window title of node_view */
1362 gtk_window_set_title(GTK_WINDOW(mainview->data->node_view), nd->name);
1364 /* Update the value in the tree store */
1365 gtk_tree_store_set (GTK_TREE_STORE(model), &iter, NODE_NAME, new_name, -1);
1367 break;
1368 } else if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE) {
1369 maepad_warning("Error updating node: %s", sqlite3_errmsg(mainview->db));
1370 break;
1373 sqlite3_finalize(stmt);
1374 } else {
1375 maepad_warning("Error preparing DB update query: %s", sqlite3_errmsg(mainview->db));
1378 sqlite3_free(sql);
1380 mainview->file_edited = TRUE;
1383 void callback_file_export_node(GtkAction * action, gpointer data)
1385 MainView *mainview = (MainView *) data;
1386 g_assert(mainview != NULL && mainview->data != NULL);
1388 nodeData *nd=getSelectedNode(mainview);
1389 if (nd == NULL)
1391 show_banner(mainview, _("Select a memo first"));
1392 return;
1395 gchar *nodename=nd->name;
1396 if (nodename==NULL) nodename=_("saved memo");
1398 if (nd->typ == NODE_TEXT)
1401 GtkTextIter begin, end;
1402 gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER(mainview->buffer), &begin, &end);
1403 gchar *text = gtk_text_buffer_get_slice(GTK_TEXT_BUFFER(mainview->buffer), &begin, &end, TRUE);
1405 GString *gstr=g_string_sized_new(4096);
1406 wp_text_buffer_save_document(mainview->buffer, (WPDocumentSaveCallback)(wp_savecallback), gstr);
1407 gint textlen=gstr->len;
1408 gchar *text=g_string_free(gstr, FALSE);
1410 if (text==NULL || !strcmp(text, ""))
1412 show_banner(mainview, _("Memo is empty"));
1414 else
1416 gchar *fn = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, nodename, "html");
1417 if (fn!=NULL)
1419 GnomeVFSResult vfs_result;
1420 GnomeVFSHandle *handle = NULL;
1421 GnomeVFSFileSize out_bytes;
1422 vfs_result = gnome_vfs_create(&handle, fn, GNOME_VFS_OPEN_WRITE, 0, 0600);
1423 if ( vfs_result != GNOME_VFS_OK ) {
1424 show_banner(mainview, _("Export failed"));
1426 else
1428 gnome_vfs_write(handle, text, textlen, &out_bytes);
1429 gnome_vfs_close(handle);
1430 if (out_bytes==strlen(text)) show_banner(mainview, _("Exported"));
1431 else show_banner(mainview, _("Export incomplete"));
1433 g_free(fn);
1436 g_free(text);
1438 else if (nd->typ == NODE_SKETCH)
1440 GdkPixmap *skpix = sketchwidget_get_Pixmap(mainview->sk);
1441 GtkWidget *skdr = sketchwidget_get_drawingarea(mainview->sk);
1442 GdkPixbuf *pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(skpix), NULL, 0, 0, 0, 0, skdr->allocation.width, skdr->allocation.height);
1443 if (pixbuf==NULL)
1445 show_banner(mainview, _("Memo is empty"));
1447 else
1449 gchar *fn = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, nodename, "png");
1450 if (fn!=NULL)
1452 if (gdk_pixbuf_save(pixbuf, fn, "png", NULL, NULL)==FALSE)
1454 show_banner(mainview, _("Export failed"));
1456 else
1458 show_banner(mainview, _("Exported"));
1460 g_free(fn);
1463 g_object_unref(skpix);
1465 else if (nd->typ == NODE_CHECKLIST)
1467 show_banner(mainview, _("Export of checklists not possible yet"));
1472 * callback from menu item
1473 * move selected node down (switch node with next sibling), don't change level of node
1475 void callback_move_down_node(GtkAction * action, gpointer data)
1477 GtkTreeIter iter;
1478 GtkTreeModel *model;
1480 MainView *mainview = (MainView *) data;
1481 g_assert(mainview != NULL && mainview->data != NULL);
1483 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1484 gtk_tree_selection_get_selected(selection, &model, &iter);
1486 GtkTreeIter old_iter = iter;/*save pointer to old iter, we will need it during swap nodes*/
1488 if (gtk_tree_model_iter_next(model,&iter)==FALSE)/*get next node*/
1489 return;
1491 GtkTreeStore *treeStore = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview)));
1492 gtk_tree_store_swap(treeStore,&iter,&old_iter);
1494 mainview->file_edited = TRUE;/*we have made changes , if required show "save changes?" dialog in future*/
1498 * callback from menu item
1499 * move selected node down (switch node with prev sibling), don't change level of node
1501 void callback_move_up_node(GtkAction * action, gpointer data)
1503 GtkTreeIter iter;
1504 GtkTreeModel *model;
1506 MainView *mainview = (MainView *) data;
1507 g_assert(mainview != NULL && mainview->data != NULL);
1509 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1510 gtk_tree_selection_get_selected(selection, &model, &iter);
1512 GtkTreeIter old_iter=iter;/*save pointer to old iter, we will need it during swap nodes*/
1514 if (tree_model_iter_prev(model,&iter)==FALSE)/*get previous node*/
1515 return;
1517 GtkTreeStore *treeStore = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview)));
1518 gtk_tree_store_swap(treeStore,&old_iter,&iter);/*do move*/
1520 mainview->file_edited = TRUE;/*we have made changes , if required show "save changes?" dialog in future*/
1524 * callback from menu item
1525 * we change level of actual node with direction to top
1527 void callback_move_to_top_level_node(GtkAction * action, gpointer data)
1529 GtkTreeIter iter,new_parent;
1530 GtkTreeIter *p_new_parent;
1531 GtkTreeIter parent;
1532 GtkTreeModel *model;
1534 MainView *mainview = (MainView *) data;
1535 g_assert(mainview != NULL && mainview->data != NULL);
1537 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1538 gtk_tree_selection_get_selected(selection, &model, &iter);
1540 /*at first we need actual parent of selected node*/
1541 if (gtk_tree_model_iter_parent(model,&parent,&iter)==FALSE)
1543 /*if parent of selected node is ROOT we can't go higher*/
1544 return;
1546 /*we need also new parent, it's parent of actual parent*/
1547 if (gtk_tree_model_iter_parent(model,&new_parent,&parent)==FALSE)
1549 /*if our new parent is ROOT we got filled new_parent with invalid value,
1550 so we need set NULL value to p_new_parent (root item)*/
1551 p_new_parent=NULL;
1553 else
1555 p_new_parent=&new_parent;/*we only redirect pointer to treeiter*/
1558 saveCurrentData(mainview);/*we save changes in node befor move*/
1560 /*this move function provide move item with all his children, be careful iter value will change!*/
1561 if (move_node(mainview,p_new_parent,&iter,&parent)==TRUE){
1563 gint id_parent = get_node_id_on_tmp_db(model,p_new_parent);
1564 gint id_node = get_node_id_on_tmp_db(model,&iter);
1565 /*we need also update parent id of moved item*/
1566 char tq[512];
1567 g_snprintf (tq, sizeof(tq), "UPDATE %s SET parent=%d WHERE nodeid=%d",datatable_tmpname,id_parent ,id_node);
1568 exec_command_on_db(mainview,tq);
1570 /*select new created iter*/
1571 gtk_tree_selection_select_iter(selection,&iter);
1573 mainview->file_edited = TRUE;/*we have made changes , if required show "save changes?" dialog in future*/
1578 * callback from menu item
1579 * we change level of actual node with direction to bottom
1580 * previous node will be parent of our actual node
1582 void callback_move_to_bottom_level_node(GtkAction * action, gpointer data)
1584 GtkTreeIter iter;
1585 GtkTreeModel *model;
1587 MainView *mainview = (MainView *) data;
1588 g_assert(mainview != NULL && mainview->data != NULL);
1590 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1591 gtk_tree_selection_get_selected(selection, &model, &iter);
1593 GtkTreeIter move_iter=iter;/*save pointer to old iter*/
1595 /*we try to get previous node*/
1596 if (tree_model_iter_prev(model,&iter)==FALSE)
1597 return;/*if previous node on the same level doesn't exist we will exit*/
1599 saveCurrentData(mainview);/*we save changes in node befor move*/
1601 /*this move function provide move item with all his children, be careful move_iter value will change!*/
1602 if (move_node(mainview,&iter,&move_iter,NULL)==TRUE)
1604 gint id_parent = get_node_id_on_tmp_db(model,&iter);
1605 gint id_node = get_node_id_on_tmp_db(model,&move_iter);
1607 /*we need also update parent id of moved item*/
1608 char tq[512];
1609 g_snprintf (tq, sizeof(tq), "UPDATE %s SET parent=%d WHERE nodeid=%d",datatable_tmpname,id_parent ,id_node);
1610 exec_command_on_db(mainview,tq);
1612 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
1613 gtk_tree_view_expand_row(GTK_TREE_VIEW(mainview->treeview), path, FALSE);/*expand parent node*/
1614 gtk_tree_path_free(path);
1616 /*select new created iter*/
1617 gtk_tree_selection_select_iter(selection,&move_iter);
1619 mainview->file_edited = TRUE;/*we have made changes , if required show "save changes?" dialog in future*/
1624 * move item_to_move to new_parent with his children, this function is designed for change level of node
1625 * we copy item_to_move with his children to new position (after item_befor if is not NULL) and then we
1626 * destroy old node with his children, so ! item_to_move is set with new iter, be careful on this!
1628 gboolean move_node(MainView *mainview,GtkTreeIter *new_parent,GtkTreeIter *item_to_move,GtkTreeIter *item_befor)
1630 GtkTreeModel *model;
1632 model=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview));
1633 GtkTreeStore *treeStore = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview)));
1635 nodeData *node;
1636 gtk_tree_model_get(model, item_to_move, NODE_DATA, &node, -1);/*get data from actual iter*/
1637 if (node)
1639 GtkTreeIter new_iter;/*create new iter*/
1640 gtk_tree_store_append(treeStore,&new_iter,new_parent);/*append new iter to new parent*/
1642 if (item_befor!=NULL)
1643 gtk_tree_store_move_after(treeStore,&new_iter,item_befor);/*sometimes we need set position*/
1645 gtk_tree_store_set(treeStore, &new_iter, NODE_NAME, node->name,NODE_PIXBUF, node->namepix, NODE_DATA, node, -1);/*set data from old iter*/
1647 GtkTreeIter child;
1648 while (gtk_tree_model_iter_children(model, &child, item_to_move)==TRUE)/*move all childrens while some exits*/
1650 if (move_node(mainview,&new_iter,&child,NULL)==FALSE)/*use recursion on children*/
1651 return FALSE;
1654 gtk_tree_store_set(treeStore, item_to_move, NODE_DATA, NULL, -1);
1655 gtk_tree_store_remove(treeStore, item_to_move);/*remove node, data need't remove, they are stored in new node*/
1657 /*we need return new value of moved item, so we need assign new_iter to item_to_move*/
1658 /*this code is ugly : new_iter to path and back to item_to_move*/
1659 GtkTreePath *path=gtk_tree_model_get_path(model,&new_iter);
1660 gtk_tree_model_get_iter(model,item_to_move,path);
1661 gtk_tree_path_free(path);
1663 else
1665 fprintf(stderr,"Get data node failed!\n");
1666 return FALSE;
1669 return TRUE;
1673 * simple execute of sql command which is stored in sql_string[]
1675 gboolean exec_command_on_db(MainView *mainview,char sql_string[])
1677 sqlite3_stmt *stmt = NULL;
1678 const char* dum;
1679 gboolean db_query_result = FALSE;
1681 int rc = sqlite3_prepare (mainview->db, sql_string, strlen(sql_string), &stmt, &dum);
1683 if (rc) {
1684 maepad_warning("Error preparing DB update query: %s", sqlite3_errmsg(mainview->db));
1685 return FALSE;
1688 rc = SQLITE_BUSY;
1689 while (rc == SQLITE_BUSY) {
1690 rc = sqlite3_step (stmt);
1691 if (rc == SQLITE_DONE) {
1692 db_query_result = TRUE;
1693 break;
1695 else if(rc == SQLITE_ERROR || rc== SQLITE_MISUSE) {
1696 maepad_warning("Error updating node: %s", sqlite3_errmsg(mainview->db));
1697 break;
1699 sqlite3_finalize(stmt);
1701 return TRUE;
1705 * 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)
1707 gboolean foreach_func_update_ord (GtkTreeModel *model,GtkTreePath *path,GtkTreeIter *iter, MainView *mainview)
1709 nodeData *node;
1710 gtk_tree_model_get(model, iter, NODE_DATA, &node, -1);
1711 /*we need index of node on actual level*/
1712 gint index=get_branch_node_index(path);
1714 /*prepare to execute update command,and exec it*/
1715 char sql_command[512];
1716 g_snprintf (sql_command, sizeof(sql_command), "UPDATE %s SET ord=\"%d\" WHERE nodeid=%d",datatable_tmpname, index, node->sql3id);
1717 exec_command_on_db(mainview,sql_command);
1719 /*we don't want break gtk_tree_model_foreach function,until we call this func on each node - so we return always FALSE*/
1720 return FALSE;
1724 * return id number of iter (id number which is used to identify in sql database of nodes)
1726 int get_node_id_on_tmp_db(GtkTreeModel *model,GtkTreeIter *iter)
1728 if (iter==NULL)
1729 return 0;/*we got ROOT parent here*/
1731 nodeData *node;
1732 gtk_tree_model_get(model, iter, NODE_DATA, &node, -1);
1733 return node->sql3id;
1737 * get index of node in current branch
1739 gint get_branch_node_index(GtkTreePath *path)
1741 int depth=gtk_tree_path_get_depth(path);
1742 gint *indicies = gtk_tree_path_get_indices(path);
1744 return indicies[depth-1];
1748 * similiar with gtk_tree_model_iter_next (), but opposite
1750 gboolean tree_model_iter_prev(GtkTreeModel *tree_model,GtkTreeIter *iter)
1752 GtkTreePath *path = gtk_tree_model_get_path(tree_model, iter);
1754 if (path==NULL){
1755 fprintf(stderr,"Error: path is null\n");
1756 return FALSE;
1759 if (gtk_tree_path_prev(path)==FALSE)
1760 return FALSE;
1762 gtk_tree_model_get_iter(tree_model, iter,path);
1764 return TRUE;
1767 gboolean ref2iter(GtkTreeModel * model, GtkTreeRowReference * ref, GtkTreeIter * iter)
1769 gboolean res = FALSE;
1770 GtkTreePath *path = gtk_tree_row_reference_get_path(ref);
1772 if (gtk_tree_model_get_iter(model, iter, path))
1774 res = TRUE;
1776 gtk_tree_path_free(path);
1777 return (res);
1780 GtkTreeRowReference *iter2ref(GtkTreeModel * model, GtkTreeIter * iter)
1782 GtkTreeRowReference *ref;
1784 GtkTreePath *path = gtk_tree_model_get_path(model, iter);
1786 ref = gtk_tree_row_reference_new(model, path);
1787 gtk_tree_path_free(path);
1788 return (ref);
1791 void move_nodes_up(GtkTreeModel * model, GtkTreeRowReference * topnode, GtkTreeRowReference * newtop)
1793 GtkTreeIter topiter;
1795 if (ref2iter(model, topnode, &topiter) == FALSE)
1796 return;
1798 GtkTreeIter child;
1800 if (gtk_tree_model_iter_children(model, &child, &topiter))
1802 GtkTreeRowReference *ref;
1803 GList *rr_list = NULL, *node;
1807 ref = iter2ref(model, &child);
1808 rr_list = g_list_append(rr_list, ref);
1810 while(gtk_tree_model_iter_next(model, &child));
1813 * got a reflist for all children
1816 for(node = rr_list; node; node = node->next)
1818 ref = (GtkTreeRowReference *) (node->data);
1819 if (ref2iter(model, ref, &child))
1821 GtkTreeIter newtopiter, newiter;
1822 GtkTreeIter *newtopiterptr;
1824 if (ref2iter(model, newtop, &newtopiter))
1825 newtopiterptr = &newtopiter;
1826 else
1827 newtopiterptr = NULL;
1829 nodeData *node;
1831 gtk_tree_model_get(model, &child, NODE_DATA, &node, -1);
1833 gtk_tree_store_append(GTK_TREE_STORE(model), &newiter, newtopiterptr);
1834 gtk_tree_store_set(GTK_TREE_STORE(model), &newiter, NODE_NAME, node->name, NODE_PIXBUF, node->namepix, NODE_DATA, node, -1);
1836 GtkTreeRowReference *newref = iter2ref(model, &newiter);
1838 move_nodes_up(model, ref, newref);
1839 gtk_tree_row_reference_free(newref);
1841 gtk_tree_store_remove(GTK_TREE_STORE(model), &child);
1843 gtk_tree_row_reference_free(ref);
1846 g_list_free(rr_list);
1851 void callback_delete_node_real(MainView* mainview)
1853 GtkTreeIter iter;
1854 GtkTreeModel *model;
1856 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1858 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
1859 return;
1861 nodeData *nd;
1863 gtk_tree_model_get(model, &iter, NODE_DATA, &nd, -1);
1864 if (!nd)
1865 return;
1867 mainview->file_edited = TRUE;
1869 unsigned int sql3id = nd->sql3id;
1871 if (nd->name)
1872 g_free(nd->name);
1875 * g_free(nd->data);
1876 * if (nd->pix) g_object_unref(nd->pix);
1878 g_free(nd);
1880 GtkTreeRowReference *upref = NULL, *ref = NULL;
1882 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
1884 ref = gtk_tree_row_reference_new(model, path);
1885 if (gtk_tree_path_up(path))
1886 upref = gtk_tree_row_reference_new(model, path);
1887 gtk_tree_path_free(path);
1889 g_object_ref(model);
1890 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), NULL);
1892 move_nodes_up(model, ref, upref);
1894 if (ref2iter(model, ref, &iter))
1896 char tq[512];
1898 g_snprintf(tq, sizeof(tq), "SELECT parent FROM %s WHERE nodeid=%d", datatable_tmpname, sql3id);
1899 sqlite3_stmt *stmt = NULL;
1900 const char *dum;
1901 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
1902 unsigned int sql3parentid = 0;
1904 if (rc)
1906 maepad_warning("Error finding children for delete: %s", sqlite3_errmsg(mainview->db));
1908 else
1910 rc = SQLITE_BUSY;
1911 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
1913 rc = sqlite3_step(stmt);
1914 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
1915 break;
1916 else if (rc == SQLITE_ROW)
1918 sql3parentid = sqlite3_column_int(stmt, 0);
1919 break;
1922 sqlite3_finalize(stmt);
1924 g_snprintf(tq, sizeof(tq), "UPDATE %s SET parent=%d WHERE parent=%d;", datatable_tmpname, sql3parentid, sql3id);
1925 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
1926 maepad_warning("Error moving nodes up one level");
1927 } else
1929 g_snprintf(tq, sizeof(tq), "DELETE FROM %s WHERE nodeid=%d;", datatable_tmpname, sql3id);
1930 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
1931 maepad_warning("Error deleting node");
1934 /* Delete all checklist items that do not have
1935 * a node anymore (= orphaned checklist items) */
1936 g_snprintf(tq, sizeof(tq), "DELETE FROM %s WHERE nodeid NOT IN (SELECT nodeid FROM %s);", checklisttable_tmpname, datatable_tmpname);
1937 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
1938 maepad_warning("Error deleting orphaned checklist items");
1942 gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
1945 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), model);
1946 g_object_unref(model);
1948 gtk_tree_row_reference_free(ref);
1949 gtk_tree_row_reference_free(upref);
1951 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview->treeview));
1955 void callback_edit_clear(GtkAction * action, gpointer data)
1957 MainView *mainview = (MainView *) data;
1958 g_assert(mainview != NULL && mainview->data != NULL);
1959 nodeData *nd = getSelectedNode(mainview);
1961 if (show_confirmation(mainview, _("Remove all contents of this memo?"))) {
1962 switch (nd->typ) {
1963 case NODE_TEXT:
1964 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), "", 0);
1965 break;
1966 case NODE_SKETCH:
1967 sketchwidget_clear(mainview->sk);
1968 break;
1969 case NODE_CHECKLIST:
1970 gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview))));
1971 break;
1972 default:
1973 /* Unknown node type */
1974 g_assert(FALSE);
1980 * cut
1982 void callback_edit_cut(GtkAction * action, gpointer data)
1984 MainView *mainview = (MainView *) data;
1985 g_assert(mainview != NULL && mainview->data != NULL);
1987 nodeData *nd = getSelectedNode(mainview);
1989 if (nd->typ == NODE_TEXT)
1990 gtk_text_buffer_cut_clipboard(GTK_TEXT_BUFFER(mainview->buffer), mainview->clipboard, TRUE);
1991 else if (nd->typ == NODE_SKETCH)
1993 if (sketchwidget_cut(mainview->sk, mainview->clipboard)==FALSE)
1994 show_banner(mainview, _("Error cutting"));
1996 else if (nd->typ == NODE_CHECKLIST)
1997 show_banner(mainview, _("Unimplemented"));
2002 * copy
2004 void callback_edit_copy(GtkAction * action, gpointer data)
2006 MainView *mainview = (MainView *) data;
2007 g_assert(mainview != NULL && mainview->data != NULL);
2009 nodeData *nd = getSelectedNode(mainview);
2011 if (nd->typ == NODE_TEXT)
2012 gtk_text_buffer_copy_clipboard(GTK_TEXT_BUFFER(mainview->buffer), mainview->clipboard);
2013 else if (nd->typ == NODE_SKETCH)
2015 if (sketchwidget_copy(mainview->sk, mainview->clipboard)==FALSE)
2016 show_banner(mainview, _("Error copying"));
2018 else if (nd->typ == NODE_CHECKLIST)
2020 /* Copy all selected entries as multiline text (1 line per entry) */
2021 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
2022 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview));
2024 gint selected_rows = gtk_tree_selection_count_selected_rows(selection);
2025 GList* l = gtk_tree_selection_get_selected_rows(selection, NULL);
2027 GtkTreeIter iter;
2028 gchar *str_data;
2030 gchar **entries = g_malloc0(sizeof(gchar*)*selected_rows+1);
2031 gint entries_idx = 0;
2033 GList* cur = l;
2034 while(cur) {
2035 GtkTreePath *path = cur->data;
2037 if (gtk_tree_model_get_iter(model, &iter, path)) {
2038 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHECKNODE_TEXT, &(entries[entries_idx++]), -1);
2040 gtk_tree_path_free(path);
2042 cur = cur->next;
2045 g_list_free(l);
2046 str_data = g_strjoinv("\n", entries);
2047 g_strfreev(entries);
2048 gtk_clipboard_set_text(mainview->clipboard, str_data, -1);
2049 g_free(str_data);
2051 str_data = g_strdup_printf(_("Copied %d entries"), selected_rows);
2052 show_banner(mainview, str_data);
2053 g_free(str_data);
2059 * paste
2061 void callback_edit_paste(GtkAction * action, gpointer data)
2063 MainView *mainview = (MainView *) data;
2064 g_assert(mainview != NULL && mainview->data != NULL);
2066 nodeData *nd = getSelectedNode(mainview);
2068 if (nd->typ == NODE_TEXT)
2069 gtk_text_buffer_paste_clipboard(GTK_TEXT_BUFFER(mainview->buffer), mainview->clipboard, NULL, TRUE);
2070 else if (nd->typ == NODE_SKETCH)
2072 if (sketchwidget_paste(mainview->sk, mainview->clipboard)==FALSE)
2073 show_banner(mainview, _("Error pasting"));
2075 else if (nd->typ == NODE_CHECKLIST) {
2076 /* Paste string from clipboard as new item */
2077 callback_checklist_paste(mainview);
2080 mainview->file_edited = TRUE;
2083 gint cb_popup(GtkWidget * widget, GdkEvent * event)
2085 GtkMenu *menu;
2086 GdkEventButton *event_button;
2089 * The "widget" is the menu that was supplied when
2090 * * g_signal_connect_swapped() was called.
2092 menu = GTK_MENU(widget);
2093 event_button = (GdkEventButton *) event;
2094 if (event->type == GDK_BUTTON_PRESS && event_button->button == 3)
2096 gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event_button->button, event_button->time);
2097 return TRUE;
2099 return FALSE;
2103 * close
2105 gboolean closefile(MainView * mainview)
2107 saveCurrentData(mainview);
2109 if (mainview->file_edited)
2111 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));
2112 gint answer = gtk_dialog_run(GTK_DIALOG(hn));
2113 gtk_widget_destroy(GTK_WIDGET(hn));
2115 if (answer == CONFRESP_CANCEL)
2116 return (FALSE);
2117 else if (answer == CONFRESP_YES)
2119 if (mainview->file_name == NULL)
2121 mainview->file_name = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, "maemopaddata", "db");
2123 write_buffer_to_file(mainview);
2127 if (mainview->db)
2128 sqlite3_close(mainview->db);
2129 mainview->db = NULL;
2130 return (TRUE);
2133 gboolean callback_file_close(GtkAction * action, gpointer data)
2136 MainView *mainview = (MainView *) data;
2137 g_assert(mainview != NULL && mainview->data != NULL);
2138 if (closefile(mainview) == FALSE)
2139 return(FALSE);
2141 gtk_main_quit();
2142 return(TRUE);
2145 void callback_file_new_node(GtkAction * action, gpointer data)
2147 MainView *mainview = (MainView *) data;
2148 g_assert(mainview != NULL && mainview->data != NULL);
2150 nodeType typ = NODE_SKETCH;
2152 nodeData *nd = getSelectedNode(mainview);
2154 if (nd != NULL)
2155 typ = nd->typ;
2157 new_node_dialog(typ, mainview);
2161 * new
2163 void callback_file_new(GtkAction * action, gpointer data)
2165 MainView *mainview = (MainView *) data;
2166 g_assert(mainview != NULL && mainview->data != NULL);
2168 gchar *filename = NULL;
2170 if (closefile(mainview) == FALSE)
2171 return;
2173 filename = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, "memos", "db");
2174 if (filename == NULL)
2175 return;
2177 new_file(mainview);
2181 busy_enter(mainview);
2183 int rc;
2185 rc = sqlite3_open(filename, &mainview->db);
2186 if (rc)
2188 show_banner(mainview, _("Cannot create database"));
2189 maepad_warning("Can't create database %s: %s", filename, sqlite3_errmsg(mainview->db));
2190 break;
2193 sqlite3_exec(mainview->db, "PRAGMA synchronous = OFF;", NULL, NULL, NULL);
2195 char tq[512];
2197 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", misctable_name, misctable);
2198 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
2200 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", datatable_name, datatable);
2201 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
2203 maepad_warning("Cannot create data table");
2204 show_banner(mainview, _("Error creating data table"));
2205 break;
2208 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", checklisttable_name, checklisttable);
2209 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
2211 maepad_warning("Cannot create checklist table");
2212 show_banner(mainview, _("Error creating checklist table"));
2213 break;
2216 if (mainview->db)
2217 sqlite3_close(mainview->db);
2218 mainview->db = NULL;
2220 mainview->file_name = filename;
2221 mainview->file_edited = FALSE;
2222 read_file_to_buffer(mainview);
2224 /*add a starter memo*/
2225 nodeData *node;
2226 node = g_malloc(sizeof(nodeData));
2227 node->typ = NODE_SKETCH;
2228 node->name = _("My first memo");
2229 node->namepix = NULL;
2230 node->lastMod = 0;
2231 node->flags = 0;
2232 node->sql3id = 0;
2233 add_new_node(node, mainview, TRUE);
2234 /*gtk_paned_set_position(GTK_PANED(mainview->hpaned), 180);*/
2235 write_buffer_to_file(mainview);
2237 }while(FALSE);
2238 busy_reset(mainview);
2241 gboolean reset_ctree(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter, gpointer data)
2243 nodeData *node;
2245 gtk_tree_model_get(model, iter, NODE_DATA, &node, -1);
2246 if (node)
2248 if (node->name)
2249 g_free(node->name);
2250 if (node->namepix)
2251 g_object_unref(node->namepix);
2252 g_free(node);
2254 gtk_tree_store_set(GTK_TREE_STORE(model), iter, NODE_DATA, NULL, -1);
2256 return (FALSE);
2259 void new_file(MainView * mainview)
2261 busy_enter(mainview);
2263 * clear buffer, filename and free buffer text
2265 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), "", -1);
2266 mainview->file_name = NULL;
2267 mainview->file_edited = FALSE;
2268 mainview->newnodedialog_createchild = TRUE;
2270 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview));
2272 g_object_ref(model);
2273 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), NULL);
2275 gtk_tree_model_foreach(model, (GtkTreeModelForeachFunc) reset_ctree, (gpointer) mainview);
2278 * crashing bastard
2279 * gtk_tree_store_clear(GTK_TREE_STORE(model));
2281 GtkTreePath *path = gtk_tree_path_new_from_indices(0, -1);
2282 GtkTreeIter iter;
2284 if (gtk_tree_model_get_iter(model, &iter, path))
2288 gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
2290 while(gtk_tree_store_iter_is_valid(GTK_TREE_STORE(model), &iter));
2292 gtk_tree_path_free(path);
2294 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), model);
2295 g_object_unref(model);
2297 prepareUIforNodeChange(mainview, NODE_UNKNOWN);
2298 busy_leave(mainview);
2302 * open
2304 void callback_file_open(GtkAction * action, gpointer data)
2306 gchar *filename = NULL;
2307 MainView *mainview = (MainView *) data;
2308 g_assert(mainview != NULL && mainview->data != NULL);
2310 if (closefile(mainview) == FALSE)
2311 return;
2314 * open new file
2316 filename = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_OPEN, NULL, NULL);
2319 * if we got a file name from chooser -> open file
2321 open_file(filename, mainview);
2322 g_free(filename);
2325 gboolean open_file(gchar * filename, MainView * mainview)
2327 gboolean ret=FALSE;
2329 busy_enter(mainview);
2331 while(filename != NULL)
2333 struct stat s;
2335 if (stat(filename, &s) == -1) break;
2337 mainview->file_name = g_strdup(filename);
2338 gboolean res = read_file_to_buffer(mainview);
2340 if (res == FALSE)
2342 g_free(mainview->file_name);
2343 mainview->file_name = NULL;
2344 break;
2346 mainview->file_edited = FALSE;
2347 ret=TRUE;
2348 break;
2351 busy_leave(mainview);
2352 return(ret);
2355 void callback_about_link(GtkAboutDialog *about, const gchar *link, gpointer data)
2357 MainView *mainview = (MainView *) data;
2358 g_assert(mainview != NULL && mainview->data != NULL);
2359 osso_rpc_run_with_defaults(mainview->data->osso, "osso_browser", OSSO_BROWSER_OPEN_NEW_WINDOW_REQ, NULL,
2360 DBUS_TYPE_STRING, link, DBUS_TYPE_INVALID);
2363 void callback_about(GtkAction * action, gpointer data)
2365 MainView* mainview = (MainView *)data;
2366 he_about_dialog_present(mainview_get_dialog_parent(mainview),
2367 NULL /* auto-detect app name */,
2368 "maepad",
2369 VERSION,
2370 _("A node-based memory pad for Maemo"),
2371 _("(c) 2008-2010 Thomas Perl, (c) 2006-2008 Kemal Hadimli"),
2372 "http://thpinfo.com/2010/maepad/",
2373 NULL /* TODO: Add bug tracker URL */,
2374 "http://thpinfo.com/2010/maepad/donate");
2378 * save
2380 void callback_file_save(GtkAction * action, gpointer data)
2382 gchar *filename = NULL;
2383 MainView *mainview = (MainView *) data;
2384 g_assert(mainview != NULL && mainview->data != NULL);
2387 * check is we had a new file
2389 if (mainview->file_name != NULL)
2391 write_buffer_to_file(mainview);
2393 else
2395 filename = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, "maemopaddata", "db");
2397 * if we got a file name from chooser -> save file
2399 if (filename != NULL)
2401 mainview->file_name = filename;
2402 write_buffer_to_file(mainview);
2403 mainview->file_edited = FALSE;
2408 void callback_shapemenu(GtkAction * action, GtkWidget * wid)
2410 int style = (int)gtk_object_get_user_data(GTK_OBJECT(wid));
2411 MainView *mainview = gtk_object_get_data(GTK_OBJECT(wid), "m");
2413 g_assert(mainview != NULL);
2415 if (style==0) sketchwidget_set_shape(mainview->sk, SKETCHSHAPE_FREEHAND);
2416 else if (style==1) sketchwidget_set_shape(mainview->sk, SKETCHSHAPE_LINE);
2417 else if (style==2) sketchwidget_set_shape(mainview->sk, SKETCHSHAPE_RECT);
2418 else if (style==3) sketchwidget_set_shape(mainview->sk, SKETCHSHAPE_ELLIPSE);
2423 void callback_eraser(GtkAction * action, MainView * mainview)
2425 g_assert(mainview != NULL && mainview->data != NULL);
2427 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mainview->eraser_tb)) == TRUE)
2429 GdkColor c2;
2431 c2.red = 65535;
2432 c2.green = 65535;
2433 c2.blue = 65535;
2435 mainview->sk->pressuresensitivity=FALSE;
2437 sketchwidget_set_brushcolor(mainview->sk, c2);
2438 mainview->brushsize_backup = sketchwidget_get_brushsize(mainview->sk);
2439 guint ers=(mainview->brushsize_backup*4)+4;
2440 sk_set_brushsize(mainview, ers);
2441 sketchwidget_set_brushsize(mainview->sk, ers); /*fixme:to override max brush size, not pretty*/
2443 else
2445 if (mainview->current_color == NULL) {
2446 GdkColor color = {0, 0, 0, 0};
2447 mainview->current_color = gdk_color_copy(&color);
2449 /* pressure sensitivity disabled for now...
2450 mainview->sk->pressuresensitivity=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(mainview->tools_pressure));*/
2452 sketchwidget_set_brushcolor(mainview->sk, *(mainview->current_color));
2453 sk_set_brushsize(mainview, mainview->brushsize_backup);
2457 void callback_menu(GtkAction * action, GtkWidget * menu)
2459 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, GDK_CURRENT_TIME);
2462 void callback_brushsizetb(GtkAction * action, MainView *mainview)
2464 g_assert(mainview != NULL && mainview->data != NULL);
2466 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mainview->eraser_tb)) == TRUE)
2468 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->eraser_tb), FALSE);
2470 else
2472 callback_menu(NULL, mainview->brushsizemenu);
2476 void callback_brushsize(GtkAction * action, GtkWidget * wid)
2478 int bsize = (int)gtk_object_get_user_data(GTK_OBJECT(wid));
2479 MainView *mainview = gtk_object_get_data(GTK_OBJECT(wid), "m");
2481 g_assert(mainview != NULL && mainview->data != NULL);
2483 sketchwidget_set_brushsize(mainview->sk, bsize);
2485 GtkWidget *pix = gtk_object_get_data(GTK_OBJECT(wid), "i");
2487 gtk_widget_show(pix);
2488 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview->brushsize_tb), pix);
2491 void callback_sketchlines(GtkAction * action, GtkWidget * wid)
2493 int style = (int)gtk_object_get_user_data(GTK_OBJECT(wid));
2494 MainView *mainview = gtk_object_get_data(GTK_OBJECT(wid), "m");
2496 g_assert(mainview != NULL);
2498 nodeData *nd = getSelectedNode(mainview);
2499 gboolean doit = FALSE;
2501 if (nd != NULL && nd->typ == NODE_SKETCH)
2503 nd->flags &= ~NODEFLAG_SKETCHLINES;
2504 nd->flags &= ~NODEFLAG_SKETCHGRAPH;
2505 /* sketchwidget_set_edited(mainview->sk, TRUE);*/ /*we call this on openfile, so this messes things up*/
2506 doit = TRUE;
2509 if (style == 0)
2511 sketchwidget_set_backstyle(mainview->sk, SKETCHBACK_NONE);
2513 else if (style == 1)
2515 sketchwidget_set_backstyle(mainview->sk, SKETCHBACK_LINES);
2516 if (doit == TRUE)
2517 nd->flags |= NODEFLAG_SKETCHLINES;
2519 else if (style == 2)
2521 sketchwidget_set_backstyle(mainview->sk, SKETCHBACK_GRAPH);
2522 if (doit == TRUE)
2523 nd->flags |= NODEFLAG_SKETCHGRAPH;
2526 GtkWidget *pix = gtk_object_get_data(GTK_OBJECT(wid), "i");
2528 gtk_widget_show(pix);
2529 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview->sketchlines_tb), pix);
2532 void callback_color(GtkAction* action, MainView* mainview)
2534 g_assert(mainview != NULL && mainview->data != NULL);
2536 nodeData *nd = getSelectedNode(mainview);
2537 if (nd == NULL) return;
2539 HeSimpleColorDialog* dialog = HE_SIMPLE_COLOR_DIALOG(he_simple_color_dialog_new());
2540 gtk_window_set_transient_for(GTK_WINDOW(dialog), mainview_get_dialog_parent(mainview));
2542 if (mainview->current_color) {
2543 he_simple_color_dialog_set_color(dialog, mainview->current_color);
2546 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
2547 gtk_widget_destroy(GTK_WIDGET(dialog));
2548 return;
2551 gdk_color_free(mainview->current_color);
2552 mainview->current_color = he_simple_color_dialog_get_color(dialog);
2554 gtk_widget_destroy(GTK_WIDGET(dialog));
2556 switch (nd->typ) {
2557 case NODE_SKETCH:
2558 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->eraser_tb), FALSE);
2559 sketchwidget_set_brushcolor(mainview->sk, *(mainview->current_color));
2560 break;
2561 case NODE_CHECKLIST:
2562 { /* Put in a separate block to allow new local variables */
2563 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
2564 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview));
2565 GList* selected = gtk_tree_selection_get_selected_rows(selection, NULL);
2567 gchar* color_string = g_strdup_printf("#%02x%02x%02x",
2568 mainview->current_color->red >> 8,
2569 mainview->current_color->green >> 8,
2570 mainview->current_color->blue >> 8);
2572 GList* cur = selected;
2573 while (cur != NULL) {
2574 GtkTreePath* path = cur->data;
2575 GtkTreeIter iter;
2576 if (gtk_tree_model_get_iter(model, &iter, path)) {
2577 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_COLOR, color_string, -1);
2579 gtk_tree_path_free(path);
2580 cur = cur->next;
2583 g_list_free(selected);
2584 g_free(color_string);
2586 break;
2587 default:
2588 g_error("Wrong node type for color selection");
2589 return;
2593 void callback_color_invoke(GtkAction * action, gpointer data)
2595 MainView *mainview = (MainView *) data;
2596 g_assert(mainview != NULL && mainview->data != NULL);
2597 gtk_button_clicked(GTK_BUTTON(mainview->colorbutton_tb));
2602 void callback_pressure(GtkAction * action, MainView *mainview)
2604 g_assert(mainview != NULL && mainview->data != NULL);
2606 nodeData *nd = getSelectedNode(mainview);
2608 if (nd == NULL)
2609 return;
2610 if (nd->typ != NODE_SKETCH)
2611 return;
2613 /* pressure sensitivity disabled for now...
2614 mainview->sk->pressuresensitivity=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(mainview->tools_pressure));*/
2618 void callback_wordwrap(GtkAction * action, MainView *mainview)
2620 g_assert(mainview != NULL && mainview->data != NULL);
2622 nodeData *nd = getSelectedNode(mainview);
2624 if (nd == NULL)
2625 return;
2626 if (nd->typ != NODE_TEXT)
2627 return;
2629 gboolean act=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(mainview->tools_wordwrap));
2630 if (act==TRUE) nd->flags |= NODEFLAG_WORDWRAP;
2631 else nd->flags &= ~NODEFLAG_WORDWRAP;
2633 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(mainview->textview), (act==TRUE)?GTK_WRAP_WORD:GTK_WRAP_NONE);
2637 void callback_font(GtkAction * action, gpointer data)
2639 MainView *mainview = (MainView *) data;
2640 g_assert(mainview != NULL && mainview->data != NULL);
2642 nodeData *nd = getSelectedNode(mainview);
2644 if (nd == NULL)
2645 return;
2646 if (nd->typ != NODE_TEXT)
2647 return;
2649 HildonFontSelectionDialog *dialog = HILDON_FONT_SELECTION_DIALOG(hildon_font_selection_dialog_new(NULL, NULL));
2651 gboolean gotsel=wp_text_buffer_has_selection(mainview->buffer);
2652 /*gotsel=FALSE;*/
2654 WPTextBufferFormat fmt;
2655 wp_text_buffer_get_attributes(mainview->buffer, &fmt, gotsel);
2657 gint ri=0;
2658 if (fmt.text_position==TEXT_POSITION_SUPERSCRIPT) ri=1;
2659 else if (fmt.text_position==TEXT_POSITION_SUBSCRIPT) ri=-1;
2661 g_object_set(G_OBJECT(dialog),
2662 "family-set", fmt.cs.font,
2663 "family", wp_get_font_name(fmt.font),
2664 "size-set", fmt.cs.font_size,
2665 "size", wp_font_size[fmt.font_size],
2666 "color-set", fmt.cs.color,
2667 "color", &fmt.color,
2668 "bold-set", fmt.cs.bold,
2669 "bold", fmt.bold,
2670 "italic-set", fmt.cs.italic,
2671 "italic", fmt.italic,
2672 "underline-set", fmt.cs.underline,
2673 "underline", fmt.underline,
2674 "strikethrough-set", fmt.cs.strikethrough,
2675 "strikethrough", fmt.strikethrough,
2676 "position-set", fmt.cs.text_position,
2677 "position", ri,
2678 NULL);
2680 gtk_widget_show_all(GTK_WIDGET(dialog));
2681 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
2683 gboolean bold, italic, underline, strikethrough;
2684 gchar *family = NULL;
2685 gint size, position;
2686 GdkColor *color=NULL;
2687 gboolean set_family, set_size, set_bold, set_italic, set_underline, set_strikethrough, set_color, set_position;
2689 g_object_get(G_OBJECT(dialog), "family", &family, "size", &size, "bold", &bold, "italic", &italic,
2690 "underline", &underline, "strikethrough", &strikethrough,
2691 "family-set", &set_family, "size-set", &set_size, "bold-set", &set_bold, "italic-set", &set_italic,
2692 "underline-set", &set_underline, "strikethrough-set", &set_strikethrough,
2693 "color", &color, "color-set", &set_color, "position", &position, "position-set", &set_position,
2694 NULL);
2696 wp_text_buffer_get_attributes(mainview->buffer, &fmt, FALSE);
2697 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;
2699 if (set_family) { fmt.font=wp_get_font_index(family, 1); fmt.cs.font=1; }
2700 if (set_size) { fmt.font_size=wp_get_font_size_index(size, 16); fmt.cs.font_size=1; }
2702 if (set_strikethrough)
2704 fmt.cs.strikethrough=1;
2705 fmt.strikethrough=strikethrough;
2708 if (set_color)
2711 GLIB WARNING ** GLib-GObject - IA__g_object_set_valist: object class `GtkTextTag' has no property named `'
2713 fmt.cs.color=1;
2714 fmt.color.pixel=color->pixel;
2715 fmt.color.red=color->red;
2716 fmt.color.green=color->green;
2717 fmt.color.blue=color->blue;
2720 if (set_position)
2722 if (position==1) ri=TEXT_POSITION_SUPERSCRIPT;
2723 else if (position==-1) ri=TEXT_POSITION_SUBSCRIPT;
2724 else ri=TEXT_POSITION_NORMAL;
2726 fmt.cs.text_position=1;
2727 fmt.text_position=ri;
2730 if (set_bold)
2732 fmt.cs.bold=1;
2733 fmt.bold=bold;
2735 if (set_italic)
2737 fmt.cs.italic=1;
2738 fmt.italic=italic;
2740 if (set_underline)
2742 fmt.cs.underline=1;
2743 fmt.underline=underline;
2746 wp_text_buffer_set_format(mainview->buffer, &fmt);
2749 gtk_widget_destroy(GTK_WIDGET(dialog));
2752 void callback_fontstyle(GtkAction * action, GtkWidget * wid)
2754 MainView *mainview = gtk_object_get_data(GTK_OBJECT(wid), "m");
2755 g_assert(mainview != NULL && mainview->data != NULL);
2757 nodeData *nd = getSelectedNode(mainview);
2759 if (nd == NULL)
2760 return;
2761 if (nd->typ == NODE_TEXT)
2763 gboolean act=gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(wid));
2765 gint style = (gint)gtk_object_get_data(GTK_OBJECT(wid), "s");
2766 wp_text_buffer_set_attribute(mainview->buffer, style, (gpointer)act);
2768 else if (nd->typ == NODE_CHECKLIST)
2770 gboolean act=gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(wid));
2771 gint style = (gint)gtk_object_get_data(GTK_OBJECT(wid), "s");
2772 if (style!=WPT_BOLD && style!=WPT_STRIKE && style!=WPT_LEFT) return;
2774 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
2775 GList* l=gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview)), NULL);
2777 gint styletoset_weight=PANGO_WEIGHT_NORMAL;
2778 gboolean styletoset_strike=FALSE;
2779 gboolean checkit=FALSE;
2781 if (style==WPT_BOLD && act==TRUE) styletoset_weight=PANGO_WEIGHT_BOLD;
2782 else if (style==WPT_STRIKE && act==TRUE) styletoset_strike=TRUE;
2783 else if (style==WPT_LEFT && act==TRUE) checkit=TRUE;
2785 GList* cur=l;
2786 while(cur)
2788 GtkTreePath *path=cur->data;
2790 GtkTreeIter iter;
2791 if (gtk_tree_model_get_iter(model, &iter, path))
2793 if (style==WPT_BOLD) gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_BOLD, styletoset_weight, -1);
2794 else if (style==WPT_STRIKE) gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_STRIKE, styletoset_strike, -1);
2795 else if (style==WPT_LEFT) {
2796 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_CHECKED, checkit, -1);
2797 if (checkit) {
2798 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_ICON_NAME, "widgets_tickmark_list", -1);
2799 } else {
2800 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_ICON_NAME, NULL, -1);
2804 gtk_tree_path_free(path);
2805 cur=cur->next;
2808 g_list_free(l);
2809 mainview->checklist_edited = TRUE;
2814 void callback_textbuffer_move(WPTextBuffer *textbuffer, MainView *mainview)
2816 g_assert(mainview != NULL && mainview->data != NULL);
2819 gboolean gotsel=wp_text_buffer_has_selection(mainview->buffer);
2821 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), gotsel);
2822 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->italic_tb), gotsel);
2823 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->underline_tb), gotsel);
2824 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->bullet_tb), gotsel);
2826 WPTextBufferFormat fmt;
2827 wp_text_buffer_get_attributes(mainview->buffer, &fmt, FALSE/*gotsel*/);
2829 g_signal_handlers_block_by_func(mainview->bold_tb, callback_fontstyle, mainview->bold_tb);
2830 g_signal_handlers_block_by_func(mainview->italic_tb, callback_fontstyle, mainview->italic_tb);
2831 g_signal_handlers_block_by_func(mainview->underline_tb, callback_fontstyle, mainview->underline_tb);
2832 g_signal_handlers_block_by_func(mainview->bullet_tb, callback_fontstyle, mainview->bullet_tb);
2834 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), fmt.bold);
2835 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->italic_tb), fmt.italic);
2836 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->underline_tb), fmt.underline);
2837 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->bullet_tb), fmt.bullet);
2839 g_signal_handlers_unblock_by_func(mainview->bold_tb, callback_fontstyle, mainview->bold_tb);
2840 g_signal_handlers_unblock_by_func(mainview->italic_tb, callback_fontstyle, mainview->italic_tb);
2841 g_signal_handlers_unblock_by_func(mainview->underline_tb, callback_fontstyle, mainview->underline_tb);
2842 g_signal_handlers_unblock_by_func(mainview->bullet_tb, callback_fontstyle, mainview->bullet_tb);
2845 gint wp_savecallback(const gchar *buffer, GString * gstr)
2847 gstr=g_string_append(gstr, buffer);
2848 return(0);
2851 void callback_undo(GtkAction * action, MainView * mainview)
2853 g_assert(mainview != NULL && mainview->data != NULL);
2855 nodeData *nd = getSelectedNode(mainview);
2857 if (nd == NULL) return;
2859 if (nd->typ == NODE_SKETCH) sketchwidget_undo(mainview->sk);
2860 else if (nd->typ == NODE_TEXT) wp_text_buffer_undo(mainview->buffer);
2863 void callback_redo(GtkAction * action, MainView * mainview)
2865 g_assert(mainview != NULL && mainview->data != NULL);
2867 nodeData *nd = getSelectedNode(mainview);
2869 if (nd == NULL) return;
2871 if (nd->typ == NODE_SKETCH) sketchwidget_redo(mainview->sk);
2872 else if (nd->typ == NODE_TEXT) wp_text_buffer_redo(mainview->buffer);
2875 void callback_undotoggle(gpointer widget, gboolean st, MainView * mainview)
2877 g_assert(mainview != NULL && mainview->data != NULL);
2879 gtk_widget_set_sensitive(GTK_WIDGET(mainview->undo_tb), st);
2882 void callback_redotoggle(gpointer widget, gboolean st, MainView * mainview)
2884 g_assert(mainview != NULL && mainview->data != NULL);
2886 gtk_widget_set_sensitive(GTK_WIDGET(mainview->redo_tb), st);
2889 gboolean close_cb(GtkWidget * widget, GdkEventAny * event, MainView * mainview)
2891 callback_file_close(NULL, mainview);
2892 return (TRUE);
2895 gboolean key_press_cb(GtkWidget * widget, GdkEventKey * event, MainView * mainview)
2897 switch (event->keyval)
2901 * case GDK_Up:
2902 * gtk_infoprint(GTK_WINDOW(app), "Navigation Key Up");
2903 * return TRUE;
2905 * case GDK_Down:
2906 * gtk_infoprint(GTK_WINDOW(app), "Navigation Key Down");
2907 * return TRUE;
2909 * case GDK_Left:
2910 * gtk_infoprint(GTK_WINDOW(app), "Navigation Key Left");
2911 * return TRUE;
2913 * case GDK_Right:
2914 * gtk_infoprint(GTK_WINDOW(app), "Navigation Key Right");
2915 * return TRUE;
2917 * case GDK_Return:
2918 * gtk_infoprint(GTK_WINDOW(app), "Navigation Key select");
2919 * return TRUE;
2921 /*code below messes up when you have a textview*/
2923 case GDK_Left:
2924 case GDK_Right:
2926 gtk_widget_child_focus(widget, event->keyval==GDK_Left?GTK_DIR_TAB_BACKWARD:GTK_DIR_TAB_FORWARD);
2927 return TRUE;
2930 case GDK_Left:
2932 nodeData *selnode = getSelectedNode(mainview);
2933 if (selnode!=NULL && selnode->typ==NODE_SKETCH)
2935 show_banner(mainview, _("Squared shapes ON"));
2936 sketchwidget_set_shift(mainview->sk, TRUE);
2937 return TRUE;
2939 return FALSE;
2941 case GDK_Right:
2943 nodeData *selnode = getSelectedNode(mainview);
2944 if (selnode!=NULL && selnode->typ==NODE_SKETCH)
2946 show_banner(mainview, _("Squared shapes OFF"));
2947 sketchwidget_set_shift(mainview->sk, FALSE);
2948 return TRUE;
2950 return FALSE;
2952 case GDK_Down:
2954 nodeData *selnode = getSelectedNode(mainview);
2955 if (selnode!=NULL && selnode->typ==NODE_SKETCH)
2957 show_banner(mainview, _("Filled shapes OFF"));
2958 sketchwidget_set_fillmode(mainview->sk, FALSE);
2959 return TRUE;
2961 return FALSE;
2963 case GDK_Up:
2965 nodeData *selnode = getSelectedNode(mainview);
2966 if (selnode!=NULL && selnode->typ==NODE_SKETCH)
2968 show_banner(mainview, _("Filled shapes ON"));
2969 sketchwidget_set_fillmode(mainview->sk, TRUE);
2970 return TRUE;
2972 return FALSE;
2974 case GDK_F7:
2976 callback_redo(NULL, mainview);
2977 return TRUE;
2979 case GDK_F8:
2981 callback_undo(NULL, mainview);
2982 return TRUE;
2986 return FALSE;
2989 void callback_fullscreen(GtkToolButton* tool_button, gpointer user_data)
2991 MainView* mainview = (MainView*)user_data;
2992 gtk_window_fullscreen(GTK_WINDOW(mainview->data->node_view));
2995 void callback_buffer_modified(GtkAction * action, gpointer data)
2997 MainView *mainview = (MainView *) data;
2998 g_assert(mainview != NULL && mainview->data != NULL);
3000 mainview->file_edited = TRUE;
3003 GtkTreeRowReference *read_sqlite3_data(MainView * mainview, unsigned int parentid, GtkTreeRowReference * parenttree, unsigned int selected, GtkTreeStore * model)
3005 GtkTreeRowReference *resref = NULL;
3007 char q[256];
3009 g_snprintf(q, sizeof(q), "SELECT nodeid, bodytype, name, nameblob, lastmodified, flags FROM %s WHERE parent=%d ORDER BY ord", datatable_tmpname, parentid);
3011 sqlite3_stmt *stmt = NULL;
3012 const char *dum;
3013 int rc = sqlite3_prepare(mainview->db, q, strlen(q), &stmt, &dum);
3015 if (rc)
3017 maepad_warning("Error reading SQLite3 data: %s", sqlite3_errmsg(mainview->db));
3018 return (NULL);
3021 rc = SQLITE_BUSY;
3022 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
3024 rc = sqlite3_step(stmt);
3025 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
3026 break;
3027 else if (rc == SQLITE_ROW)
3029 int nodeid = sqlite3_column_int(stmt, 0);
3030 int typ = sqlite3_column_int(stmt, 1);
3031 const unsigned char *name = sqlite3_column_text(stmt, 2);
3032 const unsigned char *nameblob = sqlite3_column_text(stmt, 3);
3033 int lastmod = sqlite3_column_int(stmt, 4);
3034 int flags = sqlite3_column_int(stmt, 5);
3036 if ((typ != NODE_TEXT && typ != NODE_SKETCH && typ != NODE_CHECKLIST) || (name == NULL && nameblob == NULL)) {
3037 maepad_warning("Unknown node type in database: %d (skipping)", typ);
3038 continue;
3041 nodeData *node = g_malloc(sizeof(nodeData));
3043 node->sql3id = nodeid;
3044 node->typ = typ;
3045 node->flags = flags;
3046 node->name = NULL;
3047 node->namepix = NULL;
3048 if (name != NULL) {
3049 node->name = g_strdup((char *)name);
3050 } else {
3051 node->name = g_strdup(_("Unnamed node"));
3053 /*if (nameblob != NULL)
3055 int blobsize = sqlite3_column_bytes(stmt, 3);
3057 GdkPixbufLoader *pl = gdk_pixbuf_loader_new_with_type("png", NULL);
3058 GError *err = NULL;
3060 gdk_pixbuf_loader_write(pl, (guchar *) nameblob, blobsize, &err);
3061 if (err != NULL)
3063 fprintf(stderr, "Error loading nodename! %s\n", err->message);
3064 g_error_free(err);
3065 err = NULL;
3067 gdk_pixbuf_loader_close(pl, NULL);
3068 GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(pl);
3070 if (GDK_IS_PIXBUF(pixbuf))
3071 node->namepix = pixbuf;
3073 node->lastMod = lastmod;
3075 GtkTreeIter parentiter, newiter;
3076 void *par = NULL;
3078 if (parenttree != NULL)
3080 GtkTreePath *pa = gtk_tree_row_reference_get_path(parenttree);
3082 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &parentiter, pa);
3083 gtk_tree_path_free(pa);
3084 par = &parentiter;
3087 gtk_tree_store_append(model, &newiter, par);
3088 gtk_tree_store_set(model, &newiter, NODE_NAME, node->name, NODE_PIXBUF, node->namepix, NODE_DATA, node, -1);
3090 GtkTreePath *pa = gtk_tree_model_get_path(GTK_TREE_MODEL(model), &newiter);
3092 GtkTreeRowReference *newref = gtk_tree_row_reference_new(GTK_TREE_MODEL(model), pa);
3094 if (selected == nodeid)
3095 resref = newref;
3097 gtk_tree_path_free(pa);
3098 GtkTreeRowReference *r = read_sqlite3_data(mainview, nodeid, newref, selected,
3099 model);
3101 if (resref != newref)
3102 gtk_tree_row_reference_free(newref);
3104 if (r != NULL)
3106 if (resref == NULL)
3107 resref = r;
3108 else
3109 gtk_tree_row_reference_free(r); /*safeguard */
3114 if (stmt)
3115 sqlite3_finalize(stmt);
3117 return (resref); /*ref to supposed-to-be-selected treeitem */
3121 * read file
3123 gboolean read_file_to_buffer(MainView * mainview)
3125 char tq[512];
3127 g_assert(mainview != NULL);
3128 gboolean res = FALSE;
3130 gchar *filename = mainview->file_name;
3132 new_file(mainview);
3133 mainview->file_name = filename;
3134 mainview->loading=TRUE;
3136 maepad_message("Reading database file: %s", filename);
3138 int rc;
3139 sqlite3_stmt *stmt = NULL;
3141 rc = sqlite3_open(filename, &mainview->db);
3144 if (rc)
3146 maepad_warning("Cannot open database %s: %s", filename, sqlite3_errmsg(mainview->db));
3147 break;
3150 sqlite3_exec(mainview->db, "PRAGMA synchronous = OFF;", NULL, NULL, NULL);
3152 char *q = "SELECT skey, sval FROM settings";
3153 const char *dum;
3155 rc = sqlite3_prepare(mainview->db, q, strlen(q), &stmt, &dum);
3156 if (rc)
3158 maepad_warning("Error reading settings: %s", sqlite3_errmsg(mainview->db));
3159 break;
3162 unsigned int selectedCard = 0;
3163 unsigned int curDataVersion = 0;
3164 unsigned int curChecklistVersion = 0;
3166 rc = SQLITE_BUSY;
3167 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
3169 rc = sqlite3_step(stmt);
3170 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
3171 break;
3172 else if (rc == SQLITE_ROW)
3174 const gchar* col_key = (const gchar*)sqlite3_column_text(stmt, 0);
3175 const gchar* col_val = (const gchar*)sqlite3_column_text(stmt, 1);
3176 if (!strcmp(col_key, "selectedNode"))
3178 gint tmp = atoi((char *)col_val);
3180 if (tmp > 0)
3181 selectedCard = tmp;
3183 if (!strcmp(col_key, "dataVersion"))
3185 gint tmp = atoi((char *)col_val);
3187 if (tmp > 0)
3188 curDataVersion = tmp;
3190 if (!strcmp(col_key, "checklistVersion"))
3192 gint tmp = atoi((char *)col_val);
3194 if (tmp > 0)
3195 curChecklistVersion = tmp;
3197 if (!strcmp(col_key, "newNodeDlgCreateChild"))
3199 gint tmp = atoi((char *)col_val);
3201 mainview->newnodedialog_createchild = TRUE;
3202 if (tmp == 0)
3203 mainview->newnodedialog_createchild = FALSE;
3205 if (!strcmp(col_key, "brushSize"))
3207 gint tmp = atoi((char *)col_val);
3208 if (tmp>0) sk_set_brushsize(mainview, tmp);
3210 if (!strcmp(col_key, "brushColor"))
3212 unsigned long tmp = atol((char *)col_val);
3213 GdkColor c2;
3215 c2.red = ((tmp & 0xFF0000) >> 16) << 8;
3216 c2.green = ((tmp & 0xFF00) >> 8) << 8;
3217 c2.blue = (tmp & 0xFF) << 8;
3218 sketchwidget_set_brushcolor(mainview->sk, c2);
3220 if (mainview->current_color != NULL) {
3221 gdk_color_free(mainview->current_color);
3223 mainview->current_color = gdk_color_copy(&c2);
3228 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
3230 maepad_warning("Error reading data: %s", sqlite3_errmsg(mainview->db));
3231 break;
3234 if (stmt) {
3235 sqlite3_finalize(stmt);
3236 stmt = NULL;
3239 gboolean resback = FALSE;
3241 while(curDataVersion < datatableversion)
3243 if (curDataVersion == 0)
3245 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_backupname);
3246 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3248 g_snprintf(tq, sizeof(tq), "ALTER TABLE %s RENAME TO %s", datatable_name, datatable_backupname);
3249 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3250 maepad_warning("Error backing up table %s to %s", datatable_name, datatable_backupname);
3251 break;
3253 resback = TRUE;
3255 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", datatable_name, datatable);
3256 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3257 maepad_warning("Error creating table: %s", datatable_name);
3258 break;
3260 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);
3261 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3262 maepad_warning("Error copying data from %s to %s", datatable_name, datatable_backupname);
3263 break;
3266 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_backupname);
3267 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3269 curDataVersion = datatableversion;
3271 break;
3274 if (curDataVersion != datatableversion)
3276 maepad_warning("Data table version mismatch: %d <=> %d", curDataVersion, datatableversion);
3278 if (resback == TRUE)
3280 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_name);
3281 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3282 g_snprintf(tq, sizeof(tq), "ALTER TABLE %s RENAME TO %s", datatable_backupname, datatable_name);
3283 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3286 break;
3290 while(curChecklistVersion < checklisttableversion)
3292 if (curChecklistVersion == 0) /*no checklisttable at all*/
3294 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", checklisttable_name, checklisttable);
3295 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3296 maepad_warning("Error creating checklist table during schema upgrade");
3297 break;
3299 curChecklistVersion = checklisttableversion;
3301 break;
3305 GtkTreeStore *model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview)));
3307 g_object_ref(model);
3308 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), NULL);
3312 char tq[512];
3314 g_snprintf(tq, sizeof(tq), "CREATE%s TABLE %s%s", TEMPTABLE_KEYWORD, datatable_tmpname, datatable);
3315 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3316 maepad_warning("Error creating temp table: %s", datatable_tmpname);
3317 break;
3319 g_snprintf(tq, sizeof(tq), "CREATE INDEX %s_index ON %s %s", datatable_tmpname, datatable_tmpname, dataindex);
3320 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3321 maepad_warning("Error creating temp index for %s", datatable_tmpname);
3322 break;
3324 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", datatable_tmpname, datatable_name);
3325 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3326 maepad_warning("Error copying data from %s to %s", datatable_name, datatable_tmpname);
3327 break;
3330 g_snprintf(tq, sizeof(tq), "CREATE%s TABLE %s%s", TEMPTABLE_KEYWORD, checklisttable_tmpname, checklisttable);
3331 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3332 maepad_warning("Error creating temp table: %s", checklisttable_tmpname);
3333 break;
3335 g_snprintf(tq, sizeof(tq), "CREATE INDEX %s_index ON %s %s", checklisttable_tmpname, checklisttable_tmpname, checklistindex);
3336 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3337 maepad_warning("Error creating temp index for %s", checklisttable_tmpname);
3338 break;
3340 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", checklisttable_tmpname, checklisttable_name);
3341 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3342 maepad_warning("Error copying data from %s to %s", checklisttable_name, checklisttable_tmpname);
3343 break;
3346 while(FALSE);
3348 GtkTreeRowReference *selectedRef = read_sqlite3_data(mainview, 0, NULL, selectedCard, model);
3350 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), GTK_TREE_MODEL(model));
3351 g_object_unref(model);
3352 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview->treeview));
3354 if (selectedRef != NULL)
3356 GtkTreeIter seliter;
3358 if (ref2iter(GTK_TREE_MODEL(model), selectedRef, &seliter) == TRUE)
3360 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
3361 gtk_tree_selection_select_iter(selection, &seliter);
3364 gtk_tree_row_reference_free(selectedRef);
3366 res = TRUE;
3368 while(FALSE);
3370 if (stmt) {
3371 sqlite3_finalize(stmt);
3375 mainview->loading=FALSE;
3377 return (res);
3381 * write to file
3383 void write_buffer_to_file(MainView * mainview)
3385 maepad_message("Writing database to file: %s", mainview->file_name);
3386 saveCurrentData(mainview);
3388 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview));
3389 /*update ord value in database for all nodes*/
3390 gtk_tree_model_foreach(GTK_TREE_MODEL(model),(GtkTreeModelForeachFunc) foreach_func_update_ord,mainview);
3392 busy_enter(mainview);
3394 char tq[512];
3396 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", misctable_name);
3397 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3399 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", misctable_name, misctable);
3400 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3402 gint nndcc = 1;
3404 if (mainview->newnodedialog_createchild == FALSE)
3405 nndcc = 0;
3406 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('newNodeDlgCreateChild', '%d');", misctable_name, nndcc);
3407 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3409 nodeData *node = getSelectedNode(mainview);
3411 if (node)
3413 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('selectedNode', '%d');", misctable_name, node->sql3id);
3414 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3417 guint bsize;
3418 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mainview->eraser_tb)) == TRUE)
3420 bsize=mainview->brushsize_backup;
3422 else
3424 bsize=sketchwidget_get_brushsize(mainview->sk);
3426 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('brushSize', '%d');", misctable_name, bsize);
3427 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3429 if (mainview->current_color == NULL) {
3430 GdkColor color = {0, 0, 0, 0};
3431 mainview->current_color = gdk_color_copy(&color);
3433 unsigned long bcol = ((mainview->current_color->red >> 8) << 16) |
3434 ((mainview->current_color->green >> 8) << 8) |
3435 ((mainview->current_color->blue) >> 8);
3437 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('brushColor', '%lu');", misctable_name, bcol);
3438 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3440 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('dataVersion', '%d');", misctable_name, datatableversion);
3441 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3443 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('checklistVersion', '%d');", misctable_name, checklisttableversion);
3444 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3446 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_backupname);
3447 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3448 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", datatable_backupname, datatable);
3449 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3451 maepad_warning("Error creating backup table: %s", datatable_backupname);
3452 show_banner(mainview, _("Error creating backup table"));
3454 busy_leave(mainview);
3455 return;
3457 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", datatable_backupname, datatable_name);
3458 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3460 maepad_warning("Error backing up table %s to %s", datatable_name, datatable_backupname);
3461 show_banner(mainview, _("Error creating backup table"));
3463 busy_leave(mainview);
3464 return;
3466 g_snprintf(tq, sizeof(tq), "DELETE FROM %s", datatable_name);
3467 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3469 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", datatable_name, datatable_tmpname);
3470 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3472 maepad_warning("Error saving table %s to %s", datatable_tmpname, datatable_name);
3473 show_banner(mainview, _("Error saving table"));
3475 g_snprintf(tq, sizeof(tq), "DELETE FROM %s", datatable_name);
3476 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3478 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", datatable_name, datatable_backupname);
3479 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3480 maepad_warning("Error restoring backup. Data lost :(");
3483 busy_leave(mainview);
3484 return;
3487 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_backupname);
3488 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3490 /*checklist*/
3491 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", checklisttable_backupname);
3492 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3493 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", checklisttable_backupname, checklisttable);
3494 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3496 maepad_warning("Error creating backup table: %s", checklisttable_backupname);
3497 show_banner(mainview, _("Error creating checklist backup table"));
3499 busy_leave(mainview);
3500 return;
3503 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", checklisttable_backupname, checklisttable_name);
3504 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3506 maepad_warning("Error backing up table %s to %s", checklisttable_name, checklisttable_backupname);
3507 show_banner(mainview, _("Error creating checklist backup table"));
3509 busy_leave(mainview);
3510 return;
3512 g_snprintf(tq, sizeof(tq), "DELETE FROM %s", checklisttable_name);
3513 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3515 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", checklisttable_name, checklisttable_tmpname);
3516 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3518 maepad_warning("Error saving table %s to %s", checklisttable_tmpname, checklisttable_name);
3519 show_banner(mainview, _("Error saving checklist table"));
3521 g_snprintf(tq, sizeof(tq), "DELETE FROM %s", checklisttable_name);
3522 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3524 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", checklisttable_name, checklisttable_backupname);
3525 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3526 maepad_warning("Error restoring backup. Data lost :(");
3528 busy_leave(mainview);
3529 return;
3532 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", checklisttable_backupname);
3533 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3535 mainview->file_edited = FALSE;
3536 busy_leave(mainview);
3537 show_banner(mainview, _("Changes saved"));
3540 void callback_checklist_change(GtkTreeSelection *selection, MainView *mainview)
3542 g_assert(mainview != NULL && mainview->data != NULL);
3544 g_signal_handlers_block_by_func(mainview->bold_tb, callback_fontstyle, mainview->bold_tb);
3545 g_signal_handlers_block_by_func(mainview->strikethru_tb, callback_fontstyle, mainview->strikethru_tb);
3546 g_signal_handlers_block_by_func(mainview->check_tb, callback_fontstyle, mainview->check_tb);
3548 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), FALSE);
3549 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->strikethru_tb), FALSE);
3550 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->check_tb), FALSE);
3552 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
3553 GList* l=gtk_tree_selection_get_selected_rows(selection, NULL);
3555 gboolean gotit=FALSE;
3557 GList* cur=l;
3558 while(cur)
3560 GtkTreePath *path=cur->data;
3562 if (!gotit)
3564 GtkTreeIter iter;
3565 if (gtk_tree_model_get_iter(model, &iter, path))
3567 gint styletoset_weight;
3568 gboolean styletoset_strike;
3569 gboolean ischecked;
3571 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHECKNODE_BOLD, &styletoset_weight, CHECKNODE_STRIKE, &styletoset_strike, CHECKNODE_CHECKED, &ischecked, -1);
3572 if (styletoset_weight==PANGO_WEIGHT_BOLD) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), TRUE);
3573 if (styletoset_strike==TRUE) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->strikethru_tb), TRUE);
3574 if (ischecked==TRUE) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->check_tb), TRUE);
3575 gotit=TRUE;
3578 gtk_tree_path_free(path);
3579 cur=cur->next;
3582 g_list_free(l);
3584 g_signal_handlers_unblock_by_func(mainview->bold_tb, callback_fontstyle, mainview->bold_tb);
3585 g_signal_handlers_unblock_by_func(mainview->strikethru_tb, callback_fontstyle, mainview->strikethru_tb);
3586 g_signal_handlers_unblock_by_func(mainview->check_tb, callback_fontstyle, mainview->check_tb);
3589 void callback_checklist_paste(MainView *mainview)
3591 g_assert(mainview != NULL && mainview->data != NULL);
3592 gchar **entries;
3593 gint length, i;
3595 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
3596 GtkTreeIter toplevel;
3597 gchar *pasted_text = gtk_clipboard_wait_for_text(mainview->clipboard);
3599 entries = g_strsplit(pasted_text, "\n", 0);
3600 length = g_strv_length(entries);
3602 for (i=0; i<length; i++) {
3603 gtk_list_store_append(GTK_LIST_STORE(model), &toplevel);
3604 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_CHECKED, FALSE, CHECKNODE_TEXT, entries[i], -1);
3607 mainview->checklist_edited = TRUE;
3608 g_free(pasted_text);
3609 g_strfreev(entries);
3612 void callback_checklist_add(GtkAction *action, MainView *mainview)
3614 g_assert(mainview != NULL && mainview->data != NULL);
3616 gchar* text = show_line_edit_dialog(mainview, _("Add new checklist item"), _("Name:"), _("Add"), "");
3618 if (text != NULL) {
3619 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
3620 GtkTreeIter toplevel;
3621 gtk_list_store_append(GTK_LIST_STORE(model), &toplevel);
3623 gtk_list_store_set(GTK_LIST_STORE(model),
3624 &toplevel,
3625 CHECKNODE_CHECKED, FALSE,
3626 CHECKNODE_TEXT, text,
3627 -1);
3629 GtkTreePath *path = gtk_tree_model_get_path(model, &toplevel);
3630 if (path) {
3631 gtk_tree_view_set_cursor(GTK_TREE_VIEW(mainview->listview), path, mainview->listtextcol, FALSE);
3632 gtk_tree_path_free(path);
3635 mainview->checklist_edited = TRUE;
3639 void callback_checklist_edit(GtkAction *action, MainView *mainview)
3641 g_assert(mainview != NULL && mainview->data != NULL);
3643 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview));
3645 if (gtk_tree_selection_count_selected_rows(selection) == 0) {
3646 show_banner(mainview, _("Select items first"));
3647 return;
3650 GtkTreeModel* model;
3651 GtkTreeIter iter;
3653 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
3654 gchar* old_text = NULL;
3655 gtk_tree_model_get(model, &iter, CHECKNODE_TEXT, &old_text, -1);
3657 gchar* new_text = show_line_edit_dialog(mainview, _("Edit checklist item"), _("New name:"), _("Save"), old_text);
3659 if (new_text != NULL) {
3660 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_TEXT, new_text, -1);
3661 g_free(new_text);
3664 g_free(old_text);
3667 mainview->checklist_edited = TRUE;
3670 void callback_checklist_delete(GtkAction *action, MainView *mainview)
3672 g_assert(mainview != NULL && mainview->data != NULL);
3674 if (gtk_tree_selection_count_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview)))==0) {
3675 show_banner(mainview, _("Select items first"));
3676 return;
3679 if (show_confirmation(mainview, _("Delete selected checklist item?"))) {
3680 callback_checklist_delete_real(mainview);
3684 void callback_checklist_delete_real(MainView* mainview)
3686 GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
3687 GList* l=gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview)), NULL);
3689 GList* rowrefs=NULL;
3690 GList* cur=l;
3691 while(cur)
3693 GtkTreePath *path=cur->data;
3695 GtkTreeIter iter;
3696 if (gtk_tree_model_get_iter(model, &iter, path))
3698 GtkTreeRowReference *rowref = gtk_tree_row_reference_new(model, path);
3699 rowrefs=g_list_append(rowrefs, rowref);
3701 gtk_tree_path_free(path);
3702 cur=cur->next;
3704 g_list_free(l);
3706 g_object_ref(model);
3707 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->listview), NULL);
3709 cur=rowrefs;
3710 while(cur)
3712 GtkTreeRowReference *rowref=cur->data;
3713 GtkTreePath *path= gtk_tree_row_reference_get_path(rowref);
3714 if (path)
3716 GtkTreeIter iter;
3717 if (gtk_tree_model_get_iter(model, &iter, path)) gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
3718 gtk_tree_path_free(path);
3720 gtk_tree_row_reference_free(rowref);
3721 cur=cur->next;
3723 g_list_free(rowrefs);
3725 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->listview), model);
3726 g_object_unref(model);
3727 mainview->checklist_edited = TRUE;
3730 /* Ask the user for confirmation of a specific action */
3731 gboolean
3732 show_confirmation(MainView* mainview, gchar* question)
3734 GtkDialog* dialog = GTK_DIALOG(hildon_note_new_confirmation(
3735 GTK_WINDOW(mainview->data->main_view), question));
3736 gtk_window_set_transient_for(GTK_WINDOW(dialog), mainview_get_dialog_parent(mainview));
3738 gint response = gtk_dialog_run(dialog);
3739 gtk_widget_destroy(GTK_WIDGET(dialog));
3741 return (response == GTK_RESPONSE_OK);
3744 /* Show a information banner to the user (non-modal) */
3745 void
3746 show_banner(MainView* mainview, const gchar* text)
3748 hildon_banner_show_information(GTK_WIDGET(mainview_get_dialog_parent(mainview)), NULL, text);
3751 /* Let the user enter or edit a line of text */
3752 gchar*
3753 show_line_edit_dialog(MainView* mainview, const gchar* title, const gchar* label_text, const gchar* action, const gchar* text)
3755 GtkWidget* edit_dialog;
3756 GtkWidget* label;
3757 GtkWidget* entry;
3758 GtkWidget* hbox;
3759 gchar* result = NULL;
3761 edit_dialog = GTK_WIDGET(gtk_dialog_new());
3762 gtk_window_set_title(GTK_WINDOW(edit_dialog), title);
3763 gtk_window_set_transient_for(GTK_WINDOW(edit_dialog), mainview_get_dialog_parent(mainview));
3765 label = GTK_WIDGET(gtk_label_new(label_text));
3767 entry = hildon_entry_new(HILDON_SIZE_AUTO);
3768 gtk_entry_set_text(GTK_ENTRY(entry), text);
3769 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
3770 gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
3772 gtk_dialog_add_button(GTK_DIALOG(edit_dialog), action, GTK_RESPONSE_OK);
3773 gtk_dialog_set_default_response(GTK_DIALOG(edit_dialog), GTK_RESPONSE_OK);
3775 hbox = GTK_WIDGET(gtk_hbox_new(FALSE, 10));
3777 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(edit_dialog))), GTK_WIDGET(hbox));
3778 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
3779 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
3781 gtk_widget_show_all(GTK_WIDGET(hbox));
3783 while (TRUE) {
3784 if (gtk_dialog_run(GTK_DIALOG(edit_dialog)) == GTK_RESPONSE_OK) {
3785 result = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
3786 if (strcmp(result, "") != 0) {
3787 break;
3788 } else {
3789 show_banner(mainview, _("Please enter a non-empty text"));
3790 g_free(result);
3791 result = NULL;
3793 } else {
3794 result = NULL;
3795 break;
3799 gtk_widget_destroy(GTK_WIDGET(edit_dialog));
3800 return result;