testfilechooser.c 20.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/* testfilechooser.c
 * Copyright (C) 2003  Red Hat, Inc.
 * Author: Owen Taylor
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
Javier Jardón's avatar
Javier Jardón committed
16
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17
 */
18
#include "config.h"
19

Owen Taylor's avatar
Owen Taylor committed
20
#include <string.h>
21 22 23 24
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
25
#ifdef HAVE_UNISTD_H
26
#include <unistd.h>
27
#endif
Owen Taylor's avatar
Owen Taylor committed
28
#include <gtk/gtk.h>
29 30 31

#ifdef G_OS_WIN32
#  include <io.h>
32
#  define localtime_r(t,b) *(b) = *localtime (t)
33 34 35 36 37
#  ifndef S_ISREG
#    define S_ISREG(m) ((m) & _S_IFREG)
#  endif
#endif

38 39
static GtkWidget *preview_label;
static GtkWidget *preview_image;
Jonathan Blandford's avatar
Jonathan Blandford committed
40
static GtkFileChooserAction action;
41

Owen Taylor's avatar
Owen Taylor committed
42 43 44 45 46 47
static void
print_current_folder (GtkFileChooser *chooser)
{
  gchar *uri;

  uri = gtk_file_chooser_get_current_folder_uri (chooser);
48
  g_print ("Current folder changed :\n  %s\n", uri ? uri : "(null)");
Owen Taylor's avatar
Owen Taylor committed
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
  g_free (uri);
}

static void
print_selected (GtkFileChooser *chooser)
{
  GSList *uris = gtk_file_chooser_get_uris (chooser);
  GSList *tmp_list;

  g_print ("Selection changed :\n");
  for (tmp_list = uris; tmp_list; tmp_list = tmp_list->next)
    {
      gchar *uri = tmp_list->data;
      g_print ("  %s\n", uri);
      g_free (uri);
    }
  g_print ("\n");
  g_slist_free (uris);
}

69 70 71 72
static void
response_cb (GtkDialog *dialog,
	     gint       response_id)
{
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
  if (response_id == GTK_RESPONSE_OK)
    {
      GSList *list;

      list = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));

      if (list)
	{
	  GSList *l;

	  g_print ("Selected files:\n");

	  for (l = list; l; l = l->next)
	    {
	      g_print ("%s\n", (char *) l->data);
	      g_free (l->data);
	    }

	  g_slist_free (list);
	}
      else
	g_print ("No selected files\n");
    }
  else
    g_print ("Dialog was closed\n");
98

99 100 101
  gtk_main_quit ();
}

Owen Taylor's avatar
Owen Taylor committed
102 103 104 105
static gboolean
no_backup_files_filter (const GtkFileFilterInfo *filter_info,
			gpointer                 data)
{
106
  gsize len = filter_info->display_name ? strlen (filter_info->display_name) : 0;
Owen Taylor's avatar
Owen Taylor committed
107 108 109 110 111 112
  if (len > 0 && filter_info->display_name[len - 1] == '~')
    return 0;
  else
    return 1;
}

113 114 115 116 117 118 119
static void
filter_changed (GtkFileChooserDialog *dialog,
		gpointer              data)
{
  g_print ("file filter changed\n");
}

120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
static char *
format_time (time_t t)
{
  gchar buf[128];
  struct tm tm_buf;
  time_t now = time (NULL);
  const char *format;

  if (abs (now - t) < 24*60*60)
    format = "%X";
  else
    format = "%x";

  localtime_r (&t, &tm_buf);
  if (strftime (buf, sizeof (buf), format, &tm_buf) == 0)
    return g_strdup ("<unknown>");
  else
    return g_strdup (buf);
}

