nautilus-application.c 11.8 KB
Newer Older
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 3 4 5 6 7 8

/*
 *  Nautilus
 *
 *  Copyright (C) 1999, 2000 Red Hat, Inc.
 *  Copyright (C) 2000 Eazel, Inc.
 *
9
 *  This program is free software; you can redistribute it and/or
10 11 12 13
 *  modify it under the terms of the GNU General Public License as
 *  published by the Free Software Foundation; either version 2 of the
 *  License, or (at your option) any later version.
 *
14
 *  This program is distributed in the hope that it will be useful,
15 16 17 18 19
 *  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
20
 *  along with this program; if not, write to the Free Software
21 22 23 24 25 26
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Author: Elliot Lee <sopwith@redhat.com>,
 *
 */

27
#include <config.h>
28
#include "nautilus-application.h"
29

30
#include <bonobo.h>
31 32
#include "file-manager/fm-icon-view.h"
#include "file-manager/fm-list-view.h"
33
#include <libnautilus-extensions/nautilus-gtk-macros.h>
34
#include <libnautilus-extensions/nautilus-gnome-extensions.h>
35
#include <libnautilus-extensions/nautilus-global-preferences.h>
36 37 38
#include <libnautilus-extensions/nautilus-file-utilities.h>
#include <libnautilus-extensions/nautilus-string-list.h>
#include <libnautilus-extensions/nautilus-gnome-extensions.h>
39
#include <libnautilus-extensions/nautilus-undo-manager.h>
40
#include <liboaf/liboaf.h>
41
#include "nautilus-desktop-window.h"
42

43
typedef struct {
44 45
	POA_Bonobo_GenericFactory servant;
 	NautilusApplication *bonobo_object;
46
} impl_POA_Nautilus_Application;
47

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
static CORBA_boolean manufactures                                (PortableServer_Servant    servant,
								  const CORBA_char         *iid,
								  CORBA_Environment        *ev);
static CORBA_Object  create_object                               (PortableServer_Servant    servant,
								  const CORBA_char         *iid,
								  const Bonobo_stringlist  *params,
								  CORBA_Environment        *ev);
static void          nautilus_application_initialize             (NautilusApplication      *application);
static void          nautilus_application_initialize_class       (NautilusApplicationClass *klass);
static void          nautilus_application_destroy                (GtkObject                *object);
static void          nautilus_application_check_user_directories (NautilusApplication      *application);

NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusApplication, nautilus_application, BONOBO_OBJECT_TYPE)

static POA_Bonobo_GenericFactory__epv factory_epv = {
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
63
	NULL,
64 65 66 67 68 69 70
	&manufactures,
	&create_object
};
static PortableServer_ServantBase__epv base_epv;
static POA_Bonobo_GenericFactory__vepv vepv = {
	&base_epv,
	&factory_epv
71 72 73
};

static CORBA_boolean
74 75 76
manufactures (PortableServer_Servant servant,
	      const CORBA_char *iid,
	      CORBA_Environment *ev)
77
{
78 79
	return strcmp (iid, "OAFIID:nautilus_file_manager_icon_view:42681b21-d5ca-4837-87d2-394d88ecc058") == 0
		|| strcmp (iid, "OAFIID:nautilus_file_manager_list_view:521e489d-0662-4ad7-ac3a-832deabe111c") == 0;
80 81 82
}

static CORBA_Object
83 84 85 86
create_object (PortableServer_Servant servant,
	       const CORBA_char *iid,
	       const Bonobo_stringlist *params,
	       CORBA_Environment *ev)
87
{
88
	FMDirectoryView *directory_view;
Darin Adler's avatar
Darin Adler committed
89
	NautilusView *view;
90

91 92 93 94
	if (strcmp (iid, "OAFIID:nautilus_file_manager_icon_view:42681b21-d5ca-4837-87d2-394d88ecc058") == 0) {
		directory_view = FM_DIRECTORY_VIEW (gtk_object_new (fm_icon_view_get_type (), NULL));
	} else if (strcmp (iid, "OAFIID:nautilus_file_manager_list_view:521e489d-0662-4ad7-ac3a-832deabe111c") == 0) {
		directory_view = FM_DIRECTORY_VIEW (gtk_object_new (fm_list_view_get_type (), NULL));
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
95
	} else {
96
		return CORBA_OBJECT_NIL;
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
97
	}
98
        
99
	view = fm_directory_view_get_nautilus_view (directory_view);
100
	return CORBA_Object_duplicate (bonobo_object_corba_objref (BONOBO_OBJECT (view)), ev);
101 102
}

103
static CORBA_Object
104 105 106
create_factory (PortableServer_POA poa,
		NautilusApplication *bonobo_object,
		CORBA_Environment *ev)
