Merge lp:~aauzi/midori/fix-894143 into lp:midori

Proposed by André Auzi
Status: Work in progress
Proposed branch: lp:~aauzi/midori/fix-894143
Merge into: lp:midori
Diff against target: 3396 lines (+2255/-309)
10 files modified
katze/katze-array.c (+53/-2)
katze/katze-arrayaction.c (+10/-0)
katze/katze-utils.c (+90/-3)
katze/katze-utils.h (+5/-0)
midori/midori-array.c (+7/-0)
midori/midori-bookmarks-db.c (+107/-15)
midori/midori-bookmarks-db.h (+11/-9)
midori/midori-browser.c (+11/-19)
panels/midori-bookmarks.c (+1960/-260)
tests/bookmarks.c (+1/-1)
To merge this branch: bzr merge lp:~aauzi/midori/fix-894143
Reviewer Review Type Date Requested Status
Midori Devs Pending
Review via email: mp+165249@code.launchpad.net

Description of the change

(For review: fix-1179200 is a prerequisite to fix-894143)

To post a comment you must log in.
Revision history for this message
André Auzi (aauzi) wrote :

Updated with merge in of lp:~aauzi/midori/fix-1179200-9 and lp:midori.

Bookmark item positions are now properly managed in both menus and panel.

Multiple bookmark selection and drag-n-drop in the bookmark panel allow bookmark ordering.

lp:~aauzi/midori/fix-894143 updated
6340. By André Auzi

merge lp:midori after merge of fix-1179200-8

Unmerged revisions

6340. By André Auzi

merge lp:midori after merge of fix-1179200-8

6339. By André Auzi

Fix race condition in timestamp comparison

6338. By André Auzi

merge lp:midori

6337. By André Auzi

Fix Test #9 regression error

6336. By André Auzi

merge lp:~aauzi/midori/fix-1179200-9

6335. By André Auzi

merge fix-xbel-import-regression

6334. By André Auzi

merge lp:midori

6333. By André Auzi

manage sort order in bookmarks test

6332. By André Auzi

merge lp:midori after insert of fix-1179200-4

6331. By André Auzi

Derivation of GtkTreeStore for DND drop destination control.

