gimpfilteredcontainer.c 14.9 KB
Newer Older
1 2 3 4 5
/* GIMP - The GNU Image Manipulation Program
 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
 *
 * gimpfilteredcontainer.c
 * Copyright (C) 2008 Aurimas Juška <aurisj@svn.gnome.org>
6
 *               2011 Michael Natterer <mitch@gimp.org>
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 3 of the License, or
11 12 13 14 15 16 17 18
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 21 22 23 24 25 26 27 28 29
 */

#include "config.h"

#include <glib-object.h>

#include "core-types.h"

#include "gimpfilteredcontainer.h"

30

31 32 33
enum
{
  PROP_0,
34 35 36
  PROP_SRC_CONTAINER,
  PROP_FILTER_FUNC,
  PROP_FILTER_DATA
37 38
};

39

40 41
static void     gimp_filtered_container_constructed     (GObject               *object);
static void     gimp_filtered_container_dispose         (GObject               *object);
42
static void     gimp_filtered_container_finalize        (GObject               *object);
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
static void     gimp_filtered_container_set_property    (GObject               *object,
                                                         guint                  property_id,
                                                         const GValue          *value,
                                                         GParamSpec            *pspec);
static void     gimp_filtered_container_get_property    (GObject               *object,
                                                         guint                  property_id,
                                                         GValue                *value,
                                                         GParamSpec            *pspec);

static void     gimp_filtered_container_real_src_add    (GimpFilteredContainer *filtered_container,
                                                         GimpObject            *object);
static void     gimp_filtered_container_real_src_remove (GimpFilteredContainer *filtered_container,
                                                         GimpObject            *object);
static void     gimp_filtered_container_real_src_freeze (GimpFilteredContainer *filtered_container);
static void     gimp_filtered_container_real_src_thaw   (GimpFilteredContainer *filtered_container);

static gboolean gimp_filtered_container_object_matches  (GimpFilteredContainer *filtered_container,
                                                         GimpObject            *object);
static void     gimp_filtered_container_src_add         (GimpContainer         *src_container,
                                                         GimpObject            *obj,
                                                         GimpFilteredContainer *filtered_container);
static void     gimp_filtered_container_src_remove      (GimpContainer         *src_container,
                                                         GimpObject            *obj,
                                                         GimpFilteredContainer *filtered_container);
static void     gimp_filtered_container_src_freeze      (GimpContainer         *src_container,
                                                         GimpFilteredContainer *filtered_container);
static void     gimp_filtered_container_src_thaw        (GimpContainer         *src_container,
                                                         GimpFilteredContainer *filtered_container);
71 72 73 74 75 76 77 78 79 80


G_DEFINE_TYPE (GimpFilteredContainer, gimp_filtered_container, GIMP_TYPE_LIST)

#define parent_class gimp_filtered_container_parent_class


static void
gimp_filtered_container_class_init (GimpFilteredContainerClass *klass)
{
81 82
  GObjectClass               *g_object_class = G_OBJECT_CLASS (klass);
  GimpFilteredContainerClass *filtered_class = GIMP_FILTERED_CONTAINER_CLASS (klass);
83

84 85
  g_object_class->constructed  = gimp_filtered_container_constructed;
  g_object_class->dispose      = gimp_filtered_container_dispose;
86
  g_object_class->finalize     = gimp_filtered_container_finalize;
87 88
  g_object_class->set_property = gimp_filtered_container_set_property;
  g_object_class->get_property = gimp_filtered_container_get_property;
89

90 91 92 93 94
  filtered_class->src_add      = gimp_filtered_container_real_src_add;
  filtered_class->src_remove   = gimp_filtered_container_real_src_remove;
  filtered_class->src_freeze   = gimp_filtered_container_real_src_freeze;
  filtered_class->src_thaw     = gimp_filtered_container_real_src_thaw;

95
  g_object_class_install_property (g_object_class, PROP_SRC_CONTAINER,
96 97
                                   g_param_spec_object ("src-container",
                                                        NULL, NULL,
98 99 100
                                                        GIMP_TYPE_CONTAINER,
                                                        GIMP_PARAM_READWRITE |
                                                        G_PARAM_CONSTRUCT_ONLY));
101 102 103 104 105 106 107 108 109 110 111 112

  g_object_class_install_property (g_object_class, PROP_FILTER_FUNC,
                                   g_param_spec_pointer ("filter-func",
                                                         NULL, NULL,
                                                         GIMP_PARAM_READWRITE |
                                                         G_PARAM_CONSTRUCT_ONLY));

  g_object_class_install_property (g_object_class, PROP_FILTER_DATA,
                                   g_param_spec_pointer ("filter-data",
                                                         NULL, NULL,
                                                         GIMP_PARAM_READWRITE |
                                                         G_PARAM_CONSTRUCT_ONLY));
113 114 115 116 117 118 119
}

