nautilus-application.c 11 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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
	Nautilus_ViewWindowList *retval;

	retval = Nautilus_ViewWindowList__alloc();
	retval->_length = g_slist_length(servant->app->windows);

	if(retval->_length)
	{
		int i;
		GSList *ltmp;

		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);
		}
	}
	else {
     		retval->_buffer = NULL;
     	}

	CORBA_sequence_set_release(retval, CORBA_TRUE);

	return retval;
112 113
}

Gene Ragan's avatar
Gene Ragan committed
114

115 116 117
static Nautilus_ViewWindow
impl_Nautilus_Application_new_view_window(impl_POA_Nautilus_Application *servant, CORBA_Environment * ev)
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
118
	NautilusWindow *win;
119

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
120
	win = nautilus_app_create_window (servant->app);
121

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
122
	return CORBA_Object_duplicate (bonobo_object_corba_objref (BONOBO_OBJECT (win)), ev);
123 124 125 126
}

static CORBA_boolean
impl_Nautilus_Application_supports(impl_POA_Nautilus_Application * servant,
127
				   CORBA_char * obj_iid,
128 129
				   CORBA_Environment * ev)
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
130 131 132
	return (!strcmp(obj_iid, "OAFIID:ntl_file_manager_icon_view:42681b21-d5ca-4837-87d2-394d88ecc058")
		|| !strcmp(obj_iid, "OAFIID:ntl_file_manager_list_view:521e489d-0662-4ad7-ac3a-832deabe111c")
		|| !strcmp(obj_iid, "OAFIID:ntl_window:88e8b2e4-b627-4221-b566-5ba32185c88d"));
133 134 135 136
}

static CORBA_Object
impl_Nautilus_Application_create_object(impl_POA_Nautilus_Application *servant,
137
                                        CORBA_char *obj_iid,
138 139 140
					GNOME_stringlist * params,
					CORBA_Environment * ev)
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
141 142 143
	CORBA_Object retval = CORBA_OBJECT_NIL;
	FMDirectoryView *dir_view;
	NautilusContentViewFrame *view_frame;
144

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
145 146
	if(!impl_Nautilus_Application_supports(servant, obj_iid, ev))
		return CORBA_OBJECT_NIL;
147
        
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
148 149 150 151 152 153 154 155 156
	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) {
		retval = impl_Nautilus_Application_new_view_window (servant, ev);
	} else {
		dir_view = NULL;
	}
157
        
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
158
  	g_return_val_if_fail(dir_view, CORBA_OBJECT_NIL);
159
        
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
160 161 162
  	if(dir_view)
    	{
      		view_frame = fm_directory_view_get_view_frame (dir_view);
163

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
164 165
		retval = CORBA_Object_duplicate(bonobo_object_corba_objref(BONOBO_OBJECT(view_frame)), ev);
    	}
166

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
167
  	return retval;
168 169 170
}


171 172 173 174 175
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
176
	impl_POA_Nautilus_Application *newservant;
177

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
178 179 180 181 182
	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);
183 184 185 186 187 188 189 190 191 192 193
}

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
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
	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;
214 215 216 217 218
}

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

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

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
223 224
	object_class = (GtkObjectClass*) klass;
	object_class->destroy = nautilus_app_destroy;
225

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
226
	app_parent_class = gtk_type_class (gtk_object_get_type ());
227 228 229 230 231 232 233 234

	/*
	 * Startup preferences.  This call is needed so that preferences have
	 * 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 ();
235 236 237 238 239
}

static void
nautilus_app_init (NautilusApp *app)
{
240 241 242 243 244
	CORBA_Environment ev;
	CORBA_Object objref;
	
	CORBA_exception_init(&ev);
	objref = impl_Nautilus_Application__create(bonobo_poa(), app, &ev);
245

246
	oaf_active_server_register("OAFIID:ntl_file_manager_factory:bd1e1862-92d7-4391-963e-37583f0daef3", objref);
247

248
	bonobo_object_construct(BONOBO_OBJECT(app), objref);
249

250
	/* Init undo manager */
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
251 252
	app->undo_manager = BONOBO_OBJECT (nautilus_undo_manager_new ());

253
	CORBA_exception_free(&ev);
254 255 256
}

GtkObject *
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
257
nautilus_app_new (void)
258
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
259
	return gtk_object_new(nautilus_app_get_type(), NULL);
260 261 262
}

static void
263
nautilus_app_destroy (GtkObject *object)
264
{
265 266
	/*
	 * Shutdown preferences.  This is needed so that the global preferences
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
267
	 * object and all its allocations are freed.  Not calling this function
268 269 270 271 272
	 * 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. 
	 */
	nautilus_global_preferences_shutdown ();
273

274
	nautilus_bookmarks_exiting ();
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
275
	GTK_OBJECT_CLASS(app_parent_class)->destroy(object);
276 277
}

278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
static void
display_prototype_caveat ()
{
	/* Inform the user that Nautilus has a long way to go
	 * before they should be expecting it to work well.
	 */
	nautilus_simple_dialog (
		NULL,
		_("Thank you for trying Nautilus!"
		  "\n\nIt is still under development, and many features "
		  "are not yet implemented or have some degree of instability. "
		  "Use it at your own risk."
		  "\n\nFor more information, visit http://nautilus.eazel.com."),
		 _("Nautilus: caveat"),
		 GNOME_STOCK_BUTTON_OK,
		 NULL);
}

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

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

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

static void
311
nautilus_app_destroy_window (GtkObject *obj, NautilusApp *app)
312
{
313
	app->windows = g_slist_remove(app->windows, obj);
314

315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
	if (app->windows == NULL)
  		nautilus_app_quit();
}

extern int gnome_vfs_debug_get_thread_count (void);
int quit_counter_hack;

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); */
	usleep(200000);
	
	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);
350 351 352
}

NautilusWindow *
353
nautilus_app_create_window(NautilusApp *app)
354
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
355 356 357 358
	GtkWidget *win;

	win = GTK_WIDGET (gtk_object_new (nautilus_window_get_type(), "app", BONOBO_OBJECT(app),
			  "app_id", "nautilus", NULL));
359

360

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
361
	gtk_signal_connect (GTK_OBJECT (win), "destroy", nautilus_app_destroy_window, app);
362

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

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
368
	app->windows = g_slist_prepend(app->windows, win);
369

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
370
	return NAUTILUS_WINDOW(win);
371
}