nautilus-application.c 12 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
	undo_manager = bonobo_object_corba_objref (BONOBO_OBJECT (app->undo_manager));
237
	/* Fix this */
238
239
	Bonobo_Unknown_ref (undo_manager, &ev);

240
241
242
243
	/* Stash a global reference to the object */
	nautilus_undo_manager_stash_global_undo (undo_manager);

	/* Add it to the application object*/
244
	nautilus_attach_undo_manager ( GTK_OBJECT (app), undo_manager);
Gene Z. Ragan's avatar
CVS:    
Gene Z. Ragan committed
245

246
	CORBA_exception_free (&ev);
247
248
249
}

GtkObject *
Gene Z. Ragan's avatar
CVS:    
Gene Z. Ragan committed
250
nautilus_app_new (void)
251
{
252
	return gtk_object_new (nautilus_app_get_type (), NULL);
253
254
255
}

static void
256
nautilus_app_destroy (GtkObject *object)
257
{
258
259
260
261
262
263
	/* 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.
264
265
	 */
	nautilus_global_preferences_shutdown ();
266

267
	nautilus_bookmarks_exiting ();
268
	GTK_OBJECT_CLASS(app_parent_class)->destroy (object);
269
270
}

271
static void
272
display_prototype_caveat (void)
273
274
275
276
{
	/* Inform the user that Nautilus has a long way to go
	 * before they should be expecting it to work well.
	 */
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
	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);
297
	}
298
299
}

300
void
301
nautilus_app_startup(NautilusApp *app, const char *initial_url)
302
{
303
	NautilusWindow *mainwin;
304

305
	/* Put up (modal) caveat. */
306
	display_prototype_caveat ();
307

308
  	/* Set default configuration */
Gene Z. Ragan's avatar
CVS:    
Gene Z. Ragan committed
309
310
  	mainwin = nautilus_app_create_window (app);
  	bonobo_activate ();
311
  	nautilus_window_set_initial_state (mainwin, initial_url);
312
313
314
}

static void
315
nautilus_app_destroy_window (GtkObject *obj, NautilusApp *app)
316
{
317
318
	app->windows = g_slist_remove (app->windows, obj);
	if (app->windows == NULL) {
319
  		nautilus_app_quit();
320
	}
321
322
}

323
324
325
/* FIXME: If we are really going to use this, it should probably be
 * moved to the gnome vfs public interface.
 */
326
327
328
extern int gnome_vfs_debug_get_thread_count (void);
int quit_counter_hack;

329
330
331
332
/* 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.
 */
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
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); */
350
	usleep(200000); /* 1/5 second */
351
352
353
354
355
356
357
358
359
360
	
	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);
361
362
363
}

NautilusWindow *
364
nautilus_app_create_window (NautilusApp *app)
365
{
366
	NautilusWindow *window;
367
	
368
369
370
371
372
	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);
373

Gene Z. Ragan's avatar
CVS:    
Gene Z. Ragan committed
374
	/* Do not yet show the window. It will be shown later on if it can
375
376
377
378
	 * 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);
379

380
	return window;
381
}