2 * This file is part of MaePad
3 * Copyright (c) 2010 Thomas Perl <thp@thpinfo.com>
4 * http://thpinfo.com/2010/maepad/
7 * Copyright (c) 2006-2008 Kemal Hadimli
8 * Copyright (c) 2008 Thomas Perl
10 * This software is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public License
12 * as published by the Free Software Foundation; either version 2.1 of
13 * the License, or (at your option) any later version.
15 * This software is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this software; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 #include <ui/callbacks.h>
28 #include <ui/interface.h>
30 #include <gdk/gdkkeysyms.h>
36 * strlen needed from string.h
39 #include <sys/types.h>
47 #include <hildon/hildon.h>
48 #include <hildon/hildon-banner.h>
49 #include <hildon/hildon-note.h>
50 #include <hildon/hildon-font-selection-dialog.h>
51 #include <tablet-browser-interface.h>
53 #include <libgnomevfs/gnome-vfs.h>
55 #include <sharingdialog/sharing-dialog.h>
57 #include "sketchwidget.h"
59 #include "../he/he-about-dialog.h"
60 #include "../he/he-simple-color-dialog.h"
63 * "Busy" status handling
65 * Use "busy_reset" to reset the busy status (turn off)
66 * Use "busy_enter" when starting time-consuming processing
67 * Use "busy_leave" when processing has been finished
75 /* Don't use this directly, but make use of the macros defined below */
76 void set_busy(MainView
* mainview
, SetBusyType update
);
78 #define busy_reset(mainview) set_busy(mainview, BUSY_RESET)
79 #define busy_enter(mainview) set_busy(mainview, BUSY_INCREMENT)
80 #define busy_leave(mainview) set_busy(mainview, BUSY_DECREMENT)
86 void checklist_abort_longpress(MainView
* mainview
);
87 gboolean
read_file_to_buffer(MainView
* mainview
);
88 void write_buffer_to_file(MainView
* mainview
);
89 void new_node_dialog(nodeType typ
, MainView
* mainview
);
90 gboolean
foreach_func_update_ord (GtkTreeModel
*model
,GtkTreePath
*path
,GtkTreeIter
*iter
, MainView
*mainview
);
91 void move_nodes_up(GtkTreeModel
* model
, GtkTreeRowReference
* topnode
, GtkTreeRowReference
* newtop
);
92 GtkTreeRowReference
*iter2ref(GtkTreeModel
* model
, GtkTreeIter
* iter
);
93 gboolean
exec_command_on_db(MainView
*mainview
,char sql_string
[]);
94 int get_node_id_on_tmp_db(GtkTreeModel
*model
,GtkTreeIter
*iter
);
95 gint
get_branch_node_index(GtkTreePath
*path
);
96 gboolean
move_node(MainView
*mainview
,GtkTreeIter
*new_parent
,GtkTreeIter
*item_to_move
,GtkTreeIter
*item_befor
);
97 gboolean
tree_model_iter_prev(GtkTreeModel
*tree_model
,GtkTreeIter
*iter
);
98 gboolean
show_confirmation(MainView
* mainview
, gchar
* question
);
102 gboolean
callback_node_view_window_state(GtkWidget
* window
,
103 GdkEventWindowState
* event
, gpointer user_data
)
105 MainView
* mainview
= (MainView
*)user_data
;
106 GtkWidget
* sketch_scroll
= NULL
;
107 nodeData
*nd
= getSelectedNode(mainview
);
109 if (mainview
->toolbar
== NULL
|| mainview
->sk
== NULL
) {
113 sketch_scroll
= GTK_WIDGET(sketchwidget_get_mainwidget(mainview
->sk
));
115 if (event
->changed_mask
& GDK_WINDOW_STATE_FULLSCREEN
) {
116 if (event
->new_window_state
& GDK_WINDOW_STATE_FULLSCREEN
) {
117 gtk_widget_hide(mainview
->toolbar
);
118 gtk_scrolled_window_set_policy(
119 GTK_SCROLLED_WINDOW(sketch_scroll
),
122 if (nd
->typ
== NODE_CHECKLIST
) {
123 /* Enable portrait mode when entering fullscreen */
124 hildon_gtk_window_set_portrait_flags(mainview_get_dialog_parent(mainview
),
125 HILDON_PORTRAIT_MODE_REQUEST
| HILDON_PORTRAIT_MODE_SUPPORT
);
128 gtk_widget_show(mainview
->toolbar
);
129 gtk_scrolled_window_set_policy(
130 GTK_SCROLLED_WINDOW(sketch_scroll
),
131 GTK_POLICY_AUTOMATIC
,
132 GTK_POLICY_AUTOMATIC
);
133 if (nd
->typ
== NODE_CHECKLIST
) {
134 /* Disable portrait mode when leaving fullscreen */
135 hildon_gtk_window_set_portrait_flags(mainview_get_dialog_parent(mainview
),
136 HILDON_PORTRAIT_MODE_SUPPORT
);
144 void set_busy(MainView
* mainview
, SetBusyType update
)
148 mainview
->busyrefcount
= 0;
151 mainview
->busyrefcount
++;
154 if (mainview
->busyrefcount
> 0) {
155 mainview
->busyrefcount
--;
159 g_assert_not_reached();
163 hildon_gtk_window_set_progress_indicator(GTK_WINDOW(mainview
->data
->main_view
), (mainview
->busyrefcount
> 0));
164 hildon_gtk_window_set_progress_indicator(GTK_WINDOW(mainview
->data
->node_view
), (mainview
->busyrefcount
> 0));
167 void prepareUIforNodeChange(MainView
* mainview
, nodeType typ
)
169 gtk_widget_set_sensitive(GTK_WIDGET(mainview
->undo_tb
), TRUE
);
170 gtk_widget_set_sensitive(GTK_WIDGET(mainview
->redo_tb
), TRUE
);
172 if (typ
== NODE_TEXT
)
174 gtk_widget_show(GTK_WIDGET(mainview
->font_tb
));
175 gtk_widget_show(GTK_WIDGET(mainview
->bold_tb
));
176 gtk_widget_show(GTK_WIDGET(mainview
->italic_tb
));
177 gtk_widget_show(GTK_WIDGET(mainview
->underline_tb
));
178 gtk_widget_show(GTK_WIDGET(mainview
->bullet_tb
));
179 gtk_widget_show(mainview
->tools_font
);
183 gtk_widget_hide(GTK_WIDGET(mainview
->font_tb
));
184 gtk_widget_hide(GTK_WIDGET(mainview
->bold_tb
));
185 gtk_widget_hide(GTK_WIDGET(mainview
->italic_tb
));
186 gtk_widget_hide(GTK_WIDGET(mainview
->underline_tb
));
187 gtk_widget_hide(GTK_WIDGET(mainview
->bullet_tb
));
188 gtk_widget_hide(mainview
->tools_font
);
191 if (typ
== NODE_SKETCH
)
193 /* gtk_widget_show(GTK_WIDGET(mainview->colorbutton_tb));*/
194 gtk_widget_show(GTK_WIDGET(mainview
->eraser_tb
));
195 gtk_widget_show(GTK_WIDGET(mainview
->brushsize_tb
));
196 gtk_widget_show(GTK_WIDGET(mainview
->sketchlines_tb
));
197 gtk_widget_show(GTK_WIDGET(mainview
->shape_tb
));
198 gtk_widget_show(GTK_WIDGET(mainview
->sharing_tb
));
199 gtk_widget_show(mainview
->tools_color
);
200 gtk_widget_show(mainview
->tools_brushsize
);
201 gtk_widget_show(mainview
->tools_pagestyle
);
202 gtk_widget_show(mainview
->tools_shape
);
203 gtk_widget_show(mainview
->tools_pressure
);
207 /* gtk_widget_hide(GTK_WIDGET(mainview->colorbutton_tb));*/
208 gtk_widget_hide(GTK_WIDGET(mainview
->eraser_tb
));
209 gtk_widget_hide(GTK_WIDGET(mainview
->brushsize_tb
));
210 gtk_widget_hide(GTK_WIDGET(mainview
->sketchlines_tb
));
211 gtk_widget_hide(GTK_WIDGET(mainview
->shape_tb
));
212 gtk_widget_hide(GTK_WIDGET(mainview
->sharing_tb
));
213 gtk_widget_hide(mainview
->tools_color
);
214 gtk_widget_hide(mainview
->tools_brushsize
);
215 gtk_widget_hide(mainview
->tools_pagestyle
);
216 gtk_widget_hide(mainview
->tools_shape
);
217 gtk_widget_hide(mainview
->tools_pressure
);
220 if (typ
== NODE_CHECKLIST
)
222 gtk_widget_show(GTK_WIDGET(mainview
->bold_tb
));
223 gtk_widget_show(GTK_WIDGET(mainview
->strikethru_tb
));
224 gtk_widget_show(GTK_WIDGET(mainview
->check_tb
));
225 gtk_widget_show(GTK_WIDGET(mainview
->checkadd_tb
));
226 gtk_widget_show(GTK_WIDGET(mainview
->checkedit_tb
));
227 gtk_widget_show(GTK_WIDGET(mainview
->checkdel_tb
));
228 gtk_widget_hide(GTK_WIDGET(mainview
->undo_tb
));
229 gtk_widget_hide(GTK_WIDGET(mainview
->redo_tb
));
233 gtk_widget_hide(GTK_WIDGET(mainview
->strikethru_tb
));
234 gtk_widget_hide(GTK_WIDGET(mainview
->check_tb
));
235 gtk_widget_hide(GTK_WIDGET(mainview
->checkadd_tb
));
236 gtk_widget_hide(GTK_WIDGET(mainview
->checkedit_tb
));
237 gtk_widget_hide(GTK_WIDGET(mainview
->checkdel_tb
));
238 gtk_widget_show(GTK_WIDGET(mainview
->undo_tb
));
239 gtk_widget_show(GTK_WIDGET(mainview
->redo_tb
));
242 if (typ
== NODE_TEXT
)
244 gtk_widget_hide(GTK_WIDGET(mainview
->colorbutton_tb
));
245 gtk_widget_hide(sketchwidget_get_mainwidget(mainview
->sk
));
246 gtk_widget_hide(mainview
->listscroll
);
247 gtk_widget_show(GTK_WIDGET(mainview
->scrolledwindow
));
248 gtk_widget_show(mainview
->tools_item
);
250 else if (typ
== NODE_SKETCH
)
252 gtk_widget_show(GTK_WIDGET(mainview
->colorbutton_tb
));
253 gtk_widget_hide(GTK_WIDGET(mainview
->scrolledwindow
));
254 gtk_widget_hide(mainview
->listscroll
);
255 gtk_widget_show(sketchwidget_get_mainwidget(mainview
->sk
));
256 gtk_widget_show(mainview
->tools_item
);
258 else if (typ
== NODE_CHECKLIST
)
260 gtk_widget_show(GTK_WIDGET(mainview
->colorbutton_tb
));
261 gtk_widget_hide(GTK_WIDGET(mainview
->scrolledwindow
));
262 gtk_widget_hide(sketchwidget_get_mainwidget(mainview
->sk
));
263 gtk_widget_hide(mainview
->tools_item
);
264 gtk_widget_show(mainview
->listscroll
);
268 gtk_widget_hide(GTK_WIDGET(mainview
->colorbutton_tb
));
269 gtk_widget_hide(GTK_WIDGET(mainview
->scrolledwindow
));
270 gtk_widget_hide(sketchwidget_get_mainwidget(mainview
->sk
));
271 gtk_widget_hide(mainview
->tools_item
);
272 gtk_widget_hide(mainview
->listscroll
);
276 nodeData
*getSelectedNode(MainView
* mainview
)
283 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
285 if (!gtk_tree_selection_get_selected(selection
, &model
, &iter
))
288 gtk_tree_model_get(model
, &iter
, NODE_DATA
, &nd
, -1);
293 void saveCurrentData(MainView
* mainview
)
295 nodeData
*selnode
= getSelectedNode(mainview
);
296 saveDataToNode(mainview
, selnode
);
299 void saveDataToNode(MainView
* mainview
, nodeData
*selnode
)
305 (selnode
->typ
== NODE_SKETCH
&& sketchwidget_get_edited(mainview
->sk
) == FALSE
) ||
306 (selnode
->typ
== NODE_TEXT
&& wp_text_buffer_is_modified(mainview
->buffer
)==FALSE
) ||
307 (selnode
->typ
== NODE_CHECKLIST
&& mainview
->checklist_edited
==FALSE
)
310 maepad_message("node not edited, not saving");
314 mainview
->file_edited
= TRUE
;
316 busy_enter(mainview
);
317 maepad_debug("saveDataToNode working");
319 gboolean goterr
= TRUE
;
320 gchar
*textdata
= NULL
;
321 GdkPixbuf
*pixbuf
= NULL
;
322 gchar
*sketchdata
= NULL
;
326 if (selnode
->typ
== NODE_TEXT
)
329 GtkTextIter start
, end
;
330 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(mainview
->buffer
), &start
, &end
);
331 textdata
= gtk_text_buffer_serialize_rich_text(GTK_TEXT_BUFFER(mainview
->buffer
), &start
, &end
, &datalen
);
334 GString
*gstr
=g_string_sized_new(4096);
335 wp_text_buffer_save_document(mainview
->buffer
, (WPDocumentSaveCallback
)(wp_savecallback
), gstr
);
338 textdata
=g_string_free(gstr
, FALSE
);
340 /* 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);*/
341 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
);
343 else if (selnode
->typ
== NODE_SKETCH
)
346 GdkPixmap
*skpix
= sketchwidget_get_Pixmap(mainview
->sk
);
347 GtkWidget
*skdr
= sketchwidget_get_drawingarea(mainview
->sk
);
349 pixbuf
= gdk_pixbuf_get_from_drawable(NULL
, GDK_DRAWABLE(skpix
), NULL
, 0, 0, 0, 0, skdr
->allocation
.width
, skdr
->allocation
.height
);
352 maepad_warning("error saving: pixbuf is null");
357 GdkPixbuf
*pixbuf2
= sketchwidget_trim_image(pixbuf
, skdr
->allocation
.width
, skdr
->allocation
.height
, &w
, &h
, FALSE
);
361 if (gdk_pixbuf_save_to_buffer(pixbuf2
, &sketchdata
, &datalen
, "png", &err
, NULL
) == FALSE
)
365 maepad_warning("Error saving sketch: %s", err
->message
);
368 gdk_pixbuf_unref(pixbuf2
);
371 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
);
372 maepad_debug("storing sketch in db: %d bytes", datalen
);
373 if (skpix
&& G_IS_OBJECT(skpix
)) g_object_unref(skpix
);
375 else if (selnode
->typ
== NODE_CHECKLIST
)
377 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
);
382 sqlite3_stmt
*stmt
= NULL
;
384 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt
, &dum
);
388 maepad_warning("Error updating: %s", sqlite3_errmsg(mainview
->db
));
391 if (selnode
->typ
== NODE_TEXT
)
392 sqlite3_bind_text(stmt
, 1, textdata
, datalen
, /*strlen(textdata),*/ SQLITE_TRANSIENT
);
393 else if (selnode
->typ
== NODE_SKETCH
)
394 sqlite3_bind_blob(stmt
, 1, sketchdata
, datalen
, SQLITE_TRANSIENT
);
397 while(rc
== SQLITE_BUSY
)
399 rc
= sqlite3_step(stmt
);
400 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
403 sqlite3_finalize(stmt
);
405 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
)
407 maepad_warning("Error saving node: %s", sqlite3_errmsg(mainview
->db
));
411 if (selnode
->typ
== NODE_TEXT
)
412 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(mainview
->buffer
), FALSE
);
413 else if (selnode
->typ
== NODE_SKETCH
)
414 sketchwidget_set_edited(mainview
->sk
, FALSE
);
415 else if (selnode
->typ
== NODE_CHECKLIST
)
416 mainview
->checklist_edited
= FALSE
;
421 while(goterr
==FALSE
&& selnode
->typ
== NODE_CHECKLIST
)
423 GtkTreeModel
*model
=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
426 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s WHERE nodeid=%d", checklisttable_tmpname
, selnode
->sql3id
);
427 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
430 if (gtk_tree_model_get_iter_first(model
, &iter
)==FALSE
) break;
434 gint styletoset_weight
;
435 gboolean styletoset_strike
;
441 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);
444 if (color
!=NULL
&& strcmp(color
, "(null)")!=0 && gdk_color_parse(color
, &tmpcol
))
446 col
=((tmpcol
.red
>>8)<<16)|((tmpcol
.green
>>8)<<8)|(tmpcol
.blue
>>8);
450 if (ischecked
) style
|=CHECKSTYLE_CHECKED
;
451 if (styletoset_weight
==PANGO_WEIGHT_BOLD
) style
|=CHECKSTYLE_BOLD
;
452 if (styletoset_strike
) style
|=CHECKSTYLE_STRIKE
;
454 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s (nodeid, name, style, color, ord) VALUES(%d, ?, %d, %lu, 0)", checklisttable_tmpname
, selnode
->sql3id
, style
, col
);
455 sqlite3_stmt
*stmt
= NULL
;
457 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt
, &dum
);
462 maepad_warning("Error while saving checklist: %s", sqlite3_errmsg(mainview
->db
));
465 sqlite3_bind_text(stmt
, 1, text
, strlen(text
), SQLITE_TRANSIENT
);
468 while(rc
== SQLITE_BUSY
)
470 rc
= sqlite3_step(stmt
);
471 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
474 sqlite3_finalize(stmt
);
476 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
)
479 maepad_warning("Error while saving checklist (2): %s", sqlite3_errmsg(mainview
->db
));
485 }while(gtk_tree_model_iter_next(model
, &iter
)==TRUE
);
496 show_banner(mainview
, _("Error saving memo"));
498 busy_leave(mainview
);
501 gboolean
callback_treeview_button_press(GtkTreeView
* treeview
, GdkEventButton
* event
, gpointer user_data
)
503 MainView
* mainview
= (MainView
*)user_data
;
506 if (mainview
->node_list_longpress_path
!= NULL
) {
507 /* Forget old, remembered tree path for longpress */
508 gtk_tree_path_free(mainview
->node_list_longpress_path
);
509 mainview
->node_list_longpress_path
= NULL
;
512 if (gtk_tree_view_get_path_at_pos(treeview
,
513 event
->x
, event
->y
, &path
, NULL
, NULL
, NULL
)) {
515 * Save this path in case we open the longpress menu to
516 * set the cursor in the treeview to the correct row.
518 * See on_node_menu_show() on how this is further used.
520 mainview
->node_list_longpress_path
= path
;
523 mainview
->can_show_node_view
= TRUE
;
528 void callback_treeview_celldatafunc(GtkTreeViewColumn
* tree_column
, GtkCellRenderer
* cell
, GtkTreeModel
* tree_model
, GtkTreeIter
* iter
, gpointer data
)
530 MainView
*mainview
= ( MainView
* ) data
;
531 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
535 gtk_tree_model_get(tree_model
, iter
, NODE_DATA
, &nd
, -1);
539 if (nd
->namepix
== NULL
)
541 g_object_set(cell
, "visible", FALSE
, NULL
);
545 g_object_set(cell
, "visible", TRUE
, NULL
);
546 g_object_set(cell
, "width", SKETCHNODE_RX
, NULL
);
547 g_object_set(cell
, "height", SKETCHNODE_RY
, NULL
);
551 void callback_treeview_change(GtkTreeSelection
* selection
, gpointer data
)
553 MainView
*mainview
= (MainView
*) data
;
554 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
556 nodeData
*nd
= getSelectedNode(mainview
);
558 gchar
* nodeName
= _("View memo");
560 if (nd
!= NULL
&& nd
->name
!= NULL
) {
564 /* Show node view with selected node */
565 gtk_window_set_title(GTK_WINDOW(mainview
->data
->node_view
),
568 if (mainview
->can_show_node_view
) {
569 gtk_widget_show(GTK_WIDGET(mainview
->data
->node_view
));
572 /* Make sure we don't accidentally collapse any nodes */
573 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview
->treeview
));
576 if (mainview
->cansel_time
>0 && mainview
->cansel_time
+1.0<tm
) mainview
->cansel_node
=NULL
;
580 if (mainview
->cansel_node
!=NULL
)
582 maepad_debug("[SELLOGIC] saving %d to unselect all nodes", (mainview
->cansel_node
)->sql3id
);
583 saveDataToNode(mainview
, (mainview
->cansel_node
));
584 mainview
->cansel_node
=NULL
;
589 if (mainview
->cansel_node
!=NULL
)
591 if (nd
->sql3id
== (mainview
->cansel_node
)->sql3id
)
593 mainview
->cansel_node
=NULL
;
594 maepad_debug("[SELLOGIC] doubly selected %d, doing nothing", nd
->sql3id
);
595 prepareUIforNodeChange(mainview
, nd
->typ
);
600 maepad_debug("[SELLOGIC] saving %d to load new node", (mainview
->cansel_node
)->sql3id
);
601 saveDataToNode(mainview
, (mainview
->cansel_node
));
602 mainview
->cansel_node
=NULL
;
606 if (nd
== NULL
) return;
608 busy_enter(mainview
);
610 gboolean goterr
= TRUE
;
611 char *textdata
= NULL
;
613 int blobsize
= 0, textsize
= 0;
617 g_snprintf(tq
, sizeof(tq
), "SELECT bodytype, body, bodyblob, flags FROM %s WHERE nodeid=%d", datatable_tmpname
, nd
->sql3id
);
618 sqlite3_stmt
*stmt
= NULL
;
620 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt
, &dum
);
624 maepad_warning("Error reading (1): %s", sqlite3_errmsg(mainview
->db
));
629 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
631 rc
= sqlite3_step(stmt
);
632 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
634 else if (rc
== SQLITE_ROW
)
636 nd
->typ
= sqlite3_column_int(stmt
, 0);
637 nd
->flags
= sqlite3_column_int(stmt
, 3);
639 prepareUIforNodeChange(mainview
, nd
->typ
);
640 if (nd
->typ
== NODE_TEXT
)
642 gboolean file_edited_backup
= mainview
->file_edited
;
644 blobsize
= sqlite3_column_bytes(stmt
, 2);
645 blob
= (char *)sqlite3_column_blob(stmt
, 2);
647 textdata
= (char *)sqlite3_column_text(stmt
, 1);
648 textsize
= sqlite3_column_bytes(stmt
, 1);
650 /* gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), "", -1);*/
651 wp_text_buffer_reset_buffer(mainview
->buffer
, TRUE
);
653 gboolean richtext
=FALSE
;
658 gboolean oldway
=FALSE
;
662 strncpy(tst
, blob
, 8);
664 if (strcmp(tst
, "RICHTEXT")==0) oldway
=TRUE
;
670 gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(mainview
->buffer
), &iter
);
671 gtk_text_buffer_deserialize_rich_text(GTK_TEXT_BUFFER(mainview
->buffer
), &iter
, blob
, blobsize
, TRUE
, &err
);
685 wp_text_buffer_load_document_begin(mainview
->buffer
, TRUE
);
686 wp_text_buffer_load_document_write(mainview
->buffer
, blob
, blobsize
);
687 wp_text_buffer_load_document_end(mainview
->buffer
);
691 if (richtext
==FALSE
&& !(textdata
== NULL
|| g_utf8_validate(textdata
, textsize
, NULL
) == FALSE
))
693 /* gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview->buffer), textdata, textsize);*/
694 wp_text_buffer_load_document_begin(mainview
->buffer
, FALSE
);
695 wp_text_buffer_load_document_write(mainview
->buffer
, textdata
, textsize
);
696 wp_text_buffer_load_document_end(mainview
->buffer
);
699 wp_text_buffer_enable_rich_text(mainview
->buffer
, TRUE
);
700 hildon_check_button_set_active(HILDON_CHECK_BUTTON(mainview
->menu_button_wordwrap
),
701 (nd
->flags
& NODEFLAG_WORDWRAP
)?(TRUE
):(FALSE
));
703 gtk_text_buffer_set_modified(GTK_TEXT_BUFFER(mainview
->buffer
), FALSE
); /*we probably don't need this*/
705 callback_undotoggle((gpointer
)mainview
->buffer
, FALSE
, mainview
); /*we need these*/
706 callback_redotoggle((gpointer
)mainview
->buffer
, FALSE
, mainview
);
708 if (file_edited_backup
==FALSE
) mainview
->file_edited
=FALSE
; /*textview changed event toggles this?*/
711 else if (nd
->typ
== NODE_SKETCH
)
713 sketchwidget_wipe_undo(mainview
->sk
);
715 /* Disable squared and filled mode when opening a sketch */
716 hildon_check_button_set_active(HILDON_CHECK_BUTTON(mainview
->menu_button_square
), FALSE
);
717 hildon_check_button_set_active(HILDON_CHECK_BUTTON(mainview
->menu_button_filled
), FALSE
);
719 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->shapemenuitems
[1]), TRUE
);
720 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->shapemenuitems
[0]), TRUE
);
722 blobsize
= sqlite3_column_bytes(stmt
, 2);
723 blob
= (char *)sqlite3_column_blob(stmt
, 2);
724 gboolean clear
= TRUE
;
730 maepad_debug("blob size: %d", blobsize
);
731 GdkPixbufLoader
*pl
= gdk_pixbuf_loader_new_with_type("png", NULL
);
734 gdk_pixbuf_loader_write(pl
, (guchar
*) blob
, blobsize
, &err
);
737 maepad_warning("Error loading sketch: %s", err
->message
);
741 gdk_pixbuf_loader_close(pl
, NULL
);
742 GdkPixbuf
*pixbuf
= gdk_pixbuf_loader_get_pixbuf(pl
);
744 if (GDK_IS_PIXBUF(pixbuf
))
746 GtkWidget
*skdr
= sketchwidget_get_drawingarea(mainview
->sk
);
747 GtkPixmap
*skpix
= (GtkPixmap
*) sketchwidget_get_Pixmap(mainview
->sk
);
749 int w
=gdk_pixbuf_get_width(pixbuf
);
750 int h
=gdk_pixbuf_get_height(pixbuf
);
751 if (w
!=skdr
->allocation
.width
|| h
!=skdr
->allocation
.height
)
753 if (w
>skdr
->allocation
.width
) w
=skdr
->allocation
.width
;
754 if (h
>skdr
->allocation
.height
) h
=skdr
->allocation
.height
;
755 sketchwidget_clear_real(mainview
->sk
);
757 gdk_draw_pixbuf(GDK_DRAWABLE(skpix
), NULL
, pixbuf
, 0, 0, 0, 0, w
, h
, GDK_RGB_DITHER_NONE
, 0, 0);
762 if (skpix
&& G_IS_OBJECT(skpix
)) g_object_unref(skpix
);
766 maepad_warning("Error loading pixbuf");
772 maepad_message("Clearing sketch widget");
773 sketchwidget_clear_real(mainview
->sk
);
775 gtk_widget_queue_draw(sketchwidget_get_drawingarea(mainview
->sk
));
777 else if (nd
->typ
== NODE_CHECKLIST
)
779 mainview
->checklist_edited
= FALSE
;
780 GtkTreeModel
*model
=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
782 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->listview
), NULL
);
783 gtk_list_store_clear(GTK_LIST_STORE(model
));
785 g_snprintf(tq
, sizeof(tq
), "SELECT name, style, color FROM %s WHERE nodeid=%d ORDER BY ord, idx", checklisttable_tmpname
, nd
->sql3id
);
786 sqlite3_stmt
*stmt2
= NULL
;
788 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt2
, &dum
);
791 maepad_warning("Error reading checklist (1) %s", sqlite3_errmsg(mainview
->db
));
797 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
799 rc
= sqlite3_step(stmt2
);
800 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
802 else if (rc
== SQLITE_ROW
)
804 char *textdata
= (char *)sqlite3_column_text(stmt2
, 0);
805 int style
= sqlite3_column_int(stmt2
, 1);
806 unsigned long col
= sqlite3_column_int(stmt2
, 2);
808 GtkTreeIter toplevel
;
809 gtk_list_store_append(GTK_LIST_STORE(model
), &toplevel
);
810 gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_TEXT
, textdata
, CHECKNODE_CHECKED
, FALSE
, -1);
811 if ((style
& CHECKSTYLE_CHECKED
)>0) {
812 gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_CHECKED
, TRUE
, -1);
813 gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_ICON_NAME
, "widgets_tickmark_list", -1);
815 if ((style
& CHECKSTYLE_BOLD
)>0) gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_BOLD
, PANGO_WEIGHT_BOLD
, -1);
816 if ((style
& CHECKSTYLE_STRIKE
)>0) gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_STRIKE
, TRUE
, -1);
821 g_snprintf(tmp
, sizeof(tmp
), "#%02lx%02lx%02lx", ((col
& 0xFF0000) >> 16), ((col
& 0xFF00) >> 8), (col
& 0xFF));
822 gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_COLOR
, tmp
, -1);
827 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
)
829 maepad_warning("Error reading checklist (2): %s", sqlite3_errmsg(mainview
->db
));
833 sqlite3_finalize(stmt2
);
836 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->listview
), model
);
837 g_object_unref(model
);
840 if ((nd
->flags
& NODEFLAG_SKETCHLINES
) > 0)
841 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->sketchlinesmenuitems
[1]), TRUE
);
842 else if ((nd
->flags
& NODEFLAG_SKETCHGRAPH
) > 0)
843 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->sketchlinesmenuitems
[2]), TRUE
);
846 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->sketchlinesmenuitems
[0]), TRUE
);
847 callback_sketchlines(NULL
, mainview
->sketchlinesmenuitems
[0]); /*FIXME:ugly */
849 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mainview
->tools_pressure
), TRUE
);
854 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
) {
855 maepad_warning("Error reading (2): %s", sqlite3_errmsg(mainview
->db
));
858 sqlite3_finalize(stmt
);
861 busy_leave(mainview
);
863 /* Show / hide the sketch-related menu widgets */
864 if (nd
->typ
== NODE_SKETCH
) {
865 gtk_widget_show(mainview
->menu_button_square
);
866 gtk_widget_show(mainview
->menu_button_filled
);
868 gtk_widget_hide(mainview
->menu_button_square
);
869 gtk_widget_hide(mainview
->menu_button_filled
);
872 /* Show/hide the rich text-related menu widgets */
873 if (nd
->typ
== NODE_TEXT
) {
874 gtk_widget_show(mainview
->menu_button_wordwrap
);
876 gtk_widget_hide(mainview
->menu_button_wordwrap
);
879 /* Show/hide the checklist-related menu widgets */
880 if (nd
->typ
== NODE_CHECKLIST
) {
881 gtk_widget_show(mainview
->menu_button_remove_checked
);
883 gtk_widget_hide(mainview
->menu_button_remove_checked
);
888 show_banner(mainview
, _("Error loading memo"));
892 gboolean
treeview_canselect(GtkTreeSelection
* selection
, GtkTreeModel
* model
, GtkTreePath
* path
, gboolean path_currently_selected
, gpointer userdata
)
894 MainView
*mainview
= (MainView
*) userdata
;
895 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
897 if (path_currently_selected
)
900 gtk_tree_model_get_iter(model
, &iter
, path
);
902 gtk_tree_model_get(model
, &iter
, NODE_DATA
, &(mainview
->cansel_node
), -1);
903 mainview
->cansel_time
=time(NULL
);
909 gboolean
newnodedlg_key_press_cb(GtkWidget
* widget
, GdkEventKey
* event
, GtkWidget
* dlg
)
911 SketchWidget
*s
= gtk_object_get_data(GTK_OBJECT(dlg
), "sk");
913 switch (event
->keyval
)
916 sketchwidget_redo(s
);
919 sketchwidget_undo(s
);
926 /* This struct will hold all our toggle buttons, so we can
927 * only allow one to be active at a time (i.e. radio buttons) */
928 typedef struct _newNodeToggleButtons newNodeToggleButtons
;
929 struct _newNodeToggleButtons
931 GtkWidget
*rbt
; /* Text */
932 GtkWidget
*rbs
; /* Sketch */
933 GtkWidget
*rbc
; /* Checklist */
936 void show_sketch_widget(GtkWidget
*widget
, gpointer user_data
)
938 GtkWidget
*dialog
= (GtkWidget
*)user_data
;
940 /* Show the sketch widget and hide the entry + draw button */
941 gtk_widget_show(gtk_object_get_data(GTK_OBJECT(dialog
), "al"));
942 gtk_widget_hide(gtk_object_get_data(GTK_OBJECT(dialog
), "draw_button"));
943 gtk_widget_hide(gtk_object_get_user_data(GTK_OBJECT(dialog
)));
946 void new_node_dialog(nodeType typ
, MainView
* mainview
)
948 GtkWidget
*dialog
, *entry
, *but_ok
, *vbox
, *hbox
, *al
, *cb
;
949 GtkWidget
*rb1
, *rb2
, *rb3
;
951 gchar datetime_str
[200];
954 gboolean datetime_written
= FALSE
;
957 tm_now
= localtime(&t_now
);
959 if (tm_now
!= NULL
) {
960 if (strftime(datetime_str
, sizeof(datetime_str
), "%y-%m-%d %H:%M", tm_now
) != 0) {
961 datetime_written
= TRUE
;
965 if (datetime_written
== FALSE
) {
966 /* Was not able to determine a datetime string - use default */
967 maepad_warning("Cannot determine current time");
968 strncpy(datetime_str
, _("New memo"), sizeof(datetime_str
));
969 datetime_str
[sizeof(datetime_str
)-1] = '\0';
972 newNodeToggleButtons
*nntb
= g_malloc(sizeof(newNodeToggleButtons
));
974 dialog
= gtk_dialog_new();
975 gtk_window_set_title(GTK_WINDOW(dialog
), _("Add new memo"));
976 gtk_window_set_transient_for(GTK_WINDOW(dialog
), mainview_get_dialog_parent(mainview
));
977 gtk_dialog_set_has_separator(GTK_DIALOG(dialog
), FALSE
);
979 g_signal_connect(G_OBJECT(dialog
), "key_press_event", G_CALLBACK(newnodedlg_key_press_cb
), dialog
);
981 vbox
= gtk_vbox_new(FALSE
, 0);
983 hbox
= gtk_hbox_new(TRUE
, 0);
985 /* Text note toggle button */
986 rb1
= hildon_gtk_radio_button_new(HILDON_SIZE_FINGER_HEIGHT
, NULL
);
987 gtk_button_set_label(GTK_BUTTON(rb1
), _("Rich text"));
988 gtk_button_set_image(GTK_BUTTON(rb1
), gtk_image_new_from_file(PIXMAPDIR
"/text.png"));
989 gtk_box_pack_start(GTK_BOX(hbox
), GTK_WIDGET(rb1
), TRUE
, TRUE
, 0);
992 /* Sketch toggle button */
993 rb2
= hildon_gtk_radio_button_new_from_widget(HILDON_SIZE_FINGER_HEIGHT
, GTK_RADIO_BUTTON(rb1
));
994 gtk_button_set_label(GTK_BUTTON(rb2
), _("Sketch"));
995 gtk_button_set_image(GTK_BUTTON(rb2
), gtk_image_new_from_file(PIXMAPDIR
"/sketch.png"));
996 gtk_box_pack_start(GTK_BOX(hbox
), GTK_WIDGET(rb2
), TRUE
, TRUE
, 0);
999 /* Checklist toggle button */
1000 rb3
= hildon_gtk_radio_button_new_from_widget(HILDON_SIZE_FINGER_HEIGHT
, GTK_RADIO_BUTTON(rb1
));
1001 gtk_button_set_label(GTK_BUTTON(rb3
), _("Checklist"));
1002 gtk_button_set_image(GTK_BUTTON(rb3
), gtk_image_new_from_file(PIXMAPDIR
"/checklist.png"));
1003 gtk_box_pack_start(GTK_BOX(hbox
), GTK_WIDGET(rb3
), TRUE
, TRUE
, 0);
1006 /* Set mode to 0 to get correct styling */
1007 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb1
), FALSE
);
1008 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb2
), FALSE
);
1009 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(rb3
), FALSE
);
1011 /* Remember "new note toggle buttons" list */
1012 gtk_object_set_data(GTK_OBJECT(dialog
), "nntb", nntb
);
1014 if (typ
== NODE_TEXT
) {
1015 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb1
), TRUE
);
1016 } else if (typ
== NODE_SKETCH
) {
1017 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb2
), TRUE
);
1019 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb3
), TRUE
);
1022 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 0);
1024 but_ok
= gtk_dialog_add_button(GTK_DIALOG(dialog
), _("Add"), GTK_RESPONSE_OK
);
1025 gtk_dialog_set_default_response(GTK_DIALOG(dialog
), GTK_RESPONSE_OK
);
1026 g_signal_connect(G_OBJECT(but_ok
), "clicked", G_CALLBACK(callback_new_node_real
), dialog
);
1028 gtk_object_set_data(GTK_OBJECT(dialog
), "m", mainview
);
1030 hb
= gtk_hbox_new(FALSE
, 10);
1031 gtk_box_pack_start(GTK_BOX(hb
), gtk_label_new(_("Name:")), FALSE
, FALSE
, 0);
1032 entry
= hildon_entry_new(HILDON_SIZE_AUTO
);
1033 gtk_entry_set_activates_default(GTK_ENTRY(entry
), TRUE
);
1034 gtk_object_set_user_data(GTK_OBJECT(dialog
), entry
);
1035 gtk_entry_set_text(GTK_ENTRY(entry
), datetime_str
);
1036 gtk_editable_select_region(GTK_EDITABLE(entry
), 0, -1);
1037 gtk_box_pack_start(GTK_BOX(hb
), entry
, TRUE
, TRUE
, 0);
1039 /* Sketch widget, hidden by default */
1040 al
= gtk_alignment_new(0.5, 0.5, 0, 0);
1041 SketchWidget
*s
= sketchwidget_new(SKETCHNODE_X
, SKETCHNODE_Y
, TRUE
);
1042 gtk_object_set_data(GTK_OBJECT(dialog
), "sk", s
);
1043 gtk_object_set_data(GTK_OBJECT(dialog
), "al", al
);
1044 sketchwidget_set_brushsize(s
, 2);
1045 sketchwidget_set_backstyle(s
, SKETCHBACK_GRAPH
);
1046 gtk_widget_set_size_request(sketchwidget_get_mainwidget(s
), SKETCHNODE_X
, SKETCHNODE_Y
);
1047 gtk_container_add(GTK_CONTAINER(al
), sketchwidget_get_mainwidget(s
));
1048 gtk_box_pack_start(GTK_BOX(hb
), al
, FALSE
, FALSE
, 0);
1050 /*but_sketch = hildon_button_new_with_text(
1051 HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
1052 HILDON_BUTTON_ARRANGEMENT_VERTICAL,
1053 _("Use sketch label"), NULL);
1055 gtk_object_set_data(GTK_OBJECT(dialog), "draw_button", but_sketch);
1056 gtk_signal_connect(GTK_OBJECT(but_sketch), "clicked", G_CALLBACK(show_sketch_widget), dialog);
1057 gtk_box_pack_start(GTK_BOX(hb), but_sketch, FALSE, TRUE, 0);*/
1058 gtk_box_pack_start(GTK_BOX(vbox
), hb
, TRUE
, FALSE
, 0);
1060 cb
= hildon_check_button_new(HILDON_SIZE_FINGER_HEIGHT
| HILDON_SIZE_AUTO_WIDTH
);
1061 gtk_button_set_label(GTK_BUTTON(cb
), _("Add as child of selected memo"));
1062 hildon_check_button_set_active(HILDON_CHECK_BUTTON(cb
), mainview
->newnodedialog_createchild
);
1063 gtk_box_pack_start(GTK_BOX(vbox
), cb
, FALSE
, FALSE
, 0);
1065 gtk_object_set_data(GTK_OBJECT(dialog
), "cb", cb
);
1067 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog
)->vbox
), vbox
);
1069 gtk_widget_grab_focus(entry
);
1071 gtk_widget_show_all(dialog
);
1073 /* Hide the sketch widget at first */
1074 gtk_widget_hide(al
);
1075 gtk_window_set_modal(GTK_WINDOW(dialog
), TRUE
);
1078 void add_new_node(nodeData
* node
, MainView
* mainview
, gboolean ischild
)
1080 GtkTreeIter parentiter
, newiter
;
1081 GtkTreeModel
*model
;
1084 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1086 if (gtk_tree_selection_get_selected(selection
, &model
, &parentiter
))
1089 GtkTreePath
*path
= NULL
;
1091 unsigned int parentnodeid
= 0;
1095 path
= gtk_tree_model_get_path(model
, &parentiter
);
1097 if (ischild
== FALSE
)
1099 gtk_tree_path_up(path
);
1101 if (gtk_tree_path_get_depth(path
) == 0)
1103 /* Selected node is a root node */
1104 ptr
= NULL
; /* New node can not have a Parent node */
1105 gtk_tree_path_down(path
); /*restore path so expand() works */
1107 else if (gtk_tree_path_get_depth(path
) > 0)
1109 /* Selected node is a child node */
1110 if (gtk_tree_model_get_iter(model
, &parentiter
, path
))
1120 gtk_tree_model_get(model
, ptr
, NODE_DATA
, &nd
, -1);
1122 parentnodeid
= nd
->sql3id
;
1128 sqlite3_stmt
*stmt
= NULL
;
1135 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s (parent, bodytype, name, nameblob, ord) VALUES (%d, %d, ?, ?, 0);", datatable_tmpname
, parentnodeid
, node
->typ
);
1136 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt
, &dum
);
1140 maepad_warning("Error inserting (1): %s", sqlite3_errmsg(mainview
->db
));
1143 if (node
->name
!= NULL
)
1144 sqlite3_bind_text(stmt
, 1, node
->name
, strlen(node
->name
), SQLITE_TRANSIENT
);
1146 sqlite3_bind_text(stmt
, 1, NULL
, 0, SQLITE_TRANSIENT
);
1148 if (node
->namepix
!= NULL
)
1150 gchar
*namepixdata
= NULL
;
1155 if (gdk_pixbuf_save_to_buffer(node
->namepix
, &namepixdata
, &datalen
, "png", &err
, NULL
) == FALSE
)
1159 maepad_warning("Error saving name: %s", err
->message
);
1162 sqlite3_bind_blob(stmt
, 2, namepixdata
, datalen
, SQLITE_TRANSIENT
);
1165 sqlite3_bind_blob(stmt
, 2, NULL
, 0, SQLITE_TRANSIENT
);
1168 while(rc
== SQLITE_BUSY
)
1170 rc
= sqlite3_step(stmt
);
1171 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
1174 sqlite3_finalize(stmt
);
1175 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
)
1177 maepad_warning("Error inserting (2): %s", sqlite3_errmsg(mainview
->db
));
1180 node
->sql3id
= sqlite3_last_insert_rowid(mainview
->db
);
1184 if (node
->sql3id
== 0)
1189 g_object_unref(node
->namepix
);
1192 gtk_tree_path_free(path
);
1193 show_banner(mainview
, _("Error creating memo"));
1197 gtk_tree_store_append(GTK_TREE_STORE(model
), &newiter
, ptr
);
1199 gtk_tree_store_set(GTK_TREE_STORE(model
), &newiter
,
1200 NODE_NAME
, format_overview_name(node
, NULL
),
1201 NODE_PIXBUF
, node
->namepix
,
1207 mainview
->loading
=TRUE
; /*only when we have a valid parent*/
1208 gtk_tree_view_expand_row(GTK_TREE_VIEW(mainview
->treeview
), path
, FALSE
);
1209 gtk_tree_path_free(path
);
1212 gtk_tree_selection_select_iter(selection
, &newiter
);
1214 mainview
->loading
=FALSE
;
1217 void callback_new_node_real(GtkAction
* action
, gpointer data
)
1221 GtkWidget
*dialog
= data
;
1222 GtkWidget
*entry
= gtk_object_get_user_data(GTK_OBJECT(dialog
));
1224 mainview
= gtk_object_get_data(GTK_OBJECT(dialog
), "m");
1225 SketchWidget
*s
= gtk_object_get_data(GTK_OBJECT(dialog
), "sk");
1226 GtkWidget
*cb
= gtk_object_get_data(GTK_OBJECT(dialog
), "cb");
1227 newNodeToggleButtons
*nntb
= gtk_object_get_data(GTK_OBJECT(dialog
), "nntb");
1229 nodeType typ
= NODE_TEXT
;
1230 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nntb
->rbs
))) {
1232 } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nntb
->rbc
))) {
1233 typ
= NODE_CHECKLIST
;
1239 /*if (GTK_WIDGET_VISIBLE(entry))
1241 txt
= g_strdup(gtk_entry_get_text(GTK_ENTRY(entry
)));
1242 if (strcmp(txt
, "") == 0)
1250 GtkWidget *sdr = sketchwidget_get_drawingarea(s);
1252 GdkPixmap *spix = sketchwidget_get_Pixmap(s);
1254 pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(spix), NULL, 0, 0, 0, 0, sdr->allocation.width, sdr->allocation.height);
1255 g_object_unref(spix);
1257 GdkPixbuf *pixbuf2 = sketchwidget_trim_image(pixbuf, SKETCHNODE_X, SKETCHNODE_Y, &w,
1259 if (pixbuf2==NULL) return;
1261 GdkPixbuf *pixbuf3 = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, SKETCHNODE_RX,
1264 gdk_pixbuf_fill(pixbuf3, 0xffffffff);
1266 if (w <= SKETCHNODE_RX && h <= SKETCHNODE_RY)
1268 gdk_pixbuf_copy_area(pixbuf2, 0, 0, w, h, pixbuf3, 0, (SKETCHNODE_RY - h) / 2);
1276 neww = SKETCHNODE_RX;
1277 newh = (h / w) * SKETCHNODE_RX;
1281 newh = SKETCHNODE_RY;
1282 neww = (w / h) * SKETCHNODE_RY;
1284 if (newh > SKETCHNODE_RY)
1285 newh = SKETCHNODE_RY;
1287 GdkPixbuf *tmpbuf = gdk_pixbuf_scale_simple(pixbuf2, neww, newh,
1288 GDK_INTERP_BILINEAR);
1290 gdk_pixbuf_copy_area(tmpbuf, 0, 0, neww, newh, pixbuf3, 0, (SKETCHNODE_RY - newh) / 2);
1292 gdk_pixbuf_unref(tmpbuf);
1296 gdk_pixbuf_unref(pixbuf2);
1301 node
= g_malloc(sizeof(nodeData
));
1304 node
->namepix
= NULL
;
1306 /*if (GTK_WIDGET_VISIBLE(entry))
1312 node->namepix = pixbuf;
1319 mainview
->newnodedialog_createchild
= hildon_check_button_get_active(HILDON_CHECK_BUTTON(cb
));
1320 add_new_node(node
, mainview
, mainview
->newnodedialog_createchild
);
1322 sketchwidget_destroy(s
);
1323 gtk_widget_destroy(dialog
);
1324 mainview
->file_edited
= TRUE
;
1330 void callback_file_delete_node(GtkAction
* action
, gpointer data
)
1332 MainView
*mainview
= (MainView
*) data
;
1333 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1335 if (getSelectedNode(mainview
) == NULL
) {
1336 show_banner(mainview
, _("Select a memo first"));
1340 if (show_confirmation(mainview
, _("Delete selected memo?"))) {
1341 mainview
->can_show_node_view
= FALSE
;
1342 callback_delete_node_real(mainview
);
1343 gtk_widget_hide(GTK_WIDGET(mainview
->data
->node_view
));
1348 * Callback for Rename Menuitem
1350 void callback_file_rename_node(GtkAction
* action
, gpointer data
)
1352 MainView
*mainview
= (MainView
*)data
;
1353 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1355 /* Get the selected node */
1356 nodeData
*sel_node
= getSelectedNode(mainview
);
1357 if (sel_node
== NULL
) {
1358 /* Do nothing, if no node has been selected */
1359 show_banner(mainview
, _("Select a memo first"));
1363 if (sel_node
->namepix
!= NULL
) {
1364 /* the memo has a graphical label, cannot edit! */
1365 show_banner(mainview
, _("Cannot rename memos with sketch name"));
1369 gchar
* new_name
= show_line_edit_dialog(mainview
, _("Rename memo"), _("New name:"), _("Rename"), sel_node
->name
);
1371 /* Only rename node when user accepted the new name */
1372 if (new_name
!= NULL
) {
1373 callback_rename_node_real(mainview
, new_name
);
1378 void callback_rename_node_real(MainView
* mainview
, gchar
* new_name
)
1381 GtkTreeModel
*model
;
1382 nodeData
*nd
= NULL
;
1384 /* Get the selected node */
1385 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1387 if (!gtk_tree_selection_get_selected(selection
, &model
, &iter
)) {
1391 gtk_tree_model_get (model
, &iter
, NODE_DATA
, &nd
, -1);
1397 /* Update the database */
1398 sqlite3_stmt
*stmt
= NULL
;
1400 char* sql
= sqlite3_mprintf("UPDATE %s SET name='%q' WHERE nodeid=%d", datatable_tmpname
, new_name
, nd
->sql3id
);
1402 int rc
= sqlite3_prepare(mainview
->db
, sql
, strlen(sql
), &stmt
, NULL
);
1403 if (rc
== SQLITE_OK
) {
1405 while (rc
== SQLITE_BUSY
) {
1406 rc
= sqlite3_step(stmt
);
1407 if (rc
== SQLITE_DONE
) {
1408 /* Update in the database was successful - now update the rest */
1410 /* Update the noteData */
1412 nd
->name
= g_strdup(new_name
);
1414 /* Update the window title of node_view */
1415 gtk_window_set_title(GTK_WINDOW(mainview
->data
->node_view
), nd
->name
);
1417 /* Update the value in the tree store */
1418 gtk_tree_store_set (GTK_TREE_STORE(model
), &iter
, NODE_NAME
, format_overview_name(nd
, new_name
), -1);
1421 } else if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
) {
1422 maepad_warning("Error updating node: %s", sqlite3_errmsg(mainview
->db
));
1426 sqlite3_finalize(stmt
);
1428 maepad_warning("Error preparing DB update query: %s", sqlite3_errmsg(mainview
->db
));
1433 mainview
->file_edited
= TRUE
;
1436 void callback_file_export_node(GtkAction
* action
, gpointer data
)
1438 MainView
*mainview
= (MainView
*) data
;
1439 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1441 nodeData
*nd
=getSelectedNode(mainview
);
1444 show_banner(mainview
, _("Select a memo first"));
1448 gchar
*nodename
=nd
->name
;
1449 if (nodename
==NULL
) nodename
=_("saved memo");
1451 if (nd
->typ
== NODE_TEXT
)
1454 GtkTextIter begin, end;
1455 gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER(mainview->buffer), &begin, &end);
1456 gchar *text = gtk_text_buffer_get_slice(GTK_TEXT_BUFFER(mainview->buffer), &begin, &end, TRUE);
1458 GString
*gstr
=g_string_sized_new(4096);
1459 wp_text_buffer_save_document(mainview
->buffer
, (WPDocumentSaveCallback
)(wp_savecallback
), gstr
);
1460 gint textlen
=gstr
->len
;
1461 gchar
*text
=g_string_free(gstr
, FALSE
);
1463 if (text
==NULL
|| !strcmp(text
, ""))
1465 show_banner(mainview
, _("Memo is empty"));
1469 gchar
*fn
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, nodename
, "html");
1472 GnomeVFSResult vfs_result
;
1473 GnomeVFSHandle
*handle
= NULL
;
1474 GnomeVFSFileSize out_bytes
;
1475 vfs_result
= gnome_vfs_create(&handle
, fn
, GNOME_VFS_OPEN_WRITE
, 0, 0600);
1476 if ( vfs_result
!= GNOME_VFS_OK
) {
1477 show_banner(mainview
, _("Export failed"));
1481 gnome_vfs_write(handle
, text
, textlen
, &out_bytes
);
1482 gnome_vfs_close(handle
);
1483 if (out_bytes
==strlen(text
)) show_banner(mainview
, _("Exported"));
1484 else show_banner(mainview
, _("Export incomplete"));
1491 else if (nd
->typ
== NODE_SKETCH
)
1493 GdkPixmap
*skpix
= sketchwidget_get_Pixmap(mainview
->sk
);
1494 GtkWidget
*skdr
= sketchwidget_get_drawingarea(mainview
->sk
);
1495 GdkPixbuf
*pixbuf
= gdk_pixbuf_get_from_drawable(NULL
, GDK_DRAWABLE(skpix
), NULL
, 0, 0, 0, 0, skdr
->allocation
.width
, skdr
->allocation
.height
);
1498 show_banner(mainview
, _("Memo is empty"));
1502 gchar
*fn
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, nodename
, "png");
1505 if (gdk_pixbuf_save(pixbuf
, fn
, "png", NULL
, NULL
)==FALSE
)
1507 show_banner(mainview
, _("Export failed"));
1511 show_banner(mainview
, _("Exported"));
1516 g_object_unref(skpix
);
1518 else if (nd
->typ
== NODE_CHECKLIST
)
1520 show_banner(mainview
, _("Export of checklists not possible yet"));
1525 * callback from menu item
1526 * move selected node down (switch node with next sibling), don't change level of node
1528 void callback_move_down_node(GtkAction
* action
, gpointer data
)
1531 GtkTreeModel
*model
;
1533 MainView
*mainview
= (MainView
*) data
;
1534 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1536 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1537 gtk_tree_selection_get_selected(selection
, &model
, &iter
);
1539 GtkTreeIter old_iter
= iter
;/*save pointer to old iter, we will need it during swap nodes*/
1541 if (gtk_tree_model_iter_next(model
,&iter
)==FALSE
)/*get next node*/
1544 GtkTreeStore
*treeStore
= GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
)));
1545 gtk_tree_store_swap(treeStore
,&iter
,&old_iter
);
1547 mainview
->file_edited
= TRUE
;/*we have made changes , if required show "save changes?" dialog in future*/
1551 * callback from menu item
1552 * move selected node down (switch node with prev sibling), don't change level of node
1554 void callback_move_up_node(GtkAction
* action
, gpointer data
)
1557 GtkTreeModel
*model
;
1559 MainView
*mainview
= (MainView
*) data
;
1560 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1562 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1563 gtk_tree_selection_get_selected(selection
, &model
, &iter
);
1565 GtkTreeIter old_iter
=iter
;/*save pointer to old iter, we will need it during swap nodes*/
1567 if (tree_model_iter_prev(model
,&iter
)==FALSE
)/*get previous node*/
1570 GtkTreeStore
*treeStore
= GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
)));
1571 gtk_tree_store_swap(treeStore
,&old_iter
,&iter
);/*do move*/
1573 mainview
->file_edited
= TRUE
;/*we have made changes , if required show "save changes?" dialog in future*/
1577 * callback from menu item
1578 * we change level of actual node with direction to top
1580 void callback_move_to_top_level_node(GtkAction
* action
, gpointer data
)
1582 GtkTreeIter iter
,new_parent
;
1583 GtkTreeIter
*p_new_parent
;
1585 GtkTreeModel
*model
;
1587 MainView
*mainview
= (MainView
*) data
;
1588 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1590 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1591 gtk_tree_selection_get_selected(selection
, &model
, &iter
);
1593 /*at first we need actual parent of selected node*/
1594 if (gtk_tree_model_iter_parent(model
,&parent
,&iter
)==FALSE
)
1596 /*if parent of selected node is ROOT we can't go higher*/
1599 /*we need also new parent, it's parent of actual parent*/
1600 if (gtk_tree_model_iter_parent(model
,&new_parent
,&parent
)==FALSE
)
1602 /*if our new parent is ROOT we got filled new_parent with invalid value,
1603 so we need set NULL value to p_new_parent (root item)*/
1608 p_new_parent
=&new_parent
;/*we only redirect pointer to treeiter*/
1611 saveCurrentData(mainview
);/*we save changes in node befor move*/
1613 /*this move function provide move item with all his children, be careful iter value will change!*/
1614 if (move_node(mainview
,p_new_parent
,&iter
,&parent
)==TRUE
){
1616 gint id_parent
= get_node_id_on_tmp_db(model
,p_new_parent
);
1617 gint id_node
= get_node_id_on_tmp_db(model
,&iter
);
1618 /*we need also update parent id of moved item*/
1620 g_snprintf (tq
, sizeof(tq
), "UPDATE %s SET parent=%d WHERE nodeid=%d",datatable_tmpname
,id_parent
,id_node
);
1621 exec_command_on_db(mainview
,tq
);
1623 /*select new created iter*/
1624 gtk_tree_selection_select_iter(selection
,&iter
);
1626 mainview
->file_edited
= TRUE
;/*we have made changes , if required show "save changes?" dialog in future*/
1631 * callback from menu item
1632 * we change level of actual node with direction to bottom
1633 * previous node will be parent of our actual node
1635 void callback_move_to_bottom_level_node(GtkAction
* action
, gpointer data
)
1638 GtkTreeModel
*model
;
1640 MainView
*mainview
= (MainView
*) data
;
1641 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
1643 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1644 gtk_tree_selection_get_selected(selection
, &model
, &iter
);
1646 GtkTreeIter move_iter
=iter
;/*save pointer to old iter*/
1648 /*we try to get previous node*/
1649 if (tree_model_iter_prev(model
,&iter
)==FALSE
)
1650 return;/*if previous node on the same level doesn't exist we will exit*/
1652 saveCurrentData(mainview
);/*we save changes in node befor move*/
1654 /*this move function provide move item with all his children, be careful move_iter value will change!*/
1655 if (move_node(mainview
,&iter
,&move_iter
,NULL
)==TRUE
)
1657 gint id_parent
= get_node_id_on_tmp_db(model
,&iter
);
1658 gint id_node
= get_node_id_on_tmp_db(model
,&move_iter
);
1660 /*we need also update parent id of moved item*/
1662 g_snprintf (tq
, sizeof(tq
), "UPDATE %s SET parent=%d WHERE nodeid=%d",datatable_tmpname
,id_parent
,id_node
);
1663 exec_command_on_db(mainview
,tq
);
1665 GtkTreePath
*path
= gtk_tree_model_get_path(model
, &iter
);
1666 gtk_tree_view_expand_row(GTK_TREE_VIEW(mainview
->treeview
), path
, FALSE
);/*expand parent node*/
1667 gtk_tree_path_free(path
);
1669 /*select new created iter*/
1670 gtk_tree_selection_select_iter(selection
,&move_iter
);
1672 mainview
->file_edited
= TRUE
;/*we have made changes , if required show "save changes?" dialog in future*/
1677 * move item_to_move to new_parent with his children, this function is designed for change level of node
1678 * we copy item_to_move with his children to new position (after item_befor if is not NULL) and then we
1679 * destroy old node with his children, so ! item_to_move is set with new iter, be careful on this!
1681 gboolean
move_node(MainView
*mainview
,GtkTreeIter
*new_parent
,GtkTreeIter
*item_to_move
,GtkTreeIter
*item_befor
)
1683 GtkTreeModel
*model
;
1685 model
=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
));
1686 GtkTreeStore
*treeStore
= GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
)));
1689 gtk_tree_model_get(model
, item_to_move
, NODE_DATA
, &node
, -1);/*get data from actual iter*/
1692 GtkTreeIter new_iter
;/*create new iter*/
1693 gtk_tree_store_append(treeStore
,&new_iter
,new_parent
);/*append new iter to new parent*/
1695 if (item_befor
!=NULL
)
1696 gtk_tree_store_move_after(treeStore
,&new_iter
,item_befor
);/*sometimes we need set position*/
1698 gtk_tree_store_set(treeStore
, &new_iter
, NODE_NAME
, format_overview_name(node
, NULL
), NODE_PIXBUF
, node
->namepix
, NODE_DATA
, node
, -1);/*set data from old iter*/
1701 while (gtk_tree_model_iter_children(model
, &child
, item_to_move
)==TRUE
)/*move all childrens while some exits*/
1703 if (move_node(mainview
,&new_iter
,&child
,NULL
)==FALSE
)/*use recursion on children*/
1707 gtk_tree_store_set(treeStore
, item_to_move
, NODE_DATA
, NULL
, -1);
1708 gtk_tree_store_remove(treeStore
, item_to_move
);/*remove node, data need't remove, they are stored in new node*/
1710 /*we need return new value of moved item, so we need assign new_iter to item_to_move*/
1711 /*this code is ugly : new_iter to path and back to item_to_move*/
1712 GtkTreePath
*path
=gtk_tree_model_get_path(model
,&new_iter
);
1713 gtk_tree_model_get_iter(model
,item_to_move
,path
);
1714 gtk_tree_path_free(path
);
1718 fprintf(stderr
,"Get data node failed!\n");
1726 * simple execute of sql command which is stored in sql_string[]
1728 gboolean
exec_command_on_db(MainView
*mainview
,char sql_string
[])
1730 sqlite3_stmt
*stmt
= NULL
;
1732 gboolean db_query_result
= FALSE
;
1734 int rc
= sqlite3_prepare (mainview
->db
, sql_string
, strlen(sql_string
), &stmt
, &dum
);
1737 maepad_warning("Error preparing DB update query: %s", sqlite3_errmsg(mainview
->db
));
1742 while (rc
== SQLITE_BUSY
) {
1743 rc
= sqlite3_step (stmt
);
1744 if (rc
== SQLITE_DONE
) {
1745 db_query_result
= TRUE
;
1748 else if(rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
) {
1749 maepad_warning("Error updating node: %s", sqlite3_errmsg(mainview
->db
));
1752 sqlite3_finalize(stmt
);
1758 * 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)
1760 gboolean
foreach_func_update_ord (GtkTreeModel
*model
,GtkTreePath
*path
,GtkTreeIter
*iter
, MainView
*mainview
)
1763 gtk_tree_model_get(model
, iter
, NODE_DATA
, &node
, -1);
1764 /*we need index of node on actual level*/
1765 gint index
=get_branch_node_index(path
);
1767 /*prepare to execute update command,and exec it*/
1768 char sql_command
[512];
1769 g_snprintf (sql_command
, sizeof(sql_command
), "UPDATE %s SET ord=\"%d\" WHERE nodeid=%d",datatable_tmpname
, index
, node
->sql3id
);
1770 exec_command_on_db(mainview
,sql_command
);
1772 /*we don't want break gtk_tree_model_foreach function,until we call this func on each node - so we return always FALSE*/
1777 * return id number of iter (id number which is used to identify in sql database of nodes)
1779 int get_node_id_on_tmp_db(GtkTreeModel
*model
,GtkTreeIter
*iter
)
1782 return 0;/*we got ROOT parent here*/
1785 gtk_tree_model_get(model
, iter
, NODE_DATA
, &node
, -1);
1786 return node
->sql3id
;
1790 * get index of node in current branch
1792 gint
get_branch_node_index(GtkTreePath
*path
)
1794 int depth
=gtk_tree_path_get_depth(path
);
1795 gint
*indicies
= gtk_tree_path_get_indices(path
);
1797 return indicies
[depth
-1];
1801 * similiar with gtk_tree_model_iter_next (), but opposite
1803 gboolean
tree_model_iter_prev(GtkTreeModel
*tree_model
,GtkTreeIter
*iter
)
1805 GtkTreePath
*path
= gtk_tree_model_get_path(tree_model
, iter
);
1808 fprintf(stderr
,"Error: path is null\n");
1812 if (gtk_tree_path_prev(path
)==FALSE
)
1815 gtk_tree_model_get_iter(tree_model
, iter
,path
);
1820 gboolean
ref2iter(GtkTreeModel
* model
, GtkTreeRowReference
* ref
, GtkTreeIter
* iter
)
1822 gboolean res
= FALSE
;
1823 GtkTreePath
*path
= gtk_tree_row_reference_get_path(ref
);
1825 if (gtk_tree_model_get_iter(model
, iter
, path
))
1829 gtk_tree_path_free(path
);
1833 GtkTreeRowReference
*iter2ref(GtkTreeModel
* model
, GtkTreeIter
* iter
)
1835 GtkTreeRowReference
*ref
;
1837 GtkTreePath
*path
= gtk_tree_model_get_path(model
, iter
);
1839 ref
= gtk_tree_row_reference_new(model
, path
);
1840 gtk_tree_path_free(path
);
1844 void move_nodes_up(GtkTreeModel
* model
, GtkTreeRowReference
* topnode
, GtkTreeRowReference
* newtop
)
1846 GtkTreeIter topiter
;
1848 if (ref2iter(model
, topnode
, &topiter
) == FALSE
)
1853 if (gtk_tree_model_iter_children(model
, &child
, &topiter
))
1855 GtkTreeRowReference
*ref
;
1856 GList
*rr_list
= NULL
, *node
;
1860 ref
= iter2ref(model
, &child
);
1861 rr_list
= g_list_append(rr_list
, ref
);
1863 while(gtk_tree_model_iter_next(model
, &child
));
1866 * got a reflist for all children
1869 for(node
= rr_list
; node
; node
= node
->next
)
1871 ref
= (GtkTreeRowReference
*) (node
->data
);
1872 if (ref2iter(model
, ref
, &child
))
1874 GtkTreeIter newtopiter
, newiter
;
1875 GtkTreeIter
*newtopiterptr
;
1877 if (ref2iter(model
, newtop
, &newtopiter
))
1878 newtopiterptr
= &newtopiter
;
1880 newtopiterptr
= NULL
;
1884 gtk_tree_model_get(model
, &child
, NODE_DATA
, &node
, -1);
1886 gtk_tree_store_append(GTK_TREE_STORE(model
), &newiter
, newtopiterptr
);
1887 gtk_tree_store_set(GTK_TREE_STORE(model
), &newiter
, NODE_NAME
, format_overview_name(node
, NULL
), NODE_PIXBUF
, node
->namepix
, NODE_DATA
, node
, -1);
1889 GtkTreeRowReference
*newref
= iter2ref(model
, &newiter
);
1891 move_nodes_up(model
, ref
, newref
);
1892 gtk_tree_row_reference_free(newref
);
1894 gtk_tree_store_remove(GTK_TREE_STORE(model
), &child
);
1896 gtk_tree_row_reference_free(ref
);
1899 g_list_free(rr_list
);
1904 void callback_delete_node_real(MainView
* mainview
)
1907 GtkTreeModel
*model
;
1909 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
1911 if (!gtk_tree_selection_get_selected(selection
, &model
, &iter
))
1916 gtk_tree_model_get(model
, &iter
, NODE_DATA
, &nd
, -1);
1920 mainview
->file_edited
= TRUE
;
1922 unsigned int sql3id
= nd
->sql3id
;
1929 * if (nd->pix) g_object_unref(nd->pix);
1933 GtkTreeRowReference
*upref
= NULL
, *ref
= NULL
;
1935 GtkTreePath
*path
= gtk_tree_model_get_path(model
, &iter
);
1937 ref
= gtk_tree_row_reference_new(model
, path
);
1938 if (gtk_tree_path_up(path
))
1939 upref
= gtk_tree_row_reference_new(model
, path
);
1940 gtk_tree_path_free(path
);
1942 g_object_ref(model
);
1943 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), NULL
);
1945 move_nodes_up(model
, ref
, upref
);
1947 if (ref2iter(model
, ref
, &iter
))
1951 g_snprintf(tq
, sizeof(tq
), "SELECT parent FROM %s WHERE nodeid=%d", datatable_tmpname
, sql3id
);
1952 sqlite3_stmt
*stmt
= NULL
;
1954 int rc
= sqlite3_prepare(mainview
->db
, tq
, strlen(tq
), &stmt
, &dum
);
1955 unsigned int sql3parentid
= 0;
1959 maepad_warning("Error finding children for delete: %s", sqlite3_errmsg(mainview
->db
));
1964 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
1966 rc
= sqlite3_step(stmt
);
1967 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
1969 else if (rc
== SQLITE_ROW
)
1971 sql3parentid
= sqlite3_column_int(stmt
, 0);
1975 sqlite3_finalize(stmt
);
1977 g_snprintf(tq
, sizeof(tq
), "UPDATE %s SET parent=%d WHERE parent=%d;", datatable_tmpname
, sql3parentid
, sql3id
);
1978 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
1979 maepad_warning("Error moving nodes up one level");
1982 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s WHERE nodeid=%d;", datatable_tmpname
, sql3id
);
1983 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
1984 maepad_warning("Error deleting node");
1987 /* Delete all checklist items that do not have
1988 * a node anymore (= orphaned checklist items) */
1989 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s WHERE nodeid NOT IN (SELECT nodeid FROM %s);", checklisttable_tmpname
, datatable_tmpname
);
1990 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
1991 maepad_warning("Error deleting orphaned checklist items");
1995 gtk_tree_store_remove(GTK_TREE_STORE(model
), &iter
);
1998 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), model
);
1999 g_object_unref(model
);
2001 gtk_tree_row_reference_free(ref
);
2002 gtk_tree_row_reference_free(upref
);
2004 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview
->treeview
));
2008 void callback_edit_clear(GtkAction
* action
, gpointer data
)
2010 MainView
*mainview
= (MainView
*) data
;
2011 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2012 nodeData
*nd
= getSelectedNode(mainview
);
2014 if (show_confirmation(mainview
, _("Remove all contents of this memo?"))) {
2017 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview
->buffer
), "", 0);
2020 sketchwidget_clear(mainview
->sk
);
2022 case NODE_CHECKLIST
:
2023 gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
))));
2026 g_assert_not_reached();
2034 void callback_edit_cut(GtkAction
* action
, gpointer data
)
2036 MainView
*mainview
= (MainView
*) data
;
2037 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2039 nodeData
*nd
= getSelectedNode(mainview
);
2041 if (nd
->typ
== NODE_TEXT
)
2042 gtk_text_buffer_cut_clipboard(GTK_TEXT_BUFFER(mainview
->buffer
), mainview
->clipboard
, TRUE
);
2043 else if (nd
->typ
== NODE_SKETCH
)
2045 if (sketchwidget_cut(mainview
->sk
, mainview
->clipboard
)==FALSE
)
2046 show_banner(mainview
, _("Error cutting"));
2048 else if (nd
->typ
== NODE_CHECKLIST
)
2049 show_banner(mainview
, _("Unimplemented"));
2056 void callback_edit_copy(GtkAction
* action
, gpointer data
)
2058 MainView
*mainview
= (MainView
*) data
;
2059 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2061 nodeData
*nd
= getSelectedNode(mainview
);
2063 if (nd
->typ
== NODE_TEXT
)
2064 gtk_text_buffer_copy_clipboard(GTK_TEXT_BUFFER(mainview
->buffer
), mainview
->clipboard
);
2065 else if (nd
->typ
== NODE_SKETCH
)
2067 if (sketchwidget_copy(mainview
->sk
, mainview
->clipboard
)==FALSE
)
2068 show_banner(mainview
, _("Error copying"));
2070 else if (nd
->typ
== NODE_CHECKLIST
)
2072 /* Copy all selected entries as multiline text (1 line per entry) */
2073 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
2074 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
));
2076 gint selected_rows
= gtk_tree_selection_count_selected_rows(selection
);
2077 GList
* l
= gtk_tree_selection_get_selected_rows(selection
, NULL
);
2082 gchar
**entries
= g_malloc0(sizeof(gchar
*)*selected_rows
+1);
2083 gint entries_idx
= 0;
2087 GtkTreePath
*path
= cur
->data
;
2089 if (gtk_tree_model_get_iter(model
, &iter
, path
)) {
2090 gtk_tree_model_get(GTK_TREE_MODEL(model
), &iter
, CHECKNODE_TEXT
, &(entries
[entries_idx
++]), -1);
2092 gtk_tree_path_free(path
);
2098 str_data
= g_strjoinv("\n", entries
);
2099 g_strfreev(entries
);
2100 gtk_clipboard_set_text(mainview
->clipboard
, str_data
, -1);
2103 str_data
= g_strdup_printf(_("Copied %d entries"), selected_rows
);
2104 show_banner(mainview
, str_data
);
2113 void callback_edit_paste(GtkAction
* action
, gpointer data
)
2115 MainView
*mainview
= (MainView
*) data
;
2116 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2118 nodeData
*nd
= getSelectedNode(mainview
);
2120 if (nd
->typ
== NODE_TEXT
)
2121 gtk_text_buffer_paste_clipboard(GTK_TEXT_BUFFER(mainview
->buffer
), mainview
->clipboard
, NULL
, TRUE
);
2122 else if (nd
->typ
== NODE_SKETCH
)
2124 if (sketchwidget_paste(mainview
->sk
, mainview
->clipboard
)==FALSE
)
2125 show_banner(mainview
, _("Error pasting"));
2127 else if (nd
->typ
== NODE_CHECKLIST
) {
2128 /* Paste string from clipboard as new item */
2129 callback_checklist_paste(mainview
);
2130 checklist_select(mainview
, TREEVIEW_SELECT_LAST
);
2133 mainview
->file_edited
= TRUE
;
2136 gint
cb_popup(GtkWidget
* widget
, GdkEvent
* event
)
2139 GdkEventButton
*event_button
;
2142 * The "widget" is the menu that was supplied when
2143 * * g_signal_connect_swapped() was called.
2145 menu
= GTK_MENU(widget
);
2146 event_button
= (GdkEventButton
*) event
;
2147 if (event
->type
== GDK_BUTTON_PRESS
&& event_button
->button
== 3)
2149 gtk_menu_popup(menu
, NULL
, NULL
, NULL
, NULL
, event_button
->button
, event_button
->time
);
2157 * on_node_menu_show(GtkWidget*, gpointer)
2159 * This is called when the longpress menu is shown in the main
2160 * window. In the Hildon UI mode that we are using, this does
2161 * not automatically select the touched node, so we need to set
2162 * the cursor here so that the functions in the menu operate on
2163 * the node that the user touched (i.e. the expected one).
2165 * The value of mainview->node_list_longpress_path has been set
2166 * by callback_treeview_button_press on the buttn press event.
2169 on_node_menu_show(GtkWidget
* nodemenu
, gpointer user_data
)
2171 MainView
* mainview
= (MainView
*)user_data
;
2173 if (mainview
->node_list_longpress_path
!= NULL
) {
2174 /* Set the cursor, but don't open the node view */
2175 mainview
->can_show_node_view
= FALSE
;
2176 gtk_tree_view_set_cursor(GTK_TREE_VIEW(mainview
->treeview
),
2177 mainview
->node_list_longpress_path
, NULL
, FALSE
);
2179 /* Dispose the path (we don't need it anymore) */
2180 gtk_tree_path_free(mainview
->node_list_longpress_path
);
2181 mainview
->node_list_longpress_path
= NULL
;
2188 gboolean
closefile(MainView
* mainview
)
2190 saveCurrentData(mainview
);
2192 if (mainview
->file_edited
)
2194 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
));
2195 gint answer
= gtk_dialog_run(GTK_DIALOG(hn
));
2196 gtk_widget_destroy(GTK_WIDGET(hn
));
2198 if (answer
== CONFRESP_CANCEL
)
2200 else if (answer
== CONFRESP_YES
)
2202 if (mainview
->file_name
== NULL
)
2204 mainview
->file_name
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, "maemopaddata", "db");
2206 write_buffer_to_file(mainview
);
2211 sqlite3_close(mainview
->db
);
2212 mainview
->db
= NULL
;
2216 gboolean
callback_file_close(GtkAction
* action
, gpointer data
)
2219 MainView
*mainview
= (MainView
*) data
;
2220 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2221 if (closefile(mainview
) == FALSE
)
2228 void callback_file_new_node(GtkAction
* action
, gpointer data
)
2230 MainView
*mainview
= (MainView
*) data
;
2231 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2233 nodeType typ
= NODE_SKETCH
;
2235 nodeData
*nd
= getSelectedNode(mainview
);
2240 new_node_dialog(typ
, mainview
);
2246 void callback_file_new(GtkAction
* action
, gpointer data
)
2248 MainView
*mainview
= (MainView
*) data
;
2249 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2251 gchar
*filename
= NULL
;
2253 filename
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, "memos", "db");
2254 if (filename
== NULL
) {
2258 if (closefile(mainview
) == FALSE
) {
2266 busy_enter(mainview
);
2270 rc
= sqlite3_open(filename
, &mainview
->db
);
2273 show_banner(mainview
, _("Cannot create database"));
2274 maepad_warning("Can't create database %s: %s", filename
, sqlite3_errmsg(mainview
->db
));
2278 sqlite3_exec(mainview
->db
, "PRAGMA synchronous = OFF;", NULL
, NULL
, NULL
);
2282 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", misctable_name
, misctable
);
2283 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
2285 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", datatable_name
, datatable
);
2286 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
2288 maepad_warning("Cannot create data table");
2289 show_banner(mainview
, _("Error creating data table"));
2293 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", checklisttable_name
, checklisttable
);
2294 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
2296 maepad_warning("Cannot create checklist table");
2297 show_banner(mainview
, _("Error creating checklist table"));
2302 sqlite3_close(mainview
->db
);
2303 mainview
->db
= NULL
;
2305 mainview
->file_name
= filename
;
2306 mainview
->file_edited
= FALSE
;
2307 read_file_to_buffer(mainview
);
2309 /*add a starter memo*/
2311 node
= g_malloc(sizeof(nodeData
));
2312 node
->typ
= NODE_SKETCH
;
2313 node
->name
= _("My first memo");
2314 node
->namepix
= NULL
;
2318 add_new_node(node
, mainview
, TRUE
);
2319 /*gtk_paned_set_position(GTK_PANED(mainview->hpaned), 180);*/
2320 write_buffer_to_file(mainview
);
2323 busy_reset(mainview
);
2326 gboolean
reset_ctree(GtkTreeModel
* model
, GtkTreePath
* path
, GtkTreeIter
* iter
, gpointer data
)
2330 gtk_tree_model_get(model
, iter
, NODE_DATA
, &node
, -1);
2336 g_object_unref(node
->namepix
);
2339 gtk_tree_store_set(GTK_TREE_STORE(model
), iter
, NODE_DATA
, NULL
, -1);
2344 void new_file(MainView
* mainview
)
2346 busy_enter(mainview
);
2348 * clear buffer, filename and free buffer text
2350 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(mainview
->buffer
), "", -1);
2351 mainview
->file_name
= NULL
;
2352 mainview
->file_edited
= FALSE
;
2353 mainview
->newnodedialog_createchild
= TRUE
;
2355 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
));
2357 g_object_ref(model
);
2358 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), NULL
);
2360 gtk_tree_model_foreach(model
, (GtkTreeModelForeachFunc
) reset_ctree
, (gpointer
) mainview
);
2364 * gtk_tree_store_clear(GTK_TREE_STORE(model));
2366 GtkTreePath
*path
= gtk_tree_path_new_from_indices(0, -1);
2369 if (gtk_tree_model_get_iter(model
, &iter
, path
))
2373 gtk_tree_store_remove(GTK_TREE_STORE(model
), &iter
);
2375 while(gtk_tree_store_iter_is_valid(GTK_TREE_STORE(model
), &iter
));
2377 gtk_tree_path_free(path
);
2379 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), model
);
2380 g_object_unref(model
);
2382 busy_leave(mainview
);
2388 void callback_file_open(GtkAction
* action
, gpointer data
)
2390 gchar
*filename
= NULL
;
2391 MainView
*mainview
= (MainView
*) data
;
2392 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2394 filename
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_OPEN
, NULL
, NULL
);
2395 if (filename
== NULL
) {
2399 if (closefile(mainview
) == FALSE
) {
2403 open_file(filename
, mainview
);
2407 gboolean
open_file(gchar
* filename
, MainView
* mainview
)
2411 /* Don't open nodes when opening a file */
2412 mainview
->can_show_node_view
= FALSE
;
2414 busy_enter(mainview
);
2416 while(filename
!= NULL
)
2420 if (stat(filename
, &s
) == -1) break;
2422 mainview
->file_name
= g_strdup(filename
);
2423 gboolean res
= read_file_to_buffer(mainview
);
2427 g_free(mainview
->file_name
);
2428 mainview
->file_name
= NULL
;
2431 mainview
->file_edited
= FALSE
;
2436 busy_leave(mainview
);
2440 void callback_about_link(GtkAboutDialog
*about
, const gchar
*link
, gpointer data
)
2442 MainView
*mainview
= (MainView
*) data
;
2443 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2444 osso_rpc_run_with_defaults(mainview
->data
->osso
, "osso_browser", OSSO_BROWSER_OPEN_NEW_WINDOW_REQ
, NULL
,
2445 DBUS_TYPE_STRING
, link
, DBUS_TYPE_INVALID
);
2448 void callback_about(GtkAction
* action
, gpointer data
)
2450 MainView
* mainview
= (MainView
*)data
;
2451 he_about_dialog_present(mainview_get_dialog_parent(mainview
),
2452 NULL
/* auto-detect app name */,
2455 _("A node-based memory pad for Maemo"),
2456 _("(c) 2010 Thomas Perl"),
2457 "http://thpinfo.com/2010/maepad/",
2458 "https://garage.maemo.org/tracker/?group_id=1291",
2459 "http://thpinfo.com/2010/maepad/donate");
2465 void callback_file_save(GtkAction
* action
, gpointer data
)
2467 gchar
*filename
= NULL
;
2468 MainView
*mainview
= (MainView
*) data
;
2469 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2472 * check is we had a new file
2474 if (mainview
->file_name
!= NULL
)
2476 write_buffer_to_file(mainview
);
2480 filename
= interface_file_chooser(mainview
, GTK_FILE_CHOOSER_ACTION_SAVE
, "maemopaddata", "db");
2482 * if we got a file name from chooser -> save file
2484 if (filename
!= NULL
)
2486 mainview
->file_name
= filename
;
2487 write_buffer_to_file(mainview
);
2488 mainview
->file_edited
= FALSE
;
2493 void callback_shapemenu(GtkAction
* action
, GtkWidget
* wid
)
2495 gint style
= GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(wid
)));
2496 MainView
* mainview
= gtk_object_get_data(GTK_OBJECT(wid
), "m");
2497 g_assert(mainview
!= NULL
);
2499 if (style
>= 0 && style
< SKETCHSHAPE_COUNT
) {
2500 /* We use the sketch widget's enum for available styles */
2501 sketchwidget_set_shape(mainview
->sk
, style
);
2503 /* Draw the correct indicator for the current shape */
2504 GtkWidget
* pix
= GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(wid
), "i"));
2505 g_assert(pix
!= NULL
);
2506 gtk_widget_show(pix
);
2507 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview
->shape_tb
), pix
);
2509 /* Fail. We shouldn't get here at all! */
2510 g_error("Invalid style ID from shape menu: %d", style
);
2516 void callback_eraser(GtkAction
* action
, MainView
* mainview
)
2518 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2520 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->eraser_tb
))) {
2521 /* Eraser on: Set pen color to white */
2522 GdkColor white
= { 0, 0xFFFF, 0xFFFF, 0xFFFF };
2523 sketchwidget_set_brushcolor(mainview
->sk
, white
);
2525 /* Eraser off: Set default color again (or black) */
2526 GdkColor black
= {0, 0, 0, 0};
2527 if (mainview
->current_color
== NULL
) {
2528 mainview
->current_color
= gdk_color_copy(&black
);
2530 sketchwidget_set_brushcolor(mainview
->sk
, *(mainview
->current_color
));
2534 void callback_menu(GtkAction
* action
, GtkWidget
* menu
)
2536 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, NULL
, NULL
, 0, GDK_CURRENT_TIME
);
2539 void callback_brushsizetb(GtkAction
* action
, MainView
*mainview
)
2541 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2542 callback_menu(NULL
, mainview
->brushsizemenu
);
2545 void callback_brushsize(GtkAction
* action
, GtkWidget
* wid
)
2547 int bsize
= (int)gtk_object_get_user_data(GTK_OBJECT(wid
));
2548 MainView
*mainview
= gtk_object_get_data(GTK_OBJECT(wid
), "m");
2550 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2552 sketchwidget_set_brushsize(mainview
->sk
, bsize
);
2554 GtkWidget
*pix
= gtk_object_get_data(GTK_OBJECT(wid
), "i");
2556 gtk_widget_show(pix
);
2557 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview
->brushsize_tb
), pix
);
2560 void callback_sketchlines(GtkAction
* action
, GtkWidget
* wid
)
2562 int style
= (int)gtk_object_get_user_data(GTK_OBJECT(wid
));
2563 MainView
*mainview
= gtk_object_get_data(GTK_OBJECT(wid
), "m");
2565 g_assert(mainview
!= NULL
);
2567 nodeData
*nd
= getSelectedNode(mainview
);
2568 gboolean doit
= FALSE
;
2570 if (nd
!= NULL
&& nd
->typ
== NODE_SKETCH
)
2572 nd
->flags
&= ~NODEFLAG_SKETCHLINES
;
2573 nd
->flags
&= ~NODEFLAG_SKETCHGRAPH
;
2574 /* sketchwidget_set_edited(mainview->sk, TRUE);*/ /*we call this on openfile, so this messes things up*/
2580 sketchwidget_set_backstyle(mainview
->sk
, SKETCHBACK_NONE
);
2582 else if (style
== 1)
2584 sketchwidget_set_backstyle(mainview
->sk
, SKETCHBACK_LINES
);
2586 nd
->flags
|= NODEFLAG_SKETCHLINES
;
2588 else if (style
== 2)
2590 sketchwidget_set_backstyle(mainview
->sk
, SKETCHBACK_GRAPH
);
2592 nd
->flags
|= NODEFLAG_SKETCHGRAPH
;
2595 GtkWidget
*pix
= gtk_object_get_data(GTK_OBJECT(wid
), "i");
2597 gtk_widget_show(pix
);
2598 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(mainview
->sketchlines_tb
), pix
);
2601 void callback_color(GtkAction
* action
, MainView
* mainview
)
2603 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2605 nodeData
*nd
= getSelectedNode(mainview
);
2606 if (nd
== NULL
) return;
2608 HeSimpleColorDialog
* dialog
= HE_SIMPLE_COLOR_DIALOG(he_simple_color_dialog_new());
2609 gtk_window_set_transient_for(GTK_WINDOW(dialog
), mainview_get_dialog_parent(mainview
));
2611 if (mainview
->current_color
) {
2612 he_simple_color_dialog_set_color(dialog
, mainview
->current_color
);
2615 if (gtk_dialog_run(GTK_DIALOG(dialog
)) != GTK_RESPONSE_OK
) {
2616 gtk_widget_destroy(GTK_WIDGET(dialog
));
2620 gdk_color_free(mainview
->current_color
);
2621 mainview
->current_color
= he_simple_color_dialog_get_color(dialog
);
2623 gtk_widget_destroy(GTK_WIDGET(dialog
));
2627 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->eraser_tb
), FALSE
);
2628 sketchwidget_set_brushcolor(mainview
->sk
, *(mainview
->current_color
));
2630 case NODE_CHECKLIST
:
2631 { /* Put in a separate block to allow new local variables */
2632 GtkTreeModel
* model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
2633 GtkTreeSelection
* selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
));
2634 GList
* selected
= gtk_tree_selection_get_selected_rows(selection
, NULL
);
2636 gchar
* color_string
= g_strdup_printf("#%02x%02x%02x",
2637 mainview
->current_color
->red
>> 8,
2638 mainview
->current_color
->green
>> 8,
2639 mainview
->current_color
->blue
>> 8);
2641 GList
* cur
= selected
;
2642 while (cur
!= NULL
) {
2643 GtkTreePath
* path
= cur
->data
;
2645 if (gtk_tree_model_get_iter(model
, &iter
, path
)) {
2646 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_COLOR
, color_string
, -1);
2648 gtk_tree_path_free(path
);
2652 g_list_free(selected
);
2653 g_free(color_string
);
2657 g_assert_not_reached();
2661 void callback_color_invoke(GtkAction
* action
, gpointer data
)
2663 MainView
*mainview
= (MainView
*) data
;
2664 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2665 gtk_button_clicked(GTK_BUTTON(mainview
->colorbutton_tb
));
2670 void callback_pressure(GtkAction
* action
, MainView
*mainview
)
2672 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2674 nodeData
*nd
= getSelectedNode(mainview
);
2678 if (nd
->typ
!= NODE_SKETCH
)
2681 /* pressure sensitivity disabled for now...
2682 mainview->sk->pressuresensitivity=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(mainview->tools_pressure));*/
2686 void callback_wordwrap(GtkWidget
* widget
, gpointer user_data
)
2688 MainView
* mainview
= (MainView
*)user_data
;
2689 nodeData
* nd
= getSelectedNode(mainview
);
2690 GtkWrapMode wrap_mode
;
2692 if (nd
== NULL
|| nd
->typ
!= NODE_TEXT
) {
2696 if (hildon_check_button_get_active(HILDON_CHECK_BUTTON(mainview
->menu_button_wordwrap
))) {
2697 nd
->flags
|= NODEFLAG_WORDWRAP
;
2698 wrap_mode
= GTK_WRAP_WORD_CHAR
;
2700 nd
->flags
&= ~NODEFLAG_WORDWRAP
;
2701 wrap_mode
= GTK_WRAP_NONE
;
2704 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(mainview
->textview
), wrap_mode
);
2708 void callback_font(GtkAction
* action
, gpointer data
)
2710 MainView
*mainview
= (MainView
*) data
;
2711 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2713 nodeData
*nd
= getSelectedNode(mainview
);
2717 if (nd
->typ
!= NODE_TEXT
)
2720 HildonFontSelectionDialog
*dialog
= HILDON_FONT_SELECTION_DIALOG(hildon_font_selection_dialog_new(NULL
, NULL
));
2722 gboolean gotsel
=wp_text_buffer_has_selection(mainview
->buffer
);
2725 WPTextBufferFormat fmt
;
2726 wp_text_buffer_get_attributes(mainview
->buffer
, &fmt
, gotsel
);
2729 if (fmt
.text_position
==TEXT_POSITION_SUPERSCRIPT
) ri
=1;
2730 else if (fmt
.text_position
==TEXT_POSITION_SUBSCRIPT
) ri
=-1;
2732 g_object_set(G_OBJECT(dialog
),
2733 "family-set", fmt
.cs
.font
,
2734 "family", wp_get_font_name(fmt
.font
),
2735 "size-set", fmt
.cs
.font_size
,
2736 "size", wp_font_size
[fmt
.font_size
],
2737 "color-set", fmt
.cs
.color
,
2738 "color", &fmt
.color
,
2739 "bold-set", fmt
.cs
.bold
,
2741 "italic-set", fmt
.cs
.italic
,
2742 "italic", fmt
.italic
,
2743 "underline-set", fmt
.cs
.underline
,
2744 "underline", fmt
.underline
,
2745 "strikethrough-set", fmt
.cs
.strikethrough
,
2746 "strikethrough", fmt
.strikethrough
,
2747 "position-set", fmt
.cs
.text_position
,
2751 gtk_widget_show_all(GTK_WIDGET(dialog
));
2752 if (gtk_dialog_run(GTK_DIALOG(dialog
)) == GTK_RESPONSE_OK
)
2754 gboolean bold
, italic
, underline
, strikethrough
;
2755 gchar
*family
= NULL
;
2756 gint size
, position
;
2757 GdkColor
*color
=NULL
;
2758 gboolean set_family
, set_size
, set_bold
, set_italic
, set_underline
, set_strikethrough
, set_color
, set_position
;
2760 g_object_get(G_OBJECT(dialog
), "family", &family
, "size", &size
, "bold", &bold
, "italic", &italic
,
2761 "underline", &underline
, "strikethrough", &strikethrough
,
2762 "family-set", &set_family
, "size-set", &set_size
, "bold-set", &set_bold
, "italic-set", &set_italic
,
2763 "underline-set", &set_underline
, "strikethrough-set", &set_strikethrough
,
2764 "color", &color
, "color-set", &set_color
, "position", &position
, "position-set", &set_position
,
2767 wp_text_buffer_get_attributes(mainview
->buffer
, &fmt
, FALSE
);
2768 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;
2770 if (set_family
) { fmt
.font
=wp_get_font_index(family
, 1); fmt
.cs
.font
=1; }
2771 if (set_size
) { fmt
.font_size
=wp_get_font_size_index(size
, 16); fmt
.cs
.font_size
=1; }
2773 if (set_strikethrough
)
2775 fmt
.cs
.strikethrough
=1;
2776 fmt
.strikethrough
=strikethrough
;
2782 GLIB WARNING ** GLib-GObject - IA__g_object_set_valist: object class `GtkTextTag' has no property named `'
2785 fmt
.color
.pixel
=color
->pixel
;
2786 fmt
.color
.red
=color
->red
;
2787 fmt
.color
.green
=color
->green
;
2788 fmt
.color
.blue
=color
->blue
;
2793 if (position
==1) ri
=TEXT_POSITION_SUPERSCRIPT
;
2794 else if (position
==-1) ri
=TEXT_POSITION_SUBSCRIPT
;
2795 else ri
=TEXT_POSITION_NORMAL
;
2797 fmt
.cs
.text_position
=1;
2798 fmt
.text_position
=ri
;
2814 fmt
.underline
=underline
;
2817 wp_text_buffer_set_format(mainview
->buffer
, &fmt
);
2820 gtk_widget_destroy(GTK_WIDGET(dialog
));
2823 void callback_fontstyle(GtkAction
* action
, GtkWidget
* wid
)
2825 MainView
*mainview
= gtk_object_get_data(GTK_OBJECT(wid
), "m");
2826 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2828 nodeData
*nd
= getSelectedNode(mainview
);
2832 if (nd
->typ
== NODE_TEXT
)
2834 gboolean act
=gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(wid
));
2836 gint style
= (gint
)gtk_object_get_data(GTK_OBJECT(wid
), "s");
2837 wp_text_buffer_set_attribute(mainview
->buffer
, style
, (gpointer
)act
);
2839 else if (nd
->typ
== NODE_CHECKLIST
)
2841 gboolean act
=gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(wid
));
2842 gint style
= (gint
)gtk_object_get_data(GTK_OBJECT(wid
), "s");
2843 if (style
!=WPT_BOLD
&& style
!=WPT_STRIKE
&& style
!=WPT_LEFT
) return;
2845 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
2846 GList
* l
=gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
)), NULL
);
2848 gint styletoset_weight
=PANGO_WEIGHT_NORMAL
;
2849 gboolean styletoset_strike
=FALSE
;
2850 gboolean checkit
=FALSE
;
2852 if (style
==WPT_BOLD
&& act
==TRUE
) styletoset_weight
=PANGO_WEIGHT_BOLD
;
2853 else if (style
==WPT_STRIKE
&& act
==TRUE
) styletoset_strike
=TRUE
;
2854 else if (style
==WPT_LEFT
&& act
==TRUE
) checkit
=TRUE
;
2859 GtkTreePath
*path
=cur
->data
;
2862 if (gtk_tree_model_get_iter(model
, &iter
, path
))
2864 if (style
==WPT_BOLD
) gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_BOLD
, styletoset_weight
, -1);
2865 else if (style
==WPT_STRIKE
) gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_STRIKE
, styletoset_strike
, -1);
2866 else if (style
==WPT_LEFT
) {
2867 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_CHECKED
, checkit
, -1);
2869 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_ICON_NAME
, "widgets_tickmark_list", -1);
2871 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_ICON_NAME
, NULL
, -1);
2875 gtk_tree_path_free(path
);
2880 mainview
->checklist_edited
= TRUE
;
2885 callback_sharing(GtkWidget
* widget
, gpointer user_data
)
2887 MainView
* mainview
= (MainView
*)user_data
;
2888 nodeData
* nd
= getSelectedNode(mainview
);
2889 gchar
* filename
= g_strdup("/tmp/untitled.png");
2892 if (nd
== NULL
|| nd
->typ
!= NODE_SKETCH
) {
2893 show_banner(mainview
, _("Only sketches can be shared"));
2897 if (nd
->name
!= NULL
) {
2899 filename
= g_strdup_printf("/tmp/%s.png", nd
->name
);
2902 busy_enter(mainview
);
2903 GdkPixmap
* skpix
= sketchwidget_get_Pixmap(mainview
->sk
);
2904 GtkWidget
* skdr
= sketchwidget_get_drawingarea(mainview
->sk
);
2905 GdkPixbuf
* pixbuf
= gdk_pixbuf_get_from_drawable(NULL
,
2906 GDK_DRAWABLE(skpix
), NULL
, 0, 0, 0, 0,
2907 skdr
->allocation
.width
, skdr
->allocation
.height
);
2909 if (pixbuf
== NULL
) {
2910 show_banner(mainview
, _("Memo is empty"));
2914 if (!gdk_pixbuf_save(pixbuf
, filename
, "png", NULL
, NULL
)) {
2915 show_banner(mainview
, _("File export failed"));
2919 uri
= g_strdup_printf("file://%s", filename
);
2921 sharing_dialog_with_file(mainview
->data
->osso
,
2922 mainview_get_dialog_parent(mainview
),
2926 g_object_unref(skpix
);
2929 busy_leave(mainview
);
2933 callback_remove_checked(GtkWidget
* widget
, gpointer user_data
)
2935 MainView
* mainview
= (MainView
*)user_data
;
2936 nodeData
* nd
= getSelectedNode(mainview
);
2938 GtkTreeModel
* model
= NULL
;
2939 GList
* checked_items
= NULL
;
2940 gchar
* question
= NULL
;
2943 if (nd
== NULL
|| nd
->typ
!= NODE_CHECKLIST
) {
2947 /* Get a list of checked items */
2948 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
2949 if (!gtk_tree_model_get_iter_first(model
, &iter
)) {
2953 busy_enter(mainview
);
2955 gboolean checked
= FALSE
;
2956 gtk_tree_model_get(model
, &iter
, CHECKNODE_CHECKED
, &checked
, -1);
2959 GtkTreePath
* path
= gtk_tree_model_get_path(model
, &iter
);
2961 checked_items
= g_list_append(checked_items
,
2962 gtk_tree_row_reference_new(model
, path
));
2965 gtk_tree_path_free(path
);
2967 } while (gtk_tree_model_iter_next(model
, &iter
));
2968 busy_leave(mainview
);
2970 if (checked_items
== NULL
) {
2971 show_banner(mainview
, _("No checked items in checklist"));
2975 question
= g_strdup_printf(N_("Remove %d checked item?", "Remove %d checked items?", count
), count
);
2976 if (show_confirmation(mainview
, question
)) {
2977 /* Remove the checklist items from the list */
2978 checklist_remove_rowrefs(mainview
, checked_items
, TRUE
);
2980 /* Free the allocated row references + list */
2981 GList
* cur
= checked_items
;
2982 while (cur
!= NULL
) {
2983 GtkTreeRowReference
* rowref
= cur
->data
;
2984 gtk_tree_row_reference_free(rowref
);
2987 g_list_free(checked_items
);
2992 void callback_textbuffer_move(WPTextBuffer
*textbuffer
, MainView
*mainview
)
2994 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
2997 gboolean gotsel=wp_text_buffer_has_selection(mainview->buffer);
2999 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->bold_tb), gotsel);
3000 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->italic_tb), gotsel);
3001 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->underline_tb), gotsel);
3002 _toggle_tool_button_set_inconsistent(GTK_TOGGLE_TOOL_BUTTON(mainview->bullet_tb), gotsel);
3004 WPTextBufferFormat fmt
;
3005 wp_text_buffer_get_attributes(mainview
->buffer
, &fmt
, FALSE
/*gotsel*/);
3007 g_signal_handlers_block_by_func(mainview
->bold_tb
, callback_fontstyle
, mainview
->bold_tb
);
3008 g_signal_handlers_block_by_func(mainview
->italic_tb
, callback_fontstyle
, mainview
->italic_tb
);
3009 g_signal_handlers_block_by_func(mainview
->underline_tb
, callback_fontstyle
, mainview
->underline_tb
);
3010 g_signal_handlers_block_by_func(mainview
->bullet_tb
, callback_fontstyle
, mainview
->bullet_tb
);
3012 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->bold_tb
), fmt
.bold
);
3013 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->italic_tb
), fmt
.italic
);
3014 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->underline_tb
), fmt
.underline
);
3015 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->bullet_tb
), fmt
.bullet
);
3017 g_signal_handlers_unblock_by_func(mainview
->bold_tb
, callback_fontstyle
, mainview
->bold_tb
);
3018 g_signal_handlers_unblock_by_func(mainview
->italic_tb
, callback_fontstyle
, mainview
->italic_tb
);
3019 g_signal_handlers_unblock_by_func(mainview
->underline_tb
, callback_fontstyle
, mainview
->underline_tb
);
3020 g_signal_handlers_unblock_by_func(mainview
->bullet_tb
, callback_fontstyle
, mainview
->bullet_tb
);
3023 gint
wp_savecallback(const gchar
*buffer
, GString
* gstr
)
3025 gstr
=g_string_append(gstr
, buffer
);
3029 void callback_undo(GtkAction
* action
, MainView
* mainview
)
3031 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
3033 nodeData
*nd
= getSelectedNode(mainview
);
3035 if (nd
== NULL
) return;
3037 if (nd
->typ
== NODE_SKETCH
) sketchwidget_undo(mainview
->sk
);
3038 else if (nd
->typ
== NODE_TEXT
) wp_text_buffer_undo(mainview
->buffer
);
3041 void callback_redo(GtkAction
* action
, MainView
* mainview
)
3043 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
3045 nodeData
*nd
= getSelectedNode(mainview
);
3047 if (nd
== NULL
) return;
3049 if (nd
->typ
== NODE_SKETCH
) sketchwidget_redo(mainview
->sk
);
3050 else if (nd
->typ
== NODE_TEXT
) wp_text_buffer_redo(mainview
->buffer
);
3053 void callback_undotoggle(gpointer widget
, gboolean st
, MainView
* mainview
)
3055 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
3057 gtk_widget_set_sensitive(GTK_WIDGET(mainview
->undo_tb
), st
);
3060 void callback_redotoggle(gpointer widget
, gboolean st
, MainView
* mainview
)
3062 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
3064 gtk_widget_set_sensitive(GTK_WIDGET(mainview
->redo_tb
), st
);
3067 gboolean
close_cb(GtkWidget
* widget
, GdkEventAny
* event
, MainView
* mainview
)
3069 callback_file_close(NULL
, mainview
);
3074 mainview_click_on_current_node(MainView
* mainview
)
3076 GtkTreeSelection
* selection
= NULL
;
3077 GtkTreeModel
* model
= NULL
;
3080 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
3081 if (gtk_tree_selection_get_selected(selection
, &model
, &iter
)) {
3082 GtkTreePath
* path
= gtk_tree_model_get_path(model
, &iter
);
3084 mainview
->can_show_node_view
= TRUE
;
3085 gtk_tree_view_set_cursor(GTK_TREE_VIEW(mainview
->treeview
),
3088 gtk_tree_path_free(path
);
3093 on_main_view_key_press(GtkWidget
* widget
, GdkEventKey
* event
, gpointer user_data
)
3095 MainView
* mainview
= (MainView
*)user_data
;
3096 gboolean result
= FALSE
;
3098 switch (event
->keyval
) {
3103 /* Open selected memo in node view */
3104 mainview_click_on_current_node(mainview
);
3109 /* Save changes to file ("write buffer") */
3110 callback_file_save(NULL
, mainview
);
3114 /* Delete selected node (with confirmation) */
3115 callback_file_delete_node(NULL
, mainview
);
3120 /* Add new memo to list */
3121 callback_file_new_node(NULL
, mainview
);
3126 /* Replace (edit) name of selected memo */
3127 callback_file_rename_node(NULL
, mainview
);
3131 if (mainview
->main_view_prev_keyval
== GDK_g
) {
3132 /* Goto (=select) first memo */
3133 mainview
->can_show_node_view
= FALSE
;
3134 nodelist_select(mainview
, TREEVIEW_SELECT_FIRST
);
3136 /* Don't remember this key for the next keypress */
3137 mainview
->main_view_prev_keyval_reset
= TRUE
;
3143 /* Goto (=select) last memo */
3144 mainview
->can_show_node_view
= FALSE
;
3145 nodelist_select(mainview
, TREEVIEW_SELECT_LAST
);
3151 /* Goto (=select) next memo */
3152 mainview
->can_show_node_view
= FALSE
;
3153 nodelist_select(mainview
, TREEVIEW_SELECT_NEXT
);
3159 /* Goto (=select) previous memo */
3160 mainview
->can_show_node_view
= FALSE
;
3161 nodelist_select(mainview
, TREEVIEW_SELECT_PREVIOUS
);
3173 on_node_view_key_press(GtkWidget
* widget
, GdkEventKey
* event
, gpointer user_data
)
3175 MainView
* mainview
= (MainView
*)user_data
;
3176 nodeData
* nd
= getSelectedNode(mainview
);
3177 gboolean result
= FALSE
;
3183 switch (event
->keyval
) {
3186 if (nd
->typ
!= NODE_TEXT
) {
3187 /* Save changes to file ("write buffer") */
3188 callback_file_save(NULL
, mainview
);
3193 if (event
->state
& GDK_SHIFT_MASK
) {
3194 /* Remove current memo (with confirmation) */
3195 callback_file_delete_node(NULL
, mainview
);
3197 } else if (nd
->typ
== NODE_CHECKLIST
) {
3198 /* Remove current item (with confirmation) */
3199 callback_checklist_delete(NULL
, mainview
);
3201 } else if (nd
->typ
== NODE_SKETCH
) {
3202 /* Undo last sketch action */
3203 callback_undo(NULL
, mainview
);
3208 if (nd
->typ
== NODE_CHECKLIST
) {
3209 /* Toggle check of current item */
3210 maepad_toggle_gtk_toggle_tool_button(mainview
->check_tb
);
3212 } else if (nd
->typ
== NODE_SKETCH
) {
3213 /* Toggle eraser tool */
3214 maepad_toggle_gtk_toggle_tool_button(mainview
->eraser_tb
);
3220 if (nd
->typ
!= NODE_TEXT
) {
3221 /* Toggle fullscreen mode */
3222 callback_fullscreen(NULL
, mainview
);
3228 if (nd
->typ
!= NODE_TEXT
) {
3229 /* Hide node view, go to main view ("left") */
3230 gtk_widget_hide(GTK_WIDGET(mainview
->data
->node_view
));
3236 if (nd
->typ
== NODE_CHECKLIST
) {
3237 /* Insert new checklist item */
3238 callback_checklist_add(NULL
, mainview
);
3243 if (nd
->typ
== NODE_CHECKLIST
) {
3244 if (mainview
->node_view_prev_keyval
== GDK_d
) {
3245 /* Yank selected items, then remove them silently */
3246 callback_edit_copy(NULL
, mainview
);
3247 callback_checklist_delete_real(mainview
);
3248 show_banner(mainview
, _("Item yanked to clipboard"));
3250 /* Don't remember this key for the next keypress */
3251 mainview
->node_view_prev_keyval_reset
= TRUE
;
3258 if (nd
->typ
== NODE_CHECKLIST
) {
3259 if (mainview
->node_view_prev_keyval
== GDK_y
) {
3260 /* Non-destructive yanking of items */
3261 callback_edit_copy(NULL
, mainview
);
3262 show_banner(mainview
, _("Item yanked to clipboard"));
3264 /* Don't remember this key for the next keypress */
3265 mainview
->node_view_prev_keyval_reset
= TRUE
;
3273 if (nd
->typ
== NODE_CHECKLIST
) {
3274 /* Paste text in clipboard as items */
3275 callback_edit_paste(NULL
, mainview
);
3280 if (nd
->typ
== NODE_CHECKLIST
) {
3281 if (mainview
->node_view_prev_keyval
== GDK_g
) {
3282 /* Goto (=select) first item */
3283 checklist_select(mainview
, TREEVIEW_SELECT_FIRST
);
3285 /* Don't remember this key for the next keypress */
3286 mainview
->node_view_prev_keyval_reset
= TRUE
;
3293 if (nd
->typ
== NODE_CHECKLIST
) {
3294 /* Goto (=select) last item */
3295 checklist_select(mainview
, TREEVIEW_SELECT_LAST
);
3302 if (nd
->typ
== NODE_CHECKLIST
) {
3303 /* Goto (=select) next item */
3304 checklist_select(mainview
, TREEVIEW_SELECT_NEXT
);
3306 } else if (nd
->typ
== NODE_SKETCH
) {
3307 /* Undo last sketch operation */
3308 callback_undo(NULL
, mainview
);
3315 if (nd
->typ
== NODE_CHECKLIST
) {
3316 /* Goto (=select) previous item */
3317 checklist_select(mainview
, TREEVIEW_SELECT_PREVIOUS
);
3319 } else if (nd
->typ
== NODE_SKETCH
) {
3320 /* Redo last sketch operation */
3321 callback_redo(NULL
, mainview
);
3327 if (nd
->typ
== NODE_CHECKLIST
) {
3328 /* Append text to current node */
3329 checklist_edit_selected(mainview
, LINE_EDIT_MODE_APPEND
);
3337 if (nd
->typ
== NODE_CHECKLIST
) {
3338 /* Replace (edit) text of current node */
3339 checklist_edit_selected(mainview
, LINE_EDIT_MODE_DEFAULT
);
3345 if (nd
->typ
== NODE_CHECKLIST
) {
3346 /* Prepend (insert) text to current node */
3347 checklist_edit_selected(mainview
, LINE_EDIT_MODE_PREPEND
);
3360 on_main_view_key_release(GtkWidget
* widget
, GdkEventKey
* event
, gpointer user_data
)
3362 MainView
* mainview
= (MainView
*)user_data
;
3364 if (mainview
->main_view_prev_keyval_reset
) {
3365 /* Forget last-pressed key value */
3366 mainview
->main_view_prev_keyval
= GDK_VoidSymbol
;
3367 mainview
->main_view_prev_keyval_reset
= FALSE
;
3369 /* Remember last keyval for double-press bindings */
3370 mainview
->main_view_prev_keyval
= event
->keyval
;
3377 on_node_view_key_release(GtkWidget
* widget
, GdkEventKey
* event
, gpointer user_data
)
3379 MainView
* mainview
= (MainView
*)user_data
;
3381 if (mainview
->node_view_prev_keyval_reset
) {
3382 /* Forget last-pressed key value */
3383 mainview
->node_view_prev_keyval
= GDK_VoidSymbol
;
3384 mainview
->node_view_prev_keyval_reset
= FALSE
;
3386 /* Remember last keyval for double-press bindings */
3387 mainview
->node_view_prev_keyval
= event
->keyval
;
3394 on_checklist_longpress_timeout(gpointer user_data
)
3396 MainView
* mainview
= (MainView
*)user_data
;
3397 callback_checklist_edit(NULL
, mainview
);
3398 mainview
->checklist_longpress_source_id
= 0;
3403 on_checklist_button_press(GtkWidget
* widget
, GdkEventButton
* event
, gpointer user_data
)
3405 MainView
* mainview
= (MainView
*)user_data
;
3407 GtkTreeViewColumn
* column
;
3408 GtkTreeSelection
* selection
;
3410 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget
),
3417 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(widget
));
3419 if (gtk_tree_selection_path_is_selected(selection
, path
)) {
3420 if (column
== mainview
->checklist_column_check
) {
3421 /* Check column touched - toggle checklist item */
3422 maepad_toggle_gtk_toggle_tool_button(mainview
->check_tb
);
3423 } else if (column
== mainview
->checklist_column_text
) {
3424 mainview
->checklist_longpress_source_id
= g_timeout_add(
3425 CHECKLIST_LONGPRESS_EDIT_DELAY
,
3426 on_checklist_longpress_timeout
,
3432 gtk_tree_path_free(path
);
3439 checklist_abort_longpress(MainView
* mainview
)
3441 /* Abort the longpress action on the checklist */
3442 if (mainview
->checklist_longpress_source_id
!= 0) {
3443 g_source_remove(mainview
->checklist_longpress_source_id
);
3444 mainview
->checklist_longpress_source_id
= 0;
3449 on_checklist_button_release(GtkWidget
* widget
, GdkEventButton
* event
, gpointer user_data
)
3451 MainView
* mainview
= (MainView
*)user_data
;
3452 checklist_abort_longpress(mainview
);
3457 on_checklist_start_panning(HildonPannableArea
* area
, gpointer user_data
)
3459 MainView
* mainview
= (MainView
*)user_data
;
3460 checklist_abort_longpress(mainview
);
3464 void callback_fullscreen(GtkToolButton
* tool_button
, gpointer user_data
)
3466 MainView
* mainview
= (MainView
*)user_data
;
3467 gtk_window_fullscreen(GTK_WINDOW(mainview
->data
->node_view
));
3471 callback_sketch_button_toggled(HildonCheckButton
* button
, gpointer user_data
)
3473 MainView
* mainview
= (MainView
*)user_data
;
3474 gboolean active
= hildon_check_button_get_active(button
);
3476 if (GTK_WIDGET(button
) == GTK_WIDGET(mainview
->menu_button_square
)) {
3477 sketchwidget_set_shift(mainview
->sk
, active
);
3478 } else if (GTK_WIDGET(button
) == GTK_WIDGET(mainview
->menu_button_filled
)) {
3479 sketchwidget_set_fillmode(mainview
->sk
, active
);
3483 void callback_buffer_modified(GtkAction
* action
, gpointer data
)
3485 MainView
*mainview
= (MainView
*) data
;
3486 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
3488 mainview
->file_edited
= TRUE
;
3491 GtkTreeRowReference
*read_sqlite3_data(MainView
* mainview
, unsigned int parentid
, GtkTreeRowReference
* parenttree
, unsigned int selected
, GtkTreeStore
* model
)
3493 GtkTreeRowReference
*resref
= NULL
;
3497 g_snprintf(q
, sizeof(q
), "SELECT nodeid, bodytype, name, nameblob, lastmodified, flags FROM %s WHERE parent=%d ORDER BY ord", datatable_tmpname
, parentid
);
3499 sqlite3_stmt
*stmt
= NULL
;
3501 int rc
= sqlite3_prepare(mainview
->db
, q
, strlen(q
), &stmt
, &dum
);
3505 maepad_warning("Error reading SQLite3 data: %s", sqlite3_errmsg(mainview
->db
));
3510 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
3512 rc
= sqlite3_step(stmt
);
3513 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
3515 else if (rc
== SQLITE_ROW
)
3517 int nodeid
= sqlite3_column_int(stmt
, 0);
3518 int typ
= sqlite3_column_int(stmt
, 1);
3519 const unsigned char *name
= sqlite3_column_text(stmt
, 2);
3520 const unsigned char *nameblob
= sqlite3_column_text(stmt
, 3);
3521 int lastmod
= sqlite3_column_int(stmt
, 4);
3522 int flags
= sqlite3_column_int(stmt
, 5);
3524 if ((typ
!= NODE_TEXT
&& typ
!= NODE_SKETCH
&& typ
!= NODE_CHECKLIST
) || (name
== NULL
&& nameblob
== NULL
)) {
3525 maepad_warning("Unknown node type in database: %d (skipping)", typ
);
3529 nodeData
*node
= g_malloc(sizeof(nodeData
));
3531 node
->sql3id
= nodeid
;
3533 node
->flags
= flags
;
3535 node
->namepix
= NULL
;
3537 node
->name
= g_strdup((char *)name
);
3539 node
->name
= g_strdup(_("Unnamed memo"));
3541 /*if (nameblob != NULL)
3543 int blobsize = sqlite3_column_bytes(stmt, 3);
3545 GdkPixbufLoader *pl = gdk_pixbuf_loader_new_with_type("png", NULL);
3548 gdk_pixbuf_loader_write(pl, (guchar *) nameblob, blobsize, &err);
3551 fprintf(stderr, "Error loading nodename! %s\n", err->message);
3555 gdk_pixbuf_loader_close(pl, NULL);
3556 GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(pl);
3558 if (GDK_IS_PIXBUF(pixbuf))
3559 node->namepix = pixbuf;
3561 node
->lastMod
= lastmod
;
3563 GtkTreeIter parentiter
, newiter
;
3566 if (parenttree
!= NULL
)
3568 GtkTreePath
*pa
= gtk_tree_row_reference_get_path(parenttree
);
3570 gtk_tree_model_get_iter(GTK_TREE_MODEL(model
), &parentiter
, pa
);
3571 gtk_tree_path_free(pa
);
3575 gtk_tree_store_append(model
, &newiter
, par
);
3576 gtk_tree_store_set(model
, &newiter
, NODE_NAME
, format_overview_name(node
, NULL
), NODE_PIXBUF
, node
->namepix
, NODE_DATA
, node
, -1);
3578 GtkTreePath
*pa
= gtk_tree_model_get_path(GTK_TREE_MODEL(model
), &newiter
);
3580 GtkTreeRowReference
*newref
= gtk_tree_row_reference_new(GTK_TREE_MODEL(model
), pa
);
3582 if (selected
== nodeid
)
3585 gtk_tree_path_free(pa
);
3586 GtkTreeRowReference
*r
= read_sqlite3_data(mainview
, nodeid
, newref
, selected
,
3589 if (resref
!= newref
)
3590 gtk_tree_row_reference_free(newref
);
3597 gtk_tree_row_reference_free(r
); /*safeguard */
3603 sqlite3_finalize(stmt
);
3605 return (resref
); /*ref to supposed-to-be-selected treeitem */
3611 gboolean
read_file_to_buffer(MainView
* mainview
)
3615 g_assert(mainview
!= NULL
);
3616 gboolean res
= FALSE
;
3618 gchar
*filename
= mainview
->file_name
;
3621 mainview
->file_name
= filename
;
3622 mainview
->loading
=TRUE
;
3624 maepad_message("Reading database file: %s", filename
);
3627 sqlite3_stmt
*stmt
= NULL
;
3629 rc
= sqlite3_open(filename
, &mainview
->db
);
3634 maepad_warning("Cannot open database %s: %s", filename
, sqlite3_errmsg(mainview
->db
));
3638 sqlite3_exec(mainview
->db
, "PRAGMA synchronous = OFF;", NULL
, NULL
, NULL
);
3640 char *q
= "SELECT skey, sval FROM settings";
3643 rc
= sqlite3_prepare(mainview
->db
, q
, strlen(q
), &stmt
, &dum
);
3646 maepad_warning("Error reading settings: %s", sqlite3_errmsg(mainview
->db
));
3650 unsigned int selectedCard
= 0;
3651 unsigned int curDataVersion
= 0;
3652 unsigned int curChecklistVersion
= 0;
3655 while(rc
== SQLITE_BUSY
|| rc
== SQLITE_ROW
)
3657 rc
= sqlite3_step(stmt
);
3658 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
|| rc
== SQLITE_DONE
)
3660 else if (rc
== SQLITE_ROW
)
3662 const gchar
* col_key
= (const gchar
*)sqlite3_column_text(stmt
, 0);
3663 const gchar
* col_val
= (const gchar
*)sqlite3_column_text(stmt
, 1);
3664 if (!strcmp(col_key
, "selectedNode"))
3666 gint tmp
= atoi((char *)col_val
);
3671 if (!strcmp(col_key
, "dataVersion"))
3673 gint tmp
= atoi((char *)col_val
);
3676 curDataVersion
= tmp
;
3678 if (!strcmp(col_key
, "checklistVersion"))
3680 gint tmp
= atoi((char *)col_val
);
3683 curChecklistVersion
= tmp
;
3685 if (!strcmp(col_key
, "newNodeDlgCreateChild"))
3687 gint tmp
= atoi((char *)col_val
);
3689 mainview
->newnodedialog_createchild
= TRUE
;
3691 mainview
->newnodedialog_createchild
= FALSE
;
3693 if (!strcmp(col_key
, "brushSize"))
3695 gint tmp
= atoi((char *)col_val
);
3696 if (tmp
>0) sk_set_brushsize(mainview
, tmp
);
3698 if (!strcmp(col_key
, "brushColor"))
3700 unsigned long tmp
= atol((char *)col_val
);
3703 c2
.red
= ((tmp
& 0xFF0000) >> 16) << 8;
3704 c2
.green
= ((tmp
& 0xFF00) >> 8) << 8;
3705 c2
.blue
= (tmp
& 0xFF) << 8;
3706 sketchwidget_set_brushcolor(mainview
->sk
, c2
);
3708 if (mainview
->current_color
!= NULL
) {
3709 gdk_color_free(mainview
->current_color
);
3711 mainview
->current_color
= gdk_color_copy(&c2
);
3716 if (rc
== SQLITE_ERROR
|| rc
== SQLITE_MISUSE
)
3718 maepad_warning("Error reading data: %s", sqlite3_errmsg(mainview
->db
));
3723 sqlite3_finalize(stmt
);
3727 gboolean resback
= FALSE
;
3729 while(curDataVersion
< datatableversion
)
3731 if (curDataVersion
== 0)
3733 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_backupname
);
3734 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3736 g_snprintf(tq
, sizeof(tq
), "ALTER TABLE %s RENAME TO %s", datatable_name
, datatable_backupname
);
3737 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3738 maepad_warning("Error backing up table %s to %s", datatable_name
, datatable_backupname
);
3743 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", datatable_name
, datatable
);
3744 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3745 maepad_warning("Error creating table: %s", datatable_name
);
3748 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
);
3749 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3750 maepad_warning("Error copying data from %s to %s", datatable_name
, datatable_backupname
);
3754 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_backupname
);
3755 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3757 curDataVersion
= datatableversion
;
3762 if (curDataVersion
!= datatableversion
)
3764 maepad_warning("Data table version mismatch: %d <=> %d", curDataVersion
, datatableversion
);
3766 if (resback
== TRUE
)
3768 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_name
);
3769 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3770 g_snprintf(tq
, sizeof(tq
), "ALTER TABLE %s RENAME TO %s", datatable_backupname
, datatable_name
);
3771 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3778 while(curChecklistVersion
< checklisttableversion
)
3780 if (curChecklistVersion
== 0) /*no checklisttable at all*/
3782 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", checklisttable_name
, checklisttable
);
3783 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3784 maepad_warning("Error creating checklist table during schema upgrade");
3787 curChecklistVersion
= checklisttableversion
;
3793 GtkTreeStore
*model
= GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
)));
3795 g_object_ref(model
);
3796 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), NULL
);
3802 g_snprintf(tq
, sizeof(tq
), "CREATE%s TABLE %s%s", TEMPTABLE_KEYWORD
, datatable_tmpname
, datatable
);
3803 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3804 maepad_warning("Error creating temp table: %s", datatable_tmpname
);
3807 g_snprintf(tq
, sizeof(tq
), "CREATE INDEX %s_index ON %s %s", datatable_tmpname
, datatable_tmpname
, dataindex
);
3808 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3809 maepad_warning("Error creating temp index for %s", datatable_tmpname
);
3812 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", datatable_tmpname
, datatable_name
);
3813 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3814 maepad_warning("Error copying data from %s to %s", datatable_name
, datatable_tmpname
);
3818 g_snprintf(tq
, sizeof(tq
), "CREATE%s TABLE %s%s", TEMPTABLE_KEYWORD
, checklisttable_tmpname
, checklisttable
);
3819 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3820 maepad_warning("Error creating temp table: %s", checklisttable_tmpname
);
3823 g_snprintf(tq
, sizeof(tq
), "CREATE INDEX %s_index ON %s %s", checklisttable_tmpname
, checklisttable_tmpname
, checklistindex
);
3824 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3825 maepad_warning("Error creating temp index for %s", checklisttable_tmpname
);
3828 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", checklisttable_tmpname
, checklisttable_name
);
3829 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3830 maepad_warning("Error copying data from %s to %s", checklisttable_name
, checklisttable_tmpname
);
3836 GtkTreeRowReference
*selectedRef
= read_sqlite3_data(mainview
, 0, NULL
, selectedCard
, model
);
3838 gtk_tree_view_set_model(GTK_TREE_VIEW(mainview
->treeview
), GTK_TREE_MODEL(model
));
3839 g_object_unref(model
);
3840 gtk_tree_view_expand_all(GTK_TREE_VIEW(mainview
->treeview
));
3842 if (selectedRef
!= NULL
)
3844 GtkTreeIter seliter
;
3846 if (ref2iter(GTK_TREE_MODEL(model
), selectedRef
, &seliter
) == TRUE
)
3848 GtkTreeSelection
*selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->treeview
));
3849 gtk_tree_selection_select_iter(selection
, &seliter
);
3852 gtk_tree_row_reference_free(selectedRef
);
3859 sqlite3_finalize(stmt
);
3863 mainview
->loading
=FALSE
;
3871 void write_buffer_to_file(MainView
* mainview
)
3873 maepad_message("Writing database to file: %s", mainview
->file_name
);
3874 saveCurrentData(mainview
);
3876 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->treeview
));
3877 /*update ord value in database for all nodes*/
3878 gtk_tree_model_foreach(GTK_TREE_MODEL(model
),(GtkTreeModelForeachFunc
) foreach_func_update_ord
,mainview
);
3880 busy_enter(mainview
);
3884 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", misctable_name
);
3885 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3887 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", misctable_name
, misctable
);
3888 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3892 if (mainview
->newnodedialog_createchild
== FALSE
)
3894 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('newNodeDlgCreateChild', '%d');", misctable_name
, nndcc
);
3895 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3897 nodeData
*node
= getSelectedNode(mainview
);
3901 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('selectedNode', '%d');", misctable_name
, node
->sql3id
);
3902 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3905 guint bsize
= sketchwidget_get_brushsize(mainview
->sk
);
3906 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('brushSize', '%d');", misctable_name
, bsize
);
3907 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3909 if (mainview
->current_color
== NULL
) {
3910 GdkColor color
= {0, 0, 0, 0};
3911 mainview
->current_color
= gdk_color_copy(&color
);
3913 unsigned long bcol
= ((mainview
->current_color
->red
>> 8) << 16) |
3914 ((mainview
->current_color
->green
>> 8) << 8) |
3915 ((mainview
->current_color
->blue
) >> 8);
3917 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('brushColor', '%lu');", misctable_name
, bcol
);
3918 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3920 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('dataVersion', '%d');", misctable_name
, datatableversion
);
3921 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3923 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s VALUES('checklistVersion', '%d');", misctable_name
, checklisttableversion
);
3924 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3926 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_backupname
);
3927 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3928 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", datatable_backupname
, datatable
);
3929 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3931 maepad_warning("Error creating backup table: %s", datatable_backupname
);
3932 show_banner(mainview
, _("Error creating backup table"));
3934 busy_leave(mainview
);
3937 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", datatable_backupname
, datatable_name
);
3938 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3940 maepad_warning("Error backing up table %s to %s", datatable_name
, datatable_backupname
);
3941 show_banner(mainview
, _("Error creating backup table"));
3943 busy_leave(mainview
);
3946 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s", datatable_name
);
3947 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3949 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", datatable_name
, datatable_tmpname
);
3950 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3952 maepad_warning("Error saving table %s to %s", datatable_tmpname
, datatable_name
);
3953 show_banner(mainview
, _("Error saving table"));
3955 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s", datatable_name
);
3956 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3958 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", datatable_name
, datatable_backupname
);
3959 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
3960 maepad_warning("Error restoring backup. Data lost :(");
3963 busy_leave(mainview
);
3967 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", datatable_backupname
);
3968 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3971 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", checklisttable_backupname
);
3972 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3973 g_snprintf(tq
, sizeof(tq
), "CREATE TABLE %s%s", checklisttable_backupname
, checklisttable
);
3974 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3976 maepad_warning("Error creating backup table: %s", checklisttable_backupname
);
3977 show_banner(mainview
, _("Error creating checklist backup table"));
3979 busy_leave(mainview
);
3983 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", checklisttable_backupname
, checklisttable_name
);
3984 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3986 maepad_warning("Error backing up table %s to %s", checklisttable_name
, checklisttable_backupname
);
3987 show_banner(mainview
, _("Error creating checklist backup table"));
3989 busy_leave(mainview
);
3992 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s", checklisttable_name
);
3993 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
3995 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", checklisttable_name
, checklisttable_tmpname
);
3996 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0)
3998 maepad_warning("Error saving table %s to %s", checklisttable_tmpname
, checklisttable_name
);
3999 show_banner(mainview
, _("Error saving checklist table"));
4001 g_snprintf(tq
, sizeof(tq
), "DELETE FROM %s", checklisttable_name
);
4002 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
4004 g_snprintf(tq
, sizeof(tq
), "INSERT INTO %s SELECT * FROM %s", checklisttable_name
, checklisttable_backupname
);
4005 if (sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
) != 0) {
4006 maepad_warning("Error restoring backup. Data lost :(");
4008 busy_leave(mainview
);
4012 g_snprintf(tq
, sizeof(tq
), "DROP TABLE %s", checklisttable_backupname
);
4013 sqlite3_exec(mainview
->db
, tq
, NULL
, NULL
, NULL
);
4015 mainview
->file_edited
= FALSE
;
4016 busy_leave(mainview
);
4017 show_banner(mainview
, _("Changes saved"));
4020 void callback_checklist_change(GtkTreeSelection
*selection
, MainView
*mainview
)
4022 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
4024 g_signal_handlers_block_by_func(mainview
->bold_tb
, callback_fontstyle
, mainview
->bold_tb
);
4025 g_signal_handlers_block_by_func(mainview
->strikethru_tb
, callback_fontstyle
, mainview
->strikethru_tb
);
4026 g_signal_handlers_block_by_func(mainview
->check_tb
, callback_fontstyle
, mainview
->check_tb
);
4028 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->bold_tb
), FALSE
);
4029 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->strikethru_tb
), FALSE
);
4030 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->check_tb
), FALSE
);
4032 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
4033 GList
* l
=gtk_tree_selection_get_selected_rows(selection
, NULL
);
4035 gboolean gotit
=FALSE
;
4040 GtkTreePath
*path
=cur
->data
;
4045 if (gtk_tree_model_get_iter(model
, &iter
, path
))
4047 gint styletoset_weight
;
4048 gboolean styletoset_strike
;
4051 gtk_tree_model_get(GTK_TREE_MODEL(model
), &iter
, CHECKNODE_BOLD
, &styletoset_weight
, CHECKNODE_STRIKE
, &styletoset_strike
, CHECKNODE_CHECKED
, &ischecked
, -1);
4052 if (styletoset_weight
==PANGO_WEIGHT_BOLD
) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->bold_tb
), TRUE
);
4053 if (styletoset_strike
==TRUE
) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->strikethru_tb
), TRUE
);
4054 if (ischecked
==TRUE
) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(mainview
->check_tb
), TRUE
);
4058 gtk_tree_path_free(path
);
4064 g_signal_handlers_unblock_by_func(mainview
->bold_tb
, callback_fontstyle
, mainview
->bold_tb
);
4065 g_signal_handlers_unblock_by_func(mainview
->strikethru_tb
, callback_fontstyle
, mainview
->strikethru_tb
);
4066 g_signal_handlers_unblock_by_func(mainview
->check_tb
, callback_fontstyle
, mainview
->check_tb
);
4069 void callback_checklist_paste(MainView
*mainview
)
4071 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
4075 GtkTreeModel
*model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
4076 GtkTreeIter toplevel
;
4077 gchar
*pasted_text
= gtk_clipboard_wait_for_text(mainview
->clipboard
);
4079 entries
= g_strsplit(pasted_text
, "\n", 0);
4080 length
= g_strv_length(entries
);
4082 for (i
=0; i
<length
; i
++) {
4083 gtk_list_store_append(GTK_LIST_STORE(model
), &toplevel
);
4084 gtk_list_store_set(GTK_LIST_STORE(model
), &toplevel
, CHECKNODE_CHECKED
, FALSE
, CHECKNODE_TEXT
, entries
[i
], -1);
4087 mainview
->checklist_edited
= TRUE
;
4088 g_free(pasted_text
);
4089 g_strfreev(entries
);
4092 void callback_checklist_add(GtkAction
*action
, MainView
*mainview
)
4094 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
4096 gchar
* text
= show_line_edit_dialog(mainview
, _("Add new checklist item"), _("Name:"), _("Add"), "");
4099 GtkTreeModel
* model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
4100 GtkTreeIter toplevel
;
4101 gtk_list_store_append(GTK_LIST_STORE(model
), &toplevel
);
4103 gtk_list_store_set(GTK_LIST_STORE(model
),
4105 CHECKNODE_CHECKED
, FALSE
,
4106 CHECKNODE_TEXT
, text
,
4109 GtkTreePath
*path
= gtk_tree_model_get_path(model
, &toplevel
);
4111 gtk_tree_view_set_cursor(GTK_TREE_VIEW(mainview
->listview
), path
, mainview
->checklist_column_text
, FALSE
);
4112 gtk_tree_path_free(path
);
4115 mainview
->checklist_edited
= TRUE
;
4120 checklist_edit_selected(MainView
* mainview
, LineEditMode mode
)
4122 GtkTreeSelection
* selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
));
4124 if (gtk_tree_selection_count_selected_rows(selection
) == 0) {
4125 show_banner(mainview
, _("Select items first"));
4129 GtkTreeModel
* model
;
4132 if (gtk_tree_selection_get_selected(selection
, &model
, &iter
)) {
4133 gchar
* old_text
= NULL
;
4134 gtk_tree_model_get(model
, &iter
, CHECKNODE_TEXT
, &old_text
, -1);
4136 gchar
* new_text
= show_line_edit_dialog_full(mainview
, _("Edit checklist item"), _("New name:"), _("Save"), old_text
, mode
);
4138 if (new_text
!= NULL
) {
4139 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, CHECKNODE_TEXT
, new_text
, -1);
4140 mainview
->checklist_edited
= TRUE
;
4148 void callback_checklist_edit(GtkAction
*action
, MainView
*mainview
)
4150 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
4151 checklist_edit_selected(mainview
, LINE_EDIT_MODE_DEFAULT
);
4154 void callback_checklist_delete(GtkAction
*action
, MainView
*mainview
)
4156 g_assert(mainview
!= NULL
&& mainview
->data
!= NULL
);
4158 if (gtk_tree_selection_count_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
)))==0) {
4159 show_banner(mainview
, _("Select items first"));
4163 if (show_confirmation(mainview
, _("Delete selected checklist item?"))) {
4164 callback_checklist_delete_real(mainview
);
4168 void callback_checklist_delete_real(MainView
* mainview
)
4170 GtkTreeModel
*model
=gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
4171 GList
* l
=gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
)), NULL
);
4173 /* Select the item after the selection */
4174 checklist_select(mainview
, TREEVIEW_SELECT_NEXT
);
4176 GList
* rowrefs
=NULL
;
4180 GtkTreePath
*path
=cur
->data
;
4183 if (gtk_tree_model_get_iter(model
, &iter
, path
))
4185 GtkTreeRowReference
*rowref
= gtk_tree_row_reference_new(model
, path
);
4186 rowrefs
=g_list_append(rowrefs
, rowref
);
4188 gtk_tree_path_free(path
);
4192 checklist_remove_rowrefs(mainview
, rowrefs
, FALSE
);
4196 checklist_remove_rowrefs(MainView
* mainview
, GList
* rowrefs
, gboolean show_result
)
4198 GtkTreeModel
* model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
4199 GList
* cur
= rowrefs
;
4202 busy_enter(mainview
);
4205 GtkTreeRowReference
* rowref
= cur
->data
;
4206 GtkTreePath
* path
= gtk_tree_row_reference_get_path(rowref
);
4209 if (gtk_tree_model_get_iter(model
, &iter
, path
)) {
4210 gtk_list_store_remove(GTK_LIST_STORE(model
), &iter
);
4213 gtk_tree_path_free(path
);
4215 gtk_tree_row_reference_free(rowref
);
4218 g_list_free(rowrefs
);
4220 busy_leave(mainview
);
4222 if (count
&& show_result
) {
4223 gchar
* message
= g_strdup_printf(N_("%d item removed", "%d items removed", count
), count
);
4224 show_banner(mainview
, message
);
4228 mainview
->checklist_edited
= TRUE
;
4231 /* Private callback for show_confirmation() - handle keyboard input */
4233 on_confirmation_key_press_event(GtkWidget
* widget
, GdkEventKey
* event
, gpointer user_data
)
4235 GtkDialog
* dialog
= GTK_DIALOG(widget
);
4237 switch (event
->keyval
) {
4238 /* Positive response - Enter, Return or y */
4243 gtk_dialog_response(dialog
, GTK_RESPONSE_OK
);
4246 /* Negative response - Backspace, Escape or n */
4251 gtk_dialog_response(dialog
, GTK_RESPONSE_CANCEL
);
4254 /* Don't handle the rest of the keys */
4261 /* Ask the user for confirmation of a specific action */
4263 show_confirmation(MainView
* mainview
, gchar
* question
)
4265 GtkDialog
* dialog
= GTK_DIALOG(hildon_note_new_confirmation(
4266 GTK_WINDOW(mainview
->data
->main_view
), question
));
4267 gtk_window_set_transient_for(GTK_WINDOW(dialog
), mainview_get_dialog_parent(mainview
));
4268 g_signal_connect(G_OBJECT(dialog
), "key-press-event",
4269 G_CALLBACK(on_confirmation_key_press_event
), NULL
);
4271 gint response
= gtk_dialog_run(dialog
);
4272 gtk_widget_destroy(GTK_WIDGET(dialog
));
4274 return (response
== GTK_RESPONSE_OK
);
4277 /* Show a information banner to the user (non-modal) */
4279 show_banner(MainView
* mainview
, const gchar
* text
)
4281 hildon_banner_show_information(GTK_WIDGET(mainview_get_dialog_parent(mainview
)), NULL
, text
);
4286 gboolean can_close_window
;
4287 } LineEditDialogData
;
4289 /* Helper function to close line edit dialog on Backspace */
4291 line_edit_dialog_key_press(GtkWidget
* w
, GdkEventKey
* event
, gpointer user_data
)
4293 LineEditDialogData
* dialogdata
= (LineEditDialogData
*)user_data
;
4294 GtkEntry
* entry
= GTK_ENTRY(w
);
4296 if (event
->keyval
== GDK_BackSpace
&&
4297 dialogdata
->can_close_window
&&
4298 strcmp(gtk_entry_get_text(entry
), "") == 0) {
4299 gtk_dialog_response(GTK_DIALOG(dialogdata
->dialog
), GTK_RESPONSE_CANCEL
);
4306 /* Let the user enter or edit a line of text */
4308 show_line_edit_dialog_full(MainView
* mainview
, const gchar
* title
,
4309 const gchar
* label_text
, const gchar
* action
, const gchar
* text
,
4312 GtkWidget
* edit_dialog
;
4316 gchar
* result
= NULL
;
4317 LineEditDialogData dialogdata
;
4319 edit_dialog
= GTK_WIDGET(gtk_dialog_new());
4320 gtk_window_set_title(GTK_WINDOW(edit_dialog
), title
);
4321 gtk_window_set_transient_for(GTK_WINDOW(edit_dialog
), mainview_get_dialog_parent(mainview
));
4323 label
= GTK_WIDGET(gtk_label_new(label_text
));
4325 entry
= hildon_entry_new(HILDON_SIZE_AUTO
);
4326 gtk_entry_set_text(GTK_ENTRY(entry
), text
);
4327 gtk_entry_set_activates_default(GTK_ENTRY(entry
), TRUE
);
4329 case LINE_EDIT_MODE_DEFAULT
:
4330 gtk_editable_select_region(GTK_EDITABLE(entry
), 0, -1);
4332 case LINE_EDIT_MODE_APPEND
:
4333 gtk_editable_select_region(GTK_EDITABLE(entry
), -1, -1);
4335 case LINE_EDIT_MODE_PREPEND
:
4336 gtk_editable_select_region(GTK_EDITABLE(entry
), 0, 0);
4342 gtk_dialog_add_button(GTK_DIALOG(edit_dialog
), action
, GTK_RESPONSE_OK
);
4343 gtk_dialog_set_default_response(GTK_DIALOG(edit_dialog
), GTK_RESPONSE_OK
);
4345 dialogdata
.dialog
= edit_dialog
;
4346 dialogdata
.can_close_window
= (strcmp(text
, "") == 0);
4347 g_signal_connect(G_OBJECT(entry
), "key-press-event", G_CALLBACK(line_edit_dialog_key_press
), &dialogdata
);
4349 hbox
= GTK_WIDGET(gtk_hbox_new(FALSE
, 10));
4351 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(edit_dialog
))), GTK_WIDGET(hbox
));
4352 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
4353 gtk_box_pack_start(GTK_BOX(hbox
), entry
, TRUE
, TRUE
, 0);
4355 gtk_widget_show_all(GTK_WIDGET(hbox
));
4358 if (gtk_dialog_run(GTK_DIALOG(edit_dialog
)) == GTK_RESPONSE_OK
) {
4359 result
= g_strdup(gtk_entry_get_text(GTK_ENTRY(entry
)));
4360 if (strcmp(result
, "") != 0) {
4363 show_banner(mainview
, _("Please enter a non-empty text"));
4373 gtk_widget_destroy(GTK_WIDGET(edit_dialog
));
4378 treeview_scroll_to_selection(MainView
* mainview
, TreeViewType type
)
4380 GtkTreeView
* treeview
= NULL
;
4381 HildonPannableArea
* pannable_area
= NULL
;
4382 GtkTreeModel
* model
= NULL
;
4383 GtkTreeSelection
* selection
= NULL
;
4384 GtkTreePath
* path
= NULL
;
4390 case TREEVIEW_MAINVIEW
:
4391 treeview
= GTK_TREE_VIEW(mainview
->treeview
);
4392 pannable_area
= HILDON_PANNABLE_AREA(mainview
->scrolledtree
);
4394 case TREEVIEW_CHECKLIST
:
4395 treeview
= GTK_TREE_VIEW(mainview
->listview
);
4396 pannable_area
= HILDON_PANNABLE_AREA(mainview
->listscroll
);
4399 g_assert_not_reached();
4403 /* Let the view scroll so that the selected item is visible */
4404 selection
= gtk_tree_view_get_selection(treeview
);
4405 if (gtk_tree_selection_get_selected(selection
, &model
, &iter
)) {
4406 path
= gtk_tree_model_get_path(model
, &iter
);
4408 gtk_tree_view_get_background_area(treeview
, path
, NULL
, &rect
);
4409 gtk_tree_view_convert_bin_window_to_tree_coords(treeview
,
4410 0, rect
.y
, NULL
, &y
);
4411 hildon_pannable_area_scroll_to(pannable_area
, -1, y
);
4413 gtk_tree_path_free(path
);
4418 checklist_scroll_to_selection(gpointer user_data
)
4420 MainView
* mainview
= (MainView
*)user_data
;
4421 treeview_scroll_to_selection(mainview
, TREEVIEW_CHECKLIST
);
4426 nodelist_scroll_to_selection(gpointer user_data
)
4428 MainView
* mainview
= (MainView
*)user_data
;
4429 treeview_scroll_to_selection(mainview
, TREEVIEW_MAINVIEW
);
4434 checklist_select(MainView
* mainview
, TreeviewSelectType type
)
4436 GtkTreeModel
* model
= gtk_tree_view_get_model(GTK_TREE_VIEW(mainview
->listview
));
4437 GtkTreeSelection
* selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(mainview
->listview
));
4443 case TREEVIEW_SELECT_FIRST
:
4444 if (gtk_tree_model_get_iter_first(model
, &iter
)) {
4445 path
= gtk_tree_model_get_path(model
, &iter
);
4446 gtk_tree_selection_select_path(selection
, path
);
4447 gtk_tree_path_free(path
);
4450 case TREEVIEW_SELECT_LAST
:
4451 if (gtk_tree_model_get_iter_first(model
, &iter
)) {
4454 } while (gtk_tree_model_iter_next(model
, &iter
));
4455 path
= gtk_tree_model_get_path(model
, &last
);
4456 gtk_tree_selection_select_path(selection
, path
);
4457 gtk_tree_path_free(path
);
4460 case TREEVIEW_SELECT_PREVIOUS
:
4461 if (gtk_tree_selection_get_selected(selection
, NULL
, &iter
)) {
4462 path
= gtk_tree_model_get_path(model
, &iter
);
4463 if (gtk_tree_path_prev(path
)) {
4464 gtk_tree_selection_select_path(selection
, path
);
4466 gtk_tree_path_free(path
);
4469 case TREEVIEW_SELECT_NEXT
:
4470 if (gtk_tree_selection_get_selected(selection
, NULL
, &iter
)) {
4471 path
= gtk_tree_model_get_path(model
, &iter
);
4472 gtk_tree_path_next(path
);
4473 gtk_tree_selection_select_path(selection
, path
);
4474 gtk_tree_path_free(path
);
4478 g_assert_not_reached();
4482 checklist_scroll_to_selection(mainview
);
4485 * This is a workaround: The HildonPannableArea does not seem to
4486 * scroll to the right position (especially when going to the first
4487 * or last item in the list), so we simply scroll again after 500ms.
4489 g_timeout_add(500, checklist_scroll_to_selection
, mainview
);
4493 nodelist_select(MainView
* mainview
, TreeviewSelectType type
)
4495 GtkTreeView
* treeview
= GTK_TREE_VIEW(mainview
->treeview
);
4496 GtkTreeModel
* model
= gtk_tree_view_get_model(treeview
);
4497 GtkTreeSelection
* selection
= gtk_tree_view_get_selection(treeview
);
4504 case TREEVIEW_SELECT_FIRST
:
4505 if (gtk_tree_model_get_iter_first(model
, &iter
)) {
4506 path
= gtk_tree_model_get_path(model
, &iter
);
4507 gtk_tree_selection_select_path(selection
, path
);
4508 gtk_tree_path_free(path
);
4511 case TREEVIEW_SELECT_LAST
:
4512 if (gtk_tree_model_get_iter_first(model
, &iter
)) {
4515 if (gtk_tree_model_iter_children(model
, &child
, &last
)) {
4518 } while (gtk_tree_model_iter_next(model
, &child
));
4520 } while (gtk_tree_model_iter_next(model
, &iter
));
4521 path
= gtk_tree_model_get_path(model
, &last
);
4522 gtk_tree_selection_select_path(selection
, path
);
4523 gtk_tree_path_free(path
);
4526 case TREEVIEW_SELECT_PREVIOUS
:
4527 if (gtk_tree_selection_get_selected(selection
, NULL
, &iter
)) {
4528 path
= gtk_tree_model_get_path(model
, &iter
);
4529 if (gtk_tree_path_prev(path
)) {
4530 gtk_tree_selection_select_path(selection
, path
);
4531 } else if (gtk_tree_path_up(path
)) {
4532 gtk_tree_selection_select_path(selection
, path
);
4534 gtk_tree_path_free(path
);
4537 case TREEVIEW_SELECT_NEXT
:
4538 if (gtk_tree_selection_get_selected(selection
, NULL
, &iter
)) {
4539 path
= gtk_tree_model_get_path(model
, &iter
);
4540 gtk_tree_path_down(path
);
4541 while (!gtk_tree_model_get_iter(model
, &iter
, path
)) {
4542 /* Child item does not exist - bubble up to next item */
4543 gtk_tree_path_up(path
);
4544 gtk_tree_path_next(path
);
4546 if (gtk_tree_path_get_depth(path
) == 0) {
4547 /* avoid infinite loops */
4552 if (gtk_tree_model_get_iter(model
, &iter
, path
)) {
4553 gtk_tree_selection_select_path(selection
, path
);
4556 gtk_tree_path_free(path
);
4560 g_assert_not_reached();
4564 nodelist_scroll_to_selection(mainview
);
4567 * This is a workaround: The HildonPannableArea does not seem to
4568 * scroll to the right position (especially when going to the first
4569 * or last item in the list), so we simply scroll again after 500ms.
4571 g_timeout_add(500, nodelist_scroll_to_selection
, mainview
);
4576 format_overview_name(nodeData
*nd
, const gchar
*name
)
4579 gchar
*font_desc
, *font_color
;
4589 font_desc
= he_get_logical_font_desc("SmallSystemFont");
4590 font_color
= he_get_logical_font_color("SecondaryTextColor");
4592 tmp
= g_markup_printf_escaped("%s\n<span font_desc=\"%s\" foreground=\"%s\">%s</span>",
4596 (nd
->typ
==NODE_CHECKLIST
)?(_("Checklist")):
4597 ((nd
->typ
==NODE_TEXT
)?(_("Rich text")):
4598 ((nd
->typ
==NODE_SKETCH
)?(_("Sketch")):(""))));
4608 he_get_logical_font_desc(const gchar
*name
)
4610 GtkSettings
*settings
= gtk_settings_get_default();
4611 GtkStyle
*style
= gtk_rc_get_style_by_paths(settings
,
4612 name
, NULL
, G_TYPE_NONE
);
4614 return pango_font_description_to_string(style
->font_desc
);
4618 he_get_logical_font_color(const gchar
*name
)
4621 GtkSettings
*settings
= gtk_settings_get_default();
4622 GtkStyle
*style
= gtk_rc_get_style_by_paths(settings
,
4623 "GtkButton", "osso-logical-colors", GTK_TYPE_BUTTON
);
4625 if (gtk_style_lookup_color(style
, name
, &color
)) {
4626 return gdk_color_to_string(&color
);