/* Screem: screem-file-progress-dialog.c * * ScreemFileProgressDialog provides a progress dialog for a given * ScreemFile object * * Copyright (C) 2004 David A Knight * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * * For contact information with the author of this source code please see * the AUTHORS file. If there is no AUTHORS file present then check the * about box under the help menu for a contact address */ #include #include #include #include #include #include "screem-file-progress-dialog.h" #include "support.h" #include "screemmarshal.h" struct ScreemFileProgressDialogPrivate { GtkWidget *dialog; GtkProgressBar *bar; GtkWidget *text; const gchar *uri; guint64 total; guint64 current; guint update; gboolean long_job; gboolean complete; ScreemFile *file; }; /* gobject stuff */ enum { PROP_0 }; enum { LAST_SIGNAL }; /*static guint screem_file_progress_dialog_signals[ LAST_SIGNAL ] = { 0 };*/ static void dialog_response( GtkWidget *widget, gint button, ScreemFileProgressDialog *dialog ); static void dialog_delete_event( GtkWidget *widget, ScreemFileProgressDialog *dialog ); static void set_file( ScreemFileProgressDialog *dialog, ScreemFile *file ); static gboolean update_gui( ScreemFileProgressDialog *dialog ); static void complete( ScreemFile *file, const gchar *uri, gboolean success, ScreemFileProgressDialog *dialog ); static void progress( ScreemFile *file, const gchar *uri, guint64 total, guint64 current, ScreemFileProgressDialog *dialog ); static void long_job( ScreemFile *file, ScreemFileProgressDialog *dialog ); G_DEFINE_TYPE( ScreemFileProgressDialog, screem_file_progress_dialog, G_TYPE_OBJECT ) static void screem_file_progress_dialog_finalize( GObject *object ); static void screem_file_progress_dialog_set_prop( GObject *object, guint prop_id, const GValue *value, GParamSpec *spec ); static void screem_file_progress_dialog_get_prop( GObject *object, guint prop_id, GValue *value, GParamSpec *spec ); static void screem_file_progress_dialog_class_init( ScreemFileProgressDialogClass *klass ) { GObjectClass *obj_class; obj_class = G_OBJECT_CLASS( klass ); obj_class->finalize = screem_file_progress_dialog_finalize; obj_class->get_property = screem_file_progress_dialog_get_prop; obj_class->set_property = screem_file_progress_dialog_set_prop; } static void screem_file_progress_dialog_init( ScreemFileProgressDialog *file ) { ScreemFileProgressDialogPrivate *priv; GladeXML *xml; GtkWidget *widget; priv = file->priv = g_new0( ScreemFileProgressDialogPrivate, 1 ); xml = glade_xml_new( GLADE_PATH"/screem.glade", "loading", NULL ); priv->dialog = glade_xml_get_widget( xml, "loading" ); widget = glade_xml_get_widget( xml, "loading" ); gtk_window_set_wmclass( GTK_WINDOW( widget ), "Screem", "loading_dialog" ); gtk_window_set_type_hint( GTK_WINDOW( widget ), GDK_WINDOW_TYPE_HINT_DIALOG ); g_signal_connect( G_OBJECT( widget ), "response", G_CALLBACK( dialog_response ), file ); g_signal_connect( G_OBJECT( widget ), "delete_event", G_CALLBACK( dialog_delete_event ), file ); widget = glade_xml_get_widget( xml, "progress" ); priv->bar = GTK_PROGRESS_BAR( widget ); priv->text = glade_xml_get_widget( xml, "text" ); g_object_unref( xml ); } static void screem_file_progress_dialog_finalize( GObject *object ) { ScreemFileProgressDialog *dialog; ScreemFileProgressDialogPrivate *priv; g_return_if_fail( object != NULL ); g_return_if_fail( SCREEM_IS_FILE_PROGRESS_DIALOG( object ) ); dialog = SCREEM_FILE_PROGRESS_DIALOG( object ); priv = dialog->priv; if( priv->file ) { g_signal_handlers_disconnect_matched( G_OBJECT( priv->file ), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, dialog ); g_object_unref( priv->file ); } if( priv->update ) { g_source_remove( priv->update ); } gtk_widget_destroy( priv->dialog ); g_free( priv ); G_OBJECT_CLASS( screem_file_progress_dialog_parent_class )->finalize( object ); } static void screem_file_progress_dialog_set_prop( GObject *object, guint prop_id, const GValue *value, GParamSpec *spec ) { ScreemFileProgressDialog *file; ScreemFileProgressDialogPrivate *priv; file = SCREEM_FILE_PROGRESS_DIALOG( object ); priv = file->priv; switch( prop_id ) { default: break; } } static void screem_file_progress_dialog_get_prop( GObject *object, guint prop_id, GValue *value, GParamSpec *spec ) { ScreemFileProgressDialog *file; ScreemFileProgressDialogPrivate *priv; file = SCREEM_FILE_PROGRESS_DIALOG( object ); priv = file->priv; switch( prop_id ) { default: break; } } /* private */ static void dialog_response( GtkWidget *widget, gint button, ScreemFileProgressDialog *dialog ) { ScreemFileProgressDialogPrivate *priv; priv = dialog->priv; if( ! priv->complete ) { screem_file_cancel( priv->file ); } } static void dialog_delete_event( GtkWidget *widget, ScreemFileProgressDialog *dialog ) { ScreemFileProgressDialogPrivate *priv; priv = dialog->priv; if( ! priv->complete ) { screem_file_cancel( priv->file ); } } static void set_file( ScreemFileProgressDialog *dialog, ScreemFile *file ) { ScreemFileProgressDialogPrivate *priv; const gchar *ltxt; const gchar *temp; gchar *tmp; guint pos; GString *str; GtkWidget *widget; const gchar *path; priv = dialog->priv; priv->file = file; g_object_ref( file ); path = screem_file_get_uri( file ); g_return_if_fail( path != NULL ); widget = priv->text; ltxt = gtk_label_get_text( GTK_LABEL( widget ) ); temp = strstr( ltxt, "%s" ); g_assert( temp ); pos = (guint)(temp - ltxt); str = g_string_new( "" ); pos += str->len; g_string_append( str, ltxt ); g_string_erase( str, pos, 2 ); temp = gnome_vfs_unescape_string_for_display( path ); tmp = g_markup_escape_text( temp, -1 ); g_string_insert( str, pos, tmp ); g_free( (gchar*)temp ); g_free( tmp ); temp = strstr( str->str, "\n\n" ); g_assert( temp ); pos = (guint)(temp - str->str); g_string_insert( str, pos, "" ); gtk_label_set_markup( GTK_LABEL( widget ), str->str ); g_string_free( str, TRUE ); } static gboolean update_gui( ScreemFileProgressDialog *dialog ) { ScreemFileProgressDialogPrivate *priv; GtkProgressBar *bar; gfloat fraction; priv = dialog->priv; priv->update = 0; if( priv->long_job ) { gdk_threads_enter(); if( ! GTK_WIDGET_VISIBLE( priv->dialog ) ) { gtk_widget_show( priv->dialog ); } if( ! priv->complete ) { bar = priv->bar; if( priv->total != 0 ) { fraction = priv->current / ( priv->total * 1.0 ); gtk_progress_bar_set_fraction( bar, fraction ); } else { gtk_progress_bar_pulse( bar ); } } else { gtk_widget_hide( priv->dialog ); } gdk_threads_leave(); } return FALSE; } static void complete( ScreemFile *file, const gchar *uri, gboolean success, ScreemFileProgressDialog *dialog ) { ScreemFileProgressDialogPrivate *priv; priv = dialog->priv; priv->complete = TRUE; if( ! priv->update ) { priv->update = g_idle_add( (GSourceFunc)update_gui, dialog ); } } static void progress( ScreemFile *file, const gchar *uri, guint64 total, guint64 current, ScreemFileProgressDialog *dialog ) { ScreemFileProgressDialogPrivate *priv; priv = dialog->priv; priv->uri = uri; priv->total = total; priv->current = current; if( ! priv->update ) { priv->update = g_idle_add( (GSourceFunc)update_gui, dialog ); } } static void long_job( ScreemFile *file, ScreemFileProgressDialog *dialog ) { ScreemFileProgressDialogPrivate *priv; priv = dialog->priv; priv->long_job = TRUE; if( ! priv->update ) { priv->update = g_idle_add( (GSourceFunc)update_gui, dialog ); } } static void error( ScreemFile *file, const gchar *uri, ScreemFileProgressDialog *dialog ) { dialog->priv->complete = TRUE; } /* public */ ScreemFileProgressDialog *screem_file_progress_dialog_new( ScreemFile *file ) { ScreemFileProgressDialog *dialog; dialog = g_object_new( SCREEM_TYPE_FILE_PROGRESS_DIALOG, NULL ); set_file( dialog, file ); g_signal_connect( G_OBJECT( file ), "progress", G_CALLBACK( progress ), dialog ); g_signal_connect( G_OBJECT( file ), "long_job", G_CALLBACK( long_job ), dialog ); g_signal_connect( G_OBJECT( file ), "complete", G_CALLBACK( complete ), dialog ); g_signal_connect( G_OBJECT( file ), "error", G_CALLBACK( error ), dialog ); return dialog; } void screem_file_progress_dialog_run( ScreemFileProgressDialog *dialog ) { ScreemFileProgressDialogPrivate *priv; g_return_if_fail( SCREEM_IS_FILE_PROGRESS_DIALOG( dialog ) ); priv = dialog->priv; gdk_threads_leave(); while( ! priv->complete ) { while( g_main_iteration( FALSE ) ) {} usleep( 100 ); } gdk_threads_enter(); }