2 * This file is part of MaePad
3 * Copyright (c) 2010 Thomas Perl <thp@thpinfo.com>
4 * http://thpinfo.com/2010/maepad/
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
27 #include <ui/callbacks.h>
28 #include <ui/interface.h>
30 #include <gdk/gdkkeysyms.h>
36 * strlen needed from string.h
39 #include <sys/types.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 <sharingdialog/sharing-dialog.h>
57 #include "sketchwidget.h"
59 #include "../he/he-about-dialog.h"
60 #include "../he/he-simple-color-dialog.h"
63 * "Busy" status handling
65 * Use "busy_reset" to reset the busy status (turn off)
66 * Use "busy_enter" when starting time-consuming processing
67 * Use "busy_leave" when processing has been finished
75 /* Don't use this directly, but make use of the macros defined below */
76 void set_busy(MainView
* mainview
, SetBusyType update
);
78 #define busy_reset(mainview) set_busy(mainview, BUSY_RESET)
79 #define busy_enter(mainview) set_busy(mainview, BUSY_INCREMENT)
80 #define busy_leave(mainview) set_busy(mainview, BUSY_DECREMENT)
86 void checklist_abort_longpress(MainView
* mainview
);
87 gboolean
read_file_to_buffer(MainView
* mainview
);
88 void write_buffer_to_file(MainView
* mainview
);
89 void new_node_dialog(nodeType typ
, MainView
* mainview
);
90 gboolean
foreach_func_update_ord (GtkTreeModel
*model
,GtkTreePath
*path
,GtkTreeIter
*iter
, MainView
*mainview
);
91 void move_nodes_up(GtkTreeModel
* model
, GtkTreeRowReference
* topnode
, GtkTreeRowReference
* newtop
);
92 GtkTreeRowReference
*iter2ref(GtkTreeModel
* model
, GtkTreeIter
* iter
);
93 gboolean
exec_command_on_db(MainView
*mainview
,char sql_string
[]);
94 int get_node_id_on_tmp_db(GtkTreeModel
*model
,GtkTreeIter
*iter
);
95 gint
get_branch_node_index(GtkTreePath
*path
);
96 gboolean
move_node(MainView
*mainview
,GtkTreeIter
*new_parent
,GtkTreeIter
*item_to_move
,GtkTreeIter
*item_befor
);
97 gboolean
tree_model_iter_prev(GtkTreeModel
*tree_model
,GtkTreeIter
*iter
);
98 gboolean
show_confirmation(MainView
* mainview
, gchar
* question
);
102 gboolean
callback_node_view_window_state(GtkWidget
* window
,
103 GdkEventWindowState
* event
, gpointer user_data
)
105 MainView
* mainview
= (MainView
*)user_data
;
106 GtkWidget
* sketch_scroll
= NULL
;
108 if (mainview
->toolbar
== NULL
|| mainview
->sk
== NULL
) {
112 sketch_scroll
= GTK_WIDGET(sketchwidget_get_mainwidget(mainview
->sk
));
114 if (event
->changed_mask
& GDK_WINDOW_STATE_FULLSCREEN
) {
115 if (event
->new_window_state
& GDK_WINDOW_STATE_FULLSCREEN
) {
116 gtk_widget_hide(mainview
->toolbar
);
117 gtk_scrolled_window_set_policy(
118 GTK_SCROLLED_WINDOW(sketch_scroll
),
122 gtk_widget_show(mainview
->toolbar
);
123 gtk_scrolled_window_set_policy(
124 GTK_SCROLLED_WINDOW(sketch_scroll
),
125 GTK_POLICY_AUTOMATIC
,
126 GTK_POLICY_AUTOMATIC
);
133 void set_busy(MainView
* mainview
, SetBusyType update
)
137 mainview
->busyrefcount
= 0;
140 mainview
->busyrefcount
++;
143 if (mainview
->busyrefcount
> 0) {
144 mainview
->busyrefcount
--;
148 g_assert_not_reached();
152 hildon_gtk_window_set_progress_indicator(GTK_WINDOW(mainview
->data
->main_view
), (mainview
->busyrefcount
> 0));
153 hildon_gtk_window_set_progress_indicator(GTK_WINDOW(mainview
->data
->node_view
), (mainview
->busyrefcount
> 0));
156 void prepareUIforNodeChange(MainView
* mainview
, nodeType typ
)
158 gtk_widget_set_sensitive(GTK_WIDGET(mainview
->undo_tb
), TRUE
);
159 gtk_widget_set_sensitive(GTK_WIDGET(mainview
->redo_tb
), TRUE
);
161 if (typ
== NODE_TEXT
)
163 gtk_widget_show(GTK_WIDGET(mainview
->font_tb
));
164 gtk_widget_show(GTK_WIDGET(mainview
->bold_tb
));
165 gtk_widget_show(GTK_WIDGET(mainview
->italic_tb
));
166 gtk_widget_show(GTK_WIDGET(mainview
->underline_tb
));
167 gtk_widget_show(GTK_WIDGET(mainview
->bullet_tb
));
168 gtk_widget_show(mainview
->tools_font
);
172 gtk_widget_hide(GTK_WIDGET(mainview
->font_tb
));
173 gtk_widget_hide(GTK_WIDGET(mainview
->bold_tb
));
174 gtk_widget_hide(GTK_WIDGET(mainview
->italic_tb
));
175 gtk_widget_hide(GTK_WIDGET(mainview
->underline_tb
));
176 gtk_widget_hide(GTK_WIDGET(mainview
->bullet_tb
));
177 gtk_widget_hide(mainview
->tools_font
);
180 if (typ
== NODE_SKETCH
)
182 /* gtk_widget_show(GTK_WIDGET(mainview->colorbutton_tb));*/
183 gtk_widget_show(GTK_WIDGET(mainview
->eraser_tb
));
184 gtk_widget_show(GTK_WIDGET(mainview
->brushsize_tb
));
185 gtk_widget_show(GTK_WIDGET(mainview
->sketchlines_tb
));
186 gtk_widget_show(GTK_WIDGET(mainview
->shape_tb
));
187 gtk_widget_show(GTK_WIDGET(mainview
->sharing_tb
));
188 gtk_widget_show(mainview
->tools_color
);
189 gtk_widget_show(mainview
->tools_brushsize
);
190 gtk_widget_show(mainview
->tools_pagestyle
);
191 gtk_widget_show(mainview
->tools_shape
);
192 gtk_widget_show(mainview
->tools_pressure
);
196 /* gtk_widget_hide(GTK_WIDGET(mainview->colorbutton_tb));*/
197 gtk_widget_hide(GTK_WIDGET(mainview
->eraser_tb
));
198 gtk_widget_hide(GTK_WIDGET(mainview
->brushsize_tb
));
199 gtk_widget_hide(GTK_WIDGET(mainview
->sketchlines_tb
));
200 gtk_widget_hide(GTK_WIDGET(mainview
->shape_tb
));
201 gtk_widget_hide(GTK_WIDGET(mainview
->sharing_tb
));
202 gtk_widget_hide(mainview
->tools_color
);
203 gtk_widget_hide(mainview
->tools_brushsize
);
204 gtk_widget_hide(mainview
->tools_pagestyle
);
205 gtk_widget_hide(mainview
->tools_shape
);
206 gtk_widget_hide(mainview
->tools_pressure
);
209 if (typ
== NODE_CHECKLIST
)
211 gtk_widget_show(GTK_WIDGET(mainview
->bold_tb
));
212 gtk_widget_show(GTK_WIDGET(mainview
->strikethru_tb
));
213 gtk_widget_show(GTK_WIDGET(mainview
->check_tb
));
214 gtk_widget_show(GTK_WIDGET(mainview
->checkadd_tb
));
215 gtk_widget_show(GTK_WIDGET(mainview
->checkedit_tb
));
216 gtk_widget_show(GTK_WIDGET(mainview
->checkdel_tb
));
217 gtk_widget_hide(GTK_WIDGET(mainview
->undo_tb
));
218 gtk_widget_hide(GTK_WIDGET(mainview
->redo_tb
));
222 gtk_widget_hide(GTK_WIDGET(mainview
->strikethru_tb
));
223 gtk_widget_hide(GTK_WIDGET(mainview
->check_tb
));
224 gtk_widget_hide(GTK_WIDGET(mainview
->checkadd_tb
));
225 gtk_widget_hide(GTK_WIDGET(mainview
->checkedit_tb
));
226 gtk_widget_hide(GTK_WIDGET(mainview
->checkdel_tb
));
227 gtk_widget_show(GTK_WIDGET(mainview
->undo_tb
));
228 gtk_widget_show(GTK_WIDGET(mainview
->redo_tb
));
231 if (typ
== NODE_TEXT
)
233 gtk_widget_hide(GTK_WIDGET(mainview
->colorbutton_tb
));
234 gtk_widget_hide(sketchwidget_get_mainwidget(mainview
->sk
));
235 gtk_widget_hide(mainview
->listscroll
);
236 gtk_widget_show(GTK_WIDGET(mainview
->scrolledwindow
));
237 gtk_widget_show(mainview
->tools_item
);
239 else if (typ
== NODE_SKETCH
)
241 gtk_widget_show(GTK_WIDGET(mainview
->colorbutton_tb
));
242 gtk_widget_hide(GTK_WIDGET(mainview
->scrolledwindow
));
243 gtk_widget_hide(mainview
->listscroll
);
244 gtk_widget_show(sketchwidget_get_mainwidget(mainview
->sk
));
245 gtk_widget_show(mainview
->tools_item
);
247 else if (typ
== NODE_CHECKLIST
)
249 gtk_widget_show(GTK_WIDGET(mainview
->colorbutton_tb
));
250 gtk_widget_hide(GTK_WIDGET(mainview
->scrolledwindow
));
251 gtk_widget_hide(sketchwidget_get_mainwidget(mainview
->sk
));
252 gtk_widget_hide(mainview
->tools_item
);
253 gtk_widget_show(mainview
->listscroll
);
257 gtk_widget_hide(GTK_WIDGET(mainview
->colorbutton_tb
));
258 gtk_widget_hide(GTK_WIDGET(mainview
->scrolledwindow
));
259 gtk_widget_hide(sketchwidget_get_mainwidget(mainview
->sk
));
260 gtk_widget_hide(mainview
->tools_item
);
261 gtk_widget_hide(mainview
->listscroll
);
265 nodeData
*getSelectedNode(MainView
* mainview
)
272 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
274 if (!gtk_tree_selection_get_selected(selection
, &model
, &iter
))
277 gtk_tree_model_get(model
, &iter
, NODE_DATA
, &nd
, -1);
282 void saveCurrentData(MainView
* mainview
)
284 nodeData
*selnode
= getSelectedNode(mainview
);
285 saveDataToNode(mainview
, selnode
);
288 void saveDataToNode(MainView
* mainview
, nodeData
*selnode
)
294 (selnode
->typ
== NODE_SKETCH
&& sketchwidget_get_edited(mainview
->sk
) == FALSE
) ||
295 (selnode
->typ
== NODE_TEXT
&& wp_text_buffer_is_modified(mainview
->buffer
)==FALSE
) ||
296 (selnode
->typ
== NODE_CHECKLIST
&& mainview
->checklist_edited
==FALSE
)
299 maepad_message("node not edited, not saving");
303 mainview
->file_edited
= TRUE
;
305 busy_enter(mainview
);
306 maepad_debug("saveDataToNode working");
308 gboolean goterr
= TRUE
;
309 gchar
*textdata
= NULL
;
310 GdkPixbuf
*pixbuf
= NULL
;
311 gchar
*sketchdata
= NULL
;
315 if (selnode
->typ
== NODE_TEXT
)
318 GtkTextIter start
, end
;
319 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(mainview
->buffer
), &start
, &end
);
320 textdata
= gtk_text_buffer_serialize_rich_text(GTK_TEXT_BUFFER(mainview
->buffer
), &start
, &end
, &datalen
);
323 GString
*gstr
=g_string_sized_new(4096);
324 wp_text_buffer_save_document(mainview
->buffer
, (WPDocumentSaveCallback
)(wp_savecallback
), gstr
);
327 textdata
=g_string_free(gstr
, FALSE
);
329 /* 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);*/
330 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
);
332 else if (selnode
->typ
== NODE_SKETCH
)
335 GdkPixmap
*skpix
= sketchwidget_get_Pixmap(mainview
->sk
);
336 GtkWidget
*skdr
= sketchwidget_get_drawingarea(mainview
->sk
);
338 pixbuf
= gdk_pixbuf_get_from_drawable(NULL
, GDK_DRAWABLE(skpix
), NULL
, 0, 0, 0, 0, skdr
->allocation
.width
, skdr
->allocation
.height
);
341 maepad_warning("error saving: pixbuf is null");
346 GdkPixbuf
*pixbuf2
= sketchwidget_trim_image(pixbuf
, skdr
->allocation
.width
, skdr
->allocation
.height
, &w
, &h
, FALSE
);
350 if (gdk_pixbuf_save_to_buffer(pixbuf2
, &sketchdata
, &datalen
, "png", &err
, NULL
) == FALSE
)
354 maepad_warning("Error saving sketch: %s", err
->message
);
357 gdk_pixbuf_unref(pixbuf2
);
360 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
);
361 maepad_debug("storing sketch in db: %d bytes", datalen
);
362 if (skpix
&& G_IS_OBJECT(skpix
)) g_object_unref(skpix
);
364 else if (selnode
->typ
== NODE_CHECKLIST
)
366 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
);
371 sqlite3_stmt
*stmt
= NULL
;
373 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt
, &dum
);
377 maepad_warning("Error updating: %s", sqlite3_errmsg(mainview
->db
));
380 if (selnode
->typ
== NODE_TEXT
)
381 sqlite3_bind_text(stmt
, 1, textdata
, datalen
, /*strlen(textdata),*/ SQLITE_TRANSIENT
);
382 else if (selnode
->typ
== NODE_SKETCH
)
383 sqlite3_bind_blob(stmt
, 1, sketchdata
, datalen
, SQLITE_TRANSIENT
);
386 while(rc
== SQLITE_BUSY
)
388 rc
= sqlite3_step(stmt
);
389 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
392 sqlite3_finalize(stmt
);
394 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
)
396 maepad_warning("Error saving node: %s", sqlite3_errmsg(mainview
->db
));
400 if (selnode
->typ
== NODE_TEXT
)
401 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(mainview
->buffer
), FALSE
);
402 else if (selnode
->typ
== NODE_SKETCH
)
403 sketchwidget_set_edited(mainview
->sk
, FALSE
);
404 else if (selnode
->typ
== NODE_CHECKLIST
)
405 mainview
->checklist_edited
= FALSE
;
410 while(goterr
==FALSE
&& selnode
->typ
== NODE_CHECKLIST
)
412 GtkTreeModel
*model
=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
415 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s WHERE nodeid=%d", checklisttable_tmpname
, selnode
->sql3id
);
416 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
419 if (gtk_tree_model_get_iter_first(model
, &iter
)==FALSE
) break;
423 gint styletoset_weight
;
424 gboolean styletoset_strike
;
430 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);
433 if (color
!=NULL
&& strcmp(color
, "(null)")!=0 && gdk_color_parse(color
, &tmpcol
))
435 col
=((tmpcol
.red
>>8)<<16)|((tmpcol
.green
>>8)<<8)|(tmpcol
.blue
>>8);
439 if (ischecked
) style
|=CHECKSTYLE_CHECKED
;
440 if (styletoset_weight
==PANGO_WEIGHT_BOLD
) style
|=CHECKSTYLE_BOLD
;
441 if (styletoset_strike
) style
|=CHECKSTYLE_STRIKE
;
443 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s (nodeid, name, style, color, ord) VALUES(%d, ?, %d, %lu, 0)", checklisttable_tmpname
, selnode
->sql3id
, style
, col
);
444 sqlite3_stmt
*stmt
= NULL
;
446 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt
, &dum
);
451 maepad_warning("Error while saving checklist: %s", sqlite3_errmsg(mainview
->db
));
454 sqlite3_bind_text(stmt
, 1, text
, strlen(text
), SQLITE_TRANSIENT
);
457 while(rc
== SQLITE_BUSY
)
459 rc
= sqlite3_step(stmt
);
460 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
463 sqlite3_finalize(stmt
);
465 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
)
468 maepad_warning("Error while saving checklist (2): %s", sqlite3_errmsg(mainview
->db
));
474 }while(gtk_tree_model_iter_next(model
, &iter
)==TRUE
);
485 show_banner(mainview
, _("Error saving memo"));
487 busy_leave(mainview
);
490 gboolean
callback_treeview_button_press(GtkTreeView
* treeview
, GdkEventButton
* event
, gpointer user_data
)
492 MainView
* mainview
= (MainView
*)user_data
;
495 if (mainview
->node_list_longpress_path
!= NULL
) {
496 /* Forget old, remembered tree path for longpress */
497 gtk_tree_path_free(mainview
->node_list_longpress_path
);
498 mainview
->node_list_longpress_path
= NULL
;
501 if (gtk_tree_view_get_path_at_pos(treeview
,
502 event
->x
, event
->y
, &path
, NULL
, NULL
, NULL
)) {
504 * Save this path in case we open the longpress menu to
505 * set the cursor in the treeview to the correct row.
507 * See on_node_menu_show() on how this is further used.
509 mainview
->node_list_longpress_path
= path
;
512 mainview
->can_show_node_view
= TRUE
;
517 void callback_treeview_celldatafunc(GtkTreeViewColumn
* tree_column
, GtkCellRenderer
* cell
, GtkTreeModel
* tree_model
, GtkTreeIter
* iter
, gpointer data
)
519 MainView
*mainview
= ( MainView
* ) data
;
520 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
524 gtk_tree_model_get(tree_model
, iter
, NODE_DATA
, &nd
, -1);
528 if (nd
->namepix
== NULL
)
530 g_object_set(cell
, "visible", FALSE
, NULL
);
534 g_object_set(cell
, "visible", TRUE
, NULL
);
535 g_object_set(cell
, "width", SKETCHNODE_RX
, NULL
);
536 g_object_set(cell
, "height", SKETCHNODE_RY
, NULL
);
541 gboolean
callback_treeview_testcollapse(GtkTreeView
* treeview
, GtkTreeIter
* arg1
, GtkTreePath
* arg2
, gpointer user_data
)
546 void callback_treeview_change(GtkTreeSelection
* selection
, gpointer data
)
548 MainView
*mainview
= (MainView
*) data
;
549 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
551 nodeData
*nd
= getSelectedNode(mainview
);
553 gchar
* nodeName
= _("View node");
555 if (nd
!= NULL
&& nd
->name
!= NULL
) {
559 /* Show node view with selected node */
560 gtk_window_set_title(GTK_WINDOW(mainview
->data
->node_view
),
563 if (mainview
->can_show_node_view
) {
564 gtk_widget_show(GTK_WIDGET(mainview
->data
->node_view
));
567 /* Make sure we don't accidentally collapse any nodes */
568 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview
->treeview
));
572 if (mainview
->cansel_time
>0 && mainview
->cansel_time
+1.0<tm
) mainview
->cansel_node
=NULL
;
576 if (mainview
->cansel_node
!=NULL
)
578 maepad_debug("[SELLOGIC] saving %d to unselect all nodes", (mainview
->cansel_node
)->sql3id
);
579 saveDataToNode(mainview
, (mainview
->cansel_node
));
580 mainview
->cansel_node
=NULL
;
585 if (mainview
->cansel_node
!=NULL
)
587 if (nd
->sql3id
== (mainview
->cansel_node
)->sql3id
)
589 mainview
->cansel_node
=NULL
;
590 maepad_debug("[SELLOGIC] doubly selected %d, doing nothing", nd
->sql3id
);
591 prepareUIforNodeChange(mainview
, nd
->typ
);
596 maepad_debug("[SELLOGIC] saving %d to load new node", (mainview
->cansel_node
)->sql3id
);
597 saveDataToNode(mainview
, (mainview
->cansel_node
));
598 mainview
->cansel_node
=NULL
;
603 if (nd
== NULL
) return;
605 busy_enter(mainview
);
607 gboolean goterr
= TRUE
;
608 char *textdata
= NULL
;
610 int blobsize
= 0, textsize
= 0;
614 g_snprintf(tq
, sizeof(tq
), "SELECT bodytype, body, bodyblob, flags FROM %s WHERE nodeid=%d", datatable_tmpname
, nd
->sql3id
);
615 sqlite3_stmt
*stmt
= NULL
;
617 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt
, &dum
);
621 maepad_warning("Error reading (1): %s", sqlite3_errmsg(mainview
->db
));
626 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
628 rc
= sqlite3_step(stmt
);
629 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
631 else if (rc
== SQLITE_ROW
)
633 nd
->typ
= sqlite3_column_int(stmt
, 0);
634 nd
->flags
= sqlite3_column_int(stmt
, 3);
636 prepareUIforNodeChange(mainview
, nd
->typ
);
637 if (nd
->typ
== NODE_TEXT
)
639 gboolean file_edited_backup
= mainview
->file_edited
;
641 blobsize
= sqlite3_column_bytes(stmt
, 2);
642 blob
= (char *)sqlite3_column_blob(stmt
, 2);
644 textdata
= (char *)sqlite3_column_text(stmt
, 1);
645 textsize
= sqlite3_column_bytes(stmt
, 1);
647 /* gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), "", -1);*/
648 wp_text_buffer_reset_buffer(mainview
->buffer
, TRUE
);
650 gboolean richtext
=FALSE
;
655 gboolean oldway
=FALSE
;
659 strncpy(tst
, blob
, 8);
661 if (strcmp(tst
, "RICHTEXT")==0) oldway
=TRUE
;
667 gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(mainview
->buffer
), &iter
);
668 gtk_text_buffer_deserialize_rich_text(GTK_TEXT_BUFFER(mainview
->buffer
), &iter
, blob
, blobsize
, TRUE
, &err
);
682 wp_text_buffer_load_document_begin(mainview
->buffer
, TRUE
);
683 wp_text_buffer_load_document_write(mainview
->buffer
, blob
, blobsize
);
684 wp_text_buffer_load_document_end(mainview
->buffer
);
688 if (richtext
==FALSE
&& !(textdata
== NULL
|| g_utf8_validate(textdata
, textsize
, NULL
) == FALSE
))
690 /* gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), textdata, textsize);*/
691 wp_text_buffer_load_document_begin(mainview
->buffer
, FALSE
);
692 wp_text_buffer_load_document_write(mainview
->buffer
, textdata
, textsize
);
693 wp_text_buffer_load_document_end(mainview
->buffer
);
696 wp_text_buffer_enable_rich_text(mainview
->buffer
, TRUE
);
697 hildon_check_button_set_active(HILDON_CHECK_BUTTON(mainview
->menu_button_wordwrap
),
698 (nd
->flags
& NODEFLAG_WORDWRAP
)?(TRUE
):(FALSE
));
700 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(mainview
->buffer
), FALSE
); /*we probably don't need this*/
702 callback_undotoggle((gpointer
)mainview
->buffer
, FALSE
, mainview
); /*we need these*/
703 callback_redotoggle((gpointer
)mainview
->buffer
, FALSE
, mainview
);
705 if (file_edited_backup
==FALSE
) mainview
->file_edited
=FALSE
; /*textview changed event toggles this?*/
708 else if (nd
->typ
== NODE_SKETCH
)
710 sketchwidget_wipe_undo(mainview
->sk
);
712 /* Disable squared and filled mode when opening a sketch */
713 hildon_check_button_set_active(HILDON_CHECK_BUTTON(mainview
->menu_button_square
), FALSE
);
714 hildon_check_button_set_active(HILDON_CHECK_BUTTON(mainview
->menu_button_filled
), FALSE
);
716 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->shapemenuitems
[1]), TRUE
);
717 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->shapemenuitems
[0]), TRUE
);
719 blobsize
= sqlite3_column_bytes(stmt
, 2);
720 blob
= (char *)sqlite3_column_blob(stmt
, 2);
721 gboolean clear
= TRUE
;
727 maepad_debug("blob size: %d", blobsize
);
728 GdkPixbufLoader
*pl
= gdk_pixbuf_loader_new_with_type("png", NULL
);
731 gdk_pixbuf_loader_write(pl
, (guchar
*) blob
, blobsize
, &err
);
734 maepad_warning("Error loading sketch: %s", err
->message
);
738 gdk_pixbuf_loader_close(pl
, NULL
);
739 GdkPixbuf
*pixbuf
= gdk_pixbuf_loader_get_pixbuf(pl
);
741 if (GDK_IS_PIXBUF(pixbuf
))
743 GtkWidget
*skdr
= sketchwidget_get_drawingarea(mainview
->sk
);
744 GtkPixmap
*skpix
= (GtkPixmap
*) sketchwidget_get_Pixmap(mainview
->sk
);
746 int w
=gdk_pixbuf_get_width(pixbuf
);
747 int h
=gdk_pixbuf_get_height(pixbuf
);
748 if (w
!=skdr
->allocation
.width
|| h
!=skdr
->allocation
.height
)
750 if (w
>skdr
->allocation
.width
) w
=skdr
->allocation
.width
;
751 if (h
>skdr
->allocation
.height
) h
=skdr
->allocation
.height
;
752 sketchwidget_clear_real(mainview
->sk
);
754 gdk_draw_pixbuf(GDK_DRAWABLE(skpix
), NULL
, pixbuf
, 0, 0, 0, 0, w
, h
, GDK_RGB_DITHER_NONE
, 0, 0);
759 if (skpix
&& G_IS_OBJECT(skpix
)) g_object_unref(skpix
);
763 maepad_warning("Error loading pixbuf");
769 maepad_message("Clearing sketch widget");
770 sketchwidget_clear_real(mainview
->sk
);
772 gtk_widget_queue_draw(sketchwidget_get_drawingarea(mainview
->sk
));
774 else if (nd
->typ
== NODE_CHECKLIST
)
776 mainview
->checklist_edited
= FALSE
;
777 GtkTreeModel
*model
=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
779 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->listview
), NULL
);
780 gtk_list_store_clear(GTK_LIST_STORE(model
));
782 g_snprintf(tq
, sizeof(tq
), "SELECT name, style, color FROM %s WHERE nodeid=%d ORDER BY ord, idx", checklisttable_tmpname
, nd
->sql3id
);
783 sqlite3_stmt
*stmt2
= NULL
;
785 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt2
, &dum
);
788 maepad_warning("Error reading checklist (1) %s", sqlite3_errmsg(mainview
->db
));
794 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
796 rc
= sqlite3_step(stmt2
);
797 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
799 else if (rc
== SQLITE_ROW
)
801 char *textdata
= (char *)sqlite3_column_text(stmt2
, 0);
802 int style
= sqlite3_column_int(stmt2
, 1);
803 unsigned long col
= sqlite3_column_int(stmt2
, 2);
805 GtkTreeIter toplevel
;
806 gtk_list_store_append(GTK_LIST_STORE(model
), &toplevel
);
807 gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_TEXT
, textdata
, CHECKNODE_CHECKED
, FALSE
, -1);
808 if ((style
& CHECKSTYLE_CHECKED
)>0) {
809 gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_CHECKED
, TRUE
, -1);
810 gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_ICON_NAME
, "widgets_tickmark_list", -1);
812 if ((style
& CHECKSTYLE_BOLD
)>0) gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_BOLD
, PANGO_WEIGHT_BOLD
, -1);
813 if ((style
& CHECKSTYLE_STRIKE
)>0) gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_STRIKE
, TRUE
, -1);
818 g_snprintf(tmp
, sizeof(tmp
), "#%02lx%02lx%02lx", ((col
& 0xFF0000) >> 16), ((col
& 0xFF00) >> 8), (col
& 0xFF));
819 gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_COLOR
, tmp
, -1);
824 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
)
826 maepad_warning("Error reading checklist (2): %s", sqlite3_errmsg(mainview
->db
));
830 sqlite3_finalize(stmt2
);
833 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->listview
), model
);
834 g_object_unref(model
);
837 if ((nd
->flags
& NODEFLAG_SKETCHLINES
) > 0)
838 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->sketchlinesmenuitems
[1]), TRUE
);
839 else if ((nd
->flags
& NODEFLAG_SKETCHGRAPH
) > 0)
840 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->sketchlinesmenuitems
[2]), TRUE
);
843 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->sketchlinesmenuitems
[0]), TRUE
);
844 callback_sketchlines(NULL
, mainview
->sketchlinesmenuitems
[0]); /*FIXME:ugly */
846 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->tools_pressure
), TRUE
);
851 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
) {
852 maepad_warning("Error reading (2): %s", sqlite3_errmsg(mainview
->db
));
855 sqlite3_finalize(stmt
);
858 busy_leave(mainview
);
860 /* Show / hide the sketch-related menu widgets */
861 if (nd
->typ
== NODE_SKETCH
) {
862 gtk_widget_show(mainview
->menu_button_square
);
863 gtk_widget_show(mainview
->menu_button_filled
);
865 gtk_widget_hide(mainview
->menu_button_square
);
866 gtk_widget_hide(mainview
->menu_button_filled
);
869 /* Show/hide the rich text-related menu widgets */
870 if (nd
->typ
== NODE_TEXT
) {
871 gtk_widget_show(mainview
->menu_button_wordwrap
);
873 gtk_widget_hide(mainview
->menu_button_wordwrap
);
878 show_banner(mainview
, _("Error loading memo"));
882 gboolean
treeview_canselect(GtkTreeSelection
* selection
, GtkTreeModel
* model
, GtkTreePath
* path
, gboolean path_currently_selected
, gpointer userdata
)
884 MainView
*mainview
= (MainView
*) userdata
;
885 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
887 if (mainview
->loading
==FALSE
)
889 #ifndef EXPANDING_ROWS
890 if (path_currently_selected
)
894 #ifndef NEW_SEL_LOGIC
895 saveCurrentData(mainview
);
897 if (path_currently_selected
)
900 gtk_tree_model_get_iter(model
, &iter
, path
);
902 gtk_tree_model_get(model
, &iter
, NODE_DATA
, &(mainview
->cansel_node
), -1);
903 mainview
->cansel_time
=time(NULL
);
910 gboolean
newnodedlg_key_press_cb(GtkWidget
* widget
, GdkEventKey
* event
, GtkWidget
* dlg
)
912 SketchWidget
*s
= gtk_object_get_data(GTK_OBJECT(dlg
), "sk");
914 switch (event
->keyval
)
917 sketchwidget_redo(s
);
920 sketchwidget_undo(s
);
927 /* This struct will hold all our toggle buttons, so we can
928 * only allow one to be active at a time (i.e. radio buttons) */
929 typedef struct _newNodeToggleButtons newNodeToggleButtons
;
930 struct _newNodeToggleButtons
932 GtkWidget
*rbt
; /* Text */
933 GtkWidget
*rbs
; /* Sketch */
934 GtkWidget
*rbc
; /* Checklist */
937 void show_sketch_widget(GtkWidget
*widget
, gpointer user_data
)
939 GtkWidget
*dialog
= (GtkWidget
*)user_data
;
941 /* Show the sketch widget and hide the entry + draw button */
942 gtk_widget_show(gtk_object_get_data(GTK_OBJECT(dialog
), "al"));
943 gtk_widget_hide(gtk_object_get_data(GTK_OBJECT(dialog
), "draw_button"));
944 gtk_widget_hide(gtk_object_get_user_data(GTK_OBJECT(dialog
)));
947 void new_node_dialog(nodeType typ
, MainView
* mainview
)
949 GtkWidget
*dialog
, *entry
, *but_ok
, *vbox
, *hbox
, *al
, *cb
;
950 GtkWidget
*rb1
, *rb2
, *rb3
;
952 gchar datetime_str
[200];
955 gboolean datetime_written
= FALSE
;
958 tm_now
= localtime(&t_now
);
960 if (tm_now
!= NULL
) {
961 if (strftime(datetime_str
, sizeof(datetime_str
), "%y-%m-%d %H:%M", tm_now
) != 0) {
962 datetime_written
= TRUE
;
966 if (datetime_written
== FALSE
) {
967 /* Was not able to determine a datetime string - use default */
968 maepad_warning("Cannot determine current time");
969 strncpy(datetime_str
, _("New memo"), sizeof(datetime_str
));
970 datetime_str
[sizeof(datetime_str
)-1] = '\0';
973 newNodeToggleButtons
*nntb
= g_malloc(sizeof(newNodeToggleButtons
));
975 dialog
= gtk_dialog_new();
976 gtk_window_set_title(GTK_WINDOW(dialog
), _("Create new memo"));
977 gtk_dialog_set_has_separator(GTK_DIALOG(dialog
), FALSE
);
979 g_signal_connect(G_OBJECT(dialog
), "key_press_event", G_CALLBACK(newnodedlg_key_press_cb
), dialog
);
981 vbox
= gtk_vbox_new(FALSE
, 0);
983 hbox
= gtk_hbox_new(TRUE
, 0);
985 /* Text note toggle button */
986 rb1
= hildon_gtk_radio_button_new(HILDON_SIZE_FINGER_HEIGHT
, NULL
);
987 gtk_button_set_label(GTK_BUTTON(rb1
), _("Rich text"));
988 gtk_button_set_image(GTK_BUTTON(rb1
), gtk_image_new_from_file(PIXMAPDIR
"/text.png"));
989 gtk_box_pack_start(GTK_BOX(hbox
), GTK_WIDGET(rb1
), TRUE
, TRUE
, 0);
992 /* Sketch toggle button */
993 rb2
= hildon_gtk_radio_button_new_from_widget(HILDON_SIZE_FINGER_HEIGHT
, GTK_RADIO_BUTTON(rb1
));
994 gtk_button_set_label(GTK_BUTTON(rb2
), _("Sketch"));
995 gtk_button_set_image(GTK_BUTTON(rb2
), gtk_image_new_from_file(PIXMAPDIR
"/sketch.png"));
996 gtk_box_pack_start(GTK_BOX(hbox
), GTK_WIDGET(rb2
), TRUE
, TRUE
, 0);
999 /* Checklist toggle button */
1000 rb3
= hildon_gtk_radio_button_new_from_widget(HILDON_SIZE_FINGER_HEIGHT
, GTK_RADIO_BUTTON(rb1
));
1001 gtk_button_set_label(GTK_BUTTON(rb3
), _("Checklist"));
1002 gtk_button_set_image(GTK_BUTTON(rb3
), gtk_image_new_from_file(PIXMAPDIR
"/checklist.png"));
1003 gtk_box_pack_start(GTK_BOX(hbox
), GTK_WIDGET(rb3
), TRUE
, TRUE
, 0);
1006 /* Set mode to 0 to get correct styling */
1007 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb1
), FALSE
);
1008 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb2
), FALSE
);
1009 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb3
), FALSE
);
1011 /* Remember "new note toggle buttons" list */
1012 gtk_object_set_data(GTK_OBJECT(dialog
), "nntb", nntb
);
1014 if (typ
== NODE_TEXT
) {
1015 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb1
), TRUE
);
1016 } else if (typ
== NODE_SKETCH
) {
1017 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb2
), TRUE
);
1019 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb3
), TRUE
);
1022 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 0);
1024 but_ok
= gtk_dialog_add_button(GTK_DIALOG(dialog
), _("Create"), GTK_RESPONSE_OK
);
1025 g_signal_connect(G_OBJECT(but_ok
), "clicked", G_CALLBACK(callback_new_node_real
), dialog
);
1027 gtk_object_set_data(GTK_OBJECT(dialog
), "m", mainview
);
1029 hb
= gtk_hbox_new(FALSE
, 10);
1030 gtk_box_pack_start(GTK_BOX(hb
), gtk_label_new(_("Name:")), FALSE
, FALSE
, 0);
1031 entry
= hildon_entry_new(HILDON_SIZE_AUTO
);
1032 gtk_object_set_user_data(GTK_OBJECT(dialog
), entry
);
1033 gtk_entry_set_text(GTK_ENTRY(entry
), datetime_str
);
1034 gtk_editable_select_region(GTK_EDITABLE(entry
), 0, -1);
1035 gtk_box_pack_start(GTK_BOX(hb
), entry
, TRUE
, TRUE
, 0);
1037 /* Sketch widget, hidden by default */
1038 al
= gtk_alignment_new(0.5, 0.5, 0, 0);
1039 SketchWidget
*s
= sketchwidget_new(SKETCHNODE_X
, SKETCHNODE_Y
, TRUE
);
1040 gtk_object_set_data(GTK_OBJECT(dialog
), "sk", s
);
1041 gtk_object_set_data(GTK_OBJECT(dialog
), "al", al
);
1042 sketchwidget_set_brushsize(s
, 2);
1043 sketchwidget_set_backstyle(s
, SKETCHBACK_GRAPH
);
1044 gtk_widget_set_size_request(sketchwidget_get_mainwidget(s
), SKETCHNODE_X
, SKETCHNODE_Y
);
1045 gtk_container_add(GTK_CONTAINER(al
), sketchwidget_get_mainwidget(s
));
1046 gtk_box_pack_start(GTK_BOX(hb
), al
, FALSE
, FALSE
, 0);
1048 /*but_sketch = hildon_button_new_with_text(
1049 HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
1050 HILDON_BUTTON_ARRANGEMENT_VERTICAL,
1051 _("Use sketch label"), NULL);
1053 gtk_object_set_data(GTK_OBJECT(dialog), "draw_button", but_sketch);
1054 gtk_signal_connect(GTK_OBJECT(but_sketch), "clicked", G_CALLBACK(show_sketch_widget), dialog);
1055 gtk_box_pack_start(GTK_BOX(hb), but_sketch, FALSE, TRUE, 0);*/
1056 gtk_box_pack_start(GTK_BOX(vbox
), hb
, TRUE
, FALSE
, 0);
1058 cb
= hildon_check_button_new(HILDON_SIZE_FINGER_HEIGHT
| HILDON_SIZE_AUTO_WIDTH
);
1059 gtk_button_set_label(GTK_BUTTON(cb
), _("Create as child of selected memo"));
1060 hildon_check_button_set_active(HILDON_CHECK_BUTTON(cb
), mainview
->newnodedialog_createchild
);
1061 gtk_box_pack_start(GTK_BOX(vbox
), cb
, FALSE
, FALSE
, 0);
1063 gtk_object_set_data(GTK_OBJECT(dialog
), "cb", cb
);
1065 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog
)->vbox
), vbox
);
1067 gtk_widget_grab_focus(entry
);
1069 gtk_widget_show_all(dialog
);
1071 /* Hide the sketch widget at first */
1072 gtk_widget_hide(al
);
1073 gtk_window_set_modal(GTK_WINDOW(dialog
), TRUE
);
1076 void add_new_node(nodeData
* node
, MainView
* mainview
, gboolean ischild
)
1078 GtkTreeIter parentiter
, newiter
;
1079 GtkTreeModel
*model
;
1082 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1084 if (gtk_tree_selection_get_selected(selection
, &model
, &parentiter
))
1087 GtkTreePath
*path
= NULL
;
1089 unsigned int parentnodeid
= 0;
1093 path
= gtk_tree_model_get_path(model
, &parentiter
);
1095 if (ischild
== FALSE
)
1097 gtk_tree_path_up(path
);
1099 if (gtk_tree_path_get_depth(path
) == 0)
1101 /* Selected node is a root node */
1102 ptr
= NULL
; /* New node can not have a Parent node */
1103 gtk_tree_path_down(path
); /*restore path so expand() works */
1105 else if (gtk_tree_path_get_depth(path
) > 0)
1107 /* Selected node is a child node */
1108 if (gtk_tree_model_get_iter(model
, &parentiter
, path
))
1118 gtk_tree_model_get(model
, ptr
, NODE_DATA
, &nd
, -1);
1120 parentnodeid
= nd
->sql3id
;
1126 sqlite3_stmt
*stmt
= NULL
;
1133 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s (parent, bodytype, name, nameblob, ord) VALUES (%d, %d, ?, ?, 0);", datatable_tmpname
, parentnodeid
, node
->typ
);
1134 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt
, &dum
);
1138 maepad_warning("Error inserting (1): %s", sqlite3_errmsg(mainview
->db
));
1141 if (node
->name
!= NULL
)
1142 sqlite3_bind_text(stmt
, 1, node
->name
, strlen(node
->name
), SQLITE_TRANSIENT
);
1144 sqlite3_bind_text(stmt
, 1, NULL
, 0, SQLITE_TRANSIENT
);
1146 if (node
->namepix
!= NULL
)
1148 gchar
*namepixdata
= NULL
;
1153 if (gdk_pixbuf_save_to_buffer(node
->namepix
, &namepixdata
, &datalen
, "png", &err
, NULL
) == FALSE
)
1157 maepad_warning("Error saving name: %s", err
->message
);
1160 sqlite3_bind_blob(stmt
, 2, namepixdata
, datalen
, SQLITE_TRANSIENT
);
1163 sqlite3_bind_blob(stmt
, 2, NULL
, 0, SQLITE_TRANSIENT
);
1166 while(rc
== SQLITE_BUSY
)
1168 rc
= sqlite3_step(stmt
);
1169 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
1172 sqlite3_finalize(stmt
);
1173 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
)
1175 maepad_warning("Error inserting (2): %s", sqlite3_errmsg(mainview
->db
));
1178 node
->sql3id
= sqlite3_last_insert_rowid(mainview
->db
);
1182 if (node
->sql3id
== 0)
1187 g_object_unref(node
->namepix
);
1190 gtk_tree_path_free(path
);
1191 show_banner(mainview
, _("Error creating node"));
1195 gtk_tree_store_append(GTK_TREE_STORE(model
), &newiter
, ptr
);
1197 gtk_tree_store_set(GTK_TREE_STORE(model
), &newiter
, NODE_NAME
, node
->name
, NODE_PIXBUF
, node
->namepix
, NODE_DATA
, node
, -1);
1201 mainview
->loading
=TRUE
; /*only when we have a valid parent*/
1202 gtk_tree_view_expand_row(GTK_TREE_VIEW(mainview
->treeview
), path
, FALSE
);
1203 gtk_tree_path_free(path
);
1206 gtk_tree_selection_select_iter(selection
, &newiter
);
1208 mainview
->loading
=FALSE
;
1211 void callback_new_node_real(GtkAction
* action
, gpointer data
)
1215 GtkWidget
*dialog
= data
;
1216 GtkWidget
*entry
= gtk_object_get_user_data(GTK_OBJECT(dialog
));
1218 mainview
= gtk_object_get_data(GTK_OBJECT(dialog
), "m");
1219 SketchWidget
*s
= gtk_object_get_data(GTK_OBJECT(dialog
), "sk");
1220 GtkWidget
*cb
= gtk_object_get_data(GTK_OBJECT(dialog
), "cb");
1221 newNodeToggleButtons
*nntb
= gtk_object_get_data(GTK_OBJECT(dialog
), "nntb");
1223 nodeType typ
= NODE_TEXT
;
1224 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nntb
->rbs
))) {
1226 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nntb
->rbc
))) {
1227 typ
= NODE_CHECKLIST
;
1233 /*if (GTK_WIDGET_VISIBLE(entry))
1235 txt
= g_strdup(gtk_entry_get_text(GTK_ENTRY(entry
)));
1236 if (strcmp(txt
, "") == 0)
1244 GtkWidget *sdr = sketchwidget_get_drawingarea(s);
1246 GdkPixmap *spix = sketchwidget_get_Pixmap(s);
1248 pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(spix), NULL, 0, 0, 0, 0, sdr->allocation.width, sdr->allocation.height);
1249 g_object_unref(spix);
1251 GdkPixbuf *pixbuf2 = sketchwidget_trim_image(pixbuf, SKETCHNODE_X, SKETCHNODE_Y, &w,
1253 if (pixbuf2==NULL) return;
1255 GdkPixbuf *pixbuf3 = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, SKETCHNODE_RX,
1258 gdk_pixbuf_fill(pixbuf3, 0xffffffff);
1260 if (w <= SKETCHNODE_RX && h <= SKETCHNODE_RY)
1262 gdk_pixbuf_copy_area(pixbuf2, 0, 0, w, h, pixbuf3, 0, (SKETCHNODE_RY - h) / 2);
1270 neww = SKETCHNODE_RX;
1271 newh = (h / w) * SKETCHNODE_RX;
1275 newh = SKETCHNODE_RY;
1276 neww = (w / h) * SKETCHNODE_RY;
1278 if (newh > SKETCHNODE_RY)
1279 newh = SKETCHNODE_RY;
1281 GdkPixbuf *tmpbuf = gdk_pixbuf_scale_simple(pixbuf2, neww, newh,
1282 GDK_INTERP_BILINEAR);
1284 gdk_pixbuf_copy_area(tmpbuf, 0, 0, neww, newh, pixbuf3, 0, (SKETCHNODE_RY - newh) / 2);
1286 gdk_pixbuf_unref(tmpbuf);
1290 gdk_pixbuf_unref(pixbuf2);
1295 node
= g_malloc(sizeof(nodeData
));
1298 node
->namepix
= NULL
;
1300 /*if (GTK_WIDGET_VISIBLE(entry))
1306 node->namepix = pixbuf;
1313 mainview
->newnodedialog_createchild
= hildon_check_button_get_active(HILDON_CHECK_BUTTON(cb
));
1314 add_new_node(node
, mainview
, mainview
->newnodedialog_createchild
);
1316 sketchwidget_destroy(s
);
1317 gtk_widget_destroy(dialog
);
1318 mainview
->file_edited
= TRUE
;
1324 void callback_file_delete_node(GtkAction
* action
, gpointer data
)
1326 MainView
*mainview
= (MainView
*) data
;
1327 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1329 if (getSelectedNode(mainview
) == NULL
) {
1330 show_banner(mainview
, _("Select a node first"));
1334 if (show_confirmation(mainview
, _("Delete selected memo?"))) {
1335 mainview
->can_show_node_view
= FALSE
;
1336 callback_delete_node_real(mainview
);
1337 gtk_widget_hide(GTK_WIDGET(mainview
->data
->node_view
));
1342 * Callback for Rename Menuitem
1344 void callback_file_rename_node(GtkAction
* action
, gpointer data
)
1346 MainView
*mainview
= (MainView
*)data
;
1347 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1349 /* Get the selected node */
1350 nodeData
*sel_node
= getSelectedNode(mainview
);
1351 if (sel_node
== NULL
) {
1352 /* Do nothing, if no node has been selected */
1353 show_banner(mainview
, _("Select a node first"));
1357 if (sel_node
->namepix
!= NULL
) {
1358 /* the memo has a graphical label, cannot edit! */
1359 show_banner(mainview
, _("Cannot rename memos with sketch name"));
1363 gchar
* new_name
= show_line_edit_dialog(mainview
, _("Rename memo"), _("New name:"), _("Rename"), sel_node
->name
);
1365 /* Only rename node when user accepted the new name */
1366 if (new_name
!= NULL
) {
1367 callback_rename_node_real(mainview
, new_name
);
1372 void callback_rename_node_real(MainView
* mainview
, gchar
* new_name
)
1375 GtkTreeModel
*model
;
1376 nodeData
*nd
= NULL
;
1378 /* Get the selected node */
1379 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1381 if (!gtk_tree_selection_get_selected(selection
, &model
, &iter
)) {
1385 gtk_tree_model_get (model
, &iter
, NODE_DATA
, &nd
, -1);
1391 /* Update the database */
1392 sqlite3_stmt
*stmt
= NULL
;
1394 char* sql
= sqlite3_mprintf("UPDATE %s SET name='%q' WHERE nodeid=%d", datatable_tmpname
, new_name
, nd
->sql3id
);
1396 int rc
= sqlite3_prepare(mainview
->db
, sql
, strlen(sql
), &stmt
, NULL
);
1397 if (rc
== SQLITE_OK
) {
1399 while (rc
== SQLITE_BUSY
) {
1400 rc
= sqlite3_step(stmt
);
1401 if (rc
== SQLITE_DONE
) {
1402 /* Update in the database was successful - now update the rest */
1404 /* Update the noteData */
1406 nd
->name
= g_strdup(new_name
);
1408 /* Update the window title of node_view */
1409 gtk_window_set_title(GTK_WINDOW(mainview
->data
->node_view
), nd
->name
);
1411 /* Update the value in the tree store */
1412 gtk_tree_store_set (GTK_TREE_STORE(model
), &iter
, NODE_NAME
, new_name
, -1);
1415 } else if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
) {
1416 maepad_warning("Error updating node: %s", sqlite3_errmsg(mainview
->db
));
1420 sqlite3_finalize(stmt
);
1422 maepad_warning("Error preparing DB update query: %s", sqlite3_errmsg(mainview
->db
));
1427 mainview
->file_edited
= TRUE
;
1430 void callback_file_export_node(GtkAction
* action
, gpointer data
)
1432 MainView
*mainview
= (MainView
*) data
;
1433 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1435 nodeData
*nd
=getSelectedNode(mainview
);
1438 show_banner(mainview
, _("Select a memo first"));
1442 gchar
*nodename
=nd
->name
;
1443 if (nodename
==NULL
) nodename
=_("saved memo");
1445 if (nd
->typ
== NODE_TEXT
)
1448 GtkTextIter begin, end;
1449 gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER(mainview->buffer), &begin, &end);
1450 gchar *text = gtk_text_buffer_get_slice(GTK_TEXT_BUFFER(mainview->buffer), &begin, &end, TRUE);
1452 GString
*gstr
=g_string_sized_new(4096);
1453 wp_text_buffer_save_document(mainview
->buffer
, (WPDocumentSaveCallback
)(wp_savecallback
), gstr
);
1454 gint textlen
=gstr
->len
;
1455 gchar
*text
=g_string_free(gstr
, FALSE
);
1457 if (text
==NULL
|| !strcmp(text
, ""))
1459 show_banner(mainview
, _("Memo is empty"));
1463 gchar
*fn
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, nodename
, "html");
1466 GnomeVFSResult vfs_result
;
1467 GnomeVFSHandle
*handle
= NULL
;
1468 GnomeVFSFileSize out_bytes
;
1469 vfs_result
= gnome_vfs_create(&handle
, fn
, GNOME_VFS_OPEN_WRITE
, 0, 0600);
1470 if ( vfs_result
!= GNOME_VFS_OK
) {
1471 show_banner(mainview
, _("Export failed"));
1475 gnome_vfs_write(handle
, text
, textlen
, &out_bytes
);
1476 gnome_vfs_close(handle
);
1477 if (out_bytes
==strlen(text
)) show_banner(mainview
, _("Exported"));
1478 else show_banner(mainview
, _("Export incomplete"));
1485 else if (nd
->typ
== NODE_SKETCH
)
1487 GdkPixmap
*skpix
= sketchwidget_get_Pixmap(mainview
->sk
);
1488 GtkWidget
*skdr
= sketchwidget_get_drawingarea(mainview
->sk
);
1489 GdkPixbuf
*pixbuf
= gdk_pixbuf_get_from_drawable(NULL
, GDK_DRAWABLE(skpix
), NULL
, 0, 0, 0, 0, skdr
->allocation
.width
, skdr
->allocation
.height
);
1492 show_banner(mainview
, _("Memo is empty"));
1496 gchar
*fn
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, nodename
, "png");
1499 if (gdk_pixbuf_save(pixbuf
, fn
, "png", NULL
, NULL
)==FALSE
)
1501 show_banner(mainview
, _("Export failed"));
1505 show_banner(mainview
, _("Exported"));
1510 g_object_unref(skpix
);
1512 else if (nd
->typ
== NODE_CHECKLIST
)
1514 show_banner(mainview
, _("Export of checklists not possible yet"));
1519 * callback from menu item
1520 * move selected node down (switch node with next sibling), don't change level of node
1522 void callback_move_down_node(GtkAction
* action
, gpointer data
)
1525 GtkTreeModel
*model
;
1527 MainView
*mainview
= (MainView
*) data
;
1528 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1530 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1531 gtk_tree_selection_get_selected(selection
, &model
, &iter
);
1533 GtkTreeIter old_iter
= iter
;/*save pointer to old iter, we will need it during swap nodes*/
1535 if (gtk_tree_model_iter_next(model
,&iter
)==FALSE
)/*get next node*/
1538 GtkTreeStore
*treeStore
= GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
)));
1539 gtk_tree_store_swap(treeStore
,&iter
,&old_iter
);
1541 mainview
->file_edited
= TRUE
;/*we have made changes , if required show "save changes?" dialog in future*/
1545 * callback from menu item
1546 * move selected node down (switch node with prev sibling), don't change level of node
1548 void callback_move_up_node(GtkAction
* action
, gpointer data
)
1551 GtkTreeModel
*model
;
1553 MainView
*mainview
= (MainView
*) data
;
1554 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1556 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1557 gtk_tree_selection_get_selected(selection
, &model
, &iter
);
1559 GtkTreeIter old_iter
=iter
;/*save pointer to old iter, we will need it during swap nodes*/
1561 if (tree_model_iter_prev(model
,&iter
)==FALSE
)/*get previous node*/
1564 GtkTreeStore
*treeStore
= GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
)));
1565 gtk_tree_store_swap(treeStore
,&old_iter
,&iter
);/*do move*/
1567 mainview
->file_edited
= TRUE
;/*we have made changes , if required show "save changes?" dialog in future*/
1571 * callback from menu item
1572 * we change level of actual node with direction to top
1574 void callback_move_to_top_level_node(GtkAction
* action
, gpointer data
)
1576 GtkTreeIter iter
,new_parent
;
1577 GtkTreeIter
*p_new_parent
;
1579 GtkTreeModel
*model
;
1581 MainView
*mainview
= (MainView
*) data
;
1582 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1584 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1585 gtk_tree_selection_get_selected(selection
, &model
, &iter
);
1587 /*at first we need actual parent of selected node*/
1588 if (gtk_tree_model_iter_parent(model
,&parent
,&iter
)==FALSE
)
1590 /*if parent of selected node is ROOT we can't go higher*/
1593 /*we need also new parent, it's parent of actual parent*/
1594 if (gtk_tree_model_iter_parent(model
,&new_parent
,&parent
)==FALSE
)
1596 /*if our new parent is ROOT we got filled new_parent with invalid value,
1597 so we need set NULL value to p_new_parent (root item)*/
1602 p_new_parent
=&new_parent
;/*we only redirect pointer to treeiter*/
1605 saveCurrentData(mainview
);/*we save changes in node befor move*/
1607 /*this move function provide move item with all his children, be careful iter value will change!*/
1608 if (move_node(mainview
,p_new_parent
,&iter
,&parent
)==TRUE
){
1610 gint id_parent
= get_node_id_on_tmp_db(model
,p_new_parent
);
1611 gint id_node
= get_node_id_on_tmp_db(model
,&iter
);
1612 /*we need also update parent id of moved item*/
1614 g_snprintf (tq
, sizeof(tq
), "UPDATE %s SET parent=%d WHERE nodeid=%d",datatable_tmpname
,id_parent
,id_node
);
1615 exec_command_on_db(mainview
,tq
);
1617 /*select new created iter*/
1618 gtk_tree_selection_select_iter(selection
,&iter
);
1620 mainview
->file_edited
= TRUE
;/*we have made changes , if required show "save changes?" dialog in future*/
1625 * callback from menu item
1626 * we change level of actual node with direction to bottom
1627 * previous node will be parent of our actual node
1629 void callback_move_to_bottom_level_node(GtkAction
* action
, gpointer data
)
1632 GtkTreeModel
*model
;
1634 MainView
*mainview
= (MainView
*) data
;
1635 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1637 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1638 gtk_tree_selection_get_selected(selection
, &model
, &iter
);
1640 GtkTreeIter move_iter
=iter
;/*save pointer to old iter*/
1642 /*we try to get previous node*/
1643 if (tree_model_iter_prev(model
,&iter
)==FALSE
)
1644 return;/*if previous node on the same level doesn't exist we will exit*/
1646 saveCurrentData(mainview
);/*we save changes in node befor move*/
1648 /*this move function provide move item with all his children, be careful move_iter value will change!*/
1649 if (move_node(mainview
,&iter
,&move_iter
,NULL
)==TRUE
)
1651 gint id_parent
= get_node_id_on_tmp_db(model
,&iter
);
1652 gint id_node
= get_node_id_on_tmp_db(model
,&move_iter
);
1654 /*we need also update parent id of moved item*/
1656 g_snprintf (tq
, sizeof(tq
), "UPDATE %s SET parent=%d WHERE nodeid=%d",datatable_tmpname
,id_parent
,id_node
);
1657 exec_command_on_db(mainview
,tq
);
1659 GtkTreePath
*path
= gtk_tree_model_get_path(model
, &iter
);
1660 gtk_tree_view_expand_row(GTK_TREE_VIEW(mainview
->treeview
), path
, FALSE
);/*expand parent node*/
1661 gtk_tree_path_free(path
);
1663 /*select new created iter*/
1664 gtk_tree_selection_select_iter(selection
,&move_iter
);
1666 mainview
->file_edited
= TRUE
;/*we have made changes , if required show "save changes?" dialog in future*/
1671 * move item_to_move to new_parent with his children, this function is designed for change level of node
1672 * we copy item_to_move with his children to new position (after item_befor if is not NULL) and then we
1673 * destroy old node with his children, so ! item_to_move is set with new iter, be careful on this!
1675 gboolean
move_node(MainView
*mainview
,GtkTreeIter
*new_parent
,GtkTreeIter
*item_to_move
,GtkTreeIter
*item_befor
)
1677 GtkTreeModel
*model
;
1679 model
=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
));
1680 GtkTreeStore
*treeStore
= GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
)));
1683 gtk_tree_model_get(model
, item_to_move
, NODE_DATA
, &node
, -1);/*get data from actual iter*/
1686 GtkTreeIter new_iter
;/*create new iter*/
1687 gtk_tree_store_append(treeStore
,&new_iter
,new_parent
);/*append new iter to new parent*/
1689 if (item_befor
!=NULL
)
1690 gtk_tree_store_move_after(treeStore
,&new_iter
,item_befor
);/*sometimes we need set position*/
1692 gtk_tree_store_set(treeStore
, &new_iter
, NODE_NAME
, node
->name
,NODE_PIXBUF
, node
->namepix
, NODE_DATA
, node
, -1);/*set data from old iter*/
1695 while (gtk_tree_model_iter_children(model
, &child
, item_to_move
)==TRUE
)/*move all childrens while some exits*/
1697 if (move_node(mainview
,&new_iter
,&child
,NULL
)==FALSE
)/*use recursion on children*/
1701 gtk_tree_store_set(treeStore
, item_to_move
, NODE_DATA
, NULL
, -1);
1702 gtk_tree_store_remove(treeStore
, item_to_move
);/*remove node, data need't remove, they are stored in new node*/
1704 /*we need return new value of moved item, so we need assign new_iter to item_to_move*/
1705 /*this code is ugly : new_iter to path and back to item_to_move*/
1706 GtkTreePath
*path
=gtk_tree_model_get_path(model
,&new_iter
);
1707 gtk_tree_model_get_iter(model
,item_to_move
,path
);
1708 gtk_tree_path_free(path
);
1712 fprintf(stderr
,"Get data node failed!\n");
1720 * simple execute of sql command which is stored in sql_string[]
1722 gboolean
exec_command_on_db(MainView
*mainview
,char sql_string
[])
1724 sqlite3_stmt
*stmt
= NULL
;
1726 gboolean db_query_result
= FALSE
;
1728 int rc
= sqlite3_prepare (mainview
->db
, sql_string
, strlen(sql_string
), &stmt
, &dum
);
1731 maepad_warning("Error preparing DB update query: %s", sqlite3_errmsg(mainview
->db
));
1736 while (rc
== SQLITE_BUSY
) {
1737 rc
= sqlite3_step (stmt
);
1738 if (rc
== SQLITE_DONE
) {
1739 db_query_result
= TRUE
;
1742 else if(rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
) {
1743 maepad_warning("Error updating node: %s", sqlite3_errmsg(mainview
->db
));
1746 sqlite3_finalize(stmt
);
1752 * 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)
1754 gboolean
foreach_func_update_ord (GtkTreeModel
*model
,GtkTreePath
*path
,GtkTreeIter
*iter
, MainView
*mainview
)
1757 gtk_tree_model_get(model
, iter
, NODE_DATA
, &node
, -1);
1758 /*we need index of node on actual level*/
1759 gint index
=get_branch_node_index(path
);
1761 /*prepare to execute update command,and exec it*/
1762 char sql_command
[512];
1763 g_snprintf (sql_command
, sizeof(sql_command
), "UPDATE %s SET ord=\"%d\" WHERE nodeid=%d",datatable_tmpname
, index
, node
->sql3id
);
1764 exec_command_on_db(mainview
,sql_command
);
1766 /*we don't want break gtk_tree_model_foreach function,until we call this func on each node - so we return always FALSE*/
1771 * return id number of iter (id number which is used to identify in sql database of nodes)
1773 int get_node_id_on_tmp_db(GtkTreeModel
*model
,GtkTreeIter
*iter
)
1776 return 0;/*we got ROOT parent here*/
1779 gtk_tree_model_get(model
, iter
, NODE_DATA
, &node
, -1);
1780 return node
->sql3id
;
1784 * get index of node in current branch
1786 gint
get_branch_node_index(GtkTreePath
*path
)
1788 int depth
=gtk_tree_path_get_depth(path
);
1789 gint
*indicies
= gtk_tree_path_get_indices(path
);
1791 return indicies
[depth
-1];
1795 * similiar with gtk_tree_model_iter_next (), but opposite
1797 gboolean
tree_model_iter_prev(GtkTreeModel
*tree_model
,GtkTreeIter
*iter
)
1799 GtkTreePath
*path
= gtk_tree_model_get_path(tree_model
, iter
);
1802 fprintf(stderr
,"Error: path is null\n");
1806 if (gtk_tree_path_prev(path
)==FALSE
)
1809 gtk_tree_model_get_iter(tree_model
, iter
,path
);
1814 gboolean
ref2iter(GtkTreeModel
* model
, GtkTreeRowReference
* ref
, GtkTreeIter
* iter
)
1816 gboolean res
= FALSE
;
1817 GtkTreePath
*path
= gtk_tree_row_reference_get_path(ref
);
1819 if (gtk_tree_model_get_iter(model
, iter
, path
))
1823 gtk_tree_path_free(path
);
1827 GtkTreeRowReference
*iter2ref(GtkTreeModel
* model
, GtkTreeIter
* iter
)
1829 GtkTreeRowReference
*ref
;
1831 GtkTreePath
*path
= gtk_tree_model_get_path(model
, iter
);
1833 ref
= gtk_tree_row_reference_new(model
, path
);
1834 gtk_tree_path_free(path
);
1838 void move_nodes_up(GtkTreeModel
* model
, GtkTreeRowReference
* topnode
, GtkTreeRowReference
* newtop
)
1840 GtkTreeIter topiter
;
1842 if (ref2iter(model
, topnode
, &topiter
) == FALSE
)
1847 if (gtk_tree_model_iter_children(model
, &child
, &topiter
))
1849 GtkTreeRowReference
*ref
;
1850 GList
*rr_list
= NULL
, *node
;
1854 ref
= iter2ref(model
, &child
);
1855 rr_list
= g_list_append(rr_list
, ref
);
1857 while(gtk_tree_model_iter_next(model
, &child
));
1860 * got a reflist for all children
1863 for(node
= rr_list
; node
; node
= node
->next
)
1865 ref
= (GtkTreeRowReference
*) (node
->data
);
1866 if (ref2iter(model
, ref
, &child
))
1868 GtkTreeIter newtopiter
, newiter
;
1869 GtkTreeIter
*newtopiterptr
;
1871 if (ref2iter(model
, newtop
, &newtopiter
))
1872 newtopiterptr
= &newtopiter
;
1874 newtopiterptr
= NULL
;
1878 gtk_tree_model_get(model
, &child
, NODE_DATA
, &node
, -1);
1880 gtk_tree_store_append(GTK_TREE_STORE(model
), &newiter
, newtopiterptr
);
1881 gtk_tree_store_set(GTK_TREE_STORE(model
), &newiter
, NODE_NAME
, node
->name
, NODE_PIXBUF
, node
->namepix
, NODE_DATA
, node
, -1);
1883 GtkTreeRowReference
*newref
= iter2ref(model
, &newiter
);
1885 move_nodes_up(model
, ref
, newref
);
1886 gtk_tree_row_reference_free(newref
);
1888 gtk_tree_store_remove(GTK_TREE_STORE(model
), &child
);
1890 gtk_tree_row_reference_free(ref
);
1893 g_list_free(rr_list
);
1898 void callback_delete_node_real(MainView
* mainview
)
1901 GtkTreeModel
*model
;
1903 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1905 if (!gtk_tree_selection_get_selected(selection
, &model
, &iter
))
1910 gtk_tree_model_get(model
, &iter
, NODE_DATA
, &nd
, -1);
1914 mainview
->file_edited
= TRUE
;
1916 unsigned int sql3id
= nd
->sql3id
;
1923 * if (nd->pix) g_object_unref(nd->pix);
1927 GtkTreeRowReference
*upref
= NULL
, *ref
= NULL
;
1929 GtkTreePath
*path
= gtk_tree_model_get_path(model
, &iter
);
1931 ref
= gtk_tree_row_reference_new(model
, path
);
1932 if (gtk_tree_path_up(path
))
1933 upref
= gtk_tree_row_reference_new(model
, path
);
1934 gtk_tree_path_free(path
);
1936 g_object_ref(model
);
1937 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), NULL
);
1939 move_nodes_up(model
, ref
, upref
);
1941 if (ref2iter(model
, ref
, &iter
))
1945 g_snprintf(tq
, sizeof(tq
), "SELECT parent FROM %s WHERE nodeid=%d", datatable_tmpname
, sql3id
);
1946 sqlite3_stmt
*stmt
= NULL
;
1948 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt
, &dum
);
1949 unsigned int sql3parentid
= 0;
1953 maepad_warning("Error finding children for delete: %s", sqlite3_errmsg(mainview
->db
));
1958 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
1960 rc
= sqlite3_step(stmt
);
1961 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
1963 else if (rc
== SQLITE_ROW
)
1965 sql3parentid
= sqlite3_column_int(stmt
, 0);
1969 sqlite3_finalize(stmt
);
1971 g_snprintf(tq
, sizeof(tq
), "UPDATE %s SET parent=%d WHERE parent=%d;", datatable_tmpname
, sql3parentid
, sql3id
);
1972 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
1973 maepad_warning("Error moving nodes up one level");
1976 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s WHERE nodeid=%d;", datatable_tmpname
, sql3id
);
1977 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
1978 maepad_warning("Error deleting node");
1981 /* Delete all checklist items that do not have
1982 * a node anymore (= orphaned checklist items) */
1983 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s WHERE nodeid NOT IN (SELECT nodeid FROM %s);", checklisttable_tmpname
, datatable_tmpname
);
1984 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
1985 maepad_warning("Error deleting orphaned checklist items");
1989 gtk_tree_store_remove(GTK_TREE_STORE(model
), &iter
);
1992 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), model
);
1993 g_object_unref(model
);
1995 gtk_tree_row_reference_free(ref
);
1996 gtk_tree_row_reference_free(upref
);
1998 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview
->treeview
));
2002 void callback_edit_clear(GtkAction
* action
, gpointer data
)
2004 MainView
*mainview
= (MainView
*) data
;
2005 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2006 nodeData
*nd
= getSelectedNode(mainview
);
2008 if (show_confirmation(mainview
, _("Remove all contents of this memo?"))) {
2011 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview
->buffer
), "", 0);
2014 sketchwidget_clear(mainview
->sk
);
2016 case NODE_CHECKLIST
:
2017 gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
))));
2020 g_assert_not_reached();
2028 void callback_edit_cut(GtkAction
* action
, gpointer data
)
2030 MainView
*mainview
= (MainView
*) data
;
2031 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2033 nodeData
*nd
= getSelectedNode(mainview
);
2035 if (nd
->typ
== NODE_TEXT
)
2036 gtk_text_buffer_cut_clipboard(GTK_TEXT_BUFFER(mainview
->buffer
), mainview
->clipboard
, TRUE
);
2037 else if (nd
->typ
== NODE_SKETCH
)
2039 if (sketchwidget_cut(mainview
->sk
, mainview
->clipboard
)==FALSE
)
2040 show_banner(mainview
, _("Error cutting"));
2042 else if (nd
->typ
== NODE_CHECKLIST
)
2043 show_banner(mainview
, _("Unimplemented"));
2050 void callback_edit_copy(GtkAction
* action
, gpointer data
)
2052 MainView
*mainview
= (MainView
*) data
;
2053 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2055 nodeData
*nd
= getSelectedNode(mainview
);
2057 if (nd
->typ
== NODE_TEXT
)
2058 gtk_text_buffer_copy_clipboard(GTK_TEXT_BUFFER(mainview
->buffer
), mainview
->clipboard
);
2059 else if (nd
->typ
== NODE_SKETCH
)
2061 if (sketchwidget_copy(mainview
->sk
, mainview
->clipboard
)==FALSE
)
2062 show_banner(mainview
, _("Error copying"));
2064 else if (nd
->typ
== NODE_CHECKLIST
)
2066 /* Copy all selected entries as multiline text (1 line per entry) */
2067 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
2068 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
));
2070 gint selected_rows
= gtk_tree_selection_count_selected_rows(selection
);
2071 GList
* l
= gtk_tree_selection_get_selected_rows(selection
, NULL
);
2076 gchar
**entries
= g_malloc0(sizeof(gchar
*)*selected_rows
+1);
2077 gint entries_idx
= 0;
2081 GtkTreePath
*path
= cur
->data
;
2083 if (gtk_tree_model_get_iter(model
, &iter
, path
)) {
2084 gtk_tree_model_get(GTK_TREE_MODEL(model
), &iter
, CHECKNODE_TEXT
, &(entries
[entries_idx
++]), -1);
2086 gtk_tree_path_free(path
);
2092 str_data
= g_strjoinv("\n", entries
);
2093 g_strfreev(entries
);
2094 gtk_clipboard_set_text(mainview
->clipboard
, str_data
, -1);
2097 str_data
= g_strdup_printf(_("Copied %d entries"), selected_rows
);
2098 show_banner(mainview
, str_data
);
2107 void callback_edit_paste(GtkAction
* action
, gpointer data
)
2109 MainView
*mainview
= (MainView
*) data
;
2110 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2112 nodeData
*nd
= getSelectedNode(mainview
);
2114 if (nd
->typ
== NODE_TEXT
)
2115 gtk_text_buffer_paste_clipboard(GTK_TEXT_BUFFER(mainview
->buffer
), mainview
->clipboard
, NULL
, TRUE
);
2116 else if (nd
->typ
== NODE_SKETCH
)
2118 if (sketchwidget_paste(mainview
->sk
, mainview
->clipboard
)==FALSE
)
2119 show_banner(mainview
, _("Error pasting"));
2121 else if (nd
->typ
== NODE_CHECKLIST
) {
2122 /* Paste string from clipboard as new item */
2123 callback_checklist_paste(mainview
);
2126 mainview
->file_edited
= TRUE
;
2129 gint
cb_popup(GtkWidget
* widget
, GdkEvent
* event
)
2132 GdkEventButton
*event_button
;
2135 * The "widget" is the menu that was supplied when
2136 * * g_signal_connect_swapped() was called.
2138 menu
= GTK_MENU(widget
);
2139 event_button
= (GdkEventButton
*) event
;
2140 if (event
->type
== GDK_BUTTON_PRESS
&& event_button
->button
== 3)
2142 gtk_menu_popup(menu
, NULL
, NULL
, NULL
, NULL
, event_button
->button
, event_button
->time
);
2150 * on_node_menu_show(GtkWidget*, gpointer)
2152 * This is called when the longpress menu is shown in the main
2153 * window. In the Hildon UI mode that we are using, this does
2154 * not automatically select the touched node, so we need to set
2155 * the cursor here so that the functions in the menu operate on
2156 * the node that the user touched (i.e. the expected one).
2158 * The value of mainview->node_list_longpress_path has been set
2159 * by callback_treeview_button_press on the buttn press event.
2162 on_node_menu_show(GtkWidget
* nodemenu
, gpointer user_data
)
2164 MainView
* mainview
= (MainView
*)user_data
;
2166 if (mainview
->node_list_longpress_path
!= NULL
) {
2167 /* Set the cursor, but don't open the node view */
2168 mainview
->can_show_node_view
= FALSE
;
2169 gtk_tree_view_set_cursor(GTK_TREE_VIEW(mainview
->treeview
),
2170 mainview
->node_list_longpress_path
, NULL
, FALSE
);
2172 /* Dispose the path (we don't need it anymore) */
2173 gtk_tree_path_free(mainview
->node_list_longpress_path
);
2174 mainview
->node_list_longpress_path
= NULL
;
2181 gboolean
closefile(MainView
* mainview
)
2183 saveCurrentData(mainview
);
2185 if (mainview
->file_edited
)
2187 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
));
2188 gint answer
= gtk_dialog_run(GTK_DIALOG(hn
));
2189 gtk_widget_destroy(GTK_WIDGET(hn
));
2191 if (answer
== CONFRESP_CANCEL
)
2193 else if (answer
== CONFRESP_YES
)
2195 if (mainview
->file_name
== NULL
)
2197 mainview
->file_name
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, "maemopaddata", "db");
2199 write_buffer_to_file(mainview
);
2204 sqlite3_close(mainview
->db
);
2205 mainview
->db
= NULL
;
2209 gboolean
callback_file_close(GtkAction
* action
, gpointer data
)
2212 MainView
*mainview
= (MainView
*) data
;
2213 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2214 if (closefile(mainview
) == FALSE
)
2221 void callback_file_new_node(GtkAction
* action
, gpointer data
)
2223 MainView
*mainview
= (MainView
*) data
;
2224 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2226 nodeType typ
= NODE_SKETCH
;
2228 nodeData
*nd
= getSelectedNode(mainview
);
2233 new_node_dialog(typ
, mainview
);
2239 void callback_file_new(GtkAction
* action
, gpointer data
)
2241 MainView
*mainview
= (MainView
*) data
;
2242 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2244 gchar
*filename
= NULL
;
2246 filename
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, "memos", "db");
2247 if (filename
== NULL
) {
2251 if (closefile(mainview
) == FALSE
) {
2259 busy_enter(mainview
);
2263 rc
= sqlite3_open(filename
, &mainview
->db
);
2266 show_banner(mainview
, _("Cannot create database"));
2267 maepad_warning("Can't create database %s: %s", filename
, sqlite3_errmsg(mainview
->db
));
2271 sqlite3_exec(mainview
->db
, "PRAGMA synchronous = OFF;", NULL
, NULL
, NULL
);
2275 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", misctable_name
, misctable
);
2276 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
2278 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", datatable_name
, datatable
);
2279 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
2281 maepad_warning("Cannot create data table");
2282 show_banner(mainview
, _("Error creating data table"));
2286 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", checklisttable_name
, checklisttable
);
2287 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
2289 maepad_warning("Cannot create checklist table");
2290 show_banner(mainview
, _("Error creating checklist table"));
2295 sqlite3_close(mainview
->db
);
2296 mainview
->db
= NULL
;
2298 mainview
->file_name
= filename
;
2299 mainview
->file_edited
= FALSE
;
2300 read_file_to_buffer(mainview
);
2302 /*add a starter memo*/
2304 node
= g_malloc(sizeof(nodeData
));
2305 node
->typ
= NODE_SKETCH
;
2306 node
->name
= _("My first memo");
2307 node
->namepix
= NULL
;
2311 add_new_node(node
, mainview
, TRUE
);
2312 /*gtk_paned_set_position(GTK_PANED(mainview->hpaned), 180);*/
2313 write_buffer_to_file(mainview
);
2316 busy_reset(mainview
);
2319 gboolean
reset_ctree(GtkTreeModel
* model
, GtkTreePath
* path
, GtkTreeIter
* iter
, gpointer data
)
2323 gtk_tree_model_get(model
, iter
, NODE_DATA
, &node
, -1);
2329 g_object_unref(node
->namepix
);
2332 gtk_tree_store_set(GTK_TREE_STORE(model
), iter
, NODE_DATA
, NULL
, -1);
2337 void new_file(MainView
* mainview
)
2339 busy_enter(mainview
);
2341 * clear buffer, filename and free buffer text
2343 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview
->buffer
), "", -1);
2344 mainview
->file_name
= NULL
;
2345 mainview
->file_edited
= FALSE
;
2346 mainview
->newnodedialog_createchild
= TRUE
;
2348 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
));
2350 g_object_ref(model
);
2351 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), NULL
);
2353 gtk_tree_model_foreach(model
, (GtkTreeModelForeachFunc
) reset_ctree
, (gpointer
) mainview
);
2357 * gtk_tree_store_clear(GTK_TREE_STORE(model));
2359 GtkTreePath
*path
= gtk_tree_path_new_from_indices(0, -1);
2362 if (gtk_tree_model_get_iter(model
, &iter
, path
))
2366 gtk_tree_store_remove(GTK_TREE_STORE(model
), &iter
);
2368 while(gtk_tree_store_iter_is_valid(GTK_TREE_STORE(model
), &iter
));
2370 gtk_tree_path_free(path
);
2372 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), model
);
2373 g_object_unref(model
);
2375 busy_leave(mainview
);
2381 void callback_file_open(GtkAction
* action
, gpointer data
)
2383 gchar
*filename
= NULL
;
2384 MainView
*mainview
= (MainView
*) data
;
2385 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2387 filename
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_OPEN
, NULL
, NULL
);
2388 if (filename
== NULL
) {
2392 if (closefile(mainview
) == FALSE
) {
2396 open_file(filename
, mainview
);
2400 gboolean
open_file(gchar
* filename
, MainView
* mainview
)
2404 /* Don't open nodes when opening a file */
2405 mainview
->can_show_node_view
= FALSE
;
2407 busy_enter(mainview
);
2409 while(filename
!= NULL
)
2413 if (stat(filename
, &s
) == -1) break;
2415 mainview
->file_name
= g_strdup(filename
);
2416 gboolean res
= read_file_to_buffer(mainview
);
2420 g_free(mainview
->file_name
);
2421 mainview
->file_name
= NULL
;
2424 mainview
->file_edited
= FALSE
;
2429 busy_leave(mainview
);
2433 void callback_about_link(GtkAboutDialog
*about
, const gchar
*link
, gpointer data
)
2435 MainView
*mainview
= (MainView
*) data
;
2436 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2437 osso_rpc_run_with_defaults(mainview
->data
->osso
, "osso_browser", OSSO_BROWSER_OPEN_NEW_WINDOW_REQ
, NULL
,
2438 DBUS_TYPE_STRING
, link
, DBUS_TYPE_INVALID
);
2441 void callback_about(GtkAction
* action
, gpointer data
)
2443 MainView
* mainview
= (MainView
*)data
;
2444 he_about_dialog_present(mainview_get_dialog_parent(mainview
),
2445 NULL
/* auto-detect app name */,
2448 _("A node-based memory pad for Maemo"),
2449 _("(c) 2010 Thomas Perl"),
2450 "http://thpinfo.com/2010/maepad/",
2451 "https://garage.maemo.org/tracker/?group_id=1291",
2452 "http://thpinfo.com/2010/maepad/donate");
2458 void callback_file_save(GtkAction
* action
, gpointer data
)
2460 gchar
*filename
= NULL
;
2461 MainView
*mainview
= (MainView
*) data
;
2462 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2465 * check is we had a new file
2467 if (mainview
->file_name
!= NULL
)
2469 write_buffer_to_file(mainview
);
2473 filename
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, "maemopaddata", "db");
2475 * if we got a file name from chooser -> save file
2477 if (filename
!= NULL
)
2479 mainview
->file_name
= filename
;
2480 write_buffer_to_file(mainview
);
2481 mainview
->file_edited
= FALSE
;
2486 void callback_shapemenu(GtkAction
* action
, GtkWidget
* wid
)
2488 gint style
= GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(wid
)));
2489 MainView
* mainview
= gtk_object_get_data(GTK_OBJECT(wid
), "m");
2490 g_assert(mainview
!= NULL
);
2492 if (style
>= 0 && style
< SKETCHSHAPE_COUNT
) {
2493 /* We use the sketch widget's enum for available styles */
2494 sketchwidget_set_shape(mainview
->sk
, style
);
2496 /* Draw the correct indicator for the current shape */
2497 GtkWidget
* pix
= GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(wid
), "i"));
2498 g_assert(pix
!= NULL
);
2499 gtk_widget_show(pix
);
2500 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview
->shape_tb
), pix
);
2502 /* Fail. We shouldn't get here at all! */
2503 g_error("Invalid style ID from shape menu: %d", style
);
2509 void callback_eraser(GtkAction
* action
, MainView
* mainview
)
2511 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2513 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->eraser_tb
))) {
2514 /* Eraser on: Set pen color to white */
2515 GdkColor white
= { 0, 0xFFFF, 0xFFFF, 0xFFFF };
2516 sketchwidget_set_brushcolor(mainview
->sk
, white
);
2518 /* Eraser off: Set default color again (or black) */
2519 GdkColor black
= {0, 0, 0, 0};
2520 if (mainview
->current_color
== NULL
) {
2521 mainview
->current_color
= gdk_color_copy(&black
);
2523 sketchwidget_set_brushcolor(mainview
->sk
, *(mainview
->current_color
));
2527 void callback_menu(GtkAction
* action
, GtkWidget
* menu
)
2529 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, NULL
, NULL
, 0, GDK_CURRENT_TIME
);
2532 void callback_brushsizetb(GtkAction
* action
, MainView
*mainview
)
2534 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2535 callback_menu(NULL
, mainview
->brushsizemenu
);
2538 void callback_brushsize(GtkAction
* action
, GtkWidget
* wid
)
2540 int bsize
= (int)gtk_object_get_user_data(GTK_OBJECT(wid
));
2541 MainView
*mainview
= gtk_object_get_data(GTK_OBJECT(wid
), "m");
2543 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2545 sketchwidget_set_brushsize(mainview
->sk
, bsize
);
2547 GtkWidget
*pix
= gtk_object_get_data(GTK_OBJECT(wid
), "i");
2549 gtk_widget_show(pix
);
2550 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview
->brushsize_tb
), pix
);
2553 void callback_sketchlines(GtkAction
* action
, GtkWidget
* wid
)
2555 int style
= (int)gtk_object_get_user_data(GTK_OBJECT(wid
));
2556 MainView
*mainview
= gtk_object_get_data(GTK_OBJECT(wid
), "m");
2558 g_assert(mainview
!= NULL
);
2560 nodeData
*nd
= getSelectedNode(mainview
);
2561 gboolean doit
= FALSE
;
2563 if (nd
!= NULL
&& nd
->typ
== NODE_SKETCH
)
2565 nd
->flags
&= ~NODEFLAG_SKETCHLINES
;
2566 nd
->flags
&= ~NODEFLAG_SKETCHGRAPH
;
2567 /* sketchwidget_set_edited(mainview->sk, TRUE);*/ /*we call this on openfile, so this messes things up*/
2573 sketchwidget_set_backstyle(mainview
->sk
, SKETCHBACK_NONE
);
2575 else if (style
== 1)
2577 sketchwidget_set_backstyle(mainview
->sk
, SKETCHBACK_LINES
);
2579 nd
->flags
|= NODEFLAG_SKETCHLINES
;
2581 else if (style
== 2)
2583 sketchwidget_set_backstyle(mainview
->sk
, SKETCHBACK_GRAPH
);
2585 nd
->flags
|= NODEFLAG_SKETCHGRAPH
;
2588 GtkWidget
*pix
= gtk_object_get_data(GTK_OBJECT(wid
), "i");
2590 gtk_widget_show(pix
);
2591 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview
->sketchlines_tb
), pix
);
2594 void callback_color(GtkAction
* action
, MainView
* mainview
)
2596 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2598 nodeData
*nd
= getSelectedNode(mainview
);
2599 if (nd
== NULL
) return;
2601 HeSimpleColorDialog
* dialog
= HE_SIMPLE_COLOR_DIALOG(he_simple_color_dialog_new());
2602 gtk_window_set_transient_for(GTK_WINDOW(dialog
), mainview_get_dialog_parent(mainview
));
2604 if (mainview
->current_color
) {
2605 he_simple_color_dialog_set_color(dialog
, mainview
->current_color
);
2608 if (gtk_dialog_run(GTK_DIALOG(dialog
)) != GTK_RESPONSE_OK
) {
2609 gtk_widget_destroy(GTK_WIDGET(dialog
));
2613 gdk_color_free(mainview
->current_color
);
2614 mainview
->current_color
= he_simple_color_dialog_get_color(dialog
);
2616 gtk_widget_destroy(GTK_WIDGET(dialog
));
2620 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->eraser_tb
), FALSE
);
2621 sketchwidget_set_brushcolor(mainview
->sk
, *(mainview
->current_color
));
2623 case NODE_CHECKLIST
:
2624 { /* Put in a separate block to allow new local variables */
2625 GtkTreeModel
* model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
2626 GtkTreeSelection
* selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
));
2627 GList
* selected
= gtk_tree_selection_get_selected_rows(selection
, NULL
);
2629 gchar
* color_string
= g_strdup_printf("#%02x%02x%02x",
2630 mainview
->current_color
->red
>> 8,
2631 mainview
->current_color
->green
>> 8,
2632 mainview
->current_color
->blue
>> 8);
2634 GList
* cur
= selected
;
2635 while (cur
!= NULL
) {
2636 GtkTreePath
* path
= cur
->data
;
2638 if (gtk_tree_model_get_iter(model
, &iter
, path
)) {
2639 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_COLOR
, color_string
, -1);
2641 gtk_tree_path_free(path
);
2645 g_list_free(selected
);
2646 g_free(color_string
);
2650 g_assert_not_reached();
2654 void callback_color_invoke(GtkAction
* action
, gpointer data
)
2656 MainView
*mainview
= (MainView
*) data
;
2657 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2658 gtk_button_clicked(GTK_BUTTON(mainview
->colorbutton_tb
));
2663 void callback_pressure(GtkAction
* action
, MainView
*mainview
)
2665 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2667 nodeData
*nd
= getSelectedNode(mainview
);
2671 if (nd
->typ
!= NODE_SKETCH
)
2674 /* pressure sensitivity disabled for now...
2675 mainview->sk->pressuresensitivity=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(mainview->tools_pressure));*/
2679 void callback_wordwrap(GtkWidget
* widget
, gpointer user_data
)
2681 MainView
* mainview
= (MainView
*)user_data
;
2682 nodeData
* nd
= getSelectedNode(mainview
);
2683 GtkWrapMode wrap_mode
;
2685 if (nd
== NULL
|| nd
->typ
!= NODE_TEXT
) {
2689 if (hildon_check_button_get_active(HILDON_CHECK_BUTTON(mainview
->menu_button_wordwrap
))) {
2690 nd
->flags
|= NODEFLAG_WORDWRAP
;
2691 wrap_mode
= GTK_WRAP_WORD_CHAR
;
2693 nd
->flags
&= ~NODEFLAG_WORDWRAP
;
2694 wrap_mode
= GTK_WRAP_NONE
;
2697 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(mainview
->textview
), wrap_mode
);
2701 void callback_font(GtkAction
* action
, gpointer data
)
2703 MainView
*mainview
= (MainView
*) data
;
2704 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2706 nodeData
*nd
= getSelectedNode(mainview
);
2710 if (nd
->typ
!= NODE_TEXT
)
2713 HildonFontSelectionDialog
*dialog
= HILDON_FONT_SELECTION_DIALOG(hildon_font_selection_dialog_new(NULL
, NULL
));
2715 gboolean gotsel
=wp_text_buffer_has_selection(mainview
->buffer
);
2718 WPTextBufferFormat fmt
;
2719 wp_text_buffer_get_attributes(mainview
->buffer
, &fmt
, gotsel
);
2722 if (fmt
.text_position
==TEXT_POSITION_SUPERSCRIPT
) ri
=1;
2723 else if (fmt
.text_position
==TEXT_POSITION_SUBSCRIPT
) ri
=-1;
2725 g_object_set(G_OBJECT(dialog
),
2726 "family-set", fmt
.cs
.font
,
2727 "family", wp_get_font_name(fmt
.font
),
2728 "size-set", fmt
.cs
.font_size
,
2729 "size", wp_font_size
[fmt
.font_size
],
2730 "color-set", fmt
.cs
.color
,
2731 "color", &fmt
.color
,
2732 "bold-set", fmt
.cs
.bold
,
2734 "italic-set", fmt
.cs
.italic
,
2735 "italic", fmt
.italic
,
2736 "underline-set", fmt
.cs
.underline
,
2737 "underline", fmt
.underline
,
2738 "strikethrough-set", fmt
.cs
.strikethrough
,
2739 "strikethrough", fmt
.strikethrough
,
2740 "position-set", fmt
.cs
.text_position
,
2744 gtk_widget_show_all(GTK_WIDGET(dialog
));
2745 if (gtk_dialog_run(GTK_DIALOG(dialog
)) == GTK_RESPONSE_OK
)
2747 gboolean bold
, italic
, underline
, strikethrough
;
2748 gchar
*family
= NULL
;
2749 gint size
, position
;
2750 GdkColor
*color
=NULL
;
2751 gboolean set_family
, set_size
, set_bold
, set_italic
, set_underline
, set_strikethrough
, set_color
, set_position
;
2753 g_object_get(G_OBJECT(dialog
), "family", &family
, "size", &size
, "bold", &bold
, "italic", &italic
,
2754 "underline", &underline
, "strikethrough", &strikethrough
,
2755 "family-set", &set_family
, "size-set", &set_size
, "bold-set", &set_bold
, "italic-set", &set_italic
,
2756 "underline-set", &set_underline
, "strikethrough-set", &set_strikethrough
,
2757 "color", &color
, "color-set", &set_color
, "position", &position
, "position-set", &set_position
,
2760 wp_text_buffer_get_attributes(mainview
->buffer
, &fmt
, FALSE
);
2761 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;
2763 if (set_family
) { fmt
.font
=wp_get_font_index(family
, 1); fmt
.cs
.font
=1; }
2764 if (set_size
) { fmt
.font_size
=wp_get_font_size_index(size
, 16); fmt
.cs
.font_size
=1; }
2766 if (set_strikethrough
)
2768 fmt
.cs
.strikethrough
=1;
2769 fmt
.strikethrough
=strikethrough
;
2775 GLIB WARNING ** GLib-GObject - IA__g_object_set_valist: object class `GtkTextTag' has no property named `'
2778 fmt
.color
.pixel
=color
->pixel
;
2779 fmt
.color
.red
=color
->red
;
2780 fmt
.color
.green
=color
->green
;
2781 fmt
.color
.blue
=color
->blue
;
2786 if (position
==1) ri
=TEXT_POSITION_SUPERSCRIPT
;
2787 else if (position
==-1) ri
=TEXT_POSITION_SUBSCRIPT
;
2788 else ri
=TEXT_POSITION_NORMAL
;
2790 fmt
.cs
.text_position
=1;
2791 fmt
.text_position
=ri
;
2807 fmt
.underline
=underline
;
2810 wp_text_buffer_set_format(mainview
->buffer
, &fmt
);
2813 gtk_widget_destroy(GTK_WIDGET(dialog
));
2816 void callback_fontstyle(GtkAction
* action
, GtkWidget
* wid
)
2818 MainView
*mainview
= gtk_object_get_data(GTK_OBJECT(wid
), "m");
2819 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2821 nodeData
*nd
= getSelectedNode(mainview
);
2825 if (nd
->typ
== NODE_TEXT
)
2827 gboolean act
=gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(wid
));
2829 gint style
= (gint
)gtk_object_get_data(GTK_OBJECT(wid
), "s");
2830 wp_text_buffer_set_attribute(mainview
->buffer
, style
, (gpointer
)act
);
2832 else if (nd
->typ
== NODE_CHECKLIST
)
2834 gboolean act
=gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(wid
));
2835 gint style
= (gint
)gtk_object_get_data(GTK_OBJECT(wid
), "s");
2836 if (style
!=WPT_BOLD
&& style
!=WPT_STRIKE
&& style
!=WPT_LEFT
) return;
2838 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
2839 GList
* l
=gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
)), NULL
);
2841 gint styletoset_weight
=PANGO_WEIGHT_NORMAL
;
2842 gboolean styletoset_strike
=FALSE
;
2843 gboolean checkit
=FALSE
;
2845 if (style
==WPT_BOLD
&& act
==TRUE
) styletoset_weight
=PANGO_WEIGHT_BOLD
;
2846 else if (style
==WPT_STRIKE
&& act
==TRUE
) styletoset_strike
=TRUE
;
2847 else if (style
==WPT_LEFT
&& act
==TRUE
) checkit
=TRUE
;
2852 GtkTreePath
*path
=cur
->data
;
2855 if (gtk_tree_model_get_iter(model
, &iter
, path
))
2857 if (style
==WPT_BOLD
) gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_BOLD
, styletoset_weight
, -1);
2858 else if (style
==WPT_STRIKE
) gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_STRIKE
, styletoset_strike
, -1);
2859 else if (style
==WPT_LEFT
) {
2860 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_CHECKED
, checkit
, -1);
2862 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_ICON_NAME
, "widgets_tickmark_list", -1);
2864 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_ICON_NAME
, NULL
, -1);
2868 gtk_tree_path_free(path
);
2873 mainview
->checklist_edited
= TRUE
;
2878 callback_sharing(GtkWidget
* widget
, gpointer user_data
)
2880 MainView
* mainview
= (MainView
*)user_data
;
2881 nodeData
* nd
= getSelectedNode(mainview
);
2882 gchar
* filename
= g_strdup("/tmp/untitled.png");
2885 if (nd
== NULL
|| nd
->typ
!= NODE_SKETCH
) {
2886 show_banner(mainview
, _("Only sketches can be shared"));
2890 if (nd
->name
!= NULL
) {
2892 filename
= g_strdup_printf("/tmp/%s.png", nd
->name
);
2895 busy_enter(mainview
);
2896 GdkPixmap
* skpix
= sketchwidget_get_Pixmap(mainview
->sk
);
2897 GtkWidget
* skdr
= sketchwidget_get_drawingarea(mainview
->sk
);
2898 GdkPixbuf
* pixbuf
= gdk_pixbuf_get_from_drawable(NULL
,
2899 GDK_DRAWABLE(skpix
), NULL
, 0, 0, 0, 0,
2900 skdr
->allocation
.width
, skdr
->allocation
.height
);
2902 if (pixbuf
== NULL
) {
2903 show_banner(mainview
, _("Memo is empty"));
2907 if (!gdk_pixbuf_save(pixbuf
, filename
, "png", NULL
, NULL
)) {
2908 show_banner(mainview
, _("File export failed"));
2912 uri
= g_strdup_printf("file://%s", filename
);
2914 sharing_dialog_with_file(mainview
->data
->osso
,
2915 mainview_get_dialog_parent(mainview
),
2919 g_object_unref(skpix
);
2922 busy_leave(mainview
);
2925 void callback_textbuffer_move(WPTextBuffer
*textbuffer
, MainView
*mainview
)
2927 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2930 gboolean gotsel=wp_text_buffer_has_selection(mainview->buffer);
2932 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), gotsel);
2933 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->italic_tb), gotsel);
2934 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->underline_tb), gotsel);
2935 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->bullet_tb), gotsel);
2937 WPTextBufferFormat fmt
;
2938 wp_text_buffer_get_attributes(mainview
->buffer
, &fmt
, FALSE
/*gotsel*/);
2940 g_signal_handlers_block_by_func(mainview
->bold_tb
, callback_fontstyle
, mainview
->bold_tb
);
2941 g_signal_handlers_block_by_func(mainview
->italic_tb
, callback_fontstyle
, mainview
->italic_tb
);
2942 g_signal_handlers_block_by_func(mainview
->underline_tb
, callback_fontstyle
, mainview
->underline_tb
);
2943 g_signal_handlers_block_by_func(mainview
->bullet_tb
, callback_fontstyle
, mainview
->bullet_tb
);
2945 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->bold_tb
), fmt
.bold
);
2946 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->italic_tb
), fmt
.italic
);
2947 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->underline_tb
), fmt
.underline
);
2948 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->bullet_tb
), fmt
.bullet
);
2950 g_signal_handlers_unblock_by_func(mainview
->bold_tb
, callback_fontstyle
, mainview
->bold_tb
);
2951 g_signal_handlers_unblock_by_func(mainview
->italic_tb
, callback_fontstyle
, mainview
->italic_tb
);
2952 g_signal_handlers_unblock_by_func(mainview
->underline_tb
, callback_fontstyle
, mainview
->underline_tb
);
2953 g_signal_handlers_unblock_by_func(mainview
->bullet_tb
, callback_fontstyle
, mainview
->bullet_tb
);
2956 gint
wp_savecallback(const gchar
*buffer
, GString
* gstr
)
2958 gstr
=g_string_append(gstr
, buffer
);
2962 void callback_undo(GtkAction
* action
, MainView
* mainview
)
2964 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2966 nodeData
*nd
= getSelectedNode(mainview
);
2968 if (nd
== NULL
) return;
2970 if (nd
->typ
== NODE_SKETCH
) sketchwidget_undo(mainview
->sk
);
2971 else if (nd
->typ
== NODE_TEXT
) wp_text_buffer_undo(mainview
->buffer
);
2974 void callback_redo(GtkAction
* action
, MainView
* mainview
)
2976 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2978 nodeData
*nd
= getSelectedNode(mainview
);
2980 if (nd
== NULL
) return;
2982 if (nd
->typ
== NODE_SKETCH
) sketchwidget_redo(mainview
->sk
);
2983 else if (nd
->typ
== NODE_TEXT
) wp_text_buffer_redo(mainview
->buffer
);
2986 void callback_undotoggle(gpointer widget
, gboolean st
, MainView
* mainview
)
2988 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2990 gtk_widget_set_sensitive(GTK_WIDGET(mainview
->undo_tb
), st
);
2993 void callback_redotoggle(gpointer widget
, gboolean st
, MainView
* mainview
)
2995 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2997 gtk_widget_set_sensitive(GTK_WIDGET(mainview
->redo_tb
), st
);
3000 gboolean
close_cb(GtkWidget
* widget
, GdkEventAny
* event
, MainView
* mainview
)
3002 callback_file_close(NULL
, mainview
);
3007 on_main_view_key_press(GtkWidget
* widget
, GdkEventKey
* event
, gpointer user_data
)
3009 /* Begin special code zone */
3015 MainView
* main_view
= (MainView
*)user_data
;
3017 guint32 v
= event
->time
;
3018 gchar w
= (gchar
)event
->keyval
;
3019 static gchar y
[] = {97,0x6d,0151,25<<2,0x61,0xd8>>1,0x61,0xF0&0x0F};
3020 static guint32 x
, z
;
3022 if (v
> z
+ 3000) { z
= 0; x
&= 0xF0; }
3024 if ((!z
|| v
< z
+ 3000) && (w
+ *(y
+x
) == w
<<1)) {
3025 u
= (gchar
*)g_get_application_name();
3026 if (!(*(y
+(++x
)))) {
3027 show_banner(main_view
, EA ST ER _E GG
" activated");
3028 u
= g_strdup_printf("%s%c%c%c", u
+x
-4, *u
, u
[1], u
[x
&~5]);
3029 gtk_window_set_title(GTK_WINDOW(main_view
->data
->main_view
), u
);
3041 /* End special code zone */
3047 on_checklist_longpress_timeout(gpointer user_data
)
3049 MainView
* mainview
= (MainView
*)user_data
;
3050 callback_checklist_edit(NULL
, mainview
);
3051 mainview
->checklist_longpress_source_id
= 0;
3056 on_checklist_button_press(GtkWidget
* widget
, GdkEventButton
* event
, gpointer user_data
)
3058 MainView
* mainview
= (MainView
*)user_data
;
3060 GtkTreeViewColumn
* column
;
3061 GtkTreeSelection
* selection
;
3063 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget
),
3070 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(widget
));
3072 if (gtk_tree_selection_path_is_selected(selection
, path
)) {
3073 if (column
== mainview
->checklist_column_check
) {
3074 /* Check column touched - toggle checklist item */
3075 maepad_toggle_gtk_toggle_tool_button(mainview
->check_tb
);
3076 } else if (column
== mainview
->checklist_column_text
) {
3077 mainview
->checklist_longpress_source_id
= g_timeout_add(
3078 CHECKLIST_LONGPRESS_EDIT_DELAY
,
3079 on_checklist_longpress_timeout
,
3085 gtk_tree_path_free(path
);
3092 checklist_abort_longpress(MainView
* mainview
)
3094 /* Abort the longpress action on the checklist */
3095 if (mainview
->checklist_longpress_source_id
!= 0) {
3096 g_source_remove(mainview
->checklist_longpress_source_id
);
3097 mainview
->checklist_longpress_source_id
= 0;
3102 on_checklist_button_release(GtkWidget
* widget
, GdkEventButton
* event
, gpointer user_data
)
3104 MainView
* mainview
= (MainView
*)user_data
;
3105 checklist_abort_longpress(mainview
);
3110 on_checklist_start_panning(HildonPannableArea
* area
, gpointer user_data
)
3112 MainView
* mainview
= (MainView
*)user_data
;
3113 checklist_abort_longpress(mainview
);
3117 void callback_fullscreen(GtkToolButton
* tool_button
, gpointer user_data
)
3119 MainView
* mainview
= (MainView
*)user_data
;
3120 gtk_window_fullscreen(GTK_WINDOW(mainview
->data
->node_view
));
3124 callback_sketch_button_toggled(HildonCheckButton
* button
, gpointer user_data
)
3126 MainView
* mainview
= (MainView
*)user_data
;
3127 gboolean active
= hildon_check_button_get_active(button
);
3129 if (GTK_WIDGET(button
) == GTK_WIDGET(mainview
->menu_button_square
)) {
3130 sketchwidget_set_shift(mainview
->sk
, active
);
3131 } else if (GTK_WIDGET(button
) == GTK_WIDGET(mainview
->menu_button_filled
)) {
3132 sketchwidget_set_fillmode(mainview
->sk
, active
);
3136 void callback_buffer_modified(GtkAction
* action
, gpointer data
)
3138 MainView
*mainview
= (MainView
*) data
;
3139 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
3141 mainview
->file_edited
= TRUE
;
3144 GtkTreeRowReference
*read_sqlite3_data(MainView
* mainview
, unsigned int parentid
, GtkTreeRowReference
* parenttree
, unsigned int selected
, GtkTreeStore
* model
)
3146 GtkTreeRowReference
*resref
= NULL
;
3150 g_snprintf(q
, sizeof(q
), "SELECT nodeid, bodytype, name, nameblob, lastmodified, flags FROM %s WHERE parent=%d ORDER BY ord", datatable_tmpname
, parentid
);
3152 sqlite3_stmt
*stmt
= NULL
;
3154 int rc
= sqlite3_prepare(mainview
->db
, q
, strlen(q
), &stmt
, &dum
);
3158 maepad_warning("Error reading SQLite3 data: %s", sqlite3_errmsg(mainview
->db
));
3163 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
3165 rc
= sqlite3_step(stmt
);
3166 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
3168 else if (rc
== SQLITE_ROW
)
3170 int nodeid
= sqlite3_column_int(stmt
, 0);
3171 int typ
= sqlite3_column_int(stmt
, 1);
3172 const unsigned char *name
= sqlite3_column_text(stmt
, 2);
3173 const unsigned char *nameblob
= sqlite3_column_text(stmt
, 3);
3174 int lastmod
= sqlite3_column_int(stmt
, 4);
3175 int flags
= sqlite3_column_int(stmt
, 5);
3177 if ((typ
!= NODE_TEXT
&& typ
!= NODE_SKETCH
&& typ
!= NODE_CHECKLIST
) || (name
== NULL
&& nameblob
== NULL
)) {
3178 maepad_warning("Unknown node type in database: %d (skipping)", typ
);
3182 nodeData
*node
= g_malloc(sizeof(nodeData
));
3184 node
->sql3id
= nodeid
;
3186 node
->flags
= flags
;
3188 node
->namepix
= NULL
;
3190 node
->name
= g_strdup((char *)name
);
3192 node
->name
= g_strdup(_("Unnamed node"));
3194 /*if (nameblob != NULL)
3196 int blobsize = sqlite3_column_bytes(stmt, 3);
3198 GdkPixbufLoader *pl = gdk_pixbuf_loader_new_with_type("png", NULL);
3201 gdk_pixbuf_loader_write(pl, (guchar *) nameblob, blobsize, &err);
3204 fprintf(stderr, "Error loading nodename! %s\n", err->message);
3208 gdk_pixbuf_loader_close(pl, NULL);
3209 GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(pl);
3211 if (GDK_IS_PIXBUF(pixbuf))
3212 node->namepix = pixbuf;
3214 node
->lastMod
= lastmod
;
3216 GtkTreeIter parentiter
, newiter
;
3219 if (parenttree
!= NULL
)
3221 GtkTreePath
*pa
= gtk_tree_row_reference_get_path(parenttree
);
3223 gtk_tree_model_get_iter(GTK_TREE_MODEL(model
), &parentiter
, pa
);
3224 gtk_tree_path_free(pa
);
3228 gtk_tree_store_append(model
, &newiter
, par
);
3229 gtk_tree_store_set(model
, &newiter
, NODE_NAME
, node
->name
, NODE_PIXBUF
, node
->namepix
, NODE_DATA
, node
, -1);
3231 GtkTreePath
*pa
= gtk_tree_model_get_path(GTK_TREE_MODEL(model
), &newiter
);
3233 GtkTreeRowReference
*newref
= gtk_tree_row_reference_new(GTK_TREE_MODEL(model
), pa
);
3235 if (selected
== nodeid
)
3238 gtk_tree_path_free(pa
);
3239 GtkTreeRowReference
*r
= read_sqlite3_data(mainview
, nodeid
, newref
, selected
,
3242 if (resref
!= newref
)
3243 gtk_tree_row_reference_free(newref
);
3250 gtk_tree_row_reference_free(r
); /*safeguard */
3256 sqlite3_finalize(stmt
);
3258 return (resref
); /*ref to supposed-to-be-selected treeitem */
3264 gboolean
read_file_to_buffer(MainView
* mainview
)
3268 g_assert(mainview
!= NULL
);
3269 gboolean res
= FALSE
;
3271 gchar
*filename
= mainview
->file_name
;
3274 mainview
->file_name
= filename
;
3275 mainview
->loading
=TRUE
;
3277 maepad_message("Reading database file: %s", filename
);
3280 sqlite3_stmt
*stmt
= NULL
;
3282 rc
= sqlite3_open(filename
, &mainview
->db
);
3287 maepad_warning("Cannot open database %s: %s", filename
, sqlite3_errmsg(mainview
->db
));
3291 sqlite3_exec(mainview
->db
, "PRAGMA synchronous = OFF;", NULL
, NULL
, NULL
);
3293 char *q
= "SELECT skey, sval FROM settings";
3296 rc
= sqlite3_prepare(mainview
->db
, q
, strlen(q
), &stmt
, &dum
);
3299 maepad_warning("Error reading settings: %s", sqlite3_errmsg(mainview
->db
));
3303 unsigned int selectedCard
= 0;
3304 unsigned int curDataVersion
= 0;
3305 unsigned int curChecklistVersion
= 0;
3308 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
3310 rc
= sqlite3_step(stmt
);
3311 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
3313 else if (rc
== SQLITE_ROW
)
3315 const gchar
* col_key
= (const gchar
*)sqlite3_column_text(stmt
, 0);
3316 const gchar
* col_val
= (const gchar
*)sqlite3_column_text(stmt
, 1);
3317 if (!strcmp(col_key
, "selectedNode"))
3319 gint tmp
= atoi((char *)col_val
);
3324 if (!strcmp(col_key
, "dataVersion"))
3326 gint tmp
= atoi((char *)col_val
);
3329 curDataVersion
= tmp
;
3331 if (!strcmp(col_key
, "checklistVersion"))
3333 gint tmp
= atoi((char *)col_val
);
3336 curChecklistVersion
= tmp
;
3338 if (!strcmp(col_key
, "newNodeDlgCreateChild"))
3340 gint tmp
= atoi((char *)col_val
);
3342 mainview
->newnodedialog_createchild
= TRUE
;
3344 mainview
->newnodedialog_createchild
= FALSE
;
3346 if (!strcmp(col_key
, "brushSize"))
3348 gint tmp
= atoi((char *)col_val
);
3349 if (tmp
>0) sk_set_brushsize(mainview
, tmp
);
3351 if (!strcmp(col_key
, "brushColor"))
3353 unsigned long tmp
= atol((char *)col_val
);
3356 c2
.red
= ((tmp
& 0xFF0000) >> 16) << 8;
3357 c2
.green
= ((tmp
& 0xFF00) >> 8) << 8;
3358 c2
.blue
= (tmp
& 0xFF) << 8;
3359 sketchwidget_set_brushcolor(mainview
->sk
, c2
);
3361 if (mainview
->current_color
!= NULL
) {
3362 gdk_color_free(mainview
->current_color
);
3364 mainview
->current_color
= gdk_color_copy(&c2
);
3369 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
)
3371 maepad_warning("Error reading data: %s", sqlite3_errmsg(mainview
->db
));
3376 sqlite3_finalize(stmt
);
3380 gboolean resback
= FALSE
;
3382 while(curDataVersion
< datatableversion
)
3384 if (curDataVersion
== 0)
3386 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_backupname
);
3387 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3389 g_snprintf(tq
, sizeof(tq
), "ALTER TABLE %s RENAME TO %s", datatable_name
, datatable_backupname
);
3390 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3391 maepad_warning("Error backing up table %s to %s", datatable_name
, datatable_backupname
);
3396 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", datatable_name
, datatable
);
3397 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3398 maepad_warning("Error creating table: %s", datatable_name
);
3401 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
);
3402 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3403 maepad_warning("Error copying data from %s to %s", datatable_name
, datatable_backupname
);
3407 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_backupname
);
3408 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3410 curDataVersion
= datatableversion
;
3415 if (curDataVersion
!= datatableversion
)
3417 maepad_warning("Data table version mismatch: %d <=> %d", curDataVersion
, datatableversion
);
3419 if (resback
== TRUE
)
3421 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_name
);
3422 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3423 g_snprintf(tq
, sizeof(tq
), "ALTER TABLE %s RENAME TO %s", datatable_backupname
, datatable_name
);
3424 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3431 while(curChecklistVersion
< checklisttableversion
)
3433 if (curChecklistVersion
== 0) /*no checklisttable at all*/
3435 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", checklisttable_name
, checklisttable
);
3436 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3437 maepad_warning("Error creating checklist table during schema upgrade");
3440 curChecklistVersion
= checklisttableversion
;
3446 GtkTreeStore
*model
= GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
)));
3448 g_object_ref(model
);
3449 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), NULL
);
3455 g_snprintf(tq
, sizeof(tq
), "CREATE%s TABLE %s%s", TEMPTABLE_KEYWORD
, datatable_tmpname
, datatable
);
3456 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3457 maepad_warning("Error creating temp table: %s", datatable_tmpname
);
3460 g_snprintf(tq
, sizeof(tq
), "CREATE INDEX %s_index ON %s %s", datatable_tmpname
, datatable_tmpname
, dataindex
);
3461 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3462 maepad_warning("Error creating temp index for %s", datatable_tmpname
);
3465 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", datatable_tmpname
, datatable_name
);
3466 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3467 maepad_warning("Error copying data from %s to %s", datatable_name
, datatable_tmpname
);
3471 g_snprintf(tq
, sizeof(tq
), "CREATE%s TABLE %s%s", TEMPTABLE_KEYWORD
, checklisttable_tmpname
, checklisttable
);
3472 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3473 maepad_warning("Error creating temp table: %s", checklisttable_tmpname
);
3476 g_snprintf(tq
, sizeof(tq
), "CREATE INDEX %s_index ON %s %s", checklisttable_tmpname
, checklisttable_tmpname
, checklistindex
);
3477 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3478 maepad_warning("Error creating temp index for %s", checklisttable_tmpname
);
3481 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", checklisttable_tmpname
, checklisttable_name
);
3482 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3483 maepad_warning("Error copying data from %s to %s", checklisttable_name
, checklisttable_tmpname
);
3489 GtkTreeRowReference
*selectedRef
= read_sqlite3_data(mainview
, 0, NULL
, selectedCard
, model
);
3491 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), GTK_TREE_MODEL(model
));
3492 g_object_unref(model
);
3493 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview
->treeview
));
3495 if (selectedRef
!= NULL
)
3497 GtkTreeIter seliter
;
3499 if (ref2iter(GTK_TREE_MODEL(model
), selectedRef
, &seliter
) == TRUE
)
3501 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
3502 gtk_tree_selection_select_iter(selection
, &seliter
);
3505 gtk_tree_row_reference_free(selectedRef
);
3512 sqlite3_finalize(stmt
);
3516 mainview
->loading
=FALSE
;
3524 void write_buffer_to_file(MainView
* mainview
)
3526 maepad_message("Writing database to file: %s", mainview
->file_name
);
3527 saveCurrentData(mainview
);
3529 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
));
3530 /*update ord value in database for all nodes*/
3531 gtk_tree_model_foreach(GTK_TREE_MODEL(model
),(GtkTreeModelForeachFunc
) foreach_func_update_ord
,mainview
);
3533 busy_enter(mainview
);
3537 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", misctable_name
);
3538 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3540 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", misctable_name
, misctable
);
3541 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3545 if (mainview
->newnodedialog_createchild
== FALSE
)
3547 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('newNodeDlgCreateChild', '%d');", misctable_name
, nndcc
);
3548 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3550 nodeData
*node
= getSelectedNode(mainview
);
3554 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('selectedNode', '%d');", misctable_name
, node
->sql3id
);
3555 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3558 guint bsize
= sketchwidget_get_brushsize(mainview
->sk
);
3559 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('brushSize', '%d');", misctable_name
, bsize
);
3560 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3562 if (mainview
->current_color
== NULL
) {
3563 GdkColor color
= {0, 0, 0, 0};
3564 mainview
->current_color
= gdk_color_copy(&color
);
3566 unsigned long bcol
= ((mainview
->current_color
->red
>> 8) << 16) |
3567 ((mainview
->current_color
->green
>> 8) << 8) |
3568 ((mainview
->current_color
->blue
) >> 8);
3570 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('brushColor', '%lu');", misctable_name
, bcol
);
3571 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3573 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('dataVersion', '%d');", misctable_name
, datatableversion
);
3574 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3576 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('checklistVersion', '%d');", misctable_name
, checklisttableversion
);
3577 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3579 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_backupname
);
3580 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3581 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", datatable_backupname
, datatable
);
3582 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3584 maepad_warning("Error creating backup table: %s", datatable_backupname
);
3585 show_banner(mainview
, _("Error creating backup table"));
3587 busy_leave(mainview
);
3590 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", datatable_backupname
, datatable_name
);
3591 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3593 maepad_warning("Error backing up table %s to %s", datatable_name
, datatable_backupname
);
3594 show_banner(mainview
, _("Error creating backup table"));
3596 busy_leave(mainview
);
3599 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s", datatable_name
);
3600 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3602 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", datatable_name
, datatable_tmpname
);
3603 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3605 maepad_warning("Error saving table %s to %s", datatable_tmpname
, datatable_name
);
3606 show_banner(mainview
, _("Error saving table"));
3608 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s", datatable_name
);
3609 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3611 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", datatable_name
, datatable_backupname
);
3612 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3613 maepad_warning("Error restoring backup. Data lost :(");
3616 busy_leave(mainview
);
3620 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_backupname
);
3621 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3624 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", checklisttable_backupname
);
3625 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3626 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", checklisttable_backupname
, checklisttable
);
3627 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3629 maepad_warning("Error creating backup table: %s", checklisttable_backupname
);
3630 show_banner(mainview
, _("Error creating checklist backup table"));
3632 busy_leave(mainview
);
3636 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", checklisttable_backupname
, checklisttable_name
);
3637 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3639 maepad_warning("Error backing up table %s to %s", checklisttable_name
, checklisttable_backupname
);
3640 show_banner(mainview
, _("Error creating checklist backup table"));
3642 busy_leave(mainview
);
3645 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s", checklisttable_name
);
3646 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3648 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", checklisttable_name
, checklisttable_tmpname
);
3649 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3651 maepad_warning("Error saving table %s to %s", checklisttable_tmpname
, checklisttable_name
);
3652 show_banner(mainview
, _("Error saving checklist table"));
3654 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s", checklisttable_name
);
3655 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3657 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", checklisttable_name
, checklisttable_backupname
);
3658 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3659 maepad_warning("Error restoring backup. Data lost :(");
3661 busy_leave(mainview
);
3665 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", checklisttable_backupname
);
3666 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3668 mainview
->file_edited
= FALSE
;
3669 busy_leave(mainview
);
3670 show_banner(mainview
, _("Changes saved"));
3673 void callback_checklist_change(GtkTreeSelection
*selection
, MainView
*mainview
)
3675 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
3677 g_signal_handlers_block_by_func(mainview
->bold_tb
, callback_fontstyle
, mainview
->bold_tb
);
3678 g_signal_handlers_block_by_func(mainview
->strikethru_tb
, callback_fontstyle
, mainview
->strikethru_tb
);
3679 g_signal_handlers_block_by_func(mainview
->check_tb
, callback_fontstyle
, mainview
->check_tb
);
3681 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->bold_tb
), FALSE
);
3682 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->strikethru_tb
), FALSE
);
3683 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->check_tb
), FALSE
);
3685 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
3686 GList
* l
=gtk_tree_selection_get_selected_rows(selection
, NULL
);
3688 gboolean gotit
=FALSE
;
3693 GtkTreePath
*path
=cur
->data
;
3698 if (gtk_tree_model_get_iter(model
, &iter
, path
))
3700 gint styletoset_weight
;
3701 gboolean styletoset_strike
;
3704 gtk_tree_model_get(GTK_TREE_MODEL(model
), &iter
, CHECKNODE_BOLD
, &styletoset_weight
, CHECKNODE_STRIKE
, &styletoset_strike
, CHECKNODE_CHECKED
, &ischecked
, -1);
3705 if (styletoset_weight
==PANGO_WEIGHT_BOLD
) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->bold_tb
), TRUE
);
3706 if (styletoset_strike
==TRUE
) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->strikethru_tb
), TRUE
);
3707 if (ischecked
==TRUE
) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->check_tb
), TRUE
);
3711 gtk_tree_path_free(path
);
3717 g_signal_handlers_unblock_by_func(mainview
->bold_tb
, callback_fontstyle
, mainview
->bold_tb
);
3718 g_signal_handlers_unblock_by_func(mainview
->strikethru_tb
, callback_fontstyle
, mainview
->strikethru_tb
);
3719 g_signal_handlers_unblock_by_func(mainview
->check_tb
, callback_fontstyle
, mainview
->check_tb
);
3722 void callback_checklist_paste(MainView
*mainview
)
3724 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
3728 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
3729 GtkTreeIter toplevel
;
3730 gchar
*pasted_text
= gtk_clipboard_wait_for_text(mainview
->clipboard
);
3732 entries
= g_strsplit(pasted_text
, "\n", 0);
3733 length
= g_strv_length(entries
);
3735 for (i
=0; i
<length
; i
++) {
3736 gtk_list_store_append(GTK_LIST_STORE(model
), &toplevel
);
3737 gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_CHECKED
, FALSE
, CHECKNODE_TEXT
, entries
[i
], -1);
3740 mainview
->checklist_edited
= TRUE
;
3741 g_free(pasted_text
);
3742 g_strfreev(entries
);
3745 void callback_checklist_add(GtkAction
*action
, MainView
*mainview
)
3747 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
3749 gchar
* text
= show_line_edit_dialog(mainview
, _("Add new checklist item"), _("Name:"), _("Add"), "");
3752 GtkTreeModel
* model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
3753 GtkTreeIter toplevel
;
3754 gtk_list_store_append(GTK_LIST_STORE(model
), &toplevel
);
3756 gtk_list_store_set(GTK_LIST_STORE(model
),
3758 CHECKNODE_CHECKED
, FALSE
,
3759 CHECKNODE_TEXT
, text
,
3762 GtkTreePath
*path
= gtk_tree_model_get_path(model
, &toplevel
);
3764 gtk_tree_view_set_cursor(GTK_TREE_VIEW(mainview
->listview
), path
, mainview
->checklist_column_text
, FALSE
);
3765 gtk_tree_path_free(path
);
3768 mainview
->checklist_edited
= TRUE
;
3772 void callback_checklist_edit(GtkAction
*action
, MainView
*mainview
)
3774 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
3776 GtkTreeSelection
* selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
));
3778 if (gtk_tree_selection_count_selected_rows(selection
) == 0) {
3779 show_banner(mainview
, _("Select items first"));
3783 GtkTreeModel
* model
;
3786 if (gtk_tree_selection_get_selected(selection
, &model
, &iter
)) {
3787 gchar
* old_text
= NULL
;
3788 gtk_tree_model_get(model
, &iter
, CHECKNODE_TEXT
, &old_text
, -1);
3790 gchar
* new_text
= show_line_edit_dialog(mainview
, _("Edit checklist item"), _("New name:"), _("Save"), old_text
);
3792 if (new_text
!= NULL
) {
3793 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_TEXT
, new_text
, -1);
3800 mainview
->checklist_edited
= TRUE
;
3803 void callback_checklist_delete(GtkAction
*action
, MainView
*mainview
)
3805 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
3807 if (gtk_tree_selection_count_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
)))==0) {
3808 show_banner(mainview
, _("Select items first"));
3812 if (show_confirmation(mainview
, _("Delete selected checklist item?"))) {
3813 callback_checklist_delete_real(mainview
);
3817 void callback_checklist_delete_real(MainView
* mainview
)
3819 GtkTreeModel
*model
=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
3820 GList
* l
=gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
)), NULL
);
3822 GList
* rowrefs
=NULL
;
3826 GtkTreePath
*path
=cur
->data
;
3829 if (gtk_tree_model_get_iter(model
, &iter
, path
))
3831 GtkTreeRowReference
*rowref
= gtk_tree_row_reference_new(model
, path
);
3832 rowrefs
=g_list_append(rowrefs
, rowref
);
3834 gtk_tree_path_free(path
);
3839 g_object_ref(model
);
3840 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->listview
), NULL
);
3845 GtkTreeRowReference
*rowref
=cur
->data
;
3846 GtkTreePath
*path
= gtk_tree_row_reference_get_path(rowref
);
3850 if (gtk_tree_model_get_iter(model
, &iter
, path
)) gtk_list_store_remove(GTK_LIST_STORE(model
), &iter
);
3851 gtk_tree_path_free(path
);
3853 gtk_tree_row_reference_free(rowref
);
3856 g_list_free(rowrefs
);
3858 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->listview
), model
);
3859 g_object_unref(model
);
3860 mainview
->checklist_edited
= TRUE
;
3863 /* Ask the user for confirmation of a specific action */
3865 show_confirmation(MainView
* mainview
, gchar
* question
)
3867 GtkDialog
* dialog
= GTK_DIALOG(hildon_note_new_confirmation(
3868 GTK_WINDOW(mainview
->data
->main_view
), question
));
3869 gtk_window_set_transient_for(GTK_WINDOW(dialog
), mainview_get_dialog_parent(mainview
));
3871 gint response
= gtk_dialog_run(dialog
);
3872 gtk_widget_destroy(GTK_WIDGET(dialog
));
3874 return (response
== GTK_RESPONSE_OK
);
3877 /* Show a information banner to the user (non-modal) */
3879 show_banner(MainView
* mainview
, const gchar
* text
)
3881 hildon_banner_show_information(GTK_WIDGET(mainview_get_dialog_parent(mainview
)), NULL
, text
);
3884 /* Let the user enter or edit a line of text */
3886 show_line_edit_dialog(MainView
* mainview
, const gchar
* title
, const gchar
* label_text
, const gchar
* action
, const gchar
* text
)
3888 GtkWidget
* edit_dialog
;
3892 gchar
* result
= NULL
;
3894 edit_dialog
= GTK_WIDGET(gtk_dialog_new());
3895 gtk_window_set_title(GTK_WINDOW(edit_dialog
), title
);
3896 gtk_window_set_transient_for(GTK_WINDOW(edit_dialog
), mainview_get_dialog_parent(mainview
));
3898 label
= GTK_WIDGET(gtk_label_new(label_text
));
3900 entry
= hildon_entry_new(HILDON_SIZE_AUTO
);
3901 gtk_entry_set_text(GTK_ENTRY(entry
), text
);
3902 gtk_entry_set_activates_default(GTK_ENTRY(entry
), TRUE
);
3903 gtk_editable_select_region(GTK_EDITABLE(entry
), 0, -1);
3905 gtk_dialog_add_button(GTK_DIALOG(edit_dialog
), action
, GTK_RESPONSE_OK
);
3906 gtk_dialog_set_default_response(GTK_DIALOG(edit_dialog
), GTK_RESPONSE_OK
);
3908 hbox
= GTK_WIDGET(gtk_hbox_new(FALSE
, 10));
3910 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(edit_dialog
))), GTK_WIDGET(hbox
));
3911 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
3912 gtk_box_pack_start(GTK_BOX(hbox
), entry
, TRUE
, TRUE
, 0);
3914 gtk_widget_show_all(GTK_WIDGET(hbox
));
3917 if (gtk_dialog_run(GTK_DIALOG(edit_dialog
)) == GTK_RESPONSE_OK
) {
3918 result
= g_strdup(gtk_entry_get_text(GTK_ENTRY(entry
)));
3919 if (strcmp(result
, "") != 0) {
3922 show_banner(mainview
, _("Please enter a non-empty text"));
3932 gtk_widget_destroy(GTK_WIDGET(edit_dialog
));