~mhr3/dee/gir-compare-row-func

« back to all changes in this revision

Viewing changes to src/dee-filter.c

  • Committer: Tarmac
  • Author(s): Mikkel Kamstrup Erlandsen
  • Date: 2012-01-09 17:26:12 UTC
  • mfrom: (333.1.11 sorted)
  • Revision ID: tarmac-20120109172612-fc01ukxmajou3ks0
Adds two new methods to the DeeModel interface: insert_row_sorted() and find_row_sorted(). Adding varargs convenience functions as well. There are linear default impls covering all our classes in DeeSerializableModel. We have optimized tree-based algorithms implemented for DeeSequenceModel and DeeFilterModel.

The Python support is currently broken on some bug in pygobject. I believed that my pygobject patches on https://bugzilla.gnome.org/show_bug.cgi?id=667244 would fix this, but testing unfortunately confirms that it doesn't.... Fixes: https://bugs.launchpad.net/bugs/913128. Appoved by Michal Hruby.

Show diffs side-by-side

added added

removed removed

Lines of Context:
58
58
#include "dee-filter.h"
59
59
#include "trace-log.h"
60
60
 
 
61
typedef struct {
 
62
  guint             n_cols;
 
63
  DeeCompareRowFunc cmp;
 
64
  gpointer          user_data;
 
65
  GDestroyNotify    destroy;
 
66
  GVariant        **row_buf;
 
67
} SortFilter;
 
68
 
