1 /*
2  * Copyright (C) 2009 - 2011 Vivien Malerba <malerba@gnome-db.org>
3  * Copyright (C) 2010 David King <davidk@openismus.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  */
19 
20 #include <string.h>
21 #include <glib/gi18n-lib.h>
22 #include "browser-core.h"
23 #include "browser-window.h"
24 #include "browser-connection.h"
25 
26 /*
27  * Main static functions
28  */
29 static void browser_core_class_init (BrowserCoreClass *klass);
30 static void browser_core_init (BrowserCore *bcore);
31 static void browser_core_dispose (GObject *object);
32 
33 /* get a pointer to the parents to be able to call their destructor */
34 static GObjectClass  *parent_class = NULL;
35 
36 /* pointer to the singleton */
37 static BrowserCore *_bcore = NULL;
38 
39 /* signals */
40 enum
41 	{
42 		CNC_ADDED,
43 		CNC_REMOVED,
44 		LAST_SIGNAL
45 	};
46 
47 static gint browser_core_signals[LAST_SIGNAL] = { 0, 0 };
48 
49 struct _BrowserCorePrivate {
50 	GSList         *factories; /* list of PerspectiveFactory pointers, statically compiled */
51         BrowserPerspectiveFactory *default_factory; /* used by default, no ref held on it */
52         GSList         *connections; /* list of BrowserConnection objects, referenced here */
53         GSList         *windows; /* list of BrowserWindow pointers: list of opened windows */
54 };
55 
56 GType
browser_core_get_type(void)57 browser_core_get_type (void)
58 {
59 	static GType type = 0;
60 
61 	if (G_UNLIKELY (type == 0)) {
62 		static GMutex registering;
63 		static const GTypeInfo info = {
64 			sizeof (BrowserCoreClass),
65 			(GBaseInitFunc) NULL,
66 			(GBaseFinalizeFunc) NULL,
67 			(GClassInitFunc) browser_core_class_init,
68 			NULL,
69 			NULL,
70 			sizeof (BrowserCore),
71 			0,
72 			(GInstanceInitFunc) browser_core_init,
73 			0
74 		};
75 
76 
77 		g_mutex_lock (&registering);
78 		if (type == 0)
79 			type = g_type_register_static (G_TYPE_OBJECT, "BrowserCore", &info, 0);
80 		g_mutex_unlock (&registering);
81 	}
82 	return type;
83 }
84 
85 static void
browser_core_class_init(BrowserCoreClass * klass)86 browser_core_class_init (BrowserCoreClass *klass)
87 {
88 	GObjectClass   *object_class = G_OBJECT_CLASS (klass);
89 	parent_class = g_type_class_peek_parent (klass);
90 
91         browser_core_signals[CNC_ADDED] =
92                 g_signal_new ("connection-added",
93                               G_TYPE_FROM_CLASS (object_class),
94                               G_SIGNAL_RUN_FIRST,
95                               G_STRUCT_OFFSET (BrowserCoreClass, connection_added),
96                               NULL, NULL,
97 			      g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BROWSER_TYPE_CONNECTION);
98 
99         browser_core_signals[CNC_REMOVED] =
100                 g_signal_new ("connection-removed",
101                               G_TYPE_FROM_CLASS (object_class),
102                               G_SIGNAL_RUN_FIRST,
103                               G_STRUCT_OFFSET (BrowserCoreClass, connection_removed),
104                               NULL, NULL,
105 			      g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, BROWSER_TYPE_CONNECTION);
106 
107 	klass->connection_added = NULL;
108 	klass->connection_removed = NULL;
109 
110 	object_class->dispose = browser_core_dispose;
111 }
112 
113 BrowserCoreInitFactories browser_core_init_factories = NULL;
114 
115 static void
browser_core_init(BrowserCore * bcore)116 browser_core_init (BrowserCore *bcore)
117 {
118 	bcore->priv = g_new0 (BrowserCorePrivate, 1);
119 	bcore->priv->factories = NULL;
120 
121 	if (browser_core_init_factories)
122 		bcore->priv->factories = browser_core_init_factories ();
123 
124 	/* set default perspective */
125 	if (bcore->priv->factories)
126 		bcore->priv->default_factory = (BrowserPerspectiveFactory*) bcore->priv->factories->data;
127 
128 	bcore->priv->windows = NULL;
129 }
130 
131 /**
132  * browser_core_exists
133  *
134  * Tells if a #BrowserCore has already been created
135  *
136  * Returns: %TRUE if the #BrowserCore singleton has already been created
137  */
138 gboolean
browser_core_exists(void)139 browser_core_exists (void)
140 {
141 	return _bcore ? TRUE : FALSE;
142 }
143 
144 /**
145  * browser_core_get
146  *
147  * Returns a #BrowserCore object which holds the browser's configuration. This is
148  * a singleton factory.
149  *
150  * Returns: the #BrowserCore object
151  */
152 BrowserCore*
browser_core_get(void)153 browser_core_get (void)
154 {
155 	if (!_bcore)
156 		_bcore = BROWSER_CORE (g_object_new (BROWSER_TYPE_CORE, NULL));
157 
158 	return _bcore;
159 }
160 
161 static void
browser_core_dispose(GObject * object)162 browser_core_dispose (GObject *object)
163 {
164 	BrowserCore *bcore;
165 
166 	g_return_if_fail (object != NULL);
167 	g_return_if_fail (BROWSER_IS_CORE (object));
168 
169 	bcore = BROWSER_CORE (object);
170 	if (bcore->priv) {
171 		if (bcore->priv->factories) {
172 			g_slist_free (bcore->priv->factories);
173 			bcore->priv->factories = NULL;
174 		}
175 		bcore->priv->default_factory = NULL;
176 
177 		if (bcore->priv->windows) {
178 			g_slist_foreach (bcore->priv->windows, (GFunc) g_object_unref, NULL);
179 			g_slist_free (bcore->priv->windows);
180 			bcore->priv->windows = NULL;
181 		}
182 
183 		g_free (bcore->priv);
184 		bcore->priv = NULL;
185 	}
186 
187 	/* parent class */
188 	parent_class->dispose (object);
189 }
190 
191 /**
192  * browser_core_take_window
193  * @bwin: a #BrowserWindow
194  *
195  * Makes sure @bwin is handled by the #BrowserCore object, reference to @bwin is stolen here.
196  * This method should be called after a #BrowserWindow has been created to have it managed properly.
197  */
198 void
browser_core_take_window(BrowserWindow * bwin)199 browser_core_take_window (BrowserWindow *bwin)
200 {
201         g_return_if_fail (BROWSER_IS_WINDOW (bwin));
202 
203         _bcore = browser_core_get ();
204         _bcore->priv->windows = g_slist_append (_bcore->priv->windows, bwin);
205 }
206 
207 /**
208  * browser_core_close_window
209  * @bwin: a #BrowserWindow
210  *
211  * Requests that @bwin be closed.
212  */
213 void
browser_core_close_window(BrowserWindow * bwin)214 browser_core_close_window (BrowserWindow *bwin)
215 {
216 	g_return_if_fail (BROWSER_IS_WINDOW (bwin));
217 	_bcore = browser_core_get ();
218 	g_return_if_fail (g_slist_find (_bcore->priv->windows, bwin));
219 
220 	_bcore->priv->windows = g_slist_remove (_bcore->priv->windows, bwin);
221 	gtk_widget_destroy (GTK_WIDGET (bwin));
222 
223 	if (! _bcore->priv->windows) {
224 		/* no more windows left => quit */
225 		g_print ("Closed last window, bye!\n");
226 		browser_core_quit ();
227 	}
228 }
229 
230 /**
231  * browser_core_get_windows
232  *
233  * Get a list of #BrowserWindow mananged by the browser (windows must have been
234  * declared using browser_core_take_window()).
235  *
236  * Returns: a new list, free it with g_slist_free()
237  */
238 GSList *
browser_core_get_windows(void)239 browser_core_get_windows (void)
240 {
241 	_bcore = browser_core_get ();
242 	if (_bcore->priv->windows)
243 		return g_slist_copy (_bcore->priv->windows);
244 	else
245 		return NULL;
246 }
247 
248 /**
249  * browser_core_take_connection
250  * @bcnc: a #BrowserConnection
251  *
252  * Makes sure @bcnc is handled by @dbata, reference to @bcnc is stolen here
253  */
254 void
browser_core_take_connection(BrowserConnection * bcnc)255 browser_core_take_connection (BrowserConnection *bcnc)
256 {
257         g_return_if_fail (BROWSER_IS_CONNECTION (bcnc));
258 
259         _bcore = browser_core_get ();
260         _bcore->priv->connections = g_slist_append (_bcore->priv->connections, bcnc);
261 	g_signal_emit (_bcore, browser_core_signals [CNC_ADDED], 0, bcnc);
262 }
263 
264 /**
265  * browser_core_close_connection
266  * @bcnc: a #BrowserConnection
267  *
268  * Requests that @bcnc be closed.
269  */
270 void
browser_core_close_connection(BrowserConnection * bcnc)271 browser_core_close_connection (BrowserConnection *bcnc)
272 {
273         g_return_if_fail (g_slist_find (_bcore->priv->connections, bcnc));
274 
275         _bcore = browser_core_get ();
276         _bcore->priv->connections = g_slist_remove (_bcore->priv->connections, bcnc);
277 	g_signal_emit (_bcore, browser_core_signals [CNC_REMOVED], 0, bcnc);
278         g_object_unref (bcnc);
279 }
280 
281 /**
282  * browser_core_get_connections
283  *
284  * Get a list of #BrowserWindow
285  *
286  * Returns: a new list, free it with g_slist_free()
287  */
288 GSList *
browser_core_get_connections(void)289 browser_core_get_connections (void)
290 {
291 	_bcore = browser_core_get ();
292 	if (_bcore->priv->connections)
293 		return g_slist_copy (_bcore->priv->connections);
294 	else
295 		return NULL;
296 }
297 
298 /**
299  * browser_core_get_factory
300  * @factory: the name of the requested factory
301  *
302  * Get a pointer to a #BrowserPerspectiveFactory, from its name
303  *
304  * Returns: a pointer to the #BrowserPerspectiveFactory, or %NULL if not found
305  */
306 BrowserPerspectiveFactory *
browser_core_get_factory(const gchar * factory)307 browser_core_get_factory (const gchar *factory)
308 {
309 	GSList *list;
310 	g_return_val_if_fail (factory, NULL);
311 	_bcore = browser_core_get ();
312 	for (list = _bcore->priv->factories; list; list = list->next) {
313 		BrowserPerspectiveFactory *bpf = BROWSER_PERSPECTIVE_FACTORY (list->data);
314 		if (!g_ascii_strcasecmp (bpf->perspective_name, factory))
315 			return bpf;
316 	}
317 	return NULL;
318 }
319 
320 /**
321  * browser_core_get_default_factory
322  *
323  * Get the default #BrowserPerspectiveFactory used when making new #BrowserWindow if none
324  * is provided when calling browser_window_new().
325  *
326  * Returns: the default #BrowserPerspectiveFactory
327  */
328 BrowserPerspectiveFactory *
browser_core_get_default_factory(void)329 browser_core_get_default_factory (void)
330 {
331 	_bcore = browser_core_get ();
332 	return _bcore->priv->default_factory;
333 }
334 
335 /**
336  * browser_core_set_default_factory
337  * @factory: the name of a #BrowserPerspectiveFactory
338  *
339  * Sets the default #BrowserPerspectiveFactory used when making new #BrowserWindow if none
340  * is provided when calling browser_window_new().
341  */
342 void
browser_core_set_default_factory(const gchar * factory)343 browser_core_set_default_factory (const gchar *factory)
344 {
345 	GSList *list;
346 	gchar *lc2;
347 	_bcore = browser_core_get ();
348 
349 	if (!factory)
350 		return;
351 
352 	lc2 = g_utf8_strdown (factory, -1);
353 	for (list = _bcore->priv->factories; list; list = list->next) {
354 		BrowserPerspectiveFactory *fact = (BrowserPerspectiveFactory*) list->data;
355 		gchar *lc1;
356 		lc1 = g_utf8_strdown (fact->perspective_name, -1);
357 
358 		if (strstr (lc1, lc2)) {
359 			_bcore->priv->default_factory = fact;
360 			g_free (lc1);
361 			break;
362 		}
363 
364 		g_free (lc1);
365 	}
366 	g_free (lc2);
367 }
368 
369 /**
370  * browser_core_get_factories
371  *
372  * Get a list of all the known Perspective factories
373  *
374  * Returns: a constant list which must not be altered
375  */
376 const GSList *
browser_core_get_factories(void)377 browser_core_get_factories (void)
378 {
379 	_bcore = browser_core_get ();
380 	return _bcore->priv->factories;
381 }
382 
383 /**
384  * browser_core_quit
385  *
386  * Quits the browser after having made some clean-ups
387  */
388 void
browser_core_quit(void)389 browser_core_quit (void)
390 {
391 	if (_bcore) {
392 		g_object_unref (_bcore);
393 		_bcore = NULL;
394 	}
395         gtk_main_quit();
396 }
397