107
{
108
	impl_POA_Nautilus_Application *servant;
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
109

110 111 112 113
	servant = g_new0 (impl_POA_Nautilus_Application, 1);
	servant->servant.vepv = &vepv;
	POA_Bonobo_GenericFactory__init ((PortableServer_Servant) servant, ev);
	return bonobo_object_activate_servant (BONOBO_OBJECT (bonobo_object), servant);
114 115 116
}

static void
117
nautilus_application_initialize_class (NautilusApplicationClass *klass)
118
{
119
	GTK_OBJECT_CLASS (klass)->destroy = nautilus_application_destroy;
120 121 122
}

static void
123
nautilus_application_initialize (NautilusApplication *application)
124
{
125
	CORBA_Environment ev;
126 127
	CORBA_Object corba_object;
	OAF_RegistrationResult result;
128
	
129
	CORBA_exception_init (&ev);
130

131 132 133 134 135 136
	corba_object = create_factory (bonobo_poa (), application, &ev);
	result = oaf_active_server_register ("OAFIID:nautilus_file_manager_factory:bd1e1862-92d7-4391-963e-37583f0daef3",
					     corba_object);
	/* FIXME: Report this error somehow. */
	g_assert (result == OAF_REG_SUCCESS);
	bonobo_object_construct (BONOBO_OBJECT (application), corba_object);
137

138
	/* Create an undo manager */
139
	application->undo_manager = nautilus_undo_manager_new ();
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
140

141
	CORBA_exception_free (&ev);
142 143
}

144 145
NautilusApplication *
nautilus_application_new (void)
146
{
147
	return NAUTILUS_APPLICATION (gtk_object_new (nautilus_application_get_type (), NULL));
148 149 150
}

static void
151
nautilus_application_destroy (GtkObject *object)
152
{
153 154
	/* Shut down preferences. This is needed so that the global
	 * preferences object and all its allocations are freed. Not
155 156 157
	 * calling this function would have NOT cause the user to lose
	 * preferences.  The only effect would be to leak those
	 * objects - which would be collected at exit() time anyway,
158
	 * but it adds noise to memory profile tool runs.
159 160
	 */
	nautilus_global_preferences_shutdown ();
161

162
	nautilus_bookmarks_exiting ();
163

164 165
	NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object));
}
166

167
static void
168
display_caveat (GtkWindow *parent_window)
169
{
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
	GtkWidget *dialog;
	GtkWidget *frame;
	GtkWidget *pixmap;
	GtkWidget *hbox;
	GtkWidget *text;
	char *file_name;

	dialog = gnome_dialog_new (_("Nautilus: caveat"),
				   GNOME_STOCK_BUTTON_OK,
				   NULL);
  	gtk_container_set_border_width (GTK_CONTAINER (dialog), GNOME_PAD);
  	gtk_window_set_policy (GTK_WINDOW (dialog), FALSE, FALSE, FALSE);

  	hbox = gtk_hbox_new (FALSE, GNOME_PAD);
  	gtk_container_set_border_width (GTK_CONTAINER (hbox), GNOME_PAD);
  	gtk_widget_show (hbox);
  	gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), 
  			    hbox,
  			    FALSE, FALSE, 0);

	frame = gtk_frame_new (NULL);
	gtk_widget_show (frame);
	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
  	gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
	
	file_name = gnome_pixmap_file ("nautilus/About_Image.png");
	pixmap = gnome_pixmap_new_from_file (file_name);
	g_free (file_name);
	gtk_widget_show (pixmap);
	gtk_container_add (GTK_CONTAINER (frame), pixmap);

201 202 203 204 205 206 207 208 209
  	text = gtk_label_new
		(_("The Nautilus shell is under development; it's not "
  		   "ready for daily use. Many features, including some "
  		   "of the best ones, are not yet done, partly done, or "
  		   "unstable. The program doesn't look or act the way "
  		   "it will in version 1.0."
		   "\n\n"
		   "If you do decide to test this version of Nautilus, "
		   "beware. The program could do something "
John Sullivan's avatar
John Sullivan committed
210
		   "unpredictable and may even delete or overwrite "
211 212 213 214
		   "files on your computer."
		   "\n\n"
		   "For more information, visit http://nautilus.eazel.com."));
    	gtk_label_set_line_wrap (GTK_LABEL (text), TRUE);
215 216 217 218 219
	gtk_widget_show (text);
  	gtk_box_pack_start (GTK_BOX (hbox), text, FALSE, FALSE, 0);

  	gnome_dialog_set_close (GNOME_DIALOG (dialog), TRUE);

220 221 222
	if (parent_window != NULL) {
		gnome_dialog_set_parent (GNOME_DIALOG (dialog), parent_window);
	}
223 224

	gtk_widget_show (GTK_WIDGET (dialog));
225 226
}

