4 #include "stuffkeeper-data-backend.h"
5 #include "stuffkeeper-data-schema.h"
6 #include "stuffkeeper-data-tag.h"
7 #include "stuffkeeper-data-item-search.h"
8 #include "stuffkeeper-item-view.h"
14 #include <gdk/gdkkeysyms.h>
15 #include <glib/gi18n.h>
19 /* Include the database */
21 #include "stuffkeeper-data-backend.h"
22 #include "stuffkeeper-edit-schema.h"
23 #include "stuffkeeper-show-item.h"
24 #include "stuffkeeper-item-window.h"
25 #include "stuffkeeper-export-html.h"
26 #include "stuffkeeper-item-window.h"
27 #include "stuffkeeper-plugin-manager.h"
28 #include "stuffkeeper-plugin.h"
30 #include "stuffkeeper-multiple-item-view.h"
36 const gchar *artists[] = {
37 "Jakub Szypulka (http://cubestuff.wordpress.com )",
38 "Tango Project (http://tango.freedesktop.org/ )",
40 const gchar *authors[] = {
41 "Martijn Koedam (qball) <Qball@Stuffkeeper.org>",
42 "Barak Korren (ifireball)",
45 "Rasi <rasi@stuffkeeper.org>",
48 typedef enum _LPColumnType{
57 typedef enum _LPType {
64 class Stuffkeeper:Interface from G:Object
66 private GtkTreeModel *model_tags = {NULL};
67 private GtkTreeModel *model_tags_filter = {NULL};
68 private GtkTreeModel *model_items = {NULL};
69 private GtkTreeModel *model_schemas = {NULL};
71 private GtkTreeModel *model_searches = {NULL};
72 private GtkTreeModel *model_items_filter = {NULL};
74 public GKeyFile *config_file = {NULL};
77 private GtkWidget *menu = {NULL};
78 private GtkWidget *menu_item_add = {NULL};
82 private GtkBuilder *xml;
83 private GtkWidget *win;
84 private GtkWidget *LeftPaneCB;
85 private GtkWidget *treeview1;
86 private GtkWidget *treeview2;
87 private GtkTreeViewColumn *column_lv_pixbuf = {NULL};
88 private GtkCellRenderer *treeview1_renderer = {NULL};
89 private GtkCellRenderer *renderer_toggle = {NULL};
91 private GtkWidget *LeftPane_edit ;
92 private GtkWidget *AddMenuButton ;
93 private GtkWidget *search_entry ;
94 private GtkWidget *hpaned1;
95 private GtkWidget *vpaned1;
96 private GtkWidget *item_label;
97 private GtkWidget *cb_search;
99 private GtkWidget *item_view_container;
100 private GtkWidget *show_item_pane_menu_item;
102 private GtkWidget *menuitem_item_add;
104 private StuffkeeperDataBackend *skdbg = {NULL};
105 private StuffkeeperPluginManager *spm = {NULL};
110 private gulong signal_schema_added = {0};
111 private gulong signal_schema_changed = {0};
112 private gulong signal_schema_removed = {0};
114 private gulong signal_tag_added = {0};
115 private gulong signal_tag_changed = {0};
116 private gulong signal_tag_removed = {0};
118 private gulong signal_item_added = {0};
119 private gulong signal_item_changed = {0};
120 private gulong signal_item_removed = {0};
123 private gulong search_timeout = {0};
124 private gulong signal_search_added = {0};
125 private gulong signal_search_changed = {0};
126 private gulong signal_search_removed = {0};
128 private gulong signal_backend_locked = {0};
130 private int item_sort_column = {3};
131 private int item_sort_order = {GTK_SORT_DESCENDING};
133 private signal last NONE (POINTER)
134 void item_added_here(self, Stuffkeeper:Data:Item *item (check null type))
137 GtkTreePath *path = NULL;
138 GtkTreeModel *store =GTK_TREE_MODEL(self->_priv->model_items_filter);
140 if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) {
141 StuffkeeperDataItem *found_item = NULL;
142 g_debug("Searching new item in tree\n");
144 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 2, &found_item, -1);
145 if(found_item == item) {
146 g_debug("Found new item in tree\n");
147 path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);
150 } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
152 g_debug("Moving cursor to new item\n");
153 gtk_tree_view_set_cursor(GTK_TREE_VIEW(self->_priv->treeview2), path, NULL, FALSE);
154 gtk_tree_path_free(path);
156 self_popup_item(self, item);
162 * Changes in the GtkTreeModelFilter wrapper, updating the total item label.
166 filter_model_row_inserted(self, GtkTreePath *path, GtkTreeIter *iter, GtkTreeModel *model)
168 int num_items = gtk_tree_model_iter_n_children(self->_priv->model_items_filter, NULL);
169 gchar *data = g_strdup_printf("%i", num_items);
170 gtk_label_set_text(GTK_LABEL(self->_priv->item_label), data);
176 filter_model_row_deleted(self, GtkTreePath *path, GtkTreeModel *model)
178 int num_items = gtk_tree_model_iter_n_children(self->_priv->model_items_filter, NULL);
179 gchar *data = g_strdup_printf("%i", num_items);
180 gtk_label_set_text(GTK_LABEL(self->_priv->item_label), data);
188 search_changed(self, const SearchField *field, StuffkeeperDataItemSearch *search)
193 GtkTreeModel *model = GTK_TREE_MODEL(self->_priv->model_searches);
194 gint id = stuffkeeper_data_item_search_get_id(search);
195 if(gtk_tree_model_get_iter_first(model, &iter))
199 gtk_tree_model_get(model, &iter, 0, &oid, -1);
202 gchar *title = stuffkeeper_data_item_search_get_title(search);
203 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
208 }while(gtk_tree_model_iter_next(model, &iter));
211 gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(self->_priv->model_items_filter));
216 search_added(self, StuffkeeperDataItemSearch *search, StuffkeeperDataBackend *skdb)
219 gchar *title = stuffkeeper_data_item_search_get_title(search);
221 gtk_list_store_insert_with_values(GTK_LIST_STORE(self->_priv->model_searches), &iter, -1,
222 LP_ID, stuffkeeper_data_item_search_get_id(search),
231 search_removed(self, gint id, StuffkeeperDataBackend *skdb)
234 GtkTreeModel *model = GTK_TREE_MODEL(self->_priv->model_searches);
235 if(gtk_tree_model_get_iter_first(model, &iter))
239 gtk_tree_model_get(model, &iter, LP_ID, &oid, -1);
242 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
243 gtk_combo_box_set_active(GTK_COMBO_BOX(self->_priv->cb_search), 0);
246 }while(gtk_tree_model_iter_next(model, &iter));
252 * Keep Schema's GtkListStore up2date
256 schema_added(self, StuffkeeperDataSchema *schema,StuffkeeperDataBackend *skdb )
259 gchar *title = stuffkeeper_data_schema_get_title(schema);
260 gtk_list_store_insert_with_values(GTK_LIST_STORE(self->_priv->model_schemas), &iter, -1,
261 LP_ID, stuffkeeper_data_schema_get_id(schema),
264 LP_AMOUNT, stuffkeeper_data_schema_num_items(schema),-1);
269 self_update_all_item_add_menus(self);
273 schema_changed(self, StuffkeeperDataSchema *schema, StuffkeeperDataBackend *skdb)
276 GtkTreeModel *model = GTK_TREE_MODEL(self->_priv->model_schemas);
277 gint id = stuffkeeper_data_schema_get_id(schema);
278 if(gtk_tree_model_get_iter_first(model, &iter))
282 gtk_tree_model_get(model, &iter, LP_ID, &oid, -1);
285 gchar *title = stuffkeeper_data_schema_get_title(schema);
286 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
288 LP_AMOUNT, stuffkeeper_data_schema_num_items(schema),
292 }while(gtk_tree_model_iter_next(model, &iter));
295 * If schema add-button prefered schema is this schema, update the tooltip.
297 if(g_object_get_data(G_OBJECT(self->_priv->AddMenuButton), "schema") == schema)
299 gtk_widget_set_tooltip_text(self->_priv->AddMenuButton, stuffkeeper_data_schema_get_title(schema));
301 self_update_all_item_add_menus(self);
305 schema_removed(self, gint id, StuffkeeperDataBackend *skdb)
308 GtkTreeModel *model = GTK_TREE_MODEL(self->_priv->model_schemas);
310 if(gtk_tree_model_get_iter_first(model, &iter))
314 gtk_tree_model_get(model, &iter, LP_ID, &oid, -1);
317 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
320 }while(gtk_tree_model_iter_next(model, &iter));
322 printf("Resetting schema\n" );
323 /* Reset tooltip and item that is added on AddButton */
324 g_object_set_data(G_OBJECT(self->_priv->AddMenuButton), "schema", NULL);
325 gtk_widget_set_tooltip_text(self->_priv->AddMenuButton, "");
326 /* Update both menus */
327 self_update_all_item_add_menus(self);
331 * Keep Tag's GtkListStore up2date
335 tag_added(StuffkeeperDataBackend *skdb, StuffkeeperDataTag *tag, GtkTreeModel *store)
338 gchar *title = stuffkeeper_data_tag_get_title(tag);
339 gtk_list_store_insert_with_values(GTK_LIST_STORE(store), &iter, -1,
340 LP_ID, stuffkeeper_data_tag_get_id(tag),
343 LP_AMOUNT, stuffkeeper_data_tag_num_items(tag),
349 tag_changed(StuffkeeperDataBackend *skdb, StuffkeeperDataTag *tag, GtkTreeModel *store)
352 GtkTreeModel *model = GTK_TREE_MODEL(store);
353 gint id = stuffkeeper_data_tag_get_id(tag);
354 if(gtk_tree_model_get_iter_first(model, &iter))
358 gtk_tree_model_get(model, &iter, LP_ID, &oid, -1);
361 gchar *title = stuffkeeper_data_tag_get_title(tag);
362 gtk_list_store_set(GTK_LIST_STORE(store), &iter,
364 LP_AMOUNT, stuffkeeper_data_tag_num_items(tag),
369 }while(gtk_tree_model_iter_next(model, &iter));
374 tag_removed(StuffkeeperDataBackend *skdb, gint id, GtkListStore *store)
377 GtkTreeModel *model = GTK_TREE_MODEL(store);
378 if(gtk_tree_model_get_iter_first(model, &iter))
382 gtk_tree_model_get(model, &iter, LP_ID, &oid, -1);
385 gtk_list_store_remove(store, &iter);
388 }while(gtk_tree_model_iter_next(model, &iter));
394 * Update the gtk-list-store with signals from the backend
398 item_removed(StuffkeeperDataBackend *skdb, gint id,StuffkeeperInterface *self)
401 GtkListStore *store = GTK_LIST_STORE(self->_priv->model_items);
402 GtkTreeModel *model = GTK_TREE_MODEL(store);
404 if(gtk_tree_model_get_iter_first(model, &iter))
408 gtk_tree_model_get(model, &iter, 0, &oid, -1);
411 gtk_list_store_remove(store, &iter);
414 }while(gtk_tree_model_iter_next(model, &iter));
419 item_added(StuffkeeperDataBackend *skdb, StuffkeeperDataItem *item, StuffkeeperInterface *self)
422 GtkListStore *store = GTK_LIST_STORE(self->_priv->model_items);
424 gchar *title = stuffkeeper_data_item_get_title(item);
426 gtk_list_store_insert_with_values(GTK_LIST_STORE(store), &iter,-1,
427 0, stuffkeeper_data_item_get_id(item),
430 3, stuffkeeper_data_item_get_creation_time(item),
431 4, stuffkeeper_data_schema_get_id(stuffkeeper_data_item_get_schema(item)),
432 5, stuffkeeper_data_item_get_modification_time(item),
438 item_changed(StuffkeeperDataBackend *skdb, const gchar *field, StuffkeeperDataItem *item, StuffkeeperInterface *self)
441 GtkListStore *store = GTK_LIST_STORE(self->_priv->model_items);
442 GtkTreeModel *model = GTK_TREE_MODEL(store);
443 gint id = stuffkeeper_data_item_get_id(item);
444 if(gtk_tree_model_get_iter_first(model, &iter))
448 gtk_tree_model_get(model, &iter, 0, &oid, -1);
451 gchar *title = stuffkeeper_data_item_get_title(item);
452 gtk_list_store_set(store, &iter, 1,title,
458 }while(gtk_tree_model_iter_next(model, &iter));
462 private void add_item(self, StuffkeeperDataSchema *schema)
465 StuffkeeperDataItem *item = stuffkeeper_data_backend_new_item(self->_priv->skdbg,schema);
466 /* Set new item tags */
467 if(gtk_tree_model_get_iter_first(self->_priv->model_tags, &iter))
470 StuffkeeperDataTag *tag = NULL;
472 gtk_tree_model_get(GTK_TREE_MODEL(self->_priv->model_tags), &iter,2, &enabled, 3,&tag, -1);
475 stuffkeeper_data_item_add_tag(item, tag);
478 }while(gtk_tree_model_iter_next(self->_priv->model_tags, &iter));
480 /* signal to other window components that the item was added on this
482 self_item_added_here(self, item);
485 * Add item button clicked
487 public void interface_item_add(self,GtkWidget *button)
489 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
490 if(locked){printf("**ERROR** should not be callable\n");return;}
492 GList *list = stuffkeeper_data_backend_get_schemas(self->_priv->skdbg);
493 /* check if there are schema's */
496 StuffkeeperDataSchema *schema = g_object_get_data(G_OBJECT(button), "schema");
497 /* if there is no schema, get the first*/
498 if(schema == NULL || !STUFFKEEPER_IS_DATA_SCHEMA(schema))
502 /* Update tooltip with the name of the schema to be added */
503 g_object_set_data(G_OBJECT(self->_priv->AddMenuButton), "schema", list->data);
504 gtk_widget_set_tooltip_text(button, stuffkeeper_data_schema_get_title(schema));
505 self_add_item(self, schema);
510 private void interface_item_add_menu_button(self, GtkWidget *button)
512 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
513 if(locked){printf("**ERROR** should not be callable\n");return;}
514 StuffkeeperDataSchema *schema = g_object_get_data(G_OBJECT(button), "schema");
517 self_add_item(self, schema);
518 /* Store last added item. */
519 g_object_set_data(G_OBJECT(self->_priv->AddMenuButton), "schema", schema);
521 gtk_widget_set_tooltip_text(self->_priv->AddMenuButton, stuffkeeper_data_schema_get_title(schema));
526 * Remove selected item
528 public void interface_item_remove(self)
530 if(stuffkeeper_data_backend_get_locked(self->_priv->skdbg)){
531 printf("**ERROR** should not be callable\n");
535 /** Setup a dialog that ask the user if he is sure */
536 GtkWidget *tree = self->_priv->treeview2;
537 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
538 GtkTreeModel *model = GTK_TREE_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(tree)));
540 if(gtk_tree_selection_count_selected_rows(selection)>0)
542 GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(self->_priv->win),
543 GTK_DIALOG_DESTROY_WITH_PARENT|// This belongs to the parent, so if the user closes the parent, close it
544 GTK_DIALOG_MODAL, // It is a warning, it _should_ be modal.
545 GTK_MESSAGE_WARNING, // It is a warning message.
546 GTK_BUTTONS_YES_NO, // yes/no question
547 _("Deleting an entry cannot be undone.\nAre you sure you want to continue?"));
548 if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_YES)
551 GList *node,*list = gtk_tree_selection_get_selected_rows(selection, &model);
552 for(node = g_list_last(list); node; node = g_list_previous(node))
554 if(gtk_tree_model_get_iter(model, &iter, (GtkTreePath*)node->data))
556 gtk_tree_model_get(model, &iter ,0,&id, -1);
557 stuffkeeper_data_backend_remove_item(self->_priv->skdbg, id);
561 g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
565 gtk_widget_destroy(dialog);
571 public void interface_item_clone(self)
575 GtkTreeSelection *selection;
577 if(stuffkeeper_data_backend_get_locked(self->_priv->skdbg)){
578 printf("**ERROR** should not be callable\n");
582 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview2));
583 list = gtk_tree_selection_get_selected_rows(selection, &model);
584 for(node = g_list_first(list); node; node = g_list_next(node))
586 if(gtk_tree_model_get_iter(model, &iter, (GtkTreePath *)node->data))
588 StuffkeeperDataItem *orig_item, *item;
589 gtk_tree_model_get(model, &iter , 2, &orig_item, -1);
590 item = stuffkeeper_data_backend_clone_item(self->_priv->skdbg, orig_item);
591 /* signal to other window components that the item was added on this
593 self_item_added_here(self, item);
598 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
604 * Tag is enabled/disabled
608 interface_left_pane_toggled(self, gchar *path, GtkCellRendererToggle *renderer)
610 int type = gtk_combo_box_get_active(GTK_COMBO_BOX(self->_priv->LeftPaneCB));
612 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->_priv->treeview1));
613 if(type == LP_TYPE_SEARCH)
615 gboolean value = !gtk_cell_renderer_toggle_get_active(renderer);
618 gtk_combo_box_set_active(GTK_COMBO_BOX(self->_priv->cb_search), 0);
621 if(gtk_tree_model_get_iter_from_string(model, &iter, path))
623 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(self->_priv->cb_search), &iter);
627 else if (type == LP_TYPE_TAG)
630 if(gtk_tree_model_get_iter_from_string(model, &iter, path))
633 gboolean value = !gtk_cell_renderer_toggle_get_active(renderer);
634 gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(model), &child, &iter);
636 gtk_list_store_set(GTK_LIST_STORE(self->_priv->model_tags), &child, LP_SELECTED, value, -1);
637 /* refilter the items list */
638 gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(self->_priv->model_items_filter));
644 if(gtk_tree_model_get_iter_from_string(model, &iter, path))
646 gboolean value = !gtk_cell_renderer_toggle_get_active(renderer);
648 gtk_list_store_set(GTK_LIST_STORE(model), &iter, LP_SELECTED,value,-1);
650 /* refilter the items list */
651 gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(self->_priv->model_items_filter));
657 void interface_item_title_edited
662 GtkCellRendererText *renderer
665 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->_priv->treeview2));
667 if(gtk_tree_model_get_iter_from_string(model, &iter, path))
670 StuffkeeperDataItem *item;
671 gtk_tree_model_get(model, &iter ,0,&id, -1);
672 item = stuffkeeper_data_backend_get_item(self->_priv->skdbg, id);
675 stuffkeeper_data_item_set_title(item, new_text);
681 void interface_left_pane_edited
686 GtkCellRendererText *renderer
691 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->_priv->treeview1));
692 if(gtk_tree_model_get_iter_from_string(model, &iter, path))
696 gtk_tree_model_get(model, &iter ,LP_ITEM,&item, -1);
698 if(STUFFKEEPER_IS_DATA_TAG(item)) {
699 stuffkeeper_data_tag_set_title(STUFFKEEPER_DATA_TAG(item), new_text);
700 }else if (STUFFKEEPER_IS_DATA_SCHEMA(item)){
701 stuffkeeper_data_schema_set_title(STUFFKEEPER_DATA_SCHEMA(item), new_text);
702 }else if (STUFFKEEPER_IS_DATA_ITEM_SEARCH(item)){
703 stuffkeeper_data_item_search_set_title(STUFFKEEPER_DATA_ITEM_SEARCH(item), new_text);
711 void quit_program(void)
721 g_object_unref(self);
729 ski= stuffkeeper_interface_new(self->config_file);
730 stuffkeeper_interface_initialize_interface(ski,self->_priv->skdbg,G_OBJECT(self->_priv->spm));
734 * Filtering the item list
738 interface_visible_func(GtkTreeModel *model, GtkTreeIter *iter, StuffkeeperInterface *self)
740 StuffkeeperDataItem *item;
742 gtk_tree_model_get(model, iter, 2,&item, -1);
748 return self_item_is_visible(self, item);
752 item_is_visible(self, StuffkeeperDataItem *item)
754 int type = gtk_combo_box_get_active(GTK_COMBO_BOX(self->_priv->LeftPaneCB));
755 const gchar *text = gtk_entry_get_text(GTK_ENTRY(self->_priv->search_entry));
756 GtkTreeModel *model2 = gtk_tree_view_get_model(GTK_TREE_VIEW(self->_priv->treeview1));
760 * Left pane selection filtering
761 * Only when search type is not filter
763 if(gtk_tree_model_get_iter_first(model2, &piter) && type != LP_TYPE_SEARCH)
769 /* get the tag, and if it is selected */
770 gtk_tree_model_get(model2, &piter,LP_SELECTED,&sel, LP_ITEM,&tag, -1);
774 if(type == LP_TYPE_TAG && !stuffkeeper_data_item_has_tag(item, STUFFKEEPER_DATA_TAG(tag)))
778 /* if viewing types, and it matches mark found */
779 else if (type == LP_TYPE_SCHEMA &&
780 stuffkeeper_data_schema_get_id(stuffkeeper_data_item_get_schema(item)) ==
781 stuffkeeper_data_schema_get_id(STUFFKEEPER_DATA_SCHEMA(tag)))
785 /* set that there are items selected */
786 else if (type == LP_TYPE_SCHEMA && found == -1)
792 }while(gtk_tree_model_iter_next(model2, &piter));
793 /* if viewing types and no selected item matches return FALSE */
794 if(type == LP_TYPE_SCHEMA && found == 0)
802 if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(self->_priv->cb_search), &iter))
804 StuffkeeperDataItemSearch *search;
805 gtk_tree_model_get(self->_priv->model_searches, &iter, LP_ITEM, &search, -1);
808 if(!stuffkeeper_data_item_search_match(search, item))
819 return stuffkeeper_data_item_has_value(item,text);
825 search_entry_changed_timeout(self)
827 gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(self->_priv->model_items_filter));
829 self->_priv->search_timeout =0;
835 search_entry_icon_clicked(self,GtkEntryIconPosition pos, GdkEvent *event, GtkEntry *entry)
837 if(pos == GTK_ENTRY_ICON_SECONDARY) {
838 gtk_entry_set_text(entry, "");
844 search_entry_changed(self)
846 if(self->_priv->search_timeout) {
847 g_source_remove(self->_priv->search_timeout);
848 self->_priv->search_timeout = 0;
850 self->_priv->search_timeout = g_timeout_add(100,(GSourceFunc)self_search_entry_changed_timeout, self);
855 schema_edit_button_clicked(self, GtkWidget *button)
857 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
858 if(locked){printf("**ERROR** should not be callable\n");return;}
860 StuffkeeperDataSchema *schema = g_object_get_data(G_OBJECT(button), "schema");
863 StuffkeeperEditSchema *skes = stuffkeeper_edit_schema_new();
864 stuffkeeper_edit_schema_set_schema(skes, schema);
869 interface_background_changed(GtkWidget *widget, GtkStyle *old, GtkWidget *wid)
871 g_signal_handlers_block_by_func(G_OBJECT(widget), self_interface_background_changed, wid);
872 gtk_widget_modify_bg(wid, GTK_STATE_NORMAL, &(widget->style->light[GTK_STATE_NORMAL]));
873 g_signal_handlers_unblock_by_func(G_OBJECT(widget),self_interface_background_changed, wid);
878 item_pane_checkbox(self,GtkCheckMenuItem *item)
880 self_interface_item_selection_changed(self, gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview2)));
885 interface_item_selection_changed (self, GtkTreeSelection *selection)
892 gboolean show_pane = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(self->_priv->show_item_pane_menu_item));
894 list = gtk_container_get_children(GTK_CONTAINER(self->_priv->item_view_container));
898 for(node = g_list_first(list); node; node = g_list_next(node))
900 gtk_widget_destroy(GTK_WIDGET(node->data));
906 gtk_widget_hide(self->_priv->item_view_container);
911 model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->_priv->treeview2));
912 selected_items = gtk_tree_selection_count_selected_rows(selection);
913 if( selected_items == 1)
915 StuffkeeperDataItem *item;
916 GList *list = gtk_tree_selection_get_selected_rows(selection, &model);
917 if(gtk_tree_model_get_iter(model, &iter, (GtkTreePath *)list->data))
919 gtk_tree_model_get(model, &iter, 2, &item, -1);
922 GtkWidget *wid = stuffkeeper_item_view_new(item);
923 gtk_container_add(GTK_CONTAINER(self->_priv->item_view_container), wid);
924 gtk_widget_show_all(self->_priv->item_view_container);
929 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
933 else if ( selected_items > 1)
935 GtkWidget *wid = NULL;
936 StuffkeeperDataItem *item;
937 /* Multiple items selected */
938 GList *list = gtk_tree_selection_get_selected_rows(selection, &model);
939 GList *mitems = NULL, *liter;
940 for(liter = g_list_first(list); liter ; liter = g_list_next(liter)){
941 if(gtk_tree_model_get_iter(model, &iter, (GtkTreePath *)liter->data))
943 gtk_tree_model_get(model, &iter, 2, &item, -1);
944 mitems = g_list_prepend(mitems, item);
947 if(mitems) mitems = g_list_reverse(mitems);
948 /* Edit multiple items widget */
949 wid = (GtkWidget *)stuffkeeper_multiple_item_view_new(self->_priv->skdbg,mitems, NULL);
950 gtk_container_add(GTK_CONTAINER(self->_priv->item_view_container), wid);
951 gtk_widget_show_all(self->_priv->item_view_container);
953 if(mitems) { g_list_free(mitems); mitems = NULL;}
958 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
964 GtkWidget *frame = gtk_frame_new(NULL);
965 GtkWidget *label = gtk_label_new("");
966 GtkWidget *event = gtk_event_box_new();
967 GtkWidget *hbox = gtk_hbox_new(FALSE, 6);
968 GtkWidget *ali = gtk_alignment_new(1.0, 0.5,0,0);
970 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
971 g_signal_connect(G_OBJECT(event), "style-set", G_CALLBACK(self_interface_background_changed), event);
972 gtk_label_set_markup(GTK_LABEL(label), _("<b>No item to preview, select an item from the item list to preview it</b>"));
974 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
976 gtk_container_add(GTK_CONTAINER(ali), gtk_image_new_from_icon_name("stuffkeeper", GTK_ICON_SIZE_DIALOG));
977 gtk_box_pack_start(GTK_BOX(hbox),ali, TRUE, TRUE, 0);
978 gtk_box_pack_start(GTK_BOX(hbox),label, TRUE, TRUE, 0);
980 gtk_container_add(GTK_CONTAINER(frame),hbox);
981 gtk_container_add(GTK_CONTAINER(event),frame);
982 gtk_container_add(GTK_CONTAINER(self->_priv->item_view_container), event);
984 gtk_widget_modify_bg(event, GTK_STATE_NORMAL, &(self->_priv->item_view_container->style->white));
985 gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &(self->_priv->item_view_container->style->black));
986 gtk_widget_show_all(self->_priv->item_view_container);
992 * Right mouse handling left treeview
999 add_tag(self, GtkMenuItem *item)
1001 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
1002 if(locked){printf("**ERROR** should not be callable\n");return;}
1003 g_signal_handler_block(self->_priv->skdbg,self->_priv->signal_tag_added);
1004 StuffkeeperDataTag *tag = stuffkeeper_data_backend_new_tag(self->_priv->skdbg);
1006 stuffkeeper_data_tag_set_title(tag, _("New Tag"));
1010 gtk_list_store_append(GTK_LIST_STORE(self->_priv->model_tags), &iter);
1011 gchar *title = stuffkeeper_data_tag_get_title(tag);
1012 gtk_list_store_set(GTK_LIST_STORE(self->_priv->model_tags), &iter,
1013 0, stuffkeeper_data_tag_get_id(tag),
1016 4, stuffkeeper_data_tag_num_items(tag),
1019 if(self->_priv->treeview1_renderer)
1021 GtkTreeViewColumn *col = gtk_tree_view_get_column(GTK_TREE_VIEW(self->_priv->treeview1), 1);
1022 GtkTreePath *path = gtk_tree_model_get_path(self->_priv->model_tags, &iter);
1023 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(self->_priv->treeview1), path, col,self->_priv->treeview1_renderer, TRUE);
1024 gtk_tree_path_free(path);
1028 g_signal_handler_unblock(self->_priv->skdbg,self->_priv->signal_tag_added);
1032 remove_tag(self, GtkMenuItem *item)
1034 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
1035 if(locked){printf("**ERROR** should not be callable\n");return;}
1036 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview1));
1037 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->_priv->treeview1));
1039 if(gtk_tree_selection_get_selected(selection,&model, &iter))
1043 /* Get id and items */
1044 gtk_tree_model_get(model, &iter,0,&id,4,&items, -1);
1048 stuffkeeper_data_backend_remove_tag(self->_priv->skdbg,id);
1054 open_tag(self, GtkMenuItem *item)
1056 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview1));
1057 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->_priv->treeview1));
1059 if(gtk_tree_selection_get_selected(selection,&model, &iter))
1061 StuffkeeperDataTag *tag = NULL;
1062 /* Get id and items */
1063 gtk_tree_model_get(model, &iter,3,&tag, -1);
1065 gchar *title = stuffkeeper_data_tag_get_title(tag);
1066 GtkWidget *win = stuffkeeper_item_window_new_tag_list(self->_priv->skdbg, tag,config_file, title);
1068 gtk_widget_show(win);
1078 add_item_of_type(self, GtkMenuItem *item)
1080 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
1081 if(locked){printf("**ERROR** should not be callable\n");return;}
1083 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview1));
1084 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->_priv->treeview1));
1086 if(gtk_tree_selection_get_selected(selection,&model, &iter))
1088 StuffkeeperDataSchema *schema = NULL;
1089 /* Get id and items */
1090 gtk_tree_model_get(model, &iter,LP_ITEM,&schema, -1);
1093 StuffkeeperDataItem *item = stuffkeeper_data_backend_new_item(self->_priv->skdbg,schema);
1096 /* signal to other window components that the item was added on this
1098 self_item_added_here(self, item);
1105 add_type(self, GtkMenuItem *item)
1107 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
1108 if(locked){printf("**ERROR** should not be callable\n");return;}
1110 g_signal_handler_block(self->_priv->skdbg,self->_priv->signal_schema_added);
1111 StuffkeeperDataSchema *schema = stuffkeeper_data_backend_new_schema(self->_priv->skdbg);
1112 stuffkeeper_data_schema_set_title(schema, _("New Schema"));
1116 gtk_list_store_append(GTK_LIST_STORE(self->_priv->model_schemas), &iter);
1117 gchar *title = stuffkeeper_data_schema_get_title(schema);
1118 gtk_list_store_set(GTK_LIST_STORE(self->_priv->model_schemas), &iter,
1119 0, stuffkeeper_data_schema_get_id(schema),
1122 4, stuffkeeper_data_schema_num_items(schema),-1);
1126 if(self->_priv->treeview1_renderer)
1128 GtkTreeViewColumn *col = gtk_tree_view_get_column(GTK_TREE_VIEW(self->_priv->treeview1), 1);
1129 GtkTreePath *path = gtk_tree_model_get_path(self->_priv->model_schemas, &iter);
1130 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(self->_priv->treeview1), path, col,self->_priv->treeview1_renderer, TRUE);
1131 gtk_tree_path_free(path);
1134 g_signal_handler_unblock(self->_priv->skdbg,self->_priv->signal_schema_added);
1138 remove_type(self, GtkMenuItem *item)
1140 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
1141 if(locked){printf("**ERROR** should not be callable\n");return;}
1143 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview1));
1144 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->_priv->treeview1));
1146 if(gtk_tree_selection_get_selected(selection,&model, &iter))
1150 /* Get id and items */
1151 gtk_tree_model_get(model, &iter,0,&id,4,&items, -1);
1155 stuffkeeper_data_backend_remove_schema(self->_priv->skdbg,id);
1163 edit_type(self, GtkMenuItem *item)
1165 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
1166 if(locked){printf("**ERROR** should not be callable\n");return;}
1168 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview1));
1169 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->_priv->treeview1));
1171 if(gtk_tree_selection_get_selected(selection,&model, &iter))
1173 StuffkeeperDataSchema *schema;
1174 gtk_tree_model_get(model, &iter, 3, &schema, -1);
1177 StuffkeeperEditSchema *skes = stuffkeeper_edit_schema_new();
1178 stuffkeeper_edit_schema_set_schema(skes, schema);
1183 /* right mouse menu item treeview */
1186 treeview2_button_press_event(self, GdkEventButton *event, GtkWidget *widget)
1188 return self_click_fix(self, event, widget);
1193 menu_plugin_called(self, GtkWidget *item)
1195 StuffkeeperPlugin *plugin = g_object_get_data(G_OBJECT(item), "plugin");
1198 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview2));
1199 GtkWidget *tree = self->_priv->treeview2;
1200 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree));
1202 // if(gtk_tree_selection_get_selected(selection, &model, &iter))
1203 if(gtk_tree_selection_count_selected_rows(selection) == 1)
1206 StuffkeeperDataItem *item;
1208 list = gtk_tree_selection_get_selected_rows(selection, &model);
1209 if(gtk_tree_model_get_iter(model, &iter, (GtkTreePath *)list->data))
1211 gtk_tree_model_get(model, &iter, 2, &item, -1);
1214 stuffkeeper_plugin_run_item(STUFFKEEPER_PLUGIN(plugin), item);
1220 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
1228 menu_plugin_tag_called(self, GtkWidget *item)
1230 StuffkeeperPlugin *plugin = g_object_get_data(G_OBJECT(item), "plugin");
1233 GtkWidget *tree = self->_priv->treeview1;
1234 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
1235 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree));
1237 // if(gtk_tree_selection_get_selected(selection, &model, &iter))
1238 if(gtk_tree_selection_count_selected_rows(selection) == 1)
1241 StuffkeeperDataTag *tag;
1243 list = gtk_tree_selection_get_selected_rows(selection, &model);
1244 if(gtk_tree_model_get_iter(model, &iter, (GtkTreePath *)list->data))
1246 gtk_tree_model_get(model, &iter, 3, &tag, -1);
1249 stuffkeeper_plugin_run_tag(STUFFKEEPER_PLUGIN(plugin), tag);
1255 g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
1264 treeview2_button_release_event(self, GdkEventButton *event, GtkWidget *widget)
1266 g_debug("treeview2 buttom release event\n");
1267 if(event->button == 3)
1269 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview2));
1270 //GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->_priv->treeview2));
1271 if(gtk_tree_selection_count_selected_rows(selection) > 0)
1274 GtkWidget *menu_item;
1277 menu = gtk_menu_new();
1279 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN, NULL);
1280 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(self_interface_item_open), self);
1281 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1283 if(!stuffkeeper_data_backend_get_locked(self->_priv->skdbg))
1285 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_REMOVE, NULL);
1286 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(self_interface_item_remove), self);
1287 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1290 if(gtk_tree_selection_count_selected_rows(selection) == 1)
1292 menu_item = gtk_image_menu_item_new_with_label(_("Export"));
1293 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU));
1294 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(self_export_html_item), self);
1295 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1298 node = stuffkeeper_plugin_manager_get_loaded_plugins(self->_priv->spm);
1301 for(iter = g_list_first(node);iter;iter = g_list_next(iter))
1303 StuffkeeperPlugin *plugin = iter->data;
1304 if(stuffkeeper_plugin_get_plugin_type(plugin)&PLUGIN_ITEM)
1306 gint width = 16, height=16;
1307 GdkPixbuf *pb = stuffkeeper_plugin_get_icon(plugin);
1309 menu_item = gtk_image_menu_item_new_with_label(stuffkeeper_plugin_get_name(plugin));
1312 GdkPixbuf *scale = gdk_pixbuf_scale_simple(pb,width, height, GDK_INTERP_BILINEAR);
1313 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),gtk_image_new_from_pixbuf(scale));
1314 g_object_unref(scale);
1317 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(self_menu_plugin_called), self);
1318 g_object_set_data(G_OBJECT(menu_item), "plugin", plugin);
1319 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1325 /* popup the menu */
1326 gtk_widget_show_all(menu);
1328 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, event->time);
1337 /* Right mouse button press */
1340 treeview1_button_press_event(self, GdkEventButton *event, GtkWidget *widget)
1347 treeview1_button_release_event(self, GdkEventButton *event, GtkWidget *widget)
1349 if(stuffkeeper_data_backend_get_locked(self->_priv->skdbg))
1351 /* no right menu in locked mode */
1356 /* Right mouse click, ignore rest */
1357 if(event->button == 3)
1359 int type = gtk_combo_box_get_active(GTK_COMBO_BOX(self->_priv->LeftPaneCB));
1360 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview1));
1361 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->_priv->treeview1));
1364 GtkWidget *menu_item;
1366 g_debug("treeview 1 button press event\n");
1368 menu = gtk_menu_new();
1370 if(type == LP_TYPE_TAG)
1372 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN, NULL);
1373 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(self_open_tag), self);
1374 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1377 menu_item = gtk_image_menu_item_new_with_label(_("New tag"));
1378 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
1379 gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU));
1380 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(self_add_tag), self);
1381 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1382 if(gtk_tree_selection_get_selected(selection,&model, &iter))
1385 /* Get the number of items */
1386 gtk_tree_model_get(model, &iter, 4, &items, -1);
1388 /* no items, then you can delete it*/
1391 menu_item = gtk_image_menu_item_new_with_label(_("Remove tag"));
1392 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
1393 gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
1394 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(self_remove_tag),self);
1395 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1399 GList *iter, *node = stuffkeeper_plugin_manager_get_loaded_plugins(self->_priv->spm);
1402 for(iter = g_list_first(node);iter;iter = g_list_next(iter))
1404 StuffkeeperPlugin *plugin = iter->data;
1405 if(stuffkeeper_plugin_get_plugin_type(plugin)&PLUGIN_TAG)
1407 gint width = 16, height=16;
1408 GdkPixbuf *pb = stuffkeeper_plugin_get_icon(plugin);
1409 menu_item = gtk_image_menu_item_new_with_label(stuffkeeper_plugin_get_name(plugin));
1412 GdkPixbuf *scale = gdk_pixbuf_scale_simple(pb,
1413 width, height, GDK_INTERP_BILINEAR);
1414 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
1415 gtk_image_new_from_pixbuf(scale));
1416 g_object_unref(scale);
1419 g_signal_connect_swapped(G_OBJECT(menu_item), "activate",
1420 G_CALLBACK(self_menu_plugin_tag_called), self);
1421 g_object_set_data(G_OBJECT(menu_item), "plugin", plugin);
1422 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1430 else if (type == LP_TYPE_SCHEMA)
1433 menu_item = gtk_image_menu_item_new_with_label(_("New type"));
1434 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
1435 gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU));
1436 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(self_add_type), self);
1437 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1438 if(gtk_tree_selection_get_selected(selection,&model, &iter))
1442 StuffkeeperDataSchema *schema = NULL;
1443 /* Get the number of items */
1444 gtk_tree_model_get(model, &iter, LP_ITEM, &schema, 4, &items, -1);
1447 /* no items, then you can delete it*/
1450 menu_item = gtk_image_menu_item_new_with_label(_("Remove type"));
1451 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
1452 gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
1453 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(self_remove_type),self);
1454 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1456 menu_item = gtk_image_menu_item_new_with_label(_("Edit type"));
1457 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
1458 gtk_image_new_from_stock(GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU));
1459 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(self_edit_type),self);
1460 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1463 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
1464 /* add item of this type */
1465 temp = g_strdup_printf("%s %s %s", _("Add new"), stuffkeeper_data_schema_get_title(schema), _("item"));
1466 menu_item = gtk_image_menu_item_new_with_label(temp);
1468 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
1469 gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU));
1470 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(self_add_item_of_type),self);
1471 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1474 } else if (type == LP_TYPE_SEARCH)
1477 menu_item = gtk_image_menu_item_new_with_label(_("New filter"));
1478 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
1479 gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU));
1480 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(self_new_search), self);
1481 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1482 if(gtk_tree_selection_get_selected(selection,&model, &iter))
1485 StuffkeeperDataItemSearch *search;
1486 /* Get the number of items */
1487 gtk_tree_model_get(model, &iter, 0, &id,3, &search, -1);
1489 /* no items, then you can delete it*/
1493 menu_item = gtk_image_menu_item_new_with_label(_("Remove filter"));
1494 g_object_set_data(G_OBJECT(menu_item), "search", search);
1495 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
1496 gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
1497 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(self_remove_search_menu),self);
1498 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1501 menu_item = gtk_image_menu_item_new_with_label(_("Edit filter"));
1502 g_object_set_data(G_OBJECT(menu_item), "search", search);
1503 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
1504 gtk_image_new_from_stock(GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU));
1505 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(self_edit_search_menu),self);
1506 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1511 /* popup the menu */
1512 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, event->time);
1513 /* show the widget */
1514 gtk_widget_show_all(menu);
1515 /* don't pass message */
1523 StuffkeeperInterface *
1524 new(GKeyFile *config_file)
1526 GtkAccelGroup *agroup = NULL;
1527 int value,width,height;
1528 GError *error = NULL;
1529 Self *self = g_object_ref_sink(GET_NEW);
1531 self->_priv->xml = gtk_builder_new();
1533 self->config_file = config_file;
1534 gtk_builder_add_from_file(self->_priv->xml, PACKAGE_DATADIR"/stuffkeeper.ui", &error);
1537 g_object_unref(self);
1538 g_debug("Failed top open xml file: %s\n", error->message);
1539 g_error_free(error);
1542 self->_priv->hpaned1 = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "hpaned1");
1543 self->_priv->vpaned1 = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "vpaned1");
1544 self->_priv->LeftPaneCB =(GtkWidget *) gtk_builder_get_object(self->_priv->xml, "LeftPaneCB");
1545 self->_priv->treeview1 = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "treeview1");
1546 self->_priv->treeview2 = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "treeview2");
1548 self->_priv->LeftPane_edit = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "LeftPane_edit");
1549 self->_priv->AddMenuButton = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "AddMenuButton");
1551 self->_priv->item_label = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "item_label");
1552 self->_priv->item_view_container = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "item_view_container");
1553 self->_priv->show_item_pane_menu_item = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "show_item_pane_menu_item");
1555 self->_priv->cb_search = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "cb_search");
1557 self->_priv->menuitem_item_add = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_item_add");
1559 self->_priv->win = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "win");
1562 agroup = gtk_accel_group_new();
1563 gtk_window_add_accel_group(GTK_WINDOW(self->_priv->win), agroup);
1565 gtk_widget_hide_on_delete(self->_priv->win);
1568 * Custom search widget,
1570 self->_priv->search_entry = gtk_entry_new();
1571 /* Add clear button */
1572 gtk_entry_set_icon_from_stock(GTK_ENTRY(self->_priv->search_entry),GTK_ENTRY_ICON_SECONDARY,
1575 gtk_entry_set_icon_from_stock(GTK_ENTRY(self->_priv->search_entry),GTK_ENTRY_ICON_PRIMARY,
1577 g_signal_connect_swapped(G_OBJECT(self->_priv->search_entry), "icon-release" ,
1578 G_CALLBACK(self_search_entry_icon_clicked), self);
1580 gtk_box_pack_end(GTK_BOX(gtk_builder_get_object(self->_priv->xml,"hbox3")), self->_priv->search_entry, TRUE, TRUE, 0);
1581 g_signal_connect_swapped(G_OBJECT(self->_priv->search_entry), "changed", G_CALLBACK(self_search_entry_changed), self);
1583 gtk_widget_show_all(GTK_WIDGET(self->_priv->search_entry));
1585 gtk_widget_add_accelerator(self->_priv->search_entry, "grab-focus",agroup, GDK_f, GDK_CONTROL_MASK,0);
1589 value = g_key_file_get_integer(self->config_file, "WINDOW", "hpane", &error);
1591 g_debug("No valid pane position: %s\n", error->message);
1593 g_error_free(error);
1598 g_debug("Setting position: %i\n", value);
1599 gtk_paned_set_position(GTK_PANED(self->_priv->hpaned1), value);
1601 /* restore layout */
1603 value = g_key_file_get_integer(self->config_file, "WINDOW", "alternative-layout", &error);
1605 g_debug("No valid layout position: %s\n", error->message);
1607 g_error_free(error);
1612 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_builder_get_object(self->_priv->xml, "alternative_layout_cb")), value);
1613 self_set_alternative_layout(self, value);
1615 g_debug("Setting position: %i\n", value);
1616 gtk_paned_set_position(GTK_PANED(self->_priv->vpaned1), value);
1619 /* Restore size and position */
1621 width = g_key_file_get_integer(self->config_file, "WINDOW", "width", &error);
1623 g_error_free(error);
1626 height = g_key_file_get_integer(self->config_file, "WINDOW", "height", &error);
1628 g_error_free(error);
1631 gtk_window_resize(GTK_WINDOW(self->_priv->win), width, height);
1635 width = g_key_file_get_integer(self->config_file, "WINDOW", "x-pos", &error);
1637 g_error_free(error);
1640 height = g_key_file_get_integer(self->config_file, "WINDOW", "y-pos", &error);
1642 g_error_free(error);
1645 gtk_window_move(GTK_WINDOW(self->_priv->win), width, height);
1649 width = g_key_file_get_integer(self->config_file, "WINDOW", "show-item-pane", &error);
1651 g_error_free(error);
1654 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(self->_priv->show_item_pane_menu_item),width);
1657 /* setup treeview */
1658 gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(self->_priv->treeview2), TRUE);
1659 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(self->_priv->treeview2), FALSE);
1662 gtk_builder_connect_signals_full(self->_priv->xml, (GtkBuilderConnectFunc)self____builder_xml_connect_foreach, (gpointer)self);
1664 gtk_widget_show(self->_priv->win);
1665 /* put this after the show, or it will turn up black, for some oddball reason */
1666 self_interface_item_selection_changed(self, gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview2)));
1668 interface_element_add((GtkWidget *)(self));
1675 left_pane_changed(self, GtkComboBox *box)
1677 GtkWidget *entry = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "LeftPaneFilterEntry");
1678 int i = gtk_combo_box_get_active(box);
1680 gtk_tree_view_column_set_visible(self->_priv->column_lv_pixbuf, FALSE);
1682 gtk_widget_show(entry);
1683 gtk_tree_view_set_model(GTK_TREE_VIEW(self->_priv->treeview1), GTK_TREE_MODEL(self->_priv->model_tags_filter));
1685 gtk_widget_hide(entry);
1686 gtk_tree_view_column_set_visible(self->_priv->column_lv_pixbuf, TRUE);
1687 gtk_tree_view_set_model(GTK_TREE_VIEW(self->_priv->treeview1), GTK_TREE_MODEL(self->_priv->model_schemas));
1688 }else if ( i == 2) {
1689 gtk_widget_hide(entry);
1690 gtk_tree_view_set_model(GTK_TREE_VIEW(self->_priv->treeview1), GTK_TREE_MODEL(self->_priv->model_searches));
1693 /* refilter the items list */
1694 gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(self->_priv->model_items_filter));
1699 search_type_changed(self, GtkComboBox *box)
1701 GtkTreeIter iter, node;
1702 if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(self->_priv->cb_search), &iter))
1704 StuffkeeperDataItemSearch *search;
1705 GtkWidget *item = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_filter_remove");
1706 GtkWidget *item1 = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_filter_edit");
1708 gtk_tree_model_get(self->_priv->model_searches, &iter,0,&id, 3, &search, -1);
1711 gtk_widget_set_sensitive(item, FALSE);
1712 gtk_widget_set_sensitive(item1, FALSE);
1714 gtk_widget_set_sensitive(item, TRUE);
1715 gtk_widget_set_sensitive(item1, TRUE);
1717 if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(self->_priv->model_searches), &node)) {
1719 gtk_list_store_set(GTK_LIST_STORE(self->_priv->model_searches), &node, 2, FALSE,-1);
1720 }while(gtk_tree_model_iter_next(GTK_TREE_MODEL(self->_priv->model_searches), &node));
1722 gtk_list_store_set(GTK_LIST_STORE(self->_priv->model_searches), &iter, 2, TRUE,-1);
1724 /* refilter the items list */
1725 gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(self->_priv->model_items_filter));
1728 /* This function sets the right image on the CellRenderer for the pixbuf column.
1729 * Only does it when showing Schema list
1733 interface_lv_get_schema_pixbuf(GtkTreeViewColumn *col, GtkCellRenderer *renderer,GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
1735 Self *self = SELF(data);
1736 int type = gtk_combo_box_get_active(GTK_COMBO_BOX(self->_priv->LeftPaneCB));
1737 if(type == LP_TYPE_SCHEMA)
1739 StuffkeeperDataSchema *schema;
1740 gtk_tree_model_get(self->_priv->model_schemas, iter, LP_ITEM, &schema, -1);
1743 GdkPixbuf *pb = stuffkeeper_data_schema_get_pixbuf(schema);
1744 g_object_set(G_OBJECT(renderer), "pixbuf", pb,NULL);
1752 update_all_item_add_menus(self) {
1753 self_update_item_add_menu(self, GTK_MENU_SHELL(self->_priv->menu), FALSE);
1754 self_update_item_add_menu(self, GTK_MENU_SHELL(self->_priv->menu_item_add), TRUE);
1757 if(g_object_get_data(G_OBJECT(self->_priv->AddMenuButton), "schema") == NULL)
1759 GList *list = stuffkeeper_data_backend_get_schemas(self->_priv->skdbg);
1762 gtk_widget_set_tooltip_text(self->_priv->AddMenuButton, stuffkeeper_data_schema_get_title((StuffkeeperDataSchema *)list->data));
1763 g_object_set_data(G_OBJECT(self->_priv->AddMenuButton), "schema", list->data);
1767 gtk_widget_set_tooltip_text(self->_priv->AddMenuButton, "");
1774 update_item_add_menu(self, Gtk:MenuShell *menu, gboolean add_hotkeys)
1777 GList *node,*items = NULL;
1779 items = gtk_container_get_children(GTK_CONTAINER(menu));
1780 for(node = items; node;node = g_list_next(node))
1782 gtk_widget_destroy(GTK_WIDGET(node->data));
1787 if(gtk_tree_model_get_iter_first(self->_priv->model_schemas,&iter))
1789 gchar *menu_hotkeys = NULL;
1790 gchar **menu_hotkeys_list = NULL;
1791 gchar **menu_hotkey_ptr = NULL;
1793 /* Colon-seperated list of shortcut-prefixes for menu items the
1794 * last item on the list will be repeated for all menu entries
1795 * witout their own items */
1797 menu_hotkeys = _("_1. :_2. :_3. :_4. :_5. :_6. :_7. :_8. :_9. :_0. :_A. :_B. :_C. :_D. :_E. :_F. :_G. :_H. :_I. :_J. :_K. :_L. :_M. :_M. :_N. :_O. :_P. :_Q. :_R. :_S. :_T. :_U. :_V. :_W. :_X. :_Y. :_Z. : ");
1798 menu_hotkeys_list = g_strsplit(menu_hotkeys, ":", -1);
1799 menu_hotkey_ptr = menu_hotkeys_list;
1802 gchar *title = NULL;
1803 gchar *menu_entry = NULL;
1804 GtkWidget *m = NULL;
1805 StuffkeeperDataSchema *schema = NULL;
1807 gtk_tree_model_get(self->_priv->model_schemas, &iter, 1, &title,3,&schema, -1);
1809 if(title && g_strstr_len(title, -1, "_")) {
1811 /* Need to escape underscores in the title */
1812 tsplit = g_strsplit(title, "_", -1);
1814 title = g_strjoinv("__",tsplit);
1817 menu_entry = g_strconcat(*menu_hotkey_ptr, (title == NULL)?_("n/a"):title, NULL);
1818 m=gtk_image_menu_item_new_with_mnemonic(menu_entry);
1820 m=gtk_image_menu_item_new_with_label((title == NULL)?_("n/a"):title);
1822 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(m),
1823 gtk_image_new_from_pixbuf(stuffkeeper_data_schema_get_pixbuf(schema)));
1824 gtk_menu_shell_insert(GTK_MENU_SHELL(menu), m,-1);
1825 g_object_set_data(G_OBJECT(m), "schema", schema);
1826 g_signal_connect_swapped(G_OBJECT(m), "activate", G_CALLBACK(self_interface_item_add_menu_button), self);
1833 if(add_hotkeys && menu_hotkey_ptr[1]) {
1837 } while(gtk_tree_model_iter_next(self->_priv->model_schemas, &iter));
1838 gtk_widget_show_all(GTK_WIDGET(menu));
1840 g_strfreev(menu_hotkeys_list);
1847 style_changed(GtkWidget *tree,GtkStyle *old, GtkCellRenderer *renderer)
1849 g_debug("style changed\n");
1850 g_object_set(G_OBJECT(renderer),
1851 "background-set", TRUE, "background-gdk",&(GTK_WIDGET(tree)->style->bg[GTK_STATE_SELECTED]),
1852 "foreground-set", TRUE, "foreground-gdk",&(GTK_WIDGET(tree)->style->fg[GTK_STATE_SELECTED]),
1859 get_pixbuf(GtkTreeViewColumn *column, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
1861 StuffkeeperDataItem *item;
1862 StuffkeeperDataSchema *schema;
1864 gtk_tree_model_get(model, iter, 2, &item, -1);
1865 schema = stuffkeeper_data_item_get_schema(item);
1868 pb = stuffkeeper_data_schema_get_pixbuf(schema);
1869 g_object_set(renderer, "pixbuf", pb,NULL);
1875 backend_locked(self, GParamSpec *arg1, StuffkeeperDataBackend *backend)
1877 GtkWidget *button = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "toggle_locked");
1878 gboolean value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
1879 gboolean locked = stuffkeeper_data_backend_get_locked(backend);
1883 g_signal_handler_block(self->_priv->skdbg,self->_priv->signal_backend_locked);
1884 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), locked);
1885 g_signal_handler_unblock(self->_priv->skdbg,self->_priv->signal_backend_locked);
1888 button = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_view_locked");
1889 value = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(button));
1892 g_signal_handler_block(self->_priv->skdbg,self->_priv->signal_backend_locked);
1893 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(button), locked);
1894 g_signal_handler_unblock(self->_priv->skdbg,self->_priv->signal_backend_locked);
1897 /* change the interface */
1900 g_object_set(G_OBJECT(self->_priv->treeview1_renderer), "editable", FALSE, NULL);
1901 gtk_widget_hide((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "toolbar1"));
1902 gtk_widget_hide((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_item_sep"));
1903 gtk_widget_hide((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_item_add"));
1904 gtk_widget_hide((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_item_remove"));
1905 gtk_widget_hide((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_item_clone"));
1906 gtk_widget_hide((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_filter"));
1907 gtk_widget_hide((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_type_new"));
1908 gtk_widget_hide((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_type_import"));
1910 g_object_set(G_OBJECT(self->_priv->treeview1_renderer), "editable", TRUE, NULL);
1911 gtk_widget_show((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "toolbar1"));
1912 gtk_widget_show((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_item_sep"));
1913 gtk_widget_show((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_item_add"));
1914 gtk_widget_show((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_item_remove"));
1915 gtk_widget_show((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_item_clone"));
1916 gtk_widget_show((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_filter"));
1917 gtk_widget_show((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_type_new"));
1918 gtk_widget_show((GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_type_import"));
1925 menu_backend_locked_toggled(self, GtkCheckMenuItem *item)
1927 gboolean value = gtk_check_menu_item_get_active(item);
1928 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
1931 stuffkeeper_data_backend_set_locked(self->_priv->skdbg, value);
1936 backend_locked_toggled(self, GtkToggleButton *button)
1938 gboolean value = gtk_toggle_button_get_active(button);
1939 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
1942 stuffkeeper_data_backend_set_locked(self->_priv->skdbg, value);
1947 gboolean click_fix (self, GdkEventButton *event, GtkWidget *tree)
1949 GtkTreePath *path = NULL;
1950 if(event->button == 3 && gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tree), event->x, event->y,&path,NULL,NULL,NULL))
1952 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
1953 if(gtk_tree_selection_path_is_selected(sel, path))
1955 gtk_tree_path_free(path);
1961 gtk_tree_path_free(path);
1965 public void left_pane_filter_entry_clear(self, GtkEntryIconPosition pos, GdkEvent *event, GtkEntry *entry)
1967 if(pos == GTK_ENTRY_ICON_SECONDARY) {
1968 gtk_entry_set_text(entry, "");
1972 public void left_pane_filter_changed(self, GtkEditable *editable)
1974 gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(self->_priv->model_tags_filter));
1978 * React if the user presses enter in the filter entry.
1979 * 1 item visible -> open it.
1980 * 2 or more items visible -> do nothing.
1981 * 3 items visible -> ask user to add it as tag.
1984 public void left_pane_filter_entry_activate(self, GtkEntry *entry)
1986 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
1987 int type = gtk_combo_box_get_active(GTK_COMBO_BOX(self->_priv->LeftPaneCB));
1988 int num_items = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(self->_priv->model_tags_filter), NULL);
1989 if(type != 0) return;
1990 if( num_items == 0) {
1992 GtkWidget * dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(self->_priv->win),
1993 GTK_DIALOG_DESTROY_WITH_PARENT,
1995 GTK_BUTTONS_OK_CANCEL,
1996 "Add tag with name: <i>%s</i>?",
1997 gtk_entry_get_text(GTK_ENTRY(entry)));
1998 switch(gtk_dialog_run(GTK_DIALOG(dialog)))
2000 case GTK_RESPONSE_OK:
2002 StuffkeeperDataTag *tag = stuffkeeper_data_backend_new_tag(self->_priv->skdbg);
2003 stuffkeeper_data_tag_set_title(tag, gtk_entry_get_text(entry));
2006 gtk_widget_destroy(dialog);
2010 }else if (num_items == 1) {
2012 if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(self->_priv->model_tags_filter), &iter))
2014 StuffkeeperDataTag *tag;
2015 gtk_tree_model_get(GTK_TREE_MODEL(self->_priv->model_tags_filter), &iter,3, &tag, -1);
2019 GList *items = stuffkeeper_data_tag_get_items(tag);
2021 gchar *title = stuffkeeper_data_tag_get_title(tag);
2022 printf("Window items\n");
2023 GtkWidget *win = stuffkeeper_item_window_new_multiple(self->_priv->skdbg, items,config_file, title);
2025 gtk_widget_show(win);
2038 private gboolean left_pane_filter_function(GtkTreeModel *model, GtkTreeIter *iter,gpointer data)
2040 Self *self = SELF(data);
2041 gboolean visible = FALSE;
2043 gchar *compare = NULL;
2045 GtkEntry *entry = (GtkEntry *)gtk_builder_get_object(self->_priv->xml, "LeftPaneFilterEntry");
2046 if(entry == NULL || gtk_entry_buffer_get_length (gtk_entry_get_buffer (entry)) == 0)
2048 /* if nothing entered, allow everything */
2051 data = gtk_entry_get_text(entry);
2052 gtk_tree_model_get (model, iter, 1, &compare, -1);
2055 gchar *asmall = g_utf8_normalize(compare, -1, G_NORMALIZE_ALL);
2056 gchar *bsmall = g_utf8_normalize(data, -1, G_NORMALIZE_ALL);
2057 gchar *alower = g_utf8_casefold(asmall, -1);
2058 gchar *blower = g_utf8_casefold(bsmall, -1);
2060 visible = strstr(alower, blower) != NULL;
2073 * Initialize the main gui
2077 initialize_interface(self, StuffkeeperDataBackend *skdb,GObject *spm)
2079 GError *error = NULL;
2080 gint value = 0, sort_order;
2082 GtkTreeViewColumn *column;
2083 GtkCellRenderer *renderer;
2084 GtkTreeSelection *sel;
2086 * StuffkeeperDataBackend
2088 self->_priv->skdbg = skdb;
2089 self->_priv->spm = STUFFKEEPER_PLUGIN_MANAGER(spm);
2091 self->_priv->signal_backend_locked = g_signal_connect_swapped(G_OBJECT(self->_priv->skdbg), "notify::locked", G_CALLBACK(self_backend_locked), self);
2093 /* Setting up backends */
2094 self->_priv->model_schemas = (GtkTreeModel *)gtk_list_store_new(5, G_TYPE_INT,G_TYPE_STRING,G_TYPE_BOOLEAN,G_TYPE_POINTER,G_TYPE_INT);
2095 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(self->_priv->model_schemas), 1, GTK_SORT_ASCENDING);
2097 /* New Item menus */
2098 self->_priv->menu = gtk_menu_new();
2099 gtk_menu_tool_button_set_menu(GTK_MENU_TOOL_BUTTON(self->_priv->AddMenuButton), (self->_priv->menu));
2100 self->_priv->menu_item_add = gtk_menu_new();
2101 gtk_menu_item_set_submenu(GTK_MENU_ITEM(self->_priv->menuitem_item_add), self->_priv->menu_item_add);
2103 /** Load the schemas*/
2104 node = stuffkeeper_data_backend_get_schemas(self->_priv->skdbg);
2105 for(iter = node;iter;iter = g_list_next(iter))
2107 self_schema_added(self, STUFFKEEPER_DATA_SCHEMA(iter->data), self->_priv->skdbg);
2109 if(node) g_list_free(node);
2111 self->_priv->signal_schema_added = g_signal_connect_swapped(G_OBJECT(self->_priv->skdbg),
2113 G_CALLBACK(self_schema_added),
2115 self->_priv->signal_schema_removed =g_signal_connect_swapped(G_OBJECT(self->_priv->skdbg),
2117 G_CALLBACK(self_schema_removed),
2119 self->_priv->signal_schema_changed=g_signal_connect_swapped(G_OBJECT(self->_priv->skdbg),
2121 G_CALLBACK(self_schema_changed),
2128 self->_priv->model_tags = (GtkTreeModel *)gtk_list_store_new(5, G_TYPE_INT,G_TYPE_STRING,G_TYPE_BOOLEAN,G_TYPE_POINTER,G_TYPE_INT);
2129 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(self->_priv->model_tags), 1, GTK_SORT_ASCENDING);
2130 /* Setup filtering */
2131 self->_priv->model_tags_filter = (GtkTreeModel *)gtk_tree_model_filter_new(GTK_TREE_MODEL(self->_priv->model_tags),NULL);
2132 gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(self->_priv->model_tags_filter), self_left_pane_filter_function, self, NULL);
2135 /** Load the tags */
2136 node = stuffkeeper_data_backend_get_tags(self->_priv->skdbg);
2137 for(iter = node;iter;iter = g_list_next(iter))
2139 self_tag_added(self->_priv->skdbg, iter->data,self->_priv->model_tags);
2141 if(node) g_list_free(node);
2142 /* handle an added tag */
2143 self->_priv->signal_tag_added = g_signal_connect(G_OBJECT(self->_priv->skdbg),
2145 G_CALLBACK(self_tag_added),
2146 self->_priv->model_tags);
2147 self->_priv->signal_tag_changed = g_signal_connect(G_OBJECT(self->_priv->skdbg),
2149 G_CALLBACK(self_tag_changed),
2150 self->_priv->model_tags);
2151 self->_priv->signal_tag_removed = g_signal_connect(G_OBJECT(self->_priv->skdbg),
2153 G_CALLBACK(self_tag_removed),
2154 self->_priv->model_tags);
2156 self->_priv->model_items = (GtkTreeModel *)gtk_list_store_new(6, G_TYPE_INT,G_TYPE_STRING,G_TYPE_POINTER,G_TYPE_INT,G_TYPE_INT,G_TYPE_INT);
2157 sort_order = g_key_file_get_integer(self->config_file, "WINDOW", "item-sort-order", &error);
2160 sort_order= GTK_SORT_DESCENDING;
2161 g_error_free(error);
2166 self->_priv->item_sort_order = sort_order;
2167 if(sort_order == GTK_SORT_DESCENDING)
2169 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_builder_get_object(self->_priv->xml, "menu_sort_descending")),TRUE);
2171 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_builder_get_object(self->_priv->xml, "menu_sort_ascending")),TRUE);
2174 value = g_key_file_get_integer(self->config_file, "WINDOW", "item-sort-column", &error);
2176 self->_priv->item_sort_column = value;
2177 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(self->_priv->model_items), value, sort_order);
2180 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_builder_get_object(self->_priv->xml, "menu_sort_by_title")),TRUE);
2183 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_builder_get_object(self->_priv->xml, "menu_sort_by_schema")),TRUE);
2186 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_builder_get_object(self->_priv->xml, "menu_sort_by_modification_time")),TRUE);
2189 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_builder_get_object(self->_priv->xml, "menu_sort_by_creation_time")),TRUE);
2193 g_error_free(error);
2195 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(self->_priv->model_items), 3, sort_order);
2197 /** Load the items*/
2198 node = stuffkeeper_data_backend_get_items(self->_priv->skdbg);
2199 stuffkeeper_data_backend_begin_transaction(self->_priv->skdbg);
2200 for(iter = node;iter;iter = g_list_next(iter))
2202 self_item_added(self->_priv->skdbg, STUFFKEEPER_DATA_ITEM(iter->data),self);
2204 stuffkeeper_data_backend_end_transaction(self->_priv->skdbg);
2205 if(node) g_list_free(node);
2206 self->_priv->signal_item_added = g_signal_connect(G_OBJECT(self->_priv->skdbg),
2208 G_CALLBACK(self_item_added),
2210 self->_priv->signal_item_removed = g_signal_connect(G_OBJECT(self->_priv->skdbg),
2212 G_CALLBACK(self_item_removed),
2214 self->_priv->signal_item_changed = g_signal_connect(G_OBJECT(self->_priv->skdbg),
2216 G_CALLBACK(self_item_changed),
2222 self->_priv->model_searches = (GtkTreeModel *)gtk_list_store_new(5, G_TYPE_INT,G_TYPE_STRING,G_TYPE_BOOLEAN,G_TYPE_POINTER, G_TYPE_INT);
2224 gtk_combo_box_set_model(GTK_COMBO_BOX(self->_priv->cb_search), self->_priv->model_searches);
2226 GObject* search = stuffkeeper_data_item_search_new_dummy();
2227 self_search_added(self, STUFFKEEPER_DATA_ITEM_SEARCH(search), self->_priv->skdbg);
2229 node = stuffkeeper_data_backend_get_searches(self->_priv->skdbg);
2230 for(iter = node;iter;iter = g_list_next(iter))
2232 self_search_added(self, STUFFKEEPER_DATA_ITEM_SEARCH(iter->data),self->_priv->skdbg);
2234 if(node) g_list_free(node);
2235 self->_priv->signal_search_added = g_signal_connect_swapped(G_OBJECT(self->_priv->skdbg),
2237 G_CALLBACK(self_search_added),
2239 self->_priv->signal_search_removed = g_signal_connect_swapped(G_OBJECT(self->_priv->skdbg),
2241 G_CALLBACK(self_search_removed),
2243 self->_priv->signal_search_changed = g_signal_connect_swapped(G_OBJECT(self->_priv->skdbg),
2245 G_CALLBACK(self_search_changed),
2255 /* A filtered items */
2256 self->_priv->model_items_filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(self->_priv->model_items), NULL);
2257 g_signal_connect_swapped(G_OBJECT(self->_priv->model_items_filter), "row-inserted", G_CALLBACK(self_filter_model_row_inserted), self);
2258 g_signal_connect_swapped(G_OBJECT(self->_priv->model_items_filter), "row-deleted", G_CALLBACK(self_filter_model_row_deleted), self);
2260 renderer = gtk_cell_renderer_pixbuf_new();
2262 gtk_tree_view_insert_column_with_data_func(GTK_TREE_VIEW(self->_priv->treeview2), -1,"test", renderer,
2263 self_get_pixbuf, self, NULL);
2265 gtk_tree_view_column_set_sizing(
2266 GTK_TREE_VIEW_COLUMN(gtk_tree_view_get_column(GTK_TREE_VIEW(self->_priv->treeview2), 0)),
2267 GTK_TREE_VIEW_COLUMN_FIXED);
2269 gtk_tree_view_column_set_fixed_width(
2271 GTK_TREE_VIEW_COLUMN(gtk_tree_view_get_column(GTK_TREE_VIEW(self->_priv->treeview2), 0)),
2272 24+gtk_tree_view_column_get_spacing(GTK_TREE_VIEW_COLUMN(gtk_tree_view_get_column(GTK_TREE_VIEW(self->_priv->treeview2), 0))));
2274 renderer = gtk_cell_renderer_text_new();
2275 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(self->_priv->treeview2), -1, "items", renderer, "text", 1, NULL);
2276 // g_object_set(renderer, "editable", TRUE,NULL);
2277 gtk_tree_view_column_set_sizing(
2278 GTK_TREE_VIEW_COLUMN(gtk_tree_view_get_column(GTK_TREE_VIEW(self->_priv->treeview2), 1)),
2279 GTK_TREE_VIEW_COLUMN_FIXED);
2280 g_signal_connect_swapped(G_OBJECT(renderer), "edited", G_CALLBACK(self_interface_item_title_edited), self);
2282 /* Look at the tree */
2283 gtk_tree_view_set_model(GTK_TREE_VIEW(self->_priv->treeview2), GTK_TREE_MODEL(self->_priv->model_items_filter));
2285 /* get changed selection */
2286 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview2));
2287 g_signal_connect_swapped(G_OBJECT(sel), "changed", G_CALLBACK(self_interface_item_selection_changed), self);
2288 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
2291 gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(self->_priv->model_items_filter),
2292 (GtkTreeModelFilterVisibleFunc)self_interface_visible_func, self, NULL);
2297 column = gtk_tree_view_column_new();
2301 self->_priv->renderer_toggle = renderer = gtk_cell_renderer_toggle_new();
2302 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), renderer, FALSE);
2303 gtk_tree_view_column_set_attributes(column, renderer, "active", 2, NULL);
2304 /* handle toggled */
2305 g_signal_connect_swapped(G_OBJECT(renderer), "toggled", G_CALLBACK(self_interface_left_pane_toggled), self);
2308 gtk_tree_view_append_column(GTK_TREE_VIEW(self->_priv->treeview1), column);
2310 self->_priv->column_lv_pixbuf = column = gtk_tree_view_column_new();
2311 renderer = gtk_cell_renderer_pixbuf_new();
2312 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), renderer, FALSE);
2313 gtk_tree_view_column_set_visible(self->_priv->column_lv_pixbuf, FALSE);
2314 gtk_tree_view_append_column(GTK_TREE_VIEW(self->_priv->treeview1), column);
2315 gtk_tree_view_column_set_cell_data_func(column, renderer, self_interface_lv_get_schema_pixbuf, self, NULL);
2317 column = gtk_tree_view_column_new();
2319 self->_priv->treeview1_renderer = renderer = gtk_cell_renderer_text_new();
2320 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), renderer, TRUE);
2321 gtk_tree_view_column_set_attributes(column, renderer, "text", 1, NULL);
2322 g_object_set(renderer, "editable", TRUE,NULL);
2323 g_signal_connect_swapped(G_OBJECT(renderer), "edited", G_CALLBACK(self_interface_left_pane_edited), self);
2325 /* Number of items */
2326 renderer = gtk_cell_renderer_text_new();
2327 g_object_set(G_OBJECT(renderer),
2328 "background-set", TRUE, "background-gdk",&(GTK_WIDGET(self->_priv->treeview1)->style->bg[GTK_STATE_SELECTED]),
2329 "foreground-set", TRUE, "foreground-gdk",&(GTK_WIDGET(self->_priv->treeview1)->style->fg[GTK_STATE_SELECTED]),
2331 g_signal_connect(self->_priv->treeview1, "style-set", G_CALLBACK(self_style_changed), renderer);
2334 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), renderer, FALSE);
2335 gtk_tree_view_column_set_attributes(column, renderer, "text", 4, NULL);
2337 gtk_tree_view_append_column(GTK_TREE_VIEW(self->_priv->treeview1), column);
2339 g_signal_connect_swapped(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview1))),
2341 G_CALLBACK(self_treeview1_selection_changed),
2344 gtk_combo_box_set_active(GTK_COMBO_BOX(self->_priv->LeftPaneCB), 0);
2347 renderer = gtk_cell_renderer_text_new();
2348 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(self->_priv->cb_search), renderer, TRUE);
2349 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(self->_priv->cb_search), renderer, "text", 1);
2351 gtk_combo_box_set_active(GTK_COMBO_BOX(self->_priv->cb_search), 0);
2353 /** initial setup the list */
2356 self_filter_model_row_inserted(self, NULL, NULL, NULL);
2359 /* update lock state */
2360 self_backend_locked(self, NULL, self->_priv->skdbg);
2363 node = stuffkeeper_plugin_manager_get_loaded_plugins(STUFFKEEPER_PLUGIN_MANAGER(spm));
2365 GtkWidget *parent = (GtkWidget *)gtk_builder_get_object(self->_priv->xml, "menuitem_tools");
2366 GtkWidget *menu = gtk_menu_new();
2367 gtk_menu_item_set_submenu(GTK_MENU_ITEM(parent), menu);
2368 for(iter = node;iter;iter = g_list_next(iter))
2370 StuffkeeperPlugin *plugin = iter->data;
2371 if(stuffkeeper_plugin_get_plugin_type(plugin)&PLUGIN_MENU)
2373 gint width = 16, height=16;
2374 GtkWidget *item = gtk_image_menu_item_new_with_label(stuffkeeper_plugin_get_name(plugin));
2375 GdkPixbuf *pb = stuffkeeper_plugin_get_icon(plugin);
2377 gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
2381 GdkPixbuf *scale = gdk_pixbuf_scale_simple(pb,width, height, GDK_INTERP_BILINEAR);
2382 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),gtk_image_new_from_pixbuf(scale));
2383 g_object_unref(scale);
2385 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2386 g_object_set_data(G_OBJECT(item), "plugin",plugin);
2387 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(self_tool_activate), self);
2390 gtk_widget_show_all(menu);
2396 gtk_widget_show(self->_priv->win);
2400 tool_activate(self,GtkWidget *item)
2402 StuffkeeperPlugin *plugin = g_object_get_data(G_OBJECT(item), "plugin");
2405 stuffkeeper_plugin_run_menu(STUFFKEEPER_PLUGIN(plugin),self->_priv->skdbg);
2411 finalize(G:Object *obj)
2414 Self *self = SELF(obj);
2415 g_debug("** Finalize stuffkeeper interface\n");
2416 if(self->_priv->signal_backend_locked) {
2417 g_signal_handler_disconnect(G_OBJECT(self->_priv->skdbg), self->_priv->signal_backend_locked);
2418 self->_priv->signal_backend_locked = 0;
2420 if(self->_priv->signal_schema_added) {
2421 g_signal_handler_disconnect(G_OBJECT(self->_priv->skdbg), self->_priv->signal_schema_added);
2422 self->_priv->signal_schema_added = 0;
2424 if(self->_priv->signal_schema_changed) {
2425 g_signal_handler_disconnect(G_OBJECT(self->_priv->skdbg), self->_priv->signal_schema_changed);
2426 self->_priv->signal_schema_changed = 0;
2428 if(self->_priv->signal_schema_removed) {
2429 g_signal_handler_disconnect(G_OBJECT(self->_priv->skdbg), self->_priv->signal_schema_removed);
2430 self->_priv->signal_schema_removed = 0;
2433 if(self->_priv->signal_item_added) {
2434 g_signal_handler_disconnect(G_OBJECT(self->_priv->skdbg), self->_priv->signal_item_added);
2435 self->_priv->signal_item_added = 0;
2437 if(self->_priv->signal_item_changed) {
2438 g_signal_handler_disconnect(G_OBJECT(self->_priv->skdbg), self->_priv->signal_item_changed);
2439 self->_priv->signal_item_changed = 0;
2441 if(self->_priv->signal_item_removed) {
2442 g_signal_handler_disconnect(G_OBJECT(self->_priv->skdbg), self->_priv->signal_item_removed);
2443 self->_priv->signal_item_removed = 0;
2445 if(self->_priv->signal_search_added) {
2446 g_signal_handler_disconnect(G_OBJECT(self->_priv->skdbg), self->_priv->signal_search_added);
2447 self->_priv->signal_search_added = 0;
2449 if(self->_priv->signal_search_changed) {
2450 g_signal_handler_disconnect(G_OBJECT(self->_priv->skdbg), self->_priv->signal_search_changed);
2451 self->_priv->signal_search_changed = 0;
2453 if(self->_priv->signal_search_removed) {
2454 g_signal_handler_disconnect(G_OBJECT(self->_priv->skdbg), self->_priv->signal_search_removed);
2455 self->_priv->signal_search_removed = 0;
2459 if(self->_priv->signal_tag_added) {
2460 g_signal_handler_disconnect(G_OBJECT(self->_priv->skdbg), self->_priv->signal_tag_added);
2461 self->_priv->signal_tag_added = 0;
2463 if(self->_priv->signal_tag_changed) {
2464 g_signal_handler_disconnect(G_OBJECT(self->_priv->skdbg), self->_priv->signal_tag_changed);
2465 self->_priv->signal_tag_changed = 0;
2467 if(self->_priv->signal_tag_removed) {
2468 g_signal_handler_disconnect(G_OBJECT(self->_priv->skdbg), self->_priv->signal_tag_removed);
2469 self->_priv->signal_tag_removed = 0;
2471 if(self->_priv->search_timeout) {
2472 g_source_remove(self->_priv->search_timeout);
2473 self->_priv->search_timeout = 0;
2475 value = gtk_paned_get_position(GTK_PANED(self->_priv->hpaned1));
2476 g_key_file_set_integer(self->config_file, "WINDOW", "hpane", value);
2477 self_safe_vpane_position(self);
2478 gtk_window_get_size(GTK_WINDOW(self->_priv->win), &value, NULL);
2479 g_key_file_set_integer(self->config_file, "WINDOW", "width", value);
2480 gtk_window_get_size(GTK_WINDOW(self->_priv->win), NULL, &value);
2481 g_key_file_set_integer(self->config_file, "WINDOW", "height", value);
2483 gtk_window_get_position(GTK_WINDOW(self->_priv->win), &value, NULL);
2484 g_key_file_set_integer(self->config_file, "WINDOW", "x-pos", value);
2485 gtk_window_get_position(GTK_WINDOW(self->_priv->win), NULL, &value);
2486 g_key_file_set_integer(self->config_file, "WINDOW", "y-pos", value);
2488 value = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(self->_priv->show_item_pane_menu_item));
2489 g_key_file_set_integer(self->config_file, "WINDOW", "show-item-pane", value);
2492 gtk_widget_destroy(self->_priv->win);
2494 if(self->_priv->xml)
2496 g_object_unref(self->_priv->xml);
2499 if(self->_priv->model_schemas)
2501 g_object_unref(self->_priv->model_schemas);
2502 self->_priv->model_schemas = NULL;
2504 PARENT_HANDLER(obj);
2511 interface_item_open(self)
2513 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview2));
2514 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->_priv->treeview2));
2516 if(gtk_tree_selection_count_selected_rows(selection) > 0)
2518 StuffkeeperDataItem *item;
2520 list = gtk_tree_selection_get_selected_rows(selection, &model);
2521 for(node = g_list_first(list); node; node = g_list_next(node))
2523 if(gtk_tree_model_get_iter(model, &iter, (GtkTreePath*)node->data))
2525 gtk_tree_model_get(model, &iter, 2, &item, -1);
2528 self_popup_item(self, item);
2533 g_list_foreach (list,(GFunc) gtk_tree_path_free, NULL);
2541 item_row_activated(self, GtkTreePath *path, GtkTreeViewColumn *column, GtkTreeView *view)
2544 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->_priv->treeview2));
2546 g_debug("item row activated\n");
2547 if(gtk_tree_model_get_iter(model,&iter, path))
2549 StuffkeeperDataItem *item;
2550 gtk_tree_model_get(model, &iter, 2, &item, -1);
2553 self_popup_item(self, item);
2559 * Popup an item list
2560 * TODO: Check it item is destroyed, and if it is remove the window
2564 popup_item(self, Stuffkeeper:Data:Item *item)
2566 stuffkeeper_item_window_new(self->_priv->skdbg, item,self->config_file);
2573 dialog_activate_link(GtkAboutDialog *dialog, const gchar *uri, Self *self)
2579 dialog_activate_email(GtkAboutDialog *dialog, const gchar *uri, Self *self)
2588 GtkWidget *dialog = gtk_about_dialog_new();
2589 GdkPixbuf *pixbuf = NULL;
2590 /* set url handler */
2591 gtk_about_dialog_set_url_hook((GtkAboutDialogActivateLinkFunc)self_dialog_activate_link,self, NULL);
2592 gtk_about_dialog_set_email_hook((GtkAboutDialogActivateLinkFunc)self_dialog_activate_email,self, NULL);
2593 /* Set config time defines */
2594 gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(dialog), PROGRAM_NAME);
2595 if(strlen(revision)>0)
2597 gchar *str = g_strdup_printf("%s\n%s: %s", PROGRAM_VERSION, _("Revision"), revision);
2598 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog),str);
2603 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), PROGRAM_VERSION);
2605 gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), PROGRAM_WEBSITE);
2607 gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog), _("Copyright 2008-2014 Qball Cow"));
2608 gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(dialog),
2609 _("GNU General Public License"));
2612 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "stuffkeeper", 64, 0, NULL);
2613 gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog),pixbuf);
2616 gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(dialog),artists);
2617 gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(dialog),authors);
2618 gtk_about_dialog_set_translator_credits (GTK_ABOUT_DIALOG(dialog), _("translator-credits"));
2620 gtk_dialog_run(GTK_DIALOG(dialog));
2621 gtk_widget_destroy(dialog);
2629 ___builder_xml_connect_foreach(
2630 GtkBuilder *builder,
2632 const gchar *signal_name,
2633 const gchar *handler_name,
2634 GObject *connect_object,
2635 GConnectFlags flags,
2638 static GModule * allsymbols = NULL;
2640 if (!allsymbols) allsymbols = g_module_open(NULL, 0);
2642 gchar * func_name = g_strdup_printf("stuffkeeper_interface_%s", handler_name);
2645 if (!g_module_symbol(allsymbols, func_name, (gpointer)&func)){
2646 if (!g_module_symbol(allsymbols, handler_name, (gpointer)&func)) {
2647 g_warning("could not find signal handler '%s'.", func_name);
2652 g_signal_connect_data(object, signal_name, func, user_data, NULL, G_CONNECT_SWAPPED | flags);
2660 GError *error = NULL;
2661 gchar *value = NULL;
2662 GtkBuilder *xml = gtk_builder_new();
2665 gtk_builder_add_from_file(xml, PACKAGE_DATADIR"/backup-dialog.ui",&error);
2667 g_error("Failed to open ui description file: %s\n", error->message);
2668 g_error_free(error);
2672 dialog = (GtkWidget *)gtk_builder_get_object(xml,"dialog_backup");
2673 /* Restore previous location */
2674 value = g_key_file_get_string(self->config_file, "BACKUP", "directory", &error);
2677 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(gtk_builder_get_object(xml, "location_chooser")), value);
2681 g_error_free(error);
2685 value = g_key_file_get_string(self->config_file, "BACKUP", "filename", &error);
2688 gtk_entry_set_text(GTK_ENTRY(gtk_builder_get_object(xml, "entry_filename")), value);
2692 g_error_free(error);
2696 gtk_builder_connect_signals_full(xml, (GtkBuilderConnectFunc)self____builder_xml_connect_foreach, (gpointer)self);
2697 switch(gtk_dialog_run(GTK_DIALOG(dialog)))
2701 gchar *directory = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(gtk_builder_get_object(xml, "location_chooser")));
2702 GtkWidget *entry = (GtkWidget *)gtk_builder_get_object(xml, "entry_filename");
2703 const gchar *file = gtk_entry_get_text(GTK_ENTRY(entry));
2704 const gchar *source = stuffkeeper_data_backend_get_path(self->_priv->skdbg);
2705 /* Store for next time */
2706 g_key_file_set_string(self->config_file, "BACKUP", "directory", directory);
2707 g_key_file_set_string(self->config_file, "BACKUP", "filename", file);
2711 gchar *suffix = g_path_get_dirname(directory);
2712 gchar *exec = g_strdup_printf("tar -cz -C '%s' -f '%s%c%s.tar.gz' '.'",source, directory,G_DIR_SEPARATOR,file);
2713 g_spawn_command_line_async(exec, NULL);
2722 gtk_widget_destroy(dialog);
2723 g_object_unref(xml);
2728 restore_backup(self)
2730 GtkWidget *dialog = NULL;
2732 dialog = gtk_message_dialog_new_with_markup(
2733 GTK_WINDOW(self->_priv->win),
2734 GTK_DIALOG_DESTROY_WITH_PARENT,
2735 GTK_MESSAGE_WARNING,
2736 GTK_BUTTONS_OK_CANCEL,
2737 _("Restoring from a backup will destroy the current database.\nUse with care."));
2739 switch(gtk_dialog_run(GTK_DIALOG(dialog)))
2741 case GTK_RESPONSE_CANCEL:
2742 gtk_widget_destroy(dialog);
2745 gtk_widget_destroy(dialog);
2749 dialog = gtk_file_chooser_dialog_new("Open archive",
2751 GTK_FILE_CHOOSER_ACTION_OPEN,
2752 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2753 GTK_STOCK_OPEN, GTK_RESPONSE_OK,
2755 switch(gtk_dialog_run(GTK_DIALOG(dialog)))
2757 case GTK_RESPONSE_OK:
2759 const gchar *directory= stuffkeeper_data_backend_get_path(self->_priv->skdbg);
2760 gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
2763 gchar *exec = g_strdup_printf("tar -zxf '%s' -C '%s' ",filename, directory);
2764 gchar *path = g_strdup(stuffkeeper_data_backend_get_path(self->_priv->skdbg));
2765 stuffkeeper_data_backend_close_yourself(self->_priv->skdbg);
2766 g_spawn_command_line_sync(exec,NULL, NULL, NULL,NULL);
2769 stuffkeeper_data_backend_load(self->_priv->skdbg, path);
2779 gtk_widget_destroy(dialog);
2787 gchar *path = g_strdup(stuffkeeper_data_backend_get_path(self->_priv->skdbg));
2788 stuffkeeper_data_backend_close_yourself(self->_priv->skdbg);
2789 stuffkeeper_data_backend_load(self->_priv->skdbg, path);
2794 visit_homepage(self)
2796 open_url(PROGRAM_WEBSITE);
2800 visit_bugtracker(self)
2802 open_url(PROGRAM_BUGTRACKER);
2810 /* Export the whole db */
2813 export_to_html(self)
2815 stuffkeeper_export_html_new_schema(self,self->_priv->skdbg,GTK_LIST_STORE(self->_priv->model_schemas));
2818 /* export selected item */
2821 export_html_item(self)
2823 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->_priv->treeview2));
2824 GtkWidget *tree = self->_priv->treeview2;
2825 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree));
2827 if(gtk_tree_selection_count_selected_rows(selection) == 1)
2829 GList *list = gtk_tree_selection_get_selected_rows(selection, &model);
2830 if(list && gtk_tree_model_get_iter(model, &iter, (GtkTreePath *)list->data))
2832 StuffkeeperDataItem *item;
2833 gtk_tree_model_get(model, &iter, 2, &item, -1);
2836 stuffkeeper_export_html_new(self,self->_priv->skdbg,STUFFKEEPER_DATA_ITEM(item));
2842 g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
2855 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
2856 if(locked){printf("**ERROR** should not be callable\n");return;}
2857 StuffkeeperDataItemSearch *search = stuffkeeper_data_backend_new_search(self->_priv->skdbg);
2858 stuffkeeper_data_item_search_edit_search_gui(search);
2865 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
2866 if(locked){printf("**ERROR** should not be callable\n");return;}
2868 if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(self->_priv->cb_search), &iter))
2870 StuffkeeperDataItemSearch *search;
2872 gtk_tree_model_get(self->_priv->model_searches, &iter,0,&id, 3, &search, -1);
2873 if(search && id != -1)
2875 stuffkeeper_data_backend_remove_search(self->_priv->skdbg, id);
2885 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
2886 if(locked){printf("**ERROR** should not be callable\n");return;}
2888 if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(self->_priv->cb_search), &iter))
2890 StuffkeeperDataItemSearch *search;
2892 gtk_tree_model_get(self->_priv->model_searches, &iter,0,&id, 3, &search, -1);
2893 if(search && id != -1)
2895 stuffkeeper_data_item_search_edit_search_gui(search);
2906 remove_search_menu(self, GtkWidget *menu_item)
2908 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
2909 if(locked){printf("**ERROR** should not be callable\n");return;}
2910 StuffkeeperDataItemSearch *search;
2911 search = g_object_get_data(G_OBJECT(menu_item), "search");
2914 gint id = stuffkeeper_data_item_search_get_id(search);
2915 stuffkeeper_data_backend_remove_search(self->_priv->skdbg, id);
2920 edit_search_menu(self,GtkWidget *menu_item)
2922 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
2923 if(locked){printf("**ERROR** should not be callable\n");return;}
2924 StuffkeeperDataItemSearch *search;
2925 search = g_object_get_data(G_OBJECT(menu_item), "search");
2928 stuffkeeper_data_item_search_edit_search_gui(search);
2934 treeview1_selection_changed(self, GtkTreeSelection *selection)
2942 sort_item_descending(self,GtkRadioButton *style)
2944 g_key_file_set_integer(self->config_file, "WINDOW", "item-sort-order", GTK_SORT_DESCENDING);
2945 self->_priv->item_sort_order = GTK_SORT_DESCENDING;
2946 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(self->_priv->model_items),
2947 self->_priv->item_sort_column,
2948 self->_priv->item_sort_order);
2953 sort_item_ascending(self,GtkRadioButton *style)
2955 g_key_file_set_integer(self->config_file, "WINDOW", "item-sort-order", GTK_SORT_ASCENDING);
2956 self->_priv->item_sort_order = GTK_SORT_ASCENDING;
2957 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(self->_priv->model_items),
2958 self->_priv->item_sort_column,
2959 self->_priv->item_sort_order);
2963 sort_item_by_modification_time(self,GtkRadioButton *style)
2965 g_key_file_set_integer(self->config_file, "WINDOW", "item-sort-column", 5);
2966 self->_priv->item_sort_column = 5;
2967 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(self->_priv->model_items),
2968 self->_priv->item_sort_column,
2969 self->_priv->item_sort_order);
2974 sort_item_by_creation_time(self,GtkRadioButton *style)
2976 g_key_file_set_integer(self->config_file, "WINDOW", "item-sort-column", 3);
2977 self->_priv->item_sort_column = 3;
2978 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(self->_priv->model_items),
2979 self->_priv->item_sort_column,
2980 self->_priv->item_sort_order);
2984 sort_item_by_title(self,GtkRadioButton *style)
2986 g_key_file_set_integer(self->config_file, "WINDOW", "item-sort-column", 1);
2987 self->_priv->item_sort_column = 1;
2988 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(self->_priv->model_items),
2989 self->_priv->item_sort_column,
2990 self->_priv->item_sort_order);
2994 sort_item_by_schema(self,GtkRadioButton *style)
2996 g_key_file_set_integer(self->config_file, "WINDOW", "item-sort-column", 4);
2997 self->_priv->item_sort_column = 4;
2998 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(self->_priv->model_items),
2999 self->_priv->item_sort_column,
3000 self->_priv->item_sort_order);
3002 /* storing saving schemas */
3005 schema_style_set(GtkWidget *event, GtkStyle *style, GtkBuilder *xml)
3007 GtkWidget *dialog = (GtkWidget *)gtk_builder_get_object(xml,"export_schema_dialog");
3008 GtkWidget *event = (GtkWidget *)gtk_builder_get_object(xml, "eventbox_schema");
3009 GtkWidget *label = (GtkWidget *)gtk_builder_get_object(xml, "label_title_schema");
3010 gtk_widget_modify_bg(event,
3012 &((dialog)->style->bg[GTK_STATE_SELECTED]));
3013 gtk_widget_modify_text(label,
3015 &((dialog)->style->text[GTK_STATE_SELECTED]));
3016 gtk_widget_modify_fg(label,
3018 &((dialog)->style->fg[GTK_STATE_SELECTED]));
3027 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
3028 if(locked){printf("**ERROR** should not be callable\n");return;}
3030 StuffkeeperDataSchema *schema = stuffkeeper_data_backend_new_schema(self->_priv->skdbg);
3031 StuffkeeperEditSchema *skes = stuffkeeper_edit_schema_new();
3032 stuffkeeper_edit_schema_set_schema(skes, schema);
3039 gboolean locked = stuffkeeper_data_backend_get_locked(self->_priv->skdbg);
3040 if(locked){printf("**ERROR** should not be callable\n");return;}
3042 GtkFileFilter *filter = NULL;
3043 GtkWidget *dialog = gtk_file_chooser_dialog_new(_("Import type"),
3045 GTK_FILE_CHOOSER_ACTION_OPEN,
3046 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
3047 GTK_STOCK_OPEN, GTK_RESPONSE_OK,
3049 filter = gtk_file_filter_new();
3050 gtk_file_filter_set_name(filter, _("Types files"));
3051 gtk_file_filter_add_pattern(filter, "*.type");
3052 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
3055 switch(gtk_dialog_run(GTK_DIALOG(dialog)))
3057 case GTK_RESPONSE_OK:
3059 gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
3060 stuffkeeper_data_backend_load_from_xml(self->_priv->skdbg,filename);
3066 gtk_widget_destroy(dialog);
3071 entry_changed(GtkWidget *entry, GtkWidget *button)
3073 const gchar *text = gtk_entry_get_text(GTK_ENTRY(entry));
3074 if(text[0] == '\0') {
3075 gtk_widget_set_sensitive(button, FALSE);
3077 gtk_widget_set_sensitive(button, TRUE);
3085 GtkCellRenderer *renderer;
3086 GtkWidget *entry, *cb_schema;
3087 GtkBuilder *xml = gtk_builder_new();
3089 GError *error= NULL;
3090 gtk_builder_add_from_file(xml, PACKAGE_DATADIR"/export-schema-dialog.ui",&error);
3092 g_error("Failed to open ui file: %s\n", error->message);
3093 g_error_free(error);
3094 g_object_unref(xml);
3098 dialog = (GtkWidget *)gtk_builder_get_object(xml,"export_schema_dialog");
3100 g_signal_connect(G_OBJECT(dialog), "style-set", G_CALLBACK(self_schema_style_set),xml);
3103 entry = (GtkWidget *)gtk_builder_get_object(xml, "entry_name");
3104 g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(self_entry_changed),
3105 (GtkWidget *)gtk_builder_get_object(xml, "save_button1"));
3106 cb_schema = (GtkWidget *)gtk_builder_get_object(xml, "cb_schema");
3108 gtk_combo_box_set_model(GTK_COMBO_BOX(cb_schema), GTK_TREE_MODEL(self->_priv->model_schemas));
3109 gtk_combo_box_set_active(GTK_COMBO_BOX(cb_schema), 0);
3110 renderer = gtk_cell_renderer_text_new();
3111 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(cb_schema),renderer, TRUE);
3112 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(cb_schema),renderer, "text",1 );
3115 gtk_builder_connect_signals_full(xml, (GtkBuilderConnectFunc)self____builder_xml_connect_foreach, (gpointer)self);
3116 switch(gtk_dialog_run(GTK_DIALOG(dialog)))
3121 gchar *directory = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(gtk_builder_get_object(xml, "fc_directory")));
3122 const gchar *file = gtk_entry_get_text(GTK_ENTRY(entry));
3123 if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(cb_schema),&iter))
3126 gchar *filename = g_strdup_printf("%s.type", file);
3127 StuffkeeperDataSchema *schema = NULL;
3128 /* get model schema */
3129 gtk_tree_model_get(self->_priv->model_schemas, &iter,3, &schema, -1);
3131 path = g_build_path(G_DIR_SEPARATOR_S, directory, filename,NULL);
3133 stuffkeeper_data_schema_save_to_xml(schema,path);
3142 gtk_widget_destroy(dialog);
3143 g_object_unref(xml);
3155 GError *error = NULL;
3156 gchar *path = g_build_path(G_DIR_SEPARATOR_S,PACKAGE_DATADIR, "types",NULL);
3157 /* open the directory */
3158 dir = g_dir_open(path, 0, &error);
3161 printf("Error opening: '%s': '%s'\n", path, error->message);
3162 g_error_free(error);
3166 const char *filename = NULL;
3167 while((filename = g_dir_read_name(dir)))
3169 gchar *full_path = g_build_path(G_DIR_SEPARATOR_S,PACKAGE_DATADIR, "types",filename,NULL);
3170 stuffkeeper_data_backend_load_from_xml(self->_priv->skdbg, full_path);
3181 gtk_window_present(GTK_WINDOW(self->_priv->win));
3187 safe_vpane_position(self)
3190 if(GTK_IS_HPANED(self->_priv->vpaned1))
3192 value = gtk_paned_get_position(GTK_PANED(self->_priv->vpaned1));
3193 g_key_file_set_integer(self->config_file, "WINDOW", "vpane-alternative", value);
3194 printf("store position alternative: %i\n", value);
3198 value = gtk_paned_get_position(GTK_PANED(self->_priv->vpaned1));
3199 g_key_file_set_integer(self->config_file, "WINDOW", "vpane", value);
3201 printf("store position : %i\n", value);
3206 set_alternative_layout(self, int active)
3208 GError *error = NULL;
3210 if(active && GTK_IS_VPANED(self->_priv->vpaned1))
3212 GtkWidget *p1 = g_object_ref(gtk_paned_get_child1(GTK_PANED(self->_priv->vpaned1)));
3213 GtkWidget *p2 = g_object_ref(gtk_paned_get_child2(GTK_PANED(self->_priv->vpaned1)));
3214 gtk_container_remove(GTK_CONTAINER(self->_priv->vpaned1), p1);
3215 gtk_container_remove(GTK_CONTAINER(self->_priv->vpaned1), p2);
3216 gtk_widget_destroy(self->_priv->vpaned1);
3217 self->_priv->vpaned1 = gtk_hpaned_new();
3218 gtk_paned_add2(GTK_PANED(self->_priv->hpaned1), self->_priv->vpaned1);
3219 gtk_paned_pack1(GTK_PANED(self->_priv->vpaned1), p1,TRUE, FALSE);
3220 gtk_paned_pack2(GTK_PANED(self->_priv->vpaned1), p2,TRUE, FALSE);
3223 gtk_widget_show(self->_priv->vpaned1);
3225 g_key_file_set_integer(self->config_file, "WINDOW", "alternative-layout", 1);
3227 }else if(!active && GTK_IS_HPANED(self->_priv->vpaned1)){
3229 GtkWidget *p1 = g_object_ref(gtk_paned_get_child1(GTK_PANED(self->_priv->vpaned1)));
3230 GtkWidget *p2 = g_object_ref(gtk_paned_get_child2(GTK_PANED(self->_priv->vpaned1)));
3231 gtk_container_remove(GTK_CONTAINER(self->_priv->vpaned1), p1);
3232 gtk_container_remove(GTK_CONTAINER(self->_priv->vpaned1), p2);
3233 gtk_widget_destroy(self->_priv->vpaned1);
3234 self->_priv->vpaned1 = gtk_vpaned_new();
3235 gtk_paned_add2(GTK_PANED(self->_priv->hpaned1), self->_priv->vpaned1);
3236 gtk_paned_pack1(GTK_PANED(self->_priv->vpaned1), p1,TRUE, FALSE);
3237 gtk_paned_pack2(GTK_PANED(self->_priv->vpaned1), p2,TRUE, FALSE);
3241 gtk_widget_show(self->_priv->vpaned1);
3243 g_key_file_set_integer(self->config_file, "WINDOW", "alternative-layout", 0);
3246 if(GTK_IS_HPANED(self->_priv->vpaned1)){
3247 value = g_key_file_get_integer(self->config_file, "WINDOW", "vpane-alternative", &error);
3249 g_debug("restore position alternative: %i\n", value);
3251 value = g_key_file_get_integer(self->config_file, "WINDOW", "vpane", &error);
3253 g_debug("restore position : %i\n", value);
3255 /* Restore pane position */
3257 g_debug("No valid vpane position: %s\n", error->message);
3259 g_error_free(error);
3264 g_debug("Setting position: %i\n", value);
3265 gtk_paned_set_position(GTK_PANED(self->_priv->vpaned1), value);
3271 on_alternative_layout_cb_activate(self, GtkCheckMenuItem *activate)
3273 int active = gtk_check_menu_item_get_active(activate);
3275 self_safe_vpane_position(self);
3276 self_set_alternative_layout(self, active);
3281 signal last NONE (NONE)