static char *
format_size (gint64 size)
{
  if (size < (gint64)1024)
    return g_strdup_printf ("%d bytes", (gint)size);
  else if (size < (gint64)1024*1024)
    return g_strdup_printf ("%.1f K", size / (1024.));
  else if (size < (gint64)1024*1024*1024)
    return g_strdup_printf ("%.1f M", size / (1024.*1024.));
  else
    return g_strdup_printf ("%.1f G", size / (1024.*1024.*1024.));
}

#include <stdio.h>
#include <errno.h>
#define _(s) (s)

static void
158
size_prepared_cb (GdkPixbufLoader *loader,
159 160
		  int              width,
		  int              height,
161
		  int             *data)
162
{
163 164 165 166 167 168 169 170
	int des_width = data[0];
	int des_height = data[1];

	if (des_height >= height && des_width >= width) {
		/* Nothing */
	} else if ((double)height * des_width > (double)width * des_height) {
		width = 0.5 + (double)width * des_height / (double)height;
		height = des_height;
171
	} else {
172 173
		height = 0.5 + (double)height * des_width / (double)width;
		width = des_width;
174 175 176 177 178 179 180
	}

	gdk_pixbuf_loader_set_size (loader, width, height);
}

GdkPixbuf *
my_new_from_file_at_size (const char *filename,
181
			  int         width,
182 183 184 185 186
			  int         height,
			  GError    **error)
{
	GdkPixbufLoader *loader;
	GdkPixbuf       *pixbuf;
187
	int              info[2];
188
	struct stat st;
189 190 191 192 193 194 195 196

	guchar buffer [4096];
	int length;
	FILE *f;

	g_return_val_if_fail (filename != NULL, NULL);
        g_return_val_if_fail (width > 0 && height > 0, NULL);

197
	if (stat (filename, &st) != 0) {
198 199
                int errsv = errno;

200 201
		g_set_error (error,
			     G_FILE_ERROR,
202
			     g_file_error_from_errno (errsv),
203
			     _("Could not get information for file '%s': %s"),
204
			     filename, g_strerror (errsv));
205 206 207 208 209 210
		return NULL;
	}

	if (!S_ISREG (st.st_mode))
		return NULL;

211 212
	f = fopen (filename, "rb");
	if (!f) {
213 214
                int errsv = errno;

215 216
                g_set_error (error,
                             G_FILE_ERROR,
217
                             g_file_error_from_errno (errsv),
218
                             _("Failed to open file '%s': %s"),
219
                             filename, g_strerror (errsv));
220 221
		return NULL;
        }
222

223 224 225 226
	loader = gdk_pixbuf_loader_new ();
#ifdef DONT_PRESERVE_ASPECT
	gdk_pixbuf_loader_set_size (loader, width, height);
#else
227 228 229
	info[0] = width;
	info[1] = height;
	g_signal_connect (loader, "size-prepared", G_CALLBACK (size_prepared_cb), info);
230
#endif
231 232 233 234 235 236 237

	while (!feof (f)) {
		length = fread (buffer, 1, sizeof (buffer), f);
		if (length > 0)
			if (!gdk_pixbuf_loader_write (loader, buffer, length, error)) {
			        gdk_pixbuf_loader_close (loader, NULL);
				fclose (f);
238
				g_object_unref (loader);
239 240 241 242 243 244
				return NULL;
			}
	}

	fclose (f);

245
	g_assert (*error == NULL);
246
	if (!gdk_pixbuf_loader_close (loader, error)) {
247
		g_object_unref (loader);
248 249 250 251 252 253
		return NULL;
	}

	pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);

	if (!pixbuf) {
254
		g_object_unref (loader);
255 256 257 258 259

		/* did the loader set an error? */
		if (*error != NULL)
			return NULL;

260 261 262 263 264 265 266 267 268 269
		g_set_error (error,
                             GDK_PIXBUF_ERROR,
                             GDK_PIXBUF_ERROR_FAILED,
                             _("Failed to load image '%s': reason not known, probably a corrupt image file"),
                             filename);
		return NULL;
	}

	g_object_ref (pixbuf);