Inserts are delayed to handle move operations where move is actually an insert at destination, followed by a delete at the source and finally a row change callback.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'katze/katze-array.c'
--- katze/katze-array.c 2013-11-04 20:57:37 +0000
+++ katze/katze-array.c 2014-01-30 21:24:26 +0000
@@ -33,6 +33,15 @@
33 GList* items;33 GList* items;
34};34};
3535
36enum
37{
38 PROP_0,
39
40 PROP_TYPE,
41
42 N_PROPERTIES
43};
44
36enum {45enum {
37 ADD_ITEM,46 ADD_ITEM,
38 REMOVE_ITEM,47 REMOVE_ITEM,
@@ -55,6 +64,17 @@
55{64{
56 g_object_set_data (G_OBJECT (array), "last-update",65 g_object_set_data (G_OBJECT (array), "last-update",
57 GINT_TO_POINTER (time (NULL)));66 GINT_TO_POINTER (time (NULL)));
67/* #define DEBUG_UPDATE */
68#ifdef DEBUG_UPDATE
69 if (KATZE_IS_ITEM (array))
70 {
71 const gchar *name = katze_item_get_name (KATZE_ITEM (array));
72 if (name && *name)
73 {
74 g_print ("_katze_array_update: %s\n", name);
75 }
76 }
77#endif
58}78}
5979
60static void80static void
@@ -105,6 +125,27 @@
105}125}
106126
107static void127static void
128_katze_array_set_property (GObject *object,
129 guint property_id,
130 const GValue *value,
131 GParamSpec *pspec)
132{
133 KatzeArray *array = KATZE_ARRAY (object);
134
135 switch (property_id)
136 {
137 case PROP_TYPE:
138 array->priv->type = g_value_get_gtype (value);
139 break;
140
141 default:
142 /* We don't have any other property... */
143 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
144 break;
145 }
146}
147
148static void
108katze_array_class_init (KatzeArrayClass* class)149katze_array_class_init (KatzeArrayClass* class)
109{150{
110 GObjectClass* gobject_class;151 GObjectClass* gobject_class;
@@ -187,6 +228,7 @@
187228
188 gobject_class = G_OBJECT_CLASS (class);229 gobject_class = G_OBJECT_CLASS (class);
189 gobject_class->finalize = katze_array_finalize;230 gobject_class->finalize = katze_array_finalize;
231 gobject_class->set_property = _katze_array_set_property;
190232
191 class->add_item = _katze_array_add_item;233 class->add_item = _katze_array_add_item;
192 class->remove_item = _katze_array_remove_item;234 class->remove_item = _katze_array_remove_item;
@@ -194,6 +236,16 @@
194 class->clear = _katze_array_clear;236 class->clear = _katze_array_clear;
195 class->update = _katze_array_update;237 class->update = _katze_array_update;
196238
239
240 g_object_class_install_property (gobject_class,
241 PROP_TYPE,
242 g_param_spec_gtype (
243 "type",
244 "Type",
245 "The array item type",
246 G_TYPE_NONE,
247 G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
248
197 g_type_class_add_private (class, sizeof (KatzeArrayPrivate));249 g_type_class_add_private (class, sizeof (KatzeArrayPrivate));
198}250}
199251
@@ -238,8 +290,7 @@
238290
239 g_return_val_if_fail (g_type_is_a (type, G_TYPE_OBJECT), NULL);291 g_return_val_if_fail (g_type_is_a (type, G_TYPE_OBJECT), NULL);
240292
241 array = g_object_new (KATZE_TYPE_ARRAY, NULL);293 array = g_object_new (KATZE_TYPE_ARRAY, "type", type, NULL);
242 array->priv->type = type;
243294
244 return array;295 return array;
245}296}
246297
=== modified file 'katze/katze-arrayaction.c'
--- katze/katze-arrayaction.c 2012-12-16 18:40:00 +0000
+++ katze/katze-arrayaction.c 2014-01-30 21:24:26 +0000
@@ -767,12 +767,14 @@
767 KatzeArray* array)767 KatzeArray* array)
768{768{
769 GSList* proxies;769 GSList* proxies;
770 KatzeArray *old_array = NULL;
770771
771 g_return_if_fail (KATZE_IS_ARRAY_ACTION (array_action));772 g_return_if_fail (KATZE_IS_ARRAY_ACTION (array_action));
772 g_return_if_fail (!array || katze_array_is_a (array, KATZE_TYPE_ITEM));773 g_return_if_fail (!array || katze_array_is_a (array, KATZE_TYPE_ITEM));
773774
774 /* FIXME: Disconnect old array */775 /* FIXME: Disconnect old array */
775776
777 old_array = array_action->array;
776 if (array)778 if (array)
777 g_object_ref (array);779 g_object_ref (array);
778 katze_object_assign (array_action->array, array);780 katze_object_assign (array_action->array, array);
@@ -793,7 +795,15 @@
793795
794 do796 do
795 {797 {
798 KatzeArray* item = g_object_get_data (G_OBJECT (proxies->data), "KatzeItem");
799
800 if (item && (item == old_array))
801 g_object_set_data (G_OBJECT (proxies->data), "KatzeItem", array);
802
796 gtk_widget_set_sensitive (proxies->data, array != NULL);803 gtk_widget_set_sensitive (proxies->data, array != NULL);
797 }804 }
798 while ((proxies = g_slist_next (proxies)));805 while ((proxies = g_slist_next (proxies)));
806
807 if (array)
808 katze_array_update (KATZE_ARRAY (array));
799}809}
800810
=== modified file 'katze/katze-utils.c'
--- katze/katze-utils.c 2013-11-05 21:51:18 +0000
+++ katze/katze-utils.c 2014-01-30 21:24:26 +0000
@@ -1002,12 +1002,99 @@
10021002
1003 g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE);1003 g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE);
10041004
1005 if ((selection = gtk_tree_view_get_selection (treeview)))1005 selection = gtk_tree_view_get_selection(treeview);
1006 if (gtk_tree_selection_get_selected (selection, model, iter))1006
1007 return TRUE;1007 switch (gtk_tree_selection_get_mode (selection))
1008 {
1009 default:
1010 break;
1011
1012 case GTK_SELECTION_SINGLE:
1013 case GTK_SELECTION_BROWSE:
1014 if (gtk_tree_selection_get_selected (selection, model, iter))
1015 return TRUE;
1016 break;
1017
1018 case GTK_SELECTION_MULTIPLE:
1019 if (gtk_tree_selection_count_selected_rows (selection) == 1)
1020 {
1021 GtkTreeModel *stock_model;
1022 GList *list = gtk_tree_selection_get_selected_rows (selection, &stock_model);
1023
1024 if (model)
1025 *model = stock_model;
1026
1027 if (list)
1028 {
1029 GtkTreePath *path = (GtkTreePath *)g_list_nth_data (list, 0);
1030
1031 if (path && (!iter || gtk_tree_model_get_iter (stock_model, iter, path)))
1032 {
1033 g_list_free_full(list, (GDestroyNotify) gtk_tree_path_free);
1034 return TRUE;
1035 }
1036
1037 g_list_free_full(list, (GDestroyNotify) gtk_tree_path_free);
1038 }
1039 }
1040 }
1041
1008 return FALSE;1042 return FALSE;
1009}1043}
10101044
1045/**
1046 * katze_tree_view_get_selected_rows:
1047 * @treeview: a #GtkTreeView
1048 * @model: a pointer to store the #GtkTreeModel, or %NULL
1049 * @rows: a pointer to store the #GList of #GtkTreePath, or %NULL
1050 *
1051 * Determines whether there is a selection in @treeview
1052 * and sets the @rows to the current selection.
1053 *
1054 * If there is a selection and @model is not %NULL, it is
1055 * set to the model. If @model is %NULL, the @rows will be
1056 * set to %NULL.
1057 *
1058 * Either @model or @rows or both can be %NULL in which case
1059 * no value will be assigned in any case.
1060 *
1061 * When @rows is not %NULL it must be freed using:
1062 * g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
1063 *
1064 * Return value: the count of selected rows
1065 *
1066 * Since: 0.4.7.aau.1
1067 **/
1068
1069gint
1070katze_tree_view_get_selected_rows (GtkTreeView* treeview,
1071 GtkTreeModel** model,
1072 GList** rows)
1073{
1074 gint count;
1075 GtkTreeSelection* selection;
1076
1077 if (model)
1078 *model = NULL;
1079 if (rows)
1080 *rows = NULL;
1081
1082 g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), 0);
1083
1084 selection = gtk_tree_view_get_selection(treeview);
1085
1086 count = gtk_tree_selection_count_selected_rows (selection);
1087 if (count > 0)
1088 {
1089 if (model && rows)
1090 {
1091 *rows = gtk_tree_selection_get_selected_rows (selection, model);
1092 }
1093 }
1094
1095 return count;
1096}
1097
1011void1098void
1012katze_bookmark_populate_tree_view (KatzeArray* array,1099katze_bookmark_populate_tree_view (KatzeArray* array,
1013 GtkTreeStore* model,1100 GtkTreeStore* model,
10141101
=== modified file 'katze/katze-utils.h'
--- katze/katze-utils.h 2013-04-16 22:10:56 +0000
+++ katze/katze-utils.h 2014-01-30 21:24:26 +0000
@@ -88,6 +88,11 @@
88 GtkTreeModel** model,88 GtkTreeModel** model,
89 GtkTreeIter* iter);89 GtkTreeIter* iter);
9090
91gint
92katze_tree_view_get_selected_rows (GtkTreeView* treeview,
93 GtkTreeModel** model,
94 GList** rows);
95
91void96void
92katze_bookmark_populate_tree_view (KatzeArray* array,97katze_bookmark_populate_tree_view (KatzeArray* array,
93 GtkTreeStore* model,98 GtkTreeStore* model,
9499
=== modified file 'midori/midori-array.c'
--- midori/midori-array.c 2013-08-05 19:52:52 +0000
+++ midori/midori-array.c 2014-01-30 21:24:26 +0000
@@ -1031,9 +1031,16 @@
1031 || g_str_equal (name, "last_visit") || g_str_equal (name, "visit_count")1031 || g_str_equal (name, "last_visit") || g_str_equal (name, "visit_count")
1032 || g_str_equal (name, "pos_panel") || g_str_equal (name, "pos_bar"))1032 || g_str_equal (name, "pos_panel") || g_str_equal (name, "pos_bar"))
1033 {1033 {
1034#if 0
1034 gint value;1035 gint value;
1035 value = sqlite3_column_int64 (stmt, column);1036 value = sqlite3_column_int64 (stmt, column);
1036 katze_item_set_meta_integer (item, name, value);1037 katze_item_set_meta_integer (item, name, value);
1038#else
1039 /* use text to properly handle NULL values */
1040 const unsigned char* text;
1041 text = sqlite3_column_text (stmt, column);
1042 katze_item_set_meta_string (item, name, (gchar*)text);
1043#endif
1037 }1044 }
1038 else if (g_str_equal (name, "desc"))1045 else if (g_str_equal (name, "desc"))
1039 {1046 {
10401047
=== modified file 'midori/midori-bookmarks-db.c'
--- midori/midori-bookmarks-db.c 2014-01-24 23:04:05 +0000
+++ midori/midori-bookmarks-db.c 2014-01-30 21:24:26 +0000
@@ -181,14 +181,29 @@
181midori_bookmarks_db_get_item_parent (MidoriBookmarksDb* bookmarks,181midori_bookmarks_db_get_item_parent (MidoriBookmarksDb* bookmarks,
182 gpointer item)182 gpointer item)
183{183{
184 gint64 parentid = katze_item_get_meta_integer (KATZE_ITEM (item), "parentid");
185 KatzeItem *search = katze_item_new ();
184 KatzeArray* parent;186 KatzeArray* parent;
185 gint64 parentid;187
186188 if (!parentid)
187 parentid = katze_item_get_meta_integer (KATZE_ITEM (item), "parentid");189 {
188190 parentid = katze_item_get_meta_integer (KATZE_ITEM (bookmarks), "id");
189 if (parentid == 0)191 katze_item_set_meta_integer (KATZE_ITEM (item), "parentid", parentid);
190 {192 }
193
194 katze_item_set_meta_integer(search, "id", parentid);
195
196 parent = KATZE_ARRAY (g_hash_table_lookup (bookmarks->all_items, search));
197
198 g_object_unref (search);
199
200 if (!parent)
201 {
202 g_warning ("item parent not found\n");
203
191 parent = KATZE_ARRAY (bookmarks);204 parent = KATZE_ARRAY (bookmarks);
205 katze_item_set_meta_integer (KATZE_ITEM (item), "parentid",
206 katze_item_get_meta_integer (KATZE_ITEM (bookmarks), "id"));
192 }207 }
193 else208 else
194 {209 {
@@ -267,7 +282,10 @@
267282
268 g_return_if_fail (parent);283 g_return_if_fail (parent);
269284
270 katze_array_update (parent);285 if (IS_MIDORI_BOOKMARKS_DB (parent))
286 KATZE_ARRAY_CLASS (midori_bookmarks_db_parent_class)->update (parent);
287 else
288 katze_array_update (parent);
271}289}
272290
273/**291/**
@@ -479,7 +497,7 @@
479 else if (old_parent && katze_item_get_meta_integer (old_parent, "id") > 0)497 else if (old_parent && katze_item_get_meta_integer (old_parent, "id") > 0)
480 new_parentid = g_strdup_printf ("%" G_GINT64_FORMAT, katze_item_get_meta_integer (old_parent, "id"));498 new_parentid = g_strdup_printf ("%" G_GINT64_FORMAT, katze_item_get_meta_integer (old_parent, "id"));
481 else499 else
482 new_parentid = g_strdup_printf ("NULL");500 new_parentid = g_strdup ("NULL");
483501
484 sqlcmd = sqlite3_mprintf (502 sqlcmd = sqlite3_mprintf (
485 "INSERT INTO bookmarks (id, parentid, title, uri, desc, toolbar, app) "503 "INSERT INTO bookmarks (id, parentid, title, uri, desc, toolbar, app) "
@@ -557,7 +575,8 @@
557575
558 sqlcmd = sqlite3_mprintf (576 sqlcmd = sqlite3_mprintf (
559 "UPDATE bookmarks SET "577 "UPDATE bookmarks SET "
560 "parentid=%q, title='%q', uri='%q', desc='%q', toolbar=%d, app=%d "578 "parentid=%q, title='%q', uri='%q', desc='%q', toolbar=%d, app=%d, "
579 "pos_bar=%d, pos_panel=%d "
561 "WHERE id = %q ;",580 "WHERE id = %q ;",
562 parentid,581 parentid,
563 katze_item_get_name (item),582 katze_item_get_name (item),
@@ -565,6 +584,8 @@
565 katze_str_non_null (katze_item_get_meta_string (item, "desc")),584 katze_str_non_null (katze_item_get_meta_string (item, "desc")),
566 katze_item_get_meta_boolean (item, "toolbar"),585 katze_item_get_meta_boolean (item, "toolbar"),
567 katze_item_get_meta_boolean (item, "app"),586 katze_item_get_meta_boolean (item, "app"),
587 (gint)katze_item_get_meta_integer (item, "pos_bar"),
588 (gint)katze_item_get_meta_integer (item, "pos_panel"),
568 id);589 id);
569590
570 updated = TRUE;591 updated = TRUE;
@@ -579,6 +600,14 @@
579 g_free (parentid);600 g_free (parentid);
580 g_free (id);601 g_free (id);
581602
603#ifdef DEBUG_DB_UPDATE
604 g_print ("update:%s - parentid: %s, pos_bar:%d, pos_panel:%d\n",
605 katze_item_get_name (item),
606 parentid,
607 (gint)katze_item_get_meta_integer (item, "pos_bar"),
608 (gint)katze_item_get_meta_integer (item, "pos_panel"));
609#endif
610
582 return updated;611 return updated;
583}612}
584613
@@ -710,10 +739,10 @@
710 g_return_val_if_fail (errmsg != NULL, NULL);739 g_return_val_if_fail (errmsg != NULL, NULL);
711740
712 database = midori_bookmarks_database_new (&error);741 database = midori_bookmarks_database_new (&error);
713 742
714 if (error != NULL)743 if (error != NULL)
715 {744 {
716 *errmsg = g_strdup (error->message);745 *errmsg = g_strdup (error->message);
717 g_error_free (error);746 g_error_free (error);
718 return NULL;747 return NULL;
719 }748 }
@@ -724,7 +753,10 @@
724 if (midori_debug ("bookmarks"))753 if (midori_debug ("bookmarks"))
725 sqlite3_trace (db, midori_bookmarks_db_dbtracer, NULL);754 sqlite3_trace (db, midori_bookmarks_db_dbtracer, NULL);
726755
727 bookmarks = MIDORI_BOOKMARKS_DB (g_object_new (TYPE_MIDORI_BOOKMARKS_DB, NULL));756 bookmarks = MIDORI_BOOKMARKS_DB (g_object_new (TYPE_MIDORI_BOOKMARKS_DB,
757 "type", KATZE_TYPE_ITEM,
758 NULL));
759
728 bookmarks->db = db;760 bookmarks->db = db;
729761
730 g_object_set_data (G_OBJECT (bookmarks), "db", db);762 g_object_set_data (G_OBJECT (bookmarks), "db", db);
@@ -776,6 +808,7 @@
776 katze_item_set_meta_integer (item, "parentid", parentid);808 katze_item_set_meta_integer (item, "parentid", parentid);
777 midori_bookmarks_db_add_item (bookmarks, item);809 midori_bookmarks_db_add_item (bookmarks, item);
778 }810 }
811
779 g_list_free (list);812 g_list_free (list);
780}813}
781814
@@ -859,7 +892,7 @@
859 * @array: the main bookmark array892 * @array: the main bookmark array
860 * @sqlcmd: the sqlcmd to execute893 * @sqlcmd: the sqlcmd to execute
861 *894 *
862 * Internal function that process the requested @sqlcmd.895 * Internal function that processes the requested @sqlcmd.
863 *896 *
864 * Return value: a #KatzeArray on success, %NULL otherwise897 * Return value: a #KatzeArray on success, %NULL otherwise
865 **/898 **/
@@ -885,6 +918,12 @@
885 * @fields: comma separated list of fields918 * @fields: comma separated list of fields
886 * @condition: condition, like "folder = '%q'"919 * @condition: condition, like "folder = '%q'"
887 * @value: a value to be inserted if @condition contains %q920 * @value: a value to be inserted if @condition contains %q
921 * @order: a value to be inserted in "ORDER BY"
922 * default order is :
923 * (uri='') ASC, title DESC
924 * @order is inserted before title.
925 * order then becomes :
926 * (uri='') ASC, @order title DESC
888 * @recursive: if %TRUE include children927 * @recursive: if %TRUE include children
889 *928 *
890 * Stores the result in a #KatzeArray.929 * Stores the result in a #KatzeArray.
@@ -898,6 +937,7 @@
898 const gchar* fields,937 const gchar* fields,
899 const gchar* condition,938 const gchar* condition,
900 const gchar* value,939 const gchar* value,
940 const gchar* order,
901 gboolean recursive)941 gboolean recursive)
902{942{
903 gchar* sqlcmd;943 gchar* sqlcmd;
@@ -911,7 +951,7 @@
911 g_return_val_if_fail (condition, NULL);951 g_return_val_if_fail (condition, NULL);
912952
913 sqlcmd = g_strdup_printf ("SELECT %s FROM bookmarks WHERE %s "953 sqlcmd = g_strdup_printf ("SELECT %s FROM bookmarks WHERE %s "
914 "ORDER BY (uri='') ASC, title DESC", fields, condition);954 "ORDER BY (uri='') ASC, %s title DESC", fields, condition, order ? order : "");
915 if (strstr (condition, "%q"))955 if (strstr (condition, "%q"))
916 {956 {
917 sqlcmd_value = sqlite3_mprintf (sqlcmd, value ? value : "");957 sqlcmd_value = sqlite3_mprintf (sqlcmd, value ? value : "");
@@ -932,7 +972,7 @@
932 gchar* parentid = g_strdup_printf ("%" G_GINT64_FORMAT,972 gchar* parentid = g_strdup_printf ("%" G_GINT64_FORMAT,
933 katze_item_get_meta_integer (item, "id"));973 katze_item_get_meta_integer (item, "id"));
934 KatzeArray* subarray = midori_bookmarks_db_query_recursive (bookmarks,974 KatzeArray* subarray = midori_bookmarks_db_query_recursive (bookmarks,
935 fields, "parentid=%q", parentid, TRUE);975 fields, "parentid=%q", parentid, order, TRUE);
936 KatzeItem* subitem;976 KatzeItem* subitem;
937 GList* sublist;977 GList* sublist;
938978
@@ -1097,3 +1137,55 @@
1097 value, id,1137 value, id,
1098 recursive);1138 recursive);
1099}1139}
1140
1141/**
1142 * midori_bookmarks_db_populate_folder:
1143 **/
1144
1145void
1146midori_bookmarks_db_populate_folder (MidoriBookmarksDb* bookmarks,
1147 KatzeArray *folder)
1148{
1149 const gchar* id = katze_item_get_meta_string (KATZE_ITEM (folder), "id");
1150 const gchar *condition;
1151 KatzeArray* array;
1152 KatzeItem* item;
1153 GList* list;
1154
1155 if (id == NULL)
1156 {
1157 condition = "parentid is NULL";
1158 }
1159 else
1160 {
1161 condition = "parentid = %q";
1162 }
1163
1164 array = midori_bookmarks_db_query_recursive (bookmarks,
1165 "id, title, parentid, uri, app, pos_panel, pos_bar", condition, id, "pos_panel ASC,", FALSE);
1166
1167 if (IS_MIDORI_BOOKMARKS_DB (folder))
1168 {
1169 KATZE_ARRAY_FOREACH_ITEM_L (item, folder, list)
1170 {
1171 KATZE_ARRAY_CLASS (midori_bookmarks_db_parent_class)->remove_item (folder, item);
1172 }
1173
1174 KATZE_ARRAY_FOREACH_ITEM_L (item, array, list)
1175 {
1176 KATZE_ARRAY_CLASS (midori_bookmarks_db_parent_class)->add_item (folder, item);
1177 }
1178 }
1179 else
1180 {
1181 katze_array_clear(folder);
1182
1183 KATZE_ARRAY_FOREACH_ITEM_L (item, array, list)
1184 {
1185 katze_array_add_item (folder, item);
1186 }
1187 }
1188
1189 g_object_unref (array);
1190}
1191
11001192
=== modified file 'midori/midori-bookmarks-db.h'
--- midori/midori-bookmarks-db.h 2013-09-17 19:34:23 +0000
+++ midori/midori-bookmarks-db.h 2014-01-30 21:24:26 +0000
@@ -62,19 +62,21 @@
62 const gchar* fields,62 const gchar* fields,
63 const gchar* condition,63 const gchar* condition,
64 const gchar* value,64 const gchar* value,
65 const gchar* order,
65 gboolean recursive);66 gboolean recursive);
6667
67gint6468gint64
68midori_bookmarks_db_count_recursive (MidoriBookmarksDb* bookmarks,69midori_bookmarks_db_count_recursive (MidoriBookmarksDb* bookmarks,
69 const gchar* condition,70 const gchar* condition,
70 const gchar* value,71 const gchar* value,
71 KatzeItem* folder,72 KatzeItem* folder,
72 gboolean recursive);73 gboolean recursive);
7374
74gint6475void
75midori_bookmarks_insert_item_db (sqlite3* db,76midori_bookmarks_db_on_quit (MidoriBookmarksDb* array);
76 KatzeItem* item,77
77 gint64 parentid);78void
79midori_bookmarks_db_populate_folder (MidoriBookmarksDb* bookmarks,
80 KatzeArray *folder);
7881
79#endif /* !__MIDORI_BOOKMARKS_DB_H__ */82#endif /* !__MIDORI_BOOKMARKS_DB_H__ */
80
8183
=== modified file 'midori/midori-browser.c'
--- midori/midori-browser.c 2014-01-06 23:05:10 +0000
+++ midori/midori-browser.c 2014-01-30 21:24:26 +0000
@@ -1025,7 +1025,7 @@
1025static gint641025static gint64
1026midori_bookmark_folder_button_get_active (GtkWidget* combo)1026midori_bookmark_folder_button_get_active (GtkWidget* combo)
1027{1027{
1028 gint64 id = 0;1028 gint64 id = -1;
1029 GtkTreeIter iter;1029 GtkTreeIter iter;
10301030
1031 g_return_val_if_fail (GTK_IS_COMBO_BOX (combo), 0);1031 g_return_val_if_fail (GTK_IS_COMBO_BOX (combo), 0);
@@ -3107,29 +3107,17 @@
3107 KatzeArray* folder,3107 KatzeArray* folder,
3108 MidoriBrowser* browser)3108 MidoriBrowser* browser)
3109{3109{
3110 KatzeArray* bookmarks;
3111 const gchar* id = katze_item_get_meta_string (KATZE_ITEM (folder), "id");
3112 gchar* condition;
3113
3114 if (browser->bookmarks == NULL)3110 if (browser->bookmarks == NULL)
3115 return FALSE;3111 return FALSE;
31163112
3117 if (id == NULL)3113 midori_bookmarks_db_populate_folder (browser->bookmarks, folder);
3118 condition = "parentid is NULL";
3119 else
3120 condition = "parentid = %q";
3121
3122 bookmarks = midori_bookmarks_db_query_recursive (browser->bookmarks,
3123 "id, title, parentid, uri, app, pos_panel, pos_bar", condition, id, FALSE);
3124 if (!bookmarks)
3125 return FALSE;
31263114
3127 /* Clear items from dummy array here */3115 /* Clear items from dummy array here */
3128 gtk_container_foreach (GTK_CONTAINER (menu),3116 gtk_container_foreach (GTK_CONTAINER (menu),
3129 (GtkCallback)(gtk_widget_destroy), NULL);3117 (GtkCallback)(gtk_widget_destroy), NULL);
31303118
3131 /* "Import Bookmarks" and "Export Bookmarks" at the top */3119 /* "Import Bookmarks" and "Export Bookmarks" at the top */
3132 if (id == NULL)3120 if (folder == KATZE_ARRAY (browser->bookmarks))
3133 {3121 {
3134 GtkWidget* menuitem;3122 GtkWidget* menuitem;
3135 menuitem = gtk_action_create_menu_item (_action_by_name (browser, "BookmarksImport"));3123 menuitem = gtk_action_create_menu_item (_action_by_name (browser, "BookmarksImport"));
@@ -3143,7 +3131,7 @@
3143 gtk_widget_show (menuitem);3131 gtk_widget_show (menuitem);
3144 }3132 }
31453133
3146 if (katze_array_is_empty (bookmarks))3134 if (katze_array_is_empty (folder))
3147 {3135 {
3148 GtkWidget* menuitem = gtk_image_menu_item_new_with_label (_("Empty"));3136 GtkWidget* menuitem = gtk_image_menu_item_new_with_label (_("Empty"));
3149 gtk_widget_set_sensitive (menuitem, FALSE);3137 gtk_widget_set_sensitive (menuitem, FALSE);
@@ -3152,7 +3140,7 @@
3152 return TRUE;3140 return TRUE;
3153 }3141 }
31543142
3155 katze_array_action_generate_menu (KATZE_ARRAY_ACTION (action), bookmarks,3143 katze_array_action_generate_menu (KATZE_ARRAY_ACTION (action), folder,
3156 menu, GTK_WIDGET (browser));3144 menu, GTK_WIDGET (browser));
3157 return TRUE;3145 return TRUE;
3158}3146}
@@ -4502,7 +4490,7 @@
45024490
4503 error = NULL;4491 error = NULL;
4504 bookmarks = midori_bookmarks_db_query_recursive (browser->bookmarks,4492 bookmarks = midori_bookmarks_db_query_recursive (browser->bookmarks,
4505 "*", "parentid IS NULL", NULL, TRUE);4493 "*", "parentid IS NULL", NULL, NULL, TRUE);
4506 if (!midori_array_to_file (bookmarks, path, format, &error))4494 if (!midori_array_to_file (bookmarks, path, format, &error))
4507 {4495 {
4508 sokoke_message_dialog (GTK_MESSAGE_ERROR,4496 sokoke_message_dialog (GTK_MESSAGE_ERROR,
@@ -6702,7 +6690,7 @@
6702 gtk_separator_tool_item_new (), -1);6690 gtk_separator_tool_item_new (), -1);
67036691
6704 array = midori_bookmarks_db_query_recursive (browser->bookmarks,6692 array = midori_bookmarks_db_query_recursive (browser->bookmarks,
6705 "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "toolbar = 1", NULL, FALSE);6693 "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "toolbar = 1", NULL, "pos_bar ASC,", FALSE);
6706 if (!array)6694 if (!array)
6707 {6695 {
6708 _action_set_sensitive (browser, "BookmarkAdd", FALSE);6696 _action_set_sensitive (browser, "BookmarkAdd", FALSE);
@@ -6756,6 +6744,10 @@
6756 midori_bookmarkbar_remove_item_cb, browser);6744 midori_bookmarkbar_remove_item_cb, browser);
6757 }6745 }
67586746
6747 g_object_set (G_OBJECT (_action_by_name (browser, "Bookmarks")),
6748 "array", KATZE_ARRAY (bookmarks),
6749 NULL);
6750
6759 settings = midori_browser_get_settings (browser);6751 settings = midori_browser_get_settings (browser);
6760 g_signal_handlers_disconnect_by_func (settings,6752 g_signal_handlers_disconnect_by_func (settings,
6761 midori_browser_show_bookmarkbar_notify_value_cb, browser);6753 midori_browser_show_bookmarkbar_notify_value_cb, browser);
67626754
=== modified file 'panels/midori-bookmarks.c'
--- panels/midori-bookmarks.c 2014-01-24 23:04:05 +0000
+++ panels/midori-bookmarks.c 2014-01-30 21:24:26 +0000
@@ -26,6 +26,151 @@
2626
27#define COMPLETION_DELAY 20027#define COMPLETION_DELAY 200
2828
29#define MIDORI_BOOKMARKS_TREE_MODEL_TARGET "GTK_TREE_MODEL_ROW"
30
31G_BEGIN_DECLS
32
33#define MIDORI_BOOKMARKS_TREE_STORE_TYPE \
34 (midori_bookmarks_tree_store_get_type ())
35#define MIDORI_BOOKMARKS_TREE_STORE(obj) \
36 (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_BOOKMARKS_TREE_STORE_TYPE, MidoriBookmarksTreeStore))
37#define MIDORI_BOOKMARKS_TREE_STORE_CLASS(klass) \
38 (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_BOOKMARKS_TREE_STORE_TYPE, MidoriBookmarksTreeStoreClass))
39
40static gboolean
41midori_bookmarks_tree_store_drag_data_get (GtkTreeDragSource* drag_source,
42 GtkTreePath* source_path,
43 GtkSelectionData* selection_data);
44static gboolean
45midori_bookmarks_tree_store_drag_data_delete (GtkTreeDragSource* drag_source,
46 GtkTreePath* source_path);
47static gboolean
48midori_bookmarks_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest,
49 GtkTreePath *dest_path,
50 GtkSelectionData *selection_data);
51static gboolean
52midori_bookmarks_tree_store_drag_data_received (GtkTreeDragDest *drag_dest,
53 GtkTreePath *dest_path,
54 GtkSelectionData *selection_data);
55
56typedef struct _MidoriBookmarksTreeStore MidoriBookmarksTreeStore;
57typedef struct _MidoriBookmarksTreeStoreClass MidoriBookmarksTreeStoreClass;
58typedef struct _TreeRowData TreeRowData;
59
60struct _MidoriBookmarksTreeStore
61{
62 GtkTreeStore parent_instance;
63
64 GList* stock_got_rows;
65 GtkTreeView *_view;
66};
67
68struct _MidoriBookmarksTreeStoreClass
69{
70 GtkTreeStoreClass parent_class;
71};
72
73struct _TreeRowData
74{
75 GtkTreeModel *model;
76 gchar path[4];
77};
78
79static GtkTreeDragSourceIface *
80gtk_tree_store_gtk_tree_drag_source_iface = NULL;
81static GtkTreeDragDestIface *
82gtk_tree_store_gtk_tree_drag_dest_iface = NULL;
83
84static void
85midori_bookmarks_tree_store_drag_source_init (GtkTreeDragSourceIface *iface)
86{
87 gtk_tree_store_gtk_tree_drag_source_iface = g_type_interface_peek_parent (iface);
88
89 iface->drag_data_get = midori_bookmarks_tree_store_drag_data_get;
90 iface->drag_data_delete = midori_bookmarks_tree_store_drag_data_delete;
91}
92
93static void
94midori_bookmarks_tree_store_drag_dest_init (GtkTreeDragDestIface *iface)
95{
96 gtk_tree_store_gtk_tree_drag_dest_iface = g_type_interface_peek_parent (iface);
97
98 iface->row_drop_possible = midori_bookmarks_tree_store_row_drop_possible;
99 iface->drag_data_received = midori_bookmarks_tree_store_drag_data_received;
100}
101
102static void
103midori_bookmarks_tree_store_init (MidoriBookmarksTreeStore* item)
104{
105 item->stock_got_rows = NULL;
106 item->_view = NULL;
107}
108
109static void
110midori_bookmarks_tree_store_class_init (MidoriBookmarksTreeStoreClass *class)
111{
112}
113
114G_DEFINE_TYPE_WITH_CODE (MidoriBookmarksTreeStore,
115 midori_bookmarks_tree_store,
116 GTK_TYPE_TREE_STORE,
117 G_IMPLEMENT_INTERFACE (
118 GTK_TYPE_TREE_DRAG_SOURCE,
119 midori_bookmarks_tree_store_drag_source_init)
120 G_IMPLEMENT_INTERFACE (
121 GTK_TYPE_TREE_DRAG_DEST,
122 midori_bookmarks_tree_store_drag_dest_init));
123
124
125GtkTreeStore*
126midori_bookmarks_tree_store_new (gint n_columns, ...)
127{
128 GtkTreeStore* tree_store = GTK_TREE_STORE (g_object_new (MIDORI_BOOKMARKS_TREE_STORE_TYPE, NULL));
129 va_list ap;
130 GType* types;
131 gint n;
132
133 if (!tree_store)
134 return NULL;
135
136 types = g_new (GType, n_columns);
137
138 if (!types)
139 {
140 g_object_unref(tree_store);
141 return NULL;
142 }
143
144 va_start(ap, n_columns);
145 for (n = 0; n < n_columns; n++)
146 {
147 types[n] = va_arg(ap, GType);
148 }
149 va_end(ap);
150
151 gtk_tree_store_set_column_types (tree_store,
152 n_columns,
153 types);
154
155 g_free (types);
156 return tree_store;
157}
158
159GtkTreeStore*
160midori_bookmarks_tree_store_newv (gint n_columns, GType *types)
161{
162 GtkTreeStore* tree_store = GTK_TREE_STORE (g_object_new (MIDORI_BOOKMARKS_TREE_STORE_TYPE, NULL));
163
164 if (!tree_store)
165 return NULL;
166
167 gtk_tree_store_set_column_types (tree_store,
168 n_columns,
169 types);
170
171 return tree_store;
172}
173
29gboolean174gboolean
30midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser,175midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser,
31 KatzeItem* bookmark_or_parent,176 KatzeItem* bookmark_or_parent,
@@ -37,6 +182,12 @@
37midori_browser_open_bookmark (MidoriBrowser* browser,182midori_browser_open_bookmark (MidoriBrowser* browser,
38 KatzeItem* item);183 KatzeItem* item);
39184
185static void
186midori_bookmarks_row_changed_cb (GtkTreeModel* model,
187 GtkTreePath* path,
188 GtkTreeIter* iter,
189 MidoriBookmarks* bookmarks);
190
40struct _MidoriBookmarks191struct _MidoriBookmarks
41{192{
42 GtkVBox parent_instance;193 GtkVBox parent_instance;
@@ -50,7 +201,19 @@
50 gint filter_timeout;201 gint filter_timeout;
51 gchar* filter;202 gchar* filter;
52203
204 GList* pending_inserts;
53 KatzeItem* hovering_item;205 KatzeItem* hovering_item;
206
207 struct _stock_pending_event
208 {
209 gint x;
210 gint y;
211 } *pending_event,
212 stock_pending_event;
213
214 GHashTable* updated_items;
215 GList* added_paths;
216 GList* reordered_paths;
54};217};
55218
56struct _MidoriBookmarksClass219struct _MidoriBookmarksClass
@@ -88,36 +251,47 @@
88 GParamSpec* pspec);251 GParamSpec* pspec);
89252
90static void253static void
91midori_bookmarks_row_changed_cb (GtkTreeModel* model,254midori_bookmarks_update_cb (KatzeArray* array,
92 GtkTreePath* path,255 MidoriBookmarks* bookmarks);
93 GtkTreeIter* iter,
94 MidoriBookmarks* bookmarks);
95
96static void256static void
97midori_bookmarks_add_item_cb (KatzeArray* array,257midori_bookmarks_add_item_cb (KatzeArray* array,
98 KatzeItem* item,258 KatzeItem* item,
99 MidoriBookmarks* bookmarks);259 MidoriBookmarks* bookmarks);
100
101static void260static void
102midori_bookmarks_update_item_cb (KatzeArray* array,261midori_bookmarks_update_item_cb (KatzeArray* array,
103 KatzeItem* item,262 KatzeItem* item,
104 MidoriBookmarks* bookmarks);263 MidoriBookmarks* bookmarks);
105
106static void264static void
107midori_bookmarks_remove_item_cb (KatzeArray* array,265midori_bookmarks_remove_item_cb (KatzeArray* array,
108 KatzeItem* item,266 KatzeItem* item,
109 MidoriBookmarks* bookmarks);267 MidoriBookmarks* bookmarks);
110268
111static void269static void
112midori_bookmarks_update_cb (KatzeArray* array,270midori_bookmarks_row_inserted_cb (GtkTreeModel* model,
113 MidoriBookmarks* bookmarks);271 GtkTreePath* path,
272 GtkTreeIter* iter,
273 MidoriBookmarks* bookmarks);
274static void
275midori_bookmarks_row_changed_cb (GtkTreeModel* model,
276 GtkTreePath* path,
277 GtkTreeIter* iter,
278 MidoriBookmarks* bookmarks);
279static void
280midori_bookmarks_row_deleted_cb (GtkTreeModel* model,
281 GtkTreePath* path,
282 MidoriBookmarks* bookmarks);
283
284static void
285midori_bookmarks_update_item (MidoriBookmarks* bookmarks, KatzeItem *item);
114286
115static void287static void
116midori_bookmarks_statusbar_update (MidoriBookmarks *bookmarks);288midori_bookmarks_statusbar_update (MidoriBookmarks *bookmarks);
117289
118static void290static void
119midori_bookmarks_add_item (KatzeItem* item,291midori_bookmarks_idle_remove_item (MidoriBookmarks* bookmarks, KatzeItem *item);
120 MidoriBookmarks* bookmarks);292
293static gboolean
294midori_bookmarks_idle_func (gpointer data);
121295
122static void296static void
123midori_bookmarks_class_init (MidoriBookmarksClass* class)297midori_bookmarks_class_init (MidoriBookmarksClass* class)
@@ -133,13 +307,13 @@
133 flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;307 flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
134308
135 g_object_class_install_property (gobject_class,309 g_object_class_install_property (gobject_class,
136 PROP_APP,310 PROP_APP,
137 g_param_spec_object (311 g_param_spec_object (
138 "app",312 "app",
139 "App",313 "App",
140 "The app",314 "The app",
141 MIDORI_TYPE_APP,315 MIDORI_TYPE_APP,
142 flags));316 flags));
143}317}
144318
145static const gchar*319static const gchar*
@@ -168,7 +342,7 @@
168 gchar* parent_id;342 gchar* parent_id;
169343
170 parent_id = g_strdup_printf ("%" G_GINT64_FORMAT, parentid);344 parent_id = g_strdup_printf ("%" G_GINT64_FORMAT, parentid);
171 if (!(root_array = midori_bookmarks_db_query_recursive (array, "*", "parentid = %q", parent_id, FALSE)))345 if (!(root_array = midori_bookmarks_db_query_recursive (array, "*", "parentid = %q", parent_id, "pos_panel DESC,", FALSE)))
172 {346 {
173 g_free (parent_id);347 g_free (parent_id);
174 return;348 return;
@@ -180,7 +354,7 @@
180 subarray = katze_array_new (KATZE_TYPE_ARRAY);354 subarray = katze_array_new (KATZE_TYPE_ARRAY);
181 katze_item_set_name (KATZE_ITEM (subarray), katze_item_get_name (item));355 katze_item_set_name (KATZE_ITEM (subarray), katze_item_get_name (item));
182 midori_bookmarks_export_array_db (db, subarray,356 midori_bookmarks_export_array_db (db, subarray,
183 katze_item_get_meta_integer (item, "parentid"));357 katze_item_get_meta_integer (item, "parentid"));
184 katze_array_add_item (array, subarray);358 katze_array_add_item (array, subarray);
185 }359 }
186 else360 else
@@ -201,20 +375,20 @@
201375
202 if (keyword && *keyword)376 if (keyword && *keyword)
203 array = midori_bookmarks_db_query_recursive (bookmarks->bookmarks_db,377 array = midori_bookmarks_db_query_recursive (bookmarks->bookmarks_db,
204 "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "title LIKE '%%%q%%'", keyword, FALSE);378 "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "title LIKE '%%%q%%'", keyword, NULL, FALSE);
205 else379 else
206 {380 {
207 if (parentid > 0)381 if (parentid > 0)
208 {382 {
209 gchar* parent_id = g_strdup_printf ("%" G_GINT64_FORMAT, parentid);383 gchar* parent_id = g_strdup_printf ("%" G_GINT64_FORMAT, parentid);
210 array = midori_bookmarks_db_query_recursive (bookmarks->bookmarks_db,384 array = midori_bookmarks_db_query_recursive (bookmarks->bookmarks_db,
211 "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid = %q", parent_id, FALSE);385 "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid = %q", parent_id, "pos_panel DESC, ", FALSE);
212386
213 g_free (parent_id);387 g_free (parent_id);
214 }388 }
215 else389 else
216 array = midori_bookmarks_db_query_recursive (bookmarks->bookmarks_db,390 array = midori_bookmarks_db_query_recursive (bookmarks->bookmarks_db,
217 "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid IS NULL", NULL, FALSE);391 "id, parentid, title, uri, desc, app, toolbar, pos_panel, pos_bar", "parentid IS NULL", NULL, "pos_panel DESC, ", FALSE);
218 }392 }
219 return array ? array : katze_array_new (KATZE_TYPE_ITEM);393 return array ? array : katze_array_new (KATZE_TYPE_ITEM);
220}394}
@@ -231,24 +405,52 @@
231 KatzeItem* item;405 KatzeItem* item;
232 GtkTreeIter child;406 GtkTreeIter child;
233407
408 g_signal_handlers_block_by_func (model,
409 midori_bookmarks_row_changed_cb,
410 bookmarks);
411
234 array = midori_bookmarks_read_from_db (bookmarks, parentid, keyword);412 array = midori_bookmarks_read_from_db (bookmarks, parentid, keyword);
235 katze_bookmark_populate_tree_view (array, model, parent);413 katze_bookmark_populate_tree_view (array, model, parent);
414
415 g_signal_handlers_unblock_by_func (model,
416 midori_bookmarks_row_changed_cb,
417 bookmarks);
418
236 /* Remove invisible dummy row */419 /* Remove invisible dummy row */
237 last = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), parent);420 last = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), parent);
238 if (!last)421 if (!last)
239 return;422 return;
423
424 g_signal_handlers_block_by_func (model,
425 midori_bookmarks_row_deleted_cb,
426 bookmarks);
427
240 gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (model), &child, parent, last - 1);428 gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (model), &child, parent, last - 1);
241 gtk_tree_model_get (GTK_TREE_MODEL (model), &child, 0, &item, -1);429 gtk_tree_model_get (GTK_TREE_MODEL (model), &child, 0, &item, -1);
242 if (KATZE_ITEM_IS_SEPARATOR (item))430 if (KATZE_ITEM_IS_SEPARATOR (item))
243 gtk_tree_store_remove (model, &child);431 gtk_tree_store_remove (model, &child);
244 else432 else
245 g_object_unref (item);433 g_object_unref (item);
434
435 g_signal_handlers_unblock_by_func (model,
436 midori_bookmarks_row_deleted_cb,
437 bookmarks);
438
246}439}
247440
441static void
442midori_bookmarks_add_item (KatzeItem* item,
443 MidoriBookmarks* bookmarks);
444
445static void
446add_parent_to_reorder (GtkTreeModel* model,
447 GtkTreePath* path,
448 MidoriBookmarks* bookmarks);
449
248static gboolean450static gboolean
249midori_bookmarks_reach_item_recurse (GtkTreeModel* model,451midori_bookmarks_reach_item_recurse (GtkTreeModel* model,
250 GtkTreeIter* iter,452 GtkTreeIter* iter,
251 gint64 id)453 gint64 id)
252{454{
253 do455 do
254 {456 {
@@ -258,7 +460,7 @@
258460
259 gtk_tree_model_get (model, iter, 0, &item, -1);461 gtk_tree_model_get (model, iter, 0, &item, -1);
260462
261 if (!KATZE_ITEM_IS_SEPARATOR(item))463 if (item)
262 {464 {
263 itemid = katze_item_get_meta_integer (item, "id");465 itemid = katze_item_get_meta_integer (item, "id");
264 g_object_unref (item);466 g_object_unref (item);
@@ -267,13 +469,11 @@
267 if (id == itemid)469 if (id == itemid)
268 return TRUE;470 return TRUE;
269471
270 if (gtk_tree_model_iter_children (model, &child, iter))472 if (gtk_tree_model_iter_children (model, &child, iter)
473 && midori_bookmarks_reach_item_recurse (model, &child, id))
271 {474 {
272 if (midori_bookmarks_reach_item_recurse (model, &child, id))475 *iter = child;
273 {476 return TRUE;
274 *iter = child;
275 return TRUE;
276 }
277 }477 }
278 }478 }
279 while (gtk_tree_model_iter_next(model, iter));479 while (gtk_tree_model_iter_next(model, iter));
@@ -283,8 +483,8 @@
283483
284static gboolean484static gboolean
285midori_bookmarks_reach_item (GtkTreeModel* model,485midori_bookmarks_reach_item (GtkTreeModel* model,
286 GtkTreeIter* iter,486 GtkTreeIter* iter,
287 gint64 id)487 gint64 id)
288{488{
289 if (!gtk_tree_model_get_iter_first(model, iter))489 if (!gtk_tree_model_get_iter_first(model, iter))
290 return FALSE;490 return FALSE;
@@ -293,38 +493,73 @@
293}493}
294494
295static void495static void
296midori_bookmarks_add_item_to_model(GtkTreeStore* model,496midori_bookmarks_add_item_to_model(MidoriBookmarks* bookmarks,
297 GtkTreeIter* parent,497 GtkTreeModel* model,
298 KatzeItem* item)498 GtkTreeIter* parent,
499 KatzeItem* item)
299{500{
501 GtkTreeStore* tree_store = GTK_TREE_STORE (model);
502 gint last;
503 GtkTreeIter child;
504
300 if (KATZE_ITEM_IS_BOOKMARK (item))505 if (KATZE_ITEM_IS_BOOKMARK (item))
301 {506 {
507 gint position = 0;
508
509 /* skip the folders to be consistent with the db query order */
510 if (gtk_tree_model_iter_children (model, &child, parent))
511 while (gtk_tree_model_iter_has_child (model, &child))
512 {
513 position++;
514 if (!gtk_tree_model_iter_next (model, &child))
515 break;
516 }
517
302 gchar* tooltip = g_markup_escape_text (katze_item_get_uri (item), -1);518 gchar* tooltip = g_markup_escape_text (katze_item_get_uri (item), -1);
303519
304 gtk_tree_store_insert_with_values (model, NULL, parent,520 gtk_tree_store_insert_with_values (tree_store, NULL, parent,
305 0,521 position,
306 0, item, 1, tooltip, -1);522 0, item, 1, tooltip, -1);
307 g_free (tooltip);523 g_free (tooltip);
308 }524 }
309 else525 else if (KATZE_ITEM_IS_FOLDER (item))
310 {526 {
311 GtkTreeIter root_iter;527 GtkTreeIter root_iter;
312528
313 gtk_tree_store_insert_with_values (model, &root_iter, parent,529 gtk_tree_store_insert_with_values (tree_store, &root_iter, parent,
314 0, 0, item, -1);530 0, 0, item, -1);
315531
316 /* That's an invisible dummy, so we always have an expander */532 /* That's an invisible dummy, so we always have an expander */
317 gtk_tree_store_insert_with_values (model, NULL, &root_iter,533 gtk_tree_store_insert_with_values (tree_store, NULL, &root_iter,
318 0,534 0, 0, NULL, -1);
319 0, NULL, -1);
320 }535 }
536
537 /* Remove invisible dummy row */
538 last = gtk_tree_model_iter_n_children (model, parent);
539 if (!last)
540 return;
541
542 g_signal_handlers_block_by_func (model,
543 midori_bookmarks_row_deleted_cb,
544 bookmarks);
545
546 gtk_tree_model_iter_nth_child (model, &child, parent, last - 1);
547 gtk_tree_model_get (model, &child, 0, &item, -1);
548 if (KATZE_ITEM_IS_SEPARATOR (item))
549 gtk_tree_store_remove (tree_store, &child);
550 else
551 g_object_unref (item);
552
553 g_signal_handlers_unblock_by_func (model,
554 midori_bookmarks_row_deleted_cb,
555 bookmarks);
321}556}
322557
323static void558static void
324midori_bookmarks_update_item_in_model(MidoriBookmarks* bookmarks,559midori_bookmarks_update_item_in_model(MidoriBookmarks* bookmarks,
325 GtkTreeStore* model,560 GtkTreeStore* model,
326 GtkTreeIter* iter,561 GtkTreeIter* iter,
327 KatzeItem* item)562 KatzeItem* item)
328{563{
329 g_signal_handlers_block_by_func (model,564 g_signal_handlers_block_by_func (model,
330 midori_bookmarks_row_changed_cb,565 midori_bookmarks_row_changed_cb,
@@ -350,18 +585,48 @@
350 bookmarks);585 bookmarks);
351}586}
352587
588static gboolean
589midori_bookmarks_idle_pending (MidoriBookmarks* bookmarks)
590{
591 if (bookmarks->pending_inserts
592 || bookmarks->added_paths
593 || bookmarks->reordered_paths
594 || g_hash_table_size (bookmarks->updated_items))
595 return TRUE;
596 return FALSE;
597}
598
599/**
600 * midori_bookmarks_idle_start:
601 * @bookmarks: the bookmarks panel
602 *
603 * Internal function that checks whether idle processing is pending,
604 * if not, add a new one.
605 **/
606static void
607midori_bookmarks_idle_start (MidoriBookmarks* bookmarks)
608{
609 if (midori_bookmarks_idle_pending (bookmarks))
610 return;
611
612 g_idle_add (midori_bookmarks_idle_func, bookmarks);
613}
614
353static void615static void
354midori_bookmarks_add_item (KatzeItem* item,616midori_bookmarks_add_item (KatzeItem* item,
355 MidoriBookmarks* bookmarks);617 MidoriBookmarks* bookmarks);
618
356static void619static void
357midori_bookmarks_add_item_cb (KatzeArray* array,620midori_bookmarks_add_item_cb (KatzeArray* array,
358 KatzeItem* item,621 KatzeItem* item,
359 MidoriBookmarks* bookmarks)622 MidoriBookmarks* bookmarks)
360{623{
361 midori_bookmarks_add_item (item, bookmarks);624 midori_bookmarks_idle_start (bookmarks);
625
626 g_object_ref (item);
627 bookmarks->pending_inserts = g_list_append (bookmarks->pending_inserts, item);
362}628}
363629
364
365static void630static void
366midori_bookmarks_add_item (KatzeItem* item,631midori_bookmarks_add_item (KatzeItem* item,
367 MidoriBookmarks* bookmarks)632 MidoriBookmarks* bookmarks)
@@ -370,18 +635,16 @@
370 GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));635 GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));
371 GtkTreeIter iter;636 GtkTreeIter iter;
372637
373 if (!parentid)638 if (parentid == katze_item_get_meta_integer (KATZE_ITEM (bookmarks->bookmarks_db), "id"))
374 {639 midori_bookmarks_add_item_to_model (bookmarks, model, NULL, item);
375 midori_bookmarks_add_item_to_model (GTK_TREE_STORE (model), NULL, item);
376 }
377 else if (midori_bookmarks_reach_item (model, &iter, parentid))640 else if (midori_bookmarks_reach_item (model, &iter, parentid))
378 {641 {
379 GtkTreePath* path = gtk_tree_model_get_path(model, &iter);642 GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
643 gint n_children = gtk_tree_model_iter_n_children (model, &iter);
380644
381 if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (bookmarks->treeview), path))645 if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (bookmarks->treeview), path)
382 {646 || !n_children)
383 midori_bookmarks_add_item_to_model (GTK_TREE_STORE (model), &iter, item);647 midori_bookmarks_add_item_to_model (bookmarks, model, &iter, item);
384 }
385648
386 gtk_tree_path_free (path);649 gtk_tree_path_free (path);
387 }650 }
@@ -389,8 +652,8 @@
389652
390static void653static void
391midori_bookmarks_update_item_cb (KatzeArray* array,654midori_bookmarks_update_item_cb (KatzeArray* array,
392 KatzeItem* item,655 KatzeItem* item,
393 MidoriBookmarks* bookmarks)656 MidoriBookmarks* bookmarks)
394{657{
395 gint64 id = katze_item_get_meta_integer (item, "id");658 gint64 id = katze_item_get_meta_integer (item, "id");
396 gint64 parentid = katze_item_get_meta_integer (item, "parentid");659 gint64 parentid = katze_item_get_meta_integer (item, "parentid");
@@ -433,7 +696,7 @@
433 midori_bookmarks_add_item (item, bookmarks);696 midori_bookmarks_add_item (item, bookmarks);
434 }697 }
435 }698 }
436 else if (parentid == 0)699 else if (parentid == katze_item_get_meta_integer (KATZE_ITEM (bookmarks->bookmarks_db), "id"))
437 {700 {
438 midori_bookmarks_update_item_in_model (bookmarks, GTK_TREE_STORE (model), &iter, item);701 midori_bookmarks_update_item_in_model (bookmarks, GTK_TREE_STORE (model), &iter, item);
439 }702 }
@@ -457,6 +720,10 @@
457 GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));720 GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));
458 GtkTreeIter iter;721 GtkTreeIter iter;
459722
723 g_assert (KATZE_IS_ITEM (item));
724
725 midori_bookmarks_idle_remove_item (bookmarks, item);
726
460 if (midori_bookmarks_reach_item (model, &iter, id))727 if (midori_bookmarks_reach_item (model, &iter, id))
461 {728 {
462 GtkTreeIter parent;729 GtkTreeIter parent;
@@ -486,12 +753,869 @@
486midori_bookmarks_update_cb (KatzeArray* array,753midori_bookmarks_update_cb (KatzeArray* array,
487 MidoriBookmarks* bookmarks)754 MidoriBookmarks* bookmarks)
488{755{
756#if 1
757 g_print ("midori_bookmarks_update_cb: ignored ********\n");
758#else
489 GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));759 GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));
760
490 gtk_tree_store_clear (GTK_TREE_STORE (model));761 gtk_tree_store_clear (GTK_TREE_STORE (model));
491 midori_bookmarks_read_from_db_to_model (bookmarks,762 midori_bookmarks_read_from_db_to_model (bookmarks,
492 GTK_TREE_STORE (model), NULL, 0, bookmarks->filter);763 GTK_TREE_STORE (model), NULL, 0, bookmarks->filter);
493}764#endif
494765}
766
767gboolean
768midori_bookmarks_tree_set_row_drag_data (GtkSelectionData *selection_data,
769 GtkTreeModel *tree_model,
770 GList* rows)
771{
772 TreeRowData *trd;
773 gint len;
774 gint struct_size;
775 gint length;
776 gint i;
777 GString *data;
778
779 g_return_val_if_fail (selection_data != NULL, FALSE);
780 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
781 g_return_val_if_fail (rows != NULL, FALSE);
782
783 data = g_string_new("");
784
785 length = g_list_length (rows);
786 for (i = 0; i < length; i++)
787 {
788 GtkTreePath *path = (GtkTreePath *)g_list_nth_data (rows, i);
789 gchar *path_str = gtk_tree_path_to_string (path);
790
791 g_string_append (data, path_str);
792 if (i < length-1)
793 g_string_append_c (data, '\n');
794 }
795
796 len = data->len;
797
798 /* the old allocate-end-of-struct-to-hold-string trick */
799 struct_size = sizeof (TreeRowData) + len + 1 -
800 (sizeof (TreeRowData) - G_STRUCT_OFFSET (TreeRowData, path));
801
802 trd = g_malloc (struct_size);
803
804 strcpy (trd->path, data->str);
805
806 g_string_free (data, TRUE);
807
808 trd->model = tree_model;
809
810 gtk_selection_data_set (selection_data,
811 gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET),
812 8, /* bytes */
813 (void*)trd,
814 struct_size);
815
816 g_free (trd);
817
818 return TRUE;
819}
820
821static gboolean
822midori_bookmarks_tree_store_drag_data_get (GtkTreeDragSource* drag_source,
823 GtkTreePath* source_path,
824 GtkSelectionData* selection_data)
825{
826 MidoriBookmarksTreeStore *tree_store;
827 gboolean status = FALSE;
828
829 g_return_val_if_fail (selection_data != NULL, FALSE);
830 g_return_val_if_fail (GTK_IS_TREE_MODEL (drag_source), FALSE);
831 g_return_val_if_fail (source_path != NULL, FALSE);
832
833 tree_store = MIDORI_BOOKMARKS_TREE_STORE(drag_source);
834
835 if (tree_store->stock_got_rows)
836 {
837 g_list_free_full (tree_store->stock_got_rows, (GDestroyNotify) gtk_tree_path_free);
838 tree_store->stock_got_rows = NULL;
839 }
840
841 if (gtk_selection_data_get_target (selection_data) ==
842 gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET))
843 {
844 GtkTreeModel *model;
845 GList* rows;
846 if (katze_tree_view_get_selected_rows (
847 tree_store->_view, &model, &rows))
848 {
849 status = midori_bookmarks_tree_set_row_drag_data (selection_data, model, rows);
850
851 tree_store->stock_got_rows = rows;
852 }
853 }
854
855 return status;
856}
857
858static void
859update_path_list_for_insert (GList * rows, GtkTreePath* path)
860{
861 gint length = g_list_length (rows);
862 gint i;
863
864 for (i = 0; i < length; i++ )
865 {
866 GtkTreePath *src_path_r = (GtkTreePath *)g_list_nth_data (rows, i);
867 gint la = gtk_tree_path_get_depth (path);
868 gint lb = gtk_tree_path_get_depth (src_path_r);
869 gint *ia = gtk_tree_path_get_indices (path);
870 gint *ib = gtk_tree_path_get_indices (src_path_r);
871 gint j;
872
873 if (la > lb) /* insert was donne in a deeper branch than source */
874 continue;
875
876 if (ia[la-1] > ib[la-1]) /* insert was donne after source */
877 continue;
878
879 for (j = 0; j < la; j++)
880 {
881 if (ia[j] != ib[j]) break;
882 }
883
884 if (j < la-1) /* insert and source are not in the same branch */
885 continue;
886
887 /* source at depth level of insert must be incremented due to the insert */
888 ib[la-1] += 1;
889 }
890}
891
892static gint
893midori_tree_path_compare (const GtkTreePath *a,
894 const GtkTreePath *b)
895{
896 if (!gtk_tree_path_get_depth ((GtkTreePath *)a))
897 {
898 if (!gtk_tree_path_get_depth ((GtkTreePath *)b))
899 return 0;
900
901 return -1;
902 }
903
904 if (!gtk_tree_path_get_depth ((GtkTreePath *)b))
905 return 1;
906
907 return gtk_tree_path_compare (a, b);
908}
909
910static GList*
911update_path_list_for_delete (GList* rows, GtkTreePath* removed_path)
912{
913 GList* new_rows = rows;
914
915 while (rows)
916 {
917 GtkTreePath *source_path = (GtkTreePath *)rows->data;
918 gint la = gtk_tree_path_get_depth (removed_path);
919 gint lb = gtk_tree_path_get_depth (source_path);
920 gint *ia = gtk_tree_path_get_indices (removed_path);
921 gint *ib = gtk_tree_path_get_indices (source_path);
922 gint cmp = midori_tree_path_compare (removed_path, source_path);
923 gint j;
924
925 if (cmp == 1) /* removal was done after source => kip source as it is */
926 goto keep_source;
927
928 if (cmp == 0) /* source is removed => remove source */
929 goto remove_source;
930
931 /* if removal is an ancestor of the source => remove source */
932 if (gtk_tree_path_is_ancestor (removed_path, source_path))
933 goto remove_source;
934
935 if (la > lb) /* removal was donne in a deeper branch than source */
936 goto keep_source;
937
938 for (j = 0; j < la; j++)
939 {
940 if (ia[j] != ib[j]) break;
941 }
942
943 if (j < la-1) /* removal and source are not in the same branch */
944 goto keep_source;
945
946 /* source at depth level of removal must be decremented due to the removal */
947 ib[la-1] -= 1;
948
949 if (ib[la-1] >= 0)
950 goto keep_source;
951
952 remove_source:
953 /* remove source entry */
954 gtk_tree_path_free (source_path);
955 {
956 GList *next_rows = g_list_next (rows);
957 new_rows = g_list_delete_link (new_rows, rows);
958 rows = next_rows;
959 }
960 continue;
961
962 keep_source:
963 rows = g_list_next (rows);
964 }
965
966 return new_rows;
967}
968
969static gboolean
970midori_bookmarks_tree_store_drag_data_delete (GtkTreeDragSource* drag_source,
971 GtkTreePath* source_path)
972{
973 gboolean status = TRUE;
974 MidoriBookmarksTreeStore *tree_store = MIDORI_BOOKMARKS_TREE_STORE(drag_source);
975 GtkTreeModel* model = GTK_TREE_MODEL(drag_source);
976
977 if (!tree_store->stock_got_rows)
978 return TRUE;
979
980 while (tree_store->stock_got_rows)
981 {
982 GtkTreePath *prev = (GtkTreePath *)tree_store->stock_got_rows->data;
983 GtkTreeIter iter;
984
985 tree_store->stock_got_rows = g_list_delete_link (tree_store->stock_got_rows,
986 tree_store->stock_got_rows);
987
988 if (gtk_tree_model_get_iter (model, &iter, prev))
989 {
990 /* remove item updating source paths */
991 gtk_tree_store_remove (GTK_TREE_STORE (drag_source), &iter);
992
993 tree_store->stock_got_rows = update_path_list_for_delete (tree_store->stock_got_rows, prev);
994 }
995 else
996 status = FALSE;
997
998 gtk_tree_path_free (prev);
999 }
1000
1001 return status;
1002}
1003
1004static gboolean
1005midori_bookmarks_tree_store_get_rows_drag_data (GtkSelectionData *selection_data,
1006 GtkTreeModel **tree_model,
1007 GList **rows)
1008{
1009 TreeRowData *trd;
1010
1011 g_return_val_if_fail (selection_data != NULL, FALSE);
1012
1013 if (tree_model)
1014 *tree_model = NULL;
1015
1016 if (rows)
1017 *rows = NULL;
1018
1019 if (gtk_selection_data_get_target (selection_data) !=
1020 gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET))
1021 return FALSE;
1022
1023 if (gtk_selection_data_get_length (selection_data) < 0)
1024 return FALSE;
1025
1026 trd = (void*) gtk_selection_data_get_data (selection_data);
1027
1028 if (tree_model)
1029 *tree_model = trd->model;
1030
1031 if (rows)
1032 {
1033 GList *list = NULL;
1034 gchar *trd_path = g_strdup (trd->path);
1035 gchar *path_str;
1036
1037 path_str = strtok(trd_path, "\n");
1038 while (path_str && *path_str)
1039 {
1040 list = g_list_append (list, gtk_tree_path_new_from_string (path_str));
1041 path_str = strtok (NULL, "\n");
1042 }
1043
1044 *rows = list;
1045 g_free (trd_path);
1046 }
1047
1048 return TRUE;
1049}
1050
1051#if !GTK_CHECK_VERSION (3,0,0)
1052gboolean
1053gtk_tree_model_iter_previous (GtkTreeModel *tree_model,
1054 GtkTreeIter *iter)
1055{
1056 GtkTreePath* path = gtk_tree_model_get_path (tree_model, iter);
1057 gboolean result = gtk_tree_path_prev (path);
1058
1059 if (result)
1060 result = gtk_tree_model_get_iter (tree_model, iter, path);
1061 else
1062 {
1063 GtkTreeIter invalid = {0};
1064 *iter = invalid;
1065 }
1066
1067 gtk_tree_path_free (path);
1068 return result;
1069}
1070#endif
1071
1072static gboolean
1073midori_bookmarks_tree_store_row_drop_possible (GtkTreeDragDest* drag_dest,
1074 GtkTreePath* dest_path,
1075 GtkSelectionData* selection_data)
1076{
1077 GtkTreeModel* dest_model = GTK_TREE_MODEL(drag_dest);
1078 GtkTreePath *parent;
1079 GtkTreeIter dest_parent;
1080 GtkTreeIter *dest_parent_p = NULL;
1081 gboolean row_drop_possible = TRUE;
1082 GtkTreeViewDropPosition drop_position;
1083
1084 gtk_tree_view_get_drag_dest_row (MIDORI_BOOKMARKS_TREE_STORE (dest_model)->_view,
1085 NULL, &drop_position);
1086
1087 parent = gtk_tree_path_copy (dest_path);
1088 if ((gtk_tree_path_get_depth (parent) > 1)
1089 && gtk_tree_path_up (parent)
1090 && gtk_tree_model_get_iter (dest_model, &dest_parent, parent))
1091 dest_parent_p = &dest_parent;
1092
1093 gtk_tree_path_free (parent);
1094
1095 if (dest_parent_p)
1096 {
1097 KatzeItem* item;
1098
1099 gtk_tree_model_get (dest_model, dest_parent_p, 0, &item, -1);
1100
1101 if (!KATZE_ITEM_IS_FOLDER (item))
1102 {
1103#ifdef DEBUG_DROP
1104 gchar *dest_path_str = gtk_tree_path_to_string (dest_path);
1105
1106 g_print ("%s: can only drop into folders\n", dest_path_str);
1107 g_free (dest_path_str);
1108#endif /* DEBUG_DROP */
1109 row_drop_possible = FALSE;
1110 }
1111
1112 if (item)
1113 g_object_unref (item);
1114 }
1115
1116 if (row_drop_possible
1117 && (gtk_selection_data_get_target (selection_data) ==
1118 gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET)))
1119 {
1120 GtkTreeModel *src_model;
1121 GList* rows;
1122
1123 if (midori_bookmarks_tree_store_get_rows_drag_data (selection_data,
1124 &src_model, &rows))
1125 {
1126 GtkTreeIter dest_iter;
1127 GList* src_row;
1128 gboolean dest_is_folder = FALSE;
1129 /* gboolean dest_is_bookmark = FALSE; */
1130 gboolean src_has_folders = FALSE;
1131 gboolean src_has_bookmarks = FALSE;
1132
1133 if (gtk_tree_model_get_iter (dest_model, &dest_iter, dest_path))
1134 {
1135 if (gtk_tree_model_iter_has_child (dest_model, &dest_iter))
1136 dest_is_folder = TRUE;
1137/*
1138 else
1139 {
1140 KatzeItem* item;
1141 gtk_tree_model_get (dest_model, &dest_iter, 0, &item, -1);
1142 if (item)
1143 {
1144 dest_is_bookmark = TRUE;
1145 g_object_unref (item);
1146 }
1147 }
1148*/
1149 }
1150
1151 for (src_row = rows ; src_row ; src_row = g_list_next (src_row))
1152 {
1153 GtkTreePath* src_path = (GtkTreePath*)src_row->data;
1154 GtkTreeIter src_iter;
1155 KatzeItem* item;
1156
1157 if (!gtk_tree_model_get_iter (src_model, &src_iter, src_path))
1158 continue;
1159
1160 gtk_tree_model_get (src_model, &src_iter, 0, &item, -1);
1161 if (item)
1162 {
1163 if (!src_has_folders && KATZE_ITEM_IS_FOLDER (item))
1164 src_has_folders = TRUE;
1165 else if (!src_has_bookmarks && KATZE_ITEM_IS_BOOKMARK (item))
1166 src_has_bookmarks = TRUE;
1167
1168 g_object_unref (item);
1169 }
1170 if (src_has_bookmarks && src_has_folders)
1171 break;
1172 }
1173
1174 if (src_has_bookmarks)
1175 {
1176 switch (drop_position)
1177 {
1178 case GTK_TREE_VIEW_DROP_BEFORE:
1179 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
1180 if (dest_is_folder)
1181 {
1182#ifdef DEBUG_DROP
1183 gchar *dest_path_str = gtk_tree_path_to_string (dest_path);
1184
1185 g_print ("%s: cannot drop bookmarks in folders group\n", dest_path_str);
1186 g_free (dest_path_str);
1187#endif /* DEBUG_DROP */
1188 row_drop_possible = FALSE;
1189 goto done;
1190 }
1191 break;
1192 case GTK_TREE_VIEW_DROP_AFTER:
1193 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
1194 if (dest_is_folder)
1195 {
1196 gboolean next_dest_is_folder = FALSE;
1197
1198 if (gtk_tree_model_iter_next (dest_model, &dest_iter))
1199 if (gtk_tree_model_iter_has_child (dest_model, &dest_iter))
1200 next_dest_is_folder = TRUE;
1201
1202 if (next_dest_is_folder)
1203 {
1204#ifdef DEBUG_DROP
1205 gchar *dest_path_str = gtk_tree_path_to_string (dest_path);
1206
1207 g_print ("%s: cannot drop bookmarks in folders group\n", dest_path_str);
1208 g_free (dest_path_str);
1209#endif /* DEBUG_DROP */
1210 row_drop_possible = FALSE;
1211 goto done;
1212 }
1213 }
1214 break;
1215 default:
1216 break;
1217 }
1218 }
1219 else if (src_has_folders)
1220 {
1221 gboolean prev_dest_is_folder = TRUE;
1222
1223 if (gtk_tree_model_iter_previous (dest_model, &dest_iter))
1224 if (!gtk_tree_model_iter_has_child (dest_model, &dest_iter))
1225 prev_dest_is_folder = FALSE;
1226
1227 if (!prev_dest_is_folder)
1228 {
1229#ifdef DEBUG_DROP
1230 gchar *dest_path_str = gtk_tree_path_to_string (dest_path);
1231
1232 g_print ("%s: cannot drop folders in bookmarks group\n", dest_path_str);
1233 g_free (dest_path_str);
1234#endif /* DEBUG_DROP */
1235 row_drop_possible = FALSE;
1236 goto done;
1237 }
1238 }
1239
1240 if (src_model == dest_model)
1241 {
1242 for (src_row = rows ; src_row ; src_row = g_list_next (src_row))
1243 {
1244 GtkTreePath* src_path = (GtkTreePath*)src_row->data;
1245
1246 /* Can't drop into ourself. */
1247 if (gtk_tree_path_is_ancestor (src_path, dest_path))
1248 {
1249#ifdef DEBUG_DROP
1250 g_print ("cannot drop into source folders\n");
1251#endif /* DEBUG_DROP */
1252 row_drop_possible = FALSE;
1253 goto done;
1254 }
1255 update_path_list_for_insert (rows, dest_path);
1256 }
1257 }
1258 done:
1259 g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
1260 }
1261 else
1262 row_drop_possible = FALSE;
1263 }
1264 else
1265 row_drop_possible = FALSE;
1266
1267#ifdef DEBUG_DROP
1268 if (row_drop_possible)
1269 {
1270 gchar *dest_path_str = gtk_tree_path_to_string (dest_path);
1271 gchar *drop_position_str = "unknown";
1272 switch (drop_position)
1273 {
1274 case GTK_TREE_VIEW_DROP_BEFORE:
1275 drop_position_str = "before";
1276 break;
1277 case GTK_TREE_VIEW_DROP_AFTER:
1278 drop_position_str = "after";
1279 break;
1280 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
1281 drop_position_str = "into or before";
1282 break;
1283 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
1284 drop_position_str = "into or after";
1285 break;
1286 }
1287
1288 g_print ("%s: row drop possible (%s)\n", dest_path_str, drop_position_str);
1289 g_free (dest_path_str);
1290 }
1291#endif /* DEBUG_DROP */
1292
1293 return row_drop_possible;
1294}
1295
1296static void
1297copy_node_data (GtkTreeStore *src_store,
1298 GtkTreeIter *src_iter,
1299 GtkTreeStore *dest_store,
1300 GtkTreeIter *dest_iter)
1301{
1302 gint i;
1303 gint n_columns;
1304 GtkTreeModel* src_model = GTK_TREE_MODEL (src_store);
1305
1306 n_columns = gtk_tree_model_get_n_columns (src_model);
1307
1308 for (i = 0; i < n_columns; i++)
1309 {
1310 void *item;
1311
1312 gtk_tree_model_get (src_model, src_iter, i, &item, -1);
1313 gtk_tree_store_set (dest_store, dest_iter, i, item, -1);
1314 }
1315}
1316
1317static void
1318recursive_node_copy (GtkTreeStore *src_store,
1319 GtkTreeIter *src_iter,
1320 GtkTreeStore *dest_store,
1321 GtkTreeIter *dest_iter)
1322{
1323 GtkTreeIter child;
1324 GtkTreeModel *src_model = GTK_TREE_MODEL (src_store);
1325
1326 copy_node_data (src_store, src_iter, dest_store, dest_iter);
1327
1328 if (gtk_tree_model_iter_children (src_model, &child, src_iter))
1329 {
1330 /* Need to create children and recurse. Note our
1331 * dependence on persistent iterators here.
1332 */
1333 do
1334 {
1335 GtkTreeIter copy;
1336
1337 /* Gee, a really slow algorithm... ;-) FIXME */
1338 gtk_tree_store_append (dest_store,
1339 &copy,
1340 dest_iter);
1341
1342 recursive_node_copy (src_store, &child, dest_store, &copy);
1343 }
1344 while (gtk_tree_model_iter_next (src_model, &child));
1345 }
1346}
1347
1348static gboolean
1349midori_bookmarks_tree_store_drag_data_received (GtkTreeDragDest *drag_dest,
1350 GtkTreePath *dest_path,
1351 GtkSelectionData *selection_data)
1352{
1353 gboolean status = TRUE;
1354
1355 g_return_val_if_fail (selection_data != NULL, FALSE);
1356 g_return_val_if_fail (GTK_IS_TREE_MODEL (drag_dest), FALSE);
1357 g_return_val_if_fail (dest_path != NULL, FALSE);
1358
1359 if (gtk_selection_data_get_target (selection_data) ==
1360 gdk_atom_intern_static_string (MIDORI_BOOKMARKS_TREE_MODEL_TARGET))
1361 {
1362 GtkTreeStore *dest_store = GTK_TREE_STORE (drag_dest);
1363 GtkTreeModel *dest_model = GTK_TREE_MODEL (drag_dest);
1364 GtkTreeModel *src_model;
1365 GList* rows;
1366
1367 if (midori_bookmarks_tree_store_get_rows_drag_data (selection_data,
1368 &src_model, &rows))
1369 {
1370 GtkTreeStore *src_store = GTK_TREE_STORE (src_model);
1371 GtkTreePath *prev = gtk_tree_path_copy (dest_path);
1372
1373 gint count = 0;
1374 gint length = g_list_length (rows);
1375 gint i;
1376
1377 for (i = 0; i < length; i++)
1378 {
1379 GtkTreeIter dest_iter;
1380 GtkTreeIter src_iter;
1381 GtkTreePath *src_path = (GtkTreePath *)g_list_nth_data (rows, i);
1382
1383 if (!gtk_tree_model_get_iter (src_model, &src_iter, src_path))
1384 continue;
1385
1386 /* Get the path to insert _after_ (dest is the path to insert _before_) */
1387 if (i == 0)
1388 {
1389 if (!gtk_tree_path_prev (prev))
1390 { /* Get the parent, NULL if parent is the root */
1391 GtkTreeIter dest_parent;
1392 GtkTreePath *parent = gtk_tree_path_copy (dest_path);
1393 GtkTreeIter *dest_parent_p = NULL;
1394
1395 if (gtk_tree_path_up (parent) &&
1396 gtk_tree_path_get_depth (parent) > 0)
1397 {
1398 gtk_tree_model_get_iter (dest_model,
1399 &dest_parent, parent);
1400 dest_parent_p = &dest_parent;
1401 }
1402 gtk_tree_path_free (parent);
1403
1404 gtk_tree_store_prepend (dest_store, &dest_iter, dest_parent_p);
1405 }
1406 else if (gtk_tree_model_get_iter (dest_model, &dest_iter, prev))
1407 {
1408 GtkTreeIter tmp_iter = dest_iter;
1409
1410 gtk_tree_store_insert_after (dest_store, &dest_iter, NULL,
1411 &tmp_iter);
1412 }
1413 }
1414 else if (gtk_tree_model_get_iter (dest_model, &dest_iter, prev))
1415 {
1416 GtkTreeIter tmp_iter = dest_iter;
1417
1418 gtk_tree_store_insert_after (dest_store, &dest_iter, NULL,
1419 &tmp_iter);
1420 }
1421
1422 gtk_tree_path_free (prev);
1423
1424 recursive_node_copy (src_store, &src_iter, dest_store, &dest_iter);
1425 count++;
1426
1427 prev = gtk_tree_model_get_path (dest_model, &dest_iter);
1428
1429 if (src_store != dest_store)
1430 continue;
1431
1432 update_path_list_for_insert (rows, prev);
1433 }
1434
1435 gtk_tree_path_free (prev);
1436
1437 g_assert (count == length);
1438
1439 if (src_store == dest_store)
1440 {
1441 MidoriBookmarksTreeStore *tree_store = MIDORI_BOOKMARKS_TREE_STORE(src_store);
1442
1443 g_list_free_full (tree_store->stock_got_rows, (GDestroyNotify) gtk_tree_path_free);
1444 tree_store->stock_got_rows = rows;
1445 }
1446 else
1447 g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
1448 }
1449 }
1450
1451 return status;
1452}
1453
1454static void
1455midori_bookmarks_set_item_positon (GtkTreeModel* model,
1456 GtkTreeIter* iter,
1457 gint64 parentid,
1458 MidoriBookmarks* bookmarks)
1459{
1460 KatzeItem* item;
1461 gint position = 0;
1462 GtkTreeIter next = *iter;
1463
1464 do {
1465 gboolean update = FALSE;
1466 gtk_tree_model_get (model, &next, 0, &item, -1);
1467
1468 if (!KATZE_IS_ITEM (item))
1469 continue;
1470
1471 if (position != katze_item_get_meta_integer (item, "pos_panel"))
1472 {
1473 katze_item_set_meta_integer (item, "pos_panel", position);
1474 update = TRUE;
1475 }
1476 if (parentid != katze_item_get_meta_integer (item, "parentid"))
1477 {
1478 katze_item_set_meta_integer (item, "parentid", parentid);
1479 update = TRUE;
1480 }
1481
1482 if (update)
1483 midori_bookmarks_update_item (bookmarks, item);
1484
1485 position++;
1486
1487 g_object_unref (item);
1488 }
1489 while (gtk_tree_model_iter_next (model, &next));
1490}
1491
1492static void
1493assert_reorder_are_folders (GtkTreeModel* model,
1494 MidoriBookmarks* bookmarks)
1495{
1496 GList* iter;
1497 for (iter = bookmarks->reordered_paths; iter ; iter = g_list_next (iter))
1498 {
1499 GtkTreePath* path = (GtkTreePath*)iter->data;
1500 GtkTreeIter tree_iter;
1501
1502 if (!gtk_tree_path_get_depth (path))
1503 continue;
1504
1505 if (gtk_tree_model_get_iter (model, &tree_iter, path))
1506 {
1507 KatzeItem *item;
1508
1509 gtk_tree_model_get (model, &tree_iter, 0, &item, -1);
1510
1511 g_assert (KATZE_ITEM_IS_FOLDER (item));
1512 }
1513 }
1514}
1515
1516static void
1517add_parent_to_reorder (GtkTreeModel* model,
1518 GtkTreePath* path,
1519 MidoriBookmarks* bookmarks)
1520{
1521 GtkTreePath* path_copy = gtk_tree_path_copy (path);
1522 GList* found;
1523
1524 midori_bookmarks_idle_start (bookmarks);
1525
1526 if (gtk_tree_path_get_depth (path_copy) > 1
1527 && gtk_tree_path_up (path_copy))
1528 {
1529 GtkTreeIter iter;
1530 if (gtk_tree_model_get_iter (model, &iter, path_copy))
1531 {
1532 KatzeItem* item;
1533 gtk_tree_model_get (model, &iter, 0, &item, -1);
1534 if (item)
1535 {
1536 g_assert (KATZE_ITEM_IS_FOLDER (item));
1537 g_object_unref (item);
1538 }
1539 else
1540 g_assert_not_reached ();
1541 }
1542 else
1543 g_assert_not_reached ();
1544 }
1545 else
1546 {
1547 gtk_tree_path_free (path_copy);
1548 path_copy = gtk_tree_path_new ();
1549 }
1550
1551 if ((found = g_list_find_custom (bookmarks->reordered_paths,
1552 path_copy, (GCompareFunc)midori_tree_path_compare)) != NULL)
1553 {
1554 gtk_tree_path_free (path_copy);
1555 return;
1556 }
1557
1558 bookmarks->reordered_paths = g_list_append (bookmarks->reordered_paths, path_copy);
1559}
1560
1561static void
1562midori_bookmarks_row_inserted_cb (GtkTreeModel* model,
1563 GtkTreePath* path,
1564 GtkTreeIter* iter,
1565 MidoriBookmarks* bookmarks)
1566{
1567 midori_bookmarks_idle_start (bookmarks);
1568
1569 update_path_list_for_insert (bookmarks->added_paths, path);
1570 update_path_list_for_insert (bookmarks->reordered_paths, path);
1571 assert_reorder_are_folders (model, bookmarks);
1572
1573 if (g_list_find_custom (bookmarks->added_paths,
1574 path, (GCompareFunc)midori_tree_path_compare))
1575 return;
1576
1577 bookmarks->added_paths = g_list_append (bookmarks->added_paths, gtk_tree_path_copy (path));
1578}
1579
1580#ifdef DEBUG_LIST
1581static void
1582print_path_list (GList* iter)
1583{
1584 for ( ; iter ; iter = g_list_next (iter))
1585 {
1586 gchar* str = gtk_tree_path_to_string ((GtkTreePath*)iter->data);
1587 g_print ("%s ", str);
1588 g_free (str);
1589 }
1590 g_print ("\n");
1591}
1592#endif /* DEBUG_LIST */
1593
1594static void
1595midori_bookmarks_row_deleted_cb (GtkTreeModel* model,
1596 GtkTreePath* path,
1597 MidoriBookmarks* bookmarks)
1598{
1599#ifdef DEBUG_LIST
1600 gchar* str = gtk_tree_path_to_string (path);
1601 g_print ("midori_bookmarks_row_deleted_cb: path: %s\n", str);
1602 g_free (str);
1603#endif /* DEBUG_LIST */
1604
1605 midori_bookmarks_idle_start (bookmarks);
1606
1607 bookmarks->added_paths = update_path_list_for_delete (bookmarks->added_paths, path);
1608#ifdef DEBUG_LIST
1609 print_path_list (bookmarks->reordered_paths);
1610#endif /* DEBUG_LIST */
1611 bookmarks->reordered_paths = update_path_list_for_delete (bookmarks->reordered_paths, path);
1612#ifdef DEBUG_LIST
1613 print_path_list (bookmarks->reordered_paths);
1614#endif /* DEBUG_LIST */
1615 assert_reorder_are_folders (model, bookmarks);
1616 add_parent_to_reorder (model, path, bookmarks);
1617 assert_reorder_are_folders (model, bookmarks);
1618}
4951619
496static void1620static void
497midori_bookmarks_row_changed_cb (GtkTreeModel* model,1621midori_bookmarks_row_changed_cb (GtkTreeModel* model,
@@ -499,41 +1623,8 @@
499 GtkTreeIter* iter,1623 GtkTreeIter* iter,
500 MidoriBookmarks* bookmarks)1624 MidoriBookmarks* bookmarks)
501{1625{
502 KatzeItem* item;1626 add_parent_to_reorder (model, path, bookmarks);
503 GtkTreeIter parent;1627 assert_reorder_are_folders (model, bookmarks);
504 KatzeItem* new_parent = NULL;
505 gint64 parentid;
506
507 gtk_tree_model_get (model, iter, 0, &item, -1);
508
509 if (gtk_tree_model_iter_parent (model, &parent, iter))
510 {
511 gtk_tree_model_get (model, &parent, 0, &new_parent, -1);
512
513 /* Bookmarks must not be moved into non-folder items */
514 if (!KATZE_ITEM_IS_FOLDER (new_parent))
515 parentid = 0;
516 else
517 parentid = katze_item_get_meta_integer (new_parent, "id");
518 }
519 else
520 parentid = 0;
521
522 katze_item_set_meta_integer (item, "parentid", parentid);
523
524 g_signal_handlers_block_by_func (bookmarks->bookmarks_db,
525 midori_bookmarks_update_item_cb,
526 bookmarks);
527
528 midori_bookmarks_db_update_item (bookmarks->bookmarks_db, item);
529
530 g_signal_handlers_unblock_by_func (bookmarks->bookmarks_db,
531 midori_bookmarks_update_item_cb,
532 bookmarks);
533
534 g_object_unref (item);
535 if (new_parent)
536 g_object_unref (new_parent);
537}1628}
5381629
539static void1630static void
@@ -596,7 +1687,7 @@
596 GtkTreeIter iter;1687 GtkTreeIter iter;
5971688
598 if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (bookmarks->treeview),1689 if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (bookmarks->treeview),
599 &model, &iter))1690 &model, &iter))
600 {1691 {
601 KatzeItem* item;1692 KatzeItem* item;
602 MidoriBrowser* browser;1693 MidoriBrowser* browser;
@@ -616,15 +1707,17 @@
616static void1707static void
617midori_bookmarks_toolbar_update (MidoriBookmarks *bookmarks)1708midori_bookmarks_toolbar_update (MidoriBookmarks *bookmarks)
618{1709{
619 gboolean selected;1710 gint selected;
6201711
621 selected = katze_tree_view_get_selected_iter (1712 selected = katze_tree_view_get_selected_rows (
622 GTK_TREE_VIEW (bookmarks->treeview), NULL, NULL);1713 GTK_TREE_VIEW (bookmarks->treeview), NULL, NULL);
623 gtk_widget_set_sensitive (GTK_WIDGET (bookmarks->delete), selected);1714 gtk_widget_set_sensitive (
624 gtk_widget_set_sensitive (GTK_WIDGET (bookmarks->edit), selected);1715 GTK_WIDGET (bookmarks->delete), (selected > 0 ? TRUE : FALSE));
1716 gtk_widget_set_sensitive (
1717 GTK_WIDGET (bookmarks->edit), (selected == 1 ? TRUE : FALSE));
625}1718}
6261719
627static gchar* 1720static gchar*
628midori_bookmarks_statusbar_bookmarks_str (gint count)1721midori_bookmarks_statusbar_bookmarks_str (gint count)
629{1722{
630 if (!count)1723 if (!count)
@@ -634,7 +1727,7 @@
634 return g_strdup_printf (ngettext ("%d bookmark", "%d bookmarks", count), count);1727 return g_strdup_printf (ngettext ("%d bookmark", "%d bookmarks", count), count);
635}1728}
6361729
637static gchar* 1730static gchar*
638midori_bookmarks_statusbar_subfolders_str (gint count)1731midori_bookmarks_statusbar_subfolders_str (gint count)
639{1732{
640 if (!count)1733 if (!count)
@@ -648,78 +1741,141 @@
648midori_bookmarks_statusbar_update (MidoriBookmarks *bookmarks)1741midori_bookmarks_statusbar_update (MidoriBookmarks *bookmarks)
649{1742{
650 gchar* text = NULL;1743 gchar* text = NULL;
6511744 GtkTreeModel* model;
652 if (bookmarks->hovering_item)1745 GList *rows;
653 {1746 gint selected;
654 KatzeItem* item = bookmarks->hovering_item;1747
6551748 selected = katze_tree_view_get_selected_rows (
656 g_assert (!KATZE_ITEM_IS_SEPARATOR (item));1749 GTK_TREE_VIEW (bookmarks->treeview), &model, &rows);
6571750
658 if (KATZE_ITEM_IS_FOLDER (item))1751 if (selected > 1)
1752 {
1753 gint i;
1754 gint selected_folders_count = 0;
1755 gint selected_bookmarks_count = 0;
1756 gchar* selected_folders_str = midori_bookmarks_statusbar_subfolders_str (selected_folders_count);
1757 gchar* selected_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (selected_bookmarks_count);
1758
1759 for (i = 0 ; i < selected ; i++)
1760 {
1761 GtkTreeIter iter;
1762 KatzeItem* item;
1763
1764 if (!gtk_tree_model_get_iter (
1765 model, &iter, (GtkTreePath *)g_list_nth_data (rows, i)))
1766 continue;
1767
1768 gtk_tree_model_get (model, &iter, 0, &item, -1);
1769
1770 g_assert (!KATZE_ITEM_IS_SEPARATOR (item));
1771
1772 if (KATZE_ITEM_IS_FOLDER (item))
1773 {
1774 selected_folders_count++;
1775 }
1776 else
1777 {
1778 selected_bookmarks_count++;
1779 }
1780 }
1781
1782 selected_folders_str = midori_bookmarks_statusbar_subfolders_str (selected_folders_count);
1783 selected_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (selected_bookmarks_count);
1784
1785 if (!selected_bookmarks_count && !selected_folders_count)
1786 g_assert_not_reached ();
1787 else if (!selected_bookmarks_count && (selected_folders_count >= 1))
1788 /* i18n: Selection containing [[n] folder(s)] and no bookmark */
1789 text = g_strdup_printf (_("Selection containing %s and no bookmark"),
1790 selected_folders_str);
1791 else if ((selected_bookmarks_count >= 1) && !selected_folders_count)
1792 /* i18n: Selection containing [[n] bookmark(s)] */
1793 text = g_strdup_printf (_("Selection containing %s"), selected_bookmarks_str);
1794 else if ((selected_bookmarks_count >= 1) && (selected_folders_count >= 1))
1795 /* i18n: Selection containing [[n] bookmark(s)] and [[n] folder(s)] */
1796 text = g_strdup_printf (_("Selection containing %s and %s"),
1797 selected_bookmarks_str, selected_folders_str);
1798
1799 g_free (selected_folders_str);
1800 g_free (selected_bookmarks_str);
1801
1802 g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
1803 }
1804 else
1805 {
1806 if (selected)
1807 g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
1808
1809 if (bookmarks->hovering_item)
1810 {
1811 KatzeItem* item = bookmarks->hovering_item;
1812
1813 if (KATZE_ITEM_IS_FOLDER (item))
1814 {
1815 gint child_folders_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db,
1816 "uri = ''", NULL, item, FALSE);
1817 gint child_bookmarks_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db,
1818 "uri <> ''", NULL, item, FALSE);
1819 gchar* child_folders_str = midori_bookmarks_statusbar_subfolders_str (child_folders_count);
1820 gchar* child_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (child_bookmarks_count);
1821
1822 if (!child_bookmarks_count && !child_folders_count)
1823 /* i18n: Empty folder */
1824 text = g_strdup_printf (_("Empty folder"));
1825 else if (!child_bookmarks_count && (child_folders_count >= 1))
1826 /* i18n: Folder containing [[n] folder(s)] and no bookmark */
1827 text = g_strdup_printf (_("Folder containing %s and no bookmark"),
1828 child_folders_str);
1829 else if ((child_bookmarks_count >= 1) && !child_folders_count)
1830 /* i18n: Folder containing [[n] bookmark(s)] */
1831 text = g_strdup_printf (_("Folder containing %s"), child_bookmarks_str);
1832 else if ((child_bookmarks_count >= 1) && (child_folders_count >= 1))
1833 /* i18n: Folder containing [[n] bookmark(s)] and [[n] folder(s)] */
1834 text = g_strdup_printf (_("Folder containing %s and %s"),
1835 child_bookmarks_str, child_folders_str);
1836
1837 g_free (child_folders_str);
1838 g_free (child_bookmarks_str);
1839 }
1840 else if (KATZE_ITEM_IS_BOOKMARK (item))
1841 {
1842 const gchar* uri = katze_item_get_uri (item);
1843
1844 /* i18n: Bookmark leading to: [bookmark uri] */
1845 text = g_strdup_printf (_("Bookmark leading to: %s"), uri);
1846 }
1847 }
1848 else
659 {1849 {
660 gint child_folders_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db,1850 gint child_folders_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db,
661 "uri = ''", NULL, item, FALSE);1851 "uri = ''", NULL, NULL, FALSE);
662 gint child_bookmarks_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db,1852 gint child_bookmarks_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db,
663 "uri <> ''", NULL, item, FALSE);1853 "uri <> ''", NULL, NULL, FALSE);
664 gchar* child_folders_str = midori_bookmarks_statusbar_subfolders_str (child_folders_count);1854 gchar* child_folders_str = midori_bookmarks_statusbar_subfolders_str (child_folders_count);
665 gchar* child_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (child_bookmarks_count);1855 gchar* child_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (child_bookmarks_count);
6661856
667 if (!child_bookmarks_count && !child_folders_count)1857 if (!child_bookmarks_count && (child_folders_count >= 1))
668 /* i18n: Empty folder */1858 /* i18n: [[n] folder(s)] and no bookmark */
669 text = g_strdup_printf (_("Empty folder"));1859 text = g_strdup_printf (_("%s and no bookmark"),
670 else if (!child_bookmarks_count && (child_folders_count >= 1))
671 /* i18n: Folder containing [[n] folder(s)] and no bookmark */
672 text = g_strdup_printf (_("Folder containing %s and no bookmark"),
673 child_folders_str);1860 child_folders_str);
674 else if ((child_bookmarks_count >= 1) && !child_folders_count)1861 else if ((child_bookmarks_count >= 1) && !child_folders_count)
675 /* i18n: Folder containing [[n] bookmark(s)] */1862 text = g_strdup (child_bookmarks_str);
676 text = g_strdup_printf (_("Folder containing %s"), child_bookmarks_str);
677 else if ((child_bookmarks_count >= 1) && (child_folders_count >= 1))1863 else if ((child_bookmarks_count >= 1) && (child_folders_count >= 1))
678 /* i18n: Folder containing [[n] bookmark(s)] and [[n] folder(s)] */1864 /* i18n: [[n] bookmark(s)] and [[n] folder(s)] */
679 text = g_strdup_printf (_("Folder containing %s and %s"),1865 text = g_strdup_printf (_("%s and %s"),
680 child_bookmarks_str, child_folders_str);1866 child_bookmarks_str, child_folders_str);
6811867
682 g_free (child_folders_str);1868 g_free (child_folders_str);
683 g_free (child_bookmarks_str);1869 g_free (child_bookmarks_str);
684 }1870 }
685 else if (KATZE_ITEM_IS_BOOKMARK (item))
686 {
687 const gchar* uri = katze_item_get_uri (item);
688
689 /* i18n: Bookmark leading to: [bookmark uri] */
690 text = g_strdup_printf (_("Bookmark leading to: %s"), uri);
691 }
692 }
693 else
694 {
695 gint child_folders_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db,
696 "uri = ''", NULL, NULL, FALSE);
697 gint child_bookmarks_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db,
698 "uri <> ''", NULL, NULL, FALSE);
699 gchar* child_folders_str = midori_bookmarks_statusbar_subfolders_str (child_folders_count);
700 gchar* child_bookmarks_str = midori_bookmarks_statusbar_bookmarks_str (child_bookmarks_count);
701
702 if (!child_bookmarks_count && (child_folders_count >= 1))
703 /* i18n: [[n] folder(s)] and no bookmark */
704 text = g_strdup_printf (_("%s and no bookmark"),
705 child_folders_str);
706 else if ((child_bookmarks_count >= 1) && !child_folders_count)
707 text = g_strdup (child_bookmarks_str);
708 else if ((child_bookmarks_count >= 1) && (child_folders_count >= 1))
709 /* i18n: [[n] bookmark(s)] and [[n] folder(s)] */
710 text = g_strdup_printf (_("%s and %s"),
711 child_bookmarks_str, child_folders_str);
712
713 g_free (child_folders_str);
714 g_free (child_bookmarks_str);
715 }1871 }
7161872
717 if (text)1873 if (text)
718 {1874 {
719 MidoriBrowser* browser = midori_browser_get_for_widget (bookmarks->treeview);1875 MidoriBrowser* browser = midori_browser_get_for_widget (bookmarks->treeview);
720 1876
721 g_object_set (browser, "statusbar-text", text, NULL);1877 g_object_set (browser, "statusbar-text", text, NULL);
722 1878
723 g_free(text);1879 g_free(text);
724 }1880 }
725}1881}
@@ -729,19 +1885,33 @@
729 MidoriBookmarks* bookmarks)1885 MidoriBookmarks* bookmarks)
730{1886{
731 GtkTreeModel* model;1887 GtkTreeModel* model;
732 GtkTreeIter iter;1888 GList* rows;
7331889 GList* iter_row;
734 if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (bookmarks->treeview),1890
735 &model, &iter))1891 if (!katze_tree_view_get_selected_rows(GTK_TREE_VIEW (bookmarks->treeview),
1892 &model, &rows))
1893 return;
1894
1895 for (iter_row = rows ; iter_row ; iter_row = g_list_next (iter_row))
736 {1896 {
737 KatzeItem* item;1897 GtkTreeIter iter;
7381898
739 gtk_tree_model_get (model, &iter, 0, &item, -1);1899 if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath *)iter_row->data))
7401900 {
741 midori_bookmarks_db_remove_item (bookmarks->bookmarks_db, item);1901 KatzeItem* item;
7421902
743 g_object_unref (item);1903 gtk_tree_model_get (model, &iter, 0, &item, -1);
1904
1905 if (item)
1906 {
1907 midori_bookmarks_db_remove_item (bookmarks->bookmarks_db, item);
1908
1909 g_object_unref (item);
1910 }
1911 }
744 }1912 }
1913
1914 g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
745}1915}
7461916
747static GtkWidget*1917static GtkWidget*
@@ -759,7 +1929,7 @@
759 toolitem = gtk_tool_button_new_from_stock (STOCK_BOOKMARK_ADD);1929 toolitem = gtk_tool_button_new_from_stock (STOCK_BOOKMARK_ADD);
760 gtk_widget_set_name (GTK_WIDGET (toolitem), "BookmarkAdd");1930 gtk_widget_set_name (GTK_WIDGET (toolitem), "BookmarkAdd");
761 gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),1931 gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),
762 _("Add a new bookmark"));1932 _("Add a new bookmark"));
763 gtk_tool_item_set_is_important (toolitem, TRUE);1933 gtk_tool_item_set_is_important (toolitem, TRUE);
764 g_signal_connect (toolitem, "clicked",1934 g_signal_connect (toolitem, "clicked",
765 G_CALLBACK (midori_bookmarks_add_clicked_cb), bookmarks);1935 G_CALLBACK (midori_bookmarks_add_clicked_cb), bookmarks);
@@ -767,7 +1937,7 @@
767 gtk_widget_show (GTK_WIDGET (toolitem));1937 gtk_widget_show (GTK_WIDGET (toolitem));
768 toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_EDIT);1938 toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_EDIT);
769 gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),1939 gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),
770 _("Edit the selected bookmark"));1940 _("Edit the selected bookmark"));
771 g_signal_connect (toolitem, "clicked",1941 g_signal_connect (toolitem, "clicked",
772 G_CALLBACK (midori_bookmarks_edit_clicked_cb), bookmarks);1942 G_CALLBACK (midori_bookmarks_edit_clicked_cb), bookmarks);
773 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);1943 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
@@ -775,7 +1945,7 @@
775 bookmarks->edit = GTK_WIDGET (toolitem);1945 bookmarks->edit = GTK_WIDGET (toolitem);
776 toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_DELETE);1946 toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_DELETE);
777 gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),1947 gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),
778 _("Delete the selected bookmark"));1948 _("Delete the selected bookmark"));
779 g_signal_connect (toolitem, "clicked",1949 g_signal_connect (toolitem, "clicked",
780 G_CALLBACK (midori_bookmarks_delete_clicked_cb), bookmarks);1950 G_CALLBACK (midori_bookmarks_delete_clicked_cb), bookmarks);
781 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);1951 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
@@ -791,7 +1961,7 @@
791 toolitem = gtk_tool_button_new_from_stock (STOCK_FOLDER_NEW);1961 toolitem = gtk_tool_button_new_from_stock (STOCK_FOLDER_NEW);
792 gtk_widget_set_name (GTK_WIDGET (toolitem), "BookmarkFolderAdd");1962 gtk_widget_set_name (GTK_WIDGET (toolitem), "BookmarkFolderAdd");
793 gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),1963 gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),
794 _("Add a new folder"));1964 _("Add a new folder"));
795 g_signal_connect (toolitem, "clicked",1965 g_signal_connect (toolitem, "clicked",
796 G_CALLBACK (midori_bookmarks_add_clicked_cb), bookmarks);1966 G_CALLBACK (midori_bookmarks_add_clicked_cb), bookmarks);
797 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);1967 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
@@ -841,6 +2011,12 @@
841 G_CALLBACK (midori_bookmarks_remove_item_cb), bookmarks);2011 G_CALLBACK (midori_bookmarks_remove_item_cb), bookmarks);
842 g_signal_connect (bookmarks->bookmarks_db, "update",2012 g_signal_connect (bookmarks->bookmarks_db, "update",
843 G_CALLBACK (midori_bookmarks_update_cb), bookmarks);2013 G_CALLBACK (midori_bookmarks_update_cb), bookmarks);
2014 g_signal_connect_after (model, "row-inserted",
2015 G_CALLBACK (midori_bookmarks_row_inserted_cb),
2016 bookmarks);
2017 g_signal_connect_after (model, "row-deleted",
2018 G_CALLBACK (midori_bookmarks_row_deleted_cb),
2019 bookmarks);
844 g_signal_connect_after (model, "row-changed",2020 g_signal_connect_after (model, "row-changed",
845 G_CALLBACK (midori_bookmarks_row_changed_cb),2021 G_CALLBACK (midori_bookmarks_row_changed_cb),
846 bookmarks);2022 bookmarks);
@@ -856,12 +2032,12 @@
8562032
857 switch (prop_id)2033 switch (prop_id)
858 {2034 {
859 case PROP_APP:2035 case PROP_APP:
860 midori_bookmarks_set_app (bookmarks, g_value_get_object (value));2036 midori_bookmarks_set_app (bookmarks, g_value_get_object (value));
861 break;2037 break;
862 default:2038 default:
863 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);2039 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
864 break;2040 break;
865 }2041 }
866}2042}
8672043
@@ -875,12 +2051,12 @@
8752051
876 switch (prop_id)2052 switch (prop_id)
877 {2053 {
878 case PROP_APP:2054 case PROP_APP:
879 g_value_set_object (value, bookmarks->app);2055 g_value_set_object (value, bookmarks->app);
880 break;2056 break;
881 default:2057 default:
882 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);2058 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
883 break;2059 break;
884 }2060 }
885}2061}
8862062
@@ -918,8 +2094,8 @@
918 if (item && katze_item_get_name (item))2094 if (item && katze_item_get_name (item))
919 {2095 {
920 g_object_set (renderer, "markup", NULL,2096 g_object_set (renderer, "markup", NULL,
921 "ellipsize", PANGO_ELLIPSIZE_END,2097 "ellipsize", PANGO_ELLIPSIZE_END,
922 "text", katze_item_get_name (item), NULL);2098 "text", katze_item_get_name (item), NULL);
923 }2099 }
924 else2100 else
925 g_object_set (renderer, "markup", _("<i>Separator</i>"), NULL);2101 g_object_set (renderer, "markup", _("<i>Separator</i>"), NULL);
@@ -976,7 +2152,7 @@
976 menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL);2152 menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL);
977 if (label)2153 if (label)
978 gtk_label_set_text_with_mnemonic (GTK_LABEL (gtk_bin_get_child (2154 gtk_label_set_text_with_mnemonic (GTK_LABEL (gtk_bin_get_child (
979 GTK_BIN (menuitem))), label);2155 GTK_BIN (menuitem))), label);
980 if (!strcmp (stock_id, GTK_STOCK_EDIT))2156 if (!strcmp (stock_id, GTK_STOCK_EDIT))
981 gtk_widget_set_sensitive (menuitem,2157 gtk_widget_set_sensitive (menuitem,
982 !KATZE_ITEM_IS_SEPARATOR (item));2158 !KATZE_ITEM_IS_SEPARATOR (item));
@@ -1007,39 +2183,103 @@
1007 }2183 }
1008}2184}
10092185
1010static void2186static GtkWidget*
1011midori_bookmarks_open_in_tab_activate_cb (GtkWidget* menuitem,2187midori_bookmarks_open_bookmark_in_tab (KatzeItem *item,
1012 MidoriBookmarks* bookmarks)2188 MidoriBrowser* browser)
1013{2189{
1014 KatzeItem* item;2190 const gchar* uri = katze_item_get_uri (item);
1015 const gchar* uri;2191
10162192 if (!uri || !*uri)
1017 item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem");2193 return NULL;
1018 if (KATZE_ITEM_IS_FOLDER (item))2194
2195 return midori_browser_add_item (browser, item);
2196}
2197
2198static GtkWidget*
2199midori_bookmarks_open_folder_in_tab (gint64 parentid,
2200 MidoriBookmarks* bookmarks,
2201 MidoriBrowser* browser)
2202{
2203 GtkWidget* last_view = NULL;
2204 KatzeArray* array;
2205
2206 array = midori_bookmarks_read_from_db (bookmarks, parentid, NULL);
2207
2208 if (KATZE_IS_ARRAY (array))
1019 {2209 {
1020 KatzeItem* child;2210 KatzeItem* child;
1021 KatzeArray* array;2211
1022
1023 array = midori_bookmarks_read_from_db (bookmarks,
1024 katze_item_get_meta_integer (item, "parentid"), NULL);
1025
1026 g_return_if_fail (KATZE_IS_ARRAY (array));
1027 KATZE_ARRAY_FOREACH_ITEM (child, array)2212 KATZE_ARRAY_FOREACH_ITEM (child, array)
1028 {2213 {
1029 if ((uri = katze_item_get_uri (child)) && *uri)2214 GtkWidget* view = midori_bookmarks_open_bookmark_in_tab (child, browser);
2215 if (view)
2216 last_view = view;
2217 }
2218 }
2219
2220 return last_view;
2221}
2222
2223static void
2224midori_bookmarks_open_in_tab_activate_cb (GtkWidget* menuitem,
2225 MidoriBookmarks* bookmarks)
2226{
2227 GtkWidget* last_view = NULL;
2228 MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks));
2229 GtkTreeModel* model;
2230 GList* rows;
2231 gint length;
2232
2233 length = katze_tree_view_get_selected_rows (GTK_TREE_VIEW (bookmarks->treeview),
2234 &model, &rows);
2235
2236 if (!length)
2237 {
2238 KatzeItem* root = KATZE_ITEM (bookmarks->bookmarks_db);
2239 KatzeItem* item = KATZE_ITEM (g_object_get_data (G_OBJECT (menuitem), "KatzeItem"));
2240
2241 if (item != root)
2242 return;
2243
2244 last_view = midori_bookmarks_open_folder_in_tab (0, bookmarks, browser);
2245 }
2246 else
2247 {
2248 gint i;
2249
2250 for (i = 0 ; i < length; i++)
2251 {
2252 GtkTreeIter iter;
2253
2254 if (gtk_tree_model_get_iter (
2255 model, &iter, (GtkTreePath *)g_list_nth_data (rows, i)))
1030 {2256 {
1031 MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks));2257 GtkWidget* view = NULL;
1032 GtkWidget* view = midori_browser_add_item (browser, child);2258 KatzeItem* item;
1033 midori_browser_set_current_tab_smartly (browser, view);2259
2260 gtk_tree_model_get (model, &iter, 0, &item, -1);
2261
2262 if (KATZE_ITEM_IS_SEPARATOR(item))
2263 continue;
2264
2265 if (KATZE_ITEM_IS_FOLDER (item))
2266 view = midori_bookmarks_open_folder_in_tab (
2267 katze_item_get_meta_integer (item, "id"), bookmarks, browser);
2268 else
2269 view = midori_bookmarks_open_bookmark_in_tab (item, browser);
2270
2271 g_object_unref (item);
2272
2273 if (view)
2274 last_view = view;
1034 }2275 }
1035 }2276 }
1036 }2277
1037 else if ((uri = katze_item_get_uri (item)) && *uri)2278 g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
1038 {2279 }
1039 MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks));2280
1040 GtkWidget* view = midori_browser_add_item (browser, item);2281 if (last_view)
1041 midori_browser_set_current_tab_smartly (browser, view);2282 midori_browser_set_current_tab_smartly (browser, last_view);
1042 }
1043}2283}
10442284
1045static void2285static void
@@ -1067,18 +2307,20 @@
1067 KatzeItem* item,2307 KatzeItem* item,
1068 MidoriBookmarks* bookmarks)2308 MidoriBookmarks* bookmarks)
1069{2309{
2310 KatzeItem* root = KATZE_ITEM (bookmarks->bookmarks_db);
1070 GtkWidget* menu;2311 GtkWidget* menu;
1071 GtkWidget* menuitem;2312 GtkWidget* menuitem;
10722313
1073 menu = gtk_menu_new ();2314 menu = gtk_menu_new ();
1074 if (KATZE_ITEM_IS_FOLDER (item))2315 if ((item == root)
2316 || KATZE_ITEM_IS_FOLDER (item))
1075 {2317 {
1076 gint child_bookmarks_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db,2318 gint child_bookmarks_count = midori_bookmarks_db_count_recursive (bookmarks->bookmarks_db,
1077 "uri <> ''", NULL, item, FALSE);2319 "uri <> ''", NULL, item, FALSE);
10782320
1079 midori_bookmarks_popup_item (menu,2321 midori_bookmarks_popup_item (menu,
1080 STOCK_TAB_NEW, _("Open all in _Tabs"), item, 2322 STOCK_TAB_NEW, _("Open all in _Tabs"), item,
1081 (!child_bookmarks_count ? NULL : midori_bookmarks_open_in_tab_activate_cb), 2323 (!child_bookmarks_count ? NULL : midori_bookmarks_open_in_tab_activate_cb),
1082 bookmarks);2324 bookmarks);
1083 }2325 }
1084 else2326 else
@@ -1094,11 +2336,59 @@
1094 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);2336 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
1095 gtk_widget_show (menuitem);2337 gtk_widget_show (menuitem);
1096 midori_bookmarks_popup_item (menu, GTK_STOCK_EDIT, NULL,2338 midori_bookmarks_popup_item (menu, GTK_STOCK_EDIT, NULL,
1097 item, midori_bookmarks_edit_clicked_cb, bookmarks);2339 item, (item == root) ? NULL : midori_bookmarks_edit_clicked_cb, bookmarks);
1098 midori_bookmarks_popup_item (menu, GTK_STOCK_DELETE, NULL,2340 midori_bookmarks_popup_item (menu, GTK_STOCK_DELETE, NULL,
1099 item, midori_bookmarks_delete_clicked_cb, bookmarks);2341 item, (item == root) ? NULL : midori_bookmarks_delete_clicked_cb, bookmarks);
11002342
1101 katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR);2343 katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR);
2344}
2345
2346static void
2347midori_bookmarks_multi_popup (GtkWidget* widget,
2348 GdkEventButton* event,
2349 MidoriBookmarks* bookmarks,
2350 GtkTreeModel* model,
2351 gint count,
2352 GList* rows)
2353{
2354 GtkWidget* menu;
2355 GtkWidget* menuitem;
2356
2357 menu = gtk_menu_new ();
2358
2359 midori_bookmarks_popup_item (menu,
2360 STOCK_TAB_NEW, _("Open all in _Tabs"),
2361 KATZE_ITEM(bookmarks->bookmarks_db), midori_bookmarks_open_in_tab_activate_cb, bookmarks);
2362 menuitem = gtk_separator_menu_item_new ();
2363 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2364 gtk_widget_show (menuitem);
2365
2366 midori_bookmarks_popup_item (menu, GTK_STOCK_EDIT, NULL,
2367 NULL, NULL, bookmarks);
2368 midori_bookmarks_popup_item (menu, GTK_STOCK_DELETE, NULL,
2369 KATZE_ITEM(bookmarks->bookmarks_db), midori_bookmarks_delete_clicked_cb, bookmarks);
2370
2371 katze_widget_popup (widget, GTK_MENU (menu), event, KATZE_MENU_POSITION_CURSOR);
2372}
2373
2374static gboolean
2375midori_bookmarks_do_block_selection (GtkTreeSelection *selection,
2376 GtkTreeModel *model,
2377 GtkTreePath *path,
2378 gboolean path_currently_selected,
2379 gpointer data)
2380{
2381 return FALSE;
2382}
2383
2384static gboolean
2385midori_bookmarks_do_not_block_selection (GtkTreeSelection *selection,
2386 GtkTreeModel *model,
2387 GtkTreePath *path,
2388 gboolean path_currently_selected,
2389 gpointer data)
2390{
2391 return TRUE;
1102}2392}
11032393
1104static gboolean2394static gboolean
@@ -1109,32 +2399,194 @@
1109 GtkTreeModel* model;2399 GtkTreeModel* model;
1110 GtkTreeIter iter;2400 GtkTreeIter iter;
11112401
1112 if (event->button != 2 && event->button != 3)2402 if (bookmarks->pending_event)
2403 {
2404 GtkTreeView* treeview = GTK_TREE_VIEW(widget);
2405 GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview);
2406 gint x = bookmarks->stock_pending_event.x;
2407 gint y = bookmarks->stock_pending_event.y;
2408
2409 bookmarks->pending_event = NULL;
2410 gtk_tree_selection_set_select_function (
2411 selection, midori_bookmarks_do_not_block_selection, NULL, NULL);
2412
2413 if (x != event->x || y != event->y)
2414 return FALSE;
2415 }
2416
2417 if (event->button == 3)
2418 return TRUE;
2419
2420 if (event->button != 2)
1113 return FALSE;2421 return FALSE;
11142422
1115 if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))2423 if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))
1116 {2424 {
2425 gboolean done = FALSE;
1117 KatzeItem* item;2426 KatzeItem* item;
11182427
1119 gtk_tree_model_get (model, &iter, 0, &item, -1);2428 gtk_tree_model_get (model, &iter, 0, &item, -1);
11202429
1121 if (event->button == 2)2430 if (KATZE_ITEM_IS_BOOKMARK (item))
1122 {2431 {
1123 const gchar* uri;2432 MidoriBrowser* browser = midori_browser_get_for_widget (widget);
1124 if (KATZE_ITEM_IS_BOOKMARK (item) && (uri = katze_item_get_uri (item)) && *uri)2433 GtkWidget* view = midori_bookmarks_open_bookmark_in_tab (
2434 item, browser);
2435
2436 if (widget)
1125 {2437 {
1126 MidoriBrowser* browser = midori_browser_get_for_widget (widget);2438 midori_browser_set_current_tab_smartly (browser, view);
1127 GtkWidget* view = midori_browser_add_uri (browser, uri);2439 done = TRUE;
1128 midori_browser_set_current_tab (browser, view);
1129 }2440 }
1130 }2441 }
1131 else2442
1132 midori_bookmarks_popup (widget, event, item, bookmarks);2443 g_object_unref (item);
11332444
1134 if (item != NULL)2445 return done;
1135 g_object_unref (item);2446 }
1136 return TRUE;2447
1137 }2448 return FALSE;
2449}
2450
2451static gboolean
2452midori_bookmarks_block_selection(GtkWidget* widget,
2453 GdkEventButton* event,
2454 MidoriBookmarks* bookmarks)
2455{
2456 GtkTreeView* treeview = GTK_TREE_VIEW(widget);
2457 GtkTreePath* path;
2458 GtkTreeSelection* selection;
2459 gint cell_x;
2460 gint cell_y;
2461
2462 if (!gtk_tree_view_get_path_at_pos (
2463 treeview, event->x, event->y,
2464 &path, NULL, &cell_x, &cell_y))
2465 return FALSE;
2466
2467 gtk_widget_grab_focus (widget);
2468
2469 selection = gtk_tree_view_get_selection (treeview);
2470
2471 if (gtk_tree_selection_path_is_selected (selection, path)
2472 && !(event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)))
2473 {
2474 bookmarks->pending_event = &bookmarks->stock_pending_event;
2475 bookmarks->stock_pending_event.x = event->x;
2476 bookmarks->stock_pending_event.y = event->y;
2477 gtk_tree_selection_set_select_function (
2478 selection, midori_bookmarks_do_block_selection, NULL, NULL);
2479 }
2480 else
2481 {
2482 bookmarks->pending_event = NULL;
2483 gtk_tree_selection_set_select_function (
2484 selection, midori_bookmarks_do_not_block_selection, NULL, NULL);
2485 }
2486
2487 return FALSE;
2488}
2489
2490static gboolean
2491midori_bookmarks_button_press_event_cb (GtkWidget* widget,
2492 GdkEventButton* event,
2493 MidoriBookmarks* bookmarks)
2494{
2495 GtkTreeView* treeview = GTK_TREE_VIEW(widget);
2496 GtkTreePath* path;
2497 GtkTreeSelection* selection;
2498 GtkTreeModel* model;
2499 gint selected;
2500 GList* rows;
2501 gint cell_x;
2502 gint cell_y;
2503
2504 if (event->button == 1)
2505 return midori_bookmarks_block_selection (widget, event, bookmarks);
2506
2507 if (event->button != 3)
2508 return FALSE;
2509
2510 selection = gtk_tree_view_get_selection (treeview);
2511
2512 if (!gtk_tree_view_get_path_at_pos (
2513 treeview, event->x, event->y,
2514 &path, NULL, &cell_x, &cell_y))
2515 {
2516 /* FIXME: popup opening below treeview
2517 * Rationale: the user is actually in ROOT folder
2518 * we may need to have a non editable, non deletable, ROOT folder popup
2519 * Open all in Tabs
2520 * Separator
2521 * Edit [inactive]
2522 * Delete [inactive]
2523 * Here we just mimic the Files behaviour:
2524 * 1- unselect all
2525 * 2- let popup based on selection process
2526 */
2527
2528 gtk_tree_selection_unselect_all (selection);
2529 }
2530 else if (!gtk_tree_selection_path_is_selected (selection, path))
2531 {
2532 /* Use case: popup opening on item not in selection
2533 * Rationale: the user is addressing a single item not in selection
2534 * we may need a single item popup with callbacks working on the item,
2535 * not the selection.
2536 * Here we just mimic the Files behaviour:
2537 * 1- change the selection to the item the popup is opened on
2538 * 2- let popup based on selection process
2539 */
2540
2541 gtk_tree_selection_unselect_all (selection);
2542 gtk_tree_selection_select_path (selection, path);
2543 }
2544
2545 selected = katze_tree_view_get_selected_rows(GTK_TREE_VIEW (widget), &model, &rows);
2546
2547 if (!selected)
2548 {
2549 KatzeItem* root = KATZE_ITEM (bookmarks->bookmarks_db);
2550
2551 midori_bookmarks_popup (widget, event, root, bookmarks);
2552
2553 return TRUE;
2554 }
2555
2556 if (selected == 1)
2557 {
2558 GtkTreeIter iter;
2559 KatzeItem* item;
2560
2561 if (!gtk_tree_model_get_iter (
2562 model, &iter, (GtkTreePath *)g_list_nth_data (rows, 0)))
2563 {
2564 g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
2565
2566 return FALSE;
2567 }
2568
2569 gtk_tree_model_get (model, &iter, 0, &item, -1);
2570
2571 midori_bookmarks_popup (widget, event, item, bookmarks);
2572
2573 g_object_unref (item);
2574
2575 g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
2576
2577 return TRUE;
2578 }
2579
2580 if (selected > 1)
2581 {
2582 midori_bookmarks_multi_popup (widget, event, bookmarks,
2583 model, selected, rows);
2584
2585 g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
2586
2587 return TRUE;
2588 }
2589
1138 return FALSE;2590 return FALSE;
1139}2591}
11402592
@@ -1165,39 +2617,74 @@
1165 }2617 }
1166}2618}
11672619
1168static void2620static gboolean
1169midori_bookmarks_row_expanded_cb (GtkTreeView* treeview,2621midori_bookmarks_test_expand_row_cb (GtkTreeView* treeview,
1170 GtkTreeIter* iter,2622 GtkTreeIter* iter,
1171 GtkTreePath* path,2623 GtkTreePath* path,
1172 MidoriBookmarks* bookmarks)2624 MidoriBookmarks* bookmarks)
1173{2625{
1174 GtkTreeModel* model;2626 GtkTreeModel* model;
2627 GtkTreeIter child;
1175 KatzeItem* item;2628 KatzeItem* item;
2629 gint64 id;
11762630
1177 model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));2631 model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
2632
1178 gtk_tree_model_get (model, iter, 0, &item, -1);2633 gtk_tree_model_get (model, iter, 0, &item, -1);
2634
2635 g_return_val_if_fail (KATZE_IS_ITEM(item), TRUE);
2636
2637 g_signal_handlers_block_by_func (model,
2638 midori_bookmarks_row_deleted_cb,
2639 bookmarks);
2640
2641 id = katze_item_get_meta_integer (item, "id");
2642
2643 g_object_unref (item);
2644
2645 while (gtk_tree_model_iter_children (model, &child, iter))
2646 gtk_tree_store_remove (GTK_TREE_STORE (model), &child);
2647 /* That's an invisible dummy, so we always have an expander */
2648 gtk_tree_store_insert_with_values (GTK_TREE_STORE (model), &child, iter,
2649 0, 0, NULL, -1);
2650
2651 g_signal_handlers_unblock_by_func (model,
2652 midori_bookmarks_row_deleted_cb,
2653 bookmarks);
2654
1179 midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model),2655 midori_bookmarks_read_from_db_to_model (bookmarks, GTK_TREE_STORE (model),
1180 iter, katze_item_get_meta_integer (item, "id"), NULL);2656 iter, id, NULL);
1181 g_object_unref (item);2657
2658 return FALSE;
1182}2659}
11832660
1184static void2661static void
1185midori_bookmarks_row_collapsed_cb (GtkTreeView *treeview,2662midori_bookmarks_row_collapsed_cb (GtkTreeView *treeview,
1186 GtkTreeIter *parent,2663 GtkTreeIter *parent,
1187 GtkTreePath *path,2664 GtkTreePath *path,
1188 gpointer user_data)2665 MidoriBookmarks* bookmarks)
1189{2666{
1190 GtkTreeModel* model;2667 GtkTreeModel* model;
1191 GtkTreeStore* treestore;2668 GtkTreeStore* treestore;
1192 GtkTreeIter child;2669 GtkTreeIter child;
11932670
1194 model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));2671 model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
2672
2673 g_signal_handlers_block_by_func (model,
2674 midori_bookmarks_row_deleted_cb,
2675 bookmarks);
2676
1195 treestore = GTK_TREE_STORE (model);2677 treestore = GTK_TREE_STORE (model);
1196 while (gtk_tree_model_iter_nth_child (model, &child, parent, 0))2678 while (gtk_tree_model_iter_nth_child (model, &child, parent, 0))
1197 gtk_tree_store_remove (treestore, &child);2679 gtk_tree_store_remove (treestore, &child);
1198 /* That's an invisible dummy, so we always have an expander */2680 /* That's an invisible dummy, so we always have an expander */
1199 gtk_tree_store_insert_with_values (treestore, &child, parent,2681 gtk_tree_store_insert_with_values (treestore, &child, parent,
1200 0, 0, NULL, -1);2682 0, 0, NULL, -1);
2683
2684 g_signal_handlers_block_by_func (model,
2685 midori_bookmarks_row_deleted_cb,
2686 bookmarks);
2687
1201}2688}
12022689
1203static void2690static void
@@ -1205,26 +2692,27 @@
1205 MidoriBookmarks *bookmarks)2692 MidoriBookmarks *bookmarks)
1206{2693{
1207 midori_bookmarks_toolbar_update (bookmarks);2694 midori_bookmarks_toolbar_update (bookmarks);
2695 midori_bookmarks_statusbar_update (bookmarks);
1208}2696}
12092697
1210static KatzeItem*2698static KatzeItem*
1211midori_bookmarks_get_item_at_pos (GtkTreeView *treeview,2699midori_bookmarks_get_item_at_pos (GtkTreeView *treeview,
1212 gint x, gint y)2700 gint x, gint y)
1213{ 2701{
1214 GtkTreeModel* model = gtk_tree_view_get_model (treeview);2702 GtkTreeModel* model = gtk_tree_view_get_model (treeview);
1215 GtkTreePath* path;2703 GtkTreePath* path;
1216 GtkTreeIter iter;2704 GtkTreeIter iter;
1217 KatzeItem* item = NULL;2705 KatzeItem* item = NULL;
12182706
1219 gtk_tree_view_get_path_at_pos (treeview, x, y,2707 gtk_tree_view_get_path_at_pos (treeview, x, y,
1220 &path, NULL, NULL, NULL);2708 &path, NULL, NULL, NULL);
1221 2709
1222 if (!path)2710 if (!path)
1223 return NULL;2711 return NULL;
1224 2712
1225 if (gtk_tree_model_get_iter (model, &iter, path))2713 if (gtk_tree_model_get_iter (model, &iter, path))
1226 gtk_tree_model_get (model, &iter, 0, &item, -1);2714 gtk_tree_model_get (model, &iter, 0, &item, -1);
1227 2715
1228 gtk_tree_path_free (path);2716 gtk_tree_path_free (path);
12292717
1230 return item;2718 return item;
@@ -1296,7 +2784,7 @@
12962784
1297 if (bookmarks->hovering_item)2785 if (bookmarks->hovering_item)
1298 g_object_unref (bookmarks->hovering_item);2786 g_object_unref (bookmarks->hovering_item);
1299 2787
1300 bookmarks->hovering_item = NULL;2788 bookmarks->hovering_item = NULL;
13012789
1302 g_object_set (browser, "statusbar-text", "", NULL);2790 g_object_set (browser, "statusbar-text", "", NULL);
@@ -1337,6 +2825,183 @@
1337 midori_bookmarks_filter_timeout_cb, bookmarks, NULL);2825 midori_bookmarks_filter_timeout_cb, bookmarks, NULL);
1338}2826}
13392827
2828static GtkTargetEntry midori_bookmarks_dnd_target_entries[]=
2829{
2830 {MIDORI_BOOKMARKS_TREE_MODEL_TARGET, GTK_TARGET_SAME_WIDGET, 0},
2831};
2832
2833#define MIDORI_BOOKMARKS_DND_NB_TARGET_ENTRIES \
2834 G_N_ELEMENTS (midori_bookmarks_dnd_target_entries)
2835
2836static guint
2837item_hash (gconstpointer item)
2838{
2839 gint64 id = katze_item_get_meta_integer (KATZE_ITEM (item), "id");
2840 return g_int64_hash (&id);
2841}
2842
2843static gboolean
2844item_equal (gconstpointer item_a, gconstpointer item_b)
2845{
2846 gint64 id_a = katze_item_get_meta_integer (KATZE_ITEM (item_a), "id");
2847 gint64 id_b = katze_item_get_meta_integer (KATZE_ITEM (item_b), "id");
2848 return (id_a == id_b)? TRUE : FALSE;
2849}
2850
2851static gboolean
2852midori_bookmarks_idle_func (gpointer data)
2853{
2854 MidoriBookmarks* bookmarks = MIDORI_BOOKMARKS (data);
2855 GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));
2856 GHashTableIter hash_iter;
2857 gpointer key, value;
2858 GList* list_iter;
2859
2860 /* update remaining additions */
2861 assert_reorder_are_folders (model, bookmarks);
2862 for (list_iter = bookmarks->added_paths; list_iter ; list_iter = g_list_next (list_iter))
2863 {
2864 GtkTreePath* path = (GtkTreePath*)list_iter->data;
2865
2866 add_parent_to_reorder (model, path, bookmarks);
2867 assert_reorder_are_folders (model, bookmarks);
2868 }
2869
2870 g_list_free_full (bookmarks->added_paths, (GDestroyNotify) gtk_tree_path_free);
2871 bookmarks->added_paths = NULL;
2872
2873 /* do actual reordering */
2874 for (list_iter = bookmarks->reordered_paths; list_iter ; list_iter = g_list_next (list_iter))
2875 {
2876 GtkTreeIter local_iter;
2877 GtkTreePath* path = (GtkTreePath*)list_iter->data;
2878
2879 if (gtk_tree_path_get_depth (path))
2880 {
2881 GtkTreeIter parent;
2882
2883 if (gtk_tree_model_get_iter (model, &parent, path))
2884 {
2885 KatzeItem *item;
2886 gint64 id;
2887
2888 gtk_tree_model_get (model, &parent, 0, &item, -1);
2889
2890 g_assert (KATZE_ITEM_IS_FOLDER (item));
2891
2892 id = katze_item_get_meta_integer (item, "id");
2893
2894 if (gtk_tree_model_iter_children (model, &local_iter, &parent))
2895 midori_bookmarks_set_item_positon(model, &local_iter, id, bookmarks);
2896
2897 /* update folder array for menu update */
2898 katze_array_update (KATZE_ARRAY (item));
2899
2900 g_object_unref (item);
2901 }
2902 }
2903 else
2904 {
2905 if (gtk_tree_model_get_iter_first (model, &local_iter))
2906 midori_bookmarks_set_item_positon(model, &local_iter,
2907 katze_item_get_meta_integer (KATZE_ITEM (bookmarks->bookmarks_db), "id"),
2908 bookmarks);
2909
2910 g_signal_handlers_block_by_func (bookmarks->bookmarks_db,
2911 midori_bookmarks_update_cb,
2912 bookmarks);
2913
2914 /* update folder array for menu update */
2915 katze_array_update (KATZE_ARRAY (bookmarks->bookmarks_db));
2916
2917 g_signal_handlers_unblock_by_func (bookmarks->bookmarks_db,
2918 midori_bookmarks_update_cb,
2919 bookmarks);
2920 }
2921 }
2922
2923 g_list_free_full (bookmarks->reordered_paths, (GDestroyNotify) gtk_tree_path_free);
2924 bookmarks->reordered_paths = NULL;
2925
2926 /* then finalize updates */
2927 g_signal_handlers_block_by_func (bookmarks->bookmarks_db,
2928 midori_bookmarks_update_item_cb,
2929 bookmarks);
2930
2931 g_hash_table_iter_init (&hash_iter, bookmarks->updated_items);
2932
2933 while (g_hash_table_iter_next (&hash_iter, &key, &value))
2934 {
2935 midori_bookmarks_db_update_item (bookmarks->bookmarks_db, KATZE_ITEM (value));
2936 g_object_unref (value);
2937 }
2938
2939 g_signal_handlers_unblock_by_func (bookmarks->bookmarks_db,
2940 midori_bookmarks_update_item_cb,
2941 bookmarks);
2942
2943 g_hash_table_remove_all (bookmarks->updated_items);
2944
2945 /* process pending additions of inserted bookmarks */
2946 for (list_iter = bookmarks->pending_inserts; list_iter; list_iter = g_list_next (list_iter))
2947 {
2948 KatzeItem *item = KATZE_ITEM (list_iter->data);
2949
2950 midori_bookmarks_add_item (item, bookmarks);
2951
2952 g_object_unref (item);
2953 }
2954
2955 g_list_free (bookmarks->pending_inserts);
2956 bookmarks->pending_inserts = NULL;
2957 return midori_bookmarks_idle_pending (bookmarks);
2958}
2959
2960static void
2961midori_bookmarks_update_item (MidoriBookmarks* bookmarks, KatzeItem *item)
2962{
2963 midori_bookmarks_idle_start (bookmarks);
2964
2965 if (g_hash_table_lookup (bookmarks->updated_items, item))
2966 return;
2967
2968 g_object_ref (item);
2969 g_hash_table_insert (bookmarks->updated_items, item, item);
2970}
2971
2972static void
2973midori_bookmarks_idle_remove_item (MidoriBookmarks* bookmarks, KatzeItem *item)
2974{
2975 gpointer found;
2976
2977 if (KATZE_ITEM_IS_FOLDER (item))
2978 {
2979 gint64 id = katze_item_get_meta_integer (item, "id");
2980 GHashTableIter iter;
2981 gpointer key, value;
2982
2983 g_hash_table_iter_init (&iter, bookmarks->updated_items);
2984
2985 while (g_hash_table_iter_next (&iter, &key, &value))
2986 {
2987 KatzeItem *hash_item = KATZE_ITEM(key);
2988
2989 gint64 parentid = katze_item_get_meta_integer (hash_item, "parentid");
2990 if (parentid == id)
2991 {
2992 g_hash_table_iter_remove (&iter);
2993 g_object_unref (hash_item);
2994 }
2995 }
2996 }
2997
2998 if ((found = g_hash_table_lookup (bookmarks->updated_items, item)) != NULL)
2999 {
3000 g_hash_table_remove (bookmarks->updated_items, found);
3001 g_object_unref (found);
3002 }
3003}
3004
1340static void3005static void
1341midori_bookmarks_init (MidoriBookmarks* bookmarks)3006midori_bookmarks_init (MidoriBookmarks* bookmarks)
1342{3007{
@@ -1349,6 +3014,8 @@
1349 GtkCellRenderer* renderer_text;3014 GtkCellRenderer* renderer_text;
1350 GtkTreeSelection* selection;3015 GtkTreeSelection* selection;
13513016
3017 bookmarks->pending_event = NULL;
3018
1352 /* Create the filter entry */3019 /* Create the filter entry */
1353 entry = sokoke_search_entry_new (_("Search Bookmarks"));3020 entry = sokoke_search_entry_new (_("Search Bookmarks"));
1354 g_signal_connect_after (entry, "changed",3021 g_signal_connect_after (entry, "changed",
@@ -1359,7 +3026,7 @@
1359 gtk_box_pack_start (GTK_BOX (bookmarks), box, FALSE, FALSE, 5);3026 gtk_box_pack_start (GTK_BOX (bookmarks), box, FALSE, FALSE, 5);
13603027
1361 /* Create the treeview */3028 /* Create the treeview */
1362 model = gtk_tree_store_new (2, KATZE_TYPE_ITEM, G_TYPE_STRING);3029 model = midori_bookmarks_tree_store_new (2, KATZE_TYPE_ITEM, G_TYPE_STRING);
1363 treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));3030 treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
1364 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);3031 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
1365 gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (treeview), 1);3032 gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (treeview), 1);
@@ -1376,19 +3043,32 @@
1376 (GtkTreeCellDataFunc)midori_bookmarks_treeview_render_text_cb,3043 (GtkTreeCellDataFunc)midori_bookmarks_treeview_render_text_cb,
1377 treeview, NULL);3044 treeview, NULL);
1378 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);3045 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1379 gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), TRUE);3046 gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), FALSE);
3047 gtk_tree_view_enable_model_drag_source (
3048 GTK_TREE_VIEW (treeview),
3049 GDK_BUTTON1_MASK,
3050 midori_bookmarks_dnd_target_entries,
3051 MIDORI_BOOKMARKS_DND_NB_TARGET_ENTRIES,
3052 GDK_ACTION_MOVE|GDK_ACTION_LINK);
3053 gtk_tree_view_enable_model_drag_dest (
3054 GTK_TREE_VIEW (treeview),
3055 midori_bookmarks_dnd_target_entries,
3056 MIDORI_BOOKMARKS_DND_NB_TARGET_ENTRIES,
3057 GDK_ACTION_MOVE|GDK_ACTION_LINK);
1380 g_object_unref (model);3058 g_object_unref (model);
1381 g_object_connect (treeview,3059 g_object_connect (treeview,
1382 "signal::row-activated",3060 "signal::row-activated",
1383 midori_bookmarks_row_activated_cb, bookmarks,3061 midori_bookmarks_row_activated_cb, bookmarks,
3062 "signal::button-press-event",
3063 midori_bookmarks_button_press_event_cb, bookmarks,
1384 "signal::button-release-event",3064 "signal::button-release-event",
1385 midori_bookmarks_button_release_event_cb, bookmarks,3065 midori_bookmarks_button_release_event_cb, bookmarks,
1386 "signal::key-release-event",3066 "signal::key-release-event",
1387 midori_bookmarks_key_release_event_cb, bookmarks,3067 midori_bookmarks_key_release_event_cb, bookmarks,
1388 "signal::popup-menu",3068 "signal::popup-menu",
1389 midori_bookmarks_popup_menu_cb, bookmarks,3069 midori_bookmarks_popup_menu_cb, bookmarks,
1390 "signal::row-expanded",3070 "signal::test-expand-row",
1391 midori_bookmarks_row_expanded_cb, bookmarks,3071 midori_bookmarks_test_expand_row_cb, bookmarks,
1392 "signal::row-collapsed",3072 "signal::row-collapsed",
1393 midori_bookmarks_row_collapsed_cb, bookmarks,3073 midori_bookmarks_row_collapsed_cb, bookmarks,
1394 "signal::enter-notify-event",3074 "signal::enter-notify-event",
@@ -1398,18 +3078,27 @@
1398 "signal::leave-notify-event",3078 "signal::leave-notify-event",
1399 midori_bookmarks_leave_notify_event_cb, bookmarks,3079 midori_bookmarks_leave_notify_event_cb, bookmarks,
1400 NULL);3080 NULL);
1401 gtk_widget_add_events (GTK_WIDGET (treeview), 3081
1402 GDK_POINTER_MOTION_MASK3082 MIDORI_BOOKMARKS_TREE_STORE (model)->_view = GTK_TREE_VIEW (treeview);
1403 | GDK_POINTER_MOTION_HINT_MASK);3083
3084 gtk_widget_add_events (GTK_WIDGET (treeview),
3085 GDK_POINTER_MOTION_MASK
3086 | GDK_POINTER_MOTION_HINT_MASK);
14043087
1405 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));3088 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
3089 gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
1406 g_signal_connect_after (selection, "changed",3090 g_signal_connect_after (selection, "changed",
1407 G_CALLBACK (midori_bookmarks_selection_changed_cb),3091 G_CALLBACK (midori_bookmarks_selection_changed_cb),
1408 bookmarks);3092 bookmarks);
1409 gtk_widget_show (treeview);3093 gtk_widget_show (treeview);
1410 gtk_box_pack_start (GTK_BOX (bookmarks), treeview, TRUE, TRUE, 0);3094 gtk_box_pack_start (GTK_BOX (bookmarks), treeview, TRUE, TRUE, 0);
1411 bookmarks->treeview = treeview;3095 bookmarks->treeview = treeview;
3096 bookmarks->pending_inserts = NULL;
1412 bookmarks->hovering_item = NULL;3097 bookmarks->hovering_item = NULL;
3098 bookmarks->pending_inserts = NULL;
3099 bookmarks->updated_items = g_hash_table_new (item_hash, item_equal);
3100 bookmarks->added_paths = NULL;
3101 bookmarks->reordered_paths = NULL;
1413}3102}
14143103
1415static void3104static void
@@ -1420,5 +3109,16 @@
1420 if (bookmarks->app)3109 if (bookmarks->app)
1421 g_object_unref (bookmarks->app);3110 g_object_unref (bookmarks->app);
1422 if (bookmarks->hovering_item)3111 if (bookmarks->hovering_item)
1423 g_object_unref (bookmarks->hovering_item);3112 g_object_unref (bookmarks->hovering_item);
3113
3114 if (g_idle_remove_by_data (bookmarks))
3115 {
3116 g_list_free_full (bookmarks->pending_inserts, (GDestroyNotify) g_object_unref);
3117 bookmarks->pending_inserts = NULL;
3118 g_hash_table_unref (bookmarks->updated_items);
3119 g_list_free_full (bookmarks->added_paths, (GDestroyNotify) gtk_tree_path_free);
3120 bookmarks->added_paths = NULL;
3121 g_list_free_full (bookmarks->reordered_paths, (GDestroyNotify) gtk_tree_path_free);
3122 bookmarks->reordered_paths = NULL;
3123 }
1424}3124}
14253125
=== modified file 'tests/bookmarks.c'
--- tests/bookmarks.c 2013-08-05 19:52:52 +0000
+++ tests/bookmarks.c 2014-01-30 21:24:26 +0000
@@ -128,7 +128,7 @@
128 }128 }
129129
130 db_items = midori_bookmarks_db_query_recursive (db_bookmarks,130 db_items = midori_bookmarks_db_query_recursive (db_bookmarks,
131 "*", "title='%q'", katze_item_get_name (test_item), FALSE);131 "*", "title='%q'", katze_item_get_name (test_item), NULL, FALSE);
132132
133 /* FIXME g_assert_cmpint (katze_array_get_length (db_items), ==, 1); */133 /* FIXME g_assert_cmpint (katze_array_get_length (db_items), ==, 1); */
134 db_item = katze_array_get_nth_item (db_items, 0);134 db_item = katze_array_get_nth_item (db_items, 0);

Subscribers

People subscribed via source and target branches

to all changes: