Select the correct item for a main view longpress
[maepad.git] / src / ui / callbacks.c
blob9f46f44af4019a61d3f31ae243dadb4a2ffa897a
1 /*
2 * This file is part of MaePad
3 * Copyright (c) 2010 Thomas Perl <thp@thpinfo.com>
4 * http://thpinfo.com/2010/maepad/
6 * Based on Maemopad+:
7 * Copyright (c) 2006-2008 Kemal Hadimli
8 * Copyright (c) 2008 Thomas Perl
10 * This software is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public License
12 * as published by the Free Software Foundation; either version 2.1 of
13 * the License, or (at your option) any later version.
15 * This software is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this software; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 * 02110-1301 USA
27 #include <ui/callbacks.h>
28 #include <ui/interface.h>
29 #include <gtk/gtk.h>
30 #include <gdk/gdkkeysyms.h>
31 #include <libintl.h>
33 #include <glib.h>
36 * strlen needed from string.h
38 #include <string.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <unistd.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <config.h>
45 #include <time.h>
47 #include <hildon/hildon.h>
48 #include <hildon/hildon-banner.h>
49 #include <hildon/hildon-note.h>
50 #include <hildon/hildon-font-selection-dialog.h>
51 #include <tablet-browser-interface.h>
53 #include <libgnomevfs/gnome-vfs.h>
55 #include "sketchwidget.h"
57 #include "../he/he-about-dialog.h"
58 #include "../he/he-simple-color-dialog.h"
61 * "Busy" status handling
63 * Use "busy_reset" to reset the busy status (turn off)
64 * Use "busy_enter" when starting time-consuming processing
65 * Use "busy_leave" when processing has been finished
67 typedef enum {
68 BUSY_RESET = 0,
69 BUSY_INCREMENT,
70 BUSY_DECREMENT,
71 } SetBusyType;
73 /* Don't use this directly, but make use of the macros defined below */
74 void set_busy(MainView* mainview, SetBusyType update);
76 #define busy_reset(mainview) set_busy(mainview, BUSY_RESET)
77 #define busy_enter(mainview) set_busy(mainview, BUSY_INCREMENT)
78 #define busy_leave(mainview) set_busy(mainview, BUSY_DECREMENT)
82 * Privates:
84 gboolean read_file_to_buffer(MainView * mainview);
85 void write_buffer_to_file(MainView * mainview);
86 void new_node_dialog(nodeType typ, MainView * mainview);
87 gboolean foreach_func_update_ord (GtkTreeModel *model,GtkTreePath *path,GtkTreeIter *iter, MainView *mainview);
88 void move_nodes_up(GtkTreeModel * model, GtkTreeRowReference * topnode, GtkTreeRowReference * newtop);
89 GtkTreeRowReference *iter2ref(GtkTreeModel * model, GtkTreeIter * iter);
90 gboolean exec_command_on_db(MainView *mainview,char sql_string[]);
91 int get_node_id_on_tmp_db(GtkTreeModel *model,GtkTreeIter *iter);
92 gint get_branch_node_index(GtkTreePath *path);
93 gboolean move_node(MainView *mainview,GtkTreeIter *new_parent,GtkTreeIter *item_to_move,GtkTreeIter *item_befor);
94 gboolean tree_model_iter_prev(GtkTreeModel *tree_model,GtkTreeIter *iter);
95 gboolean show_confirmation(MainView* mainview, gchar* question);
99 gboolean callback_node_view_window_state(GtkWidget* window,
100 GdkEventWindowState* event, gpointer user_data)
102 MainView* mainview = (MainView*)user_data;
103 GtkWidget* sketch_scroll = NULL;
105 if (mainview->toolbar == NULL || mainview->sk == NULL) {
106 return FALSE;
109 sketch_scroll = GTK_WIDGET(sketchwidget_get_mainwidget(mainview->sk));
111 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
112 if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) {
113 gtk_widget_hide(mainview->toolbar);
114 gtk_scrolled_window_set_policy(
115 GTK_SCROLLED_WINDOW(sketch_scroll),
116 GTK_POLICY_NEVER,
117 GTK_POLICY_NEVER);
118 } else {
119 gtk_widget_show(mainview->toolbar);
120 gtk_scrolled_window_set_policy(
121 GTK_SCROLLED_WINDOW(sketch_scroll),
122 GTK_POLICY_AUTOMATIC,
123 GTK_POLICY_AUTOMATIC);
127 return FALSE;
130 void set_busy(MainView* mainview, SetBusyType update)
132 switch (update) {
133 case BUSY_RESET:
134 mainview->busyrefcount = 0;
135 break;
136 case BUSY_INCREMENT:
137 mainview->busyrefcount++;
138 break;
139 case BUSY_DECREMENT:
140 if (mainview->busyrefcount > 0) {
141 mainview->busyrefcount--;
143 break;
144 default:
145 g_assert_not_reached();
146 return;
149 hildon_gtk_window_set_progress_indicator(GTK_WINDOW(mainview->data->main_view), (mainview->busyrefcount > 0));
150 hildon_gtk_window_set_progress_indicator(GTK_WINDOW(mainview->data->node_view), (mainview->busyrefcount > 0));
153 void prepareUIforNodeChange(MainView * mainview, nodeType typ)
155 gtk_widget_set_sensitive(GTK_WIDGET(mainview->undo_tb), TRUE);
156 gtk_widget_set_sensitive(GTK_WIDGET(mainview->redo_tb), TRUE);
158 if (typ == NODE_TEXT)
160 gtk_widget_show(GTK_WIDGET(mainview->font_tb));
161 gtk_widget_show(GTK_WIDGET(mainview->bold_tb));
162 gtk_widget_show(GTK_WIDGET(mainview->italic_tb));
163 gtk_widget_show(GTK_WIDGET(mainview->underline_tb));
164 gtk_widget_show(GTK_WIDGET(mainview->bullet_tb));
165 gtk_widget_show(mainview->tools_font);
166 gtk_widget_show(mainview->tools_wordwrap);
168 else
170 gtk_widget_hide(GTK_WIDGET(mainview->font_tb));
171 gtk_widget_hide(GTK_WIDGET(mainview->bold_tb));
172 gtk_widget_hide(GTK_WIDGET(mainview->italic_tb));
173 gtk_widget_hide(GTK_WIDGET(mainview->underline_tb));
174 gtk_widget_hide(GTK_WIDGET(mainview->bullet_tb));
175 gtk_widget_hide(mainview->tools_font);
176 gtk_widget_hide(mainview->tools_wordwrap);
179 if (typ == NODE_SKETCH)
181 /* gtk_widget_show(GTK_WIDGET(mainview->colorbutton_tb));*/
182 gtk_widget_show(GTK_WIDGET(mainview->eraser_tb));
183 gtk_widget_show(GTK_WIDGET(mainview->brushsize_tb));
184 gtk_widget_show(GTK_WIDGET(mainview->sketchlines_tb));
185 gtk_widget_show(GTK_WIDGET(mainview->shape_tb));
186 gtk_widget_show(mainview->tools_color);
187 gtk_widget_show(mainview->tools_brushsize);
188 gtk_widget_show(mainview->tools_pagestyle);
189 gtk_widget_show(mainview->tools_shape);
190 gtk_widget_show(mainview->tools_pressure);
192 else
194 /* gtk_widget_hide(GTK_WIDGET(mainview->colorbutton_tb));*/
195 gtk_widget_hide(GTK_WIDGET(mainview->eraser_tb));
196 gtk_widget_hide(GTK_WIDGET(mainview->brushsize_tb));
197 gtk_widget_hide(GTK_WIDGET(mainview->sketchlines_tb));
198 gtk_widget_hide(GTK_WIDGET(mainview->shape_tb));
199 gtk_widget_hide(mainview->tools_color);
200 gtk_widget_hide(mainview->tools_brushsize);
201 gtk_widget_hide(mainview->tools_pagestyle);
202 gtk_widget_hide(mainview->tools_shape);
203 gtk_widget_hide(mainview->tools_pressure);
206 if (typ == NODE_CHECKLIST)
208 gtk_widget_show(GTK_WIDGET(mainview->bold_tb));
209 gtk_widget_show(GTK_WIDGET(mainview->strikethru_tb));
210 gtk_widget_show(GTK_WIDGET(mainview->check_tb));
211 gtk_widget_show(GTK_WIDGET(mainview->checkadd_tb));
212 gtk_widget_show(GTK_WIDGET(mainview->checkedit_tb));
213 gtk_widget_show(GTK_WIDGET(mainview->checkdel_tb));
214 gtk_widget_hide(GTK_WIDGET(mainview->undo_tb));
215 gtk_widget_hide(GTK_WIDGET(mainview->redo_tb));
217 else
219 gtk_widget_hide(GTK_WIDGET(mainview->strikethru_tb));
220 gtk_widget_hide(GTK_WIDGET(mainview->check_tb));
221 gtk_widget_hide(GTK_WIDGET(mainview->checkadd_tb));
222 gtk_widget_hide(GTK_WIDGET(mainview->checkedit_tb));
223 gtk_widget_hide(GTK_WIDGET(mainview->checkdel_tb));
224 gtk_widget_show(GTK_WIDGET(mainview->undo_tb));
225 gtk_widget_show(GTK_WIDGET(mainview->redo_tb));
228 if (typ == NODE_TEXT)
230 gtk_widget_hide(GTK_WIDGET(mainview->colorbutton_tb));
231 gtk_widget_hide(sketchwidget_get_mainwidget(mainview->sk));
232 gtk_widget_hide(mainview->listscroll);
233 gtk_widget_show(GTK_WIDGET(mainview->scrolledwindow));
234 gtk_widget_show(mainview->tools_item);
236 else if (typ == NODE_SKETCH)
238 gtk_widget_show(GTK_WIDGET(mainview->colorbutton_tb));
239 gtk_widget_hide(GTK_WIDGET(mainview->scrolledwindow));
240 gtk_widget_hide(mainview->listscroll);
241 gtk_widget_show(sketchwidget_get_mainwidget(mainview->sk));
242 gtk_widget_show(mainview->tools_item);
244 else if (typ == NODE_CHECKLIST)
246 gtk_widget_show(GTK_WIDGET(mainview->colorbutton_tb));
247 gtk_widget_hide(GTK_WIDGET(mainview->scrolledwindow));
248 gtk_widget_hide(sketchwidget_get_mainwidget(mainview->sk));
249 gtk_widget_hide(mainview->tools_item);
250 gtk_widget_show(mainview->listscroll);
252 else
254 gtk_widget_hide(GTK_WIDGET(mainview->colorbutton_tb));
255 gtk_widget_hide(GTK_WIDGET(mainview->scrolledwindow));
256 gtk_widget_hide(sketchwidget_get_mainwidget(mainview->sk));
257 gtk_widget_hide(mainview->tools_item);
258 gtk_widget_hide(mainview->listscroll);
262 nodeData *getSelectedNode(MainView * mainview)
264 GtkTreeIter iter;
265 GtkTreeModel *model;
267 nodeData *nd;
269 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
271 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
272 return (NULL);
274 gtk_tree_model_get(model, &iter, NODE_DATA, &nd, -1);
276 return (nd);
279 void saveCurrentData(MainView * mainview)
281 nodeData *selnode = getSelectedNode(mainview);
282 saveDataToNode(mainview, selnode);
285 void saveDataToNode(MainView * mainview, nodeData *selnode)
287 if (selnode == NULL)
288 return;
290 if (
291 (selnode->typ == NODE_SKETCH && sketchwidget_get_edited(mainview->sk) == FALSE) ||
292 (selnode->typ == NODE_TEXT && wp_text_buffer_is_modified(mainview->buffer)==FALSE) ||
293 (selnode->typ == NODE_CHECKLIST && mainview->checklist_edited==FALSE)
296 maepad_message("node not edited, not saving");
297 return;
300 mainview->file_edited = TRUE;
302 busy_enter(mainview);
303 maepad_debug("saveDataToNode working");
305 gboolean goterr = TRUE;
306 gchar *textdata = NULL;
307 GdkPixbuf *pixbuf = NULL;
308 gchar *sketchdata = NULL;
309 gsize datalen = 0;
310 char tq[512];
312 if (selnode->typ == NODE_TEXT)
314 #if 0
315 GtkTextIter start, end;
316 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(mainview->buffer), &start, &end);
317 textdata = gtk_text_buffer_serialize_rich_text(GTK_TEXT_BUFFER(mainview->buffer), &start, &end, &datalen);
318 #endif
320 GString *gstr=g_string_sized_new(4096);
321 wp_text_buffer_save_document(mainview->buffer, (WPDocumentSaveCallback)(wp_savecallback), gstr);
323 datalen=gstr->len;
324 textdata=g_string_free(gstr, FALSE);
326 /* 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);*/
327 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);
329 else if (selnode->typ == NODE_SKETCH)
331 GError *err = NULL;
332 GdkPixmap *skpix = sketchwidget_get_Pixmap(mainview->sk);
333 GtkWidget *skdr = sketchwidget_get_drawingarea(mainview->sk);
335 pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(skpix), NULL, 0, 0, 0, 0, skdr->allocation.width, skdr->allocation.height);
336 if (pixbuf == NULL)
338 maepad_warning("error saving: pixbuf is null");
340 else
342 double w, h;
343 GdkPixbuf *pixbuf2 = sketchwidget_trim_image(pixbuf, skdr->allocation.width, skdr->allocation.height, &w, &h, FALSE);
345 if (pixbuf2!=NULL)
347 if (gdk_pixbuf_save_to_buffer(pixbuf2, &sketchdata, &datalen, "png", &err, NULL) == FALSE)
349 sketchdata = NULL;
350 datalen = 0;
351 maepad_warning("Error saving sketch: %s", err->message);
352 g_error_free(err);
354 gdk_pixbuf_unref(pixbuf2);
357 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);
358 maepad_debug("storing sketch in db: %d bytes", datalen);
359 if (skpix && G_IS_OBJECT(skpix)) g_object_unref(skpix);
361 else if (selnode->typ == NODE_CHECKLIST)
363 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);
368 sqlite3_stmt *stmt = NULL;
369 const char *dum;
370 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
372 if (rc)
374 maepad_warning("Error updating: %s", sqlite3_errmsg(mainview->db));
375 break;
377 if (selnode->typ == NODE_TEXT)
378 sqlite3_bind_text(stmt, 1, textdata, datalen, /*strlen(textdata),*/ SQLITE_TRANSIENT);
379 else if (selnode->typ == NODE_SKETCH)
380 sqlite3_bind_blob(stmt, 1, sketchdata, datalen, SQLITE_TRANSIENT);
382 rc = SQLITE_BUSY;
383 while(rc == SQLITE_BUSY)
385 rc = sqlite3_step(stmt);
386 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
387 break;
389 sqlite3_finalize(stmt);
391 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
393 maepad_warning("Error saving node: %s", sqlite3_errmsg(mainview->db));
395 else
397 if (selnode->typ == NODE_TEXT)
398 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(mainview->buffer), FALSE);
399 else if (selnode->typ == NODE_SKETCH)
400 sketchwidget_set_edited(mainview->sk, FALSE);
401 else if (selnode->typ == NODE_CHECKLIST)
402 mainview->checklist_edited = FALSE;
403 goterr = FALSE;
405 }while(FALSE);
407 while(goterr==FALSE && selnode->typ == NODE_CHECKLIST)
409 GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
411 char tq[512];
412 g_snprintf(tq, sizeof(tq), "DELETE FROM %s WHERE nodeid=%d", checklisttable_tmpname, selnode->sql3id);
413 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
415 GtkTreeIter iter;
416 if (gtk_tree_model_get_iter_first(model, &iter)==FALSE) break;
420 gint styletoset_weight;
421 gboolean styletoset_strike;
422 gboolean ischecked;
423 gchar *text;
424 gchar *color;
425 unsigned long col=0;
427 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);
429 GdkColor tmpcol;
430 if (color!=NULL && strcmp(color, "(null)")!=0 && gdk_color_parse(color, &tmpcol))
432 col=((tmpcol.red>>8)<<16)|((tmpcol.green>>8)<<8)|(tmpcol.blue>>8);
435 gint style=0;
436 if (ischecked) style|=CHECKSTYLE_CHECKED;
437 if (styletoset_weight==PANGO_WEIGHT_BOLD) style|=CHECKSTYLE_BOLD;
438 if (styletoset_strike) style|=CHECKSTYLE_STRIKE;
440 g_snprintf(tq, sizeof(tq), "INSERT INTO %s (nodeid, name, style, color, ord) VALUES(%d, ?, %d, %lu, 0)", checklisttable_tmpname, selnode->sql3id, style, col);
441 sqlite3_stmt *stmt = NULL;
442 const char *dum;
443 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
445 if (rc)
447 goterr=TRUE;
448 maepad_warning("Error while saving checklist: %s", sqlite3_errmsg(mainview->db));
449 break;
451 sqlite3_bind_text(stmt, 1, text, strlen(text), SQLITE_TRANSIENT);
453 rc = SQLITE_BUSY;
454 while(rc == SQLITE_BUSY)
456 rc = sqlite3_step(stmt);
457 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
458 break;
460 sqlite3_finalize(stmt);
462 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
464 goterr=TRUE;
465 maepad_warning("Error while saving checklist (2): %s", sqlite3_errmsg(mainview->db));
468 g_free(color);
469 g_free(text);
471 }while(gtk_tree_model_iter_next(model, &iter)==TRUE);
473 break;
476 if (textdata)
477 g_free(textdata);
478 if (sketchdata)
479 g_free(sketchdata);
480 if (goterr == TRUE)
482 show_banner(mainview, _("Error saving memo"));
484 busy_leave(mainview);
487 gboolean callback_treeview_button_press(GtkTreeView* treeview, GdkEventButton* event, gpointer user_data)
489 MainView* mainview = (MainView*)user_data;
490 GtkTreePath* path;
492 if (mainview->node_list_longpress_path != NULL) {
493 /* Forget old, remembered tree path for longpress */
494 gtk_tree_path_free(mainview->node_list_longpress_path);
495 mainview->node_list_longpress_path = NULL;
498 if (gtk_tree_view_get_path_at_pos(treeview,
499 event->x, event->y, &path, NULL, NULL, NULL)) {
501 * Save this path in case we open the longpress menu to
502 * set the cursor in the treeview to the correct row.
504 * See on_node_menu_show() on how this is further used.
506 mainview->node_list_longpress_path = path;
509 mainview->can_show_node_view = TRUE;
511 return FALSE;
514 void callback_treeview_celldatafunc(GtkTreeViewColumn * tree_column, GtkCellRenderer * cell, GtkTreeModel * tree_model, GtkTreeIter * iter, gpointer data)
516 MainView *mainview = ( MainView * ) data;
517 g_assert(mainview != NULL && mainview->data != NULL );
519 nodeData *nd;
521 gtk_tree_model_get(tree_model, iter, NODE_DATA, &nd, -1);
522 if (nd == NULL)
523 return;
525 if (nd->namepix == NULL)
527 g_object_set(cell, "visible", FALSE, NULL);
529 else
531 g_object_set(cell, "visible", TRUE, NULL);
532 g_object_set(cell, "width", SKETCHNODE_RX, NULL);
533 g_object_set(cell, "height", SKETCHNODE_RY, NULL);
538 gboolean callback_treeview_testcollapse(GtkTreeView * treeview, GtkTreeIter * arg1, GtkTreePath * arg2, gpointer user_data)
540 return (FALSE);
543 void callback_treeview_change(GtkTreeSelection * selection, gpointer data)
545 MainView *mainview = (MainView *) data;
546 g_assert(mainview != NULL && mainview->data != NULL);
548 nodeData *nd = getSelectedNode(mainview);
550 gchar* nodeName = _("View node");
552 if (nd != NULL && nd->name != NULL) {
553 nodeName = nd->name;
556 /* Show node view with selected node */
557 gtk_window_set_title(GTK_WINDOW(mainview->data->node_view),
558 nodeName);
560 if (mainview->can_show_node_view) {
561 gtk_widget_show(GTK_WIDGET(mainview->data->node_view));
564 /* Make sure we don't accidentally collapse any nodes */
565 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview->treeview));
567 #ifdef NEW_SEL_LOGIC
568 guint tm=time(NULL);
569 if (mainview->cansel_time>0 && mainview->cansel_time+1.0<tm) mainview->cansel_node=NULL;
571 if (nd==NULL)
573 if (mainview->cansel_node!=NULL)
575 maepad_debug("[SELLOGIC] saving %d to unselect all nodes", (mainview->cansel_node)->sql3id);
576 saveDataToNode(mainview, (mainview->cansel_node));
577 mainview->cansel_node=NULL;
579 return;
582 if (mainview->cansel_node!=NULL)
584 if (nd->sql3id == (mainview->cansel_node)->sql3id)
586 mainview->cansel_node=NULL;
587 maepad_debug("[SELLOGIC] doubly selected %d, doing nothing", nd->sql3id);
588 prepareUIforNodeChange(mainview, nd->typ);
589 return;
591 else
593 maepad_debug("[SELLOGIC] saving %d to load new node", (mainview->cansel_node)->sql3id);
594 saveDataToNode(mainview, (mainview->cansel_node));
595 mainview->cansel_node=NULL;
598 #endif
600 if (nd == NULL) return;
602 busy_enter(mainview);
604 gboolean goterr = TRUE;
605 char *textdata = NULL;
606 char *blob = NULL;
607 int blobsize = 0, textsize = 0;
609 char tq[512];
611 g_snprintf(tq, sizeof(tq), "SELECT bodytype, body, bodyblob, flags FROM %s WHERE nodeid=%d", datatable_tmpname, nd->sql3id);
612 sqlite3_stmt *stmt = NULL;
613 const char *dum;
614 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
616 if (rc)
618 maepad_warning("Error reading (1): %s", sqlite3_errmsg(mainview->db));
620 else
622 rc = SQLITE_BUSY;
623 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
625 rc = sqlite3_step(stmt);
626 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
627 break;
628 else if (rc == SQLITE_ROW)
630 nd->typ = sqlite3_column_int(stmt, 0);
631 nd->flags = sqlite3_column_int(stmt, 3);
633 prepareUIforNodeChange(mainview, nd->typ);
634 if (nd->typ == NODE_TEXT)
636 gboolean file_edited_backup = mainview->file_edited;
638 blobsize = sqlite3_column_bytes(stmt, 2);
639 blob = (char *)sqlite3_column_blob(stmt, 2);
641 textdata = (char *)sqlite3_column_text(stmt, 1);
642 textsize = sqlite3_column_bytes(stmt, 1);
644 /* gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), "", -1);*/
645 wp_text_buffer_reset_buffer(mainview->buffer, TRUE);
647 gboolean richtext=FALSE;
649 if (blob != NULL)
651 #if 0
652 gboolean oldway=FALSE;
653 if (blobsize>8)
655 char tst[8];
656 strncpy(tst, blob, 8);
657 tst[8]=0;
658 if (strcmp(tst, "RICHTEXT")==0) oldway=TRUE;
660 if (oldway)
662 GError *err = NULL;
663 GtkTextIter iter;
664 gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(mainview->buffer), &iter);
665 gtk_text_buffer_deserialize_rich_text(GTK_TEXT_BUFFER(mainview->buffer), &iter, blob, blobsize, TRUE, &err);
666 if (err != NULL)
668 g_error_free(err);
670 else
672 richtext=TRUE;
675 #endif
677 if (richtext==FALSE)
679 wp_text_buffer_load_document_begin(mainview->buffer, TRUE);
680 wp_text_buffer_load_document_write(mainview->buffer, blob, blobsize);
681 wp_text_buffer_load_document_end(mainview->buffer);
682 richtext=TRUE;
685 if (richtext==FALSE && !(textdata == NULL || g_utf8_validate(textdata, textsize, NULL) == FALSE))
687 /* gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), textdata, textsize);*/
688 wp_text_buffer_load_document_begin(mainview->buffer, FALSE);
689 wp_text_buffer_load_document_write(mainview->buffer, textdata, textsize);
690 wp_text_buffer_load_document_end(mainview->buffer);
693 wp_text_buffer_enable_rich_text(mainview->buffer, TRUE);
694 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->tools_wordwrap), ((nd->flags & NODEFLAG_WORDWRAP) > 0)?TRUE:FALSE);
695 callback_wordwrap(NULL, mainview); /*FIXME:ugly (do we need this? gotta test) */
697 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(mainview->buffer), FALSE); /*we probably don't need this*/
699 callback_undotoggle((gpointer)mainview->buffer, FALSE, mainview); /*we need these*/
700 callback_redotoggle((gpointer)mainview->buffer, FALSE, mainview);
702 if (file_edited_backup==FALSE) mainview->file_edited=FALSE; /*textview changed event toggles this?*/
703 goterr = FALSE;
705 else if (nd->typ == NODE_SKETCH)
707 sketchwidget_wipe_undo(mainview->sk);
709 /* Disable squared and filled mode when opening a sketch */
710 hildon_check_button_set_active(HILDON_CHECK_BUTTON(mainview->menu_button_square), FALSE);
711 hildon_check_button_set_active(HILDON_CHECK_BUTTON(mainview->menu_button_filled), FALSE);
713 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->shapemenuitems[1]), TRUE);
714 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->shapemenuitems[0]), TRUE);
716 blobsize = sqlite3_column_bytes(stmt, 2);
717 blob = (char *)sqlite3_column_blob(stmt, 2);
718 gboolean clear = TRUE;
720 if (blob == NULL)
721 goterr = FALSE;
722 if (blob != NULL)
724 maepad_debug("blob size: %d", blobsize);
725 GdkPixbufLoader *pl = gdk_pixbuf_loader_new_with_type("png", NULL);
726 GError *err = NULL;
728 gdk_pixbuf_loader_write(pl, (guchar *) blob, blobsize, &err);
729 if (err != NULL)
731 maepad_warning("Error loading sketch: %s", err->message);
732 g_error_free(err);
733 err = NULL;
735 gdk_pixbuf_loader_close(pl, NULL);
736 GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(pl);
738 if (GDK_IS_PIXBUF(pixbuf))
740 GtkWidget *skdr = sketchwidget_get_drawingarea(mainview->sk);
741 GtkPixmap *skpix = (GtkPixmap *) sketchwidget_get_Pixmap(mainview->sk);
743 int w=gdk_pixbuf_get_width(pixbuf);
744 int h=gdk_pixbuf_get_height(pixbuf);
745 if (w!=skdr->allocation.width || h!=skdr->allocation.height)
747 if (w>skdr->allocation.width) w=skdr->allocation.width;
748 if (h>skdr->allocation.height) h=skdr->allocation.height;
749 sketchwidget_clear_real(mainview->sk);
751 gdk_draw_pixbuf(GDK_DRAWABLE(skpix), NULL, pixbuf, 0, 0, 0, 0, w, h, GDK_RGB_DITHER_NONE, 0, 0);
753 clear = FALSE;
754 goterr = FALSE;
756 if (skpix && G_IS_OBJECT(skpix)) g_object_unref(skpix);
758 else
760 maepad_warning("Error loading pixbuf");
762 g_object_unref(pl);
764 if (clear == TRUE)
766 maepad_message("Clearing sketch widget");
767 sketchwidget_clear_real(mainview->sk);
769 gtk_widget_queue_draw(sketchwidget_get_drawingarea(mainview->sk));
771 else if (nd->typ == NODE_CHECKLIST)
773 mainview->checklist_edited = FALSE;
774 GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
775 g_object_ref(model);
776 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->listview), NULL);
777 gtk_list_store_clear(GTK_LIST_STORE(model));
779 g_snprintf(tq, sizeof(tq), "SELECT name, style, color FROM %s WHERE nodeid=%d ORDER BY ord, idx", checklisttable_tmpname, nd->sql3id);
780 sqlite3_stmt *stmt2 = NULL;
781 const char *dum;
782 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt2, &dum);
783 if (rc)
785 maepad_warning("Error reading checklist (1) %s", sqlite3_errmsg(mainview->db));
787 else
789 goterr=FALSE;
790 rc = SQLITE_BUSY;
791 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
793 rc = sqlite3_step(stmt2);
794 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
795 break;
796 else if (rc == SQLITE_ROW)
798 char *textdata = (char *)sqlite3_column_text(stmt2, 0);
799 int style = sqlite3_column_int(stmt2, 1);
800 unsigned long col = sqlite3_column_int(stmt2, 2);
802 GtkTreeIter toplevel;
803 gtk_list_store_append(GTK_LIST_STORE(model), &toplevel);
804 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_TEXT, textdata, CHECKNODE_CHECKED, FALSE, -1);
805 if ((style & CHECKSTYLE_CHECKED)>0) {
806 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_CHECKED, TRUE, -1);
807 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_ICON_NAME, "widgets_tickmark_list", -1);
809 if ((style & CHECKSTYLE_BOLD)>0) gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_BOLD, PANGO_WEIGHT_BOLD, -1);
810 if ((style & CHECKSTYLE_STRIKE)>0) gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_STRIKE, TRUE, -1);
812 if (col>0)
814 char tmp[10];
815 g_snprintf(tmp, sizeof(tmp), "#%02lx%02lx%02lx", ((col & 0xFF0000) >> 16), ((col & 0xFF00) >> 8), (col & 0xFF));
816 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_COLOR, tmp, -1);
821 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
823 maepad_warning("Error reading checklist (2): %s", sqlite3_errmsg(mainview->db));
824 goterr=TRUE;
827 sqlite3_finalize(stmt2);
830 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->listview), model);
831 g_object_unref(model);
834 if ((nd->flags & NODEFLAG_SKETCHLINES) > 0)
835 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->sketchlinesmenuitems[1]), TRUE);
836 else if ((nd->flags & NODEFLAG_SKETCHGRAPH) > 0)
837 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->sketchlinesmenuitems[2]), TRUE);
838 else
840 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->sketchlinesmenuitems[0]), TRUE);
841 callback_sketchlines(NULL, mainview->sketchlinesmenuitems[0]); /*FIXME:ugly */
843 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview->tools_pressure), TRUE);
845 break;
848 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE) {
849 maepad_warning("Error reading (2): %s", sqlite3_errmsg(mainview->db));
852 sqlite3_finalize(stmt);
855 busy_leave(mainview);
857 /* Show / hide the sketch-related menu widgets */
858 if (nd->typ == NODE_SKETCH) {
859 gtk_widget_show(mainview->menu_button_square);
860 gtk_widget_show(mainview->menu_button_filled);
861 } else {
862 gtk_widget_hide(mainview->menu_button_square);
863 gtk_widget_hide(mainview->menu_button_filled);
866 if (goterr == TRUE)
868 show_banner(mainview, _("Error loading memo"));
872 gboolean treeview_canselect(GtkTreeSelection * selection, GtkTreeModel * model, GtkTreePath * path, gboolean path_currently_selected, gpointer userdata)
874 MainView *mainview = (MainView *) userdata;
875 g_assert(mainview != NULL && mainview->data != NULL);
877 if (mainview->loading==FALSE)
879 #ifndef EXPANDING_ROWS
880 if (path_currently_selected)
881 return (FALSE);
882 #endif
884 #ifndef NEW_SEL_LOGIC
885 saveCurrentData(mainview);
886 #else
887 if (path_currently_selected)
889 GtkTreeIter iter;
890 gtk_tree_model_get_iter(model, &iter, path);
892 gtk_tree_model_get(model, &iter, NODE_DATA, &(mainview->cansel_node), -1);
893 mainview->cansel_time=time(NULL);
895 #endif
897 return (TRUE);
900 gboolean newnodedlg_key_press_cb(GtkWidget * widget, GdkEventKey * event, GtkWidget * dlg)
902 SketchWidget *s = gtk_object_get_data(GTK_OBJECT(dlg), "sk");
904 switch (event->keyval)
906 case GDK_F7:
907 sketchwidget_redo(s);
908 return TRUE;
909 case GDK_F8:
910 sketchwidget_undo(s);
911 return TRUE;
913 return FALSE;
917 /* This struct will hold all our toggle buttons, so we can
918 * only allow one to be active at a time (i.e. radio buttons) */
919 typedef struct _newNodeToggleButtons newNodeToggleButtons;
920 struct _newNodeToggleButtons
922 GtkWidget *rbt; /* Text */
923 GtkWidget *rbs; /* Sketch */
924 GtkWidget *rbc; /* Checklist */
927 void show_sketch_widget(GtkWidget *widget, gpointer user_data)
929 GtkWidget *dialog = (GtkWidget*)user_data;
931 /* Show the sketch widget and hide the entry + draw button */
932 gtk_widget_show(gtk_object_get_data(GTK_OBJECT(dialog), "al"));
933 gtk_widget_hide(gtk_object_get_data(GTK_OBJECT(dialog), "draw_button"));
934 gtk_widget_hide(gtk_object_get_user_data(GTK_OBJECT(dialog)));
937 void new_node_dialog(nodeType typ, MainView * mainview)
939 GtkWidget *dialog, *entry, *but_ok, *vbox, *hbox, *al, *cb;
940 GtkWidget *rb1, *rb2, *rb3;
941 GtkWidget *hb;
942 gchar datetime_str[200];
943 time_t t_now;
944 struct tm *tm_now;
945 gboolean datetime_written = FALSE;
947 t_now = time(NULL);
948 tm_now = localtime(&t_now);
950 if (tm_now != NULL) {
951 if (strftime(datetime_str, sizeof(datetime_str), "%y-%m-%d %H:%M", tm_now) != 0) {
952 datetime_written = TRUE;
956 if (datetime_written == FALSE) {
957 /* Was not able to determine a datetime string - use default */
958 maepad_warning("Cannot determine current time");
959 strncpy(datetime_str, _("New memo"), sizeof(datetime_str));
960 datetime_str[sizeof(datetime_str)-1] = '\0';
963 newNodeToggleButtons *nntb = g_malloc(sizeof(newNodeToggleButtons));
965 dialog = gtk_dialog_new();
966 gtk_window_set_title(GTK_WINDOW(dialog), _("Create new memo"));
967 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
969 g_signal_connect(G_OBJECT(dialog), "key_press_event", G_CALLBACK(newnodedlg_key_press_cb), dialog);
971 vbox = gtk_vbox_new(FALSE, 0);
973 hbox = gtk_hbox_new(TRUE, 0);
975 /* Text note toggle button */
976 rb1 = hildon_gtk_radio_button_new(HILDON_SIZE_FINGER_HEIGHT, NULL);
977 gtk_button_set_label(GTK_BUTTON(rb1), _("Rich text"));
978 gtk_button_set_image(GTK_BUTTON(rb1), gtk_image_new_from_file(PIXMAPDIR "/text.png"));
979 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(rb1), TRUE, TRUE, 0);
980 nntb->rbt = rb1;
982 /* Sketch toggle button */
983 rb2 = hildon_gtk_radio_button_new_from_widget(HILDON_SIZE_FINGER_HEIGHT, GTK_RADIO_BUTTON(rb1));
984 gtk_button_set_label(GTK_BUTTON(rb2), _("Sketch"));
985 gtk_button_set_image(GTK_BUTTON(rb2), gtk_image_new_from_file(PIXMAPDIR "/sketch.png"));
986 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(rb2), TRUE, TRUE, 0);
987 nntb->rbs = rb2;
989 /* Checklist toggle button */
990 rb3 = hildon_gtk_radio_button_new_from_widget(HILDON_SIZE_FINGER_HEIGHT, GTK_RADIO_BUTTON(rb1));
991 gtk_button_set_label(GTK_BUTTON(rb3), _("Checklist"));
992 gtk_button_set_image(GTK_BUTTON(rb3), gtk_image_new_from_file(PIXMAPDIR "/checklist.png"));
993 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(rb3), TRUE, TRUE, 0);
994 nntb->rbc = rb3;
996 /* Set mode to 0 to get correct styling */
997 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb1), FALSE);
998 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb2), FALSE);
999 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb3), FALSE);
1001 /* Remember "new note toggle buttons" list */
1002 gtk_object_set_data(GTK_OBJECT(dialog), "nntb", nntb);
1004 if (typ == NODE_TEXT) {
1005 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb1), TRUE);
1006 } else if (typ == NODE_SKETCH) {
1007 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb2), TRUE);
1008 } else {
1009 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb3), TRUE);
1012 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1014 but_ok = gtk_dialog_add_button(GTK_DIALOG(dialog), _("Create"), GTK_RESPONSE_OK);
1015 g_signal_connect(G_OBJECT(but_ok), "clicked", G_CALLBACK(callback_new_node_real), dialog);
1017 gtk_object_set_data(GTK_OBJECT(dialog), "m", mainview);
1019 hb = gtk_hbox_new(FALSE, 10);
1020 gtk_box_pack_start(GTK_BOX(hb), gtk_label_new(_("Name:")), FALSE, FALSE, 0);
1021 entry = hildon_entry_new(HILDON_SIZE_AUTO);
1022 gtk_object_set_user_data(GTK_OBJECT(dialog), entry);
1023 gtk_entry_set_text(GTK_ENTRY(entry), datetime_str);
1024 gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
1025 gtk_box_pack_start(GTK_BOX(hb), entry, TRUE, TRUE, 0);
1027 /* Sketch widget, hidden by default */
1028 al = gtk_alignment_new(0.5, 0.5, 0, 0);
1029 SketchWidget *s = sketchwidget_new(SKETCHNODE_X, SKETCHNODE_Y, TRUE);
1030 gtk_object_set_data(GTK_OBJECT(dialog), "sk", s);
1031 gtk_object_set_data(GTK_OBJECT(dialog), "al", al);
1032 sketchwidget_set_brushsize(s, 2);
1033 sketchwidget_set_backstyle(s, SKETCHBACK_GRAPH);
1034 gtk_widget_set_size_request(sketchwidget_get_mainwidget(s), SKETCHNODE_X, SKETCHNODE_Y);
1035 gtk_container_add(GTK_CONTAINER(al), sketchwidget_get_mainwidget(s));
1036 gtk_box_pack_start(GTK_BOX(hb), al, FALSE, FALSE, 0);
1038 /*but_sketch = hildon_button_new_with_text(
1039 HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
1040 HILDON_BUTTON_ARRANGEMENT_VERTICAL,
1041 _("Use sketch label"), NULL);
1043 gtk_object_set_data(GTK_OBJECT(dialog), "draw_button", but_sketch);
1044 gtk_signal_connect(GTK_OBJECT(but_sketch), "clicked", G_CALLBACK(show_sketch_widget), dialog);
1045 gtk_box_pack_start(GTK_BOX(hb), but_sketch, FALSE, TRUE, 0);*/
1046 gtk_box_pack_start(GTK_BOX(vbox), hb, TRUE, FALSE, 0);
1048 cb = hildon_check_button_new(HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
1049 gtk_button_set_label(GTK_BUTTON(cb), _("Create as child of selected memo"));
1050 hildon_check_button_set_active(HILDON_CHECK_BUTTON(cb), mainview->newnodedialog_createchild);
1051 gtk_box_pack_start(GTK_BOX(vbox), cb, FALSE, FALSE, 0);
1053 gtk_object_set_data(GTK_OBJECT(dialog), "cb", cb);
1055 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), vbox);
1057 gtk_widget_grab_focus(entry);
1059 gtk_widget_show_all(dialog);
1061 /* Hide the sketch widget at first */
1062 gtk_widget_hide(al);
1063 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
1066 void add_new_node(nodeData * node, MainView * mainview, gboolean ischild)
1068 GtkTreeIter parentiter, newiter;
1069 GtkTreeModel *model;
1070 void *ptr = NULL;
1072 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1074 if (gtk_tree_selection_get_selected(selection, &model, &parentiter))
1075 ptr = &parentiter;
1077 GtkTreePath *path = NULL;
1079 unsigned int parentnodeid = 0;
1081 if (ptr != NULL)
1083 path = gtk_tree_model_get_path(model, &parentiter);
1085 if (ischild == FALSE)
1087 gtk_tree_path_up(path);
1089 if (gtk_tree_path_get_depth(path) == 0)
1091 /* Selected node is a root node */
1092 ptr = NULL; /* New node can not have a Parent node */
1093 gtk_tree_path_down(path); /*restore path so expand() works */
1095 else if (gtk_tree_path_get_depth(path) > 0)
1097 /* Selected node is a child node */
1098 if (gtk_tree_model_get_iter(model, &parentiter, path))
1099 ptr = &parentiter;
1104 if (ptr != NULL)
1106 nodeData *nd;
1108 gtk_tree_model_get(model, ptr, NODE_DATA, &nd, -1);
1109 if (nd)
1110 parentnodeid = nd->sql3id;
1113 node->sql3id = 0;
1116 sqlite3_stmt *stmt = NULL;
1117 const char *dum;
1118 char tq[512];
1121 * FIXME: ord
1123 g_snprintf(tq, sizeof(tq), "INSERT INTO %s (parent, bodytype, name, nameblob, ord) VALUES (%d, %d, ?, ?, 0);", datatable_tmpname, parentnodeid, node->typ);
1124 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
1126 if (rc)
1128 maepad_warning("Error inserting (1): %s", sqlite3_errmsg(mainview->db));
1129 break;
1131 if (node->name != NULL)
1132 sqlite3_bind_text(stmt, 1, node->name, strlen(node->name), SQLITE_TRANSIENT);
1133 else
1134 sqlite3_bind_text(stmt, 1, NULL, 0, SQLITE_TRANSIENT);
1136 if (node->namepix != NULL)
1138 gchar *namepixdata = NULL;
1139 gsize datalen = 0;
1141 GError *err = NULL;
1143 if (gdk_pixbuf_save_to_buffer(node->namepix, &namepixdata, &datalen, "png", &err, NULL) == FALSE)
1145 namepixdata = NULL;
1146 datalen = 0;
1147 maepad_warning("Error saving name: %s", err->message);
1148 g_error_free(err);
1150 sqlite3_bind_blob(stmt, 2, namepixdata, datalen, SQLITE_TRANSIENT);
1152 else
1153 sqlite3_bind_blob(stmt, 2, NULL, 0, SQLITE_TRANSIENT);
1155 rc = SQLITE_BUSY;
1156 while(rc == SQLITE_BUSY)
1158 rc = sqlite3_step(stmt);
1159 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
1160 break;
1162 sqlite3_finalize(stmt);
1163 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
1165 maepad_warning("Error inserting (2): %s", sqlite3_errmsg(mainview->db));
1166 break;
1168 node->sql3id = sqlite3_last_insert_rowid(mainview->db);
1170 while(FALSE);
1172 if (node->sql3id == 0)
1174 if (node->name)
1175 g_free(node->name);
1176 if (node->namepix)
1177 g_object_unref(node->namepix);
1178 g_free(node);
1179 if (path)
1180 gtk_tree_path_free(path);
1181 show_banner(mainview, _("Error creating node"));
1182 return;
1185 gtk_tree_store_append(GTK_TREE_STORE(model), &newiter, ptr);
1187 gtk_tree_store_set(GTK_TREE_STORE(model), &newiter, NODE_NAME, node->name, NODE_PIXBUF, node->namepix, NODE_DATA, node, -1);
1189 if (path)
1191 mainview->loading=TRUE; /*only when we have a valid parent*/
1192 gtk_tree_view_expand_row(GTK_TREE_VIEW(mainview->treeview), path, FALSE);
1193 gtk_tree_path_free(path);
1196 gtk_tree_selection_select_iter(selection, &newiter);
1198 mainview->loading=FALSE;
1201 void callback_new_node_real(GtkAction * action, gpointer data)
1203 MainView *mainview;
1205 GtkWidget *dialog = data;
1206 GtkWidget *entry = gtk_object_get_user_data(GTK_OBJECT(dialog));
1208 mainview = gtk_object_get_data(GTK_OBJECT(dialog), "m");
1209 SketchWidget *s = gtk_object_get_data(GTK_OBJECT(dialog), "sk");
1210 GtkWidget *cb = gtk_object_get_data(GTK_OBJECT(dialog), "cb");
1211 newNodeToggleButtons *nntb = gtk_object_get_data(GTK_OBJECT(dialog), "nntb");
1213 nodeType typ = NODE_TEXT;
1214 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nntb->rbs))) {
1215 typ = NODE_SKETCH;
1216 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nntb->rbc))) {
1217 typ = NODE_CHECKLIST;
1219 g_free(nntb);
1221 gchar *txt = NULL;
1223 /*if (GTK_WIDGET_VISIBLE(entry))
1225 txt = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
1226 if (strcmp(txt, "") == 0)
1228 g_free(txt);
1229 return;
1232 else
1234 GtkWidget *sdr = sketchwidget_get_drawingarea(s);
1236 GdkPixmap *spix = sketchwidget_get_Pixmap(s);
1238 pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(spix), NULL, 0, 0, 0, 0, sdr->allocation.width, sdr->allocation.height);
1239 g_object_unref(spix);
1240 double w, h;
1241 GdkPixbuf *pixbuf2 = sketchwidget_trim_image(pixbuf, SKETCHNODE_X, SKETCHNODE_Y, &w,
1242 &h, TRUE);
1243 if (pixbuf2==NULL) return;
1245 GdkPixbuf *pixbuf3 = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, SKETCHNODE_RX,
1246 SKETCHNODE_RY);
1248 gdk_pixbuf_fill(pixbuf3, 0xffffffff);
1250 if (w <= SKETCHNODE_RX && h <= SKETCHNODE_RY)
1252 gdk_pixbuf_copy_area(pixbuf2, 0, 0, w, h, pixbuf3, 0, (SKETCHNODE_RY - h) / 2);
1254 else
1256 double neww, newh;
1258 if (w > h)
1260 neww = SKETCHNODE_RX;
1261 newh = (h / w) * SKETCHNODE_RX;
1263 else
1265 newh = SKETCHNODE_RY;
1266 neww = (w / h) * SKETCHNODE_RY;
1268 if (newh > SKETCHNODE_RY)
1269 newh = SKETCHNODE_RY;
1271 GdkPixbuf *tmpbuf = gdk_pixbuf_scale_simple(pixbuf2, neww, newh,
1272 GDK_INTERP_BILINEAR);
1274 gdk_pixbuf_copy_area(tmpbuf, 0, 0, neww, newh, pixbuf3, 0, (SKETCHNODE_RY - newh) / 2);
1276 gdk_pixbuf_unref(tmpbuf);
1279 pixbuf = pixbuf3;
1280 gdk_pixbuf_unref(pixbuf2);
1283 nodeData *node;
1285 node = g_malloc(sizeof(nodeData));
1286 node->typ = typ;
1287 node->name = txt;
1288 node->namepix = NULL;
1290 /*if (GTK_WIDGET_VISIBLE(entry))
1292 node->name = txt;
1294 else
1296 node->namepix = pixbuf;
1299 node->lastMod = 0;
1300 node->flags = 0;
1301 node->sql3id = 0;
1303 mainview->newnodedialog_createchild = hildon_check_button_get_active(HILDON_CHECK_BUTTON(cb));
1304 add_new_node(node, mainview, mainview->newnodedialog_createchild);
1306 sketchwidget_destroy(s);
1307 gtk_widget_destroy(dialog);
1308 mainview->file_edited = TRUE;
1312 * delete node
1314 void callback_file_delete_node(GtkAction * action, gpointer data)
1316 MainView *mainview = (MainView *) data;
1317 g_assert(mainview != NULL && mainview->data != NULL);
1319 if (getSelectedNode(mainview) == NULL) {
1320 show_banner(mainview, _("Select a node first"));
1321 return;
1324 if (show_confirmation(mainview, _("Delete selected memo?"))) {
1325 callback_delete_node_real(mainview);
1326 gtk_widget_hide(GTK_WIDGET(mainview->data->node_view));
1331 * Callback for Rename Menuitem
1333 void callback_file_rename_node(GtkAction * action, gpointer data)
1335 MainView *mainview = (MainView*)data;
1336 g_assert(mainview != NULL && mainview->data != NULL);
1338 /* Get the selected node */
1339 nodeData *sel_node = getSelectedNode(mainview);
1340 if (sel_node == NULL) {
1341 /* Do nothing, if no node has been selected */
1342 show_banner(mainview, _("Select a node first"));
1343 return;
1346 if (sel_node->namepix != NULL) {
1347 /* the memo has a graphical label, cannot edit! */
1348 show_banner(mainview, _("Cannot rename memos with sketch name"));
1349 return;
1352 gchar* new_name = show_line_edit_dialog(mainview, _("Rename memo"), _("New name:"), _("Rename"), sel_node->name);
1354 /* Only rename node when user accepted the new name */
1355 if (new_name != NULL) {
1356 callback_rename_node_real(mainview, new_name);
1357 g_free(new_name);
1361 void callback_rename_node_real(MainView* mainview, gchar* new_name)
1363 GtkTreeIter iter;
1364 GtkTreeModel *model;
1365 nodeData *nd = NULL;
1367 /* Get the selected node */
1368 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1370 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
1371 return;
1374 gtk_tree_model_get (model, &iter, NODE_DATA, &nd, -1);
1376 if (nd == NULL) {
1377 return;
1380 /* Update the database */
1381 sqlite3_stmt *stmt = NULL;
1383 char* sql = sqlite3_mprintf("UPDATE %s SET name='%q' WHERE nodeid=%d", datatable_tmpname, new_name, nd->sql3id);
1385 int rc = sqlite3_prepare(mainview->db, sql, strlen(sql), &stmt, NULL);
1386 if (rc == SQLITE_OK) {
1387 rc = SQLITE_BUSY;
1388 while (rc == SQLITE_BUSY) {
1389 rc = sqlite3_step(stmt);
1390 if (rc == SQLITE_DONE) {
1391 /* Update in the database was successful - now update the rest */
1393 /* Update the noteData */
1394 g_free(nd->name);
1395 nd->name = g_strdup(new_name);
1397 /* Update the window title of node_view */
1398 gtk_window_set_title(GTK_WINDOW(mainview->data->node_view), nd->name);
1400 /* Update the value in the tree store */
1401 gtk_tree_store_set (GTK_TREE_STORE(model), &iter, NODE_NAME, new_name, -1);
1403 break;
1404 } else if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE) {
1405 maepad_warning("Error updating node: %s", sqlite3_errmsg(mainview->db));
1406 break;
1409 sqlite3_finalize(stmt);
1410 } else {
1411 maepad_warning("Error preparing DB update query: %s", sqlite3_errmsg(mainview->db));
1414 sqlite3_free(sql);
1416 mainview->file_edited = TRUE;
1419 void callback_file_export_node(GtkAction * action, gpointer data)
1421 MainView *mainview = (MainView *) data;
1422 g_assert(mainview != NULL && mainview->data != NULL);
1424 nodeData *nd=getSelectedNode(mainview);
1425 if (nd == NULL)
1427 show_banner(mainview, _("Select a memo first"));
1428 return;
1431 gchar *nodename=nd->name;
1432 if (nodename==NULL) nodename=_("saved memo");
1434 if (nd->typ == NODE_TEXT)
1437 GtkTextIter begin, end;
1438 gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER(mainview->buffer), &begin, &end);
1439 gchar *text = gtk_text_buffer_get_slice(GTK_TEXT_BUFFER(mainview->buffer), &begin, &end, TRUE);
1441 GString *gstr=g_string_sized_new(4096);
1442 wp_text_buffer_save_document(mainview->buffer, (WPDocumentSaveCallback)(wp_savecallback), gstr);
1443 gint textlen=gstr->len;
1444 gchar *text=g_string_free(gstr, FALSE);
1446 if (text==NULL || !strcmp(text, ""))
1448 show_banner(mainview, _("Memo is empty"));
1450 else
1452 gchar *fn = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, nodename, "html");
1453 if (fn!=NULL)
1455 GnomeVFSResult vfs_result;
1456 GnomeVFSHandle *handle = NULL;
1457 GnomeVFSFileSize out_bytes;
1458 vfs_result = gnome_vfs_create(&handle, fn, GNOME_VFS_OPEN_WRITE, 0, 0600);
1459 if ( vfs_result != GNOME_VFS_OK ) {
1460 show_banner(mainview, _("Export failed"));
1462 else
1464 gnome_vfs_write(handle, text, textlen, &out_bytes);
1465 gnome_vfs_close(handle);
1466 if (out_bytes==strlen(text)) show_banner(mainview, _("Exported"));
1467 else show_banner(mainview, _("Export incomplete"));
1469 g_free(fn);
1472 g_free(text);
1474 else if (nd->typ == NODE_SKETCH)
1476 GdkPixmap *skpix = sketchwidget_get_Pixmap(mainview->sk);
1477 GtkWidget *skdr = sketchwidget_get_drawingarea(mainview->sk);
1478 GdkPixbuf *pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(skpix), NULL, 0, 0, 0, 0, skdr->allocation.width, skdr->allocation.height);
1479 if (pixbuf==NULL)
1481 show_banner(mainview, _("Memo is empty"));
1483 else
1485 gchar *fn = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, nodename, "png");
1486 if (fn!=NULL)
1488 if (gdk_pixbuf_save(pixbuf, fn, "png", NULL, NULL)==FALSE)
1490 show_banner(mainview, _("Export failed"));
1492 else
1494 show_banner(mainview, _("Exported"));
1496 g_free(fn);
1499 g_object_unref(skpix);
1501 else if (nd->typ == NODE_CHECKLIST)
1503 show_banner(mainview, _("Export of checklists not possible yet"));
1508 * callback from menu item
1509 * move selected node down (switch node with next sibling), don't change level of node
1511 void callback_move_down_node(GtkAction * action, gpointer data)
1513 GtkTreeIter iter;
1514 GtkTreeModel *model;
1516 MainView *mainview = (MainView *) data;
1517 g_assert(mainview != NULL && mainview->data != NULL);
1519 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1520 gtk_tree_selection_get_selected(selection, &model, &iter);
1522 GtkTreeIter old_iter = iter;/*save pointer to old iter, we will need it during swap nodes*/
1524 if (gtk_tree_model_iter_next(model,&iter)==FALSE)/*get next node*/
1525 return;
1527 GtkTreeStore *treeStore = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview)));
1528 gtk_tree_store_swap(treeStore,&iter,&old_iter);
1530 mainview->file_edited = TRUE;/*we have made changes , if required show "save changes?" dialog in future*/
1534 * callback from menu item
1535 * move selected node down (switch node with prev sibling), don't change level of node
1537 void callback_move_up_node(GtkAction * action, gpointer data)
1539 GtkTreeIter iter;
1540 GtkTreeModel *model;
1542 MainView *mainview = (MainView *) data;
1543 g_assert(mainview != NULL && mainview->data != NULL);
1545 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1546 gtk_tree_selection_get_selected(selection, &model, &iter);
1548 GtkTreeIter old_iter=iter;/*save pointer to old iter, we will need it during swap nodes*/
1550 if (tree_model_iter_prev(model,&iter)==FALSE)/*get previous node*/
1551 return;
1553 GtkTreeStore *treeStore = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview)));
1554 gtk_tree_store_swap(treeStore,&old_iter,&iter);/*do move*/
1556 mainview->file_edited = TRUE;/*we have made changes , if required show "save changes?" dialog in future*/
1560 * callback from menu item
1561 * we change level of actual node with direction to top
1563 void callback_move_to_top_level_node(GtkAction * action, gpointer data)
1565 GtkTreeIter iter,new_parent;
1566 GtkTreeIter *p_new_parent;
1567 GtkTreeIter parent;
1568 GtkTreeModel *model;
1570 MainView *mainview = (MainView *) data;
1571 g_assert(mainview != NULL && mainview->data != NULL);
1573 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1574 gtk_tree_selection_get_selected(selection, &model, &iter);
1576 /*at first we need actual parent of selected node*/
1577 if (gtk_tree_model_iter_parent(model,&parent,&iter)==FALSE)
1579 /*if parent of selected node is ROOT we can't go higher*/
1580 return;
1582 /*we need also new parent, it's parent of actual parent*/
1583 if (gtk_tree_model_iter_parent(model,&new_parent,&parent)==FALSE)
1585 /*if our new parent is ROOT we got filled new_parent with invalid value,
1586 so we need set NULL value to p_new_parent (root item)*/
1587 p_new_parent=NULL;
1589 else
1591 p_new_parent=&new_parent;/*we only redirect pointer to treeiter*/
1594 saveCurrentData(mainview);/*we save changes in node befor move*/
1596 /*this move function provide move item with all his children, be careful iter value will change!*/
1597 if (move_node(mainview,p_new_parent,&iter,&parent)==TRUE){
1599 gint id_parent = get_node_id_on_tmp_db(model,p_new_parent);
1600 gint id_node = get_node_id_on_tmp_db(model,&iter);
1601 /*we need also update parent id of moved item*/
1602 char tq[512];
1603 g_snprintf (tq, sizeof(tq), "UPDATE %s SET parent=%d WHERE nodeid=%d",datatable_tmpname,id_parent ,id_node);
1604 exec_command_on_db(mainview,tq);
1606 /*select new created iter*/
1607 gtk_tree_selection_select_iter(selection,&iter);
1609 mainview->file_edited = TRUE;/*we have made changes , if required show "save changes?" dialog in future*/
1614 * callback from menu item
1615 * we change level of actual node with direction to bottom
1616 * previous node will be parent of our actual node
1618 void callback_move_to_bottom_level_node(GtkAction * action, gpointer data)
1620 GtkTreeIter iter;
1621 GtkTreeModel *model;
1623 MainView *mainview = (MainView *) data;
1624 g_assert(mainview != NULL && mainview->data != NULL);
1626 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1627 gtk_tree_selection_get_selected(selection, &model, &iter);
1629 GtkTreeIter move_iter=iter;/*save pointer to old iter*/
1631 /*we try to get previous node*/
1632 if (tree_model_iter_prev(model,&iter)==FALSE)
1633 return;/*if previous node on the same level doesn't exist we will exit*/
1635 saveCurrentData(mainview);/*we save changes in node befor move*/
1637 /*this move function provide move item with all his children, be careful move_iter value will change!*/
1638 if (move_node(mainview,&iter,&move_iter,NULL)==TRUE)
1640 gint id_parent = get_node_id_on_tmp_db(model,&iter);
1641 gint id_node = get_node_id_on_tmp_db(model,&move_iter);
1643 /*we need also update parent id of moved item*/
1644 char tq[512];
1645 g_snprintf (tq, sizeof(tq), "UPDATE %s SET parent=%d WHERE nodeid=%d",datatable_tmpname,id_parent ,id_node);
1646 exec_command_on_db(mainview,tq);
1648 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
1649 gtk_tree_view_expand_row(GTK_TREE_VIEW(mainview->treeview), path, FALSE);/*expand parent node*/
1650 gtk_tree_path_free(path);
1652 /*select new created iter*/
1653 gtk_tree_selection_select_iter(selection,&move_iter);
1655 mainview->file_edited = TRUE;/*we have made changes , if required show "save changes?" dialog in future*/
1660 * move item_to_move to new_parent with his children, this function is designed for change level of node
1661 * we copy item_to_move with his children to new position (after item_befor if is not NULL) and then we
1662 * destroy old node with his children, so ! item_to_move is set with new iter, be careful on this!
1664 gboolean move_node(MainView *mainview,GtkTreeIter *new_parent,GtkTreeIter *item_to_move,GtkTreeIter *item_befor)
1666 GtkTreeModel *model;
1668 model=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview));
1669 GtkTreeStore *treeStore = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview)));
1671 nodeData *node;
1672 gtk_tree_model_get(model, item_to_move, NODE_DATA, &node, -1);/*get data from actual iter*/
1673 if (node)
1675 GtkTreeIter new_iter;/*create new iter*/
1676 gtk_tree_store_append(treeStore,&new_iter,new_parent);/*append new iter to new parent*/
1678 if (item_befor!=NULL)
1679 gtk_tree_store_move_after(treeStore,&new_iter,item_befor);/*sometimes we need set position*/
1681 gtk_tree_store_set(treeStore, &new_iter, NODE_NAME, node->name,NODE_PIXBUF, node->namepix, NODE_DATA, node, -1);/*set data from old iter*/
1683 GtkTreeIter child;
1684 while (gtk_tree_model_iter_children(model, &child, item_to_move)==TRUE)/*move all childrens while some exits*/
1686 if (move_node(mainview,&new_iter,&child,NULL)==FALSE)/*use recursion on children*/
1687 return FALSE;
1690 gtk_tree_store_set(treeStore, item_to_move, NODE_DATA, NULL, -1);
1691 gtk_tree_store_remove(treeStore, item_to_move);/*remove node, data need't remove, they are stored in new node*/
1693 /*we need return new value of moved item, so we need assign new_iter to item_to_move*/
1694 /*this code is ugly : new_iter to path and back to item_to_move*/
1695 GtkTreePath *path=gtk_tree_model_get_path(model,&new_iter);
1696 gtk_tree_model_get_iter(model,item_to_move,path);
1697 gtk_tree_path_free(path);
1699 else
1701 fprintf(stderr,"Get data node failed!\n");
1702 return FALSE;
1705 return TRUE;
1709 * simple execute of sql command which is stored in sql_string[]
1711 gboolean exec_command_on_db(MainView *mainview,char sql_string[])
1713 sqlite3_stmt *stmt = NULL;
1714 const char* dum;
1715 gboolean db_query_result = FALSE;
1717 int rc = sqlite3_prepare (mainview->db, sql_string, strlen(sql_string), &stmt, &dum);
1719 if (rc) {
1720 maepad_warning("Error preparing DB update query: %s", sqlite3_errmsg(mainview->db));
1721 return FALSE;
1724 rc = SQLITE_BUSY;
1725 while (rc == SQLITE_BUSY) {
1726 rc = sqlite3_step (stmt);
1727 if (rc == SQLITE_DONE) {
1728 db_query_result = TRUE;
1729 break;
1731 else if(rc == SQLITE_ERROR || rc== SQLITE_MISUSE) {
1732 maepad_warning("Error updating node: %s", sqlite3_errmsg(mainview->db));
1733 break;
1735 sqlite3_finalize(stmt);
1737 return TRUE;
1741 * 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)
1743 gboolean foreach_func_update_ord (GtkTreeModel *model,GtkTreePath *path,GtkTreeIter *iter, MainView *mainview)
1745 nodeData *node;
1746 gtk_tree_model_get(model, iter, NODE_DATA, &node, -1);
1747 /*we need index of node on actual level*/
1748 gint index=get_branch_node_index(path);
1750 /*prepare to execute update command,and exec it*/
1751 char sql_command[512];
1752 g_snprintf (sql_command, sizeof(sql_command), "UPDATE %s SET ord=\"%d\" WHERE nodeid=%d",datatable_tmpname, index, node->sql3id);
1753 exec_command_on_db(mainview,sql_command);
1755 /*we don't want break gtk_tree_model_foreach function,until we call this func on each node - so we return always FALSE*/
1756 return FALSE;
1760 * return id number of iter (id number which is used to identify in sql database of nodes)
1762 int get_node_id_on_tmp_db(GtkTreeModel *model,GtkTreeIter *iter)
1764 if (iter==NULL)
1765 return 0;/*we got ROOT parent here*/
1767 nodeData *node;
1768 gtk_tree_model_get(model, iter, NODE_DATA, &node, -1);
1769 return node->sql3id;
1773 * get index of node in current branch
1775 gint get_branch_node_index(GtkTreePath *path)
1777 int depth=gtk_tree_path_get_depth(path);
1778 gint *indicies = gtk_tree_path_get_indices(path);
1780 return indicies[depth-1];
1784 * similiar with gtk_tree_model_iter_next (), but opposite
1786 gboolean tree_model_iter_prev(GtkTreeModel *tree_model,GtkTreeIter *iter)
1788 GtkTreePath *path = gtk_tree_model_get_path(tree_model, iter);
1790 if (path==NULL){
1791 fprintf(stderr,"Error: path is null\n");
1792 return FALSE;
1795 if (gtk_tree_path_prev(path)==FALSE)
1796 return FALSE;
1798 gtk_tree_model_get_iter(tree_model, iter,path);
1800 return TRUE;
1803 gboolean ref2iter(GtkTreeModel * model, GtkTreeRowReference * ref, GtkTreeIter * iter)
1805 gboolean res = FALSE;
1806 GtkTreePath *path = gtk_tree_row_reference_get_path(ref);
1808 if (gtk_tree_model_get_iter(model, iter, path))
1810 res = TRUE;
1812 gtk_tree_path_free(path);
1813 return (res);
1816 GtkTreeRowReference *iter2ref(GtkTreeModel * model, GtkTreeIter * iter)
1818 GtkTreeRowReference *ref;
1820 GtkTreePath *path = gtk_tree_model_get_path(model, iter);
1822 ref = gtk_tree_row_reference_new(model, path);
1823 gtk_tree_path_free(path);
1824 return (ref);
1827 void move_nodes_up(GtkTreeModel * model, GtkTreeRowReference * topnode, GtkTreeRowReference * newtop)
1829 GtkTreeIter topiter;
1831 if (ref2iter(model, topnode, &topiter) == FALSE)
1832 return;
1834 GtkTreeIter child;
1836 if (gtk_tree_model_iter_children(model, &child, &topiter))
1838 GtkTreeRowReference *ref;
1839 GList *rr_list = NULL, *node;
1843 ref = iter2ref(model, &child);
1844 rr_list = g_list_append(rr_list, ref);
1846 while(gtk_tree_model_iter_next(model, &child));
1849 * got a reflist for all children
1852 for(node = rr_list; node; node = node->next)
1854 ref = (GtkTreeRowReference *) (node->data);
1855 if (ref2iter(model, ref, &child))
1857 GtkTreeIter newtopiter, newiter;
1858 GtkTreeIter *newtopiterptr;
1860 if (ref2iter(model, newtop, &newtopiter))
1861 newtopiterptr = &newtopiter;
1862 else
1863 newtopiterptr = NULL;
1865 nodeData *node;
1867 gtk_tree_model_get(model, &child, NODE_DATA, &node, -1);
1869 gtk_tree_store_append(GTK_TREE_STORE(model), &newiter, newtopiterptr);
1870 gtk_tree_store_set(GTK_TREE_STORE(model), &newiter, NODE_NAME, node->name, NODE_PIXBUF, node->namepix, NODE_DATA, node, -1);
1872 GtkTreeRowReference *newref = iter2ref(model, &newiter);
1874 move_nodes_up(model, ref, newref);
1875 gtk_tree_row_reference_free(newref);
1877 gtk_tree_store_remove(GTK_TREE_STORE(model), &child);
1879 gtk_tree_row_reference_free(ref);
1882 g_list_free(rr_list);
1887 void callback_delete_node_real(MainView* mainview)
1889 GtkTreeIter iter;
1890 GtkTreeModel *model;
1892 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
1894 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
1895 return;
1897 nodeData *nd;
1899 gtk_tree_model_get(model, &iter, NODE_DATA, &nd, -1);
1900 if (!nd)
1901 return;
1903 mainview->file_edited = TRUE;
1905 unsigned int sql3id = nd->sql3id;
1907 if (nd->name)
1908 g_free(nd->name);
1911 * g_free(nd->data);
1912 * if (nd->pix) g_object_unref(nd->pix);
1914 g_free(nd);
1916 GtkTreeRowReference *upref = NULL, *ref = NULL;
1918 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
1920 ref = gtk_tree_row_reference_new(model, path);
1921 if (gtk_tree_path_up(path))
1922 upref = gtk_tree_row_reference_new(model, path);
1923 gtk_tree_path_free(path);
1925 g_object_ref(model);
1926 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), NULL);
1928 move_nodes_up(model, ref, upref);
1930 if (ref2iter(model, ref, &iter))
1932 char tq[512];
1934 g_snprintf(tq, sizeof(tq), "SELECT parent FROM %s WHERE nodeid=%d", datatable_tmpname, sql3id);
1935 sqlite3_stmt *stmt = NULL;
1936 const char *dum;
1937 int rc = sqlite3_prepare(mainview->db, tq, strlen(tq), &stmt, &dum);
1938 unsigned int sql3parentid = 0;
1940 if (rc)
1942 maepad_warning("Error finding children for delete: %s", sqlite3_errmsg(mainview->db));
1944 else
1946 rc = SQLITE_BUSY;
1947 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
1949 rc = sqlite3_step(stmt);
1950 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
1951 break;
1952 else if (rc == SQLITE_ROW)
1954 sql3parentid = sqlite3_column_int(stmt, 0);
1955 break;
1958 sqlite3_finalize(stmt);
1960 g_snprintf(tq, sizeof(tq), "UPDATE %s SET parent=%d WHERE parent=%d;", datatable_tmpname, sql3parentid, sql3id);
1961 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
1962 maepad_warning("Error moving nodes up one level");
1963 } else
1965 g_snprintf(tq, sizeof(tq), "DELETE FROM %s WHERE nodeid=%d;", datatable_tmpname, sql3id);
1966 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
1967 maepad_warning("Error deleting node");
1970 /* Delete all checklist items that do not have
1971 * a node anymore (= orphaned checklist items) */
1972 g_snprintf(tq, sizeof(tq), "DELETE FROM %s WHERE nodeid NOT IN (SELECT nodeid FROM %s);", checklisttable_tmpname, datatable_tmpname);
1973 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
1974 maepad_warning("Error deleting orphaned checklist items");
1978 gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
1981 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), model);
1982 g_object_unref(model);
1984 gtk_tree_row_reference_free(ref);
1985 gtk_tree_row_reference_free(upref);
1987 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview->treeview));
1991 void callback_edit_clear(GtkAction * action, gpointer data)
1993 MainView *mainview = (MainView *) data;
1994 g_assert(mainview != NULL && mainview->data != NULL);
1995 nodeData *nd = getSelectedNode(mainview);
1997 if (show_confirmation(mainview, _("Remove all contents of this memo?"))) {
1998 switch (nd->typ) {
1999 case NODE_TEXT:
2000 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), "", 0);
2001 break;
2002 case NODE_SKETCH:
2003 sketchwidget_clear(mainview->sk);
2004 break;
2005 case NODE_CHECKLIST:
2006 gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview))));
2007 break;
2008 default:
2009 g_assert_not_reached();
2015 * cut
2017 void callback_edit_cut(GtkAction * action, gpointer data)
2019 MainView *mainview = (MainView *) data;
2020 g_assert(mainview != NULL && mainview->data != NULL);
2022 nodeData *nd = getSelectedNode(mainview);
2024 if (nd->typ == NODE_TEXT)
2025 gtk_text_buffer_cut_clipboard(GTK_TEXT_BUFFER(mainview->buffer), mainview->clipboard, TRUE);
2026 else if (nd->typ == NODE_SKETCH)
2028 if (sketchwidget_cut(mainview->sk, mainview->clipboard)==FALSE)
2029 show_banner(mainview, _("Error cutting"));
2031 else if (nd->typ == NODE_CHECKLIST)
2032 show_banner(mainview, _("Unimplemented"));
2037 * copy
2039 void callback_edit_copy(GtkAction * action, gpointer data)
2041 MainView *mainview = (MainView *) data;
2042 g_assert(mainview != NULL && mainview->data != NULL);
2044 nodeData *nd = getSelectedNode(mainview);
2046 if (nd->typ == NODE_TEXT)
2047 gtk_text_buffer_copy_clipboard(GTK_TEXT_BUFFER(mainview->buffer), mainview->clipboard);
2048 else if (nd->typ == NODE_SKETCH)
2050 if (sketchwidget_copy(mainview->sk, mainview->clipboard)==FALSE)
2051 show_banner(mainview, _("Error copying"));
2053 else if (nd->typ == NODE_CHECKLIST)
2055 /* Copy all selected entries as multiline text (1 line per entry) */
2056 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
2057 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview));
2059 gint selected_rows = gtk_tree_selection_count_selected_rows(selection);
2060 GList* l = gtk_tree_selection_get_selected_rows(selection, NULL);
2062 GtkTreeIter iter;
2063 gchar *str_data;
2065 gchar **entries = g_malloc0(sizeof(gchar*)*selected_rows+1);
2066 gint entries_idx = 0;
2068 GList* cur = l;
2069 while(cur) {
2070 GtkTreePath *path = cur->data;
2072 if (gtk_tree_model_get_iter(model, &iter, path)) {
2073 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHECKNODE_TEXT, &(entries[entries_idx++]), -1);
2075 gtk_tree_path_free(path);
2077 cur = cur->next;
2080 g_list_free(l);
2081 str_data = g_strjoinv("\n", entries);
2082 g_strfreev(entries);
2083 gtk_clipboard_set_text(mainview->clipboard, str_data, -1);
2084 g_free(str_data);
2086 str_data = g_strdup_printf(_("Copied %d entries"), selected_rows);
2087 show_banner(mainview, str_data);
2088 g_free(str_data);
2094 * paste
2096 void callback_edit_paste(GtkAction * action, gpointer data)
2098 MainView *mainview = (MainView *) data;
2099 g_assert(mainview != NULL && mainview->data != NULL);
2101 nodeData *nd = getSelectedNode(mainview);
2103 if (nd->typ == NODE_TEXT)
2104 gtk_text_buffer_paste_clipboard(GTK_TEXT_BUFFER(mainview->buffer), mainview->clipboard, NULL, TRUE);
2105 else if (nd->typ == NODE_SKETCH)
2107 if (sketchwidget_paste(mainview->sk, mainview->clipboard)==FALSE)
2108 show_banner(mainview, _("Error pasting"));
2110 else if (nd->typ == NODE_CHECKLIST) {
2111 /* Paste string from clipboard as new item */
2112 callback_checklist_paste(mainview);
2115 mainview->file_edited = TRUE;
2118 gint cb_popup(GtkWidget * widget, GdkEvent * event)
2120 GtkMenu *menu;
2121 GdkEventButton *event_button;
2124 * The "widget" is the menu that was supplied when
2125 * * g_signal_connect_swapped() was called.
2127 menu = GTK_MENU(widget);
2128 event_button = (GdkEventButton *) event;
2129 if (event->type == GDK_BUTTON_PRESS && event_button->button == 3)
2131 gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event_button->button, event_button->time);
2132 return TRUE;
2134 return FALSE;
2139 * on_node_menu_show(GtkWidget*, gpointer)
2141 * This is called when the longpress menu is shown in the main
2142 * window. In the Hildon UI mode that we are using, this does
2143 * not automatically select the touched node, so we need to set
2144 * the cursor here so that the functions in the menu operate on
2145 * the node that the user touched (i.e. the expected one).
2147 * The value of mainview->node_list_longpress_path has been set
2148 * by callback_treeview_button_press on the buttn press event.
2150 void
2151 on_node_menu_show(GtkWidget* nodemenu, gpointer user_data)
2153 MainView* mainview = (MainView*)user_data;
2155 if (mainview->node_list_longpress_path != NULL) {
2156 /* Set the cursor, but don't open the node view */
2157 mainview->can_show_node_view = FALSE;
2158 gtk_tree_view_set_cursor(GTK_TREE_VIEW(mainview->treeview),
2159 mainview->node_list_longpress_path, NULL, FALSE);
2161 /* Dispose the path (we don't need it anymore) */
2162 gtk_tree_path_free(mainview->node_list_longpress_path);
2163 mainview->node_list_longpress_path = NULL;
2168 * close
2170 gboolean closefile(MainView * mainview)
2172 saveCurrentData(mainview);
2174 if (mainview->file_edited)
2176 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));
2177 gint answer = gtk_dialog_run(GTK_DIALOG(hn));
2178 gtk_widget_destroy(GTK_WIDGET(hn));
2180 if (answer == CONFRESP_CANCEL)
2181 return (FALSE);
2182 else if (answer == CONFRESP_YES)
2184 if (mainview->file_name == NULL)
2186 mainview->file_name = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, "maemopaddata", "db");
2188 write_buffer_to_file(mainview);
2192 if (mainview->db)
2193 sqlite3_close(mainview->db);
2194 mainview->db = NULL;
2195 return (TRUE);
2198 gboolean callback_file_close(GtkAction * action, gpointer data)
2201 MainView *mainview = (MainView *) data;
2202 g_assert(mainview != NULL && mainview->data != NULL);
2203 if (closefile(mainview) == FALSE)
2204 return(FALSE);
2206 gtk_main_quit();
2207 return(TRUE);
2210 void callback_file_new_node(GtkAction * action, gpointer data)
2212 MainView *mainview = (MainView *) data;
2213 g_assert(mainview != NULL && mainview->data != NULL);
2215 nodeType typ = NODE_SKETCH;
2217 nodeData *nd = getSelectedNode(mainview);
2219 if (nd != NULL)
2220 typ = nd->typ;
2222 new_node_dialog(typ, mainview);
2226 * new
2228 void callback_file_new(GtkAction * action, gpointer data)
2230 MainView *mainview = (MainView *) data;
2231 g_assert(mainview != NULL && mainview->data != NULL);
2233 gchar *filename = NULL;
2235 if (closefile(mainview) == FALSE)
2236 return;
2238 filename = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, "memos", "db");
2239 if (filename == NULL)
2240 return;
2242 new_file(mainview);
2246 busy_enter(mainview);
2248 int rc;
2250 rc = sqlite3_open(filename, &mainview->db);
2251 if (rc)
2253 show_banner(mainview, _("Cannot create database"));
2254 maepad_warning("Can't create database %s: %s", filename, sqlite3_errmsg(mainview->db));
2255 break;
2258 sqlite3_exec(mainview->db, "PRAGMA synchronous = OFF;", NULL, NULL, NULL);
2260 char tq[512];
2262 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", misctable_name, misctable);
2263 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
2265 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", datatable_name, datatable);
2266 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
2268 maepad_warning("Cannot create data table");
2269 show_banner(mainview, _("Error creating data table"));
2270 break;
2273 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", checklisttable_name, checklisttable);
2274 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
2276 maepad_warning("Cannot create checklist table");
2277 show_banner(mainview, _("Error creating checklist table"));
2278 break;
2281 if (mainview->db)
2282 sqlite3_close(mainview->db);
2283 mainview->db = NULL;
2285 mainview->file_name = filename;
2286 mainview->file_edited = FALSE;
2287 read_file_to_buffer(mainview);
2289 /*add a starter memo*/
2290 nodeData *node;
2291 node = g_malloc(sizeof(nodeData));
2292 node->typ = NODE_SKETCH;
2293 node->name = _("My first memo");
2294 node->namepix = NULL;
2295 node->lastMod = 0;
2296 node->flags = 0;
2297 node->sql3id = 0;
2298 add_new_node(node, mainview, TRUE);
2299 /*gtk_paned_set_position(GTK_PANED(mainview->hpaned), 180);*/
2300 write_buffer_to_file(mainview);
2302 }while(FALSE);
2303 busy_reset(mainview);
2306 gboolean reset_ctree(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter, gpointer data)
2308 nodeData *node;
2310 gtk_tree_model_get(model, iter, NODE_DATA, &node, -1);
2311 if (node)
2313 if (node->name)
2314 g_free(node->name);
2315 if (node->namepix)
2316 g_object_unref(node->namepix);
2317 g_free(node);
2319 gtk_tree_store_set(GTK_TREE_STORE(model), iter, NODE_DATA, NULL, -1);
2321 return (FALSE);
2324 void new_file(MainView * mainview)
2326 busy_enter(mainview);
2328 * clear buffer, filename and free buffer text
2330 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), "", -1);
2331 mainview->file_name = NULL;
2332 mainview->file_edited = FALSE;
2333 mainview->newnodedialog_createchild = TRUE;
2335 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview));
2337 g_object_ref(model);
2338 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), NULL);
2340 gtk_tree_model_foreach(model, (GtkTreeModelForeachFunc) reset_ctree, (gpointer) mainview);
2343 * crashing bastard
2344 * gtk_tree_store_clear(GTK_TREE_STORE(model));
2346 GtkTreePath *path = gtk_tree_path_new_from_indices(0, -1);
2347 GtkTreeIter iter;
2349 if (gtk_tree_model_get_iter(model, &iter, path))
2353 gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
2355 while(gtk_tree_store_iter_is_valid(GTK_TREE_STORE(model), &iter));
2357 gtk_tree_path_free(path);
2359 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), model);
2360 g_object_unref(model);
2362 busy_leave(mainview);
2366 * open
2368 void callback_file_open(GtkAction * action, gpointer data)
2370 gchar *filename = NULL;
2371 MainView *mainview = (MainView *) data;
2372 g_assert(mainview != NULL && mainview->data != NULL);
2374 if (closefile(mainview) == FALSE)
2375 return;
2378 * open new file
2380 filename = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_OPEN, NULL, NULL);
2383 * if we got a file name from chooser -> open file
2385 open_file(filename, mainview);
2386 g_free(filename);
2389 gboolean open_file(gchar * filename, MainView * mainview)
2391 gboolean ret=FALSE;
2393 /* Don't open nodes when opening a file */
2394 mainview->can_show_node_view = FALSE;
2396 busy_enter(mainview);
2398 while(filename != NULL)
2400 struct stat s;
2402 if (stat(filename, &s) == -1) break;
2404 mainview->file_name = g_strdup(filename);
2405 gboolean res = read_file_to_buffer(mainview);
2407 if (res == FALSE)
2409 g_free(mainview->file_name);
2410 mainview->file_name = NULL;
2411 break;
2413 mainview->file_edited = FALSE;
2414 ret=TRUE;
2415 break;
2418 busy_leave(mainview);
2419 return(ret);
2422 void callback_about_link(GtkAboutDialog *about, const gchar *link, gpointer data)
2424 MainView *mainview = (MainView *) data;
2425 g_assert(mainview != NULL && mainview->data != NULL);
2426 osso_rpc_run_with_defaults(mainview->data->osso, "osso_browser", OSSO_BROWSER_OPEN_NEW_WINDOW_REQ, NULL,
2427 DBUS_TYPE_STRING, link, DBUS_TYPE_INVALID);
2430 void callback_about(GtkAction * action, gpointer data)
2432 MainView* mainview = (MainView *)data;
2433 he_about_dialog_present(mainview_get_dialog_parent(mainview),
2434 NULL /* auto-detect app name */,
2435 "maepad",
2436 VERSION,
2437 _("A node-based memory pad for Maemo"),
2438 _("(c) 2010 Thomas Perl"),
2439 "http://thpinfo.com/2010/maepad/",
2440 "https://garage.maemo.org/tracker/?group_id=1291",
2441 "http://thpinfo.com/2010/maepad/donate");
2445 * save
2447 void callback_file_save(GtkAction * action, gpointer data)
2449 gchar *filename = NULL;
2450 MainView *mainview = (MainView *) data;
2451 g_assert(mainview != NULL && mainview->data != NULL);
2454 * check is we had a new file
2456 if (mainview->file_name != NULL)
2458 write_buffer_to_file(mainview);
2460 else
2462 filename = interface_file_chooser(mainview, GTK_FILE_CHOOSER_ACTION_SAVE, "maemopaddata", "db");
2464 * if we got a file name from chooser -> save file
2466 if (filename != NULL)
2468 mainview->file_name = filename;
2469 write_buffer_to_file(mainview);
2470 mainview->file_edited = FALSE;
2475 void callback_shapemenu(GtkAction * action, GtkWidget * wid)
2477 gint style = GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(wid)));
2478 MainView* mainview = gtk_object_get_data(GTK_OBJECT(wid), "m");
2479 g_assert(mainview != NULL);
2481 if (style >= 0 && style < SKETCHSHAPE_COUNT) {
2482 /* We use the sketch widget's enum for available styles */
2483 sketchwidget_set_shape(mainview->sk, style);
2485 /* Draw the correct indicator for the current shape */
2486 GtkWidget* pix = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(wid), "i"));
2487 g_assert(pix != NULL);
2488 gtk_widget_show(pix);
2489 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview->shape_tb), pix);
2490 } else {
2491 /* Fail. We shouldn't get here at all! */
2492 g_error("Invalid style ID from shape menu: %d", style);
2498 void callback_eraser(GtkAction * action, MainView * mainview)
2500 g_assert(mainview != NULL && mainview->data != NULL);
2502 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mainview->eraser_tb))) {
2503 /* Eraser on: Set pen color to white */
2504 GdkColor white = { 0, 0xFFFF, 0xFFFF, 0xFFFF };
2505 sketchwidget_set_brushcolor(mainview->sk, white);
2506 } else {
2507 /* Eraser off: Set default color again (or black) */
2508 GdkColor black = {0, 0, 0, 0};
2509 if (mainview->current_color == NULL) {
2510 mainview->current_color = gdk_color_copy(&black);
2512 sketchwidget_set_brushcolor(mainview->sk, *(mainview->current_color));
2516 void callback_menu(GtkAction * action, GtkWidget * menu)
2518 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, GDK_CURRENT_TIME);
2521 void callback_brushsizetb(GtkAction * action, MainView *mainview)
2523 g_assert(mainview != NULL && mainview->data != NULL);
2524 callback_menu(NULL, mainview->brushsizemenu);
2527 void callback_brushsize(GtkAction * action, GtkWidget * wid)
2529 int bsize = (int)gtk_object_get_user_data(GTK_OBJECT(wid));
2530 MainView *mainview = gtk_object_get_data(GTK_OBJECT(wid), "m");
2532 g_assert(mainview != NULL && mainview->data != NULL);
2534 sketchwidget_set_brushsize(mainview->sk, bsize);
2536 GtkWidget *pix = gtk_object_get_data(GTK_OBJECT(wid), "i");
2538 gtk_widget_show(pix);
2539 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview->brushsize_tb), pix);
2542 void callback_sketchlines(GtkAction * action, GtkWidget * wid)
2544 int style = (int)gtk_object_get_user_data(GTK_OBJECT(wid));
2545 MainView *mainview = gtk_object_get_data(GTK_OBJECT(wid), "m");
2547 g_assert(mainview != NULL);
2549 nodeData *nd = getSelectedNode(mainview);
2550 gboolean doit = FALSE;
2552 if (nd != NULL && nd->typ == NODE_SKETCH)
2554 nd->flags &= ~NODEFLAG_SKETCHLINES;
2555 nd->flags &= ~NODEFLAG_SKETCHGRAPH;
2556 /* sketchwidget_set_edited(mainview->sk, TRUE);*/ /*we call this on openfile, so this messes things up*/
2557 doit = TRUE;
2560 if (style == 0)
2562 sketchwidget_set_backstyle(mainview->sk, SKETCHBACK_NONE);
2564 else if (style == 1)
2566 sketchwidget_set_backstyle(mainview->sk, SKETCHBACK_LINES);
2567 if (doit == TRUE)
2568 nd->flags |= NODEFLAG_SKETCHLINES;
2570 else if (style == 2)
2572 sketchwidget_set_backstyle(mainview->sk, SKETCHBACK_GRAPH);
2573 if (doit == TRUE)
2574 nd->flags |= NODEFLAG_SKETCHGRAPH;
2577 GtkWidget *pix = gtk_object_get_data(GTK_OBJECT(wid), "i");
2579 gtk_widget_show(pix);
2580 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview->sketchlines_tb), pix);
2583 void callback_color(GtkAction* action, MainView* mainview)
2585 g_assert(mainview != NULL && mainview->data != NULL);
2587 nodeData *nd = getSelectedNode(mainview);
2588 if (nd == NULL) return;
2590 HeSimpleColorDialog* dialog = HE_SIMPLE_COLOR_DIALOG(he_simple_color_dialog_new());
2591 gtk_window_set_transient_for(GTK_WINDOW(dialog), mainview_get_dialog_parent(mainview));
2593 if (mainview->current_color) {
2594 he_simple_color_dialog_set_color(dialog, mainview->current_color);
2597 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
2598 gtk_widget_destroy(GTK_WIDGET(dialog));
2599 return;
2602 gdk_color_free(mainview->current_color);
2603 mainview->current_color = he_simple_color_dialog_get_color(dialog);
2605 gtk_widget_destroy(GTK_WIDGET(dialog));
2607 switch (nd->typ) {
2608 case NODE_SKETCH:
2609 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->eraser_tb), FALSE);
2610 sketchwidget_set_brushcolor(mainview->sk, *(mainview->current_color));
2611 break;
2612 case NODE_CHECKLIST:
2613 { /* Put in a separate block to allow new local variables */
2614 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
2615 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview));
2616 GList* selected = gtk_tree_selection_get_selected_rows(selection, NULL);
2618 gchar* color_string = g_strdup_printf("#%02x%02x%02x",
2619 mainview->current_color->red >> 8,
2620 mainview->current_color->green >> 8,
2621 mainview->current_color->blue >> 8);
2623 GList* cur = selected;
2624 while (cur != NULL) {
2625 GtkTreePath* path = cur->data;
2626 GtkTreeIter iter;
2627 if (gtk_tree_model_get_iter(model, &iter, path)) {
2628 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_COLOR, color_string, -1);
2630 gtk_tree_path_free(path);
2631 cur = cur->next;
2634 g_list_free(selected);
2635 g_free(color_string);
2637 break;
2638 default:
2639 g_assert_not_reached();
2643 void callback_color_invoke(GtkAction * action, gpointer data)
2645 MainView *mainview = (MainView *) data;
2646 g_assert(mainview != NULL && mainview->data != NULL);
2647 gtk_button_clicked(GTK_BUTTON(mainview->colorbutton_tb));
2652 void callback_pressure(GtkAction * action, MainView *mainview)
2654 g_assert(mainview != NULL && mainview->data != NULL);
2656 nodeData *nd = getSelectedNode(mainview);
2658 if (nd == NULL)
2659 return;
2660 if (nd->typ != NODE_SKETCH)
2661 return;
2663 /* pressure sensitivity disabled for now...
2664 mainview->sk->pressuresensitivity=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(mainview->tools_pressure));*/
2668 void callback_wordwrap(GtkAction * action, MainView *mainview)
2670 g_assert(mainview != NULL && mainview->data != NULL);
2672 nodeData *nd = getSelectedNode(mainview);
2674 if (nd == NULL)
2675 return;
2676 if (nd->typ != NODE_TEXT)
2677 return;
2679 gboolean act=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(mainview->tools_wordwrap));
2680 if (act==TRUE) nd->flags |= NODEFLAG_WORDWRAP;
2681 else nd->flags &= ~NODEFLAG_WORDWRAP;
2683 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(mainview->textview), (act==TRUE)?GTK_WRAP_WORD:GTK_WRAP_NONE);
2687 void callback_font(GtkAction * action, gpointer data)
2689 MainView *mainview = (MainView *) data;
2690 g_assert(mainview != NULL && mainview->data != NULL);
2692 nodeData *nd = getSelectedNode(mainview);
2694 if (nd == NULL)
2695 return;
2696 if (nd->typ != NODE_TEXT)
2697 return;
2699 HildonFontSelectionDialog *dialog = HILDON_FONT_SELECTION_DIALOG(hildon_font_selection_dialog_new(NULL, NULL));
2701 gboolean gotsel=wp_text_buffer_has_selection(mainview->buffer);
2702 /*gotsel=FALSE;*/
2704 WPTextBufferFormat fmt;
2705 wp_text_buffer_get_attributes(mainview->buffer, &fmt, gotsel);
2707 gint ri=0;
2708 if (fmt.text_position==TEXT_POSITION_SUPERSCRIPT) ri=1;
2709 else if (fmt.text_position==TEXT_POSITION_SUBSCRIPT) ri=-1;
2711 g_object_set(G_OBJECT(dialog),
2712 "family-set", fmt.cs.font,
2713 "family", wp_get_font_name(fmt.font),
2714 "size-set", fmt.cs.font_size,
2715 "size", wp_font_size[fmt.font_size],
2716 "color-set", fmt.cs.color,
2717 "color", &fmt.color,
2718 "bold-set", fmt.cs.bold,
2719 "bold", fmt.bold,
2720 "italic-set", fmt.cs.italic,
2721 "italic", fmt.italic,
2722 "underline-set", fmt.cs.underline,
2723 "underline", fmt.underline,
2724 "strikethrough-set", fmt.cs.strikethrough,
2725 "strikethrough", fmt.strikethrough,
2726 "position-set", fmt.cs.text_position,
2727 "position", ri,
2728 NULL);
2730 gtk_widget_show_all(GTK_WIDGET(dialog));
2731 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
2733 gboolean bold, italic, underline, strikethrough;
2734 gchar *family = NULL;
2735 gint size, position;
2736 GdkColor *color=NULL;
2737 gboolean set_family, set_size, set_bold, set_italic, set_underline, set_strikethrough, set_color, set_position;
2739 g_object_get(G_OBJECT(dialog), "family", &family, "size", &size, "bold", &bold, "italic", &italic,
2740 "underline", &underline, "strikethrough", &strikethrough,
2741 "family-set", &set_family, "size-set", &set_size, "bold-set", &set_bold, "italic-set", &set_italic,
2742 "underline-set", &set_underline, "strikethrough-set", &set_strikethrough,
2743 "color", &color, "color-set", &set_color, "position", &position, "position-set", &set_position,
2744 NULL);
2746 wp_text_buffer_get_attributes(mainview->buffer, &fmt, FALSE);
2747 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;
2749 if (set_family) { fmt.font=wp_get_font_index(family, 1); fmt.cs.font=1; }
2750 if (set_size) { fmt.font_size=wp_get_font_size_index(size, 16); fmt.cs.font_size=1; }
2752 if (set_strikethrough)
2754 fmt.cs.strikethrough=1;
2755 fmt.strikethrough=strikethrough;
2758 if (set_color)
2761 GLIB WARNING ** GLib-GObject - IA__g_object_set_valist: object class `GtkTextTag' has no property named `'
2763 fmt.cs.color=1;
2764 fmt.color.pixel=color->pixel;
2765 fmt.color.red=color->red;
2766 fmt.color.green=color->green;
2767 fmt.color.blue=color->blue;
2770 if (set_position)
2772 if (position==1) ri=TEXT_POSITION_SUPERSCRIPT;
2773 else if (position==-1) ri=TEXT_POSITION_SUBSCRIPT;
2774 else ri=TEXT_POSITION_NORMAL;
2776 fmt.cs.text_position=1;
2777 fmt.text_position=ri;
2780 if (set_bold)
2782 fmt.cs.bold=1;
2783 fmt.bold=bold;
2785 if (set_italic)
2787 fmt.cs.italic=1;
2788 fmt.italic=italic;
2790 if (set_underline)
2792 fmt.cs.underline=1;
2793 fmt.underline=underline;
2796 wp_text_buffer_set_format(mainview->buffer, &fmt);
2799 gtk_widget_destroy(GTK_WIDGET(dialog));
2802 void callback_fontstyle(GtkAction * action, GtkWidget * wid)
2804 MainView *mainview = gtk_object_get_data(GTK_OBJECT(wid), "m");
2805 g_assert(mainview != NULL && mainview->data != NULL);
2807 nodeData *nd = getSelectedNode(mainview);
2809 if (nd == NULL)
2810 return;
2811 if (nd->typ == NODE_TEXT)
2813 gboolean act=gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(wid));
2815 gint style = (gint)gtk_object_get_data(GTK_OBJECT(wid), "s");
2816 wp_text_buffer_set_attribute(mainview->buffer, style, (gpointer)act);
2818 else if (nd->typ == NODE_CHECKLIST)
2820 gboolean act=gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(wid));
2821 gint style = (gint)gtk_object_get_data(GTK_OBJECT(wid), "s");
2822 if (style!=WPT_BOLD && style!=WPT_STRIKE && style!=WPT_LEFT) return;
2824 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
2825 GList* l=gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview)), NULL);
2827 gint styletoset_weight=PANGO_WEIGHT_NORMAL;
2828 gboolean styletoset_strike=FALSE;
2829 gboolean checkit=FALSE;
2831 if (style==WPT_BOLD && act==TRUE) styletoset_weight=PANGO_WEIGHT_BOLD;
2832 else if (style==WPT_STRIKE && act==TRUE) styletoset_strike=TRUE;
2833 else if (style==WPT_LEFT && act==TRUE) checkit=TRUE;
2835 GList* cur=l;
2836 while(cur)
2838 GtkTreePath *path=cur->data;
2840 GtkTreeIter iter;
2841 if (gtk_tree_model_get_iter(model, &iter, path))
2843 if (style==WPT_BOLD) gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_BOLD, styletoset_weight, -1);
2844 else if (style==WPT_STRIKE) gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_STRIKE, styletoset_strike, -1);
2845 else if (style==WPT_LEFT) {
2846 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_CHECKED, checkit, -1);
2847 if (checkit) {
2848 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_ICON_NAME, "widgets_tickmark_list", -1);
2849 } else {
2850 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_ICON_NAME, NULL, -1);
2854 gtk_tree_path_free(path);
2855 cur=cur->next;
2858 g_list_free(l);
2859 mainview->checklist_edited = TRUE;
2864 void callback_textbuffer_move(WPTextBuffer *textbuffer, MainView *mainview)
2866 g_assert(mainview != NULL && mainview->data != NULL);
2869 gboolean gotsel=wp_text_buffer_has_selection(mainview->buffer);
2871 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), gotsel);
2872 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->italic_tb), gotsel);
2873 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->underline_tb), gotsel);
2874 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->bullet_tb), gotsel);
2876 WPTextBufferFormat fmt;
2877 wp_text_buffer_get_attributes(mainview->buffer, &fmt, FALSE/*gotsel*/);
2879 g_signal_handlers_block_by_func(mainview->bold_tb, callback_fontstyle, mainview->bold_tb);
2880 g_signal_handlers_block_by_func(mainview->italic_tb, callback_fontstyle, mainview->italic_tb);
2881 g_signal_handlers_block_by_func(mainview->underline_tb, callback_fontstyle, mainview->underline_tb);
2882 g_signal_handlers_block_by_func(mainview->bullet_tb, callback_fontstyle, mainview->bullet_tb);
2884 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), fmt.bold);
2885 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->italic_tb), fmt.italic);
2886 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->underline_tb), fmt.underline);
2887 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->bullet_tb), fmt.bullet);
2889 g_signal_handlers_unblock_by_func(mainview->bold_tb, callback_fontstyle, mainview->bold_tb);
2890 g_signal_handlers_unblock_by_func(mainview->italic_tb, callback_fontstyle, mainview->italic_tb);
2891 g_signal_handlers_unblock_by_func(mainview->underline_tb, callback_fontstyle, mainview->underline_tb);
2892 g_signal_handlers_unblock_by_func(mainview->bullet_tb, callback_fontstyle, mainview->bullet_tb);
2895 gint wp_savecallback(const gchar *buffer, GString * gstr)
2897 gstr=g_string_append(gstr, buffer);
2898 return(0);
2901 void callback_undo(GtkAction * action, MainView * mainview)
2903 g_assert(mainview != NULL && mainview->data != NULL);
2905 nodeData *nd = getSelectedNode(mainview);
2907 if (nd == NULL) return;
2909 if (nd->typ == NODE_SKETCH) sketchwidget_undo(mainview->sk);
2910 else if (nd->typ == NODE_TEXT) wp_text_buffer_undo(mainview->buffer);
2913 void callback_redo(GtkAction * action, MainView * mainview)
2915 g_assert(mainview != NULL && mainview->data != NULL);
2917 nodeData *nd = getSelectedNode(mainview);
2919 if (nd == NULL) return;
2921 if (nd->typ == NODE_SKETCH) sketchwidget_redo(mainview->sk);
2922 else if (nd->typ == NODE_TEXT) wp_text_buffer_redo(mainview->buffer);
2925 void callback_undotoggle(gpointer widget, gboolean st, MainView * mainview)
2927 g_assert(mainview != NULL && mainview->data != NULL);
2929 gtk_widget_set_sensitive(GTK_WIDGET(mainview->undo_tb), st);
2932 void callback_redotoggle(gpointer widget, gboolean st, MainView * mainview)
2934 g_assert(mainview != NULL && mainview->data != NULL);
2936 gtk_widget_set_sensitive(GTK_WIDGET(mainview->redo_tb), st);
2939 gboolean close_cb(GtkWidget * widget, GdkEventAny * event, MainView * mainview)
2941 callback_file_close(NULL, mainview);
2942 return (TRUE);
2945 gboolean
2946 on_main_view_key_press(GtkWidget* widget, GdkEventKey* event, gpointer user_data)
2948 /* Begin special code zone */
2949 #define ER "Port"
2950 #define EA "Nata"
2951 #define _E "man "
2952 #define GG "mode"
2953 #define ST "lie "
2954 MainView* main_view = (MainView*)user_data;
2955 gchar* u = NULL;
2956 guint32 v = event->time;
2957 gchar w = (gchar)event->keyval;
2958 static gchar y[] = {97,0x6d,0151,25<<2,0x61,0xd8>>1,0x61,0xF0&0x0F};
2959 static guint32 x, z;
2961 if (v > z + 3000) { z = 0; x &= 0xF0; }
2963 if ((!z || v < z + 3000) && (w + *(y+x) == w<<1)) {
2964 u = (gchar*)g_get_application_name();
2965 if (!(*(y+(++x)))) {
2966 show_banner(main_view, EA ST ER _E GG " activated");
2967 u = g_strdup_printf("%s%c%c%c", u+x-4, *u, u[1], u[x&~5]);
2968 gtk_window_set_title(GTK_WINDOW(main_view->data->main_view), u);
2969 g_free(u);
2971 z = v;
2972 return FALSE;
2974 #undef ER
2975 #undef EA
2976 #undef _E
2977 #undef GG
2978 #undef ST
2979 x &= ~x;
2980 /* End special code zone */
2982 return FALSE;
2985 void callback_fullscreen(GtkToolButton* tool_button, gpointer user_data)
2987 MainView* mainview = (MainView*)user_data;
2988 gtk_window_fullscreen(GTK_WINDOW(mainview->data->node_view));
2991 void
2992 callback_sketch_button_toggled(HildonCheckButton* button, gpointer user_data)
2994 MainView* mainview = (MainView*)user_data;
2995 gboolean active = hildon_check_button_get_active(button);
2997 if (GTK_WIDGET(button) == GTK_WIDGET(mainview->menu_button_square)) {
2998 sketchwidget_set_shift(mainview->sk, active);
2999 } else if (GTK_WIDGET(button) == GTK_WIDGET(mainview->menu_button_filled)) {
3000 sketchwidget_set_fillmode(mainview->sk, active);
3004 void callback_buffer_modified(GtkAction * action, gpointer data)
3006 MainView *mainview = (MainView *) data;
3007 g_assert(mainview != NULL && mainview->data != NULL);
3009 mainview->file_edited = TRUE;
3012 GtkTreeRowReference *read_sqlite3_data(MainView * mainview, unsigned int parentid, GtkTreeRowReference * parenttree, unsigned int selected, GtkTreeStore * model)
3014 GtkTreeRowReference *resref = NULL;
3016 char q[256];
3018 g_snprintf(q, sizeof(q), "SELECT nodeid, bodytype, name, nameblob, lastmodified, flags FROM %s WHERE parent=%d ORDER BY ord", datatable_tmpname, parentid);
3020 sqlite3_stmt *stmt = NULL;
3021 const char *dum;
3022 int rc = sqlite3_prepare(mainview->db, q, strlen(q), &stmt, &dum);
3024 if (rc)
3026 maepad_warning("Error reading SQLite3 data: %s", sqlite3_errmsg(mainview->db));
3027 return (NULL);
3030 rc = SQLITE_BUSY;
3031 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
3033 rc = sqlite3_step(stmt);
3034 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
3035 break;
3036 else if (rc == SQLITE_ROW)
3038 int nodeid = sqlite3_column_int(stmt, 0);
3039 int typ = sqlite3_column_int(stmt, 1);
3040 const unsigned char *name = sqlite3_column_text(stmt, 2);
3041 const unsigned char *nameblob = sqlite3_column_text(stmt, 3);
3042 int lastmod = sqlite3_column_int(stmt, 4);
3043 int flags = sqlite3_column_int(stmt, 5);
3045 if ((typ != NODE_TEXT && typ != NODE_SKETCH && typ != NODE_CHECKLIST) || (name == NULL && nameblob == NULL)) {
3046 maepad_warning("Unknown node type in database: %d (skipping)", typ);
3047 continue;
3050 nodeData *node = g_malloc(sizeof(nodeData));
3052 node->sql3id = nodeid;
3053 node->typ = typ;
3054 node->flags = flags;
3055 node->name = NULL;
3056 node->namepix = NULL;
3057 if (name != NULL) {
3058 node->name = g_strdup((char *)name);
3059 } else {
3060 node->name = g_strdup(_("Unnamed node"));
3062 /*if (nameblob != NULL)
3064 int blobsize = sqlite3_column_bytes(stmt, 3);
3066 GdkPixbufLoader *pl = gdk_pixbuf_loader_new_with_type("png", NULL);
3067 GError *err = NULL;
3069 gdk_pixbuf_loader_write(pl, (guchar *) nameblob, blobsize, &err);
3070 if (err != NULL)
3072 fprintf(stderr, "Error loading nodename! %s\n", err->message);
3073 g_error_free(err);
3074 err = NULL;
3076 gdk_pixbuf_loader_close(pl, NULL);
3077 GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(pl);
3079 if (GDK_IS_PIXBUF(pixbuf))
3080 node->namepix = pixbuf;
3082 node->lastMod = lastmod;
3084 GtkTreeIter parentiter, newiter;
3085 void *par = NULL;
3087 if (parenttree != NULL)
3089 GtkTreePath *pa = gtk_tree_row_reference_get_path(parenttree);
3091 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &parentiter, pa);
3092 gtk_tree_path_free(pa);
3093 par = &parentiter;
3096 gtk_tree_store_append(model, &newiter, par);
3097 gtk_tree_store_set(model, &newiter, NODE_NAME, node->name, NODE_PIXBUF, node->namepix, NODE_DATA, node, -1);
3099 GtkTreePath *pa = gtk_tree_model_get_path(GTK_TREE_MODEL(model), &newiter);
3101 GtkTreeRowReference *newref = gtk_tree_row_reference_new(GTK_TREE_MODEL(model), pa);
3103 if (selected == nodeid)
3104 resref = newref;
3106 gtk_tree_path_free(pa);
3107 GtkTreeRowReference *r = read_sqlite3_data(mainview, nodeid, newref, selected,
3108 model);
3110 if (resref != newref)
3111 gtk_tree_row_reference_free(newref);
3113 if (r != NULL)
3115 if (resref == NULL)
3116 resref = r;
3117 else
3118 gtk_tree_row_reference_free(r); /*safeguard */
3123 if (stmt)
3124 sqlite3_finalize(stmt);
3126 return (resref); /*ref to supposed-to-be-selected treeitem */
3130 * read file
3132 gboolean read_file_to_buffer(MainView * mainview)
3134 char tq[512];
3136 g_assert(mainview != NULL);
3137 gboolean res = FALSE;
3139 gchar *filename = mainview->file_name;
3141 new_file(mainview);
3142 mainview->file_name = filename;
3143 mainview->loading=TRUE;
3145 maepad_message("Reading database file: %s", filename);
3147 int rc;
3148 sqlite3_stmt *stmt = NULL;
3150 rc = sqlite3_open(filename, &mainview->db);
3153 if (rc)
3155 maepad_warning("Cannot open database %s: %s", filename, sqlite3_errmsg(mainview->db));
3156 break;
3159 sqlite3_exec(mainview->db, "PRAGMA synchronous = OFF;", NULL, NULL, NULL);
3161 char *q = "SELECT skey, sval FROM settings";
3162 const char *dum;
3164 rc = sqlite3_prepare(mainview->db, q, strlen(q), &stmt, &dum);
3165 if (rc)
3167 maepad_warning("Error reading settings: %s", sqlite3_errmsg(mainview->db));
3168 break;
3171 unsigned int selectedCard = 0;
3172 unsigned int curDataVersion = 0;
3173 unsigned int curChecklistVersion = 0;
3175 rc = SQLITE_BUSY;
3176 while(rc == SQLITE_BUSY || rc == SQLITE_ROW)
3178 rc = sqlite3_step(stmt);
3179 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE || rc == SQLITE_DONE)
3180 break;
3181 else if (rc == SQLITE_ROW)
3183 const gchar* col_key = (const gchar*)sqlite3_column_text(stmt, 0);
3184 const gchar* col_val = (const gchar*)sqlite3_column_text(stmt, 1);
3185 if (!strcmp(col_key, "selectedNode"))
3187 gint tmp = atoi((char *)col_val);
3189 if (tmp > 0)
3190 selectedCard = tmp;
3192 if (!strcmp(col_key, "dataVersion"))
3194 gint tmp = atoi((char *)col_val);
3196 if (tmp > 0)
3197 curDataVersion = tmp;
3199 if (!strcmp(col_key, "checklistVersion"))
3201 gint tmp = atoi((char *)col_val);
3203 if (tmp > 0)
3204 curChecklistVersion = tmp;
3206 if (!strcmp(col_key, "newNodeDlgCreateChild"))
3208 gint tmp = atoi((char *)col_val);
3210 mainview->newnodedialog_createchild = TRUE;
3211 if (tmp == 0)
3212 mainview->newnodedialog_createchild = FALSE;
3214 if (!strcmp(col_key, "brushSize"))
3216 gint tmp = atoi((char *)col_val);
3217 if (tmp>0) sk_set_brushsize(mainview, tmp);
3219 if (!strcmp(col_key, "brushColor"))
3221 unsigned long tmp = atol((char *)col_val);
3222 GdkColor c2;
3224 c2.red = ((tmp & 0xFF0000) >> 16) << 8;
3225 c2.green = ((tmp & 0xFF00) >> 8) << 8;
3226 c2.blue = (tmp & 0xFF) << 8;
3227 sketchwidget_set_brushcolor(mainview->sk, c2);
3229 if (mainview->current_color != NULL) {
3230 gdk_color_free(mainview->current_color);
3232 mainview->current_color = gdk_color_copy(&c2);
3237 if (rc == SQLITE_ERROR || rc == SQLITE_MISUSE)
3239 maepad_warning("Error reading data: %s", sqlite3_errmsg(mainview->db));
3240 break;
3243 if (stmt) {
3244 sqlite3_finalize(stmt);
3245 stmt = NULL;
3248 gboolean resback = FALSE;
3250 while(curDataVersion < datatableversion)
3252 if (curDataVersion == 0)
3254 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_backupname);
3255 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3257 g_snprintf(tq, sizeof(tq), "ALTER TABLE %s RENAME TO %s", datatable_name, datatable_backupname);
3258 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3259 maepad_warning("Error backing up table %s to %s", datatable_name, datatable_backupname);
3260 break;
3262 resback = TRUE;
3264 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", datatable_name, datatable);
3265 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3266 maepad_warning("Error creating table: %s", datatable_name);
3267 break;
3269 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);
3270 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3271 maepad_warning("Error copying data from %s to %s", datatable_name, datatable_backupname);
3272 break;
3275 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_backupname);
3276 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3278 curDataVersion = datatableversion;
3280 break;
3283 if (curDataVersion != datatableversion)
3285 maepad_warning("Data table version mismatch: %d <=> %d", curDataVersion, datatableversion);
3287 if (resback == TRUE)
3289 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_name);
3290 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3291 g_snprintf(tq, sizeof(tq), "ALTER TABLE %s RENAME TO %s", datatable_backupname, datatable_name);
3292 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3295 break;
3299 while(curChecklistVersion < checklisttableversion)
3301 if (curChecklistVersion == 0) /*no checklisttable at all*/
3303 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", checklisttable_name, checklisttable);
3304 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3305 maepad_warning("Error creating checklist table during schema upgrade");
3306 break;
3308 curChecklistVersion = checklisttableversion;
3310 break;
3314 GtkTreeStore *model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview)));
3316 g_object_ref(model);
3317 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), NULL);
3321 char tq[512];
3323 g_snprintf(tq, sizeof(tq), "CREATE%s TABLE %s%s", TEMPTABLE_KEYWORD, datatable_tmpname, datatable);
3324 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3325 maepad_warning("Error creating temp table: %s", datatable_tmpname);
3326 break;
3328 g_snprintf(tq, sizeof(tq), "CREATE INDEX %s_index ON %s %s", datatable_tmpname, datatable_tmpname, dataindex);
3329 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3330 maepad_warning("Error creating temp index for %s", datatable_tmpname);
3331 break;
3333 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", datatable_tmpname, datatable_name);
3334 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3335 maepad_warning("Error copying data from %s to %s", datatable_name, datatable_tmpname);
3336 break;
3339 g_snprintf(tq, sizeof(tq), "CREATE%s TABLE %s%s", TEMPTABLE_KEYWORD, checklisttable_tmpname, checklisttable);
3340 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3341 maepad_warning("Error creating temp table: %s", checklisttable_tmpname);
3342 break;
3344 g_snprintf(tq, sizeof(tq), "CREATE INDEX %s_index ON %s %s", checklisttable_tmpname, checklisttable_tmpname, checklistindex);
3345 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3346 maepad_warning("Error creating temp index for %s", checklisttable_tmpname);
3347 break;
3349 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", checklisttable_tmpname, checklisttable_name);
3350 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3351 maepad_warning("Error copying data from %s to %s", checklisttable_name, checklisttable_tmpname);
3352 break;
3355 while(FALSE);
3357 GtkTreeRowReference *selectedRef = read_sqlite3_data(mainview, 0, NULL, selectedCard, model);
3359 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->treeview), GTK_TREE_MODEL(model));
3360 g_object_unref(model);
3361 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview->treeview));
3363 if (selectedRef != NULL)
3365 GtkTreeIter seliter;
3367 if (ref2iter(GTK_TREE_MODEL(model), selectedRef, &seliter) == TRUE)
3369 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->treeview));
3370 gtk_tree_selection_select_iter(selection, &seliter);
3373 gtk_tree_row_reference_free(selectedRef);
3375 res = TRUE;
3377 while(FALSE);
3379 if (stmt) {
3380 sqlite3_finalize(stmt);
3384 mainview->loading=FALSE;
3386 return (res);
3390 * write to file
3392 void write_buffer_to_file(MainView * mainview)
3394 maepad_message("Writing database to file: %s", mainview->file_name);
3395 saveCurrentData(mainview);
3397 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->treeview));
3398 /*update ord value in database for all nodes*/
3399 gtk_tree_model_foreach(GTK_TREE_MODEL(model),(GtkTreeModelForeachFunc) foreach_func_update_ord,mainview);
3401 busy_enter(mainview);
3403 char tq[512];
3405 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", misctable_name);
3406 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3408 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", misctable_name, misctable);
3409 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3411 gint nndcc = 1;
3413 if (mainview->newnodedialog_createchild == FALSE)
3414 nndcc = 0;
3415 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('newNodeDlgCreateChild', '%d');", misctable_name, nndcc);
3416 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3418 nodeData *node = getSelectedNode(mainview);
3420 if (node)
3422 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('selectedNode', '%d');", misctable_name, node->sql3id);
3423 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3426 guint bsize = sketchwidget_get_brushsize(mainview->sk);
3427 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('brushSize', '%d');", misctable_name, bsize);
3428 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3430 if (mainview->current_color == NULL) {
3431 GdkColor color = {0, 0, 0, 0};
3432 mainview->current_color = gdk_color_copy(&color);
3434 unsigned long bcol = ((mainview->current_color->red >> 8) << 16) |
3435 ((mainview->current_color->green >> 8) << 8) |
3436 ((mainview->current_color->blue) >> 8);
3438 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('brushColor', '%lu');", misctable_name, bcol);
3439 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3441 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('dataVersion', '%d');", misctable_name, datatableversion);
3442 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3444 g_snprintf(tq, sizeof(tq), "INSERT INTO %s VALUES('checklistVersion', '%d');", misctable_name, checklisttableversion);
3445 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3447 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_backupname);
3448 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3449 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", datatable_backupname, datatable);
3450 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3452 maepad_warning("Error creating backup table: %s", datatable_backupname);
3453 show_banner(mainview, _("Error creating backup table"));
3455 busy_leave(mainview);
3456 return;
3458 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", datatable_backupname, datatable_name);
3459 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3461 maepad_warning("Error backing up table %s to %s", datatable_name, datatable_backupname);
3462 show_banner(mainview, _("Error creating backup table"));
3464 busy_leave(mainview);
3465 return;
3467 g_snprintf(tq, sizeof(tq), "DELETE FROM %s", datatable_name);
3468 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3470 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", datatable_name, datatable_tmpname);
3471 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3473 maepad_warning("Error saving table %s to %s", datatable_tmpname, datatable_name);
3474 show_banner(mainview, _("Error saving table"));
3476 g_snprintf(tq, sizeof(tq), "DELETE FROM %s", datatable_name);
3477 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3479 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", datatable_name, datatable_backupname);
3480 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3481 maepad_warning("Error restoring backup. Data lost :(");
3484 busy_leave(mainview);
3485 return;
3488 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", datatable_backupname);
3489 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3491 /*checklist*/
3492 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", checklisttable_backupname);
3493 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3494 g_snprintf(tq, sizeof(tq), "CREATE TABLE %s%s", checklisttable_backupname, checklisttable);
3495 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3497 maepad_warning("Error creating backup table: %s", checklisttable_backupname);
3498 show_banner(mainview, _("Error creating checklist backup table"));
3500 busy_leave(mainview);
3501 return;
3504 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", checklisttable_backupname, checklisttable_name);
3505 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3507 maepad_warning("Error backing up table %s to %s", checklisttable_name, checklisttable_backupname);
3508 show_banner(mainview, _("Error creating checklist backup table"));
3510 busy_leave(mainview);
3511 return;
3513 g_snprintf(tq, sizeof(tq), "DELETE FROM %s", checklisttable_name);
3514 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3516 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", checklisttable_name, checklisttable_tmpname);
3517 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0)
3519 maepad_warning("Error saving table %s to %s", checklisttable_tmpname, checklisttable_name);
3520 show_banner(mainview, _("Error saving checklist table"));
3522 g_snprintf(tq, sizeof(tq), "DELETE FROM %s", checklisttable_name);
3523 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3525 g_snprintf(tq, sizeof(tq), "INSERT INTO %s SELECT * FROM %s", checklisttable_name, checklisttable_backupname);
3526 if (sqlite3_exec(mainview->db, tq, NULL, NULL, NULL) != 0) {
3527 maepad_warning("Error restoring backup. Data lost :(");
3529 busy_leave(mainview);
3530 return;
3533 g_snprintf(tq, sizeof(tq), "DROP TABLE %s", checklisttable_backupname);
3534 sqlite3_exec(mainview->db, tq, NULL, NULL, NULL);
3536 mainview->file_edited = FALSE;
3537 busy_leave(mainview);
3538 show_banner(mainview, _("Changes saved"));
3541 void callback_checklist_change(GtkTreeSelection *selection, MainView *mainview)
3543 g_assert(mainview != NULL && mainview->data != NULL);
3545 g_signal_handlers_block_by_func(mainview->bold_tb, callback_fontstyle, mainview->bold_tb);
3546 g_signal_handlers_block_by_func(mainview->strikethru_tb, callback_fontstyle, mainview->strikethru_tb);
3547 g_signal_handlers_block_by_func(mainview->check_tb, callback_fontstyle, mainview->check_tb);
3549 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), FALSE);
3550 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->strikethru_tb), FALSE);
3551 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->check_tb), FALSE);
3553 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
3554 GList* l=gtk_tree_selection_get_selected_rows(selection, NULL);
3556 gboolean gotit=FALSE;
3558 GList* cur=l;
3559 while(cur)
3561 GtkTreePath *path=cur->data;
3563 if (!gotit)
3565 GtkTreeIter iter;
3566 if (gtk_tree_model_get_iter(model, &iter, path))
3568 gint styletoset_weight;
3569 gboolean styletoset_strike;
3570 gboolean ischecked;
3572 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHECKNODE_BOLD, &styletoset_weight, CHECKNODE_STRIKE, &styletoset_strike, CHECKNODE_CHECKED, &ischecked, -1);
3573 if (styletoset_weight==PANGO_WEIGHT_BOLD) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), TRUE);
3574 if (styletoset_strike==TRUE) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->strikethru_tb), TRUE);
3575 if (ischecked==TRUE) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview->check_tb), TRUE);
3576 gotit=TRUE;
3579 gtk_tree_path_free(path);
3580 cur=cur->next;
3583 g_list_free(l);
3585 g_signal_handlers_unblock_by_func(mainview->bold_tb, callback_fontstyle, mainview->bold_tb);
3586 g_signal_handlers_unblock_by_func(mainview->strikethru_tb, callback_fontstyle, mainview->strikethru_tb);
3587 g_signal_handlers_unblock_by_func(mainview->check_tb, callback_fontstyle, mainview->check_tb);
3590 void callback_checklist_paste(MainView *mainview)
3592 g_assert(mainview != NULL && mainview->data != NULL);
3593 gchar **entries;
3594 gint length, i;
3596 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
3597 GtkTreeIter toplevel;
3598 gchar *pasted_text = gtk_clipboard_wait_for_text(mainview->clipboard);
3600 entries = g_strsplit(pasted_text, "\n", 0);
3601 length = g_strv_length(entries);
3603 for (i=0; i<length; i++) {
3604 gtk_list_store_append(GTK_LIST_STORE(model), &toplevel);
3605 gtk_list_store_set(GTK_LIST_STORE(model), &toplevel, CHECKNODE_CHECKED, FALSE, CHECKNODE_TEXT, entries[i], -1);
3608 mainview->checklist_edited = TRUE;
3609 g_free(pasted_text);
3610 g_strfreev(entries);
3613 void callback_checklist_add(GtkAction *action, MainView *mainview)
3615 g_assert(mainview != NULL && mainview->data != NULL);
3617 gchar* text = show_line_edit_dialog(mainview, _("Add new checklist item"), _("Name:"), _("Add"), "");
3619 if (text != NULL) {
3620 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
3621 GtkTreeIter toplevel;
3622 gtk_list_store_append(GTK_LIST_STORE(model), &toplevel);
3624 gtk_list_store_set(GTK_LIST_STORE(model),
3625 &toplevel,
3626 CHECKNODE_CHECKED, FALSE,
3627 CHECKNODE_TEXT, text,
3628 -1);
3630 GtkTreePath *path = gtk_tree_model_get_path(model, &toplevel);
3631 if (path) {
3632 gtk_tree_view_set_cursor(GTK_TREE_VIEW(mainview->listview), path, mainview->listtextcol, FALSE);
3633 gtk_tree_path_free(path);
3636 mainview->checklist_edited = TRUE;
3640 void callback_checklist_edit(GtkAction *action, MainView *mainview)
3642 g_assert(mainview != NULL && mainview->data != NULL);
3644 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview));
3646 if (gtk_tree_selection_count_selected_rows(selection) == 0) {
3647 show_banner(mainview, _("Select items first"));
3648 return;
3651 GtkTreeModel* model;
3652 GtkTreeIter iter;
3654 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
3655 gchar* old_text = NULL;
3656 gtk_tree_model_get(model, &iter, CHECKNODE_TEXT, &old_text, -1);
3658 gchar* new_text = show_line_edit_dialog(mainview, _("Edit checklist item"), _("New name:"), _("Save"), old_text);
3660 if (new_text != NULL) {
3661 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHECKNODE_TEXT, new_text, -1);
3662 g_free(new_text);
3665 g_free(old_text);
3668 mainview->checklist_edited = TRUE;
3671 void callback_checklist_delete(GtkAction *action, MainView *mainview)
3673 g_assert(mainview != NULL && mainview->data != NULL);
3675 if (gtk_tree_selection_count_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview)))==0) {
3676 show_banner(mainview, _("Select items first"));
3677 return;
3680 if (show_confirmation(mainview, _("Delete selected checklist item?"))) {
3681 callback_checklist_delete_real(mainview);
3685 void callback_checklist_delete_real(MainView* mainview)
3687 GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview->listview));
3688 GList* l=gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview->listview)), NULL);
3690 GList* rowrefs=NULL;
3691 GList* cur=l;
3692 while(cur)
3694 GtkTreePath *path=cur->data;
3696 GtkTreeIter iter;
3697 if (gtk_tree_model_get_iter(model, &iter, path))
3699 GtkTreeRowReference *rowref = gtk_tree_row_reference_new(model, path);
3700 rowrefs=g_list_append(rowrefs, rowref);
3702 gtk_tree_path_free(path);
3703 cur=cur->next;
3705 g_list_free(l);
3707 g_object_ref(model);
3708 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->listview), NULL);
3710 cur=rowrefs;
3711 while(cur)
3713 GtkTreeRowReference *rowref=cur->data;
3714 GtkTreePath *path= gtk_tree_row_reference_get_path(rowref);
3715 if (path)
3717 GtkTreeIter iter;
3718 if (gtk_tree_model_get_iter(model, &iter, path)) gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
3719 gtk_tree_path_free(path);
3721 gtk_tree_row_reference_free(rowref);
3722 cur=cur->next;
3724 g_list_free(rowrefs);
3726 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview->listview), model);
3727 g_object_unref(model);
3728 mainview->checklist_edited = TRUE;
3731 /* Ask the user for confirmation of a specific action */
3732 gboolean
3733 show_confirmation(MainView* mainview, gchar* question)
3735 GtkDialog* dialog = GTK_DIALOG(hildon_note_new_confirmation(
3736 GTK_WINDOW(mainview->data->main_view), question));
3737 gtk_window_set_transient_for(GTK_WINDOW(dialog), mainview_get_dialog_parent(mainview));
3739 gint response = gtk_dialog_run(dialog);
3740 gtk_widget_destroy(GTK_WIDGET(dialog));
3742 return (response == GTK_RESPONSE_OK);
3745 /* Show a information banner to the user (non-modal) */
3746 void
3747 show_banner(MainView* mainview, const gchar* text)
3749 hildon_banner_show_information(GTK_WIDGET(mainview_get_dialog_parent(mainview)), NULL, text);
3752 /* Let the user enter or edit a line of text */
3753 gchar*
3754 show_line_edit_dialog(MainView* mainview, const gchar* title, const gchar* label_text, const gchar* action, const gchar* text)
3756 GtkWidget* edit_dialog;
3757 GtkWidget* label;
3758 GtkWidget* entry;
3759 GtkWidget* hbox;
3760 gchar* result = NULL;
3762 edit_dialog = GTK_WIDGET(gtk_dialog_new());
3763 gtk_window_set_title(GTK_WINDOW(edit_dialog), title);
3764 gtk_window_set_transient_for(GTK_WINDOW(edit_dialog), mainview_get_dialog_parent(mainview));
3766 label = GTK_WIDGET(gtk_label_new(label_text));
3768 entry = hildon_entry_new(HILDON_SIZE_AUTO);
3769 gtk_entry_set_text(GTK_ENTRY(entry), text);
3770 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
3771 gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
3773 gtk_dialog_add_button(GTK_DIALOG(edit_dialog), action, GTK_RESPONSE_OK);
3774 gtk_dialog_set_default_response(GTK_DIALOG(edit_dialog), GTK_RESPONSE_OK);
3776 hbox = GTK_WIDGET(gtk_hbox_new(FALSE, 10));
3778 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(edit_dialog))), GTK_WIDGET(hbox));
3779 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
3780 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
3782 gtk_widget_show_all(GTK_WIDGET(hbox));
3784 while (TRUE) {
3785 if (gtk_dialog_run(GTK_DIALOG(edit_dialog)) == GTK_RESPONSE_OK) {
3786 result = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
3787 if (strcmp(result, "") != 0) {
3788 break;
3789 } else {
3790 show_banner(mainview, _("Please enter a non-empty text"));
3791 g_free(result);
3792 result = NULL;
3794 } else {
3795 result = NULL;
3796 break;
3800 gtk_widget_destroy(GTK_WIDGET(edit_dialog));
3801 return result;