~ubuntu-branches/ubuntu/breezy/gimp/breezy

« back to all changes in this revision

Viewing changes to libgimpwidgets/gimpfileentry.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2005-10-04 19:04:46 UTC
  • Revision ID: james.westby@ubuntu.com-20051004190446-ukh32kwk56s4sjhu
Tags: upstream-2.2.8
ImportĀ upstreamĀ versionĀ 2.2.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* LIBGIMP - The GIMP Library
 
2
 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
 
3
 *
 
4
 * gimpfileentry.c
 
5
 * Copyright (C) 1999-2004 Michael Natterer <mitch@gimp.org>
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Library General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this library; if not, write to the
 
19
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
20
 * Boston, MA 02111-1307, USA.
 
21
 */
 
22
 
 
23
#include "config.h"
 
24
 
 
25
#include <string.h>
 
26
 
 
27
#include <gtk/gtk.h>
 
28
 
 
29
#include "gimpwidgetstypes.h"
 
30
 
 
31
#include "gimpfileentry.h"
 
32
 
 
33
#include "libgimp/libgimp-intl.h"
 
34
 
 
35
 
 
36
enum
 
37
{
 
38
  FILENAME_CHANGED,
 
39
  LAST_SIGNAL
 
40
};
 
41
 
 
42
 
 
43
static void   gimp_file_entry_class_init      (GimpFileEntryClass *klass);
 
44
static void   gimp_file_entry_init            (GimpFileEntry      *entry);
 
45
 
 
46
static void   gimp_file_entry_destroy         (GtkObject          *object);
 
47
 
 
48
static void   gimp_file_entry_entry_activate  (GtkWidget          *widget,
 
49
                                               GimpFileEntry      *entry);
 
50
static gint   gimp_file_entry_entry_focus_out (GtkWidget          *widget,
 
51
                                               GdkEvent           *event,
 
52
                                               GimpFileEntry      *entry);
 
53
static void   gimp_file_entry_browse_clicked  (GtkWidget          *widget,
 
54
                                               GimpFileEntry      *entry);
 
55
static void   gimp_file_entry_check_filename  (GimpFileEntry      *entry);
 
56
 
 
57
 
 
58
static guint gimp_file_entry_signals[LAST_SIGNAL] = { 0 };
 
59
 
 
60
static GtkHBoxClass *parent_class = NULL;
 
61
 
 
62
 
 
63
GType
 
64
gimp_file_entry_get_type (void)
 
65
{
 
66
  static GType entry_type = 0;
 
67
 
 
68
  if (! entry_type)
 
69
    {
 
70
      static const GTypeInfo entry_info =
 
71
      {
 
72
        sizeof (GimpFileEntryClass),
 
73
        (GBaseInitFunc) NULL,
 
74
        (GBaseFinalizeFunc) NULL,
 
75
        (GClassInitFunc) gimp_file_entry_class_init,
 
76
        NULL,           /* class_finalize */
 
77
        NULL,           /* class_data     */
 
78
        sizeof (GimpFileEntry),
 
79
        0,              /* n_preallocs    */
 
80
        (GInstanceInitFunc) gimp_file_entry_init,
 
81
      };
 
82
 
 
83
      entry_type = g_type_register_static (GTK_TYPE_HBOX,
 
84
                                           "GimpFileEntry",
 
85
                                           &entry_info, 0);
 
86
    }
 
87
 
 
88
  return entry_type;
 
89
}
 
90
 
 
91
static void
 
92
gimp_file_entry_class_init (GimpFileEntryClass *klass)
 
93
{
 
94
  GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
 
95
 
 
96
  parent_class = g_type_class_peek_parent (klass);
 
97
 
 
98
  /**
 
99
   * GimpFileEntry::filename-changed:
 
100
   *
 
101
   * This signal is emitted whenever the user changes the filename.
 
102
   **/
 
103
  gimp_file_entry_signals[FILENAME_CHANGED] =
 
104
    g_signal_new ("filename_changed",
 
105
                  G_TYPE_FROM_CLASS (klass),
 
106
                  G_SIGNAL_RUN_FIRST,
 
107
                  G_STRUCT_OFFSET (GimpFileEntryClass, filename_changed),
 
108
                  NULL, NULL,
 
109
                  g_cclosure_marshal_VOID__VOID,
 
110
                  G_TYPE_NONE, 0);
 
111
 
 
112
  object_class->destroy   = gimp_file_entry_destroy;
 
113
 
 
114
  klass->filename_changed = NULL;
 
115
}
 
