nautilus-application.c 11.1 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-global-preferences.h>
35
#include <libnautilus/nautilus-undo-manager.h>
36

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

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

44 45 46
static Nautilus_ViewWindowList *
impl_Nautilus_Application__get_view_windows(impl_POA_Nautilus_Application* servant,
                                            CORBA_Environment * ev);
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
47
static Nautilus_Undo_Manager
Gene Ragan's avatar
Gene Ragan committed
48 49
impl_Nautilus_Application__get_undo_manager(impl_POA_Nautilus_Application* servant,
                                            CORBA_Environment * ev);
50 51 52 53 54
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,
55
				   CORBA_char *obj_iid,
56 57 58
				   CORBA_Environment * ev);
static CORBA_Object
impl_Nautilus_Application_create_object(impl_POA_Nautilus_Application *servant,
59
                                        CORBA_char *obj_iid,
60 61 62
					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
63 64 65 66
	NULL,			/* _private */
	(gpointer) &impl_Nautilus_Application__get_view_windows,
	(gpointer) &impl_Nautilus_Application__get_undo_manager,
	(gpointer) &impl_Nautilus_Application_new_view_window
67 68

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

static Nautilus_ViewWindowList *
87 88
impl_Nautilus_Application__get_view_windows(impl_POA_Nautilus_Application *servant,
                                            CORBA_Environment * ev)
89
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
	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;
115 116
}

Gene Ragan's avatar
Gene Ragan committed
117

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
118
static Nautilus_Undo_Manager
Gene Ragan's avatar
Gene Ragan committed
119 120 121 122 123 124 125
impl_Nautilus_Application__get_undo_manager(impl_POA_Nautilus_Application *servant,
                                            CORBA_Environment * ev)
{
	return CORBA_Object_duplicate(bonobo_object_corba_objref(servant->app->undo_manager), ev);
}


126 127 128
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
129
	NautilusWindow *win;
130

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

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
133
	return CORBA_Object_duplicate (bonobo_object_corba_objref (BONOBO_OBJECT (win)), ev);
134 135 136 137
}

static CORBA_boolean
impl_Nautilus_Application_supports(impl_POA_Nautilus_Application * servant,
138
				   CORBA_char * obj_iid,
139 140
				   CORBA_Environment * ev)
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
141 142 143
	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"));
144 145 146 147
}

static CORBA_Object
impl_Nautilus_Application_create_object(impl_POA_Nautilus_Application *servant,
148
                                        CORBA_char *obj_iid,
149 150 151
					GNOME_stringlist * params,
					CORBA_Environment * ev)
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
152 153 154
	CORBA_Object retval = CORBA_OBJECT_NIL;
	FMDirectoryView *dir_view;
	NautilusContentViewFrame *view_frame;
155

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
156 157
	if(!impl_Nautilus_Application_supports(servant, obj_iid, ev))
		return CORBA_OBJECT_NIL;
158
        
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
159 160 161 162 163 164 165 166 167
	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;
	}
168
        
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
169
  	g_return_val_if_fail(dir_view, CORBA_OBJECT_NIL);
170
        
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
171 172 173
  	if(dir_view)
    	{
      		view_frame = fm_directory_view_get_view_frame (dir_view);
174

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
175 176
		retval = CORBA_Object_duplicate(bonobo_object_corba_objref(BONOBO_OBJECT(view_frame)), ev);
    	}
177

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
178
  	return retval;
179 180 181
}


182 183 184 185 186
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
187
	impl_POA_Nautilus_Application *newservant;
188

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
189 190 191 192 193
	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);
194 195 196 197 198 199 200 201 202 203 204
}

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
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
	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;
225 226 227 228 229
}

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

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

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
234 235
	object_class = (GtkObjectClass*) klass;
	object_class->destroy = nautilus_app_destroy;
236

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
237
	app_parent_class = gtk_type_class (gtk_object_get_type ());
238 239 240 241 242 243 244 245

	/*
	 * 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 ();
246 247 248 249 250
}

static void
nautilus_app_init (NautilusApp *app)
{
251 252 253 254 255
	CORBA_Environment ev;
	CORBA_Object objref;
	
	CORBA_exception_init(&ev);
	objref = impl_Nautilus_Application__create(bonobo_poa(), app, &ev);
256

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

259
	bonobo_object_construct(BONOBO_OBJECT(app), objref);
260

261
	/* Init undo manager */
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
262 263 264 265 266 267
	app->undo_manager = BONOBO_OBJECT (nautilus_undo_manager_new ());

	/* Add undo manager to the app */	
	g_assert (app->undo_manager);
	gtk_object_set_data (GTK_OBJECT (app), "NautilusUndoManager", app->undo_manager);

268
	CORBA_exception_free(&ev);
269 270 271
}

GtkObject *
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
272
nautilus_app_new (void)
273
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
274
	return gtk_object_new(nautilus_app_get_type(), NULL);
275 276 277 278
}

static void
nautilus_app_destroy(GtkObject *object)
279
{
280 281
	/*
	 * Shutdown preferences.  This is needed so that the global preferences
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
282
	 * object and all its allocations are freed.  Not calling this function
283 284 285 286 287
	 * 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 ();
288

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
289 290
	nautilus_bookmarks_exiting (object);
	GTK_OBJECT_CLASS(app_parent_class)->destroy(object);
291 292
}

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

298
  	/* Set default configuration */
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
299 300 301
  	mainwin = nautilus_app_create_window (app);
  	bonobo_activate ();
  	nautilus_window_set_initial_state (mainwin, initial_url);  	
302 303 304
}

static void
305
nautilus_app_destroy_window (GtkObject *obj, NautilusApp *app)
306
{
307
	app->windows = g_slist_remove(app->windows, obj);
308

309 310 311 312 313 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
	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);
344 345 346
}

NautilusWindow *
347
nautilus_app_create_window(NautilusApp *app)
348
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
349 350 351 352
	GtkWidget *win;

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

354

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

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
357 358 359 360
	/* 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.
	*/
361

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

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