diff options
author | Carlos Soriano <csoriano@gnome.org> | 2015-07-01 15:53:43 +0200 |
---|---|---|
committer | Carlos Soriano <csoriano@gnome.org> | 2015-07-17 00:25:45 +0200 |
commit | 1e8ede102f115d66c52fe098f4e1ebc4ef2d790f (patch) | |
tree | e2aaa901955f722d1618cc6374e5b2434704feea | |
parent | 066b057c2d6ba064832fcb1a341051ce7dce0e59 (diff) | |
download | nautilus-1e8ede102f115d66c52fe098f4e1ebc4ef2d790f.tar.gz |
operations: implement new design
Now operations reside in the toolbar, in form of a button with
a popover. In this way we avoid to have a nautilus window hanging
around for it.
When no nautilus window is open, the persistence handlers of nautilus
are enough. This use a notification if the server supports it or
a systray icon in case it doesn't.
-rw-r--r-- | libnautilus-private/nautilus-file-operations.c | 28 | ||||
-rw-r--r-- | libnautilus-private/nautilus-file-operations.h | 2 | ||||
-rw-r--r-- | libnautilus-private/nautilus-progress-info-manager.c | 16 | ||||
-rw-r--r-- | libnautilus-private/nautilus-progress-info-manager.h | 3 | ||||
-rw-r--r-- | libnautilus-private/nautilus-progress-info.c | 46 | ||||
-rw-r--r-- | libnautilus-private/nautilus-progress-info.h | 7 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/nautilus-application-actions.c | 13 | ||||
-rw-r--r-- | src/nautilus-application.c | 13 | ||||
-rw-r--r-- | src/nautilus-application.h | 4 | ||||
-rw-r--r-- | src/nautilus-progress-info-widget.c | 8 | ||||
-rw-r--r-- | src/nautilus-progress-info-widget.h | 4 | ||||
-rw-r--r-- | src/nautilus-progress-info-widget.xml | 85 | ||||
-rw-r--r-- | src/nautilus-progress-persistence-handler.c (renamed from src/nautilus-progress-ui-handler.c) | 250 | ||||
-rw-r--r-- | src/nautilus-progress-persistence-handler.h | 65 | ||||
-rw-r--r-- | src/nautilus-progress-ui-handler.h | 64 | ||||
-rw-r--r-- | src/nautilus-toolbar-ui.xml | 53 | ||||
-rw-r--r-- | src/nautilus-toolbar.c | 232 | ||||
-rw-r--r-- | test/test-copy.c | 2 |
19 files changed, 608 insertions, 291 deletions
diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c index acb4c7c61..7762916a4 100644 --- a/libnautilus-private/nautilus-file-operations.c +++ b/libnautilus-private/nautilus-file-operations.c @@ -1478,13 +1478,18 @@ report_delete_progress (CommonJob *job, f (_("Deleting files"))); elapsed = g_timer_elapsed (job->time, NULL); - if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE) { + transfer_rate = 0; + remaining_time = INT_MAX; + if (elapsed > 0) { + transfer_rate = transfer_info->num_files / elapsed; + if (transfer_rate > 0) + remaining_time = (source_info->num_files - transfer_info->num_files) / transfer_rate; + } + if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE) { nautilus_progress_info_set_details (job->progress, files_left_s); } else { char *details, *time_left_s; - transfer_rate = transfer_info->num_files / elapsed; - remaining_time = files_left / transfer_rate; /* To translators: %T will expand to a time like "2 minutes". * The singular/plural form will be used depending on the remaining time (i.e. the %T argument). @@ -1500,6 +1505,12 @@ report_delete_progress (CommonJob *job, g_free (time_left_s); } + if (elapsed > SECONDS_NEEDED_FOR_APROXIMATE_TRANSFER_RATE) { + nautilus_progress_info_set_remaining_time (job->progress, + remaining_time); + nautilus_progress_info_set_elapsed_time (job->progress, + elapsed); + } g_free (files_left_s); if (source_info->num_files != 0) { @@ -3039,8 +3050,11 @@ report_copy_progress (CopyMoveJob *copy_job, elapsed = g_timer_elapsed (job->time, NULL); transfer_rate = 0; + remaining_time = INT_MAX; if (elapsed > 0) { transfer_rate = transfer_info->num_bytes / elapsed; + if (transfer_rate > 0) + remaining_time = (total_size - transfer_info->num_bytes) / transfer_rate; } if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE && @@ -3051,7 +3065,6 @@ report_copy_progress (CopyMoveJob *copy_job, nautilus_progress_info_take_details (job->progress, s); } else { char *s; - remaining_time = (total_size - transfer_info->num_bytes) / transfer_rate; /* To translators: %S will expand to a size like "2 bytes" or "3 MB", %T to a time duration like * "2 minutes". So the whole thing will be something like "2 kb of 4 MB -- 2 hours left (4kb/sec)" @@ -3067,6 +3080,13 @@ report_copy_progress (CopyMoveJob *copy_job, nautilus_progress_info_take_details (job->progress, s); } + if (elapsed > SECONDS_NEEDED_FOR_APROXIMATE_TRANSFER_RATE) { + nautilus_progress_info_set_remaining_time (job->progress, + remaining_time); + nautilus_progress_info_set_elapsed_time (job->progress, + elapsed); + } + nautilus_progress_info_set_progress (job->progress, transfer_info->num_bytes, total_size); } diff --git a/libnautilus-private/nautilus-file-operations.h b/libnautilus-private/nautilus-file-operations.h index e65ba7d7c..38b714fd9 100644 --- a/libnautilus-private/nautilus-file-operations.h +++ b/libnautilus-private/nautilus-file-operations.h @@ -28,6 +28,8 @@ #include <gtk/gtk.h> #include <gio/gio.h> +#define SECONDS_NEEDED_FOR_APROXIMATE_TRANSFER_RATE 1 + typedef void (* NautilusCopyCallback) (GHashTable *debuting_uris, gboolean success, gpointer callback_data); diff --git a/libnautilus-private/nautilus-progress-info-manager.c b/libnautilus-private/nautilus-progress-info-manager.c index 97343ee77..401cd47fa 100644 --- a/libnautilus-private/nautilus-progress-info-manager.c +++ b/libnautilus-private/nautilus-progress-info-manager.c @@ -111,7 +111,7 @@ progress_info_finished_cb (NautilusProgressInfo *info, } NautilusProgressInfoManager * -nautilus_progress_info_manager_new (void) +nautilus_progress_info_manager_dup_singleton (void) { return g_object_new (NAUTILUS_TYPE_PROGRESS_INFO_MANAGER, NULL); } @@ -139,3 +139,17 @@ nautilus_progress_info_manager_get_all_infos (NautilusProgressInfoManager *self) { return self->priv->progress_infos; } + +gboolean +nautilus_progress_manager_are_all_infos_finished (NautilusProgressInfoManager *self) +{ + GList *l; + + for (l = self->priv->progress_infos; l != NULL; l = l->next) { + if (!nautilus_progress_info_get_is_finished (l->data)) { + return FALSE; + } + } + + return TRUE; +} diff --git a/libnautilus-private/nautilus-progress-info-manager.h b/libnautilus-private/nautilus-progress-info-manager.h index 21c22f01e..da0eda751 100644 --- a/libnautilus-private/nautilus-progress-info-manager.h +++ b/libnautilus-private/nautilus-progress-info-manager.h @@ -57,11 +57,12 @@ struct _NautilusProgressInfoManagerClass { GType nautilus_progress_info_manager_get_type (void); -NautilusProgressInfoManager* nautilus_progress_info_manager_new (void); +NautilusProgressInfoManager* nautilus_progress_info_manager_dup_singleton (void); void nautilus_progress_info_manager_add_new_info (NautilusProgressInfoManager *self, NautilusProgressInfo *info); GList *nautilus_progress_info_manager_get_all_infos (NautilusProgressInfoManager *self); +gboolean nautilus_progress_manager_are_all_infos_finished (NautilusProgressInfoManager *self); G_END_DECLS diff --git a/libnautilus-private/nautilus-progress-info.c b/libnautilus-private/nautilus-progress-info.c index 16b2cb272..389aaeb15 100644 --- a/libnautilus-private/nautilus-progress-info.c +++ b/libnautilus-private/nautilus-progress-info.c @@ -50,6 +50,8 @@ struct _NautilusProgressInfo char *status; char *details; double progress; + gdouble remaining_time; + gdouble elapsed_time; gboolean activity_mode; gboolean started; gboolean finished; @@ -162,7 +164,7 @@ nautilus_progress_info_init (NautilusProgressInfo *info) info->cancellable = g_cancellable_new (); - manager = nautilus_progress_info_manager_new (); + manager = nautilus_progress_info_manager_dup_singleton (); nautilus_progress_info_manager_add_new_info (manager, info); g_object_unref (manager); } @@ -570,3 +572,45 @@ nautilus_progress_info_set_progress (NautilusProgressInfo *info, G_UNLOCK (progress_info); } + +void +nautilus_progress_info_set_remaining_time (NautilusProgressInfo *info, + gdouble time) +{ + G_LOCK (progress_info); + info->remaining_time = time; + G_UNLOCK (progress_info); +} + +gdouble +nautilus_progress_info_get_remaining_time (NautilusProgressInfo *info) +{ + gint remaining_time; + + G_LOCK (progress_info); + remaining_time = info->remaining_time; + G_UNLOCK (progress_info); + + return remaining_time; +} + +void +nautilus_progress_info_set_elapsed_time (NautilusProgressInfo *info, + gdouble time) +{ + G_LOCK (progress_info); + info->elapsed_time = time; + G_UNLOCK (progress_info); +} + +gdouble +nautilus_progress_info_get_elapsed_time (NautilusProgressInfo *info) +{ + gint elapsed_time; + + G_LOCK (progress_info); + elapsed_time = info->elapsed_time; + G_UNLOCK (progress_info); + + return elapsed_time; +} diff --git a/libnautilus-private/nautilus-progress-info.h b/libnautilus-private/nautilus-progress-info.h index edca861eb..0ce0ad19f 100644 --- a/libnautilus-private/nautilus-progress-info.h +++ b/libnautilus-private/nautilus-progress-info.h @@ -78,6 +78,13 @@ void nautilus_progress_info_set_progress (NautilusProgressInfo *info double total); void nautilus_progress_info_pulse_progress (NautilusProgressInfo *info); +void nautilus_progress_info_set_remaining_time (NautilusProgressInfo *info, + gdouble time); +gdouble nautilus_progress_info_get_remaining_time (NautilusProgressInfo *info); +void nautilus_progress_info_set_elapsed_time (NautilusProgressInfo *info, + gdouble time); +gdouble nautilus_progress_info_get_elapsed_time (NautilusProgressInfo *info); + #endif /* NAUTILUS_PROGRESS_INFO_H */ diff --git a/src/Makefile.am b/src/Makefile.am index 72a07c374..7de649b7d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -189,8 +189,8 @@ nautilus_SOURCES = \ nautilus-previewer.h \ nautilus-progress-info-widget.c \ nautilus-progress-info-widget.h \ - nautilus-progress-ui-handler.c \ - nautilus-progress-ui-handler.h \ + nautilus-progress-persistence-handler.c \ + nautilus-progress-persistence-handler.h \ nautilus-properties-window.c \ nautilus-properties-window.h \ nautilus-query-editor.c \ diff --git a/src/nautilus-application-actions.c b/src/nautilus-application-actions.c index 3caa09eac..17c4b6802 100644 --- a/src/nautilus-application-actions.c +++ b/src/nautilus-application-actions.c @@ -217,18 +217,6 @@ action_search (GSimpleAction *action, } static void -action_show_file_transfers (GSimpleAction *action, - GVariant *parameter, - gpointer user_data) -{ - NautilusApplication *application = user_data; - NautilusProgressUIHandler *progress_handler; - - progress_handler = nautilus_application_get_progress_ui_handler (application); - nautilus_progress_ui_handler_ensure_window (progress_handler); -} - -static void action_show_hide_sidebar (GSimpleAction *action, GVariant *state, gpointer user_data) @@ -261,7 +249,6 @@ static GActionEntry app_entries[] = { { "kill", action_kill, NULL, NULL, NULL }, { "open-desktop", action_open_desktop, NULL, NULL, NULL }, { "close-desktop", action_close_desktop, NULL, NULL, NULL }, - { "show-file-transfers", action_show_file_transfers, NULL, NULL, NULL } }; void diff --git a/src/nautilus-application.c b/src/nautilus-application.c index bde2330d9..19ce99a04 100644 --- a/src/nautilus-application.c +++ b/src/nautilus-application.c @@ -37,6 +37,7 @@ #include "nautilus-freedesktop-dbus.h" #include "nautilus-image-properties-page.h" #include "nautilus-previewer.h" +#include "nautilus-progress-persistence-handler.h" #include "nautilus-self-check-functions.h" #include "nautilus-shell-search-provider.h" #include "nautilus-window.h" @@ -70,7 +71,7 @@ G_DEFINE_TYPE (NautilusApplication, nautilus_application, GTK_TYPE_APPLICATION); struct _NautilusApplicationPriv { - NautilusProgressUIHandler *progress_handler; + NautilusProgressPersistenceHandler *progress_handler; NautilusDBusManager *dbus_manager; NautilusFreedesktopDBus *fdb_manager; @@ -104,13 +105,6 @@ nautilus_application_get_windows (NautilusApplication *application) return application->priv->windows; } - -NautilusProgressUIHandler * -nautilus_application_get_progress_ui_handler (NautilusApplication *application) -{ - return application->priv->progress_handler; -} - NautilusBookmarkList * nautilus_application_get_bookmarks (NautilusApplication *application) { @@ -996,7 +990,7 @@ nautilus_application_startup (GApplication *app) menu_provider_init_callback (); /* Initialize the UI handler singleton for file operations */ - self->priv->progress_handler = nautilus_progress_ui_handler_new (); + self->priv->progress_handler = nautilus_progress_persistence_handler_new (G_OBJECT (self)); /* Check the user's .nautilus directories and post warnings * if there are problems. @@ -1169,6 +1163,7 @@ nautilus_application_window_removed (GtkApplication *app, /* if this was the last window, close the previewer */ if (g_list_length (self->priv->windows) == 0) { nautilus_previewer_call_close (); + nautilus_progress_persistence_handler_make_persistent (self->priv->progress_handler); } } diff --git a/src/nautilus-application.h b/src/nautilus-application.h index 3dd4af598..8b6ef79eb 100644 --- a/src/nautilus-application.h +++ b/src/nautilus-application.h @@ -27,7 +27,6 @@ #include <gtk/gtk.h> #include "nautilus-bookmark-list.h" -#include "nautilus-progress-ui-handler.h" #include "nautilus-window.h" #define NAUTILUS_DESKTOP_ICON_VIEW_IID "OAFIID:Nautilus_File_Manager_Desktop_Canvas_View" @@ -81,7 +80,4 @@ void nautilus_application_edit_bookmarks (NautilusApplication *application, GtkWidget * nautilus_application_connect_server (NautilusApplication *application, NautilusWindow *window); - -NautilusProgressUIHandler * nautilus_application_get_progress_ui_handler (NautilusApplication *application); - #endif /* __NAUTILUS_APPLICATION_H__ */ diff --git a/src/nautilus-progress-info-widget.c b/src/nautilus-progress-info-widget.c index 86b34fdab..783467686 100644 --- a/src/nautilus-progress-info-widget.c +++ b/src/nautilus-progress-info-widget.c @@ -42,7 +42,7 @@ enum { static GParamSpec *properties[NUM_PROPERTIES] = { NULL }; G_DEFINE_TYPE_WITH_PRIVATE (NautilusProgressInfoWidget, nautilus_progress_info_widget, - GTK_TYPE_BOX); + GTK_TYPE_GRID); static void info_finished (NautilusProgressInfoWidget *self) @@ -93,6 +93,9 @@ nautilus_progress_info_widget_dispose (GObject *obj) { NautilusProgressInfoWidget *self = NAUTILUS_PROGRESS_INFO_WIDGET (obj); + if (self->priv->info != NULL) { + g_signal_handlers_disconnect_by_data (self->priv->info, self); + } g_clear_object (&self->priv->info); G_OBJECT_CLASS (nautilus_progress_info_widget_parent_class)->dispose (obj); @@ -185,8 +188,5 @@ nautilus_progress_info_widget_new (NautilusProgressInfo *info) { return g_object_new (NAUTILUS_TYPE_PROGRESS_INFO_WIDGET, "info", info, - "orientation", GTK_ORIENTATION_VERTICAL, - "homogeneous", FALSE, - "spacing", 5, NULL); } diff --git a/src/nautilus-progress-info-widget.h b/src/nautilus-progress-info-widget.h index 5bb40c9fe..f1c99c0db 100644 --- a/src/nautilus-progress-info-widget.h +++ b/src/nautilus-progress-info-widget.h @@ -44,14 +44,14 @@ typedef struct _NautilusProgressInfoWidgetPrivate NautilusProgressInfoWidgetPrivate; typedef struct { - GtkBox parent; + GtkGrid parent; /* private */ NautilusProgressInfoWidgetPrivate *priv; } NautilusProgressInfoWidget; typedef struct { - GtkBoxClass parent_class; + GtkGridClass parent_class; } NautilusProgressInfoWidgetClass; GType nautilus_progress_info_widget_get_type (void); diff --git a/src/nautilus-progress-info-widget.xml b/src/nautilus-progress-info-widget.xml index e4a980221..3eace47df 100644 --- a/src/nautilus-progress-info-widget.xml +++ b/src/nautilus-progress-info-widget.xml @@ -1,67 +1,59 @@ <?xml version="1.0" encoding="UTF-8"?> <interface> - <template class="NautilusProgressInfoWidget" parent="GtkBox"> + <template class="NautilusProgressInfoWidget" parent="GtkGrid"> <property name="visible">True</property> - <property name="margin">5</property> - <property name="orientation">vertical</property> + <property name="margin-start">5</property> + <property name="margin-end">5</property> <child> <object class="GtkLabel" id="status"> <property name="label">status</property> <property name="visible">True</property> <property name="xalign">0</property> - <property name="width-request">400</property> - <property name="wrap">True</property> - <property name="wrap-mode">word-char</property> + <property name="width-request">300</property> + <property name="max-width-chars">30</property> + <property name="ellipsize">middle</property> + <property name="margin-bottom">6</property> </object> <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> + <property name="top-attach">0</property> + <property name="left-attach">0</property> </packing> </child> <child> - <object class="GtkBox" id="box2"> + <object class="GtkProgressBar" id="progress_bar"> <property name="visible">True</property> + <property name="valign">center</property> + <property name="pulse-step">0.05</property> + <property name="margin_start">2</property> + <property name="margin-bottom">4</property> + </object> + <packing> + <property name="top-attach">1</property> + <property name="left-attach">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="cancel"> + <property name="visible">True</property> + <property name="receives_default">True</property> + <property name="margin_start">20</property> + <property name="valign">center</property> + <style> + <class name="image-button"/> + <class name="nautilus-circular-button"/> + </style> <child> - <object class="GtkProgressBar" id="progress_bar"> - <property name="visible">True</property> - <property name="valign">center</property> - <property name="pulse-step">0.05</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="cancel"> + <object class="GtkImage" id="cancel_icon"> <property name="visible">True</property> - <property name="receives_default">True</property> - <property name="margin_start">20</property> - <style> - <class name="image-button"/> - <class name="nautilus-circular-button"/> - </style> - <child> - <object class="GtkImage" id="cancel_icon"> - <property name="visible">True</property> - <property name="icon-name">window-close-symbolic</property> - <property name="icon-size">1</property> - </object> - </child> + <property name="icon-name">window-close-symbolic</property> + <property name="icon-size">1</property> </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> </child> </object> <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> + <property name="height">3</property> + <property name="top-attach">0</property> + <property name="left-attach">1</property> </packing> </child> <child> @@ -78,9 +70,8 @@ </style> </object> <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> + <property name="top-attach">2</property> + <property name="left-attach">0</property> </packing> </child> </template> diff --git a/src/nautilus-progress-ui-handler.c b/src/nautilus-progress-persistence-handler.c index 21722df91..10e9fc4d6 100644 --- a/src/nautilus-progress-ui-handler.c +++ b/src/nautilus-progress-persistence-handler.c @@ -1,8 +1,8 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* - * nautilus-progress-ui-handler.c: file operation progress user interface. + * nautilus-progress-persistence-handler.c: file operation progress systray icon and notification handler. * - * Copyright (C) 2007, 2011 Red Hat, Inc. + * Copyright (C) 2007, 2011, 2015 Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -19,12 +19,13 @@ * * Authors: Alexander Larsson <alexl@redhat.com> * Cosimo Cecchi <cosimoc@redhat.com> + * Carlos Soriano <csoriano@gnome.com> * */ #include <config.h> -#include "nautilus-progress-ui-handler.h" +#include "nautilus-progress-persistence-handler.h" #include "nautilus-application.h" #include "nautilus-progress-info-widget.h" @@ -34,17 +35,16 @@ #include <libnautilus-private/nautilus-progress-info.h> #include <libnautilus-private/nautilus-progress-info-manager.h> -struct _NautilusProgressUIHandlerPriv { +struct _NautilusProgressPersistenceHandlerPriv { NautilusProgressInfoManager *manager; - GtkWidget *progress_dialog; - GtkWidget *content_area; + NautilusApplication *app; guint active_infos; GtkStatusIcon *status_icon; }; -G_DEFINE_TYPE (NautilusProgressUIHandler, nautilus_progress_ui_handler, G_TYPE_OBJECT); +G_DEFINE_TYPE (NautilusProgressPersistenceHandler, nautilus_progress_persistence_handler, G_TYPE_OBJECT); /* Our policy for showing progress notification is the following: * - file operations that end within two seconds do not get notified in any way @@ -66,15 +66,41 @@ G_DEFINE_TYPE (NautilusProgressUIHandler, nautilus_progress_ui_handler, G_TYPE_O static gboolean server_has_persistence (void); static void -status_icon_activate_cb (GtkStatusIcon *icon, - NautilusProgressUIHandler *self) -{ +show_file_transfers (NautilusProgressPersistenceHandler *self) +{ + GFile *home; + + home = g_file_new_for_path (g_get_home_dir ()); + nautilus_application_open_location (self->priv->app, home, NULL, NULL); + + g_object_unref (home); +} + +static void +action_show_file_transfers (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + NautilusProgressPersistenceHandler *self; + + self = NAUTILUS_PROGRESS_PERSISTENCE_HANDLER (user_data); + show_file_transfers (self); +} + +static GActionEntry progress_persistence_entries[] = { + { "show-file-transfers", action_show_file_transfers, NULL, NULL, NULL } +}; + +static void +status_icon_activate_cb (GtkStatusIcon *icon, + NautilusProgressPersistenceHandler *self) +{ gtk_status_icon_set_visible (icon, FALSE); - gtk_window_present (GTK_WINDOW (self->priv->progress_dialog)); + show_file_transfers (self); } static void -progress_ui_handler_ensure_status_icon (NautilusProgressUIHandler *self) +progress_persistence_handler_ensure_status_icon (NautilusProgressPersistenceHandler *self) { GIcon *icon; GtkStatusIcon *status_icon; @@ -96,7 +122,7 @@ progress_ui_handler_ensure_status_icon (NautilusProgressUIHandler *self) } static void -progress_ui_handler_update_notification (NautilusProgressUIHandler *self) +progress_persistence_handler_update_notification (NautilusProgressPersistenceHandler *self) { GNotification *notification; gchar *body; @@ -120,11 +146,11 @@ progress_ui_handler_update_notification (NautilusProgressUIHandler *self) } static void -progress_ui_handler_update_status_icon (NautilusProgressUIHandler *self) +progress_persistence_handler_update_status_icon (NautilusProgressPersistenceHandler *self) { gchar *tooltip; - progress_ui_handler_ensure_status_icon (self); + progress_persistence_handler_ensure_status_icon (self); tooltip = g_strdup_printf (ngettext ("%'d file operation active", "%'d file operations active", @@ -136,81 +162,34 @@ progress_ui_handler_update_status_icon (NautilusProgressUIHandler *self) gtk_status_icon_set_visible (self->priv->status_icon, TRUE); } -static gboolean -progress_window_delete_event (GtkWidget *widget, - GdkEvent *event, - NautilusProgressUIHandler *self) -{ - gtk_widget_hide (widget); - - if (server_has_persistence ()) { - progress_ui_handler_update_notification (self); - } else { - progress_ui_handler_update_status_icon (self); - } - - return TRUE; -} - -static void -progress_ui_handler_ensure_window (NautilusProgressUIHandler *self) +void +nautilus_progress_persistence_handler_make_persistent (NautilusProgressPersistenceHandler *self) { - GtkWidget *progress_dialog; - - if (self->priv->progress_dialog != NULL) { - return; - } - - progress_dialog = g_object_new (GTK_TYPE_DIALOG, "use-header-bar", TRUE, NULL); - self->priv->progress_dialog = progress_dialog; - gtk_window_set_resizable (GTK_WINDOW (progress_dialog), - FALSE); - gtk_container_set_border_width (GTK_CONTAINER (progress_dialog), 10); - - gtk_window_set_title (GTK_WINDOW (progress_dialog), - _("File Operations")); - gtk_window_set_wmclass (GTK_WINDOW (progress_dialog), - "file_progress", "Nautilus"); - gtk_window_set_position (GTK_WINDOW (progress_dialog), - GTK_WIN_POS_CENTER); - gtk_window_set_icon_name (GTK_WINDOW (progress_dialog), - "system-file-manager"); - - self->priv->content_area = gtk_dialog_get_content_area (GTK_DIALOG (self->priv->progress_dialog)); - - g_signal_connect (progress_dialog, - "delete-event", - (GCallback) progress_window_delete_event, self); + GList *windows; + + windows = nautilus_application_get_windows (self->priv->app); + if (self->priv->active_infos > 0 && + g_list_length (windows) == 0) { + if (server_has_persistence ()) { + progress_persistence_handler_update_notification (self); + } else { + progress_persistence_handler_update_status_icon (self); + } + } } static void -progress_ui_handler_update_notification_or_status (NautilusProgressUIHandler *self) +progress_persistence_handler_update_notification_or_status (NautilusProgressPersistenceHandler *self) { if (server_has_persistence ()) { - progress_ui_handler_update_notification (self); + progress_persistence_handler_update_notification (self); } else { - progress_ui_handler_update_status_icon (self); + progress_persistence_handler_update_status_icon (self); } } static void -progress_ui_handler_add_to_window (NautilusProgressUIHandler *self, - NautilusProgressInfo *info) -{ - GtkWidget *progress; - - progress = nautilus_progress_info_widget_new (info); - progress_ui_handler_ensure_window (self); - - gtk_box_pack_start (GTK_BOX (self->priv->content_area), - progress, - FALSE, FALSE, 6); - - gtk_widget_show (progress); -} - -static void -progress_ui_handler_show_complete_notification (NautilusProgressUIHandler *self) +progress_persistence_handler_show_complete_notification (NautilusProgressPersistenceHandler *self) { GNotification *complete_notification; @@ -230,7 +209,7 @@ progress_ui_handler_show_complete_notification (NautilusProgressUIHandler *self) } static void -progress_ui_handler_hide_notification_or_status (NautilusProgressUIHandler *self) +progress_persistence_handler_hide_notification_or_status (NautilusProgressPersistenceHandler *self) { if (self->priv->status_icon != NULL) { gtk_status_icon_set_visible (self->priv->status_icon, FALSE); @@ -241,50 +220,44 @@ progress_ui_handler_hide_notification_or_status (NautilusProgressUIHandler *self } static void -progress_info_finished_cb (NautilusProgressInfo *info, - NautilusProgressUIHandler *self) +progress_info_finished_cb (NautilusProgressInfo *info, + NautilusProgressPersistenceHandler *self) { + GList *windows; + self->priv->active_infos--; - if (self->priv->active_infos > 0) { - if (!gtk_widget_get_visible (self->priv->progress_dialog)) { - progress_ui_handler_update_notification_or_status (self); - } - } else { - if (gtk_widget_get_visible (self->priv->progress_dialog)) { - gtk_widget_hide (self->priv->progress_dialog); - } else { - progress_ui_handler_hide_notification_or_status (self); - progress_ui_handler_show_complete_notification (self); - } - } + windows = nautilus_application_get_windows (self->priv->app); + if (self->priv->active_infos > 0) { + if (g_list_length (windows) == 0) { + progress_persistence_handler_update_notification_or_status (self); + } + } else if (g_list_length (windows) == 0) { + progress_persistence_handler_hide_notification_or_status (self); + progress_persistence_handler_show_complete_notification (self); + } + } static void -handle_new_progress_info (NautilusProgressUIHandler *self, - NautilusProgressInfo *info) +handle_new_progress_info (NautilusProgressPersistenceHandler *self, + NautilusProgressInfo *info) { + GList *windows; g_signal_connect (info, "finished", G_CALLBACK (progress_info_finished_cb), self); self->priv->active_infos++; + windows = nautilus_application_get_windows (self->priv->app); - if (self->priv->active_infos == 1) { - /* this is the only active operation, present the window */ - progress_ui_handler_add_to_window (self, info); - gtk_window_present (GTK_WINDOW (self->priv->progress_dialog)); - } else { - if (gtk_widget_get_visible (self->priv->progress_dialog)) { - progress_ui_handler_add_to_window (self, info); - } else { - progress_ui_handler_update_notification_or_status (self); - } - } + if (g_list_length (windows) == 0) { + progress_persistence_handler_update_notification_or_status (self); + } } typedef struct { NautilusProgressInfo *info; - NautilusProgressUIHandler *self; + NautilusProgressPersistenceHandler *self; } TimeoutData; static void @@ -297,8 +270,8 @@ timeout_data_free (TimeoutData *data) } static TimeoutData * -timeout_data_new (NautilusProgressUIHandler *self, - NautilusProgressInfo *info) +timeout_data_new (NautilusProgressPersistenceHandler *self, + NautilusProgressInfo *info) { TimeoutData *retval; @@ -313,7 +286,7 @@ static gboolean new_op_started_timeout (TimeoutData *data) { NautilusProgressInfo *info = data->info; - NautilusProgressUIHandler *self = data->self; + NautilusProgressPersistenceHandler *self = data->self; if (nautilus_progress_info_get_is_paused (info)) { return TRUE; @@ -329,16 +302,16 @@ new_op_started_timeout (TimeoutData *data) } static void -release_application (NautilusProgressInfo *info, - NautilusProgressUIHandler *self) +release_application (NautilusProgressInfo *info, + NautilusProgressPersistenceHandler *self) { /* release the GApplication hold we acquired */ g_application_release (g_application_get_default ()); } static void -progress_info_started_cb (NautilusProgressInfo *info, - NautilusProgressUIHandler *self) +progress_info_started_cb (NautilusProgressInfo *info, + NautilusProgressPersistenceHandler *self) { TimeoutData *data; @@ -357,22 +330,22 @@ progress_info_started_cb (NautilusProgressInfo *info, } static void -new_progress_info_cb (NautilusProgressInfoManager *manager, - NautilusProgressInfo *info, - NautilusProgressUIHandler *self) +new_progress_info_cb (NautilusProgressInfoManager *manager, + NautilusProgressInfo *info, + NautilusProgressPersistenceHandler *self) { g_signal_connect (info, "started", G_CALLBACK (progress_info_started_cb), self); } static void -nautilus_progress_ui_handler_dispose (GObject *obj) +nautilus_progress_persistence_handler_dispose (GObject *obj) { - NautilusProgressUIHandler *self = NAUTILUS_PROGRESS_UI_HANDLER (obj); + NautilusProgressPersistenceHandler *self = NAUTILUS_PROGRESS_PERSISTENCE_HANDLER (obj); g_clear_object (&self->priv->manager); - G_OBJECT_CLASS (nautilus_progress_ui_handler_parent_class)->dispose (obj); + G_OBJECT_CLASS (nautilus_progress_persistence_handler_parent_class)->dispose (obj); } static gboolean @@ -416,36 +389,37 @@ server_has_persistence (void) } static void -nautilus_progress_ui_handler_init (NautilusProgressUIHandler *self) +nautilus_progress_persistence_handler_init (NautilusProgressPersistenceHandler *self) { - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NAUTILUS_TYPE_PROGRESS_UI_HANDLER, - NautilusProgressUIHandlerPriv); + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NAUTILUS_TYPE_PROGRESS_PERSISTENCE_HANDLER, + NautilusProgressPersistenceHandlerPriv); - self->priv->manager = nautilus_progress_info_manager_new (); + self->priv->manager = nautilus_progress_info_manager_dup_singleton (); g_signal_connect (self->priv->manager, "new-progress-info", G_CALLBACK (new_progress_info_cb), self); } static void -nautilus_progress_ui_handler_class_init (NautilusProgressUIHandlerClass *klass) +nautilus_progress_persistence_handler_class_init (NautilusProgressPersistenceHandlerClass *klass) { GObjectClass *oclass; oclass = G_OBJECT_CLASS (klass); - oclass->dispose = nautilus_progress_ui_handler_dispose; - - g_type_class_add_private (klass, sizeof (NautilusProgressUIHandlerPriv)); -} + oclass->dispose = nautilus_progress_persistence_handler_dispose; -NautilusProgressUIHandler * -nautilus_progress_ui_handler_new (void) -{ - return g_object_new (NAUTILUS_TYPE_PROGRESS_UI_HANDLER, NULL); + g_type_class_add_private (klass, sizeof (NautilusProgressPersistenceHandlerPriv)); } -void -nautilus_progress_ui_handler_ensure_window (NautilusProgressUIHandler *self) +NautilusProgressPersistenceHandler * +nautilus_progress_persistence_handler_new (GObject *app) { - if (self->priv->active_infos > 0) - gtk_window_present (GTK_WINDOW (self->priv->progress_dialog)); + NautilusProgressPersistenceHandler *self; + + self = g_object_new (NAUTILUS_TYPE_PROGRESS_PERSISTENCE_HANDLER, NULL); + self->priv->app = NAUTILUS_APPLICATION (app); + + g_action_map_add_action_entries (G_ACTION_MAP (self->priv->app), + progress_persistence_entries, G_N_ELEMENTS (progress_persistence_entries), + self); + return self; } diff --git a/src/nautilus-progress-persistence-handler.h b/src/nautilus-progress-persistence-handler.h new file mode 100644 index 000000000..924255cba --- /dev/null +++ b/src/nautilus-progress-persistence-handler.h @@ -0,0 +1,65 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * nautilus-progress-persistence-handler.h: file operation progress systray icon or notification handler. + * + * Copyright (C) 2007, 2011 Red Hat, Inc. + * + * This program 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. + * + * This program 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; if not, see <http://www.gnu.org/licenses/>. + * + * Authors: Alexander Larsson <alexl@redhat.com> + * Cosimo Cecchi <cosimoc@redhat.com> + * + */ + +#ifndef __NAUTILUS_PROGRESS_PERSISTENCE_HANDLER_H__ +#define __NAUTILUS_PROGRESS_PERSISTENCE_HANDLER_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define NAUTILUS_TYPE_PROGRESS_PERSISTENCE_HANDLER nautilus_progress_persistence_handler_get_type() +#define NAUTILUS_PROGRESS_PERSISTENCE_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_PROGRESS_PERSISTENCE_HANDLER, NautilusProgressPersistenceHandler)) +#define NAUTILUS_PROGRESS_PERSISTENCE_HANDLER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_PROGRESS_PERSISTENCE_HANDLER, NautilusProgressPersistenceHandlerClass)) +#define NAUTILUS_IS_PROGRESS_PERSISTENCE_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_PROGRESS_PERSISTENCE_HANDLER)) +#define NAUTILUS_IS_PROGRESS_PERSISTENCE_HANDLER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_PROGRESS_PERSISTENCE_HANDLER)) +#define NAUTILUS_PROGRESS_PERSISTENCE_HANDLER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_PROGRESS_PERSISTENCE_HANDLER, NautilusProgressPersistenceHandlerClass)) + +typedef struct _NautilusProgressPersistenceHandlerPriv NautilusProgressPersistenceHandlerPriv; + +typedef struct { + GObject parent; + + /* private */ + NautilusProgressPersistenceHandlerPriv *priv; +} NautilusProgressPersistenceHandler; + +typedef struct { + GObjectClass parent_class; +} NautilusProgressPersistenceHandlerClass; + +GType nautilus_progress_persistence_handler_get_type (void); + +/* @app is actually a NautilusApplication, but we need to avoid circular dependencies */ +NautilusProgressPersistenceHandler * nautilus_progress_persistence_handler_new (GObject *app); +void nautilus_progress_persistence_handler_make_persistent (NautilusProgressPersistenceHandler *self); + +G_END_DECLS + +#endif /* __NAUTILUS_PROGRESS_PERSISTENCE_HANDLER_H__ */ diff --git a/src/nautilus-progress-ui-handler.h b/src/nautilus-progress-ui-handler.h deleted file mode 100644 index 4109b68b2..000000000 --- a/src/nautilus-progress-ui-handler.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* - * nautilus-progress-ui-handler.h: file operation progress user interface. - * - * Copyright (C) 2007, 2011 Red Hat, Inc. - * - * This program 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. - * - * This program 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; if not, see <http://www.gnu.org/licenses/>. - * - * Authors: Alexander Larsson <alexl@redhat.com> - * Cosimo Cecchi <cosimoc@redhat.com> - * - */ - -#ifndef __NAUTILUS_PROGRESS_UI_HANDLER_H__ -#define __NAUTILUS_PROGRESS_UI_HANDLER_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -#define NAUTILUS_TYPE_PROGRESS_UI_HANDLER nautilus_progress_ui_handler_get_type() -#define NAUTILUS_PROGRESS_UI_HANDLER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_PROGRESS_UI_HANDLER, NautilusProgressUIHandler)) -#define NAUTILUS_PROGRESS_UI_HANDLER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_PROGRESS_UI_HANDLER, NautilusProgressUIHandlerClass)) -#define NAUTILUS_IS_PROGRESS_UI_HANDLER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_PROGRESS_UI_HANDLER)) -#define NAUTILUS_IS_PROGRESS_UI_HANDLER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_PROGRESS_UI_HANDLER)) -#define NAUTILUS_PROGRESS_UI_HANDLER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_PROGRESS_UI_HANDLER, NautilusProgressUIHandlerClass)) - -typedef struct _NautilusProgressUIHandlerPriv NautilusProgressUIHandlerPriv; - -typedef struct { - GObject parent; - - /* private */ - NautilusProgressUIHandlerPriv *priv; -} NautilusProgressUIHandler; - -typedef struct { - GObjectClass parent_class; -} NautilusProgressUIHandlerClass; - -GType nautilus_progress_ui_handler_get_type (void); - -NautilusProgressUIHandler * nautilus_progress_ui_handler_new (void); -void nautilus_progress_ui_handler_ensure_window (NautilusProgressUIHandler *self); - -G_END_DECLS - -#endif /* __NAUTILUS_PROGRESS_UI_HANDLER_H__ */ diff --git a/src/nautilus-toolbar-ui.xml b/src/nautilus-toolbar-ui.xml index bf371b0f0..42051b258 100644 --- a/src/nautilus-toolbar-ui.xml +++ b/src/nautilus-toolbar-ui.xml @@ -141,5 +141,58 @@ <property name="pack-type">end</property> </packing> </child> + <child> + <object class="GtkRevealer" id="operations_revealer"> + <property name="visible">True</property> + <property name="transition-type">GTK_REVEALER_TRANSITION_TYPE_CROSSFADE</property> + <child> + <object class="GtkMenuButton" id="operations_button"> + <property name="visible">False</property> + <property name="popover">operations_popover</property> + <style> + <class name="button"/> + </style> + <child> + <object class="GtkDrawingArea" id="operations_icon"> + <property name="visible">True</property> + <property name="height-request">16</property> + <property name="width-request">16</property> + <property name="valign">GTK_ALIGN_CENTER</property> + <property name="halign">GTK_ALIGN_CENTER</property> + <signal name="draw" handler="on_operations_icon_draw" object="NautilusToolbar" swapped="no"/> + </object> + </child> + <child internal-child="accessible"> + <object class="AtkObject"> + <property name="accessible-name" translatable="yes">Operations in progress</property> + <property name="accessible-description" translatable="yes">Open operations in progress</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="pack-type">end</property> + </packing> + </child> </template> + <object class="GtkPopover" id="operations_popover"> + <property name="modal">false</property> + <property name="relative-to">operations_button</property> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> + <property name="min-content-height">270</property> + <child> + <object class="GtkBox" id="operations_container"> + <property name="orientation">vertical</property> + <property name="visible">True</property> + <property name="margin">12</property> + <property name="spacing">10</property> + </object> + </child> + </object> + </child> + </object> </interface> diff --git a/src/nautilus-toolbar.c b/src/nautilus-toolbar.c index 79697a71a..c083e13d2 100644 --- a/src/nautilus-toolbar.c +++ b/src/nautilus-toolbar.c @@ -29,13 +29,18 @@ #include "nautilus-location-entry.h" #include "nautilus-pathbar.h" #include "nautilus-window.h" +#include "nautilus-progress-info-widget.h" #include <libnautilus-private/nautilus-global-preferences.h> #include <libnautilus-private/nautilus-ui-utilities.h> +#include <libnautilus-private/nautilus-progress-info-manager.h> +#include <libnautilus-private/nautilus-file-operations.h> #include <glib/gi18n.h> #include <math.h> +#define OPERATION_MINIMUM_TIME 5 //s + typedef enum { NAUTILUS_NAVIGATION_DIRECTION_NONE, NAUTILUS_NAVIGATION_DIRECTION_BACK, @@ -53,10 +58,16 @@ struct _NautilusToolbarPrivate { gboolean show_location_entry; guint popup_timeout_id; + guint start_operations_timeout_id; + GtkWidget *operations_button; GtkWidget *view_button; GtkWidget *action_button; + GtkWidget *operations_popover; + GtkWidget *operations_container; + GtkWidget *operations_revealer; + GtkWidget *operations_icon; GtkWidget *view_menu_widget; GtkWidget *sort_menu; GtkWidget *sort_modification_date; @@ -72,6 +83,8 @@ struct _NautilusToolbarPrivate { GtkWidget *forward_button; GtkWidget *back_button; + + NautilusProgressInfoManager *progress_manager; }; enum { @@ -420,6 +433,209 @@ view_menu_popover_closed (GtkPopover *popover, nautilus_view_grab_focus (view); } +static gboolean +should_hide_operations_button (NautilusToolbar *self) +{ + GList *progress_infos; + GList *l; + + progress_infos = nautilus_progress_info_manager_get_all_infos (self->priv->progress_manager); + + for (l = progress_infos; l != NULL; l = l->next) { + if (nautilus_progress_info_get_elapsed_time (l->data) + + nautilus_progress_info_get_remaining_time (l->data) > OPERATION_MINIMUM_TIME) { + return FALSE; + } + } + + return TRUE; +} + +static void +on_progress_info_progress_changed (NautilusProgressInfo *info, + NautilusToolbar *self) +{ + /* Update the pie chart progress */ + gtk_widget_queue_draw (self->priv->operations_icon); +} + +static void +on_progress_info_finished (NautilusProgressInfo *info, + NautilusToolbar *self) +{ + /* Update the pie chart progress */ + gtk_widget_queue_draw (self->priv->operations_icon); + + if (should_hide_operations_button (self)) { + gtk_revealer_set_reveal_child (GTK_REVEALER (self->priv->operations_revealer), + FALSE); + } +} + +static void +disconnect_progress_infos (NautilusToolbar *self) +{ + GList *progress_infos; + GList *l; + + progress_infos = nautilus_progress_info_manager_get_all_infos (self->priv->progress_manager); + for (l = progress_infos; l != NULL; l = l->next) { + g_signal_handlers_disconnect_by_data (l->data, self); + } +} + +static void +update_operations (NautilusToolbar *self) +{ + GList *progress_infos; + GList *l; + GtkWidget *progress; + guint total_remaining_time = 0; + + gtk_container_foreach (GTK_CONTAINER (self->priv->operations_container), + (GtkCallback) gtk_widget_destroy, + NULL); + + disconnect_progress_infos (self); + + progress_infos = nautilus_progress_info_manager_get_all_infos (self->priv->progress_manager); + for (l = progress_infos; l != NULL; l = l->next) { + if (nautilus_progress_info_get_elapsed_time (l->data) + + nautilus_progress_info_get_remaining_time (l->data) > OPERATION_MINIMUM_TIME) { + total_remaining_time = nautilus_progress_info_get_remaining_time (l->data); + + g_signal_connect (l->data, "finished", + G_CALLBACK (on_progress_info_finished), self); + g_signal_connect (l->data, "progress-changed", + G_CALLBACK (on_progress_info_progress_changed), self); + progress = nautilus_progress_info_widget_new (l->data); + gtk_box_pack_start (GTK_BOX (self->priv->operations_container), + progress, + FALSE, FALSE, 0); + } + } + + /* Either we are already showing the button, so keep showing it until the user + * toggle it to hide the operations popover, or, if we want now to show it, + * we have to have at least one operation that its total stimated time + * is longer than OPERATION_MINIMUM_TIME seconds, or if we failed to get + * a correct stimated time and it's around OPERATION_MINIMUM_TIME, + * showing the button for just for a moment because now we realized the + * estimated time is longer than a OPERATION_MINIMUM_TIME is odd, so show + * it only if the remaining time is bigger than again OPERATION_MINIMUM_TIME. + */ + if (total_remaining_time > OPERATION_MINIMUM_TIME || + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->operations_button))) { + gtk_revealer_set_reveal_child (GTK_REVEALER (self->priv->operations_revealer), + TRUE); + gtk_widget_queue_draw (self->priv->operations_icon); + } +} + +static gboolean +on_progress_info_started_timeout (NautilusToolbar *self) +{ + update_operations (self); + + /* In case we didn't show the operations button because the operation total + * time stimation is not good enough, update again to make sure we don't miss + * a long time operation because of that */ + if (!nautilus_progress_manager_are_all_infos_finished (self->priv->progress_manager)) { + return G_SOURCE_CONTINUE; + } else { + self->priv->start_operations_timeout_id = 0; + return G_SOURCE_REMOVE; + } +} + +static void +schedule_operations_start (NautilusToolbar *self) +{ + if (self->priv->start_operations_timeout_id == 0) { + /* Timeout is a little more than what we require for a stimated operation + * total time, to make sure the stimated total time is correct */ + self->priv->start_operations_timeout_id = + g_timeout_add (SECONDS_NEEDED_FOR_APROXIMATE_TRANSFER_RATE * 1000 + 500, + (GSourceFunc) on_progress_info_started_timeout, + self); + } +} + +static void +unschedule_operations_start (NautilusToolbar *self) +{ + if (self->priv->start_operations_timeout_id != 0) { + g_source_remove (self->priv->start_operations_timeout_id); + self->priv->start_operations_timeout_id = 0; + } +} + +static void +on_progress_info_started (NautilusProgressInfo *info, + NautilusToolbar *self) +{ + g_signal_handlers_disconnect_by_data (info, self); + schedule_operations_start (self); +} + +static void +on_new_progress_info (NautilusProgressInfoManager *manager, + NautilusProgressInfo *info, + NautilusToolbar *self) +{ + g_signal_connect (info, "started", + G_CALLBACK (on_progress_info_started), self); +} + +static void +on_operations_icon_draw (GtkWidget *widget, + cairo_t *cr, + NautilusToolbar *self) +{ + gfloat elapsed_progress = 0; + gint remaining_progress = 0; + gint total_progress; + gdouble ratio; + GList *progress_infos; + GList *l; + guint width; + guint height; + GdkRGBA background = {.red = 0, .green = 0, .blue = 0, .alpha = 0.2 }; + GdkRGBA foreground = {.red = 0, .green = 0, .blue = 0, .alpha = 0.7 }; + + progress_infos = nautilus_progress_info_manager_get_all_infos (self->priv->progress_manager); + for (l = progress_infos; l != NULL; l = l->next) { + remaining_progress += nautilus_progress_info_get_remaining_time (l->data); + elapsed_progress += nautilus_progress_info_get_elapsed_time (l->data); + } + + total_progress = remaining_progress + elapsed_progress; + + if (total_progress > 0) + ratio = MAX (0.05, elapsed_progress / total_progress); + else + ratio = 0.05; + + + width = gtk_widget_get_allocated_width (widget); + height = gtk_widget_get_allocated_height (widget); + + gdk_cairo_set_source_rgba(cr, &background); + cairo_arc (cr, + width / 2.0, height / 2.0, + MIN (width, height) / 2.0, + 0, 2 *G_PI); + cairo_fill (cr); + cairo_move_to (cr, width / 2.0, height / 2.0); + gdk_cairo_set_source_rgba (cr, &foreground); + cairo_arc (cr, + width / 2.0, height / 2.0, + MIN (width, height) / 2.0, + -G_PI / 2.0, ratio * 2 * G_PI - G_PI / 2.0); + + cairo_fill (cr); +} + static void nautilus_toolbar_init (NautilusToolbar *self) { @@ -462,6 +678,11 @@ nautilus_toolbar_init (NautilusToolbar *self) G_MENU_MODEL (self->priv->action_menu)); g_object_unref (builder); + self->priv->progress_manager = nautilus_progress_info_manager_dup_singleton (); + g_signal_connect (self->priv->progress_manager, "new-progress-info", + G_CALLBACK (on_new_progress_info), self); + update_operations (self); + g_object_set_data (G_OBJECT (self->priv->back_button), "nav-direction", GUINT_TO_POINTER (NAUTILUS_NAVIGATION_DIRECTION_BACK)); g_object_set_data (G_OBJECT (self->priv->forward_button), "nav-direction", @@ -527,7 +748,12 @@ nautilus_toolbar_dispose (GObject *obj) g_signal_handlers_disconnect_by_func (nautilus_preferences, toolbar_update_appearance, self); + disconnect_progress_infos (self); unschedule_menu_popup_timeout (self); + unschedule_operations_start (self); + + g_signal_handlers_disconnect_by_data (self->priv->progress_manager, self); + g_clear_object (&self->priv->progress_manager); G_OBJECT_CLASS (nautilus_toolbar_parent_class)->dispose (obj); } @@ -563,12 +789,18 @@ nautilus_toolbar_class_init (NautilusToolbarClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/nautilus/nautilus-toolbar-ui.xml"); + gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, operations_button); + gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, operations_icon); + gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, operations_container); + gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, operations_revealer); gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, view_button); gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, action_button); gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, path_bar_container); gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, location_entry_container); gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, back_button); gtk_widget_class_bind_template_child_private (widget_class, NautilusToolbar, forward_button); + + gtk_widget_class_bind_template_callback (widget_class, on_operations_icon_draw); } void diff --git a/test/test-copy.c b/test/test-copy.c index be8e7c4da..d9c491eb2 100644 --- a/test/test-copy.c +++ b/test/test-copy.c @@ -69,7 +69,7 @@ main (int argc, char* argv[]) gtk_widget_show (window); - manager = nautilus_progress_info_manager_new (); + manager = nautilus_progress_info_manager_dup_singleton (); nautilus_file_operations_copy (sources, NULL /* GArray *relative_item_points */, |