116
 
 
117
static void
 
118
gimp_file_entry_init (GimpFileEntry *entry)
 
119
{
 
120
  entry->title       = NULL;
 
121
  entry->file_dialog = NULL;
 
122
  entry->check_valid = FALSE;
 
123
  entry->file_exists = NULL;
 
124
 
 
125
  gtk_box_set_spacing (GTK_BOX (entry), 4);
 
126
  gtk_box_set_homogeneous (GTK_BOX (entry), FALSE);
 
127
 
 
128
  entry->browse_button = gtk_button_new_with_label (" ... ");
 
129
  gtk_box_pack_end (GTK_BOX (entry), entry->browse_button, FALSE, FALSE, 0);
 
130
  gtk_widget_show (entry->browse_button);
 
131
 
 
132
  g_signal_connect (entry->browse_button, "clicked",
 
133
                    G_CALLBACK (gimp_file_entry_browse_clicked),
 
134
                    entry);
 
135
 
 
136
  entry->entry = gtk_entry_new ();
 
137
  gtk_box_pack_end (GTK_BOX (entry), entry->entry, TRUE, TRUE, 0);
 
138
  gtk_widget_show (entry->entry);
 
139
 
 
140
  g_signal_connect (entry->entry, "activate",
 
141
                    G_CALLBACK (gimp_file_entry_entry_activate),
 
142
                    entry);
 
143
  g_signal_connect (entry->entry, "focus_out_event",
 
144
                    G_CALLBACK (gimp_file_entry_entry_focus_out),
 
145
                    entry);
 
146
}
 
147
 
 
148
static void
 
149
gimp_file_entry_destroy (GtkObject *object)
 
150
{
 
151
  GimpFileEntry *entry = GIMP_FILE_ENTRY (object);
 
152
 
 
153
  if (entry->file_dialog)
 
154
    {
 
155
      gtk_widget_destroy (entry->file_dialog);
 
156
      entry->file_dialog = NULL;
 
157
    }
 
158
 
 
159
  if (entry->title)
 
160
    {
 
161
      g_free (entry->title);
 
162
      entry->title = NULL;
 
163
    }
 
164
 
 
165
  GTK_OBJECT_CLASS (parent_class)->destroy (object);
 
166
}
 
167
 
 
168
/**
 
169
 * gimp_file_entry_new:
 
170
 * @title:       The title of the #GtkFileEntry dialog.
 
171
 * @filename:    The initial filename.
 
172
 * @dir_only:    %TRUE if the file entry should accept directories only.
 
173
 * @check_valid: %TRUE if the widget should check if the entered file
 
174
 *               really exists.
 
175
 *
 
176
 * Creates a new #GimpFileEntry widget.
 
177
 *
 
178
 * Returns: A pointer to the new #GimpFileEntry widget.
 
179
 **/
 
180
GtkWidget *
 
181
gimp_file_entry_new (const gchar *title,
 
182
                     const gchar *filename,
 
183
                     gboolean     dir_only,
 
184
                     gboolean     check_valid)
 
185
{
 
186
  GimpFileEntry *entry;
 
187
 
 
188
  entry = g_object_new (GIMP_TYPE_FILE_ENTRY, NULL);
 
189
 
 
190
  entry->title       = g_strdup (title);
 
191
  entry->dir_only    = dir_only;
 
192
  entry->check_valid = check_valid;
 
193
 
 
194
  if (check_valid)
 
195
    {
 
196
      entry->file_exists = gtk_image_new_from_stock (GTK_STOCK_NO,
 
197
                                                     GTK_ICON_SIZE_BUTTON);
 
198
      gtk_box_pack_start (GTK_BOX (entry), entry->file_exists, FALSE, FALSE, 0);
 
199
      gtk_widget_show (entry->file_exists);
 
200
    }
 
201
 
 
202
  gimp_file_entry_set_filename (entry, filename);
 
203
 
 
204
  return GTK_WIDGET (entry);
 
205
}
 
206
 
 
207
/**
 
208
 * gimp_file_entry_get_filename:
 
209
 * @entry: The file entry you want to know the filename from.
 
210
 *
 
211
 * Note that you have to g_free() the returned string.
 
212
 *
 
213
 * Returns: The file or directory the user has entered.
 
214
 **/
 
