2 * This file is part of MaePad
3 * Copyright (c) 2010 Thomas Perl <thp.io/about>
4 * http://thp.io/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
tree_model_iter_prev(GtkTreeModel
*tree_model
,GtkTreeIter
*iter
);
97 gboolean
show_confirmation(MainView
* mainview
, gchar
* question
);
101 gboolean
callback_node_view_window_state(GtkWidget
* window
,
102 GdkEventWindowState
* event
, gpointer user_data
)
104 MainView
* mainview
= (MainView
*)user_data
;
105 GtkWidget
* sketch_scroll
= NULL
;
106 nodeData
*nd
= getSelectedNode(mainview
);
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
->checklist_content
);
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
->checklist_content
);
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
->checklist_content
);
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
->checklist_content
);
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
);
540 void callback_treeview_change(GtkTreeSelection
* selection
, gpointer data
)
542 MainView
*mainview
= (MainView
*) data
;
543 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
545 nodeData
*nd
= getSelectedNode(mainview
);
547 gchar
* nodeName
= _("View memo");
549 if (nd
!= NULL
&& nd
->name
!= NULL
) {
553 /* Show node view with selected node */
554 gtk_window_set_title(GTK_WINDOW(mainview
->data
->node_view
),
557 if (mainview
->can_show_node_view
) {
558 gtk_widget_show(GTK_WIDGET(mainview
->data
->node_view
));
561 /* Make sure we don't accidentally collapse any nodes */
562 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview
->treeview
));
565 if (mainview
->cansel_time
>0 && mainview
->cansel_time
+1.0<tm
) mainview
->cansel_node
=NULL
;
569 if (mainview
->cansel_node
!=NULL
)
571 maepad_debug("[SELLOGIC] saving %d to unselect all nodes", (mainview
->cansel_node
)->sql3id
);
572 saveDataToNode(mainview
, (mainview
->cansel_node
));
573 mainview
->cansel_node
=NULL
;
578 if (mainview
->cansel_node
!=NULL
)
580 if (nd
->sql3id
== (mainview
->cansel_node
)->sql3id
)
582 mainview
->cansel_node
=NULL
;
583 maepad_debug("[SELLOGIC] doubly selected %d, doing nothing", nd
->sql3id
);
584 prepareUIforNodeChange(mainview
, nd
->typ
);
589 maepad_debug("[SELLOGIC] saving %d to load new node", (mainview
->cansel_node
)->sql3id
);
590 saveDataToNode(mainview
, (mainview
->cansel_node
));
591 mainview
->cansel_node
=NULL
;
595 if (nd
== NULL
) return;
597 busy_enter(mainview
);
599 gboolean goterr
= TRUE
;
600 char *textdata
= NULL
;
602 int blobsize
= 0, textsize
= 0;
606 g_snprintf(tq
, sizeof(tq
), "SELECT bodytype, body, bodyblob, flags FROM %s WHERE nodeid=%d", datatable_tmpname
, nd
->sql3id
);
607 sqlite3_stmt
*stmt
= NULL
;
609 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt
, &dum
);
613 maepad_warning("Error reading (1): %s", sqlite3_errmsg(mainview
->db
));
618 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
620 rc
= sqlite3_step(stmt
);
621 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
623 else if (rc
== SQLITE_ROW
)
625 nd
->typ
= sqlite3_column_int(stmt
, 0);
626 nd
->flags
= sqlite3_column_int(stmt
, 3);
628 prepareUIforNodeChange(mainview
, nd
->typ
);
629 if (nd
->typ
== NODE_TEXT
)
631 gboolean file_edited_backup
= mainview
->file_edited
;
633 blobsize
= sqlite3_column_bytes(stmt
, 2);
634 blob
= (char *)sqlite3_column_blob(stmt
, 2);
636 textdata
= (char *)sqlite3_column_text(stmt
, 1);
637 textsize
= sqlite3_column_bytes(stmt
, 1);
639 /* gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), "", -1);*/
640 wp_text_buffer_reset_buffer(mainview
->buffer
, TRUE
);
642 gboolean richtext
=FALSE
;
647 gboolean oldway
=FALSE
;
651 strncpy(tst
, blob
, 8);
653 if (strcmp(tst
, "RICHTEXT")==0) oldway
=TRUE
;
659 gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(mainview
->buffer
), &iter
);
660 gtk_text_buffer_deserialize_rich_text(GTK_TEXT_BUFFER(mainview
->buffer
), &iter
, blob
, blobsize
, TRUE
, &err
);
674 wp_text_buffer_load_document_begin(mainview
->buffer
, TRUE
);
675 wp_text_buffer_load_document_write(mainview
->buffer
, blob
, blobsize
);
676 wp_text_buffer_load_document_end(mainview
->buffer
);
680 if (richtext
==FALSE
&& !(textdata
== NULL
|| g_utf8_validate(textdata
, textsize
, NULL
) == FALSE
))
682 /* gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), textdata, textsize);*/
683 wp_text_buffer_load_document_begin(mainview
->buffer
, FALSE
);
684 wp_text_buffer_load_document_write(mainview
->buffer
, textdata
, textsize
);
685 wp_text_buffer_load_document_end(mainview
->buffer
);
688 wp_text_buffer_enable_rich_text(mainview
->buffer
, TRUE
);
689 hildon_check_button_set_active(HILDON_CHECK_BUTTON(mainview
->menu_button_wordwrap
),
690 (nd
->flags
& NODEFLAG_WORDWRAP
)?(TRUE
):(FALSE
));
692 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(mainview
->buffer
), FALSE
); /*we probably don't need this*/
694 callback_undotoggle((gpointer
)mainview
->buffer
, FALSE
, mainview
); /*we need these*/
695 callback_redotoggle((gpointer
)mainview
->buffer
, FALSE
, mainview
);
697 if (file_edited_backup
==FALSE
) mainview
->file_edited
=FALSE
; /*textview changed event toggles this?*/
700 else if (nd
->typ
== NODE_SKETCH
)
702 sketchwidget_wipe_undo(mainview
->sk
);
704 /* Disable squared and filled mode when opening a sketch */
705 hildon_check_button_set_active(HILDON_CHECK_BUTTON(mainview
->menu_button_square
), FALSE
);
706 hildon_check_button_set_active(HILDON_CHECK_BUTTON(mainview
->menu_button_filled
), FALSE
);
708 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->shapemenuitems
[1]), TRUE
);
709 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->shapemenuitems
[0]), TRUE
);
711 blobsize
= sqlite3_column_bytes(stmt
, 2);
712 blob
= (char *)sqlite3_column_blob(stmt
, 2);
713 gboolean clear
= TRUE
;
719 maepad_debug("blob size: %d", blobsize
);
720 GdkPixbufLoader
*pl
= gdk_pixbuf_loader_new_with_type("png", NULL
);
723 gdk_pixbuf_loader_write(pl
, (guchar
*) blob
, blobsize
, &err
);
726 maepad_warning("Error loading sketch: %s", err
->message
);
730 gdk_pixbuf_loader_close(pl
, NULL
);
731 GdkPixbuf
*pixbuf
= gdk_pixbuf_loader_get_pixbuf(pl
);
733 if (GDK_IS_PIXBUF(pixbuf
))
735 GtkWidget
*skdr
= sketchwidget_get_drawingarea(mainview
->sk
);
736 GtkPixmap
*skpix
= (GtkPixmap
*) sketchwidget_get_Pixmap(mainview
->sk
);
738 int w
=gdk_pixbuf_get_width(pixbuf
);
739 int h
=gdk_pixbuf_get_height(pixbuf
);
740 if (w
!=skdr
->allocation
.width
|| h
!=skdr
->allocation
.height
)
742 if (w
>skdr
->allocation
.width
) w
=skdr
->allocation
.width
;
743 if (h
>skdr
->allocation
.height
) h
=skdr
->allocation
.height
;
744 sketchwidget_clear_real(mainview
->sk
);
746 gdk_draw_pixbuf(GDK_DRAWABLE(skpix
), NULL
, pixbuf
, 0, 0, 0, 0, w
, h
, GDK_RGB_DITHER_NONE
, 0, 0);
751 if (skpix
&& G_IS_OBJECT(skpix
)) g_object_unref(skpix
);
755 maepad_warning("Error loading pixbuf");
761 maepad_message("Clearing sketch widget");
762 sketchwidget_clear_real(mainview
->sk
);
764 gtk_widget_queue_draw(sketchwidget_get_drawingarea(mainview
->sk
));
766 else if (nd
->typ
== NODE_CHECKLIST
)
768 mainview
->checklist_edited
= FALSE
;
769 GtkTreeModel
*model
=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
771 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->listview
), NULL
);
772 gtk_list_store_clear(GTK_LIST_STORE(model
));
774 g_snprintf(tq
, sizeof(tq
), "SELECT name, style, color FROM %s WHERE nodeid=%d ORDER BY ord, idx", checklisttable_tmpname
, nd
->sql3id
);
775 sqlite3_stmt
*stmt2
= NULL
;
777 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt2
, &dum
);
780 maepad_warning("Error reading checklist (1) %s", sqlite3_errmsg(mainview
->db
));
786 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
788 rc
= sqlite3_step(stmt2
);
789 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
791 else if (rc
== SQLITE_ROW
)
793 char *textdata
= (char *)sqlite3_column_text(stmt2
, 0);
794 int style
= sqlite3_column_int(stmt2
, 1);
795 unsigned long col
= sqlite3_column_int(stmt2
, 2);
797 GtkTreeIter toplevel
;
798 gtk_list_store_append(GTK_LIST_STORE(model
), &toplevel
);
799 gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_TEXT
, textdata
, CHECKNODE_CHECKED
, FALSE
, -1);
800 if ((style
& CHECKSTYLE_CHECKED
)>0) {
801 gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_CHECKED
, TRUE
, -1);
802 gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_ICON_NAME
, "widgets_tickmark_list", -1);
804 if ((style
& CHECKSTYLE_BOLD
)>0) gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_BOLD
, PANGO_WEIGHT_BOLD
, -1);
805 if ((style
& CHECKSTYLE_STRIKE
)>0) gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_STRIKE
, TRUE
, -1);
810 g_snprintf(tmp
, sizeof(tmp
), "#%02lx%02lx%02lx", ((col
& 0xFF0000) >> 16), ((col
& 0xFF00) >> 8), (col
& 0xFF));
811 gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_COLOR
, tmp
, -1);
816 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
)
818 maepad_warning("Error reading checklist (2): %s", sqlite3_errmsg(mainview
->db
));
822 sqlite3_finalize(stmt2
);
825 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->listview
), model
);
826 g_object_unref(model
);
829 if ((nd
->flags
& NODEFLAG_SKETCHLINES
) > 0)
830 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->sketchlinesmenuitems
[1]), TRUE
);
831 else if ((nd
->flags
& NODEFLAG_SKETCHGRAPH
) > 0)
832 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->sketchlinesmenuitems
[2]), TRUE
);
835 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->sketchlinesmenuitems
[0]), TRUE
);
836 callback_sketchlines(NULL
, mainview
->sketchlinesmenuitems
[0]); /*FIXME:ugly */
838 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->tools_pressure
), TRUE
);
843 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
) {
844 maepad_warning("Error reading (2): %s", sqlite3_errmsg(mainview
->db
));
847 sqlite3_finalize(stmt
);
850 busy_leave(mainview
);
852 /* Show / hide the sketch-related menu widgets */
853 if (nd
->typ
== NODE_SKETCH
) {
854 gtk_widget_show(mainview
->menu_button_square
);
855 gtk_widget_show(mainview
->menu_button_filled
);
857 gtk_widget_hide(mainview
->menu_button_square
);
858 gtk_widget_hide(mainview
->menu_button_filled
);
861 /* Show/hide the rich text-related menu widgets */
862 if (nd
->typ
== NODE_TEXT
) {
863 gtk_widget_show(mainview
->menu_button_wordwrap
);
865 gtk_widget_hide(mainview
->menu_button_wordwrap
);
868 /* Show/hide the checklist-related menu widgets */
869 if (nd
->typ
== NODE_CHECKLIST
) {
870 gtk_widget_show(mainview
->menu_button_remove_checked
);
872 gtk_widget_hide(mainview
->menu_button_remove_checked
);
877 show_banner(mainview
, _("Error loading memo"));
881 gboolean
treeview_canselect(GtkTreeSelection
* selection
, GtkTreeModel
* model
, GtkTreePath
* path
, gboolean path_currently_selected
, gpointer userdata
)
883 MainView
*mainview
= (MainView
*) userdata
;
884 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
886 if (path_currently_selected
)
889 gtk_tree_model_get_iter(model
, &iter
, path
);
891 gtk_tree_model_get(model
, &iter
, NODE_DATA
, &(mainview
->cansel_node
), -1);
892 mainview
->cansel_time
=time(NULL
);
898 gboolean
newnodedlg_key_press_cb(GtkWidget
* widget
, GdkEventKey
* event
, GtkWidget
* dlg
)
900 SketchWidget
*s
= gtk_object_get_data(GTK_OBJECT(dlg
), "sk");
902 switch (event
->keyval
)
905 sketchwidget_redo(s
);
908 sketchwidget_undo(s
);
915 /* This struct will hold all our toggle buttons, so we can
916 * only allow one to be active at a time (i.e. radio buttons) */
917 typedef struct _newNodeToggleButtons newNodeToggleButtons
;
918 struct _newNodeToggleButtons
920 GtkWidget
*rbt
; /* Text */
921 GtkWidget
*rbs
; /* Sketch */
922 GtkWidget
*rbc
; /* Checklist */
925 void show_sketch_widget(GtkWidget
*widget
, gpointer user_data
)
927 GtkWidget
*dialog
= (GtkWidget
*)user_data
;
929 /* Show the sketch widget and hide the entry + draw button */
930 gtk_widget_show(gtk_object_get_data(GTK_OBJECT(dialog
), "al"));
931 gtk_widget_hide(gtk_object_get_data(GTK_OBJECT(dialog
), "draw_button"));
932 gtk_widget_hide(gtk_object_get_user_data(GTK_OBJECT(dialog
)));
935 void new_node_dialog(nodeType typ
, MainView
* mainview
)
937 GtkWidget
*dialog
, *entry
, *but_ok
, *vbox
, *hbox
, *al
;
938 GtkWidget
*rb1
, *rb2
, *rb3
;
940 gchar datetime_str
[200];
943 gboolean datetime_written
= FALSE
;
946 tm_now
= localtime(&t_now
);
948 if (tm_now
!= NULL
) {
949 if (strftime(datetime_str
, sizeof(datetime_str
), "%y-%m-%d %H:%M", tm_now
) != 0) {
950 datetime_written
= TRUE
;
954 if (datetime_written
== FALSE
) {
955 /* Was not able to determine a datetime string - use default */
956 maepad_warning("Cannot determine current time");
957 strncpy(datetime_str
, _("New memo"), sizeof(datetime_str
));
958 datetime_str
[sizeof(datetime_str
)-1] = '\0';
961 newNodeToggleButtons
*nntb
= g_malloc(sizeof(newNodeToggleButtons
));
963 dialog
= gtk_dialog_new();
964 gtk_window_set_title(GTK_WINDOW(dialog
), _("Add new memo"));
965 gtk_window_set_transient_for(GTK_WINDOW(dialog
), mainview_get_dialog_parent(mainview
));
966 gtk_dialog_set_has_separator(GTK_DIALOG(dialog
), FALSE
);
968 g_signal_connect(G_OBJECT(dialog
), "key_press_event", G_CALLBACK(newnodedlg_key_press_cb
), dialog
);
970 vbox
= gtk_vbox_new(FALSE
, 0);
972 hbox
= gtk_hbox_new(TRUE
, 0);
974 /* Text note toggle button */
975 rb1
= hildon_gtk_radio_button_new(HILDON_SIZE_FINGER_HEIGHT
, NULL
);
976 gtk_button_set_label(GTK_BUTTON(rb1
), _("Rich text"));
977 gtk_button_set_image(GTK_BUTTON(rb1
), gtk_image_new_from_file(PIXMAPDIR
"/text.png"));
978 gtk_box_pack_start(GTK_BOX(hbox
), GTK_WIDGET(rb1
), TRUE
, TRUE
, 0);
981 /* Sketch toggle button */
982 rb2
= hildon_gtk_radio_button_new_from_widget(HILDON_SIZE_FINGER_HEIGHT
, GTK_RADIO_BUTTON(rb1
));
983 gtk_button_set_label(GTK_BUTTON(rb2
), _("Sketch"));
984 gtk_button_set_image(GTK_BUTTON(rb2
), gtk_image_new_from_file(PIXMAPDIR
"/sketch.png"));
985 gtk_box_pack_start(GTK_BOX(hbox
), GTK_WIDGET(rb2
), TRUE
, TRUE
, 0);
988 /* Checklist toggle button */
989 rb3
= hildon_gtk_radio_button_new_from_widget(HILDON_SIZE_FINGER_HEIGHT
, GTK_RADIO_BUTTON(rb1
));
990 gtk_button_set_label(GTK_BUTTON(rb3
), _("Checklist"));
991 gtk_button_set_image(GTK_BUTTON(rb3
), gtk_image_new_from_file(PIXMAPDIR
"/checklist.png"));
992 gtk_box_pack_start(GTK_BOX(hbox
), GTK_WIDGET(rb3
), TRUE
, TRUE
, 0);
995 /* Set mode to 0 to get correct styling */
996 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb1
), FALSE
);
997 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb2
), FALSE
);
998 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb3
), FALSE
);
1000 /* Remember "new note toggle buttons" list */
1001 gtk_object_set_data(GTK_OBJECT(dialog
), "nntb", nntb
);
1003 if (typ
== NODE_TEXT
) {
1004 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb1
), TRUE
);
1005 } else if (typ
== NODE_SKETCH
) {
1006 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb2
), TRUE
);
1008 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb3
), TRUE
);
1011 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 0);
1013 but_ok
= gtk_dialog_add_button(GTK_DIALOG(dialog
), _("Add"), GTK_RESPONSE_OK
);
1014 gtk_dialog_set_default_response(GTK_DIALOG(dialog
), GTK_RESPONSE_OK
);
1015 g_signal_connect(G_OBJECT(but_ok
), "clicked", G_CALLBACK(callback_new_node_real
), dialog
);
1017 gtk_object_set_data(GTK_OBJECT(dialog
), "m", mainview
);
1019 hb
= gtk_hbox_new(FALSE
, 10);
1020 gtk_box_pack_start(GTK_BOX(hb
), gtk_label_new(_("Name:")), FALSE
, FALSE
, 0);
1021 entry
= hildon_entry_new(HILDON_SIZE_AUTO
);
1022 gtk_entry_set_activates_default(GTK_ENTRY(entry
), TRUE
);
1023 gtk_object_set_user_data(GTK_OBJECT(dialog
), entry
);
1024 gtk_entry_set_text(GTK_ENTRY(entry
), datetime_str
);
1025 gtk_editable_select_region(GTK_EDITABLE(entry
), 0, -1);
1026 gtk_box_pack_start(GTK_BOX(hb
), entry
, TRUE
, TRUE
, 0);
1028 /* Sketch widget, hidden by default */
1029 al
= gtk_alignment_new(0.5, 0.5, 0, 0);
1030 SketchWidget
*s
= sketchwidget_new(SKETCHNODE_X
, SKETCHNODE_Y
, TRUE
);
1031 gtk_object_set_data(GTK_OBJECT(dialog
), "sk", s
);
1032 gtk_object_set_data(GTK_OBJECT(dialog
), "al", al
);
1033 sketchwidget_set_brushsize(s
, 2);
1034 sketchwidget_set_backstyle(s
, SKETCHBACK_GRAPH
);
1035 gtk_widget_set_size_request(sketchwidget_get_mainwidget(s
), SKETCHNODE_X
, SKETCHNODE_Y
);
1036 gtk_container_add(GTK_CONTAINER(al
), sketchwidget_get_mainwidget(s
));
1037 gtk_box_pack_start(GTK_BOX(hb
), al
, FALSE
, FALSE
, 0);
1039 /*but_sketch = hildon_button_new_with_text(
1040 HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
1041 HILDON_BUTTON_ARRANGEMENT_VERTICAL,
1042 _("Use sketch label"), NULL);
1044 gtk_object_set_data(GTK_OBJECT(dialog), "draw_button", but_sketch);
1045 gtk_signal_connect(GTK_OBJECT(but_sketch), "clicked", G_CALLBACK(show_sketch_widget), dialog);
1046 gtk_box_pack_start(GTK_BOX(hb), but_sketch, FALSE, TRUE, 0);*/
1047 gtk_box_pack_start(GTK_BOX(vbox
), hb
, TRUE
, FALSE
, 0);
1049 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog
)->vbox
), vbox
);
1051 gtk_widget_grab_focus(entry
);
1053 gtk_widget_show_all(dialog
);
1055 /* Hide the sketch widget at first */
1056 gtk_widget_hide(al
);
1057 gtk_window_set_modal(GTK_WINDOW(dialog
), TRUE
);
1060 void add_new_node(nodeData
* node
, MainView
* mainview
, gboolean ischild
)
1062 GtkTreeIter parentiter
, newiter
;
1063 GtkTreeIter parentiterFilter
, newiterFilter
;
1064 GtkTreeModel
*model
;
1065 GtkTreeIter
*ptr
= NULL
;
1066 gboolean setPtr
= FALSE
;
1068 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1070 if (gtk_tree_selection_get_selected(selection
, &model
, &parentiterFilter
)) {
1074 model
= GTK_TREE_MODEL(mainview
->main_view_tree_store
);
1075 gtk_tree_model_filter_convert_iter_to_child_iter(
1076 GTK_TREE_MODEL_FILTER(mainview
->main_view_tree_filter
),
1084 GtkTreePath
*path
= NULL
;
1086 unsigned int parentnodeid
= 0;
1090 path
= gtk_tree_model_get_path(model
, &parentiter
);
1092 if (ischild
== FALSE
)
1094 gtk_tree_path_up(path
);
1096 if (gtk_tree_path_get_depth(path
) == 0)
1098 /* Selected node is a root node */
1099 ptr
= NULL
; /* New node can not have a Parent node */
1100 gtk_tree_path_down(path
); /*restore path so expand() works */
1102 else if (gtk_tree_path_get_depth(path
) > 0)
1104 /* Selected node is a child node */
1105 if (gtk_tree_model_get_iter(model
, &parentiter
, path
))
1115 gtk_tree_model_get(model
, ptr
, NODE_DATA
, &nd
, -1);
1117 parentnodeid
= nd
->sql3id
;
1123 sqlite3_stmt
*stmt
= NULL
;
1130 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s (parent, bodytype, name, nameblob, ord) VALUES (%d, %d, ?, ?, 0);", datatable_tmpname
, parentnodeid
, node
->typ
);
1131 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt
, &dum
);
1135 maepad_warning("Error inserting (1): %s", sqlite3_errmsg(mainview
->db
));
1138 if (node
->name
!= NULL
)
1139 sqlite3_bind_text(stmt
, 1, node
->name
, strlen(node
->name
), SQLITE_TRANSIENT
);
1141 sqlite3_bind_text(stmt
, 1, NULL
, 0, SQLITE_TRANSIENT
);
1143 if (node
->namepix
!= NULL
)
1145 gchar
*namepixdata
= NULL
;
1150 if (gdk_pixbuf_save_to_buffer(node
->namepix
, &namepixdata
, &datalen
, "png", &err
, NULL
) == FALSE
)
1154 maepad_warning("Error saving name: %s", err
->message
);
1157 sqlite3_bind_blob(stmt
, 2, namepixdata
, datalen
, SQLITE_TRANSIENT
);
1160 sqlite3_bind_blob(stmt
, 2, NULL
, 0, SQLITE_TRANSIENT
);
1163 while(rc
== SQLITE_BUSY
)
1165 rc
= sqlite3_step(stmt
);
1166 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
1169 sqlite3_finalize(stmt
);
1170 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
)
1172 maepad_warning("Error inserting (2): %s", sqlite3_errmsg(mainview
->db
));
1175 node
->sql3id
= sqlite3_last_insert_rowid(mainview
->db
);
1179 if (node
->sql3id
== 0)
1184 g_object_unref(node
->namepix
);
1187 gtk_tree_path_free(path
);
1188 show_banner(mainview
, _("Error creating memo"));
1192 gtk_tree_store_append(GTK_TREE_STORE(model
), &newiter
, ptr
);
1194 gtk_tree_store_set(GTK_TREE_STORE(model
), &newiter
,
1195 NODE_NAME
, format_overview_name(node
, NULL
),
1196 NODE_PIXBUF
, node
->namepix
,
1202 mainview
->loading
=TRUE
; /*only when we have a valid parent*/
1203 gtk_tree_view_expand_row(GTK_TREE_VIEW(mainview
->treeview
), path
, FALSE
);
1204 gtk_tree_path_free(path
);
1207 if (gtk_tree_model_filter_convert_child_iter_to_iter(
1208 GTK_TREE_MODEL_FILTER(mainview
->main_view_tree_filter
),
1211 /* Only set the selection if the new item is visible -
1212 * it could be invisible if the filter doesn't show it */
1213 gtk_tree_selection_select_iter(selection
, &newiterFilter
);
1216 mainview
->loading
=FALSE
;
1219 void callback_new_node_real(GtkAction
* action
, gpointer data
)
1223 GtkWidget
*dialog
= data
;
1224 GtkWidget
*entry
= gtk_object_get_user_data(GTK_OBJECT(dialog
));
1226 mainview
= gtk_object_get_data(GTK_OBJECT(dialog
), "m");
1227 SketchWidget
*s
= gtk_object_get_data(GTK_OBJECT(dialog
), "sk");
1228 newNodeToggleButtons
*nntb
= gtk_object_get_data(GTK_OBJECT(dialog
), "nntb");
1230 nodeType typ
= NODE_TEXT
;
1231 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nntb
->rbs
))) {
1233 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nntb
->rbc
))) {
1234 typ
= NODE_CHECKLIST
;
1240 /*if (GTK_WIDGET_VISIBLE(entry))
1242 txt
= g_strdup(gtk_entry_get_text(GTK_ENTRY(entry
)));
1243 if (strcmp(txt
, "") == 0)
1251 GtkWidget *sdr = sketchwidget_get_drawingarea(s);
1253 GdkPixmap *spix = sketchwidget_get_Pixmap(s);
1255 pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(spix), NULL, 0, 0, 0, 0, sdr->allocation.width, sdr->allocation.height);
1256 g_object_unref(spix);
1258 GdkPixbuf *pixbuf2 = sketchwidget_trim_image(pixbuf, SKETCHNODE_X, SKETCHNODE_Y, &w,
1260 if (pixbuf2==NULL) return;
1262 GdkPixbuf *pixbuf3 = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, SKETCHNODE_RX,
1265 gdk_pixbuf_fill(pixbuf3, 0xffffffff);
1267 if (w <= SKETCHNODE_RX && h <= SKETCHNODE_RY)
1269 gdk_pixbuf_copy_area(pixbuf2, 0, 0, w, h, pixbuf3, 0, (SKETCHNODE_RY - h) / 2);
1277 neww = SKETCHNODE_RX;
1278 newh = (h / w) * SKETCHNODE_RX;
1282 newh = SKETCHNODE_RY;
1283 neww = (w / h) * SKETCHNODE_RY;
1285 if (newh > SKETCHNODE_RY)
1286 newh = SKETCHNODE_RY;
1288 GdkPixbuf *tmpbuf = gdk_pixbuf_scale_simple(pixbuf2, neww, newh,
1289 GDK_INTERP_BILINEAR);
1291 gdk_pixbuf_copy_area(tmpbuf, 0, 0, neww, newh, pixbuf3, 0, (SKETCHNODE_RY - newh) / 2);
1293 gdk_pixbuf_unref(tmpbuf);
1297 gdk_pixbuf_unref(pixbuf2);
1302 node
= g_malloc(sizeof(nodeData
));
1305 node
->namepix
= NULL
;
1307 /*if (GTK_WIDGET_VISIBLE(entry))
1313 node->namepix = pixbuf;
1320 mainview
->newnodedialog_createchild
= FALSE
;
1321 add_new_node(node
, mainview
, FALSE
);
1323 sketchwidget_destroy(s
);
1324 gtk_widget_destroy(dialog
);
1325 mainview
->file_edited
= TRUE
;
1331 void callback_file_delete_node(GtkAction
* action
, gpointer data
)
1333 MainView
*mainview
= (MainView
*) data
;
1334 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1336 if (getSelectedNode(mainview
) == NULL
) {
1337 show_banner(mainview
, _("Select a memo first"));
1341 if (show_confirmation(mainview
, _("Delete selected memo?"))) {
1342 mainview
->can_show_node_view
= FALSE
;
1343 callback_delete_node_real(mainview
);
1344 gtk_widget_hide(GTK_WIDGET(mainview
->data
->node_view
));
1349 * Callback for Rename Menuitem
1351 void callback_file_rename_node(GtkAction
* action
, gpointer data
)
1353 MainView
*mainview
= (MainView
*)data
;
1354 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1356 /* Get the selected node */
1357 nodeData
*sel_node
= getSelectedNode(mainview
);
1358 if (sel_node
== NULL
) {
1359 /* Do nothing, if no node has been selected */
1360 show_banner(mainview
, _("Select a memo first"));
1364 if (sel_node
->namepix
!= NULL
) {
1365 /* the memo has a graphical label, cannot edit! */
1366 show_banner(mainview
, _("Cannot rename memos with sketch name"));
1370 gchar
* new_name
= show_line_edit_dialog(mainview
, _("Rename memo"), _("New name:"), _("Rename"), sel_node
->name
);
1372 /* Only rename node when user accepted the new name */
1373 if (new_name
!= NULL
) {
1374 callback_rename_node_real(mainview
, new_name
);
1379 void callback_rename_node_real(MainView
* mainview
, gchar
* new_name
)
1381 GtkTreeIter iter
, filterIter
;
1382 GtkTreeModel
*model
;
1383 nodeData
*nd
= NULL
;
1385 /* Get the selected node */
1386 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1388 if (!gtk_tree_selection_get_selected(selection
, &model
, &filterIter
)) {
1392 /* Convert filter iter to (backend) model iter for rename */
1393 model
= GTK_TREE_MODEL(mainview
->main_view_tree_store
);
1394 gtk_tree_model_filter_convert_iter_to_child_iter(
1395 GTK_TREE_MODEL_FILTER(mainview
->main_view_tree_filter
),
1399 gtk_tree_model_get (model
, &iter
, NODE_DATA
, &nd
, -1);
1405 /* Update the database */
1406 sqlite3_stmt
*stmt
= NULL
;
1408 char* sql
= sqlite3_mprintf("UPDATE %s SET name='%q' WHERE nodeid=%d", datatable_tmpname
, new_name
, nd
->sql3id
);
1410 int rc
= sqlite3_prepare(mainview
->db
, sql
, strlen(sql
), &stmt
, NULL
);
1411 if (rc
== SQLITE_OK
) {
1413 while (rc
== SQLITE_BUSY
) {
1414 rc
= sqlite3_step(stmt
);
1415 if (rc
== SQLITE_DONE
) {
1416 /* Update in the database was successful - now update the rest */
1418 /* Update the noteData */
1420 nd
->name
= g_strdup(new_name
);
1422 /* Update the window title of node_view */
1423 gtk_window_set_title(GTK_WINDOW(mainview
->data
->node_view
), nd
->name
);
1425 /* Update the value in the tree store */
1426 gtk_tree_store_set (GTK_TREE_STORE(model
), &iter
, NODE_NAME
, format_overview_name(nd
, new_name
), -1);
1429 } else if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
) {
1430 maepad_warning("Error updating node: %s", sqlite3_errmsg(mainview
->db
));
1434 sqlite3_finalize(stmt
);
1436 maepad_warning("Error preparing DB update query: %s", sqlite3_errmsg(mainview
->db
));
1441 mainview
->file_edited
= TRUE
;
1444 void callback_file_export_node(GtkAction
* action
, gpointer data
)
1446 MainView
*mainview
= (MainView
*) data
;
1447 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1449 nodeData
*nd
=getSelectedNode(mainview
);
1452 show_banner(mainview
, _("Select a memo first"));
1456 gchar
*nodename
=nd
->name
;
1457 if (nodename
==NULL
) nodename
=_("saved memo");
1459 if (nd
->typ
== NODE_TEXT
)
1462 GtkTextIter begin, end;
1463 gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER(mainview->buffer), &begin, &end);
1464 gchar *text = gtk_text_buffer_get_slice(GTK_TEXT_BUFFER(mainview->buffer), &begin, &end, TRUE);
1466 GString
*gstr
=g_string_sized_new(4096);
1467 wp_text_buffer_save_document(mainview
->buffer
, (WPDocumentSaveCallback
)(wp_savecallback
), gstr
);
1468 gint textlen
=gstr
->len
;
1469 gchar
*text
=g_string_free(gstr
, FALSE
);
1471 if (text
==NULL
|| !strcmp(text
, ""))
1473 show_banner(mainview
, _("Memo is empty"));
1477 gchar
*fn
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, nodename
, "html");
1480 GnomeVFSResult vfs_result
;
1481 GnomeVFSHandle
*handle
= NULL
;
1482 GnomeVFSFileSize out_bytes
;
1483 vfs_result
= gnome_vfs_create(&handle
, fn
, GNOME_VFS_OPEN_WRITE
, 0, 0600);
1484 if ( vfs_result
!= GNOME_VFS_OK
) {
1485 show_banner(mainview
, _("Export failed"));
1489 gnome_vfs_write(handle
, text
, textlen
, &out_bytes
);
1490 gnome_vfs_close(handle
);
1491 if (out_bytes
==strlen(text
)) show_banner(mainview
, _("Exported"));
1492 else show_banner(mainview
, _("Export incomplete"));
1499 else if (nd
->typ
== NODE_SKETCH
)
1501 GdkPixmap
*skpix
= sketchwidget_get_Pixmap(mainview
->sk
);
1502 GtkWidget
*skdr
= sketchwidget_get_drawingarea(mainview
->sk
);
1503 GdkPixbuf
*pixbuf
= gdk_pixbuf_get_from_drawable(NULL
, GDK_DRAWABLE(skpix
), NULL
, 0, 0, 0, 0, skdr
->allocation
.width
, skdr
->allocation
.height
);
1506 show_banner(mainview
, _("Memo is empty"));
1510 gchar
*fn
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, nodename
, "png");
1513 if (gdk_pixbuf_save(pixbuf
, fn
, "png", NULL
, NULL
)==FALSE
)
1515 show_banner(mainview
, _("Export failed"));
1519 show_banner(mainview
, _("Exported"));
1524 g_object_unref(skpix
);
1526 else if (nd
->typ
== NODE_CHECKLIST
)
1528 show_banner(mainview
, _("Export of checklists not possible yet"));
1533 * callback from menu item
1534 * move selected node down (switch node with next sibling), don't change level of node
1536 void callback_move_down_node(GtkAction
* action
, gpointer data
)
1538 GtkTreeIter iter
, filterIter
;
1539 GtkTreeModel
*model
;
1541 MainView
*mainview
= (MainView
*) data
;
1542 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1544 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1545 gtk_tree_selection_get_selected(selection
, &model
, &filterIter
);
1547 model
= GTK_TREE_MODEL(mainview
->main_view_tree_store
);
1548 gtk_tree_model_filter_convert_iter_to_child_iter(
1549 GTK_TREE_MODEL_FILTER(mainview
->main_view_tree_filter
),
1553 GtkTreeIter old_iter
= iter
;/*save pointer to old iter, we will need it during swap nodes*/
1555 if (gtk_tree_model_iter_next(model
,&iter
)==FALSE
)/*get next node*/
1558 GtkTreeStore
*treeStore
= GTK_TREE_STORE(model
);
1559 gtk_tree_store_swap(treeStore
,&iter
,&old_iter
);
1561 mainview
->file_edited
= TRUE
;/*we have made changes , if required show "save changes?" dialog in future*/
1565 * callback from menu item
1566 * move selected node down (switch node with prev sibling), don't change level of node
1568 void callback_move_up_node(GtkAction
* action
, gpointer data
)
1570 GtkTreeIter iter
, filterIter
;
1571 GtkTreeModel
*model
;
1573 MainView
*mainview
= (MainView
*) data
;
1574 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1576 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1577 gtk_tree_selection_get_selected(selection
, &model
, &filterIter
);
1579 model
= GTK_TREE_MODEL(mainview
->main_view_tree_store
);
1580 gtk_tree_model_filter_convert_iter_to_child_iter(
1581 GTK_TREE_MODEL_FILTER(mainview
->main_view_tree_filter
),
1585 GtkTreeIter old_iter
=iter
;/*save pointer to old iter, we will need it during swap nodes*/
1587 if (tree_model_iter_prev(model
,&iter
)==FALSE
)/*get previous node*/
1590 GtkTreeStore
*treeStore
= GTK_TREE_STORE(model
);
1591 gtk_tree_store_swap(treeStore
,&old_iter
,&iter
);/*do move*/
1593 mainview
->file_edited
= TRUE
;/*we have made changes , if required show "save changes?" dialog in future*/
1598 * simple execute of sql command which is stored in sql_string[]
1600 gboolean
exec_command_on_db(MainView
*mainview
,char sql_string
[])
1602 sqlite3_stmt
*stmt
= NULL
;
1604 gboolean db_query_result
= FALSE
;
1606 int rc
= sqlite3_prepare (mainview
->db
, sql_string
, strlen(sql_string
), &stmt
, &dum
);
1609 maepad_warning("Error preparing DB update query: %s", sqlite3_errmsg(mainview
->db
));
1614 while (rc
== SQLITE_BUSY
) {
1615 rc
= sqlite3_step (stmt
);
1616 if (rc
== SQLITE_DONE
) {
1617 db_query_result
= TRUE
;
1620 else if(rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
) {
1621 maepad_warning("Error updating node: %s", sqlite3_errmsg(mainview
->db
));
1624 sqlite3_finalize(stmt
);
1630 * 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)
1632 gboolean
foreach_func_update_ord (GtkTreeModel
*model
,GtkTreePath
*path
,GtkTreeIter
*iter
, MainView
*mainview
)
1635 gtk_tree_model_get(model
, iter
, NODE_DATA
, &node
, -1);
1636 /*we need index of node on actual level*/
1637 gint index
=get_branch_node_index(path
);
1639 /*prepare to execute update command,and exec it*/
1640 char sql_command
[512];
1641 g_snprintf (sql_command
, sizeof(sql_command
), "UPDATE %s SET ord=\"%d\" WHERE nodeid=%d",datatable_tmpname
, index
, node
->sql3id
);
1642 exec_command_on_db(mainview
,sql_command
);
1644 /*we don't want break gtk_tree_model_foreach function,until we call this func on each node - so we return always FALSE*/
1649 * return id number of iter (id number which is used to identify in sql database of nodes)
1651 int get_node_id_on_tmp_db(GtkTreeModel
*model
,GtkTreeIter
*iter
)
1654 return 0;/*we got ROOT parent here*/
1657 gtk_tree_model_get(model
, iter
, NODE_DATA
, &node
, -1);
1658 return node
->sql3id
;
1662 * get index of node in current branch
1664 gint
get_branch_node_index(GtkTreePath
*path
)
1666 int depth
=gtk_tree_path_get_depth(path
);
1667 gint
*indicies
= gtk_tree_path_get_indices(path
);
1669 return indicies
[depth
-1];
1673 * similiar with gtk_tree_model_iter_next (), but opposite
1675 gboolean
tree_model_iter_prev(GtkTreeModel
*tree_model
,GtkTreeIter
*iter
)
1677 GtkTreePath
*path
= gtk_tree_model_get_path(tree_model
, iter
);
1680 fprintf(stderr
,"Error: path is null\n");
1684 if (gtk_tree_path_prev(path
)==FALSE
)
1687 gtk_tree_model_get_iter(tree_model
, iter
,path
);
1692 gboolean
ref2iter(GtkTreeModel
* model
, GtkTreeRowReference
* ref
, GtkTreeIter
* iter
)
1694 gboolean res
= FALSE
;
1695 GtkTreePath
*path
= gtk_tree_row_reference_get_path(ref
);
1697 if (gtk_tree_model_get_iter(model
, iter
, path
))
1701 gtk_tree_path_free(path
);
1705 GtkTreeRowReference
*iter2ref(GtkTreeModel
* model
, GtkTreeIter
* iter
)
1707 GtkTreeRowReference
*ref
;
1709 GtkTreePath
*path
= gtk_tree_model_get_path(model
, iter
);
1711 ref
= gtk_tree_row_reference_new(model
, path
);
1712 gtk_tree_path_free(path
);
1716 void move_nodes_up(GtkTreeModel
* model
, GtkTreeRowReference
* topnode
, GtkTreeRowReference
* newtop
)
1718 GtkTreeIter topiter
;
1720 if (ref2iter(model
, topnode
, &topiter
) == FALSE
)
1725 if (gtk_tree_model_iter_children(model
, &child
, &topiter
))
1727 GtkTreeRowReference
*ref
;
1728 GList
*rr_list
= NULL
, *node
;
1732 ref
= iter2ref(model
, &child
);
1733 rr_list
= g_list_append(rr_list
, ref
);
1735 while(gtk_tree_model_iter_next(model
, &child
));
1738 * got a reflist for all children
1741 for(node
= rr_list
; node
; node
= node
->next
)
1743 ref
= (GtkTreeRowReference
*) (node
->data
);
1744 if (ref2iter(model
, ref
, &child
))
1746 GtkTreeIter newtopiter
, newiter
;
1747 GtkTreeIter
*newtopiterptr
;
1749 if (ref2iter(model
, newtop
, &newtopiter
))
1750 newtopiterptr
= &newtopiter
;
1752 newtopiterptr
= NULL
;
1756 gtk_tree_model_get(model
, &child
, NODE_DATA
, &node
, -1);
1758 gtk_tree_store_append(GTK_TREE_STORE(model
), &newiter
, newtopiterptr
);
1759 gtk_tree_store_set(GTK_TREE_STORE(model
), &newiter
, NODE_NAME
, format_overview_name(node
, NULL
), NODE_PIXBUF
, node
->namepix
, NODE_DATA
, node
, -1);
1761 GtkTreeRowReference
*newref
= iter2ref(model
, &newiter
);
1763 move_nodes_up(model
, ref
, newref
);
1764 gtk_tree_row_reference_free(newref
);
1766 gtk_tree_store_remove(GTK_TREE_STORE(model
), &child
);
1768 gtk_tree_row_reference_free(ref
);
1771 g_list_free(rr_list
);
1776 void callback_delete_node_real(MainView
* mainview
)
1778 GtkTreeIter iter
, filterIter
;
1779 GtkTreeModel
*model
;
1781 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1783 if (!gtk_tree_selection_get_selected(selection
, &model
, &filterIter
))
1786 /* Convert filter iter to (backend) model iter */
1787 model
= GTK_TREE_MODEL(mainview
->main_view_tree_store
);
1788 gtk_tree_model_filter_convert_iter_to_child_iter(
1789 GTK_TREE_MODEL_FILTER(mainview
->main_view_tree_filter
),
1795 gtk_tree_model_get(model
, &iter
, NODE_DATA
, &nd
, -1);
1799 mainview
->file_edited
= TRUE
;
1801 unsigned int sql3id
= nd
->sql3id
;
1808 * if (nd->pix) g_object_unref(nd->pix);
1812 GtkTreeRowReference
*upref
= NULL
, *ref
= NULL
;
1814 GtkTreePath
*path
= gtk_tree_model_get_path(model
, &iter
);
1816 ref
= gtk_tree_row_reference_new(model
, path
);
1817 if (gtk_tree_path_up(path
))
1818 upref
= gtk_tree_row_reference_new(model
, path
);
1819 gtk_tree_path_free(path
);
1821 g_object_ref(mainview
->main_view_tree_filter
);
1822 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), NULL
);
1824 move_nodes_up(model
, ref
, upref
);
1826 if (ref2iter(model
, ref
, &iter
))
1830 g_snprintf(tq
, sizeof(tq
), "SELECT parent FROM %s WHERE nodeid=%d", datatable_tmpname
, sql3id
);
1831 sqlite3_stmt
*stmt
= NULL
;
1833 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt
, &dum
);
1834 unsigned int sql3parentid
= 0;
1838 maepad_warning("Error finding children for delete: %s", sqlite3_errmsg(mainview
->db
));
1843 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
1845 rc
= sqlite3_step(stmt
);
1846 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
1848 else if (rc
== SQLITE_ROW
)
1850 sql3parentid
= sqlite3_column_int(stmt
, 0);
1854 sqlite3_finalize(stmt
);
1856 g_snprintf(tq
, sizeof(tq
), "UPDATE %s SET parent=%d WHERE parent=%d;", datatable_tmpname
, sql3parentid
, sql3id
);
1857 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
1858 maepad_warning("Error moving nodes up one level");
1861 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s WHERE nodeid=%d;", datatable_tmpname
, sql3id
);
1862 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
1863 maepad_warning("Error deleting node");
1866 /* Delete all checklist items that do not have
1867 * a node anymore (= orphaned checklist items) */
1868 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s WHERE nodeid NOT IN (SELECT nodeid FROM %s);", checklisttable_tmpname
, datatable_tmpname
);
1869 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
1870 maepad_warning("Error deleting orphaned checklist items");
1874 gtk_tree_store_remove(GTK_TREE_STORE(model
), &iter
);
1877 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
),
1878 GTK_TREE_MODEL(mainview
->main_view_tree_filter
));
1879 g_object_unref(mainview
->main_view_tree_filter
);
1881 /* Carry out a refilter to show/hide remaining items */
1882 gtk_tree_model_filter_refilter(mainview
->main_view_tree_filter
);
1884 gtk_tree_row_reference_free(ref
);
1885 gtk_tree_row_reference_free(upref
);
1887 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview
->treeview
));
1891 void callback_edit_clear(GtkAction
* action
, gpointer data
)
1893 MainView
*mainview
= (MainView
*) data
;
1894 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1895 nodeData
*nd
= getSelectedNode(mainview
);
1897 if (show_confirmation(mainview
, _("Remove all contents of this memo?"))) {
1900 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview
->buffer
), "", 0);
1903 sketchwidget_clear(mainview
->sk
);
1905 case NODE_CHECKLIST
:
1906 gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
))));
1909 g_assert_not_reached();
1917 void callback_edit_cut(GtkAction
* action
, gpointer data
)
1919 MainView
*mainview
= (MainView
*) data
;
1920 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1922 nodeData
*nd
= getSelectedNode(mainview
);
1924 if (nd
->typ
== NODE_TEXT
)
1925 gtk_text_buffer_cut_clipboard(GTK_TEXT_BUFFER(mainview
->buffer
), mainview
->clipboard
, TRUE
);
1926 else if (nd
->typ
== NODE_SKETCH
)
1928 if (sketchwidget_cut(mainview
->sk
, mainview
->clipboard
)==FALSE
)
1929 show_banner(mainview
, _("Error cutting"));
1931 else if (nd
->typ
== NODE_CHECKLIST
)
1932 show_banner(mainview
, _("Unimplemented"));
1939 void callback_edit_copy(GtkAction
* action
, gpointer data
)
1941 MainView
*mainview
= (MainView
*) data
;
1942 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1944 nodeData
*nd
= getSelectedNode(mainview
);
1946 if (nd
->typ
== NODE_TEXT
)
1947 gtk_text_buffer_copy_clipboard(GTK_TEXT_BUFFER(mainview
->buffer
), mainview
->clipboard
);
1948 else if (nd
->typ
== NODE_SKETCH
)
1950 if (sketchwidget_copy(mainview
->sk
, mainview
->clipboard
)==FALSE
)
1951 show_banner(mainview
, _("Error copying"));
1953 else if (nd
->typ
== NODE_CHECKLIST
)
1955 /* Copy all selected entries as multiline text (1 line per entry) */
1956 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
1957 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
));
1959 gint selected_rows
= gtk_tree_selection_count_selected_rows(selection
);
1960 GList
* l
= gtk_tree_selection_get_selected_rows(selection
, NULL
);
1965 gchar
**entries
= g_malloc0(sizeof(gchar
*)*selected_rows
+1);
1966 gint entries_idx
= 0;
1970 GtkTreePath
*path
= cur
->data
;
1972 if (gtk_tree_model_get_iter(model
, &iter
, path
)) {
1973 gtk_tree_model_get(GTK_TREE_MODEL(model
), &iter
, CHECKNODE_TEXT
, &(entries
[entries_idx
++]), -1);
1975 gtk_tree_path_free(path
);
1981 str_data
= g_strjoinv("\n", entries
);
1982 g_strfreev(entries
);
1983 gtk_clipboard_set_text(mainview
->clipboard
, str_data
, -1);
1986 str_data
= g_strdup_printf(_("Copied %d entries"), selected_rows
);
1987 show_banner(mainview
, str_data
);
1996 void callback_edit_paste(GtkAction
* action
, gpointer data
)
1998 MainView
*mainview
= (MainView
*) data
;
1999 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2001 nodeData
*nd
= getSelectedNode(mainview
);
2003 if (nd
->typ
== NODE_TEXT
)
2004 gtk_text_buffer_paste_clipboard(GTK_TEXT_BUFFER(mainview
->buffer
), mainview
->clipboard
, NULL
, TRUE
);
2005 else if (nd
->typ
== NODE_SKETCH
)
2007 if (sketchwidget_paste(mainview
->sk
, mainview
->clipboard
)==FALSE
)
2008 show_banner(mainview
, _("Error pasting"));
2010 else if (nd
->typ
== NODE_CHECKLIST
) {
2011 /* Paste string from clipboard as new item */
2012 callback_checklist_paste(mainview
);
2015 mainview
->file_edited
= TRUE
;
2018 gint
cb_popup(GtkWidget
* widget
, GdkEvent
* event
)
2021 GdkEventButton
*event_button
;
2024 * The "widget" is the menu that was supplied when
2025 * * g_signal_connect_swapped() was called.
2027 menu
= GTK_MENU(widget
);
2028 event_button
= (GdkEventButton
*) event
;
2029 if (event
->type
== GDK_BUTTON_PRESS
&& event_button
->button
== 3)
2031 gtk_menu_popup(menu
, NULL
, NULL
, NULL
, NULL
, event_button
->button
, event_button
->time
);
2039 * on_node_menu_show(GtkWidget*, gpointer)
2041 * This is called when the longpress menu is shown in the main
2042 * window. In the Hildon UI mode that we are using, this does
2043 * not automatically select the touched node, so we need to set
2044 * the cursor here so that the functions in the menu operate on
2045 * the node that the user touched (i.e. the expected one).
2047 * The value of mainview->node_list_longpress_path has been set
2048 * by callback_treeview_button_press on the buttn press event.
2051 on_node_menu_show(GtkWidget
* nodemenu
, gpointer user_data
)
2053 MainView
* mainview
= (MainView
*)user_data
;
2055 if (mainview
->node_list_longpress_path
!= NULL
) {
2056 /* Set the cursor, but don't open the node view */
2057 mainview
->can_show_node_view
= FALSE
;
2058 gtk_tree_view_set_cursor(GTK_TREE_VIEW(mainview
->treeview
),
2059 mainview
->node_list_longpress_path
, NULL
, FALSE
);
2061 /* Dispose the path (we don't need it anymore) */
2062 gtk_tree_path_free(mainview
->node_list_longpress_path
);
2063 mainview
->node_list_longpress_path
= NULL
;
2070 gboolean
closefile(MainView
* mainview
)
2072 saveCurrentData(mainview
);
2074 if (mainview
->file_edited
)
2076 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
));
2077 gint answer
= gtk_dialog_run(GTK_DIALOG(hn
));
2078 gtk_widget_destroy(GTK_WIDGET(hn
));
2080 if (answer
== CONFRESP_CANCEL
)
2082 else if (answer
== CONFRESP_YES
)
2084 if (mainview
->file_name
== NULL
)
2086 mainview
->file_name
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, "maemopaddata", "db");
2088 write_buffer_to_file(mainview
);
2093 sqlite3_close(mainview
->db
);
2094 mainview
->db
= NULL
;
2098 gboolean
callback_file_close(GtkAction
* action
, gpointer data
)
2101 MainView
*mainview
= (MainView
*) data
;
2102 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2103 if (closefile(mainview
) == FALSE
)
2110 void callback_file_new_node(GtkAction
* action
, gpointer data
)
2112 MainView
*mainview
= (MainView
*) data
;
2113 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2115 nodeType typ
= NODE_SKETCH
;
2117 nodeData
*nd
= getSelectedNode(mainview
);
2122 new_node_dialog(typ
, mainview
);
2128 void callback_file_new(GtkAction
* action
, gpointer data
)
2130 MainView
*mainview
= (MainView
*) data
;
2131 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2133 gchar
*filename
= NULL
;
2135 filename
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, "memos", "db");
2136 if (filename
== NULL
) {
2140 if (closefile(mainview
) == FALSE
) {
2148 busy_enter(mainview
);
2152 rc
= sqlite3_open(filename
, &mainview
->db
);
2155 show_banner(mainview
, _("Cannot create database"));
2156 maepad_warning("Can't create database %s: %s", filename
, sqlite3_errmsg(mainview
->db
));
2160 sqlite3_exec(mainview
->db
, "PRAGMA synchronous = OFF;", NULL
, NULL
, NULL
);
2164 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", misctable_name
, misctable
);
2165 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
2167 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", datatable_name
, datatable
);
2168 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
2170 maepad_warning("Cannot create data table");
2171 show_banner(mainview
, _("Error creating data table"));
2175 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", checklisttable_name
, checklisttable
);
2176 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
2178 maepad_warning("Cannot create checklist table");
2179 show_banner(mainview
, _("Error creating checklist table"));
2184 sqlite3_close(mainview
->db
);
2185 mainview
->db
= NULL
;
2187 mainview
->file_name
= filename
;
2188 mainview
->file_edited
= FALSE
;
2189 read_file_to_buffer(mainview
);
2191 /*add a starter memo*/
2193 node
= g_malloc(sizeof(nodeData
));
2194 node
->typ
= NODE_SKETCH
;
2195 node
->name
= g_strdup(_("My first memo"));
2196 node
->namepix
= NULL
;
2200 add_new_node(node
, mainview
, TRUE
);
2201 /*gtk_paned_set_position(GTK_PANED(mainview->hpaned), 180);*/
2202 write_buffer_to_file(mainview
);
2205 busy_reset(mainview
);
2208 gboolean
reset_ctree(GtkTreeModel
* model
, GtkTreePath
* path
, GtkTreeIter
* iter
, gpointer data
)
2212 gtk_tree_model_get(model
, iter
, NODE_DATA
, &node
, -1);
2218 g_object_unref(node
->namepix
);
2221 gtk_tree_store_set(GTK_TREE_STORE(model
), iter
, NODE_DATA
, NULL
, -1);
2226 void new_file(MainView
* mainview
)
2228 busy_enter(mainview
);
2230 * clear buffer, filename and free buffer text
2232 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview
->buffer
), "", -1);
2233 mainview
->file_name
= NULL
;
2234 mainview
->file_edited
= FALSE
;
2235 mainview
->newnodedialog_createchild
= TRUE
;
2237 /* The filter is the "filtered down" list that's displayed in the
2238 * treeview and the model is the underlying real data */
2239 GtkTreeModel
*filter
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
));
2240 GtkTreeModel
*model
= GTK_TREE_MODEL(mainview
->main_view_tree_store
);
2242 g_object_ref(filter
);
2243 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), NULL
);
2245 gtk_tree_model_foreach(model
, (GtkTreeModelForeachFunc
) reset_ctree
, (gpointer
) mainview
);
2249 * gtk_tree_store_clear(GTK_TREE_STORE(model));
2251 GtkTreePath
*path
= gtk_tree_path_new_from_indices(0, -1);
2254 if (gtk_tree_model_get_iter(model
, &iter
, path
))
2258 gtk_tree_store_remove(GTK_TREE_STORE(model
), &iter
);
2260 while(gtk_tree_store_iter_is_valid(GTK_TREE_STORE(model
), &iter
));
2262 gtk_tree_path_free(path
);
2264 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), filter
);
2265 g_object_unref(filter
);
2267 busy_leave(mainview
);
2273 void callback_file_open(GtkAction
* action
, gpointer data
)
2275 gchar
*filename
= NULL
;
2276 MainView
*mainview
= (MainView
*) data
;
2277 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2279 filename
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_OPEN
, NULL
, NULL
);
2280 if (filename
== NULL
) {
2284 if (closefile(mainview
) == FALSE
) {
2288 open_file(filename
, mainview
);
2292 gboolean
open_file(gchar
* filename
, MainView
* mainview
)
2296 /* Don't open nodes when opening a file */
2297 mainview
->can_show_node_view
= FALSE
;
2299 busy_enter(mainview
);
2301 while(filename
!= NULL
)
2305 if (stat(filename
, &s
) == -1) break;
2307 mainview
->file_name
= g_strdup(filename
);
2308 gboolean res
= read_file_to_buffer(mainview
);
2312 g_free(mainview
->file_name
);
2313 mainview
->file_name
= NULL
;
2316 mainview
->file_edited
= FALSE
;
2321 busy_leave(mainview
);
2325 void callback_about_link(GtkAboutDialog
*about
, const gchar
*link
, gpointer data
)
2327 MainView
*mainview
= (MainView
*) data
;
2328 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2329 osso_rpc_run_with_defaults(mainview
->data
->osso
, "osso_browser", OSSO_BROWSER_OPEN_NEW_WINDOW_REQ
, NULL
,
2330 DBUS_TYPE_STRING
, link
, DBUS_TYPE_INVALID
);
2333 void callback_about(GtkAction
* action
, gpointer data
)
2335 MainView
* mainview
= (MainView
*)data
;
2336 he_about_dialog_present(mainview_get_dialog_parent(mainview
),
2337 NULL
/* auto-detect app name */,
2340 _("A node-based memory pad for Maemo"),
2341 _("(c) 2010 Thomas Perl"),
2342 "http://thp.io/2010/maepad/",
2343 "https://garage.maemo.org/tracker/?group_id=1291",
2344 "http://thp.io/2010/maepad/donate");
2347 gboolean
callback_live_search_refilter(HildonLiveSearch
*livesearch
, gpointer user_data
)
2349 MainView
*mainview
= (MainView
*)user_data
;
2350 /* Avoid showing the node view when filtering */
2351 mainview
->can_show_node_view
= FALSE
;
2358 void callback_file_save(GtkAction
* action
, gpointer data
)
2360 gchar
*filename
= NULL
;
2361 MainView
*mainview
= (MainView
*) data
;
2362 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2365 * check is we had a new file
2367 if (mainview
->file_name
!= NULL
)
2369 write_buffer_to_file(mainview
);
2373 filename
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, "maemopaddata", "db");
2375 * if we got a file name from chooser -> save file
2377 if (filename
!= NULL
)
2379 mainview
->file_name
= filename
;
2380 write_buffer_to_file(mainview
);
2381 mainview
->file_edited
= FALSE
;
2386 void callback_shapemenu(GtkAction
* action
, GtkWidget
* wid
)
2388 gint style
= GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(wid
)));
2389 MainView
* mainview
= gtk_object_get_data(GTK_OBJECT(wid
), "m");
2390 g_assert(mainview
!= NULL
);
2392 if (style
>= 0 && style
< SKETCHSHAPE_COUNT
) {
2393 /* We use the sketch widget's enum for available styles */
2394 sketchwidget_set_shape(mainview
->sk
, style
);
2396 /* Draw the correct indicator for the current shape */
2397 GtkWidget
* pix
= GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(wid
), "i"));
2398 g_assert(pix
!= NULL
);
2399 gtk_widget_show(pix
);
2400 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview
->shape_tb
), pix
);
2402 /* Fail. We shouldn't get here at all! */
2403 g_error("Invalid style ID from shape menu: %d", style
);
2409 void callback_eraser(GtkAction
* action
, MainView
* mainview
)
2411 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2413 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->eraser_tb
))) {
2414 /* Eraser on: Set pen color to white */
2415 GdkColor white
= { 0, 0xFFFF, 0xFFFF, 0xFFFF };
2416 sketchwidget_set_brushcolor(mainview
->sk
, white
);
2418 /* Eraser off: Set default color again (or black) */
2419 GdkColor black
= {0, 0, 0, 0};
2420 if (mainview
->current_color
== NULL
) {
2421 mainview
->current_color
= gdk_color_copy(&black
);
2423 sketchwidget_set_brushcolor(mainview
->sk
, *(mainview
->current_color
));
2427 void callback_menu(GtkAction
* action
, GtkWidget
* menu
)
2429 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, NULL
, NULL
, 0, GDK_CURRENT_TIME
);
2432 void callback_brushsizetb(GtkAction
* action
, MainView
*mainview
)
2434 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2435 callback_menu(NULL
, mainview
->brushsizemenu
);
2438 void callback_brushsize(GtkAction
* action
, GtkWidget
* wid
)
2440 int bsize
= (int)gtk_object_get_user_data(GTK_OBJECT(wid
));
2441 MainView
*mainview
= gtk_object_get_data(GTK_OBJECT(wid
), "m");
2443 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2445 sketchwidget_set_brushsize(mainview
->sk
, bsize
);
2447 GtkWidget
*pix
= gtk_object_get_data(GTK_OBJECT(wid
), "i");
2449 gtk_widget_show(pix
);
2450 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview
->brushsize_tb
), pix
);
2453 void callback_sketchlines(GtkAction
* action
, GtkWidget
* wid
)
2455 int style
= (int)gtk_object_get_user_data(GTK_OBJECT(wid
));
2456 MainView
*mainview
= gtk_object_get_data(GTK_OBJECT(wid
), "m");
2458 g_assert(mainview
!= NULL
);
2460 nodeData
*nd
= getSelectedNode(mainview
);
2461 gboolean doit
= FALSE
;
2463 if (nd
!= NULL
&& nd
->typ
== NODE_SKETCH
)
2465 nd
->flags
&= ~NODEFLAG_SKETCHLINES
;
2466 nd
->flags
&= ~NODEFLAG_SKETCHGRAPH
;
2467 /* sketchwidget_set_edited(mainview->sk, TRUE);*/ /*we call this on openfile, so this messes things up*/
2473 sketchwidget_set_backstyle(mainview
->sk
, SKETCHBACK_NONE
);
2475 else if (style
== 1)
2477 sketchwidget_set_backstyle(mainview
->sk
, SKETCHBACK_LINES
);
2479 nd
->flags
|= NODEFLAG_SKETCHLINES
;
2481 else if (style
== 2)
2483 sketchwidget_set_backstyle(mainview
->sk
, SKETCHBACK_GRAPH
);
2485 nd
->flags
|= NODEFLAG_SKETCHGRAPH
;
2488 GtkWidget
*pix
= gtk_object_get_data(GTK_OBJECT(wid
), "i");
2490 gtk_widget_show(pix
);
2491 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview
->sketchlines_tb
), pix
);
2494 void callback_color(GtkAction
* action
, MainView
* mainview
)
2496 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2498 nodeData
*nd
= getSelectedNode(mainview
);
2499 if (nd
== NULL
) return;
2501 HeSimpleColorDialog
* dialog
= HE_SIMPLE_COLOR_DIALOG(he_simple_color_dialog_new());
2502 gtk_window_set_transient_for(GTK_WINDOW(dialog
), mainview_get_dialog_parent(mainview
));
2504 if (mainview
->current_color
) {
2505 he_simple_color_dialog_set_color(dialog
, mainview
->current_color
);
2508 if (gtk_dialog_run(GTK_DIALOG(dialog
)) != GTK_RESPONSE_OK
) {
2509 gtk_widget_destroy(GTK_WIDGET(dialog
));
2513 gdk_color_free(mainview
->current_color
);
2514 mainview
->current_color
= he_simple_color_dialog_get_color(dialog
);
2516 gtk_widget_destroy(GTK_WIDGET(dialog
));
2520 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->eraser_tb
), FALSE
);
2521 sketchwidget_set_brushcolor(mainview
->sk
, *(mainview
->current_color
));
2523 case NODE_CHECKLIST
:
2524 { /* Put in a separate block to allow new local variables */
2525 GtkTreeModel
* model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
2526 GtkTreeSelection
* selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
));
2527 GList
* selected
= gtk_tree_selection_get_selected_rows(selection
, NULL
);
2529 gchar
* color_string
= g_strdup_printf("#%02x%02x%02x",
2530 mainview
->current_color
->red
>> 8,
2531 mainview
->current_color
->green
>> 8,
2532 mainview
->current_color
->blue
>> 8);
2534 GList
* cur
= selected
;
2535 while (cur
!= NULL
) {
2536 GtkTreePath
* path
= cur
->data
;
2538 if (gtk_tree_model_get_iter(model
, &iter
, path
)) {
2539 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_COLOR
, color_string
, -1);
2541 gtk_tree_path_free(path
);
2545 g_list_free(selected
);
2546 g_free(color_string
);
2550 g_assert_not_reached();
2554 void callback_color_invoke(GtkAction
* action
, gpointer data
)
2556 MainView
*mainview
= (MainView
*) data
;
2557 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2558 gtk_button_clicked(GTK_BUTTON(mainview
->colorbutton_tb
));
2563 void callback_pressure(GtkAction
* action
, MainView
*mainview
)
2565 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2567 nodeData
*nd
= getSelectedNode(mainview
);
2571 if (nd
->typ
!= NODE_SKETCH
)
2574 /* pressure sensitivity disabled for now...
2575 mainview->sk->pressuresensitivity=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(mainview->tools_pressure));*/
2579 void callback_wordwrap(GtkWidget
* widget
, gpointer user_data
)
2581 MainView
* mainview
= (MainView
*)user_data
;
2582 nodeData
* nd
= getSelectedNode(mainview
);
2583 GtkWrapMode wrap_mode
;
2585 if (nd
== NULL
|| nd
->typ
!= NODE_TEXT
) {
2589 if (hildon_check_button_get_active(HILDON_CHECK_BUTTON(mainview
->menu_button_wordwrap
))) {
2590 nd
->flags
|= NODEFLAG_WORDWRAP
;
2591 wrap_mode
= GTK_WRAP_WORD_CHAR
;
2593 nd
->flags
&= ~NODEFLAG_WORDWRAP
;
2594 wrap_mode
= GTK_WRAP_NONE
;
2597 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(mainview
->textview
), wrap_mode
);
2601 void callback_font(GtkAction
* action
, gpointer data
)
2603 MainView
*mainview
= (MainView
*) data
;
2604 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2606 nodeData
*nd
= getSelectedNode(mainview
);
2610 if (nd
->typ
!= NODE_TEXT
)
2613 HildonFontSelectionDialog
*dialog
= HILDON_FONT_SELECTION_DIALOG(hildon_font_selection_dialog_new(NULL
, NULL
));
2615 gboolean gotsel
=wp_text_buffer_has_selection(mainview
->buffer
);
2618 WPTextBufferFormat fmt
;
2619 wp_text_buffer_get_attributes(mainview
->buffer
, &fmt
, gotsel
);
2622 if (fmt
.text_position
==TEXT_POSITION_SUPERSCRIPT
) ri
=1;
2623 else if (fmt
.text_position
==TEXT_POSITION_SUBSCRIPT
) ri
=-1;
2625 g_object_set(G_OBJECT(dialog
),
2626 "family-set", fmt
.cs
.font
,
2627 "family", wp_get_font_name(fmt
.font
),
2628 "size-set", fmt
.cs
.font_size
,
2629 "size", wp_font_size
[fmt
.font_size
],
2630 "color-set", fmt
.cs
.color
,
2631 "color", &fmt
.color
,
2632 "bold-set", fmt
.cs
.bold
,
2634 "italic-set", fmt
.cs
.italic
,
2635 "italic", fmt
.italic
,
2636 "underline-set", fmt
.cs
.underline
,
2637 "underline", fmt
.underline
,
2638 "strikethrough-set", fmt
.cs
.strikethrough
,
2639 "strikethrough", fmt
.strikethrough
,
2640 "position-set", fmt
.cs
.text_position
,
2644 gtk_widget_show_all(GTK_WIDGET(dialog
));
2645 if (gtk_dialog_run(GTK_DIALOG(dialog
)) == GTK_RESPONSE_OK
)
2647 gboolean bold
, italic
, underline
, strikethrough
;
2648 gchar
*family
= NULL
;
2649 gint size
, position
;
2650 GdkColor
*color
=NULL
;
2651 gboolean set_family
, set_size
, set_bold
, set_italic
, set_underline
, set_strikethrough
, set_color
, set_position
;
2653 g_object_get(G_OBJECT(dialog
), "family", &family
, "size", &size
, "bold", &bold
, "italic", &italic
,
2654 "underline", &underline
, "strikethrough", &strikethrough
,
2655 "family-set", &set_family
, "size-set", &set_size
, "bold-set", &set_bold
, "italic-set", &set_italic
,
2656 "underline-set", &set_underline
, "strikethrough-set", &set_strikethrough
,
2657 "color", &color
, "color-set", &set_color
, "position", &position
, "position-set", &set_position
,
2660 wp_text_buffer_get_attributes(mainview
->buffer
, &fmt
, FALSE
);
2661 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;
2663 if (set_family
) { fmt
.font
=wp_get_font_index(family
, 1); fmt
.cs
.font
=1; }
2664 if (set_size
) { fmt
.font_size
=wp_get_font_size_index(size
, 16); fmt
.cs
.font_size
=1; }
2666 if (set_strikethrough
)
2668 fmt
.cs
.strikethrough
=1;
2669 fmt
.strikethrough
=strikethrough
;
2675 GLIB WARNING ** GLib-GObject - IA__g_object_set_valist: object class `GtkTextTag' has no property named `'
2678 fmt
.color
.pixel
=color
->pixel
;
2679 fmt
.color
.red
=color
->red
;
2680 fmt
.color
.green
=color
->green
;
2681 fmt
.color
.blue
=color
->blue
;
2686 if (position
==1) ri
=TEXT_POSITION_SUPERSCRIPT
;
2687 else if (position
==-1) ri
=TEXT_POSITION_SUBSCRIPT
;
2688 else ri
=TEXT_POSITION_NORMAL
;
2690 fmt
.cs
.text_position
=1;
2691 fmt
.text_position
=ri
;
2707 fmt
.underline
=underline
;
2710 wp_text_buffer_set_format(mainview
->buffer
, &fmt
);
2713 gtk_widget_destroy(GTK_WIDGET(dialog
));
2716 void callback_fontstyle(GtkAction
* action
, GtkWidget
* wid
)
2718 MainView
*mainview
= gtk_object_get_data(GTK_OBJECT(wid
), "m");
2719 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2721 nodeData
*nd
= getSelectedNode(mainview
);
2725 if (nd
->typ
== NODE_TEXT
)
2727 gboolean act
=gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(wid
));
2729 gint style
= (gint
)gtk_object_get_data(GTK_OBJECT(wid
), "s");
2730 wp_text_buffer_set_attribute(mainview
->buffer
, style
, (gpointer
)act
);
2732 else if (nd
->typ
== NODE_CHECKLIST
)
2734 gboolean act
=gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(wid
));
2735 gint style
= (gint
)gtk_object_get_data(GTK_OBJECT(wid
), "s");
2736 if (style
!=WPT_BOLD
&& style
!=WPT_STRIKE
&& style
!=WPT_LEFT
) return;
2738 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
2739 GList
* l
=gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
)), NULL
);
2741 gint styletoset_weight
=PANGO_WEIGHT_NORMAL
;
2742 gboolean styletoset_strike
=FALSE
;
2743 gboolean checkit
=FALSE
;
2745 if (style
==WPT_BOLD
&& act
==TRUE
) styletoset_weight
=PANGO_WEIGHT_BOLD
;
2746 else if (style
==WPT_STRIKE
&& act
==TRUE
) styletoset_strike
=TRUE
;
2747 else if (style
==WPT_LEFT
&& act
==TRUE
) checkit
=TRUE
;
2752 GtkTreePath
*path
=cur
->data
;
2755 if (gtk_tree_model_get_iter(model
, &iter
, path
))
2757 if (style
==WPT_BOLD
) gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_BOLD
, styletoset_weight
, -1);
2758 else if (style
==WPT_STRIKE
) gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_STRIKE
, styletoset_strike
, -1);
2759 else if (style
==WPT_LEFT
) {
2760 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_CHECKED
, checkit
, -1);
2762 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_ICON_NAME
, "widgets_tickmark_list", -1);
2764 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_ICON_NAME
, NULL
, -1);
2768 gtk_tree_path_free(path
);
2773 mainview
->checklist_edited
= TRUE
;
2778 callback_sharing(GtkWidget
* widget
, gpointer user_data
)
2780 MainView
* mainview
= (MainView
*)user_data
;
2781 nodeData
* nd
= getSelectedNode(mainview
);
2782 gchar
* filename
= g_strdup("/tmp/untitled.png");
2785 if (nd
== NULL
|| nd
->typ
!= NODE_SKETCH
) {
2786 show_banner(mainview
, _("Only sketches can be shared"));
2790 if (nd
->name
!= NULL
) {
2792 filename
= g_strdup_printf("/tmp/%s.png", nd
->name
);
2795 busy_enter(mainview
);
2796 GdkPixmap
* skpix
= sketchwidget_get_Pixmap(mainview
->sk
);
2797 GtkWidget
* skdr
= sketchwidget_get_drawingarea(mainview
->sk
);
2798 GdkPixbuf
* pixbuf
= gdk_pixbuf_get_from_drawable(NULL
,
2799 GDK_DRAWABLE(skpix
), NULL
, 0, 0, 0, 0,
2800 skdr
->allocation
.width
, skdr
->allocation
.height
);
2802 if (pixbuf
== NULL
) {
2803 show_banner(mainview
, _("Memo is empty"));
2807 if (!gdk_pixbuf_save(pixbuf
, filename
, "png", NULL
, NULL
)) {
2808 show_banner(mainview
, _("File export failed"));
2812 uri
= g_strdup_printf("file://%s", filename
);
2814 sharing_dialog_with_file(mainview
->data
->osso
,
2815 mainview_get_dialog_parent(mainview
),
2819 g_object_unref(skpix
);
2822 busy_leave(mainview
);
2826 callback_remove_checked(GtkWidget
* widget
, gpointer user_data
)
2828 MainView
* mainview
= (MainView
*)user_data
;
2829 nodeData
* nd
= getSelectedNode(mainview
);
2831 GtkTreeModel
* model
= NULL
;
2832 GList
* checked_items
= NULL
;
2833 gchar
* question
= NULL
;
2836 if (nd
== NULL
|| nd
->typ
!= NODE_CHECKLIST
) {
2840 /* Get a list of checked items */
2841 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
2842 if (!gtk_tree_model_get_iter_first(model
, &iter
)) {
2846 busy_enter(mainview
);
2848 gboolean checked
= FALSE
;
2849 gtk_tree_model_get(model
, &iter
, CHECKNODE_CHECKED
, &checked
, -1);
2852 GtkTreePath
* path
= gtk_tree_model_get_path(model
, &iter
);
2854 checked_items
= g_list_append(checked_items
,
2855 gtk_tree_row_reference_new(model
, path
));
2858 gtk_tree_path_free(path
);
2860 } while (gtk_tree_model_iter_next(model
, &iter
));
2861 busy_leave(mainview
);
2863 if (checked_items
== NULL
) {
2864 show_banner(mainview
, _("No checked items in checklist"));
2868 question
= g_strdup_printf(N_("Remove %d checked item?", "Remove %d checked items?", count
), count
);
2869 if (show_confirmation(mainview
, question
)) {
2870 /* Remove the checklist items from the list */
2871 checklist_remove_rowrefs(mainview
, checked_items
, TRUE
);
2873 /* Free the allocated row references + list */
2874 GList
* cur
= checked_items
;
2875 while (cur
!= NULL
) {
2876 GtkTreeRowReference
* rowref
= cur
->data
;
2877 gtk_tree_row_reference_free(rowref
);
2880 g_list_free(checked_items
);
2885 void callback_textbuffer_move(WPTextBuffer
*textbuffer
, MainView
*mainview
)
2887 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2890 gboolean gotsel=wp_text_buffer_has_selection(mainview->buffer);
2892 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), gotsel);
2893 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->italic_tb), gotsel);
2894 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->underline_tb), gotsel);
2895 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->bullet_tb), gotsel);
2897 WPTextBufferFormat fmt
;
2898 wp_text_buffer_get_attributes(mainview
->buffer
, &fmt
, FALSE
/*gotsel*/);
2900 g_signal_handlers_block_by_func(mainview
->bold_tb
, callback_fontstyle
, mainview
->bold_tb
);
2901 g_signal_handlers_block_by_func(mainview
->italic_tb
, callback_fontstyle
, mainview
->italic_tb
);
2902 g_signal_handlers_block_by_func(mainview
->underline_tb
, callback_fontstyle
, mainview
->underline_tb
);
2903 g_signal_handlers_block_by_func(mainview
->bullet_tb
, callback_fontstyle
, mainview
->bullet_tb
);
2905 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->bold_tb
), fmt
.bold
);
2906 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->italic_tb
), fmt
.italic
);
2907 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->underline_tb
), fmt
.underline
);
2908 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->bullet_tb
), fmt
.bullet
);
2910 g_signal_handlers_unblock_by_func(mainview
->bold_tb
, callback_fontstyle
, mainview
->bold_tb
);
2911 g_signal_handlers_unblock_by_func(mainview
->italic_tb
, callback_fontstyle
, mainview
->italic_tb
);
2912 g_signal_handlers_unblock_by_func(mainview
->underline_tb
, callback_fontstyle
, mainview
->underline_tb
);
2913 g_signal_handlers_unblock_by_func(mainview
->bullet_tb
, callback_fontstyle
, mainview
->bullet_tb
);
2916 gint
wp_savecallback(const gchar
*buffer
, GString
* gstr
)
2918 gstr
=g_string_append(gstr
, buffer
);
2922 void callback_undo(GtkAction
* action
, MainView
* mainview
)
2924 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2926 nodeData
*nd
= getSelectedNode(mainview
);
2928 if (nd
== NULL
) return;
2930 if (nd
->typ
== NODE_SKETCH
) sketchwidget_undo(mainview
->sk
);
2931 else if (nd
->typ
== NODE_TEXT
) wp_text_buffer_undo(mainview
->buffer
);
2934 void callback_redo(GtkAction
* action
, MainView
* mainview
)
2936 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2938 nodeData
*nd
= getSelectedNode(mainview
);
2940 if (nd
== NULL
) return;
2942 if (nd
->typ
== NODE_SKETCH
) sketchwidget_redo(mainview
->sk
);
2943 else if (nd
->typ
== NODE_TEXT
) wp_text_buffer_redo(mainview
->buffer
);
2946 void callback_undotoggle(gpointer widget
, gboolean st
, MainView
* mainview
)
2948 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2950 gtk_widget_set_sensitive(GTK_WIDGET(mainview
->undo_tb
), st
);
2953 void callback_redotoggle(gpointer widget
, gboolean st
, MainView
* mainview
)
2955 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2957 gtk_widget_set_sensitive(GTK_WIDGET(mainview
->redo_tb
), st
);
2960 gboolean
close_cb(GtkWidget
* widget
, GdkEventAny
* event
, MainView
* mainview
)
2962 callback_file_close(NULL
, mainview
);
2967 mainview_click_on_current_node(MainView
* mainview
)
2969 GtkTreeSelection
* selection
= NULL
;
2970 GtkTreeModel
* model
= NULL
;
2973 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
2974 if (gtk_tree_selection_get_selected(selection
, &model
, &iter
)) {
2975 GtkTreePath
* path
= gtk_tree_model_get_path(model
, &iter
);
2977 mainview
->can_show_node_view
= TRUE
;
2978 gtk_tree_view_set_cursor(GTK_TREE_VIEW(mainview
->treeview
),
2981 gtk_tree_path_free(path
);
2986 on_main_view_key_press(GtkWidget
* widget
, GdkEventKey
* event
, gpointer user_data
)
2988 MainView
* mainview
= (MainView
*)user_data
;
2989 gboolean result
= FALSE
;
2990 gboolean visible
= FALSE
;
2992 g_object_get(G_OBJECT(mainview
->main_view_live_search
),
2993 "visible", &visible
,
2997 /* Live search is active - only handle tree navigation */
2998 switch (event
->keyval
) {
3001 /* Open selected memo in node view */
3002 mainview_click_on_current_node(mainview
);
3006 /* Goto (=select) next memo */
3007 mainview
->can_show_node_view
= FALSE
;
3008 nodelist_select(mainview
, TREEVIEW_SELECT_NEXT
);
3012 /* Goto (=select) previous memo */
3013 mainview
->can_show_node_view
= FALSE
;
3014 nodelist_select(mainview
, TREEVIEW_SELECT_PREVIOUS
);
3021 /* Return early, so we don't handle normal input */
3025 switch (event
->keyval
) {
3030 /* Open selected memo in node view */
3031 mainview_click_on_current_node(mainview
);
3036 /* Save changes to file ("write buffer") */
3037 callback_file_save(NULL
, mainview
);
3041 /* Delete selected node (with confirmation) */
3042 callback_file_delete_node(NULL
, mainview
);
3047 /* Add new memo to list */
3048 callback_file_new_node(NULL
, mainview
);
3053 /* Replace (edit) name of selected memo */
3054 callback_file_rename_node(NULL
, mainview
);
3058 if (mainview
->main_view_prev_keyval
== GDK_g
) {
3059 /* Goto (=select) first memo */
3060 mainview
->can_show_node_view
= FALSE
;
3061 nodelist_select(mainview
, TREEVIEW_SELECT_FIRST
);
3063 /* Don't remember this key for the next keypress */
3064 mainview
->main_view_prev_keyval_reset
= TRUE
;
3070 /* Goto (=select) last memo */
3071 mainview
->can_show_node_view
= FALSE
;
3072 nodelist_select(mainview
, TREEVIEW_SELECT_LAST
);
3078 /* Goto (=select) next memo */
3079 mainview
->can_show_node_view
= FALSE
;
3080 nodelist_select(mainview
, TREEVIEW_SELECT_NEXT
);
3086 /* Goto (=select) previous memo */
3087 mainview
->can_show_node_view
= FALSE
;
3088 nodelist_select(mainview
, TREEVIEW_SELECT_PREVIOUS
);
3092 /* Start live search */
3093 gtk_widget_show(GTK_WIDGET(mainview
->main_view_live_search
));
3095 * TODO: It would be nice if we would focus the entry here
3096 * already, but the entry is private to HildonLiveSearch.
3098 * See Maemo bug 11458
3103 /* Ignore keypress (consume it!) */
3112 on_node_view_key_press(GtkWidget
* widget
, GdkEventKey
* event
, gpointer user_data
)
3114 MainView
* mainview
= (MainView
*)user_data
;
3115 nodeData
* nd
= getSelectedNode(mainview
);
3116 gboolean result
= FALSE
;
3122 switch (event
->keyval
) {
3125 if (nd
->typ
!= NODE_TEXT
) {
3126 /* Save changes to file ("write buffer") */
3127 callback_file_save(NULL
, mainview
);
3132 if (event
->state
& GDK_SHIFT_MASK
) {
3133 /* Remove current memo (with confirmation) */
3134 callback_file_delete_node(NULL
, mainview
);
3136 } else if (nd
->typ
== NODE_CHECKLIST
) {
3137 /* Remove current item (with confirmation) */
3138 callback_checklist_delete(NULL
, mainview
);
3140 } else if (nd
->typ
== NODE_SKETCH
) {
3141 /* Undo last sketch action */
3142 callback_undo(NULL
, mainview
);
3147 if (nd
->typ
== NODE_CHECKLIST
) {
3148 /* Toggle check of current item */
3149 maepad_toggle_gtk_toggle_tool_button(mainview
->check_tb
);
3151 } else if (nd
->typ
== NODE_SKETCH
) {
3152 /* Toggle eraser tool */
3153 maepad_toggle_gtk_toggle_tool_button(mainview
->eraser_tb
);
3159 if (nd
->typ
!= NODE_TEXT
) {
3160 /* Toggle fullscreen mode */
3161 callback_fullscreen(NULL
, mainview
);
3167 if (nd
->typ
!= NODE_TEXT
) {
3168 /* Hide node view, go to main view ("left") */
3169 gtk_widget_hide(GTK_WIDGET(mainview
->data
->node_view
));
3175 if (nd
->typ
== NODE_CHECKLIST
) {
3176 /* Prepend if using uppercase "o" */
3177 mainview
->checklist_prepend
= ((event
->keyval
) == GDK_O
);
3178 /* Insert new checklist item */
3179 callback_checklist_add(NULL
, mainview
);
3184 if (nd
->typ
== NODE_CHECKLIST
) {
3185 if (mainview
->node_view_prev_keyval
== GDK_d
) {
3186 /* Yank selected items, then remove them silently */
3187 callback_edit_copy(NULL
, mainview
);
3188 callback_checklist_delete_real(mainview
);
3189 show_banner(mainview
, _("Item yanked to clipboard"));
3191 /* Don't remember this key for the next keypress */
3192 mainview
->node_view_prev_keyval_reset
= TRUE
;
3199 if (nd
->typ
== NODE_CHECKLIST
) {
3200 if (mainview
->node_view_prev_keyval
== GDK_y
) {
3201 /* Non-destructive yanking of items */
3202 callback_edit_copy(NULL
, mainview
);
3203 show_banner(mainview
, _("Item yanked to clipboard"));
3205 /* Don't remember this key for the next keypress */
3206 mainview
->node_view_prev_keyval_reset
= TRUE
;
3214 if (nd
->typ
== NODE_CHECKLIST
) {
3215 /* Prepend if using uppercase "P" */
3216 mainview
->checklist_prepend
= ((event
->keyval
) == GDK_P
);
3217 /* Paste text in clipboard as items */
3218 callback_edit_paste(NULL
, mainview
);
3223 if (nd
->typ
== NODE_CHECKLIST
) {
3224 if (mainview
->node_view_prev_keyval
== GDK_g
) {
3225 /* Goto (=select) first item */
3226 checklist_select(mainview
, TREEVIEW_SELECT_FIRST
);
3228 /* Don't remember this key for the next keypress */
3229 mainview
->node_view_prev_keyval_reset
= TRUE
;
3236 if (nd
->typ
== NODE_CHECKLIST
) {
3237 /* Goto (=select) last item */
3238 checklist_select(mainview
, TREEVIEW_SELECT_LAST
);
3245 if (nd
->typ
== NODE_CHECKLIST
) {
3246 /* Goto (=select) next item */
3247 checklist_select(mainview
, TREEVIEW_SELECT_NEXT
);
3249 } else if (nd
->typ
== NODE_SKETCH
) {
3250 /* Undo last sketch operation */
3251 callback_undo(NULL
, mainview
);
3258 if (nd
->typ
== NODE_CHECKLIST
) {
3259 /* Goto (=select) previous item */
3260 checklist_select(mainview
, TREEVIEW_SELECT_PREVIOUS
);
3262 } else if (nd
->typ
== NODE_SKETCH
) {
3263 /* Redo last sketch operation */
3264 callback_redo(NULL
, mainview
);
3270 if (nd
->typ
== NODE_CHECKLIST
) {
3271 /* Append text to current node */
3272 checklist_edit_selected(mainview
, LINE_EDIT_MODE_APPEND
);
3280 if (nd
->typ
== NODE_CHECKLIST
) {
3281 /* Replace (edit) text of current node */
3282 checklist_edit_selected(mainview
, LINE_EDIT_MODE_DEFAULT
);
3288 if (nd
->typ
== NODE_CHECKLIST
) {
3289 /* Prepend (insert) text to current node */
3290 checklist_edit_selected(mainview
, LINE_EDIT_MODE_PREPEND
);
3303 on_main_view_key_release(GtkWidget
* widget
, GdkEventKey
* event
, gpointer user_data
)
3305 MainView
* mainview
= (MainView
*)user_data
;
3307 if (mainview
->main_view_prev_keyval_reset
) {
3308 /* Forget last-pressed key value */
3309 mainview
->main_view_prev_keyval
= GDK_VoidSymbol
;
3310 mainview
->main_view_prev_keyval_reset
= FALSE
;
3312 /* Remember last keyval for double-press bindings */
3313 mainview
->main_view_prev_keyval
= event
->keyval
;
3320 on_node_view_key_release(GtkWidget
* widget
, GdkEventKey
* event
, gpointer user_data
)
3322 MainView
* mainview
= (MainView
*)user_data
;
3324 if (mainview
->node_view_prev_keyval_reset
) {
3325 /* Forget last-pressed key value */
3326 mainview
->node_view_prev_keyval
= GDK_VoidSymbol
;
3327 mainview
->node_view_prev_keyval_reset
= FALSE
;
3329 /* Remember last keyval for double-press bindings */
3330 mainview
->node_view_prev_keyval
= event
->keyval
;
3337 on_checklist_longpress_timeout(gpointer user_data
)
3339 MainView
* mainview
= (MainView
*)user_data
;
3340 callback_checklist_edit(NULL
, mainview
);
3341 mainview
->checklist_longpress_source_id
= 0;
3346 on_checklist_button_press(GtkWidget
* widget
, GdkEventButton
* event
, gpointer user_data
)
3348 MainView
* mainview
= (MainView
*)user_data
;
3350 GtkTreeViewColumn
* column
;
3351 GtkTreeSelection
* selection
;
3353 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget
),
3360 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(widget
));
3362 if (gtk_tree_selection_path_is_selected(selection
, path
)) {
3363 if (column
== mainview
->checklist_column_check
) {
3364 /* Check column touched - toggle checklist item */
3365 maepad_toggle_gtk_toggle_tool_button(mainview
->check_tb
);
3366 } else if (column
== mainview
->checklist_column_text
) {
3367 mainview
->checklist_longpress_source_id
= g_timeout_add(
3368 CHECKLIST_LONGPRESS_EDIT_DELAY
,
3369 on_checklist_longpress_timeout
,
3375 gtk_tree_path_free(path
);
3382 checklist_abort_longpress(MainView
* mainview
)
3384 /* Abort the longpress action on the checklist */
3385 if (mainview
->checklist_longpress_source_id
!= 0) {
3386 g_source_remove(mainview
->checklist_longpress_source_id
);
3387 mainview
->checklist_longpress_source_id
= 0;
3392 on_checklist_button_release(GtkWidget
* widget
, GdkEventButton
* event
, gpointer user_data
)
3394 MainView
* mainview
= (MainView
*)user_data
;
3395 checklist_abort_longpress(mainview
);
3400 on_checklist_start_panning(HildonPannableArea
* area
, gpointer user_data
)
3402 MainView
* mainview
= (MainView
*)user_data
;
3403 checklist_abort_longpress(mainview
);
3407 void callback_fullscreen(GtkToolButton
* tool_button
, gpointer user_data
)
3409 MainView
* mainview
= (MainView
*)user_data
;
3410 gtk_window_fullscreen(GTK_WINDOW(mainview
->data
->node_view
));
3414 callback_sketch_button_toggled(HildonCheckButton
* button
, gpointer user_data
)
3416 MainView
* mainview
= (MainView
*)user_data
;
3417 gboolean active
= hildon_check_button_get_active(button
);
3419 if (GTK_WIDGET(button
) == GTK_WIDGET(mainview
->menu_button_square
)) {
3420 sketchwidget_set_shift(mainview
->sk
, active
);
3421 } else if (GTK_WIDGET(button
) == GTK_WIDGET(mainview
->menu_button_filled
)) {
3422 sketchwidget_set_fillmode(mainview
->sk
, active
);
3426 void callback_buffer_modified(GtkAction
* action
, gpointer data
)
3428 MainView
*mainview
= (MainView
*) data
;
3429 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
3431 mainview
->file_edited
= TRUE
;
3434 GtkTreeRowReference
*read_sqlite3_data(MainView
* mainview
, unsigned int parentid
, GtkTreeRowReference
* parenttree
, unsigned int selected
, GtkTreeStore
* model
)
3436 GtkTreeRowReference
*resref
= NULL
;
3440 g_snprintf(q
, sizeof(q
), "SELECT nodeid, bodytype, name, nameblob, lastmodified, flags FROM %s WHERE parent=%d ORDER BY ord", datatable_tmpname
, parentid
);
3442 sqlite3_stmt
*stmt
= NULL
;
3444 int rc
= sqlite3_prepare(mainview
->db
, q
, strlen(q
), &stmt
, &dum
);
3448 maepad_warning("Error reading SQLite3 data: %s", sqlite3_errmsg(mainview
->db
));
3453 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
3455 rc
= sqlite3_step(stmt
);
3456 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
3458 else if (rc
== SQLITE_ROW
)
3460 int nodeid
= sqlite3_column_int(stmt
, 0);
3461 int typ
= sqlite3_column_int(stmt
, 1);
3462 const unsigned char *name
= sqlite3_column_text(stmt
, 2);
3463 const unsigned char *nameblob
= sqlite3_column_text(stmt
, 3);
3464 int lastmod
= sqlite3_column_int(stmt
, 4);
3465 int flags
= sqlite3_column_int(stmt
, 5);
3467 if ((typ
!= NODE_TEXT
&& typ
!= NODE_SKETCH
&& typ
!= NODE_CHECKLIST
) || (name
== NULL
&& nameblob
== NULL
)) {
3468 maepad_warning("Unknown node type in database: %d (skipping)", typ
);
3472 nodeData
*node
= g_malloc(sizeof(nodeData
));
3474 node
->sql3id
= nodeid
;
3476 node
->flags
= flags
;
3478 node
->namepix
= NULL
;
3480 node
->name
= g_strdup((char *)name
);
3482 node
->name
= g_strdup(_("Unnamed memo"));
3484 /*if (nameblob != NULL)
3486 int blobsize = sqlite3_column_bytes(stmt, 3);
3488 GdkPixbufLoader *pl = gdk_pixbuf_loader_new_with_type("png", NULL);
3491 gdk_pixbuf_loader_write(pl, (guchar *) nameblob, blobsize, &err);
3494 fprintf(stderr, "Error loading nodename! %s\n", err->message);
3498 gdk_pixbuf_loader_close(pl, NULL);
3499 GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(pl);
3501 if (GDK_IS_PIXBUF(pixbuf))
3502 node->namepix = pixbuf;
3504 node
->lastMod
= lastmod
;
3506 GtkTreeIter parentiter
, newiter
;
3509 if (parenttree
!= NULL
)
3511 GtkTreePath
*pa
= gtk_tree_row_reference_get_path(parenttree
);
3513 gtk_tree_model_get_iter(GTK_TREE_MODEL(model
), &parentiter
, pa
);
3514 gtk_tree_path_free(pa
);
3518 gtk_tree_store_append(model
, &newiter
, par
);
3519 gtk_tree_store_set(model
, &newiter
, NODE_NAME
, format_overview_name(node
, NULL
), NODE_PIXBUF
, node
->namepix
, NODE_DATA
, node
, -1);
3521 GtkTreePath
*pa
= gtk_tree_model_get_path(GTK_TREE_MODEL(model
), &newiter
);
3523 GtkTreeRowReference
*newref
= gtk_tree_row_reference_new(GTK_TREE_MODEL(model
), pa
);
3525 if (selected
== nodeid
)
3528 gtk_tree_path_free(pa
);
3529 GtkTreeRowReference
*r
= read_sqlite3_data(mainview
, nodeid
, newref
, selected
,
3532 if (resref
!= newref
)
3533 gtk_tree_row_reference_free(newref
);
3540 gtk_tree_row_reference_free(r
); /*safeguard */
3546 sqlite3_finalize(stmt
);
3548 return (resref
); /*ref to supposed-to-be-selected treeitem */
3554 gboolean
read_file_to_buffer(MainView
* mainview
)
3558 g_assert(mainview
!= NULL
);
3559 gboolean res
= FALSE
;
3561 gchar
*filename
= mainview
->file_name
;
3564 mainview
->file_name
= filename
;
3565 mainview
->loading
=TRUE
;
3567 maepad_message("Reading database file: %s", filename
);
3570 sqlite3_stmt
*stmt
= NULL
;
3572 rc
= sqlite3_open(filename
, &mainview
->db
);
3577 maepad_warning("Cannot open database %s: %s", filename
, sqlite3_errmsg(mainview
->db
));
3581 sqlite3_exec(mainview
->db
, "PRAGMA synchronous = OFF;", NULL
, NULL
, NULL
);
3583 char *q
= "SELECT skey, sval FROM settings";
3586 rc
= sqlite3_prepare(mainview
->db
, q
, strlen(q
), &stmt
, &dum
);
3589 maepad_warning("Error reading settings: %s", sqlite3_errmsg(mainview
->db
));
3593 unsigned int selectedCard
= 0;
3594 unsigned int curDataVersion
= 0;
3595 unsigned int curChecklistVersion
= 0;
3598 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
3600 rc
= sqlite3_step(stmt
);
3601 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
3603 else if (rc
== SQLITE_ROW
)
3605 const gchar
* col_key
= (const gchar
*)sqlite3_column_text(stmt
, 0);
3606 const gchar
* col_val
= (const gchar
*)sqlite3_column_text(stmt
, 1);
3607 if (!strcmp(col_key
, "selectedNode"))
3609 gint tmp
= atoi((char *)col_val
);
3614 if (!strcmp(col_key
, "dataVersion"))
3616 gint tmp
= atoi((char *)col_val
);
3619 curDataVersion
= tmp
;
3621 if (!strcmp(col_key
, "checklistVersion"))
3623 gint tmp
= atoi((char *)col_val
);
3626 curChecklistVersion
= tmp
;
3628 if (!strcmp(col_key
, "newNodeDlgCreateChild"))
3630 gint tmp
= atoi((char *)col_val
);
3632 mainview
->newnodedialog_createchild
= TRUE
;
3634 mainview
->newnodedialog_createchild
= FALSE
;
3636 if (!strcmp(col_key
, "brushSize"))
3638 gint tmp
= atoi((char *)col_val
);
3639 if (tmp
>0) sk_set_brushsize(mainview
, tmp
);
3641 if (!strcmp(col_key
, "brushColor"))
3643 unsigned long tmp
= atol((char *)col_val
);
3646 c2
.red
= ((tmp
& 0xFF0000) >> 16) << 8;
3647 c2
.green
= ((tmp
& 0xFF00) >> 8) << 8;
3648 c2
.blue
= (tmp
& 0xFF) << 8;
3649 sketchwidget_set_brushcolor(mainview
->sk
, c2
);
3651 if (mainview
->current_color
!= NULL
) {
3652 gdk_color_free(mainview
->current_color
);
3654 mainview
->current_color
= gdk_color_copy(&c2
);
3659 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
)
3661 maepad_warning("Error reading data: %s", sqlite3_errmsg(mainview
->db
));
3666 sqlite3_finalize(stmt
);
3670 gboolean resback
= FALSE
;
3672 while(curDataVersion
< datatableversion
)
3674 if (curDataVersion
== 0)
3676 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_backupname
);
3677 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3679 g_snprintf(tq
, sizeof(tq
), "ALTER TABLE %s RENAME TO %s", datatable_name
, datatable_backupname
);
3680 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3681 maepad_warning("Error backing up table %s to %s", datatable_name
, datatable_backupname
);
3686 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", datatable_name
, datatable
);
3687 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3688 maepad_warning("Error creating table: %s", datatable_name
);
3691 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
);
3692 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3693 maepad_warning("Error copying data from %s to %s", datatable_name
, datatable_backupname
);
3697 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_backupname
);
3698 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3700 curDataVersion
= datatableversion
;
3705 if (curDataVersion
!= datatableversion
)
3707 maepad_warning("Data table version mismatch: %d <=> %d", curDataVersion
, datatableversion
);
3709 if (resback
== TRUE
)
3711 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_name
);
3712 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3713 g_snprintf(tq
, sizeof(tq
), "ALTER TABLE %s RENAME TO %s", datatable_backupname
, datatable_name
);
3714 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3721 while(curChecklistVersion
< checklisttableversion
)
3723 if (curChecklistVersion
== 0) /*no checklisttable at all*/
3725 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", checklisttable_name
, checklisttable
);
3726 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3727 maepad_warning("Error creating checklist table during schema upgrade");
3730 curChecklistVersion
= checklisttableversion
;
3736 GtkTreeStore
*filter
= GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
)));
3738 g_object_ref(filter
);
3739 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), NULL
);
3745 g_snprintf(tq
, sizeof(tq
), "CREATE%s TABLE %s%s", TEMPTABLE_KEYWORD
, datatable_tmpname
, datatable
);
3746 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3747 maepad_warning("Error creating temp table: %s", datatable_tmpname
);
3750 g_snprintf(tq
, sizeof(tq
), "CREATE INDEX %s_index ON %s %s", datatable_tmpname
, datatable_tmpname
, dataindex
);
3751 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3752 maepad_warning("Error creating temp index for %s", datatable_tmpname
);
3755 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", datatable_tmpname
, datatable_name
);
3756 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3757 maepad_warning("Error copying data from %s to %s", datatable_name
, datatable_tmpname
);
3761 g_snprintf(tq
, sizeof(tq
), "CREATE%s TABLE %s%s", TEMPTABLE_KEYWORD
, checklisttable_tmpname
, checklisttable
);
3762 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3763 maepad_warning("Error creating temp table: %s", checklisttable_tmpname
);
3766 g_snprintf(tq
, sizeof(tq
), "CREATE INDEX %s_index ON %s %s", checklisttable_tmpname
, checklisttable_tmpname
, checklistindex
);
3767 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3768 maepad_warning("Error creating temp index for %s", checklisttable_tmpname
);
3771 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", checklisttable_tmpname
, checklisttable_name
);
3772 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3773 maepad_warning("Error copying data from %s to %s", checklisttable_name
, checklisttable_tmpname
);
3779 read_sqlite3_data(mainview
, 0, NULL
, selectedCard
, mainview
->main_view_tree_store
);
3781 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), GTK_TREE_MODEL(filter
));
3782 g_object_unref(filter
);
3783 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview
->treeview
));
3790 sqlite3_finalize(stmt
);
3794 mainview
->loading
=FALSE
;
3802 void write_buffer_to_file(MainView
* mainview
)
3804 maepad_message("Writing database to file: %s", mainview
->file_name
);
3805 saveCurrentData(mainview
);
3807 /*update ord value in database for all nodes*/
3808 gtk_tree_model_foreach(GTK_TREE_MODEL(mainview
->main_view_tree_store
),
3809 (GtkTreeModelForeachFunc
)foreach_func_update_ord
, mainview
);
3811 busy_enter(mainview
);
3815 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", misctable_name
);
3816 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3818 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", misctable_name
, misctable
);
3819 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3823 if (mainview
->newnodedialog_createchild
== FALSE
)
3825 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('newNodeDlgCreateChild', '%d');", misctable_name
, nndcc
);
3826 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3828 nodeData
*node
= getSelectedNode(mainview
);
3832 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('selectedNode', '%d');", misctable_name
, node
->sql3id
);
3833 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3836 guint bsize
= sketchwidget_get_brushsize(mainview
->sk
);
3837 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('brushSize', '%d');", misctable_name
, bsize
);
3838 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3840 if (mainview
->current_color
== NULL
) {
3841 GdkColor color
= {0, 0, 0, 0};
3842 mainview
->current_color
= gdk_color_copy(&color
);
3844 unsigned long bcol
= ((mainview
->current_color
->red
>> 8) << 16) |
3845 ((mainview
->current_color
->green
>> 8) << 8) |
3846 ((mainview
->current_color
->blue
) >> 8);
3848 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('brushColor', '%lu');", misctable_name
, bcol
);
3849 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3851 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('dataVersion', '%d');", misctable_name
, datatableversion
);
3852 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3854 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('checklistVersion', '%d');", misctable_name
, checklisttableversion
);
3855 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3857 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_backupname
);
3858 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3859 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", datatable_backupname
, datatable
);
3860 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3862 maepad_warning("Error creating backup table: %s", datatable_backupname
);
3863 show_banner(mainview
, _("Error creating backup table"));
3865 busy_leave(mainview
);
3868 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", datatable_backupname
, datatable_name
);
3869 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3871 maepad_warning("Error backing up table %s to %s", datatable_name
, datatable_backupname
);
3872 show_banner(mainview
, _("Error creating backup table"));
3874 busy_leave(mainview
);
3877 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s", datatable_name
);
3878 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3880 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", datatable_name
, datatable_tmpname
);
3881 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3883 maepad_warning("Error saving table %s to %s", datatable_tmpname
, datatable_name
);
3884 show_banner(mainview
, _("Error saving table"));
3886 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s", datatable_name
);
3887 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3889 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", datatable_name
, datatable_backupname
);
3890 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3891 maepad_warning("Error restoring backup. Data lost :(");
3894 busy_leave(mainview
);
3898 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_backupname
);
3899 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3902 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", checklisttable_backupname
);
3903 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3904 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", checklisttable_backupname
, checklisttable
);
3905 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3907 maepad_warning("Error creating backup table: %s", checklisttable_backupname
);
3908 show_banner(mainview
, _("Error creating checklist backup table"));
3910 busy_leave(mainview
);
3914 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", checklisttable_backupname
, checklisttable_name
);
3915 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3917 maepad_warning("Error backing up table %s to %s", checklisttable_name
, checklisttable_backupname
);
3918 show_banner(mainview
, _("Error creating checklist backup table"));
3920 busy_leave(mainview
);
3923 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s", checklisttable_name
);
3924 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3926 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", checklisttable_name
, checklisttable_tmpname
);
3927 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3929 maepad_warning("Error saving table %s to %s", checklisttable_tmpname
, checklisttable_name
);
3930 show_banner(mainview
, _("Error saving checklist table"));
3932 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s", checklisttable_name
);
3933 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3935 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", checklisttable_name
, checklisttable_backupname
);
3936 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3937 maepad_warning("Error restoring backup. Data lost :(");
3939 busy_leave(mainview
);
3943 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", checklisttable_backupname
);
3944 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3946 mainview
->file_edited
= FALSE
;
3947 busy_leave(mainview
);
3948 show_banner(mainview
, _("Changes saved"));
3951 void callback_checklist_change(GtkTreeSelection
*selection
, MainView
*mainview
)
3955 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
3957 g_signal_handlers_block_by_func(mainview
->bold_tb
, callback_fontstyle
, mainview
->bold_tb
);
3958 g_signal_handlers_block_by_func(mainview
->strikethru_tb
, callback_fontstyle
, mainview
->strikethru_tb
);
3959 g_signal_handlers_block_by_func(mainview
->check_tb
, callback_fontstyle
, mainview
->check_tb
);
3961 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->bold_tb
), FALSE
);
3962 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->strikethru_tb
), FALSE
);
3963 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->check_tb
), FALSE
);
3965 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
3967 if (gtk_tree_model_get_iter_first(model
, &iter
)) {
3968 gtk_widget_show(mainview
->listscroll
);
3969 gtk_widget_hide(mainview
->checklist_empty_label
);
3971 gtk_widget_hide(mainview
->listscroll
);
3972 gtk_widget_show(mainview
->checklist_empty_label
);
3975 GList
* l
=gtk_tree_selection_get_selected_rows(selection
, NULL
);
3977 gboolean gotit
=FALSE
;
3982 GtkTreePath
*path
=cur
->data
;
3987 if (gtk_tree_model_get_iter(model
, &iter
, path
))
3989 gint styletoset_weight
;
3990 gboolean styletoset_strike
;
3993 gtk_tree_model_get(GTK_TREE_MODEL(model
), &iter
, CHECKNODE_BOLD
, &styletoset_weight
, CHECKNODE_STRIKE
, &styletoset_strike
, CHECKNODE_CHECKED
, &ischecked
, -1);
3994 if (styletoset_weight
==PANGO_WEIGHT_BOLD
) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->bold_tb
), TRUE
);
3995 if (styletoset_strike
==TRUE
) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->strikethru_tb
), TRUE
);
3996 if (ischecked
==TRUE
) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->check_tb
), TRUE
);
4000 gtk_tree_path_free(path
);
4006 g_signal_handlers_unblock_by_func(mainview
->bold_tb
, callback_fontstyle
, mainview
->bold_tb
);
4007 g_signal_handlers_unblock_by_func(mainview
->strikethru_tb
, callback_fontstyle
, mainview
->strikethru_tb
);
4008 g_signal_handlers_unblock_by_func(mainview
->check_tb
, callback_fontstyle
, mainview
->check_tb
);
4011 void callback_checklist_paste(MainView
*mainview
)
4013 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
4015 gboolean append
= FALSE
;
4018 gchar
*pasted_text
= gtk_clipboard_wait_for_text(mainview
->clipboard
);
4019 entries
= g_strsplit(pasted_text
, "\n", 0);
4021 GtkTreeSelection
*selection
;
4022 GtkTreeModel
*model
;
4023 GtkTreeIter current
, insert
;
4025 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
));
4026 if (gtk_tree_selection_get_selected(selection
, &model
, ¤t
)) {
4027 /* Insert after current (selected) item */
4031 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
4035 for (i
=0; i
<g_strv_length(entries
); i
++) {
4037 gtk_list_store_append(GTK_LIST_STORE(model
),
4040 if (i
== 0 && mainview
->checklist_prepend
) {
4041 gtk_list_store_insert_before(GTK_LIST_STORE(model
),
4045 gtk_list_store_insert_after(GTK_LIST_STORE(model
),
4052 gtk_list_store_set(GTK_LIST_STORE(model
),
4054 CHECKNODE_CHECKED
, FALSE
,
4055 CHECKNODE_TEXT
, entries
[i
],
4059 mainview
->checklist_edited
= TRUE
;
4061 g_strfreev(entries
);
4062 g_free(pasted_text
);
4065 void callback_checklist_add(GtkAction
*action
, MainView
*mainview
)
4067 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
4069 if (action
!= NULL
) {
4070 /* If coming from the tool button, always append */
4071 mainview
->checklist_prepend
= FALSE
;
4074 gchar
* text
= show_line_edit_dialog(mainview
, _("Add new checklist item"), _("Name:"), _("Add"), "");
4077 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
));
4078 GtkTreeModel
*model
;
4079 GtkTreeIter current
, insert
;
4081 if (gtk_tree_selection_get_selected(selection
, &model
, ¤t
)) {
4082 /* Something is selected */
4083 if (mainview
->checklist_prepend
) {
4084 /* User wants to insert before current item */
4085 gtk_list_store_insert_before(GTK_LIST_STORE(model
),
4089 /* User wants to insert after current item */
4090 gtk_list_store_insert_after(GTK_LIST_STORE(model
),
4095 /* Nothing is selected - just append at the end */
4096 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
4097 gtk_list_store_append(GTK_LIST_STORE(model
), &insert
);
4100 gtk_list_store_set(GTK_LIST_STORE(model
),
4102 CHECKNODE_CHECKED
, FALSE
,
4103 CHECKNODE_TEXT
, text
,
4106 GtkTreePath
*path
= gtk_tree_model_get_path(model
, &insert
);
4108 gtk_tree_view_set_cursor(GTK_TREE_VIEW(mainview
->listview
), path
, mainview
->checklist_column_text
, FALSE
);
4109 gtk_tree_path_free(path
);
4112 mainview
->checklist_edited
= TRUE
;
4117 checklist_edit_selected(MainView
* mainview
, LineEditMode mode
)
4119 GtkTreeSelection
* selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
));
4121 if (gtk_tree_selection_count_selected_rows(selection
) == 0) {
4122 show_banner(mainview
, _("Select items first"));
4126 GtkTreeModel
* model
;
4129 if (gtk_tree_selection_get_selected(selection
, &model
, &iter
)) {
4130 gchar
* old_text
= NULL
;
4131 gtk_tree_model_get(model
, &iter
, CHECKNODE_TEXT
, &old_text
, -1);
4133 gchar
* new_text
= show_line_edit_dialog_full(mainview
, _("Edit checklist item"), _("New name:"), _("Save"), old_text
, mode
);
4135 if (new_text
!= NULL
) {
4136 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_TEXT
, new_text
, -1);
4137 mainview
->checklist_edited
= TRUE
;
4145 void callback_checklist_edit(GtkAction
*action
, MainView
*mainview
)
4147 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
4148 checklist_edit_selected(mainview
, LINE_EDIT_MODE_DEFAULT
);
4151 void callback_checklist_delete(GtkAction
*action
, MainView
*mainview
)
4153 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
4155 if (gtk_tree_selection_count_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
)))==0) {
4156 show_banner(mainview
, _("Select items first"));
4160 if (show_confirmation(mainview
, _("Delete selected checklist item?"))) {
4161 callback_checklist_delete_real(mainview
);
4165 void callback_checklist_delete_real(MainView
* mainview
)
4167 GtkTreeModel
*model
=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
4168 GList
* l
=gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
)), NULL
);
4170 /* Select the item after the selection */
4171 checklist_select(mainview
, TREEVIEW_SELECT_NEXT
);
4173 GList
* rowrefs
=NULL
;
4177 GtkTreePath
*path
=cur
->data
;
4180 if (gtk_tree_model_get_iter(model
, &iter
, path
))
4182 GtkTreeRowReference
*rowref
= gtk_tree_row_reference_new(model
, path
);
4183 rowrefs
=g_list_append(rowrefs
, rowref
);
4185 gtk_tree_path_free(path
);
4189 checklist_remove_rowrefs(mainview
, rowrefs
, FALSE
);
4193 checklist_remove_rowrefs(MainView
* mainview
, GList
* rowrefs
, gboolean show_result
)
4195 GtkTreeModel
* model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
4196 GList
* cur
= rowrefs
;
4199 busy_enter(mainview
);
4202 GtkTreeRowReference
* rowref
= cur
->data
;
4203 GtkTreePath
* path
= gtk_tree_row_reference_get_path(rowref
);
4206 if (gtk_tree_model_get_iter(model
, &iter
, path
)) {
4207 gtk_list_store_remove(GTK_LIST_STORE(model
), &iter
);
4210 gtk_tree_path_free(path
);
4212 gtk_tree_row_reference_free(rowref
);
4215 g_list_free(rowrefs
);
4217 busy_leave(mainview
);
4219 if (count
&& show_result
) {
4220 gchar
* message
= g_strdup_printf(N_("%d item removed", "%d items removed", count
), count
);
4221 show_banner(mainview
, message
);
4225 mainview
->checklist_edited
= TRUE
;
4228 /* Private callback for show_confirmation() - handle keyboard input */
4230 on_confirmation_key_press_event(GtkWidget
* widget
, GdkEventKey
* event
, gpointer user_data
)
4232 GtkDialog
* dialog
= GTK_DIALOG(widget
);
4234 switch (event
->keyval
) {
4235 /* Positive response - Enter, Return or y */
4240 gtk_dialog_response(dialog
, GTK_RESPONSE_OK
);
4243 /* Negative response - Backspace, Escape or n */
4248 gtk_dialog_response(dialog
, GTK_RESPONSE_CANCEL
);
4251 /* Don't handle the rest of the keys */
4258 /* Ask the user for confirmation of a specific action */
4260 show_confirmation(MainView
* mainview
, gchar
* question
)
4262 GtkDialog
* dialog
= GTK_DIALOG(hildon_note_new_confirmation(
4263 GTK_WINDOW(mainview
->data
->main_view
), question
));
4264 gtk_window_set_transient_for(GTK_WINDOW(dialog
), mainview_get_dialog_parent(mainview
));
4265 g_signal_connect(G_OBJECT(dialog
), "key-press-event",
4266 G_CALLBACK(on_confirmation_key_press_event
), NULL
);
4268 gint response
= gtk_dialog_run(dialog
);
4269 gtk_widget_destroy(GTK_WIDGET(dialog
));
4271 return (response
== GTK_RESPONSE_OK
);
4274 /* Show a information banner to the user (non-modal) */
4276 show_banner(MainView
* mainview
, const gchar
* text
)
4278 hildon_banner_show_information(GTK_WIDGET(mainview_get_dialog_parent(mainview
)), NULL
, text
);
4283 gboolean can_close_window
;
4284 } LineEditDialogData
;
4286 /* Helper function to close line edit dialog on Backspace */
4288 line_edit_dialog_key_press(GtkWidget
* w
, GdkEventKey
* event
, gpointer user_data
)
4290 LineEditDialogData
* dialogdata
= (LineEditDialogData
*)user_data
;
4291 GtkEntry
* entry
= GTK_ENTRY(w
);
4293 if (event
->keyval
== GDK_BackSpace
&&
4294 dialogdata
->can_close_window
&&
4295 strcmp(gtk_entry_get_text(entry
), "") == 0) {
4296 gtk_dialog_response(GTK_DIALOG(dialogdata
->dialog
), GTK_RESPONSE_CANCEL
);
4303 /* Let the user enter or edit a line of text */
4305 show_line_edit_dialog_full(MainView
* mainview
, const gchar
* title
,
4306 const gchar
* label_text
, const gchar
* action
, const gchar
* text
,
4309 GtkWidget
* edit_dialog
;
4313 gchar
* result
= NULL
;
4314 LineEditDialogData dialogdata
;
4316 edit_dialog
= GTK_WIDGET(gtk_dialog_new());
4317 gtk_window_set_title(GTK_WINDOW(edit_dialog
), title
);
4318 gtk_window_set_transient_for(GTK_WINDOW(edit_dialog
), mainview_get_dialog_parent(mainview
));
4320 label
= GTK_WIDGET(gtk_label_new(label_text
));
4322 entry
= hildon_entry_new(HILDON_SIZE_AUTO
);
4323 gtk_entry_set_text(GTK_ENTRY(entry
), text
);
4324 gtk_entry_set_activates_default(GTK_ENTRY(entry
), TRUE
);
4326 case LINE_EDIT_MODE_DEFAULT
:
4327 gtk_editable_select_region(GTK_EDITABLE(entry
), 0, -1);
4329 case LINE_EDIT_MODE_APPEND
:
4330 gtk_editable_select_region(GTK_EDITABLE(entry
), -1, -1);
4332 case LINE_EDIT_MODE_PREPEND
:
4333 gtk_editable_select_region(GTK_EDITABLE(entry
), 0, 0);
4339 gtk_dialog_add_button(GTK_DIALOG(edit_dialog
), action
, GTK_RESPONSE_OK
);
4340 gtk_dialog_set_default_response(GTK_DIALOG(edit_dialog
), GTK_RESPONSE_OK
);
4342 dialogdata
.dialog
= edit_dialog
;
4343 dialogdata
.can_close_window
= (strcmp(text
, "") == 0);
4344 g_signal_connect(G_OBJECT(entry
), "key-press-event", G_CALLBACK(line_edit_dialog_key_press
), &dialogdata
);
4346 hbox
= GTK_WIDGET(gtk_hbox_new(FALSE
, 10));
4348 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(edit_dialog
))), GTK_WIDGET(hbox
));
4349 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
4350 gtk_box_pack_start(GTK_BOX(hbox
), entry
, TRUE
, TRUE
, 0);
4352 gtk_widget_show_all(GTK_WIDGET(hbox
));
4355 if (gtk_dialog_run(GTK_DIALOG(edit_dialog
)) == GTK_RESPONSE_OK
) {
4356 result
= g_strdup(gtk_entry_get_text(GTK_ENTRY(entry
)));
4357 if (strcmp(result
, "") != 0) {
4360 show_banner(mainview
, _("Please enter a non-empty text"));
4370 gtk_widget_destroy(GTK_WIDGET(edit_dialog
));
4375 treeview_scroll_to_selection(MainView
* mainview
, TreeViewType type
)
4377 GtkTreeView
* treeview
= NULL
;
4378 HildonPannableArea
* pannable_area
= NULL
;
4379 GtkTreeModel
* model
= NULL
;
4380 GtkTreeSelection
* selection
= NULL
;
4381 GtkTreePath
* path
= NULL
;
4387 case TREEVIEW_MAINVIEW
:
4388 treeview
= GTK_TREE_VIEW(mainview
->treeview
);
4389 pannable_area
= HILDON_PANNABLE_AREA(mainview
->scrolledtree
);
4391 case TREEVIEW_CHECKLIST
:
4392 treeview
= GTK_TREE_VIEW(mainview
->listview
);
4393 pannable_area
= HILDON_PANNABLE_AREA(mainview
->listscroll
);
4396 g_assert_not_reached();
4400 /* Let the view scroll so that the selected item is visible */
4401 selection
= gtk_tree_view_get_selection(treeview
);
4402 if (gtk_tree_selection_get_selected(selection
, &model
, &iter
)) {
4403 path
= gtk_tree_model_get_path(model
, &iter
);
4405 gtk_tree_view_get_background_area(treeview
, path
, NULL
, &rect
);
4406 gtk_tree_view_convert_bin_window_to_tree_coords(treeview
,
4407 0, rect
.y
, NULL
, &y
);
4408 hildon_pannable_area_scroll_to(pannable_area
, -1, y
);
4410 gtk_tree_path_free(path
);
4415 checklist_scroll_to_selection(gpointer user_data
)
4417 MainView
* mainview
= (MainView
*)user_data
;
4418 treeview_scroll_to_selection(mainview
, TREEVIEW_CHECKLIST
);
4423 nodelist_scroll_to_selection(gpointer user_data
)
4425 MainView
* mainview
= (MainView
*)user_data
;
4426 treeview_scroll_to_selection(mainview
, TREEVIEW_MAINVIEW
);
4431 checklist_select(MainView
* mainview
, TreeviewSelectType type
)
4433 GtkTreeModel
* model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
4434 GtkTreeSelection
* selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
));
4440 case TREEVIEW_SELECT_FIRST
:
4441 if (gtk_tree_model_get_iter_first(model
, &iter
)) {
4442 path
= gtk_tree_model_get_path(model
, &iter
);
4443 gtk_tree_selection_select_path(selection
, path
);
4444 gtk_tree_path_free(path
);
4447 case TREEVIEW_SELECT_LAST
:
4448 if (gtk_tree_model_get_iter_first(model
, &iter
)) {
4451 } while (gtk_tree_model_iter_next(model
, &iter
));
4452 path
= gtk_tree_model_get_path(model
, &last
);
4453 gtk_tree_selection_select_path(selection
, path
);
4454 gtk_tree_path_free(path
);
4457 case TREEVIEW_SELECT_PREVIOUS
:
4458 if (gtk_tree_selection_get_selected(selection
, NULL
, &iter
)) {
4459 path
= gtk_tree_model_get_path(model
, &iter
);
4460 if (gtk_tree_path_prev(path
)) {
4461 gtk_tree_selection_select_path(selection
, path
);
4463 gtk_tree_path_free(path
);
4466 case TREEVIEW_SELECT_NEXT
:
4467 if (gtk_tree_selection_get_selected(selection
, NULL
, &iter
)) {
4468 path
= gtk_tree_model_get_path(model
, &iter
);
4469 gtk_tree_path_next(path
);
4470 gtk_tree_selection_select_path(selection
, path
);
4471 gtk_tree_path_free(path
);
4475 g_assert_not_reached();
4479 checklist_scroll_to_selection(mainview
);
4482 * This is a workaround: The HildonPannableArea does not seem to
4483 * scroll to the right position (especially when going to the first
4484 * or last item in the list), so we simply scroll again after 500ms.
4486 g_timeout_add(500, checklist_scroll_to_selection
, mainview
);
4490 nodelist_select(MainView
* mainview
, TreeviewSelectType type
)
4492 GtkTreeView
* treeview
= GTK_TREE_VIEW(mainview
->treeview
);
4493 GtkTreeModel
* model
= gtk_tree_view_get_model(treeview
);
4494 GtkTreeSelection
* selection
= gtk_tree_view_get_selection(treeview
);
4501 case TREEVIEW_SELECT_FIRST
:
4502 if (gtk_tree_model_get_iter_first(model
, &iter
)) {
4503 path
= gtk_tree_model_get_path(model
, &iter
);
4504 gtk_tree_selection_select_path(selection
, path
);
4505 gtk_tree_path_free(path
);
4508 case TREEVIEW_SELECT_LAST
:
4509 if (gtk_tree_model_get_iter_first(model
, &iter
)) {
4512 if (gtk_tree_model_iter_children(model
, &child
, &last
)) {
4515 } while (gtk_tree_model_iter_next(model
, &child
));
4517 } while (gtk_tree_model_iter_next(model
, &iter
));
4518 path
= gtk_tree_model_get_path(model
, &last
);
4519 gtk_tree_selection_select_path(selection
, path
);
4520 gtk_tree_path_free(path
);
4523 case TREEVIEW_SELECT_PREVIOUS
:
4524 if (gtk_tree_selection_get_selected(selection
, NULL
, &iter
)) {
4525 path
= gtk_tree_model_get_path(model
, &iter
);
4526 if (gtk_tree_path_prev(path
)) {
4527 gtk_tree_selection_select_path(selection
, path
);
4528 } else if (gtk_tree_path_up(path
)) {
4529 gtk_tree_selection_select_path(selection
, path
);
4531 gtk_tree_path_free(path
);
4533 nodelist_select(mainview
, TREEVIEW_SELECT_FIRST
);
4536 case TREEVIEW_SELECT_NEXT
:
4537 if (gtk_tree_selection_get_selected(selection
, NULL
, &iter
)) {
4538 path
= gtk_tree_model_get_path(model
, &iter
);
4539 gtk_tree_path_down(path
);
4540 while (!gtk_tree_model_get_iter(model
, &iter
, path
)) {
4541 /* Child item does not exist - bubble up to next item */
4542 gtk_tree_path_up(path
);
4543 gtk_tree_path_next(path
);
4545 if (gtk_tree_path_get_depth(path
) == 0) {
4546 /* avoid infinite loops */
4551 if (gtk_tree_model_get_iter(model
, &iter
, path
)) {
4552 gtk_tree_selection_select_path(selection
, path
);
4555 gtk_tree_path_free(path
);
4557 nodelist_select(mainview
, TREEVIEW_SELECT_FIRST
);
4561 g_assert_not_reached();
4565 nodelist_scroll_to_selection(mainview
);
4568 * This is a workaround: The HildonPannableArea does not seem to
4569 * scroll to the right position (especially when going to the first
4570 * or last item in the list), so we simply scroll again after 500ms.
4572 g_timeout_add(500, nodelist_scroll_to_selection
, mainview
);
4577 format_overview_name(nodeData
*nd
, const gchar
*name
)
4580 gchar
*font_desc
, *font_color
;
4590 font_desc
= he_get_logical_font_desc("SmallSystemFont");
4591 font_color
= he_get_logical_font_color("SecondaryTextColor");
4593 tmp
= g_markup_printf_escaped("%s\n<span font_desc=\"%s\" foreground=\"%s\">%s</span>",
4597 (nd
->typ
==NODE_CHECKLIST
)?(_("Checklist")):
4598 ((nd
->typ
==NODE_TEXT
)?(_("Rich text")):
4599 ((nd
->typ
==NODE_SKETCH
)?(_("Sketch")):(""))));
4609 he_get_logical_font_desc(const gchar
*name
)
4611 GtkSettings
*settings
= gtk_settings_get_default();
4612 GtkStyle
*style
= gtk_rc_get_style_by_paths(settings
,
4613 name
, NULL
, G_TYPE_NONE
);
4615 return pango_font_description_to_string(style
->font_desc
);
4619 he_get_logical_font_color(const gchar
*name
)
4622 GtkSettings
*settings
= gtk_settings_get_default();
4623 GtkStyle
*style
= gtk_rc_get_style_by_paths(settings
,
4624 "GtkButton", "osso-logical-colors", GTK_TYPE_BUTTON
);
4626 if (gtk_style_lookup_color(style
, name
, &color
)) {
4627 return gdk_color_to_string(&color
);