dee

Merge lp:~mhr3/dee/introspectable-sort-methods into lp:dee

Proposed by Michal Hruby
Status: Merged
Approved by: Paweł Stołowski
Approved revision: 376
Merged at revision: 376
Proposed branch: lp:~mhr3/dee/introspectable-sort-methods
Merge into: lp:dee
Diff against target: 418 lines (+289/-6)
5 files modified
bindings/python/Dee.py (+20/-1)
src/dee-model.c (+98/-0)
src/dee-model.h (+37/-5)
tests/test-model-rows.c (+130/-0)
vapi/dee-1.0.vapi (+4/-0)
To merge this branch: bzr merge lp:~mhr3/dee/introspectable-sort-methods
Reviewer Review Type Date Requested Status
Paweł Stołowski (community) Approve
Review via email: mp+118801@code.launchpad.net

Commit message

Make the *sorted methods usable with introspection

Description of the change

Dee's find_sorted and insert_sorted were not usable from introspectable languages.

Added a delegate that's introspection friendly and tests that make sure it's working.

To post a comment you must log in.
Revision history for this message
Paweł Stołowski (stolowski) wrote :

Looks, good. Just one question:
30 + # FIXME: perhaps override __eq__ on ModelIter?
is this still applicable?

review: Needs Information
376. By Michal Hruby

Remove fixed FIXME

Revision history for this message
Michal Hruby (mhr3) wrote :

> Looks, good. Just one question:
> 30 + # FIXME: perhaps override __eq__ on ModelIter?
> is this still applicable?

Right, already fixed.

Revision history for this message
Paweł Stołowski (stolowski) wrote :