static void
gimp_filtered_container_init (GimpFilteredContainer *filtered_container)
{
}

120 121
static void
gimp_filtered_container_constructed (GObject *object)
122
{
123
  GimpFilteredContainer *filtered_container = GIMP_FILTERED_CONTAINER (object);
124

125
  G_OBJECT_CLASS (parent_class)->constructed (object);
126

127
  gimp_assert (GIMP_IS_CONTAINER (filtered_container->src_container));
128

129
  if (! gimp_container_frozen (filtered_container->src_container))
130 131 132 133 134 135 136 137 138 139
    {
      /*  a freeze/thaw can't hurt on a newly created container because
       *  we can't have any views yet. This way we get away without
       *  having a virtual function for initializing the container.
       */
      gimp_filtered_container_src_freeze (filtered_container->src_container,
                                          filtered_container);
      gimp_filtered_container_src_thaw (filtered_container->src_container,
                                        filtered_container);
    }
140 141 142
}

static void
143
gimp_filtered_container_dispose (GObject *object)
144
{
145
  GimpFilteredContainer *filtered_container = GIMP_FILTERED_CONTAINER (object);
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160

  if (filtered_container->src_container)
    {
      g_signal_handlers_disconnect_by_func (filtered_container->src_container,
                                            gimp_filtered_container_src_add,
                                            filtered_container);
      g_signal_handlers_disconnect_by_func (filtered_container->src_container,
                                            gimp_filtered_container_src_remove,
                                            filtered_container);
      g_signal_handlers_disconnect_by_func (filtered_container->src_container,
                                            gimp_filtered_container_src_freeze,
                                            filtered_container);
      g_signal_handlers_disconnect_by_func (filtered_container->src_container,
                                            gimp_filtered_container_src_thaw,
                                            filtered_container);
161 162 163 164
    }

  G_OBJECT_CLASS (parent_class)->dispose (object);
}
165

166 167 168 169 170
static void
gimp_filtered_container_finalize (GObject *object)
{
  GimpFilteredContainer *filtered_container = GIMP_FILTERED_CONTAINER (object);

171
  g_clear_object (&filtered_container->src_container);
172

173
  G_OBJECT_CLASS (parent_class)->finalize (object);
174 175 176 177 178 179 180 181 182 183 184 185
}

static void
gimp_filtered_container_set_property (GObject      *object,
                                      guint         property_id,
                                      const GValue *value,
                                      GParamSpec   *pspec)
{
  GimpFilteredContainer *filtered_container = GIMP_FILTERED_CONTAINER (object);

  switch (property_id)
    {
186
    case PROP_SRC_CONTAINER:
187
      filtered_container->src_container = g_value_dup_object (value);
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202

      g_signal_connect (filtered_container->src_container, "add",
                        G_CALLBACK (gimp_filtered_container_src_add),
                        filtered_container);
      g_signal_connect (filtered_container->src_container, "remove",
                        G_CALLBACK (gimp_filtered_container_src_remove),
                        filtered_container);
      g_signal_connect (filtered_container->src_container, "freeze",
                        G_CALLBACK (gimp_filtered_container_src_freeze),
                        filtered_container);
      g_signal_connect (filtered_container->src_container, "thaw",
                        G_CALLBACK (gimp_filtered_container_src_thaw),
                        filtered_container);
      break;

203 204 205 206 207 208 209 210
    case PROP_FILTER_FUNC:
      filtered_container->filter_func = g_value_get_pointer (value);
      break;

    case PROP_FILTER_DATA:
      filtered_container->filter_data = g_value_get_pointer (value);
      break;

211 212 213
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
214 215 216 217
    }
}

static void
218 219 220 221
gimp_filtered_container_get_property (GObject    *object,
                                      guint       property_id,
                                      GValue     *value,
                                      GParamSpec *pspec)
222 223 224 225 226
{
  GimpFilteredContainer *filtered_container = GIMP_FILTERED_CONTAINER (object);

  switch (property_id)
    {
227 228 229
    case PROP_SRC_CONTAINER:
      g_value_set_object (value, filtered_container->src_container);
      break;
230

231 232 233 234 235 236 237 238
    case PROP_FILTER_FUNC:
      g_value_set_pointer (value, filtered_container->filter_func);
      break;

    case PROP_FILTER_DATA:
      g_value_set_pointer (value, filtered_container->filter_data);
      break;

239 240 241
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
242 243 244
    }
}

