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.h"
29
#include <libnautilus/libnautilus.h>
30
#include <bonobo.h>
31 32
#include "file-manager/fm-icon-view.h"
#include "file-manager/fm-list-view.h"
33
#include <libgnomevfs/gnome-vfs-init.h>
34
#include <libnautilus-extensions/nautilus-gnome-extensions.h>
35
#include <libnautilus-extensions/nautilus-global-preferences.h>
36
#include <libnautilus/nautilus-undo-manager.h>
37

38
typedef struct {
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
39 40
	POA_Nautilus_Application servant;
 	NautilusApp *app;
41

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
42
	Nautilus_ViewWindowList attr_view_windows;
43
} impl_POA_Nautilus_Application;
44

45 46 47 48 49 50 51 52
static Nautilus_ViewWindowList *
impl_Nautilus_Application__get_view_windows(impl_POA_Nautilus_Application* servant,
                                            CORBA_Environment * ev);
static Nautilus_ViewWindow
impl_Nautilus_Application_new_view_window(impl_POA_Nautilus_Application *servant,
                                          CORBA_Environment * ev);
static CORBA_boolean
impl_Nautilus_Application_supports(impl_POA_Nautilus_Application * servant,
53
				   CORBA_char *obj_iid,
54 55 56
				   CORBA_Environment * ev);
static CORBA_Object
impl_Nautilus_Application_create_object(impl_POA_Nautilus_Application *servant,
57
                                        CORBA_char *obj_iid,
58 59 60
					GNOME_stringlist * params,
					CORBA_Environment * ev);
static POA_Nautilus_Application__epv impl_Nautilus_Application_epv = {
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
61 62 63
	NULL,			/* _private */
	(gpointer) &impl_Nautilus_Application__get_view_windows,
	(gpointer) &impl_Nautilus_Application_new_view_window
64 65

};
66
static POA_Bonobo_GenericFactory__epv impl_Nautilus_Application_Bonobo_GenericFactory_epv = {
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
67 68 69
	NULL,			/* _private */
	(gpointer) &impl_Nautilus_Application_supports,
	(gpointer) &impl_Nautilus_Application_create_object
70 71
};
static PortableServer_ServantBase__epv impl_Nautilus_Application_base_epv = {
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
72 73 74
	NULL,			/* _private data */
	NULL,			/* finalize routine */
	NULL,			/* default_POA routine */
75 76
};
static POA_Nautilus_Application__vepv impl_Nautilus_Application_vepv = {
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
77 78 79 80
	&impl_Nautilus_Application_base_epv,
	&impl_Nautilus_Application_Bonobo_GenericFactory_epv,
	NULL,
	&impl_Nautilus_Application_epv,
81 82 83
};

static Nautilus_ViewWindowList *
84 85
impl_Nautilus_Application__get_view_windows(impl_POA_Nautilus_Application *servant,
                                            CORBA_Environment * ev)
86
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
87
	Nautilus_ViewWindowList *retval;
88 89
	int i;
	GSList *ltmp;
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
90

91 92
	retval = Nautilus_ViewWindowList__alloc ();
	retval->_length = g_slist_length (servant->app->windows);
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
93

94 95 96 97 98
	retval->_buffer = CORBA_sequence_Nautilus_ViewWindow_allocbuf (retval->_length);
	for(i = 0, ltmp = servant->app->windows; ltmp; ltmp = ltmp->next, i++) {
		CORBA_Object obj;
		obj = bonobo_object_corba_objref(NAUTILUS_WINDOW(ltmp->data)->ntl_viewwindow);
		retval->_buffer[i] = CORBA_Object_duplicate(obj, ev);
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
99 100
	}

101
	CORBA_sequence_set_release (retval, CORBA_TRUE);
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
102 103

	return retval;
104 105
}

Gene Ragan's avatar
Gene Ragan committed
106

107
static Nautilus_ViewWindow
108 109
impl_Nautilus_Application_new_view_window (impl_POA_Nautilus_Application *servant,
					   CORBA_Environment * ev)
110
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
111
	NautilusWindow *win;
112

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
113 114
	win = nautilus_app_create_window (servant->app);
	return CORBA_Object_duplicate (bonobo_object_corba_objref (BONOBO_OBJECT (win)), ev);
115 116 117
}

static CORBA_boolean
118 119 120
impl_Nautilus_Application_supports (impl_POA_Nautilus_Application * servant,
				    CORBA_char * obj_iid,
				    CORBA_Environment * ev)
121
{
122 123 124
	return strcmp(obj_iid, "OAFIID:ntl_file_manager_icon_view:42681b21-d5ca-4837-87d2-394d88ecc058") == 0
		|| strcmp(obj_iid, "OAFIID:ntl_file_manager_list_view:521e489d-0662-4ad7-ac3a-832deabe111c") == 0
		|| strcmp(obj_iid, "OAFIID:ntl_window:88e8b2e4-b627-4221-b566-5ba32185c88d") == 0;
125 126 127
}

