Example #1
0
int 
main (int argc, char* argv[])
{
	GtkWidget *window;
	GList *sources;
	GFile *dest;
	GFile *source;
	int i;
	GList *infos;
        NautilusProgressInfoManager *manager;
	NautilusProgressInfo *progress_info;
	
	test_init (&argc, &argv);

	if (argc < 3) {
		g_print ("Usage test-copy <sources...> <dest dir>\n");
		return 1;
	}

	sources = NULL;
	for (i = 1; i < argc - 1; i++) {
		source = g_file_new_for_commandline_arg (argv[i]);
		sources = g_list_prepend (sources, source);
	}
	sources = g_list_reverse (sources);
	
	dest = g_file_new_for_commandline_arg (argv[i]);
	
	window = test_window_new ("copy test", 5);
	
	gtk_widget_show (window);

        manager = nautilus_progress_info_manager_new ();

	nautilus_file_operations_copy (sources,
				       NULL /* GArray *relative_item_points */,
				       dest,
				       GTK_WINDOW (window),
				       copy_done, NULL);
        
	infos = nautilus_progress_info_manager_get_all_infos (manager);

	if (infos == NULL) {
		g_object_unref (manager);
		return 0;
	}

	progress_info = NAUTILUS_PROGRESS_INFO (infos->data);

	g_signal_connect (progress_info, "changed", (GCallback)changed_cb, NULL);
	g_signal_connect (progress_info, "progress-changed", (GCallback)progress_changed_cb, NULL);
	g_signal_connect (progress_info, "finished", (GCallback)finished_cb, NULL);
	
	gtk_main ();

        g_object_unref (manager);
	
	return 0;
}
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_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 GList*
get_filtered_progress_infos (NautilusToolbar *self)
{
        GList *l;
        GList *filtered_progress_infos;
        GList *progress_infos;

        progress_infos = nautilus_progress_info_manager_get_all_infos (self->priv->progress_manager);
        filtered_progress_infos = NULL;

        for (l = progress_infos; l != NULL; l = l->next) {
                if (should_show_progress_info (l->data)) {
                        filtered_progress_infos = g_list_append (filtered_progress_infos, l->data);
                    }
        }

        return filtered_progress_infos;
}
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 gboolean
on_progress_info_started_timeout (NautilusToolbar *self)
{
        GList *progress_infos;
        GList *filtered_progress_infos;

        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 */

        progress_infos = nautilus_progress_info_manager_get_all_infos (self->priv->progress_manager);
        filtered_progress_infos = get_filtered_progress_infos (self);
        if (!nautilus_progress_manager_are_all_infos_finished_or_cancelled (self->priv->progress_manager) &&
            g_list_length (progress_infos) != g_list_length (filtered_progress_infos)) {
                g_list_free (filtered_progress_infos);
                return G_SOURCE_CONTINUE;
        } else {
                g_list_free (filtered_progress_infos);
                self->priv->start_operations_timeout_id = 0;
                return G_SOURCE_REMOVE;
        }
}
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 = 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_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);
                }
        }

        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-view-menu.xml");
	self->priv->view_menu_widget =  GTK_WIDGET (gtk_builder_get_object (builder, "view_menu_widget"));
	self->priv->zoom_level_scale = GTK_WIDGET (gtk_builder_get_object (builder, "zoom_level_scale"));
	self->priv->zoom_adjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "zoom_adjustment"));

	self->priv->sort_menu =  GTK_WIDGET (gtk_builder_get_object (builder, "sort_menu"));
	self->priv->sort_trash_time =  GTK_WIDGET (gtk_builder_get_object (builder, "sort_trash_time"));
	self->priv->sort_search_relevance =  GTK_WIDGET (gtk_builder_get_object (builder, "sort_search_relevance"));
	self->priv->visible_columns =  GTK_WIDGET (gtk_builder_get_object (builder, "visible_columns"));
	self->priv->reload =  GTK_WIDGET (gtk_builder_get_object (builder, "reload"));
	self->priv->stop =  GTK_WIDGET (gtk_builder_get_object (builder, "stop"));

	g_signal_connect (self->priv->view_menu_widget, "closed",
			  G_CALLBACK (view_menu_popover_closed), self);
	gtk_menu_button_set_popover (GTK_MENU_BUTTON (self->priv->view_button),
				     self->priv->view_menu_widget);
	g_object_unref (builder);

	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);
	g_signal_connect (self->priv->zoom_level_scale, "value-changed",
			  G_CALLBACK (zoom_level_changed), self);

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