245 246 247 248
static void
gimp_filtered_container_real_src_add (GimpFilteredContainer *filtered_container,
                                      GimpObject            *object)
{
249
  if (gimp_filtered_container_object_matches (filtered_container, object))
250 251 252 253 254 255 256 257 258
    {
      gimp_container_add (GIMP_CONTAINER (filtered_container), object);
    }
}

static void
gimp_filtered_container_real_src_remove (GimpFilteredContainer *filtered_container,
                                         GimpObject            *object)
{
259
  if (gimp_filtered_container_object_matches (filtered_container, object))
260 261 262 263 264 265 266 267 268 269 270 271 272 273
    {
      gimp_container_remove (GIMP_CONTAINER (filtered_container), object);
    }
}

static void
gimp_filtered_container_real_src_freeze (GimpFilteredContainer *filtered_container)
{
  gimp_container_clear (GIMP_CONTAINER (filtered_container));
}

static void
gimp_filtered_container_real_src_thaw (GimpFilteredContainer *filtered_container)
{
274 275
  GList *list;

276
  for (list = GIMP_LIST (filtered_container->src_container)->queue->head;
277 278 279 280 281 282 283 284 285 286
       list;
       list = g_list_next (list))
    {
      GimpObject *object = list->data;

      if (gimp_filtered_container_object_matches (filtered_container, object))
        {
          gimp_container_add (GIMP_CONTAINER (filtered_container), object);
        }
    }
287 288
}

289 290 291 292 293 294
/**
 * gimp_filtered_container_new:
 * @src_container: container to be filtered.
 *
 * Creates a new #GimpFilteredContainer object which creates filtered
 * data view of #GimpTagged objects. It filters @src_container for objects
295
 * containing all of the filtering tags. Synchronization with @src_container
296 297 298 299 300
 * data is performed automatically.
 *
 * Return value: a new #GimpFilteredContainer object.
 **/
GimpContainer *
301 302 303
gimp_filtered_container_new (GimpContainer        *src_container,
                             GimpObjectFilterFunc  filter_func,
                             gpointer              filter_data)
304
{
305 306
  GType        children_type;
  GCompareFunc sort_func;
307

308
  g_return_val_if_fail (GIMP_IS_LIST (src_container), NULL);
309 310

  children_type = gimp_container_get_children_type (src_container);
311 312 313 314 315 316 317 318 319 320 321
  sort_func     = GIMP_LIST (src_container)->sort_func;

  return g_object_new (GIMP_TYPE_FILTERED_CONTAINER,
                       "sort-func",     sort_func,
                       "children-type", children_type,
                       "policy",        GIMP_CONTAINER_POLICY_WEAK,
                       "unique-names",  FALSE,
                       "src-container", src_container,
                       "filter-func",   filter_func,
                       "filter-data",   filter_data,
                       NULL);
322 323
}

324 325 326
static gboolean
gimp_filtered_container_object_matches (GimpFilteredContainer *filtered_container,
                                        GimpObject            *object)
327
{
328 329 330
  return (! filtered_container->filter_func ||
          filtered_container->filter_func (object,
                                           filtered_container->filter_data));
331 332 333 334
}

static void
gimp_filtered_container_src_add (GimpContainer         *src_container,
335
                                 GimpObject            *object,
336 337
                                 GimpFilteredContainer *filtered_container)
{
338
  if (! gimp_container_frozen (filtered_container->src_container))
339
    {
340 341
      GIMP_FILTERED_CONTAINER_GET_CLASS (filtered_container)->src_add (filtered_container,
                                                                       object);
342 343 344 345 346
    }
}

static void
gimp_filtered_container_src_remove (GimpContainer         *src_container,
347
                                    GimpObject            *object,
348 349
                                    GimpFilteredContainer *filtered_container)
{
350
  if (! gimp_container_frozen (filtered_container->src_container))
351
    {
352 353
      GIMP_FILTERED_CONTAINER_GET_CLASS (filtered_container)->src_remove (filtered_container,
                                                                          object);
354 355 356 357
    }
}

static void
358 359
gimp_filtered_container_src_freeze (GimpContainer         *src_container,
                                    GimpFilteredContainer *filtered_container)
360 361
{
  gimp_container_freeze (GIMP_CONTAINER (filtered_container));
362 363

  GIMP_FILTERED_CONTAINER_GET_CLASS (filtered_container)->src_freeze (filtered_container);
364 365 366
}

static void
367 368
gimp_filtered_container_src_thaw (GimpContainer         *src_container,
                                  GimpFilteredContainer *filtered_container)
369
{
370 371
  GIMP_FILTERED_CONTAINER_GET_CLASS (filtered_container)->src_thaw (filtered_container);

372 373
  gimp_container_thaw (GIMP_CONTAINER (filtered_container));
}