progress-info: split progress information notify into a new manager

This commit is contained in:
Cosimo Cecchi 2011-02-01 16:13:04 -05:00
parent 2a86f1c60b
commit a0f8947383
9 changed files with 281 additions and 99 deletions

View file

@ -130,6 +130,8 @@ libnautilus_private_la_SOURCES = \
nautilus-monitor.h \
nautilus-progress-info.c \
nautilus-progress-info.h \
nautilus-progress-info-manager.c \
nautilus-progress-info-manager.h \
nautilus-program-choosing.c \
nautilus-program-choosing.h \
nautilus-recent.c \

View file

@ -0,0 +1,142 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/*
* Nautilus
*
* Copyright (C) 2011 Red Hat, Inc.
*
* Nautilus is free software; you can redistribute it and/or
* 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.
*
* Nautilus is distributed in the hope that it will be useful,
* 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 along with this program; see the file COPYING. If not,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Cosimo Cecchi <cosimoc@redhat.com>
*/
#include <config.h>
#include "nautilus-progress-info-manager.h"
struct _NautilusProgressInfoManagerPriv {
GList *progress_infos;
};
enum {
NEW_PROGRESS_INFO,
LAST_SIGNAL
};
static NautilusProgressInfoManager *singleton = NULL;
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (NautilusProgressInfoManager, nautilus_progress_info_manager,
G_TYPE_OBJECT);
static void
nautilus_progress_info_manager_finalize (GObject *obj)
{
NautilusProgressInfoManager *self = NAUTILUS_PROGRESS_INFO_MANAGER (obj);
if (self->priv->progress_infos != NULL) {
g_list_free_full (self->priv->progress_infos, g_object_unref);
}
G_OBJECT_CLASS (nautilus_progress_info_manager_parent_class)->finalize (obj);
}
static GObject *
nautilus_progress_info_manager_constructor (GType type,
guint n_props,
GObjectConstructParam *props)
{
GObject *retval;
if (singleton != NULL) {
return g_object_ref (singleton);
}
retval = G_OBJECT_CLASS (nautilus_progress_info_manager_parent_class)->constructor
(type, n_props, props);
singleton = NAUTILUS_PROGRESS_INFO_MANAGER (retval);
g_object_add_weak_pointer (retval, (gpointer) &singleton);
return retval;
}
static void
nautilus_progress_info_manager_init (NautilusProgressInfoManager *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NAUTILUS_TYPE_PROGRESS_INFO_MANAGER,
NautilusProgressInfoManagerPriv);
}
static void
nautilus_progress_info_manager_class_init (NautilusProgressInfoManagerClass *klass)
{
GObjectClass *oclass;
oclass = G_OBJECT_CLASS (klass);
oclass->constructor = nautilus_progress_info_manager_constructor;
oclass->finalize = nautilus_progress_info_manager_finalize;
signals[NEW_PROGRESS_INFO] =
g_signal_new ("new-progress-info",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1,
NAUTILUS_TYPE_PROGRESS_INFO);
g_type_class_add_private (klass, sizeof (NautilusProgressInfoManagerPriv));
}
static void
progress_info_finished_cb (NautilusProgressInfo *info,
NautilusProgressInfoManager *self)
{
self->priv->progress_infos =
g_list_remove (self->priv->progress_infos, info);
}
NautilusProgressInfoManager *
nautilus_progress_info_manager_new (void)
{
return g_object_new (NAUTILUS_TYPE_PROGRESS_INFO_MANAGER, NULL);
}
void
nautilus_progress_info_manager_add_new_info (NautilusProgressInfoManager *self,
NautilusProgressInfo *info)
{
if (g_list_find (self->priv->progress_infos, info) != NULL) {
g_warning ("Adding two times the same progress info object to the manager");
return;
}
self->priv->progress_infos =
g_list_prepend (self->priv->progress_infos, g_object_ref (info));
g_signal_connect (info, "finished",
G_CALLBACK (progress_info_finished_cb), self);
g_signal_emit (self, signals[NEW_PROGRESS_INFO], 0, info);
}
GList *
nautilus_progress_info_manager_get_all_infos (NautilusProgressInfoManager *self)
{
return self->priv->progress_infos;
}

View file