215
gchar *
 
216
gimp_file_entry_get_filename (GimpFileEntry *entry)
 
217
{
 
218
  gchar *utf8;
 
219
  gchar *filename;
 
220
 
 
221
  g_return_val_if_fail (GIMP_IS_FILE_ENTRY (entry), NULL);
 
222
 
 
223
  utf8 = gtk_editable_get_chars (GTK_EDITABLE (entry->entry), 0, -1);
 
224
 
 
225
  filename = g_filename_from_utf8 (utf8, -1, NULL, NULL, NULL);
 
226
 
 
227
  g_free (utf8);
 
228
 
 
229
  return filename;
 
230
}
 
231
 
 
232
/**
 
233
 * gimp_file_entry_set_filename:
 
234
 * @entry:    The file entry you want to set the filename for.
 
235
 * @filename: The new filename.
 
236
 *
 
237
 * If you specified @check_valid as %TRUE in gimp_file_entry_new()
 
238
 * the #GimpFileEntry will immediately check the validity of the file
 
239
 * name.
 
240
 **/
 
241
void
 
242
gimp_file_entry_set_filename (GimpFileEntry *entry,
 
243
                              const gchar   *filename)
 
244
{
 
245
  gchar *utf8;
 
246
 
 
247
  g_return_if_fail (GIMP_IS_FILE_ENTRY (entry));
 
248
 
 
249
  if (filename)
 
250
    utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
 
251
  else
 
252
    utf8 = g_strdup ("");
 
253
 
 
254
  gtk_entry_set_text (GTK_ENTRY (entry->entry), utf8);
 
255
  g_free (utf8);
 
256
 
 
257
  /*  update everything
 
258
   */
 
259
  gimp_file_entry_entry_activate (entry->entry, entry);
 
260
}
 
261
 
 
262
static void
 
263
gimp_file_entry_entry_activate (GtkWidget     *widget,
 
264
                                GimpFileEntry *entry)
 
265
{
 
266
  gchar *utf8;
 
267
  gchar *filename;
 
268
  gint   len;
 
269
 
 
270
  /*  filenames still need more sanity checking
 
271
   *  (erase double G_DIR_SEPARATORS, ...)
 
272
   */
 
273
  utf8 = gtk_editable_get_chars (GTK_EDITABLE (widget), 0, -1);
 
274
  utf8 = g_strstrip (utf8);
 
275
 
 
276
  while (((len = strlen (utf8)) > 1) &&
 
277
         (utf8[len - 1] == G_DIR_SEPARATOR))
 
278
    utf8[len - 1] = '\0';
 
279
 
 
280
  filename = g_filename_from_utf8 (utf8, -1, NULL, NULL, NULL);
 
281
 
 
282
  g_signal_handlers_block_by_func (entry->entry,
 
283
                                   gimp_file_entry_entry_activate,
 
284
                                   entry);
 
285
  gtk_entry_set_text (GTK_ENTRY (entry->entry), utf8);
 
286
  g_signal_handlers_unblock_by_func (entry->entry,
 
287
                                     gimp_file_entry_entry_activate,
 
288
                                     entry);
 
289
 
 
290
  if (entry->file_dialog)
 
291
    gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (entry->file_dialog),
 
292
                                   filename);
 
293
 
 
294
  g_free (filename);
 
295
  g_free (utf8);
 
296
 
 
297
  gimp_file_entry_check_filename (entry);
 
298
 
 
299
  gtk_editable_set_position (GTK_EDITABLE (entry->entry), -1);
 
300
 
 
301
  g_signal_emit (entry, gimp_file_entry_signals[FILENAME_CHANGED], 0);
 
302
}
 
303
 
 
304
static gboolean
 
305
gimp_file_entry_entry_focus_out (GtkWidget     *widget,
 
306
                                 GdkEvent      *event,
 
307
                                 GimpFileEntry *entry)
 
308
{
 
309
  gimp_file_entry_entry_activate (widget, entry);
 
310
 
 
311
  return FALSE;
 
312
}
 
313
 
 
314
/*  local callback of gimp_file_entry_browse_clicked()  */
 
315
static void
 
