summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Soriano <csoriano@gnome.org>2015-07-01 15:53:43 +0200
committerCarlos Soriano <csoriano@gnome.org>2015-07-17 00:25:45 +0200
commit1e8ede102f115d66c52fe098f4e1ebc4ef2d790f (patch)
treee2aaa901955f722d1618cc6374e5b2434704feea
parent066b057c2d6ba064832fcb1a341051ce7dce0e59 (diff)
downloadnautilus-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.c28
-rw-r--r--libnautilus-private/nautilus-file-operations.h2
-rw-r--r--libnautilus-private/nautilus-progress-info-manager.c16
-rw-r--r--libnautilus-private/nautilus-progress-info-manager.h3
-rw-r--r--libnautilus-private/nautilus-progress-info.c46
-rw-r--r--libnautilus-private/nautilus-progress-info.h7
-rw-r--r--src/Makefile.am4
-rw-r--r--src/nautilus-application-actions.c13
-rw-r--r--src/nautilus-application.c13
-rw-r--r--src/nautilus-application.h4
-rw-r--r--src/nautilus-progress-info-widget.c8
-rw-r--r--src/nautilus-progress-info-widget.h4
-rw-r--r--src/nautilus-progress-info-widget.xml85
-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.h65
-rw-r--r--src/nautilus-progress-ui-handler.h64
-rw-r--r--src/nautilus-toolbar-ui.xml53
-rw-r--r--src/nautilus-toolbar.c232
-rw-r--r--test/test-copy.c2
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 */,