static CORBA_Object
128 129 130 131
impl_Nautilus_Application_create_object (impl_POA_Nautilus_Application *servant,
					 CORBA_char *obj_iid,
					 GNOME_stringlist * params,
					 CORBA_Environment * ev)
132
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
133
	FMDirectoryView *dir_view;
134
	NautilusContentView *view;
135

136
	if (!impl_Nautilus_Application_supports (servant, obj_iid, ev)) {
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
137
		return CORBA_OBJECT_NIL;
138
	}
139
        
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
140 141 142 143 144
	if (strcmp (obj_iid, "OAFIID:ntl_file_manager_icon_view:42681b21-d5ca-4837-87d2-394d88ecc058") == 0) {
		dir_view = FM_DIRECTORY_VIEW (gtk_object_new (fm_icon_view_get_type (), NULL));
	} else if (strcmp (obj_iid, "OAFIID:ntl_file_manager_list_view:521e489d-0662-4ad7-ac3a-832deabe111c") == 0) {
		dir_view = FM_DIRECTORY_VIEW (gtk_object_new (fm_list_view_get_type (), NULL));
	} else if (strcmp (obj_iid,"OAFIID:ntl_window:88e8b2e4-b627-4221-b566-5ba32185c88d") == 0) {
145
		return impl_Nautilus_Application_new_view_window (servant, ev);
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
146
	} else {
147
		return CORBA_OBJECT_NIL;
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
148
	}
149
        
150 151
	view = fm_directory_view_get_nautilus_view (dir_view);
	return CORBA_Object_duplicate (bonobo_object_corba_objref (BONOBO_OBJECT (view)), ev);
152 153 154
}


155 156 157 158 159
static CORBA_Object
impl_Nautilus_Application__create(PortableServer_POA poa,
                                  NautilusApp *app,
				  CORBA_Environment * ev)
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
160
	impl_POA_Nautilus_Application *newservant;
161

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
162 163 164 165 166
	newservant = g_new0(impl_POA_Nautilus_Application, 1);
	newservant->servant.vepv = &impl_Nautilus_Application_vepv;
	newservant->servant.vepv->Bonobo_Unknown_epv = NAUTILUS_APP_CLASS(GTK_OBJECT(app)->klass)->unknown_epv;
	POA_Nautilus_Application__init((PortableServer_Servant) newservant, ev);
	return bonobo_object_activate_servant(BONOBO_OBJECT(app), newservant);
167 168 169 170 171 172 173 174 175 176 177
}

static void nautilus_app_init		(NautilusApp		 *app);
static void nautilus_app_class_init	(NautilusAppClass	 *klass);
static void nautilus_app_destroy        (GtkObject *object);

static GtkObjectClass *app_parent_class = NULL;

GtkType
nautilus_app_get_type (void)
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
	static GtkType App_type = 0;

	if (!App_type)
	{
		static const GtkTypeInfo App_info =
		{
			"NautilusApp",
			sizeof (NautilusApp),
			sizeof (NautilusAppClass),
			(GtkClassInitFunc) nautilus_app_class_init,
			(GtkObjectInitFunc) nautilus_app_init,
			/* reserved_1 */ NULL,
			/* reserved_2 */ NULL,
			(GtkClassInitFunc) NULL,
      		};

		App_type = gtk_type_unique (bonobo_object_get_type (), &App_info);
	}

	return App_type;
198 199 200 201 202
}

static void
nautilus_app_class_init (NautilusAppClass *klass)
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
203
	GtkObjectClass *object_class;
204

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
205
	klass->unknown_epv = bonobo_object_get_epv();
206

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
207 208
	object_class = (GtkObjectClass*) klass;
	object_class->destroy = nautilus_app_destroy;
209

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
210
	app_parent_class = gtk_type_class (gtk_object_get_type ());
211

212
	/* Startup preferences.  This call is needed so that preferences have
213 214 215 216 217
	 * decent defaults.  Not calling this function would cause some
	 * preferences to have "not nice" defaults.  Things would still work
	 * because it is legal to use nautilus preferences implicitly. 
	 */
	nautilus_global_preferences_startup ();
218 219 220 221 222
}

