From 124342e9791f995a6cd6f7bc09405a859054d6dd Mon Sep 17 00:00:00 2001 From: Phillip Susi Date: Mon, 14 Jan 2013 21:20:49 -0500 Subject: [PATCH] Use a full fledged nested main loop while waiting and pulsing progress bars (#685740) Win_Gparted and Dialog_Progress were looping on Gtk::Main::events_pending() and iteration() with usleeps in between. Use a full mainloop instead and a proper timeout to trigger pulsebar updates instead of usleeps. Part of Bug 685740 - Refactor to use asynchronous command execution --- include/Dialog_Progress.h | 5 +-- include/Win_GParted.h | 3 +- src/Dialog_Progress.cc | 41 ++++++++++++---------- src/Win_GParted.cc | 74 ++++++++++++++++++--------------------- 4 files changed, 60 insertions(+), 63 deletions(-) diff --git a/include/Dialog_Progress.h b/include/Dialog_Progress.h index e3be49e9..a580ddb9 100644 --- a/include/Dialog_Progress.h +++ b/include/Dialog_Progress.h @@ -57,6 +57,7 @@ private: void on_response( int response_id ) ; bool on_delete_event( GdkEventAny * event ) ; + bool pulsebar_pulse(); Gtk::Label label_current ; Gtk::Label label_current_sub ; @@ -91,11 +92,11 @@ private: std::vector operations ; OperationDetail operationdetail ; - bool running, succes, cancel, pulse ; + bool succes, cancel; pthread_t pthread ; double fraction ; unsigned int t, warnings ; - + sigc::connection pulsetimer; Glib::Dispatcher dispatcher_update_gui_elements ; Glib::ustring label_current_sub_text ; }; diff --git a/include/Win_GParted.h b/include/Win_GParted.h index d9a2e410..15a4f34c 100644 --- a/include/Win_GParted.h +++ b/include/Win_GParted.h @@ -259,8 +259,7 @@ private: std::vector device_info ; //stuff for progress overview and pulsebar - Glib::Thread *thread ; - bool pulse ; + bool pulsebar_pulse(); }; } //GParted diff --git a/src/Dialog_Progress.cc b/src/Dialog_Progress.cc index dd314e8b..6e3fe2f7 100644 --- a/src/Dialog_Progress.cc +++ b/src/Dialog_Progress.cc @@ -152,8 +152,6 @@ void Dialog_Progress::on_signal_update( const OperationDetail & operationdetail break ; } - pulse = operationdetail .fraction < 0 ; - //update the gui elements.. this ->operationdetail = operationdetail ; @@ -161,6 +159,11 @@ void Dialog_Progress::on_signal_update( const OperationDetail & operationdetail label_current_sub_text = operationdetail .get_description() ; dispatcher_update_gui_elements() ; + if ( operationdetail.fraction >= 0 ) { + pulsetimer.disconnect(); + progressbar_current.set_fraction( operationdetail.fraction > 1.0 ? 1.0 : operationdetail.fraction ); + } else if( !pulsetimer.connected() ) + pulsetimer = Glib::signal_timeout().connect( sigc::mem_fun(*this, &Dialog_Progress::pulsebar_pulse), 100 ); } else//it's an new od which needs to be added to the model. { @@ -183,13 +186,16 @@ void Dialog_Progress::dispatcher_on_update_gui_elements() { label_current_sub .set_markup( "" + label_current_sub_text + "\n" ) ; - if ( operationdetail .fraction >= 0 ) - progressbar_current .set_fraction( operationdetail .fraction > 1.0 ? 1.0 : operationdetail .fraction ) ; - //To ensure progress bar height remains the same, add a space in case message is empty progressbar_current .set_text( operationdetail .progress_text + " " ) ; } +bool Dialog_Progress::pulsebar_pulse() +{ + progressbar_current.pulse(); + return true; +} + void Dialog_Progress::on_signal_show() { for ( t = 0 ; t < operations .size() && succes && ! cancel ; t++ ) @@ -211,19 +217,8 @@ void Dialog_Progress::on_signal_show() treeview_operations .set_cursor( static_cast( treerow ) ) ; //and start.. - running = true ; pthread_create( & pthread, NULL, Dialog_Progress::static_pthread_apply_operation, this ); - - while ( running ) - { - if ( pulse ) - progressbar_current .pulse() ; - - while ( Gtk::Main::events_pending() ) - Gtk::Main::iteration(); - usleep( 100000 ) ; - } - + Gtk::Main::run(); //set status (succes/error) for this operation operations[ t ] ->operation_detail .set_status( succes ? STATUS_SUCCES : STATUS_ERROR ) ; } @@ -236,6 +231,8 @@ void Dialog_Progress::on_signal_show() this ->get_action_area() ->remove( * children .back() ) ; this ->add_button( Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE ); + pulsetimer.disconnect(); + if ( cancel ) { progressbar_current .set_text( _("Operation cancelled") ) ; @@ -299,13 +296,19 @@ void Dialog_Progress::on_cell_data_description( Gtk::CellRenderer * renderer, co static_cast( *iter )[ treeview_operations_columns .operation_description ] ; } +static bool _mainquit( void *dummy ) +{ + Gtk::Main::quit(); + return false; +} + void * Dialog_Progress::static_pthread_apply_operation( void * p_dialog_progress ) { Dialog_Progress *dp = static_cast( p_dialog_progress ) ; dp ->succes = dp ->signal_apply_operation .emit( dp ->operations[ dp ->t ] ) ; - dp ->running = false ; + g_idle_add( (GSourceFunc)_mainquit, NULL ); return NULL ; } @@ -328,7 +331,7 @@ void Dialog_Progress::on_cancel() { pthread_cancel( pthread ) ; cancel = true ; - running = false ; + Gtk::Main::quit(); succes = false ; } } diff --git a/src/Win_GParted.cc b/src/Win_GParted.cc index 0c8302de..4e3e859f 100644 --- a/src/Win_GParted.cc +++ b/src/Win_GParted.cc @@ -53,7 +53,6 @@ Win_GParted::Win_GParted( const std::vector & user_devices ) selected_partition .Reset() ; new_count = 1; current_device = 0 ; - pulse = false ; OPERATIONSLIST_OPEN = true ; gparted_core .set_user_devices( user_devices ) ; @@ -608,8 +607,22 @@ void Win_GParted::refresh_combo_devices() combo_devices .set_active( current_device ) ; } +bool Win_GParted::pulsebar_pulse() +{ + pulsebar.pulse(); + Glib::ustring tmp_msg = gparted_core .get_thread_status_message() ; + if ( tmp_msg != "" ) { + statusbar.pop(); + statusbar.push( tmp_msg ); + } + + return true; +} + void Win_GParted::show_pulsebar( const Glib::ustring & status_message ) { + sigc::connection pulsetimer; + pulsebar .show(); statusbar .push( status_message) ; @@ -621,20 +634,10 @@ void Win_GParted::show_pulsebar( const Glib::ustring & status_message ) treeview_detail .set_sensitive( false ) ; drawingarea_visualdisk .set_sensitive( false ) ; - //the actual 'pulsing' - while ( pulse ) - { - pulsebar .pulse(); - while ( Gtk::Main::events_pending() ) - Gtk::Main::iteration(); - usleep( 100000 ); - Glib::ustring tmp_msg = gparted_core .get_thread_status_message() ; - if ( tmp_msg != "" ) - statusbar .push( tmp_msg ) ; - } - - thread ->join() ; - + // connect pulse update timer + pulsetimer = Glib::signal_timeout().connect( sigc::mem_fun(*this, &Win_GParted::pulsebar_pulse), 100 ); + Gtk::Main::run(); + pulsetimer.disconnect(); pulsebar .hide(); statusbar .pop() ; @@ -1199,13 +1202,12 @@ void Win_GParted::on_show() void Win_GParted::thread_refresh_devices() { gparted_core .set_devices( devices ) ; - pulse = false ; + Gtk::Main::quit(); } void Win_GParted::menu_gparted_refresh_devices() { - pulse = true ; - thread = Glib::Thread::create( sigc::mem_fun( *this, &Win_GParted::thread_refresh_devices ), true ) ; + Glib::Thread::create( sigc::mem_fun( *this, &Win_GParted::thread_refresh_devices ), false ); show_pulsebar( _("Scanning all devices...") ) ; @@ -2012,7 +2014,7 @@ void Win_GParted::thread_unmount_partition( bool * succes, Glib::ustring * error else *error = "" + Glib::build_path( "\n", errors ) + "" ; - pulse = false ; + Gtk::Main::quit(); } void Win_GParted::thread_mount_partition( Glib::ustring mountpoint, bool * succes, Glib::ustring * error ) @@ -2023,8 +2025,7 @@ void Win_GParted::thread_mount_partition( Glib::ustring mountpoint, bool * succe *succes = ! Utils::execute_command( "mount -v " + selected_partition .get_path() + " \"" + mountpoint + "\"", dummy, *error ) ; - - pulse = false ; + Gtk::Main::quit(); } void Win_GParted::thread_toggle_swap( bool * succes, Glib::ustring * error ) @@ -2039,8 +2040,7 @@ void Win_GParted::thread_toggle_swap( bool * succes, Glib::ustring * error ) *succes = ! Utils::execute_command( "swapon -v " + selected_partition .get_path() + " && sync", dummy, *error ) ; - - pulse = false ; + Gtk::Main::quit(); } void Win_GParted::thread_toggle_lvm2_pv( bool * success, Glib::ustring * error ) @@ -2056,8 +2056,7 @@ void Win_GParted::thread_toggle_lvm2_pv( bool * success, Glib::ustring * error ) *success = ! Utils::execute_command( "lvm vgchange -a y " + selected_partition .get_mountpoint(), dummy, *error ) ; - - pulse = false ; + Gtk::Main::quit(); } // Runs gpart in a thread @@ -2065,7 +2064,7 @@ void Win_GParted::thread_guess_partition_table() { this->gpart_output=""; this->gparted_core.guess_partition_table(devices[ current_device ], this->gpart_output); - pulse=false; + Gtk::Main::quit(); } void Win_GParted::toggle_busy_state() @@ -2116,12 +2115,10 @@ void Win_GParted::toggle_busy_state() bool succes = false ; Glib::ustring error ; - pulse = true ; - if ( selected_partition .filesystem == GParted::FS_LINUX_SWAP ) { - thread = Glib::Thread::create( sigc::bind( - sigc::mem_fun( *this, &Win_GParted::thread_toggle_swap ), &succes, &error ), true ) ; + Glib::Thread::create( sigc::bind( + sigc::mem_fun( *this, &Win_GParted::thread_toggle_swap ), &succes, &error ), false ); show_pulsebar( String::ucompose( @@ -2145,8 +2142,8 @@ void Win_GParted::toggle_busy_state() } else if ( selected_partition .filesystem == GParted::FS_LVM2_PV ) { - thread = Glib::Thread::create( sigc::bind( - sigc::mem_fun( *this, &Win_GParted::thread_toggle_lvm2_pv ), &succes, &error ), true ) ; + Glib::Thread::create( sigc::bind( + sigc::mem_fun( *this, &Win_GParted::thread_toggle_lvm2_pv ), &succes, &error ), false ); show_pulsebar( String::ucompose( @@ -2173,8 +2170,8 @@ void Win_GParted::toggle_busy_state() } else if ( selected_partition .busy ) { - thread = Glib::Thread::create( sigc::bind( - sigc::mem_fun( *this, &Win_GParted::thread_unmount_partition ), &succes, &error ), true ) ; + Glib::Thread::create( sigc::bind( + sigc::mem_fun( *this, &Win_GParted::thread_unmount_partition ), &succes, &error ), false ); show_pulsebar( String::ucompose( _("Unmounting %1"), selected_partition .get_path() ) ) ; @@ -2228,14 +2225,12 @@ void Win_GParted::activate_mount_partition( unsigned int index ) bool succes = false ; Glib::ustring error ; - pulse = true ; - - thread = Glib::Thread::create( sigc::bind( + Glib::Thread::create( sigc::bind( sigc::mem_fun( *this, &Win_GParted::thread_mount_partition ), selected_partition .get_mountpoints()[ index ], &succes, &error ), - true ) ; + false ); show_pulsebar( String::ucompose( _("mounting %1 on %2"), selected_partition .get_path(), @@ -2380,8 +2375,7 @@ void Win_GParted::activate_attempt_rescue_data() messageDialog.hide(); - pulse=true; - this->thread = Glib::Thread::create( sigc::mem_fun( *this, &Win_GParted::thread_guess_partition_table ), true ) ; + Glib::Thread::create( sigc::mem_fun( *this, &Win_GParted::thread_guess_partition_table ), false ); /*TO TRANSLATORS: looks like Searching for file systems on /deb/sdb */ show_pulsebar(String::ucompose( _("Searching for file systems on %1"), devices[ current_device ] .get_path()));