61
69
/* The CollatorFilter stores collation keys for the columns in a DeeModelTag */
62
70
typedef struct {
63
71
  guint        column;
82
90
/*
83
91
 * Private impl
84
92
 */
85
 
static gboolean _dee_filter_collator_map_notify (DeeModel *orig_model,
86
 
                                                 DeeModelIter *orig_iter,
87
 
                                                 DeeFilterModel *filter_model,
88
 
                                                 gpointer user_data);
89
 
 
90
 
static gboolean _dee_filter_collator_desc_map_notify (DeeModel *orig_model,
91
 
                                                      DeeModelIter *orig_iter,
92
 
                                                      DeeFilterModel *filter_model,
93
 
                                                      gpointer user_data);
94
 
 
95
 
static void
96
 
_dee_filter_collator_map_func (DeeModel *orig_model,
97
 
                               DeeFilterModel *filter_model,
98
 
                               gpointer user_data)
99
 
{
100
 
  DeeModelIter   *iter, *end;
101
 
  CollatorFilter *filter;
102
 
 
103
 
  g_return_if_fail (user_data != NULL);
104
 
 
105
 
  filter = (CollatorFilter *) user_data;
106
 
  filter->collation_key_tag =
107
 
                 dee_model_register_tag (orig_model, (GDestroyNotify) g_free);
108
 
 
109
 
  iter = dee_model_get_first_iter (orig_model);
110
 
  end = dee_model_get_last_iter (orig_model);
111
 
  while (iter != end)
112
 
    {
113
 
      _dee_filter_collator_map_notify (orig_model, iter, filter_model, filter);
114
 
      iter = dee_model_next (orig_model, iter);
115
 
    }
116
 
 
117
 
}
118
 
 
119
 
static void
120
 
_dee_filter_collator_desc_map_func (DeeModel *orig_model,
121
 
                               DeeFilterModel *filter_model,
122
 
                               gpointer user_data)
123
 
{
124
 
  DeeModelIter   *iter, *end;
125
 
  CollatorFilter *filter;
126
 
 
127
 
  g_return_if_fail (user_data != NULL);
128
 
 
129
 
  filter = (CollatorFilter *) user_data;
130
 
  filter->collation_key_tag =
131
 
                 dee_model_register_tag (orig_model, (GDestroyNotify) g_free);
132
 
 
133
 
  iter = dee_model_get_first_iter (orig_model);
134
 
  end = dee_model_get_last_iter (orig_model);
135
 
  while (iter != end)
136
 
    {
137
 
      _dee_filter_collator_desc_map_notify (orig_model, iter, filter_model, filter);
138
 
      iter = dee_model_next (orig_model, iter);
139
 
    }
140
 
 
141
 
}
142
 
 
143
 
static gboolean
144
 
_dee_filter_collator_map_notify (DeeModel *orig_model,
145
 
                                 DeeModelIter *orig_iter,
146
 
                                 DeeFilterModel *filter_model,
147
 
                                 gpointer user_data)
148
 
{
149
 
  DeeModelIter   *iter, *end;
150
 
  CollatorFilter *filter;
151
 
  const gchar    *column_value, *test_value;
152
 
  gchar          *collation_key;
153
 
 
154
 
  g_return_val_if_fail (user_data != NULL, FALSE);
155
 
  g_return_val_if_fail (orig_iter != NULL, FALSE);
156
 
 
157
 
  filter = (CollatorFilter *) user_data;
158
 
 
159
 
  /* Build and set collation ley for the current row */
160
 
  column_value = dee_model_get_string (orig_model, orig_iter, filter->column);
161
 
  collation_key = g_utf8_collate_key (column_value, -1);
162
 
  dee_model_set_tag (orig_model, orig_iter,
163
 
                     filter->collation_key_tag, collation_key); // steal collation_key
164
 
 
165
 
  iter = dee_model_get_first_iter (DEE_MODEL (filter_model));
166
 
  end = dee_model_get_last_iter (DEE_MODEL (filter_model));
167
 
  while (iter != end)
168
 
    {
169
 
      test_value = dee_model_get_tag (orig_model, iter, filter->collation_key_tag);
170
 
      if (g_strcmp0 (test_value, column_value) < 0)
171
 
        {
172
 
          iter = dee_model_next (DEE_MODEL (filter_model), iter);
173
 
        }
174
 
      else
175
 
        {
176
 
          dee_filter_model_insert_iter_before (filter_model, orig_iter, iter);
177
 
          iter = NULL;
178
 
          break;
179
 
        }
180
 
    }
181
 
 
182
 
  if (iter == end)
183
 
    {
184
 
      dee_filter_model_append_iter(filter_model, orig_iter);
185
 
    }
186
 
    
187
 
  return TRUE;
188
 
}
189
 
 
190
 
static gboolean
191
 
_dee_filter_collator_desc_map_notify (DeeModel *orig_model,
192
 
                                 DeeModelIter *orig_iter,
193
 
                                 DeeFilterModel *filter_model,
194
 
                                 gpointer user_data)
195
 
{
196
 
  DeeModelIter   *iter, *end;
197
 
  CollatorFilter *filter;
198
 
  const gchar    *column_value, *test_value;
199
 
  gchar          *collation_key;
200
 
 
201
 
  g_return_val_if_fail (user_data != NULL, FALSE);
202
 
  g_return_val_if_fail (orig_iter != NULL, FALSE);
203
 
 
204
 
  filter = (CollatorFilter *) user_data;
205
 
 
206
 
  /* Build and set collation ley for the current row */
207
 
  column_value = dee_model_get_string (orig_model, orig_iter, filter->column);
208
 
  collation_key = g_utf8_collate_key (column_value, -1);
209
 
  dee_model_set_tag (orig_model, orig_iter,
210
 
                     filter->collation_key_tag, collation_key); // steal collation_key
211
 
 
212
 
  iter = dee_model_get_first_iter (DEE_MODEL (filter_model));
213
 
  end = dee_model_get_last_iter (DEE_MODEL (filter_model));
214
 
  while (iter != end)
215
 
    {
216
 
      test_value = dee_model_get_tag (orig_model, iter, filter->collation_key_tag);
217
 
      if (g_strcmp0 (test_value, column_value) > 0)
218
 
        {
219
 
          iter = dee_model_next (DEE_MODEL (filter_model), iter);
220
 
        }
221
 
      else
222
 
        {
223
 
          dee_filter_model_insert_iter_before (filter_model, orig_iter, iter);
224
 
          iter = NULL;
225
 
          break;
226
 
        }
227
 
    }
228
 
 
229
 
  if (iter == end)
230
 
    {
231
 
      dee_filter_model_append_iter(filter_model, orig_iter);
232
 
    }
233
 
  
234
 
  return TRUE;
 
93
 
 
94
static gboolean
 
95
_dee_filter_sort_map_notify (DeeModel *orig_model,
 
96
                             DeeModelIter *orig_iter,
 
97
                             DeeFilterModel *filter_model,
 
98
                             gpointer user_data)
 
99
{
 
100
  DeeModelIter   *pos_iter;
 
101
  SortFilter     *filter;
 
102
  guint           i;
 
103
  gboolean        was_found;
 
104
 
 
105
  g_return_val_if_fail (user_data != NULL, FALSE);
 
106
 
 
107
  filter = (SortFilter *) user_data;
 
108
 
 
109
  dee_model_get_row (orig_model, orig_iter, filter->row_buf);
 
110
 
 
111
  pos_iter = dee_model_find_row_sorted (DEE_MODEL (filter_model),
 
112
                                        filter->row_buf,
 
113
                                        filter->cmp,
 
114
                                        filter->user_data,
 
115
                                        &was_found);
 
116
 
 
117
  dee_filter_model_insert_iter_before (filter_model, orig_iter, pos_iter);
 
118
 
 
119
  for (i = 0; i < filter->n_cols; i++) g_variant_unref (filter->row_buf[i]);
 
120
 
 
121
  return was_found;
 
122
}
 
123
 
 
124
static void
 
125
_dee_filter_sort_map_func (DeeModel *orig_model,
 
126
                           DeeFilterModel *filter_model,
 
127
                           gpointer user_data)
 
128
{
 
129
  DeeModelIter   *iter, *end;
 
130
  SortFilter     *filter;
 
131
 
 
132
  g_return_if_fail (user_data != NULL);
 
133
 
 
134
  filter = (SortFilter *) user_data;
 
135
  filter->n_cols = dee_model_get_n_columns (orig_model);
 
136
  filter->row_buf = g_new0(GVariant*, filter->n_cols);
 
137
 
 
138
  iter = dee_model_get_first_iter (orig_model);
 
139
  end = dee_model_get_last_iter (orig_model);
 
140
  while (iter != end)
 
141
    {
 
142
      _dee_filter_sort_map_notify (orig_model, iter, filter_model, filter);
 
143
      iter = dee_model_next (orig_model, iter);
 
144
    }
 
145
}
 
146
 
 
147
static gint
 
148
_cmp_collate_asc (GVariant **row1, GVariant **row2, gpointer user_data)
 
149
{
 
150
  guint col = GPOINTER_TO_UINT (user_data);
 
151
 
 
152
  return g_utf8_collate (g_variant_get_string (row1[col], NULL),
 
153
                         g_variant_get_string (row2[col], NULL));
 
154
}
 
155
 
 
156
static gint
 
157
_cmp_collate_desc (GVariant **row1, GVariant **row2, gpointer user_data)
 
158
{
 
159
  guint col = GPOINTER_TO_UINT (user_data);
 
160
 
 
161
  return  - g_utf8_collate (g_variant_get_string (row1[col], NULL),
 
162
                            g_variant_get_string (row2[col], NULL));
235
163
}
236
164
 
237
165
static void
386
314
}
387
315
 
388
316
static void
 
317
sort_filter_free (SortFilter *filter)
 
318
{
 
319
  if (filter->destroy != NULL)
 
320
    filter->destroy (filter->user_data);
 
321
 
 
322
  g_free (filter->row_buf);
 
323
  g_free (filter);
 
324
}
 
325
 
 
326
static void
389
327
key_filter_free (KeyFilter *filter)
390
328
{
391
329
  g_free (filter->key);
511
449
}
512
450
 
513
451
/**
 
452
 * dee_filter_new_sort:
 
453
 * @cmp_row: (scope notified): A #DeeCompareRowFunc to use for sorting
 
454
 * @cmp_user_data: (closure): User data passed to @cmp_row
 
455
 * @cmp_destroy: (allow-none): The #GDestroyNotify to call on
 
456
 *                         @cmp_user_data when disposing of the filter
 
457
 * @out_filter: (out): A pointer to an uninitialized #DeeFilter struct.
 
458
 *                     This struct will zeroed and configured with the filter
 
459
 *                     parameters
 
460
 *
 
461
 * Create a new #DeeFilter sorting a model according to a #DeeCompareRowFunc.
 
462
 *
 
463
 */
 
464
void
 
465
dee_filter_new_sort (DeeCompareRowFunc cmp_row,
 
466
                     gpointer          cmp_user_data,
 
467
                     GDestroyNotify    cmp_destroy,
 
468
                     DeeFilter        *out_filter)
 
469
{
 
470
  SortFilter *filter;
 
471
 
 
472
  filter = g_new0 (SortFilter, 1);
 
473
  filter->cmp = cmp_row;
 
474
  filter->user_data = cmp_user_data;
 
475
  filter->destroy = cmp_destroy;
 
476
 
 
477
  dee_filter_new (_dee_filter_sort_map_func,
 
478
                  _dee_filter_sort_map_notify,
 
479
                  filter,
 
480
                  (GDestroyNotify) sort_filter_free,
 
481
                  out_filter);
 
482
}
 
483
 
 
484
/**
514
485
 * dee_filter_new_collator:
515
486
 * @column: The index of a column containing the strings to sort after
516
487
 * @out_filter: (out): A pointer to an uninitialized #DeeFilter struct.
525
496
dee_filter_new_collator    (guint      column,
526
497
                            DeeFilter *out_filter)
527
498
{
528
 
  CollatorFilter *collator;
529
 
 
530
 
  collator = g_new0 (CollatorFilter, 1);
531
 
  collator->column = column;
532
 
 
533
 
  dee_filter_new (_dee_filter_collator_map_func,
534
 
                  _dee_filter_collator_map_notify,
535
 
                  collator,
536
 
                  (GDestroyNotify) g_free,
537
 
                  out_filter);
 
499
  dee_filter_new_sort (_cmp_collate_asc, GUINT_TO_POINTER (column),
 
500
                       NULL, out_filter);
538
501
}
539
502
 
540
503
/**
552
515
dee_filter_new_collator_desc    (guint      column,
553
516
                                 DeeFilter *out_filter)
554
517
{
555
 
  CollatorFilter *collator; 
556
 
 
557
 
  collator = g_new0 (CollatorFilter, 1);
558
 
  collator->column = column;
559
 
 
560
 
  dee_filter_new (_dee_filter_collator_desc_map_func,
561
 
                  _dee_filter_collator_desc_map_notify,
562
 
                  collator,
563
 
                  (GDestroyNotify) g_free,
564
 
                  out_filter);
 
518
  dee_filter_new_sort (_cmp_collate_desc, GUINT_TO_POINTER (column),
 
519
                       NULL, out_filter);
565
520
566
521
 
567
522