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_swapped (l->data, "finished",
			                          G_CALLBACK (on_progress_info_finished), self);
	                g_signal_connect_swapped (l->data, "cancelled",
			                          G_CALLBACK (on_progress_info_cancelled), self);
	                g_signal_connect_swapped (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
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 &&
                    !nautilus_progress_info_get_is_cancelled (l->data) &&
                    !nautilus_progress_info_get_is_finished (l->data)) {
                        return FALSE;
                }
        }

        return TRUE;
}
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;
        gboolean all_cancelled;
        GdkRGBA background = {.red = 0, .green = 0, .blue = 0, .alpha = 0.2 };
        GdkRGBA foreground = {.red = 0, .green = 0, .blue = 0, .alpha = 0.7 };

        all_cancelled = TRUE;
        progress_infos = get_filtered_progress_infos (self);
        for (l = progress_infos; l != NULL; l = l->next) {
                if (!nautilus_progress_info_get_is_cancelled (l->data)) {
                        all_cancelled = FALSE;
                        remaining_progress += nautilus_progress_info_get_remaining_time (l->data);
                        elapsed_progress += nautilus_progress_info_get_elapsed_time (l->data);
                }
        }

        g_list_free (progress_infos);

        total_progress = remaining_progress + elapsed_progress;

        if (all_cancelled) {
                ratio = 1.0;
        } else {
                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
on_operations_button_toggled (NautilusToolbar *self)
{
        unschedule_remove_finished_operations (self);
        if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->operations_button))) {
                schedule_remove_finished_operations (self);
        } else {
                update_operations (self);
        }
}

static void
nautilus_toolbar_init (NautilusToolbar *self)
{
	GtkBuilder *builder;

	self->priv = nautilus_toolbar_get_instance_private (self);
	gtk_widget_init_template (GTK_WIDGET (self));

	self->priv->path_bar = g_object_new (NAUTILUS_TYPE_PATH_BAR, NULL);
	gtk_container_add (GTK_CONTAINER (self->priv->path_bar_container),
					  self->priv->path_bar);

	self->priv->location_entry = nautilus_location_entry_new ();
	gtk_container_add (GTK_CONTAINER (self->priv->location_entry_container),
					  self->priv->location_entry);

	builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-toolbar-action-menu.xml");
	self->priv->action_menu = G_MENU (gtk_builder_get_object (builder, "action-menu"));
	gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (self->priv->action_button),
					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",
			   GUINT_TO_POINTER (NAUTILUS_NAVIGATION_DIRECTION_FORWARD));
	g_signal_connect (self->priv->back_button, "button-press-event",
			  G_CALLBACK (navigation_button_press_cb), self);
	g_signal_connect (self->priv->back_button, "button-release-event",
			  G_CALLBACK (navigation_button_release_cb), self);
	g_signal_connect (self->priv->forward_button, "button-press-event",
			  G_CALLBACK (navigation_button_press_cb), self);
	g_signal_connect (self->priv->forward_button, "button-release-event",
			  G_CALLBACK (navigation_button_release_cb), self);

	gtk_widget_show_all (GTK_WIDGET (self));
	toolbar_update_appearance (self);
}