316
gimp_file_entry_chooser_response (GtkWidget     *dialog,
 
317
                                  gint           response_id,
 
318
                                  GimpFileEntry *entry)
 
319
{
 
320
  if (response_id == GTK_RESPONSE_OK)
 
321
    {
 
322
      gchar *filename;
 
323
 
 
324
      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
 
325
      gimp_file_entry_set_filename (entry, filename);
 
326
      g_free (filename);
 
327
    }
 
328
 
 
329
  gtk_widget_hide (dialog);
 
330
}
 
331
 
 
332
static void
 
333
gimp_file_entry_browse_clicked (GtkWidget     *widget,
 
334
                                GimpFileEntry *entry)
 
335
{
 
336
  GtkFileChooser *chooser;
 
337
  gchar          *utf8;
 
338
  gchar          *filename;
 
339
 
 
340
  utf8 = gtk_editable_get_chars (GTK_EDITABLE (entry->entry), 0, -1);
 
341
  filename = g_filename_from_utf8 (utf8, -1, NULL, NULL, NULL);
 
342
  g_free (utf8);
 
343
 
 
344
  if (! entry->file_dialog)
 
345
    {
 
346
      const gchar *title = entry->title;
 
347
 
 
348
      if (! title)
 
349
        {
 
350
          if (entry->dir_only)
 
351
            title = _("Select Folder");
 
352
          else
 
353
            title = _("Select File");
 
354
        }
 
355
 
 
356
      entry->file_dialog =
 
357
        gtk_file_chooser_dialog_new (title, NULL,
 
358
                                     entry->dir_only ?
 
359
                                     GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER :
 
360
                                     GTK_FILE_CHOOSER_ACTION_OPEN,
 
361
 
 
362
                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
363
                                     GTK_STOCK_OK,     GTK_RESPONSE_OK,
 
364
 
 
365
                                     NULL);
 
366
 
 
367
      chooser = GTK_FILE_CHOOSER (entry->file_dialog);
 
368
 
 
369
      gtk_window_set_position (GTK_WINDOW (chooser), GTK_WIN_POS_MOUSE);
 
370
      gtk_window_set_role (GTK_WINDOW (chooser),
 
371
                           "gimp-file-entry-file-dialog");
 
372
 
 
373
      g_signal_connect (chooser, "response",
 
374
                        G_CALLBACK (gimp_file_entry_chooser_response),
 
375
                        entry);
 
376
      g_signal_connect (chooser, "delete_event",
 
377
                        G_CALLBACK (gtk_true),
 
378
                        NULL);
 
379
 
 
380
      g_signal_connect_swapped (entry, "unmap",
 
381
                                G_CALLBACK (gtk_widget_hide),
 
382
                                chooser);
 
383
    }
 
384
  else
 
385
    {
 
386
      chooser = GTK_FILE_CHOOSER (entry->file_dialog);
 
387
    }
 
388
 
 
389
  gtk_file_chooser_set_filename (chooser, filename);
 
390
 
 
391
  g_free (filename);
 
392
 
 
393
  gtk_window_set_screen (GTK_WINDOW (chooser), gtk_widget_get_screen (widget));
 
394
  gtk_window_present (GTK_WINDOW (chooser));
 
395
}
 
396
 
 
397
static void
 
398
gimp_file_entry_check_filename (GimpFileEntry *entry)
 
399
{
 
400
  gchar    *utf8;
 
401
  gchar    *filename;
 
402
  gboolean  exists;
 
403
 
 
404
  if (! entry->check_valid || ! entry->file_exists)
 
405
    return;
 
406
 
 
407
  utf8 = gtk_editable_get_chars (GTK_EDITABLE (entry->entry), 0, -1);
 
408
  filename = g_filename_from_utf8 (utf8, -1, NULL, NULL, NULL);
 
409
  g_free (utf8);
 
410
 
 
411
  if (entry->dir_only)
 
412
    exists = g_file_test (filename, G_FILE_TEST_IS_DIR);
 
413
  else
 
414
    exists = g_file_test (filename, G_FILE_TEST_IS_REGULAR);
 
415
 
 
416
  g_free (filename);
 
417
 
 
418
  gtk_image_set_from_stock (GTK_IMAGE (entry->file_exists),
 
419
                            exists ? GTK_STOCK_YES : GTK_STOCK_NO,
 
420
                            GTK_ICON_SIZE_BUTTON);
 
421
}