1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
2 /* logview-manager.c - manager for the opened log objects
4 * Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 551 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 /* logview-manager.c */
28 #include "logview-manager.h"
30 #include <glib/gi18n.h>
32 #include "logview-prefs.h"
33 #include "logview-marshal.h"
34 #include "logview-app.h"
44 LogviewManager
*manager
;
56 struct _LogviewManagerPrivate
{
58 LogviewLog
*active_log
;
61 static LogviewManager
*singleton
= NULL
;
62 static MultipleCreation
*op
= NULL
;
63 static guint signals
[LAST_SIGNAL
] = { 0 };
65 G_DEFINE_TYPE (LogviewManager
, logview_manager
, G_TYPE_OBJECT
);
67 #define GET_PRIVATE(o) \
68 (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOGVIEW_TYPE_MANAGER, LogviewManagerPrivate))
71 logview_manager_finalize (GObject
*object
)
73 LogviewManager
*manager
;
75 manager
= LOGVIEW_MANAGER (object
);
77 if (manager
->priv
->active_log
) {
78 g_object_unref (manager
->priv
->active_log
);
81 g_hash_table_destroy (manager
->priv
->logs
);
83 G_OBJECT_CLASS (logview_manager_parent_class
)->finalize (object
);
87 logview_manager_class_init (LogviewManagerClass
*klass
)
89 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
91 object_class
->finalize
= logview_manager_finalize
;
93 signals
[LOG_ADDED
] = g_signal_new ("log-added",
94 G_OBJECT_CLASS_TYPE (object_class
),
96 G_STRUCT_OFFSET (LogviewManagerClass
, log_added
),
98 g_cclosure_marshal_VOID__OBJECT
,
102 signals
[LOG_CLOSED
] = g_signal_new ("log-closed",
103 G_OBJECT_CLASS_TYPE (object_class
),
105 G_STRUCT_OFFSET (LogviewManagerClass
, log_closed
),
107 g_cclosure_marshal_VOID__OBJECT
,
111 signals
[ACTIVE_CHANGED
] = g_signal_new ("active-changed",
112 G_OBJECT_CLASS_TYPE (object_class
),
114 G_STRUCT_OFFSET (LogviewManagerClass
, active_changed
),
116 logview_marshal_VOID__OBJECT_OBJECT
,
121 g_type_class_add_private (klass
, sizeof (LogviewManagerPrivate
));
125 logview_manager_init (LogviewManager
*self
)
127 LogviewManagerPrivate
*priv
= self
->priv
= GET_PRIVATE (self
);
129 priv
->active_log
= NULL
;
130 priv
->logs
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
131 (GDestroyNotify
) g_free
, (GDestroyNotify
) g_object_unref
);
134 static MultipleCreation
*
135 multiple_creation_op_new (int total
)
137 MultipleCreation
*retval
;
139 retval
= g_slice_new0 (MultipleCreation
);
140 retval
->total
= total
;
142 retval
->errors
= g_ptr_array_new ();
148 multiple_creation_op_free (MultipleCreation
*mc
)
150 g_ptr_array_foreach (mc
->errors
, (GFunc
) g_strfreev
, NULL
);
151 g_ptr_array_free (mc
->errors
, TRUE
);
153 g_slice_free (MultipleCreation
, mc
);
157 create_log_cb (LogviewLog
*log
,
161 CreateCBData
*data
= user_data
;
168 log_uri
= logview_log_get_uri (log
);
170 /* creation went well, store the log and notify */
171 g_hash_table_insert (data
->manager
->priv
->logs
,
174 prefs
= logview_prefs_get ();
175 file
= logview_log_get_gfile (log
);
176 logview_prefs_store_log (prefs
, file
);
178 g_object_unref (file
);
180 g_signal_emit (data
->manager
, signals
[LOG_ADDED
], 0, log
, NULL
);
182 if (data
->set_active
) {
183 logview_manager_set_active_log (data
->manager
, log
);
188 /* notify the error */
189 path
= g_file_get_path (data
->file
);
191 if (!data
->is_multiple
) {
192 logview_app_add_error (logview_app_get (),
193 path
, error
->message
);
195 char **error_arr
= g_new0 (char *, 3);
197 error_arr
[0] = g_strdup (path
);
198 error_arr
[1] = g_strdup (error
->message
);
201 g_ptr_array_add (op
->errors
, error_arr
);
207 if (data
->is_multiple
) {
210 if (op
->total
== op
->current
) {
211 logview_app_add_errors (logview_app_get (), op
->errors
);
212 multiple_creation_op_free (op
);
217 g_object_unref (data
->file
);
218 g_slice_free (CreateCBData
, data
);
222 add_log_from_gfile_internal (LogviewManager
*manager
,
225 gboolean is_multiple
)
231 file_uri
= g_file_get_uri (file
);
233 if (set_active
== FALSE
) {
234 /* if it's the first log being added, set it as active anyway */
235 set_active
= (manager
->priv
->logs
== NULL
);
238 if ((log
= g_hash_table_lookup (manager
->priv
->logs
, file_uri
)) != NULL
) {
239 /* log already exists, don't load it */
241 logview_manager_set_active_log (manager
, log
);
244 data
= g_slice_new0 (CreateCBData
);
245 data
->manager
= manager
;
246 data
->set_active
= set_active
;
247 data
->is_multiple
= is_multiple
;
248 data
->file
= g_object_ref (file
);
250 logview_log_create_from_gfile (file
, create_log_cb
, data
);
257 logview_manager_add_log_from_name (LogviewManager
*manager
,
258 const char *filename
, gboolean set_active
,
259 gboolean is_multiple
)
263 file
= g_file_new_for_path (filename
);
265 add_log_from_gfile_internal (manager
, file
, set_active
, is_multiple
);
267 g_object_unref (file
);
273 logview_manager_get (void)
276 singleton
= g_object_new (LOGVIEW_TYPE_MANAGER
, NULL
);
283 logview_manager_set_active_log (LogviewManager
*manager
,
286 LogviewLog
*old_log
= NULL
;
288 g_assert (LOGVIEW_IS_MANAGER (manager
));
290 if (manager
->priv
->active_log
) {
291 old_log
= manager
->priv
->active_log
;
294 manager
->priv
->active_log
= g_object_ref (log
);
296 g_signal_emit (manager
, signals
[ACTIVE_CHANGED
], 0, log
, old_log
, NULL
);
299 g_object_unref (old_log
);
304 logview_manager_get_active_log (LogviewManager
*manager
)
306 g_assert (LOGVIEW_IS_MANAGER (manager
));
308 return (manager
->priv
->active_log
!= NULL
) ?
309 g_object_ref (manager
->priv
->active_log
) :
314 logview_manager_add_log_from_gfile (LogviewManager
*manager
,
318 g_assert (LOGVIEW_IS_MANAGER (manager
));
320 add_log_from_gfile_internal (manager
, file
, set_active
, FALSE
);
324 logview_manager_add_logs_from_name_list (LogviewManager
*manager
,
330 g_assert (LOGVIEW_IS_MANAGER (manager
));
331 g_assert (op
== NULL
);
333 op
= multiple_creation_op_new (g_slist_length (names
));
335 for (l
= names
; l
; l
= l
->next
) {
336 logview_manager_add_log_from_name (manager
, l
->data
,
337 (g_ascii_strcasecmp (active
, l
->data
) == 0),
343 logview_manager_add_logs_from_names (LogviewManager
*manager
,
350 g_assert (LOGVIEW_IS_MANAGER (manager
));
351 g_assert (op
== NULL
);
353 op
= multiple_creation_op_new (g_strv_length (names
));
355 for (i
= 0; names
[i
]; i
++) {
356 set_active
= (active
!= NULL
) && (g_ascii_strcasecmp (active
, names
[i
]));
357 logview_manager_add_log_from_name (manager
, names
[i
], set_active
,
363 logview_manager_get_log_count (LogviewManager
*manager
)
365 g_assert (LOGVIEW_IS_MANAGER (manager
));
367 return g_hash_table_size (manager
->priv
->logs
);
371 logview_manager_get_if_loaded (LogviewManager
*manager
, char *uri
)
375 g_assert (LOGVIEW_IS_MANAGER (manager
));
377 log
= g_hash_table_lookup (manager
->priv
->logs
, uri
);
380 return g_object_ref (log
);
387 logview_manager_close_active_log (LogviewManager
*manager
)
389 LogviewLog
*active_log
;
393 g_assert (LOGVIEW_IS_MANAGER (manager
));
395 active_log
= manager
->priv
->active_log
;
396 log_uri
= logview_log_get_uri (active_log
);
397 file
= logview_log_get_gfile (active_log
);
399 g_signal_emit (manager
, signals
[LOG_CLOSED
], 0, active_log
, NULL
);
401 logview_prefs_remove_stored_log (logview_prefs_get (), file
);
403 g_object_unref (file
);
405 /* we own two refs to the active log; one is inside the hash table */
406 g_object_unref (active_log
);
407 g_hash_table_remove (manager
->priv
->logs
, log_uri
);
411 /* someone else will take care of setting the next active log to us */
415 logview_manager_log_is_active (LogviewManager
*manager
,
418 g_assert (LOGVIEW_IS_MANAGER (manager
));
420 return (manager
->priv
->active_log
== log
);