270
	g_object_unref (loader);
271 272 273 274 275 276 277 278 279

	return pixbuf;
}

static void
update_preview_cb (GtkFileChooser *chooser)
{
  gchar *filename = gtk_file_chooser_get_preview_filename (chooser);
  gboolean have_preview = FALSE;
280

281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
  if (filename)
    {
      GdkPixbuf *pixbuf;
      GError *error = NULL;

      pixbuf = my_new_from_file_at_size (filename, 128, 128, &error);
      if (pixbuf)
	{
	  gtk_image_set_from_pixbuf (GTK_IMAGE (preview_image), pixbuf);
	  g_object_unref (pixbuf);
	  gtk_widget_show (preview_image);
	  gtk_widget_hide (preview_label);
	  have_preview = TRUE;
	}
      else
	{
	  struct stat buf;
	  if (stat (filename, &buf) == 0)
	    {
	      gchar *preview_text;
	      gchar *size_str;
	      gchar *modified_time;
303

304 305
	      size_str = format_size (buf.st_size);
	      modified_time = format_time (buf.st_mtime);
306

307 308 309 310 311 312 313 314
	      preview_text = g_strdup_printf ("<i>Modified:</i>\t%s\n"
					      "<i>Size:</i>\t%s\n",
					      modified_time,
					      size_str);
	      gtk_label_set_markup (GTK_LABEL (preview_label), preview_text);
	      g_free (modified_time);
	      g_free (size_str);
	      g_free (preview_text);
315

316 317 318 319 320
	      gtk_widget_hide (preview_image);
	      gtk_widget_show (preview_label);
	      have_preview = TRUE;
	    }
	}
321

322
      g_free (filename);
Morten Welinder's avatar
Morten Welinder committed
323 324 325

      if (error)
	g_error_free (error);
326 327 328 329 330
    }

  gtk_file_chooser_set_preview_widget_active (chooser, have_preview);
}

331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
static void
set_current_folder (GtkFileChooser *chooser,
		    const char     *name)
{
  if (!gtk_file_chooser_set_current_folder (chooser, name))
    {
      GtkWidget *dialog;

      dialog = gtk_message_dialog_new (GTK_WINDOW (chooser),
				       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
				       GTK_MESSAGE_ERROR,
				       GTK_BUTTONS_CLOSE,
				       "Could not set the folder to %s",
				       name);
      gtk_dialog_run (GTK_DIALOG (dialog));
      gtk_widget_destroy (dialog);
    }
}

350
static void
351
set_folder_nonexistent_cb (GtkButton      *button,
352 353
			   GtkFileChooser *chooser)
{
354
  set_current_folder (chooser, "/nonexistent");
355 356 357
}

static void
358
set_folder_existing_nonexistent_cb (GtkButton      *button,
359 360
				    GtkFileChooser *chooser)
{
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
  set_current_folder (chooser, "/usr/nonexistent");
}

static void
set_filename (GtkFileChooser *chooser,
	      const char     *name)
{
  if (!gtk_file_chooser_set_filename (chooser, name))
    {
      GtkWidget *dialog;

      dialog = gtk_message_dialog_new (GTK_WINDOW (chooser),
				       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
				       GTK_MESSAGE_ERROR,
				       GTK_BUTTONS_CLOSE,
				       "Could not select %s",
				       name);
      gtk_dialog_run (GTK_DIALOG (dialog));
      gtk_widget_destroy (dialog);
    }
381 382 383
}

static void
384
set_filename_nonexistent_cb (GtkButton      *button,
385 386
			     GtkFileChooser *chooser)
{
387
  set_filename (chooser, "/nonexistent");
388 389 390
}

static void
391
set_filename_existing_nonexistent_cb (GtkButton      *button,
392 393
				      GtkFileChooser *chooser)
{
394
  set_filename (chooser, "/usr/nonexistent");
395 396
}

