nautilus-application.c 10.4 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 47 48 49 50 51
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,
52
				   CORBA_char *obj_iid,
53 54 55
				   CORBA_Environment * ev);
static CORBA_Object
impl_Nautilus_Application_create_object(impl_POA_Nautilus_Application *servant,
56
                                        CORBA_char *obj_iid,
57 58 59
					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
60 61 62
	NULL,			/* _private */
	(gpointer) &impl_Nautilus_Application__get_view_windows,
	(gpointer) &impl_Nautilus_Application_new_view_window
63 64

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

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

Gene Ragan's avatar
Gene Ragan committed
113

114 115 116
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
117
	NautilusWindow *win;
118

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

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

static CORBA_boolean
impl_Nautilus_Application_supports(impl_POA_Nautilus_Application * servant,
126
				   CORBA_char * obj_iid,
127 128
				   CORBA_Environment * ev)
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
129 130 131
	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"));
132 133 134 135
}

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

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

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

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


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

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

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

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

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

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

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

	/*
	 * 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 ();
234 235 236 237 238
}

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

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

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

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

252
	CORBA_exception_free(&ev);
253 254 255
}

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

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

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

277
void
278
nautilus_app_startup(NautilusApp *app, const char *initial_url)
279
{
280
	NautilusWindow *mainwin;
281

282
  	/* Set default configuration */
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
283 284 285
  	mainwin = nautilus_app_create_window (app);
  	bonobo_activate ();
  	nautilus_window_set_initial_state (mainwin, initial_url);  	
286 287 288
}

static void
289
nautilus_app_destroy_window (GtkObject *obj, NautilusApp *app)
290
{
291
	app->windows = g_slist_remove(app->windows, obj);
292

293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
	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);
328 329 330
}

NautilusWindow *
331
nautilus_app_create_window(NautilusApp *app)
332
{
Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
333 334 335 336
	GtkWidget *win;

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

338

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

Gene Z. Ragan's avatar
CVS:  
Gene Z. Ragan committed
341 342 343 344
	/* 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.
	*/
345

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

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