@ -0,0 +1,69 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/*
* Nautilus
*
* Copyright (C) 2011 Red Hat, Inc.
*
* Nautilus is free software; you can redistribute it and/or
* 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.
*
* Nautilus is distributed in the hope that it will be useful,
* 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 along with this program; see the file COPYING. If not,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Cosimo Cecchi <cosimoc@redhat.com>
*/
#ifndef __NAUTILUS_PROGRESS_INFO_MANAGER_H__
#define __NAUTILUS_PROGRESS_INFO_MANAGER_H__
#include <glib-object.h>
#include <libnautilus-private/nautilus-progress-info.h>
#define NAUTILUS_TYPE_PROGRESS_INFO_MANAGER nautilus_progress_info_manager_get_type()
#define NAUTILUS_PROGRESS_INFO_MANAGER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_PROGRESS_INFO_MANAGER, NautilusProgressInfoManager))
#define NAUTILUS_PROGRESS_INFO_MANAGER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_PROGRESS_INFO_MANAGER, NautilusProgressInfoManagerClass))
#define NAUTILUS_IS_PROGRESS_INFO_MANAGER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_PROGRESS_INFO_MANAGER))
#define NAUTILUS_IS_PROGRESS_INFO_MANAGER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_PROGRESS_INFO_MANAGER))
#define NAUTILUS_PROGRESS_INFO_MANAGER_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_PROGRESS_INFO_MANAGER, NautilusProgressInfoManagerClass))
typedef struct _NautilusProgressInfoManager NautilusProgressInfoManager;
typedef struct _NautilusProgressInfoManagerClass NautilusProgressInfoManagerClass;
typedef struct _NautilusProgressInfoManagerPriv NautilusProgressInfoManagerPriv;
struct _NautilusProgressInfoManager {
GObject parent;
/* private */
NautilusProgressInfoManagerPriv *priv;
};
struct _NautilusProgressInfoManagerClass {
GObjectClass parent_class;
};
GType nautilus_progress_info_manager_get_type (void);
NautilusProgressInfoManager* nautilus_progress_info_manager_new (void);
void nautilus_progress_info_manager_add_new_info (NautilusProgressInfoManager *self,
NautilusProgressInfo *info);
GList *nautilus_progress_info_manager_get_all_infos (NautilusProgressInfoManager *self);
G_END_DECLS
#endif /* __NAUTILUS_PROGRESS_INFO_MANAGER_H__ */

View file

@ -29,7 +29,8 @@
#include <eel/eel-string.h>
#include <eel/eel-glib-extensions.h>
#include "nautilus-progress-info.h"
#include "nautilus-ui-utilities.h"
#include "nautilus-progress-info-manager.h"
#include "nautilus-icon-info.h"
enum {
CHANGED,
@ -76,8 +77,6 @@ struct _NautilusProgressInfoClass
GObjectClass parent_class;
};
static GList *active_progress_infos = NULL;
static GtkStatusIcon *status_icon = NULL;
static int n_progress_ops = 0;
@ -86,20 +85,6 @@ G_LOCK_DEFINE_STATIC(progress_info);
G_DEFINE_TYPE (NautilusProgressInfo, nautilus_progress_info, G_TYPE_OBJECT)
GList *
nautilus_get_all_progress_info (void)
{
GList *l;
G_LOCK (progress_info);
l = eel_g_object_list_copy (active_progress_infos);
G_UNLOCK (progress_info);
return l;
}
static void
nautilus_progress_info_finalize (GObject *object)
{
@ -125,10 +110,6 @@ nautilus_progress_info_dispose (GObject *object)
G_LOCK (progress_info);
/* Remove from active list in dispose, since a get_all_progress_info()
call later could revive the object */
active_progress_infos = g_list_remove (active_progress_infos, object);
/* Destroy source in dispose, because the callback
could come here before the destroy, which should
ressurect the object for a while */
@ -442,13 +423,6 @@ handle_new_progress_info (NautilusProgressInfo *info)
update_status_icon_and_window ();
}
static void
new_op_finished (NautilusProgressInfo *info)
{
/* release the hold we added in new_op_started() */
g_application_release (G_APPLICATION (nautilus_get_application ()));
}
static gboolean
new_op_started_timeout (NautilusProgressInfo *info)
{
@ -469,24 +443,20 @@ new_op_started (NautilusProgressInfo *info)
g_timeout_add_seconds (2,
(GSourceFunc)new_op_started_timeout,
g_object_ref (info));
/* hold the application, so that it doesn't quit while this operation is
* in progress.
*/
g_application_hold (G_APPLICATION (nautilus_get_application ()));
}
static void
nautilus_progress_info_init (NautilusProgressInfo *info)
{
NautilusProgressInfoManager *manager;
info->cancellable = g_cancellable_new ();
G_LOCK (progress_info);
active_progress_infos = g_list_append (active_progress_infos, info);
G_UNLOCK (progress_info);
g_signal_connect (info, "started", (GCallback)new_op_started, NULL);
g_signal_connect (info, "finished", (GCallback)new_op_finished, NULL);
manager = nautilus_progress_info_manager_new ();
nautilus_progress_info_manager_add_new_info (manager, info);
g_object_unref (manager);
}
NautilusProgressInfo *

View file