397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
static void
get_selection_cb (GtkButton      *button,
		  GtkFileChooser *chooser)
{
  GSList *selection;

  selection = gtk_file_chooser_get_uris (chooser);

  g_print ("Selection: ");

  if (selection == NULL)
    g_print ("empty\n");
  else
    {
      GSList *l;
      
      for (l = selection; l; l = l->next)
	{
	  char *uri = l->data;

	  g_print ("%s\n", uri);

	  if (l->next)
	    g_print ("           ");
	}
    }

  g_slist_free_full (selection, g_free);
}

static void
get_current_name_cb (GtkButton      *button,
		     GtkFileChooser *chooser)
{
  char *name;

  name = gtk_file_chooser_get_current_name (chooser);
  g_print ("Current name: %s\n", name ? name : "NULL");
  g_free (name);
}

438 439 440 441 442 443 444 445
static void
unmap_and_remap_cb (GtkButton *button,
		    GtkFileChooser *chooser)
{
  gtk_widget_hide (GTK_WIDGET (chooser));
  gtk_widget_show (GTK_WIDGET (chooser));
}

446
static void
447
kill_dependent (GtkWindow *win, GtkWidget *dep)
448
{
449
  gtk_widget_destroy (dep);
450 451 452
  g_object_unref (dep);
}

453 454 455 456 457 458 459 460
static void
notify_multiple_cb (GtkWidget  *dialog,
		    GParamSpec *pspec,
		    GtkWidget  *button)
{
  gboolean multiple;

  multiple = gtk_file_chooser_get_select_multiple (GTK_FILE_CHOOSER (dialog));
461

462 463 464
  gtk_widget_set_sensitive (button, multiple);
}

465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
static GtkFileChooserConfirmation
confirm_overwrite_cb (GtkFileChooser *chooser,
		      gpointer        data)
{
  GtkWidget *dialog;
  GtkWidget *button;
  int response;
  GtkFileChooserConfirmation conf;

  dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (chooser))),
				   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
				   GTK_MESSAGE_QUESTION,
				   GTK_BUTTONS_NONE,
				   "What do you want to do?");

  button = gtk_button_new_with_label ("Use the stock confirmation dialog");
  gtk_widget_show (button);
  gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, 1);

  button = gtk_button_new_with_label ("Type a new file name");
  gtk_widget_show (button);
  gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, 2);

  button = gtk_button_new_with_label ("Accept the file name");
  gtk_widget_show (button);
  gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, 3);

  response = gtk_dialog_run (GTK_DIALOG (dialog));

  switch (response)
    {
    case 1:
      conf = GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM;
      break;

    case 3:
      conf = GTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME;
      break;

    default:
      conf = GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN;
      break;
    }

  gtk_widget_destroy (dialog);

  return conf;
}