static void
nautilus_app_init (NautilusApp *app)
{
223
	CORBA_Environment ev;
224 225
	CORBA_Object objref;
	Nautilus_Undo_Manager undo_manager;
226
	
227
	CORBA_exception_init (&ev);
228

229
	objref = impl_Nautilus_Application__create (bonobo_poa (), app, &ev);
230
	oaf_active_server_register ("OAFIID:ntl_file_manager_factory:bd1e1862-92d7-4391-963e-37583f0daef3",
231 232
				    objref);
	bonobo_object_construct (BONOBO_OBJECT(app), objref);
233

234
	/* Init undo manager */
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
235
	app->undo_manager = BONOBO_OBJECT (nautilus_undo_manager_new ());
236 237 238 239
	undo_manager = bonobo_object_corba_objref (BONOBO_OBJECT (app->undo_manager));
	Bonobo_Unknown_ref (undo_manager, &ev);

	nautilus_attach_undo_manager ( GTK_OBJECT (app), undo_manager);
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
240

241
	CORBA_exception_free (&ev);
242 243 244
}

GtkObject *
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
245
nautilus_app_new (void)
246
{
247
	return gtk_object_new (nautilus_app_get_type (), NULL);
248 249 250
}

static void
251
nautilus_app_destroy (GtkObject *object)
252
{
253 254 255 256 257 258
	/* Shut down preferences.  This is needed so that the global
	 * preferences object and all its allocations are freed.  Not
	 * 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,
	 * but it adds noice to memory profile tool runs.
259 260
	 */
	nautilus_global_preferences_shutdown ();
261

262
	nautilus_bookmarks_exiting ();
263
	GTK_OBJECT_CLASS(app_parent_class)->destroy (object);
264 265
}

266
static void
267
display_prototype_caveat (void)
268 269 270 271
{
	/* Inform the user that Nautilus has a long way to go
	 * before they should be expecting it to work well.
	 */
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
	if (getenv ("NAUTILUS_NO_CAVEAT_DIALOG") == NULL) {
		/* Before you change this code back to use gnome_warning_dialog
		 * or nautilus_warning_dialog, you better test it. See bug 963.
		 */
		nautilus_simple_dialog
			(NULL,
			 _("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 unpredictable and may even "
			   "delete or overwrite files on your computer."
			   "\n\n"
			   "For more information, visit http://nautilus.eazel.com."),
			 _("Nautilus: caveat"),
			 GNOME_STOCK_BUTTON_OK, NULL);
292
	}
293 294
}

295
void
296
nautilus_app_startup(NautilusApp *app, const char *initial_url)
297
{
298
	NautilusWindow *mainwin;
299

300
	/* Put up (modal) caveat. */
301
	display_prototype_caveat ();
302

303
  	/* Set default configuration */
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
304 305
  	mainwin = nautilus_app_create_window (app);
  	bonobo_activate ();
306
  	nautilus_window_set_initial_state (mainwin, initial_url);
307 308 309
}

static void
310
nautilus_app_destroy_window (GtkObject *obj, NautilusApp *app)
311
{
312 313
	app->windows = g_slist_remove (app->windows, obj);
	if (app->windows == NULL) {
314
  		nautilus_app_quit();
315
	}
316 317
}

318 319 320
/* FIXME: If we are really going to use this, it should probably be
 * moved to the gnome vfs public interface.
 */
321 322 323
extern int gnome_vfs_debug_get_thread_count (void);
int quit_counter_hack;

324 325 326 327
/* FIXME: This waiting for quit is needed by anyone who uses gnome-vfs,
 * especially users or NautilusDirectory. So we need to provide it for
 * others who are not using NautilusApp.
 */
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
static gboolean
nautilus_app_real_quit (void *unused)
{
	int count;

	count = gnome_vfs_debug_get_thread_count ();
	if (count == 0) {
		/* g_message ("no more gnome vfs threads, ready to quit"); */
		gtk_main_quit ();
		return FALSE;
	} 
	if (--quit_counter_hack == 0) {
		g_message ("gnome vfs threads not going away, trying to quit anyway");
		gtk_main_quit ();
		return FALSE;
	}
	/* g_message ("%d gnome vfs threads left, will try to quit later", count); */
345
	usleep(200000); /* 1/5 second */
346 347 348 349 350 351 352 353 354 355
	
	return TRUE;
}

void 
nautilus_app_quit (void)
{
	quit_counter_hack = 20;
	/* wait for gnome vfs slave threads to go away before quitting */
	gtk_idle_add ((GtkFunction)nautilus_app_real_quit, NULL);
356 357 358
}

NautilusWindow *
359
nautilus_app_create_window (NautilusApp *app)
360
{
361
	NautilusWindow *window;
362
	
363 364 365 366 367
	window = NAUTILUS_WINDOW (gtk_object_new (nautilus_window_get_type(), "app", BONOBO_OBJECT(app),
						  "app_id", "nautilus", NULL));
	
	gtk_signal_connect (GTK_OBJECT (window),
			    "destroy", nautilus_app_destroy_window, app);
368

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
369
	/* Do not yet show the window. It will be shown later on if it can
370 371 372 373
	 * successfully display its initial URI. Otherwise it will be destroyed
	 * without ever having seen the light of day.
	 */
	app->windows = g_slist_prepend (app->windows, window);
374

375
	return window;
376
}