@ -30,29 +30,6 @@
#include <gtk/gtk.h>
#include <eel/eel-debug.h>
/* FIXME: this is needed only because we need to access the application
* object from inside libnautilus-private and that's in src instead.
*/
static GtkApplication *app = NULL;
GtkApplication *
nautilus_get_application (void)
{
g_assert (app != NULL);
return app;
}
void
nautilus_store_application (GtkApplication *application)
{
if (app != NULL) {
return;
}
app = application;
}
void
nautilus_ui_unmerge_ui (GtkUIManager *ui_manager,
guint *merge_id,

View file

@ -40,7 +40,4 @@ GtkAction * nautilus_action_from_menu_item (NautilusMenuItem *item);
GtkAction * nautilus_toolbar_action_from_menu_item (NautilusMenuItem *item);
const char *nautilus_ui_string_get (const char *filename);
GtkApplication *nautilus_get_application (void);
void nautilus_store_application (GtkApplication *application);
#endif /* NAUTILUS_UI_UTILITIES_H */

View file

@ -41,6 +41,7 @@
#include "nautilus-list-view.h"
#include "nautilus-navigation-window.h"
#include "nautilus-navigation-window-slot.h"
#include "nautilus-progress-info-manager.h"
#include "nautilus-self-check-functions.h"
#include "nautilus-spatial-window.h"
#include "nautilus-window-bookmarks.h"
@ -105,6 +106,15 @@ static void mount_added_callback (GVolumeMonitor *mo
G_DEFINE_TYPE (NautilusApplication, nautilus_application, GTK_TYPE_APPLICATION);
struct _NautilusApplicationPriv {
GVolumeMonitor *volume_monitor;
GDBusProxy *ck_proxy;
gboolean session_is_active;
NautilusProgressInfoManager *progress_manager;
gboolean initialized;
};
static GList *
nautilus_application_get_spatial_window_list (void)
{
@ -275,8 +285,8 @@ ck_session_proxy_signal_cb (GDBusProxy *proxy,
NautilusApplication *application = user_data;
if (g_strcmp0 (signal_name, "ActiveChanged") == 0) {
g_variant_get (parameters, "(b)", &application->session_is_active);
DEBUG ("ConsoleKit session is active %d", application->session_is_active);
g_variant_get (parameters, "(b)", &application->priv->session_is_active);
DEBUG ("ConsoleKit session is active %d", application->priv->session_is_active);
}
}
@ -293,14 +303,14 @@ ck_call_is_active_cb (GDBusProxy *proxy,
if (variant == NULL) {
g_warning ("Error when calling IsActive(): %s\n", error->message);
application->session_is_active = TRUE;
application->priv->session_is_active = TRUE;
g_error_free (error);
return;
}
g_variant_get (variant, "(b)", &application->session_is_active);
DEBUG ("ConsoleKit session is active %d", application->session_is_active);
g_variant_get (variant, "(b)", &application->priv->session_is_active);
DEBUG ("ConsoleKit session is active %d", application->priv->session_is_active);
g_variant_unref (variant);
}
@ -320,7 +330,7 @@ session_proxy_appeared (GObject *source,
g_warning ("Failed to get the current CK session: %s", error->message);
g_error_free (error);
application->session_is_active = TRUE;
application->priv->session_is_active = TRUE;
return;
}
@ -337,7 +347,7 @@ session_proxy_appeared (GObject *source,
(GAsyncReadyCallback) ck_call_is_active_cb,
application);
application->proxy = proxy;
application->priv->ck_proxy = proxy;
}
static void
@ -356,7 +366,7 @@ ck_get_current_session_cb (GDBusConnection *connection,
g_warning ("Failed to get the current CK session: %s", error->message);
g_error_free (error);
application->session_is_active = TRUE;
application->priv->session_is_active = TRUE;
return;
}
@ -385,7 +395,7 @@ do_initialize_consolekit (NautilusApplication *application)
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
if (connection == NULL) {
application->session_is_active = TRUE;
application->priv->session_is_active = TRUE;
return;
}
@ -462,6 +472,18 @@ do_upgrades_once (NautilusApplication *application,
g_free (xdg_dir);
}
static void
new_progress_info_cb (NautilusProgressInfoManager *manager,
NautilusProgressInfo *info,
NautilusApplication *self)
{
/* hold/release application while there are file operations in progress */
g_signal_connect_swapped (info, "started",
G_CALLBACK (g_application_hold), self);
g_signal_connect_swapped (info, "finished",
G_CALLBACK (g_application_release), self);
}
static void
finish_startup (NautilusApplication *application,
gboolean no_desktop)
@ -480,16 +502,16 @@ finish_startup (NautilusApplication *application,
/* Initialize the ConsoleKit listener for active session */
do_initialize_consolekit (application);
/* Watch for mounts so we can restore open windows This used
* to be for showing new window on mount, but is not used
* anymore */
application->priv->progress_manager = nautilus_progress_info_manager_new ();
g_signal_connect (application->priv->progress_manager, "new-progress-info",
G_CALLBACK (new_progress_info_cb), application);
/* Watch for unmounts so we can close open windows */
/* TODO-gio: This should be using the UNMOUNTED feature of GFileMonitor instead */
application->volume_monitor = g_volume_monitor_get ();
g_signal_connect_object (application->volume_monitor, "mount_removed",
application->priv->volume_monitor = g_volume_monitor_get ();
g_signal_connect_object (application->priv->volume_monitor, "mount_removed",
G_CALLBACK (mount_removed_callback), application, 0);
g_signal_connect_object (application->volume_monitor, "mount_added",
g_signal_connect_object (application->priv->volume_monitor, "mount_added",
G_CALLBACK (mount_added_callback), application, 0);
}
@ -1084,7 +1106,7 @@ mount_added_callback (GVolumeMonitor *monitor,
GFile *root;
gchar *uri;
if (!application->session_is_active) {
if (!application->priv->session_is_active) {
return;
}
@ -1238,8 +1260,9 @@ nautilus_application_constructor (GType type,
static void
nautilus_application_init (NautilusApplication *application)
{
/* FIXME: make this available to libnautilus-private in another way */
nautilus_store_application (GTK_APPLICATION (application));
application->priv =
G_TYPE_INSTANCE_GET_PRIVATE (application, NAUTILUS_TYPE_APPLICATION,
NautilusApplicationPriv);
}
static void
@ -1256,15 +1279,9 @@ nautilus_application_finalize (GObject *object)
application->undo_manager = NULL;
}
if (application->volume_monitor) {
g_object_unref (application->volume_monitor);
application->volume_monitor = NULL;
}
if (application->proxy != NULL) {
g_object_unref (application->proxy);
application->proxy = NULL;
}
g_clear_object (&application->priv->volume_monitor);
g_clear_object (&application->priv->ck_proxy);
g_clear_object (&application->priv->progress_manager);
nautilus_dbus_manager_stop ();
@ -1407,7 +1424,7 @@ nautilus_application_command_line (GApplication *app,
if (kill_shell) {
nautilus_application_quit (self);
} else {
if (!self->initialized) {
if (!self->priv->initialized) {
char *accel_map_filename;
if (!no_desktop &&
@ -1437,7 +1454,7 @@ nautilus_application_command_line (GApplication *app,
g_signal_connect (gtk_accel_map_get (), "changed",
G_CALLBACK (queue_accel_map_save_callback), NULL);
self->initialized = TRUE;
self->priv->initialized = TRUE;
}
/* Convert args to URIs */
@ -1571,6 +1588,8 @@ nautilus_application_class_init (NautilusApplicationClass *class)
application_class->startup = nautilus_application_startup;
application_class->command_line = nautilus_application_command_line;
application_class->quit_mainloop = nautilus_application_quit_mainloop;
g_type_class_add_private (class, sizeof (NautilusApplication));
}
NautilusApplication *

View file

@ -51,15 +51,14 @@
typedef struct _NautilusSpatialWindow NautilusSpatialWindow;
#endif
typedef struct _NautilusApplicationPriv NautilusApplicationPriv;
typedef struct {
GtkApplication parent;
NautilusUndoManager *undo_manager;
GVolumeMonitor *volume_monitor;
GDBusProxy *proxy;
gboolean session_is_active;
gboolean initialized;
NautilusApplicationPriv *priv;
} NautilusApplication;
typedef struct {

View file

@ -2,6 +2,7 @@
#include <libnautilus-private/nautilus-file-operations.h>
#include <libnautilus-private/nautilus-progress-info.h>
#include <libnautilus-private/nautilus-progress-info-manager.h>
static void
copy_done (GHashTable *debuting_uris, gpointer data)
@ -43,6 +44,7 @@ main (int argc, char* argv[])
GFile *source;
int i;
GList *infos;
NautilusProgressInfoManager *manager;
NautilusProgressInfo *progress_info;
g_thread_init (NULL);
@ -67,15 +69,18 @@ main (int argc, char* argv[])
gtk_widget_show (window);
manager = nautilus_progress_info_manager_new ();
nautilus_file_operations_copy (sources,
NULL /* GArray *relative_item_points */,
dest,
GTK_WINDOW (window),
copy_done, NULL);
infos = nautilus_get_all_progress_info ();
infos = nautilus_progress_info_manager_get_all_infos (manager);
if (infos == NULL) {
g_object_unref (manager);
return 0;
}
@ -86,6 +91,8 @@ main (int argc, char* argv[])
g_signal_connect (progress_info, "finished", (GCallback)finished_cb, NULL);
gtk_main ();
g_object_unref (manager);
return 0;
}