Owen Taylor's avatar
Owen Taylor committed
514 515 516 517 518 519 520
int
main (int argc, char **argv)
{
  GtkWidget *control_window;
  GtkWidget *vbbox;
  GtkWidget *button;
  GtkWidget *dialog;
521
  GtkWidget *extra;
Owen Taylor's avatar
Owen Taylor committed
522
  GtkFileFilter *filter;
523
  GtkWidget *preview_vbox;
524
  gboolean force_rtl = FALSE;
525
  gboolean multiple = FALSE;
526
  char *action_arg = NULL;
527
  char *initial_filename = NULL;
528
  char *initial_folder = NULL;
529 530
  GError *error = NULL;
  GOptionEntry options[] = {
531
    { "action", 'a', 0, G_OPTION_ARG_STRING, &action_arg, "Filechooser action", "ACTION" },
532 533
    { "multiple", 'm', 0, G_OPTION_ARG_NONE, &multiple, "Select-multiple", NULL },
    { "right-to-left", 'r', 0, G_OPTION_ARG_NONE, &force_rtl, "Force right-to-left layout.", NULL },
534
    { "initial-filename", 'f', 0, G_OPTION_ARG_FILENAME, &initial_filename, "Initial filename to select", "FILENAME" },
535
    { "initial-folder", 'F', 0, G_OPTION_ARG_FILENAME, &initial_folder, "Initial folder to show", "FILENAME" },
536 537 538 539 540 541 542 543 544
    { NULL }
  };

  if (!gtk_init_with_args (&argc, &argv, "", options, NULL, &error))
    {
      g_print ("Failed to parse args: %s\n", error->message);
      g_error_free (error);
      return 1;
    }
545

546 547 548 549 550 551
  if (initial_filename && initial_folder)
    {
      g_print ("Only one of --initial-filename and --initial-folder may be specified");
      return 1;
    }

552
  if (force_rtl)
553
    gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
554

Jonathan Blandford's avatar
Jonathan Blandford committed
555 556
  action = GTK_FILE_CHOOSER_ACTION_OPEN;

557
  if (action_arg != NULL)
Jonathan Blandford's avatar
Jonathan Blandford committed
558
    {
559
      if (! strcmp ("open", action_arg))
Jonathan Blandford's avatar
Jonathan Blandford committed
560
	action = GTK_FILE_CHOOSER_ACTION_OPEN;
561
      else if (! strcmp ("save", action_arg))
Jonathan Blandford's avatar
Jonathan Blandford committed
562
	action = GTK_FILE_CHOOSER_ACTION_SAVE;
563
      else if (! strcmp ("select_folder", action_arg))
Jonathan Blandford's avatar
Jonathan Blandford committed
564
	action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
565
      else if (! strcmp ("create_folder", action_arg))
Jonathan Blandford's avatar
Jonathan Blandford committed
566
	action = GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER;
567 568 569 570 571
      else
	{
	  g_print ("--action must be one of \"open\", \"save\", \"select_folder\", \"create_folder\"\n");
	  return 1;
	}
572 573

      g_free (action_arg);
Jonathan Blandford's avatar
Jonathan Blandford committed
574 575
    }

576
  dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
Jonathan Blandford's avatar
Jonathan Blandford committed
577
			 "action", action,
578
			 "select-multiple", multiple,
579
			 NULL);
580

Jonathan Blandford's avatar
Jonathan Blandford committed
581 582 583 584 585 586
  switch (action)
    {
    case GTK_FILE_CHOOSER_ACTION_OPEN:
    case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
      gtk_window_set_title (GTK_WINDOW (dialog), "Select a file");
      gtk_dialog_add_buttons (GTK_DIALOG (dialog),
587 588
			      _("_Cancel"), GTK_RESPONSE_CANCEL,
			      _("_Open"), GTK_RESPONSE_OK,
Jonathan Blandford's avatar
Jonathan Blandford committed
589 590 591 592 593 594
			      NULL);
      break;
    case GTK_FILE_CHOOSER_ACTION_SAVE:
    case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
      gtk_window_set_title (GTK_WINDOW (dialog), "Save a file");
      gtk_dialog_add_buttons (GTK_DIALOG (dialog),
595 596
			      _("_Cancel"), GTK_RESPONSE_CANCEL,
			      _("_Open"), GTK_RESPONSE_OK,
Jonathan Blandford's avatar
Jonathan Blandford committed
597 598 599
			      NULL);
      break;
    }
600
  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
601

602
  g_signal_connect (dialog, "selection-changed",
Owen Taylor's avatar
Owen Taylor committed
603
		    G_CALLBACK (print_selected), NULL);
604
  g_signal_connect (dialog, "current-folder-changed",
Owen Taylor's avatar
Owen Taylor committed
605
		    G_CALLBACK (print_current_folder), NULL);
606 607
  g_signal_connect (dialog, "response",
		    G_CALLBACK (response_cb), NULL);
608 609
  g_signal_connect (dialog, "confirm-overwrite",
		    G_CALLBACK (confirm_overwrite_cb), NULL);