Looks good, tests pass.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bindings/python/Dee.py'
2--- bindings/python/Dee.py 2012-06-27 15:36:53 +0000
3+++ bindings/python/Dee.py 2012-08-15 13:38:19 +0000
4@@ -63,14 +63,20 @@
5 def insert_before (self, iter, *args):
6 return self.insert_row_before (iter, self._build_row(args))
7
8+ def insert_row_sorted (self, row_spec, sort_func, data):
9+ return self.insert_row_sorted_with_sizes (row_spec, sort_func, data)
10+
11 def insert_sorted (self, sort_func, *args):
12 return self.insert_row_sorted (self._build_row(args), sort_func, None)
13
14+ def find_row_sorted (self, row_spec, sort_func, data):
15+ return self.find_row_sorted_with_sizes (row_spec, sort_func, data)
16+
17 def find_sorted (self, sort_func, *args):
18 return self.find_row_sorted (self._build_row(args), sort_func, None)
19
20 def get_schema (self):
21- return Dee.Model.get_schema(self)[0]
22+ return Dee.Model.get_schema(self)
23
24 def get_value (self, itr, column):
25 return Dee.Model.get_value (self, itr, column).unpack()
26@@ -108,8 +114,21 @@
27 return self.get_n_rows()
28
29
30+class ModelIter(Dee.ModelIter):
31+
32+ def __init__(self):
33+ Dee.ModelIter.__init__(self)
34+
35+ def __eq__ (self, other):
36+ if not isinstance (other, ModelIter):
37+ return False
38+ return repr(self) == repr(other)
39+
40+
41
42 Model = override(Model)
43 __all__.append('Model')
44+ModelIter = override(ModelIter)
45+__all__.append('ModelIter')
46
47
48
49=== modified file 'src/dee-model.c'
50--- src/dee-model.c 2012-02-28 00:36:16 +0000
51+++ src/dee-model.c 2012-08-15 13:38:19 +0000
52@@ -975,6 +975,20 @@
53 return (* iface->insert_row_before) (self, iter, row_members);
54 }
55
56+/* Translates DeeCompareRowFunc callback into DeeCompareRowSizedFunc */
57+static gint
58+dee_model_cmp_func_translate_func (GVariant **row1,
59+ GVariant **row2,
60+ gpointer data)
61+{
62+ gpointer *all_data = (gpointer*) data;
63+ DeeCompareRowSizedFunc cmp_func = (DeeCompareRowSizedFunc) all_data[0];
64+ gpointer user_data = all_data[1];
65+ guint array_length = GPOINTER_TO_UINT (all_data[2]);
66+
67+ return cmp_func (row1, array_length, row2, array_length, user_data);
68+}
69+
70 /**
71 * dee_model_insert_row_sorted:
72 * @self: The model to do a sorted insert on
73@@ -1009,6 +1023,41 @@
74 }
75
76 /**
77+ * dee_model_insert_row_sorted_with_sizes:
78+ * @self: The model to do a sorted insert on
79+ * @row_members: (array zero-terminated=1): An array of
80+ * #GVariants with type signature matching those of the
81+ * column schemas of @self. If any of the variants have floating
82+ * references they will be consumed.
83+ * @cmp_func: (scope call): Callback used for comparison or rows
84+ * @user_data: (closure): Arbitrary pointer passed to @cmp_func during search
85+ *
86+ * Inserts a row in @self according to the sorting specified by @cmp_func.
87+ * If you use this method for insertion you should not use other methods as this
88+ * method assumes the model to be already sorted by @cmp_func.
89+ *
90+ * Returns: (transfer none) (type Dee.ModelIter): A #DeeModelIter pointing to the new row
91+ */
92+DeeModelIter*
93+dee_model_insert_row_sorted_with_sizes (DeeModel *self,
94+ GVariant **row_members,
95+ DeeCompareRowSizedFunc cmp_func,
96+ gpointer user_data)
97+{
98+ gpointer all_data[3];
99+
100+ g_return_val_if_fail (DEE_IS_MODEL (self), NULL);
101+
102+ all_data[0] = cmp_func;
103+ all_data[1] = user_data;
104+ all_data[2] = GUINT_TO_POINTER (dee_model_get_n_columns (self));
105+
106+ return dee_model_insert_row_sorted (self, row_members,
107+ dee_model_cmp_func_translate_func,
108+ all_data);
109+}
110+
111+/**
112 * dee_model_insert_sorted:
113 * @self: The model to do a sorted insert on
114 * @cmp_func: (scope call): Callback used for comparison or rows
115@@ -1103,6 +1152,55 @@
116 }
117
118 /**
119+ * dee_model_find_row_sorted_with_sizes:
120+ * @self: The model to search
121+ * @row_spec: (array zero-terminated=1): An array of
122+ * #GVariants with type signature matching those of the
123+ * column schemas of @self. No references will be taken on the variants.
124+ * @cmp_func: (scope call): Callback used for comparison or rows
125+ * @user_data: (closure): Arbitrary pointer passed to @cmp_func during search
126+ * @out_was_found: (out): A place to store a boolean value that will be set when
127+ * this method returns. If %TRUE then an exact match was found.
128+ * If %FALSE then the returned iter points to a row just after
129+ * where @row_spec would have been inserted.
130+ * Pass %NULL to ignore.
131+ *
132+ * Like dee_model_find_row_sorted(), but uses DeeCompareRowSizedFunc and
133+ * therefore doesn't cause trouble when used from introspected languages.
134+ *
135+ * Finds a row in @self according to the sorting specified by @cmp_func.
136+ * This method will assume that @self is already sorted by @cmp_func.
137+ *
138+ * If you use this method for searching you should only use
139+ * dee_model_insert_row_sorted() (or dee_model_insert_row_sorted_with_sizes())
140+ * to insert rows in the model.
141+ *
142+ * Returns: (transfer none) (type Dee.ModelIter): If @out_was_found is set to
143+ * %TRUE then a #DeeModelIter pointing to the first matching row.
144+ * If it is %FALSE then the iter pointing to the row just after where
145+ * @row_spec_would have been inserted.
146+ */
147+DeeModelIter*
148+dee_model_find_row_sorted_with_sizes (DeeModel *self,
149+ GVariant **row_spec,
150+ DeeCompareRowSizedFunc cmp_func,
151+ gpointer user_data,
152+ gboolean *out_was_found)
153+{
154+ gpointer all_data[3];
155+
156+ g_return_val_if_fail (DEE_IS_MODEL (self), NULL);
157+
158+ all_data[0] = cmp_func;
159+ all_data[1] = user_data;
160+ all_data[2] = GUINT_TO_POINTER (dee_model_get_n_columns (self));
161+
162+ return dee_model_find_row_sorted (self, row_spec,
163+ dee_model_cmp_func_translate_func,
164+ all_data, out_was_found);
165+}
166+
167+/**
168 * dee_model_find_sorted:
169 * @self: The model to search
170 * @cmp_func: (scope call): Callback used for comparison or rows
171
172=== modified file 'src/dee-model.h'
173--- src/dee-model.h 2012-03-19 11:18:50 +0000
174+++ src/dee-model.h 2012-08-15 13:38:19 +0000
175@@ -78,6 +78,27 @@
176 GVariant** row2,
177 gpointer user_data);
178
179+/**
180+ * DeeCompareRowSizedFunc:
181+ * @row1: (array length=row1_length): Row data
182+ * @row1_length: The number of elements in row1 array
183+ * @row2: (array length=row2_length): Row data to compare with
184+ * @row2_length: The number of elements in row2 array
185+ * @user_data: (closure): User data passed to comparison function
186+ *
187+ * Compares @row1 and @row2. Mainly used with
188+ * dee_model_insert_row_sorted_with_sizes() and
189+ * dee_model_find_row_sorted_with_sizes().
190+ *
191+ * Returns: -1, 0, or 1 if @row1 is respectively less than, equal, or greater
192+ * than @row2.
193+ */
194+typedef gint (*DeeCompareRowSizedFunc) (GVariant** row1,
195+ guint row1_length,
196+ GVariant** row2,
197+ guint row2_length,
198+ gpointer user_data);
199+
200 struct _DeeModelIface
201 {
202 GTypeInterface g_iface;
203@@ -291,6 +312,11 @@
204 DeeCompareRowFunc cmp_func,
205 gpointer user_data);
206
207+DeeModelIter* dee_model_insert_row_sorted_with_sizes (DeeModel *self,
208+ GVariant **row_members,
209+ DeeCompareRowSizedFunc cmp_func,
210+ gpointer user_data);
211+
212 DeeModelIter* dee_model_insert_sorted (DeeModel *self,
213 DeeCompareRowFunc cmp_func,
214 gpointer user_data,
215@@ -302,11 +328,17 @@
216 gpointer user_data,
217 gboolean *out_was_found);
218
219-DeeModelIter* dee_model_find_sorted (DeeModel *self,
220- DeeCompareRowFunc cmp_func,
221- gpointer user_data,
222- gboolean *out_was_found,
223- ...);
224+DeeModelIter* dee_model_find_row_sorted_with_sizes (DeeModel *self,
225+ GVariant **row_spec,
226+ DeeCompareRowSizedFunc cmp_func,
227+ gpointer user_data,
228+ gboolean *out_was_found);
229+
230+DeeModelIter* dee_model_find_sorted (DeeModel *self,
231+ DeeCompareRowFunc cmp_func,
232+ gpointer user_data,
233+ gboolean *out_was_found,
234+ ...);
235
236 void dee_model_remove (DeeModel *self,
237 DeeModelIter *iter);
238
239=== modified file 'tests/test-model-rows.c'
240--- tests/test-model-rows.c 2012-01-26 19:08:42 +0000
241+++ tests/test-model-rows.c 2012-08-15 13:38:19 +0000
242@@ -47,6 +47,7 @@
243 static void test_iter_backwards (RowsFixture *fix, gconstpointer data);
244 static void test_illegal_access (RowsFixture *fix, gconstpointer data);
245 static void test_sorted (RowsFixture *fix, gconstpointer data);
246+static void test_sorted_with_sizes (RowsFixture *fix, gconstpointer data);
247
248 static void test_model_iter_copy (RowsFixture *fix, gconstpointer data);
249 static void test_model_iter_free (RowsFixture *fix, gconstpointer data);
250@@ -133,6 +134,13 @@
251 proxy_rows_setup, test_sorted, proxy_rows_teardown);
252 g_test_add (TXN_DOMAIN"/Sorted", RowsFixture, 0,
253 txn_rows_setup, test_sorted, txn_rows_teardown);
254+
255+ g_test_add (SEQ_DOMAIN"/Sorted/WithSizes", RowsFixture, 0,
256+ seq_rows_setup, test_sorted_with_sizes, seq_rows_teardown);
257+ g_test_add (PROXY_DOMAIN"/Sorted/WithSizes", RowsFixture, 0,
258+ proxy_rows_setup, test_sorted_with_sizes, proxy_rows_teardown);
259+ g_test_add (TXN_DOMAIN"/Sorted/WithSizes", RowsFixture, 0,
260+ txn_rows_setup, test_sorted_with_sizes, txn_rows_teardown);
261 }
262
263 static void
264@@ -560,3 +568,125 @@
265 g_assert (was_found);
266 g_assert (result == hter);
267 }
268+
269+static gint
270+sized_cmp_col_0 (GVariant **row1, guint row1_length,
271+ GVariant **row2, guint row2_length, gpointer user_data)
272+{
273+ g_assert_cmpstr (user_data, ==, "test-user-data");
274+ g_assert_cmpuint (row1_length, ==, 2);
275+ g_assert_cmpuint (row2_length, ==, 2);
276+ g_assert_cmpuint (row1_length, ==, row2_length);
277+ return g_variant_get_int32 (row2[0]) - g_variant_get_int32 (row1[0]);
278+}
279+
280+static void
281+test_sorted_with_sizes (RowsFixture *fix, gconstpointer data)
282+{
283+ DeeModelIter *hter, *iter, *jter, *kter;
284+ gboolean was_found;
285+ GVariant *row_spec[2];
286+
287+ /* FINAL MODEL: [(28,s), (27,s), (26,s), (25,s)]
288+ * ~= [hter, iter, jter, kter] */
289+
290+ row_spec[0] = g_variant_new_int32 (0);
291+ row_spec[1] = g_variant_new_string ("");
292+ /* Test find() with an empty model. With NULL was_found arg */
293+ iter = dee_model_find_row_sorted_with_sizes (fix->model, row_spec,
294+ sized_cmp_col_0,
295+ "test-user-data",
296+ NULL);
297+ g_assert (iter == dee_model_get_last_iter (fix->model));
298+
299+ /* Test find() with an empty model. With non-NULL was_found arg */
300+ was_found = TRUE;
301+ iter = dee_model_find_row_sorted_with_sizes (fix->model, row_spec,
302+ sized_cmp_col_0,
303+ "test-user-data",
304+ &was_found);
305+ g_assert (!was_found);
306+ g_assert (iter == dee_model_get_last_iter (fix->model));
307+
308+ /* Insert the first row */
309+ row_spec[0] = g_variant_new_int32 (27);
310+ row_spec[1] = g_variant_new_string ("Sorta sorted");
311+ iter = dee_model_insert_row_sorted_with_sizes (fix->model, row_spec,
312+ sized_cmp_col_0,
313+ "test-user-data");
314+ g_assert (iter != dee_model_get_last_iter (fix->model));
315+ g_assert (iter == dee_model_get_first_iter (fix->model));
316+
317+ /* Test append */
318+ row_spec[0] = g_variant_new_int32 (25);
319+ row_spec[1] = g_variant_new_string ("Sorta sorted");
320+ kter = dee_model_insert_row_sorted_with_sizes (fix->model, row_spec,
321+ sized_cmp_col_0,
322+ "test-user-data");
323+ g_assert (kter != dee_model_get_last_iter (fix->model));
324+ g_assert (kter != dee_model_get_first_iter (fix->model));
325+ g_assert (iter == dee_model_get_first_iter (fix->model));
326+ g_assert (kter != iter);
327+
328+ g_assert_cmpint (2, ==, dee_model_get_n_rows (fix->model));
329+ g_assert (kter == dee_model_next (fix->model, iter));
330+
331+ /* Test insert in between rows */
332+ row_spec[0] = g_variant_new_int32 (26);
333+ row_spec[1] = g_variant_new_string ("Sorta sorted");
334+ jter = dee_model_insert_row_sorted_with_sizes (fix->model, row_spec,
335+ sized_cmp_col_0,
336+ "test-user-data");
337+ g_assert (jter != dee_model_get_last_iter (fix->model));
338+ g_assert (jter != dee_model_get_first_iter (fix->model));
339+ g_assert (iter == dee_model_get_first_iter (fix->model));
340+ g_assert (jter != iter);
341+ g_assert (jter != kter);
342+
343+ g_assert (jter == dee_model_next (fix->model, iter));
344+ g_assert (kter == dee_model_next (fix->model, jter));
345+ g_assert (dee_model_get_last_iter (fix->model) == dee_model_next (fix->model, kter));
346+
347+ /* Test prepend */
348+ row_spec[0] = g_variant_new_int32 (28);
349+ row_spec[1] = g_variant_new_string ("Sorta sorted");
350+ hter = dee_model_insert_row_sorted_with_sizes (fix->model, row_spec,
351+ sized_cmp_col_0,
352+ "test-user-data");
353+ g_assert (hter == dee_model_get_first_iter (fix->model));
354+ g_assert (iter == dee_model_next (fix->model, hter));
355+
356+ g_assert_cmpint (4, ==, dee_model_get_n_rows (fix->model));
357+
358+ /* Test find() again now that we have data in the model */
359+ DeeModelIter *result;
360+ row_spec[0] = g_variant_new_int32 (24);
361+ row_spec[1] = g_variant_new_string ("");
362+ result = dee_model_find_row_sorted_with_sizes (fix->model, row_spec,
363+ sized_cmp_col_0,
364+ "test-user-data", NULL);
365+ g_assert (result == dee_model_get_last_iter (fix->model));
366+ row_spec[0] = g_variant_new_int32 (28);
367+ row_spec[1] = g_variant_new_string ("");
368+ result = dee_model_find_row_sorted_with_sizes (fix->model, row_spec,
369+ sized_cmp_col_0,
370+ "test-user-data", NULL);
371+ g_assert (result == hter);
372+
373+ /* Test find(). With non-NULL was_found arg */
374+ was_found = FALSE;
375+ row_spec[0] = g_variant_new_int32 (24);
376+ row_spec[1] = g_variant_new_string ("");
377+ result = dee_model_find_row_sorted_with_sizes (fix->model, row_spec,
378+ sized_cmp_col_0,
379+ "test-user-data", &was_found);
380+ g_assert (result == dee_model_get_last_iter (fix->model));
381+ row_spec[0] = g_variant_new_int32 (28);
382+ row_spec[1] = g_variant_new_string ("");
383+ result = dee_model_find_row_sorted_with_sizes (fix->model, row_spec,
384+ sized_cmp_col_0,
385+ "test-user-data", &was_found);
386+ g_assert (was_found);
387+ g_assert (result == hter);
388+}
389+
390
391=== modified file 'vapi/dee-1.0.vapi'
392--- vapi/dee-1.0.vapi 2012-03-19 11:18:50 +0000
393+++ vapi/dee-1.0.vapi 2012-08-15 13:38:19 +0000
394@@ -208,6 +208,7 @@
395 public abstract unowned Dee.ModelIter append_row ([CCode (array_length = false, array_null_terminated = true)] GLib.Variant[] row_members);
396 public abstract void clear ();
397 public abstract unowned Dee.ModelIter find_row_sorted ([CCode (array_length = false, array_null_terminated = true)] GLib.Variant[] row_spec, [CCode (delegate_target_pos = 2.5)] Dee.CompareRowFunc cmp_func, out bool out_was_found);
398+ public unowned Dee.ModelIter find_row_sorted_with_sizes ([CCode (array_length = false, array_null_terminated = true)] GLib.Variant[] row_spec, [CCode (delegate_target_pos = 2.5)] Dee.CompareRowSizedFunc cmp_func, out bool out_was_found);
399 public unowned Dee.ModelIter find_sorted ([CCode (delegate_target_pos = 1.5)] Dee.CompareRowFunc cmp_func, out bool out_was_found, ...);
400 public void @get (Dee.ModelIter iter, ...);
401 public abstract bool get_bool (Dee.ModelIter iter, uint column);
402@@ -235,6 +236,7 @@
403 public abstract unowned Dee.ModelIter insert_row (uint pos, [CCode (array_length = false, array_null_terminated = true)] GLib.Variant[] row_members);
404 public abstract unowned Dee.ModelIter insert_row_before (Dee.ModelIter iter, [CCode (array_length = false, array_null_terminated = true)] GLib.Variant[] row_members);
405 public abstract unowned Dee.ModelIter insert_row_sorted ([CCode (array_length = false, array_null_terminated = true)] GLib.Variant[] row_members, Dee.CompareRowFunc cmp_func);
406+ public unowned Dee.ModelIter insert_row_sorted_with_sizes ([CCode (array_length = false, array_null_terminated = true)] GLib.Variant[] row_members, Dee.CompareRowSizedFunc cmp_func);
407 public unowned Dee.ModelIter insert_sorted ([CCode (delegate_target_pos = 1.5)] Dee.CompareRowFunc cmp_func, ...);
408 public abstract bool is_first (Dee.ModelIter iter);
409 public abstract bool is_last (Dee.ModelIter iter);
410@@ -343,6 +345,8 @@
411 [CCode (cheader_filename = "dee.h", instance_pos = 2.9)]
412 public delegate int CompareRowFunc ([CCode (array_length = false)] GLib.Variant[] row1, [CCode (array_length = false)] GLib.Variant[] row2);
413 [CCode (cheader_filename = "dee.h", instance_pos = 2.9)]
414+ public delegate int CompareRowSizedFunc ([CCode (array_length_cname = "row1_length", array_length_pos = 1.5, array_length_type = "guint")] GLib.Variant[] row1, [CCode (array_length_cname = "row2_length", array_length_pos = 2.1, array_length_type = "guint")] GLib.Variant[] row2);
415+ [CCode (cheader_filename = "dee.h", instance_pos = 2.9)]
416 public delegate void FilterMapFunc (Dee.Model orig_model, Dee.FilterModel filter_model);
417 [CCode (cheader_filename = "dee.h", instance_pos = 3.9)]
418 public delegate bool FilterMapNotify (Dee.Model orig_model, Dee.ModelIter orig_iter, Dee.FilterModel filter_model);

Subscribers

People subscribed via source and target branches

to all changes: