gimppdbdialog.c 12.4 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
2 3 4 5 6
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * gimppdbdialog.c
 * Copyright (C) 2004 Michael Natterer <mitch@gimp.org>
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10 11 12 13 14 15 16 17
 * (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
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 20 21 22 23 24
 */

#include "config.h"

#include <string.h>

25
#include <gegl.h>
26 27
#include <gtk/gtk.h>

28
#include "libgimpbase/gimpbase.h"
29 30 31 32
#include "libgimpwidgets/gimpwidgets.h"

#include "widgets-types.h"

33
#include "core/gimp.h"
34 35
#include "core/gimpcontext.h"

36
#include "pdb/gimppdb.h"
37 38 39

#include "gimpmenufactory.h"
#include "gimppdbdialog.h"
40
#include "gimpwidgets-utils.h"
41 42 43 44 45 46 47

#include "gimp-intl.h"


enum
{
  PROP_0,
48
  PROP_PDB,
49 50 51 52 53 54 55 56
  PROP_CONTEXT,
  PROP_SELECT_TYPE,
  PROP_INITIAL_OBJECT,
  PROP_CALLBACK_NAME,
  PROP_MENU_FACTORY
};


57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
static void   gimp_pdb_dialog_class_init      (GimpPdbDialogClass *klass);
static void   gimp_pdb_dialog_init            (GimpPdbDialog      *dialog,
                                               GimpPdbDialogClass *klass);

static void   gimp_pdb_dialog_constructed     (GObject            *object);
static void   gimp_pdb_dialog_dispose         (GObject            *object);
static void   gimp_pdb_dialog_set_property    (GObject            *object,
                                               guint               property_id,
                                               const GValue       *value,
                                               GParamSpec         *pspec);

static void   gimp_pdb_dialog_response        (GtkDialog          *dialog,
                                               gint                response_id);

static void   gimp_pdb_dialog_context_changed (GimpContext        *context,
                                               GimpObject         *object,
                                               GimpPdbDialog      *dialog);
static void   gimp_pdb_dialog_plug_in_closed  (GimpPlugInManager  *manager,
                                               GimpPlugIn         *plug_in,
                                               GimpPdbDialog      *dialog);
77 78 79 80 81 82 83 84 85 86 87 88


static GimpDialogClass *parent_class = NULL;


GType
gimp_pdb_dialog_get_type (void)
{
  static GType dialog_type = 0;

  if (! dialog_type)
    {
89
      const GTypeInfo dialog_info =
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
      {
        sizeof (GimpPdbDialogClass),
        (GBaseInitFunc) NULL,
        (GBaseFinalizeFunc) NULL,
        (GClassInitFunc) gimp_pdb_dialog_class_init,
        NULL,           /* class_finalize */
        NULL,           /* class_data     */
        sizeof (GimpPdbDialog),
        0,              /* n_preallocs    */
        (GInstanceInitFunc) gimp_pdb_dialog_init,
      };

      dialog_type = g_type_register_static (GIMP_TYPE_DIALOG,
                                            "GimpPdbDialog",
                                            &dialog_info,
                                            G_TYPE_FLAG_ABSTRACT);
    }

  return dialog_type;
}

static void
gimp_pdb_dialog_class_init (GimpPdbDialogClass *klass)
{
114 115
  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
  GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
116 117 118

  parent_class = g_type_class_peek_parent (klass);

119
  object_class->constructed  = gimp_pdb_dialog_constructed;
120 121 122 123 124 125 126 127 128 129
  object_class->dispose      = gimp_pdb_dialog_dispose;
  object_class->set_property = gimp_pdb_dialog_set_property;

  dialog_class->response     = gimp_pdb_dialog_response;

  klass->run_callback        = NULL;

  g_object_class_install_property (object_class, PROP_CONTEXT,
                                   g_param_spec_object ("context", NULL, NULL,
                                                        GIMP_TYPE_CONTEXT,
130
                                                        GIMP_PARAM_WRITABLE |
131 132
                                                        G_PARAM_CONSTRUCT_ONLY));

133 134 135 136 137 138
  g_object_class_install_property (object_class, PROP_PDB,
                                   g_param_spec_object ("pdb", NULL, NULL,
                                                        GIMP_TYPE_PDB,
                                                        GIMP_PARAM_WRITABLE |
                                                        G_PARAM_CONSTRUCT_ONLY));

139
  g_object_class_install_property (object_class, PROP_SELECT_TYPE,
140 141 142 143 144
                                   g_param_spec_gtype ("select-type",
                                                       NULL, NULL,
                                                       GIMP_TYPE_OBJECT,
                                                       GIMP_PARAM_WRITABLE |
                                                       G_PARAM_CONSTRUCT_ONLY));
145 146 147 148 149

  g_object_class_install_property (object_class, PROP_INITIAL_OBJECT,
                                   g_param_spec_object ("initial-object",
                                                        NULL, NULL,
                                                        GIMP_TYPE_OBJECT,
150
                                                        GIMP_PARAM_WRITABLE |
151 152 153 154 155 156
                                                        G_PARAM_CONSTRUCT_ONLY));

  g_object_class_install_property (object_class, PROP_CALLBACK_NAME,
                                   g_param_spec_string ("callback-name",
                                                        NULL, NULL,
                                                        NULL,
157
                                                        GIMP_PARAM_WRITABLE |
158 159 160 161 162 163
                                                        G_PARAM_CONSTRUCT_ONLY));

  g_object_class_install_property (object_class, PROP_MENU_FACTORY,
                                   g_param_spec_object ("menu-factory",
                                                        NULL, NULL,
                                                        GIMP_TYPE_MENU_FACTORY,
164
                                                        GIMP_PARAM_WRITABLE |
165 166 167 168 169 170 171 172 173 174
                                                        G_PARAM_CONSTRUCT_ONLY));
}

static void
gimp_pdb_dialog_init (GimpPdbDialog      *dialog,
                      GimpPdbDialogClass *klass)
{
  klass->dialogs = g_list_prepend (klass->dialogs, dialog);

  gtk_dialog_add_button (GTK_DIALOG (dialog),
175
                         _("_Close"), GTK_RESPONSE_CLOSE);
176 177
}

178 179
static void
gimp_pdb_dialog_constructed (GObject *object)
180
{
181
  GimpPdbDialog *dialog = GIMP_PDB_DIALOG (object);
182 183
  const gchar   *signal_name;

184
  G_OBJECT_CLASS (parent_class)->constructed (object);
185

186 187 188
  gimp_assert (GIMP_IS_PDB (dialog->pdb));
  gimp_assert (GIMP_IS_CONTEXT (dialog->caller_context));
  gimp_assert (g_type_is_a (dialog->select_type, GIMP_TYPE_OBJECT));
189

190
  dialog->context = gimp_context_new (dialog->caller_context->gimp,
191
                                      G_OBJECT_TYPE_NAME (object),
192 193 194 195 196 197 198 199 200 201 202 203
                                      NULL);

  gimp_context_set_by_type (dialog->context, dialog->select_type,
                            dialog->initial_object);

  dialog->initial_object = NULL;

  signal_name = gimp_context_type_to_signal_name (dialog->select_type);

  g_signal_connect_object (dialog->context, signal_name,
                           G_CALLBACK (gimp_pdb_dialog_context_changed),
                           dialog, 0);
204 205 206 207
  g_signal_connect_object (dialog->context->gimp->plug_in_manager,
                           "plug-in-closed",
                           G_CALLBACK (gimp_pdb_dialog_plug_in_closed),
                           dialog, 0);
208 209 210 211 212
}

static void
gimp_pdb_dialog_dispose (GObject *object)
{
213 214
  GimpPdbDialog      *dialog = GIMP_PDB_DIALOG (object);
  GimpPdbDialogClass *klass  = GIMP_PDB_DIALOG_GET_CLASS (object);
215 216 217

  klass->dialogs = g_list_remove (klass->dialogs, object);

218 219 220
  g_clear_object (&dialog->pdb);
  g_clear_object (&dialog->caller_context);
  g_clear_object (&dialog->context);
221

222
  g_clear_pointer (&dialog->callback_name, g_free);
223

224
  g_clear_object (&dialog->menu_factory);
225

226 227 228 229 230 231 232 233 234 235 236 237 238
  G_OBJECT_CLASS (parent_class)->dispose (object);
}

static void
gimp_pdb_dialog_set_property (GObject      *object,
                              guint         property_id,
                              const GValue *value,
                              GParamSpec   *pspec)
{
  GimpPdbDialog *dialog = GIMP_PDB_DIALOG (object);

  switch (property_id)
    {
239
    case PROP_PDB:
240
      dialog->pdb = g_value_dup_object (value);
241
      break;
242

243
    case PROP_CONTEXT:
244
      dialog->caller_context = g_value_dup_object (value);
245
      break;
246

247
    case PROP_SELECT_TYPE:
248
      dialog->select_type = g_value_get_gtype (value);
249
      break;
250

251 252 253 254
    case PROP_INITIAL_OBJECT:
      /* don't ref, see constructor */
      dialog->initial_object = g_value_get_object (value);
      break;
255

256 257 258 259 260
    case PROP_CALLBACK_NAME:
      if (dialog->callback_name)
        g_free (dialog->callback_name);
      dialog->callback_name = g_value_dup_string (value);
      break;
261

262
    case PROP_MENU_FACTORY:
263
      dialog->menu_factory = g_value_dup_object (value);
264
      break;
265

266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static void
gimp_pdb_dialog_response (GtkDialog *gtk_dialog,
                          gint       response_id)
{
  GimpPdbDialog *dialog = GIMP_PDB_DIALOG (gtk_dialog);

  gimp_pdb_dialog_run_callback (dialog, TRUE);
  gtk_widget_destroy (GTK_WIDGET (dialog));
}

void
gimp_pdb_dialog_run_callback (GimpPdbDialog *dialog,
                              gboolean       closing)
{
  GimpPdbDialogClass *klass = GIMP_PDB_DIALOG_GET_CLASS (dialog);
  GimpObject         *object;

  object = gimp_context_get_by_type (dialog->context, dialog->select_type);

  if (object                &&
      klass->run_callback   &&
      dialog->callback_name &&
      ! dialog->callback_busy)
    {
      dialog->callback_busy = TRUE;

298
      if (gimp_pdb_lookup_procedure (dialog->pdb, dialog->callback_name))
299
        {
300 301
          GimpValueArray *return_vals;
          GError         *error = NULL;
302

303
          return_vals = klass->run_callback (dialog, object, closing, &error);
304

305 306
          if (g_value_get_enum (gimp_value_array_index (return_vals, 0)) !=
              GIMP_PDB_SUCCESS)
307
            {
308 309 310 311 312 313
              gimp_message (dialog->context->gimp, G_OBJECT (dialog),
                            GIMP_MESSAGE_ERROR,
                            _("Unable to run %s callback. "
                              "The corresponding plug-in may have "
                              "crashed."),
                            g_type_name (G_TYPE_FROM_INSTANCE (dialog)));
314
            }
315 316
          else if (error)
            {
317
              gimp_message_literal (dialog->context->gimp, G_OBJECT (dialog),
318 319
                                    GIMP_MESSAGE_ERROR,
                                    error->message);
320 321
              g_error_free (error);
            }
322

323
          gimp_value_array_unref (return_vals);
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
        }

      dialog->callback_busy = FALSE;
    }
}

GimpPdbDialog *
gimp_pdb_dialog_get_by_callback (GimpPdbDialogClass *klass,
                                 const gchar        *callback_name)
{
  GList *list;

  g_return_val_if_fail (GIMP_IS_PDB_DIALOG_CLASS (klass), NULL);
  g_return_val_if_fail (callback_name != NULL, NULL);

  for (list = klass->dialogs; list; list = g_list_next (list))
    {
      GimpPdbDialog *dialog = list->data;

      if (dialog->callback_name &&
          ! strcmp (callback_name, dialog->callback_name))
345
        return dialog;
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
    }

  return NULL;
}


/*  private functions  */

static void
gimp_pdb_dialog_context_changed (GimpContext   *context,
                                 GimpObject    *object,
                                 GimpPdbDialog *dialog)
{
  if (object)
    gimp_pdb_dialog_run_callback (dialog, FALSE);
}
362 363 364 365 366 367 368 369 370 371 372 373 374 375

static void
gimp_pdb_dialog_plug_in_closed (GimpPlugInManager *manager,
                                GimpPlugIn        *plug_in,
                                GimpPdbDialog     *dialog)
{
  if (dialog->caller_context && dialog->callback_name)
    {
      if (! gimp_pdb_lookup_procedure (dialog->pdb, dialog->callback_name))
        {
          gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
        }
    }
}