Owen Taylor's avatar
Owen Taylor committed
610 611 612 613 614 615

  /* Filters */
  filter = gtk_file_filter_new ();
  gtk_file_filter_set_name (filter, "All Files");
  gtk_file_filter_add_pattern (filter, "*");
  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
616

617 618 619
  /* Make this filter the default */
  gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);

Owen Taylor's avatar
Owen Taylor committed
620 621 622 623 624 625 626
  filter = gtk_file_filter_new ();
  gtk_file_filter_set_name (filter, "No backup files");
  gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_DISPLAY_NAME,
			      no_backup_files_filter, NULL, NULL);
  gtk_file_filter_add_mime_type (filter, "image/png");
  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);

Matthias Clasen's avatar
Matthias Clasen committed
627 628 629 630 631
  filter = gtk_file_filter_new ();
  gtk_file_filter_set_name (filter, "Starts with D");
  gtk_file_filter_add_pattern (filter, "D*");
  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);

632
  g_signal_connect (dialog, "notify::filter",
633 634
		    G_CALLBACK (filter_changed), NULL);

Owen Taylor's avatar
Owen Taylor committed
635 636 637 638 639 640
  filter = gtk_file_filter_new ();
  gtk_file_filter_set_name (filter, "PNG and JPEG");
  gtk_file_filter_add_mime_type (filter, "image/jpeg");
  gtk_file_filter_add_mime_type (filter, "image/png");
  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);

641 642 643 644
  filter = gtk_file_filter_new ();
  gtk_file_filter_set_name (filter, "Images");
  gtk_file_filter_add_pixbuf_formats (filter);
  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
645

646
#if 0
647
  /* Preview widget */
648 649
  /* THIS IS A TERRIBLE PREVIEW WIDGET, AND SHOULD NOT BE COPIED AT ALL.
   */
650
  preview_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
651
  gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (dialog), preview_vbox);
652

653 654
  preview_label = gtk_label_new (NULL);
  gtk_box_pack_start (GTK_BOX (preview_vbox), preview_label, TRUE, TRUE, 0);
655
  g_object_set (preview_label, "margin", 6, NULL);
656

657 658
  preview_image = gtk_image_new ();
  gtk_box_pack_start (GTK_BOX (preview_vbox), preview_image, TRUE, TRUE, 0);
659
  g_object_set (preview_image, "margin", 6, NULL);
660

661 662 663
  update_preview_cb (GTK_FILE_CHOOSER (dialog));
  g_signal_connect (dialog, "update-preview",
		    G_CALLBACK (update_preview_cb), NULL);
664
#endif
665 666

  /* Extra widget */
667

668 669 670
  extra = gtk_check_button_new_with_mnemonic ("Lar_t whoever asks about this button");
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (extra), TRUE);
  gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), extra);
671 672 673 674 675 676

  /* Shortcuts */

  gtk_file_chooser_add_shortcut_folder_uri (GTK_FILE_CHOOSER (dialog),
					    "file:///usr/share/pixmaps",
					    NULL);
Matthias Clasen's avatar
Matthias Clasen committed
677 678 679
  gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog),
					g_get_user_special_dir (G_USER_DIRECTORY_MUSIC),
					NULL);
680

681
  /* Initial filename or folder */
682 683 684 685

  if (initial_filename)
    set_filename (GTK_FILE_CHOOSER (dialog), initial_filename);

686 687 688
  if (initial_folder)
    set_current_folder (GTK_FILE_CHOOSER (dialog), initial_folder);

Owen Taylor's avatar
Owen Taylor committed
689 690
  /* show_all() to reveal bugs in composite widget handling */
  gtk_widget_show_all (dialog);
Owen Taylor's avatar
Owen Taylor committed
691

692 693
  /* Extra controls for manipulating the test environment
   */
Owen Taylor's avatar
Owen Taylor committed
694 695

  control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