227
static void
228
nautilus_application_check_user_directories (NautilusApplication *application)
229 230 231 232 233 234
{
	const char		*user_directory;
	const char		*user_main_directory;
	const char		*desktop_directory;
	NautilusStringList	*dir_list;
	
235
	g_assert (NAUTILUS_IS_APPLICATION (application));
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278

	user_directory = nautilus_get_user_directory ();
	user_main_directory = nautilus_get_user_main_directory ();
	desktop_directory = nautilus_get_desktop_directory ();

	dir_list = nautilus_string_list_new ();
	
	/* FIXME bugzilla.eazel.com 1115: Need better name for "User Directory"
	 * and "User Data Directory".
	 */

	if (!g_file_test (user_directory, G_FILE_TEST_ISDIR)) {
		nautilus_string_list_insert (dir_list, "User Directory");
	}
	    
	if (!g_file_test (user_main_directory, G_FILE_TEST_ISDIR)) {
		nautilus_string_list_insert (dir_list, "User Main Directory");
	}
	    
	if (!g_file_test (desktop_directory, G_FILE_TEST_ISDIR)) {
		nautilus_string_list_insert (dir_list, "Desktop Directory");
	}

	if (nautilus_string_list_get_length (dir_list) > 0) {
		char *dir_list_concatenated;
		char *error_string;

		dir_list_concatenated = nautilus_string_list_as_concatenated_string (dir_list, "\n");
		
		error_string = g_strdup_printf ("%s\n\n%s\n\n%s",
						"The following directories are missing:",
						dir_list_concatenated,
						"Please restart Nautilus to fix this problem.");

		nautilus_error_dialog (error_string);

		g_free (dir_list_concatenated);
		g_free (error_string);
	}

	nautilus_string_list_free (dir_list);
}

279
void
280 281 282
nautilus_application_startup (NautilusApplication *application,
			      gboolean manage_desktop,
			      const char *urls[])
283
{
284
	const char **p;
285
	NautilusWindow *window;
286
	NautilusWindow *first_window;
287

288 289 290
	/* Check the user's ~/.nautilus directories and post warnings if there
	 * are problems
	 */
291
	nautilus_application_check_user_directories (application);
292

293 294
	/* Set up the desktop. */
	if (manage_desktop) {
295
		gtk_widget_show (GTK_WIDGET (nautilus_desktop_window_new (application)));
296
	}
297

298 299 300 301
  	/* Create the other windows. */
	first_window = NULL;
	if (urls != NULL) {
		for (p = urls; *p != NULL; p++) {
302
			window = nautilus_application_create_window (application);
303 304 305 306 307 308
			nautilus_window_goto_uri (window, *p);
			if (first_window == NULL) {
				first_window = window;
			}
		}
	}
309 310 311 312 313
	/* FIXME bugzilla.eazel.com 1051: Change this logic back so it won't
	 * make a new window when asked to manage the desktop, once we have
	 * a way to get rid of the desktop.
	 */
	if (/* !manage_desktop && */ first_window == NULL) {
314
		first_window = nautilus_application_create_window (application);
315 316
		nautilus_window_go_home (first_window);
	}
317

318
	/* Show the "not ready for prime time" dialog after the first
319 320
	 * window appears, so it's on top.
	 */
John Sullivan's avatar
John Sullivan committed
321
	/* FIXME bugzilla.eazel.com 1256: It's not on top of the other windows. */
Darin Adler's avatar
Darin Adler committed
322
	if (g_getenv ("NAUTILUS_NO_CAVEAT_DIALOG") == NULL) {
323 324 325 326 327 328
	  	if (first_window == NULL) {
			display_caveat (NULL);
		} else {
			gtk_signal_connect (GTK_OBJECT (first_window), "show",
					    display_caveat, first_window);
		}
329
  	}
330 331 332
}

static void
333
nautilus_application_destroy_window (GtkObject *obj, NautilusApplication *application)
334
{
335 336 337
	application->windows = g_slist_remove (application->windows, obj);
	if (application->windows == NULL) {
  		nautilus_application_quit();
338
	}
339 340 341
}

void 
342
nautilus_application_quit (void)
343
{
344
	gtk_main_quit ();
345 346 347
}

NautilusWindow *
348
nautilus_application_create_window (NautilusApplication *application)
349
{
350
	NautilusWindow *window;
351 352

	g_return_val_if_fail (NAUTILUS_IS_APPLICATION (application), NULL);
353
	
354
	window = NAUTILUS_WINDOW (gtk_object_new (nautilus_window_get_type (),
355
						  "app", GTK_OBJECT (application),
356 357
						  "app_id", "nautilus", NULL));
	gtk_signal_connect (GTK_OBJECT (window),
358 359 360 361
			    "destroy", nautilus_application_destroy_window,
			    application);

	application->windows = g_slist_prepend (application->windows, window);
362

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
363
	/* Do not yet show the window. It will be shown later on if it can
364 365 366
	 * successfully display its initial URI. Otherwise it will be destroyed
	 * without ever having seen the light of day.
	 */
367

368
	return window;
369
}