696

697
  vbbox = gtk_button_box_new (GTK_ORIENTATION_VERTICAL);
Owen Taylor's avatar
Owen Taylor committed
698 699 700
  gtk_container_add (GTK_CONTAINER (control_window), vbbox);

  button = gtk_button_new_with_mnemonic ("_Select all");
701
  gtk_widget_set_sensitive (button, multiple);
Owen Taylor's avatar
Owen Taylor committed
702 703 704
  gtk_container_add (GTK_CONTAINER (vbbox), button);
  g_signal_connect_swapped (button, "clicked",
			    G_CALLBACK (gtk_file_chooser_select_all), dialog);
705
  g_signal_connect (dialog, "notify::select-multiple",
706
		    G_CALLBACK (notify_multiple_cb), button);
707

Owen Taylor's avatar
Owen Taylor committed
708 709 710 711 712
  button = gtk_button_new_with_mnemonic ("_Unselect all");
  gtk_container_add (GTK_CONTAINER (vbbox), button);
  g_signal_connect_swapped (button, "clicked",
			    G_CALLBACK (gtk_file_chooser_unselect_all), dialog);

713 714 715 716 717
  button = gtk_button_new_with_label ("set_current_folder (\"/nonexistent\")");
  gtk_container_add (GTK_CONTAINER (vbbox), button);
  g_signal_connect (button, "clicked",
		    G_CALLBACK (set_folder_nonexistent_cb), dialog);

718
  button = gtk_button_new_with_label ("set_current_folder (\"/usr/nonexistent\")");
719 720 721 722
  gtk_container_add (GTK_CONTAINER (vbbox), button);
  g_signal_connect (button, "clicked",
		    G_CALLBACK (set_folder_existing_nonexistent_cb), dialog);

723
  button = gtk_button_new_with_label ("set_filename (\"/nonexistent\")");
724 725 726 727
  gtk_container_add (GTK_CONTAINER (vbbox), button);
  g_signal_connect (button, "clicked",
		    G_CALLBACK (set_filename_nonexistent_cb), dialog);

728
  button = gtk_button_new_with_label ("set_filename (\"/usr/nonexistent\")");
729 730 731 732
  gtk_container_add (GTK_CONTAINER (vbbox), button);
  g_signal_connect (button, "clicked",
		    G_CALLBACK (set_filename_existing_nonexistent_cb), dialog);

733 734 735 736 737 738 739 740 741 742
  button = gtk_button_new_with_label ("Get selection");
  gtk_container_add (GTK_CONTAINER (vbbox), button);
  g_signal_connect (button, "clicked",
		    G_CALLBACK (get_selection_cb), dialog);

  button = gtk_button_new_with_label ("Get current name");
  gtk_container_add (GTK_CONTAINER (vbbox), button);
  g_signal_connect (button, "clicked",
		    G_CALLBACK (get_current_name_cb), dialog);

743 744 745 746 747
  button = gtk_button_new_with_label ("Unmap and remap");
  gtk_container_add (GTK_CONTAINER (vbbox), button);
  g_signal_connect (button, "clicked",
		    G_CALLBACK (unmap_and_remap_cb), dialog);

Owen Taylor's avatar
Owen Taylor committed
748
  gtk_widget_show_all (control_window);
749 750

  g_object_ref (control_window);
751
  g_signal_connect (dialog, "destroy",
752 753 754 755 756 757
		    G_CALLBACK (kill_dependent), control_window);

  /* We need to hold a ref until we have destroyed the widgets, just in case
   * someone else destroys them.  We explicitly destroy windows to catch leaks.
   */
  g_object_ref (dialog);
Owen Taylor's avatar
Owen Taylor committed
758
  gtk_main ();
759 760
  gtk_widget_destroy (dialog);
  g_object_unref (dialog);
Owen Taylor's avatar
Owen Taylor committed
761 762 763

  return 0;
}