[gparted/psusi/refactor: 2/19] Use a full fledged nested main loop while waiting and pulsing progress bars (#685740)



commit 9e828c10ea4537c2d5e20e5a455deff8af498068
Author: Phillip Susi <psusi ubuntu com>
Date:   Mon Jan 14 21:20:49 2013 -0500

    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 e3be49e..a580ddb 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<Operation *> 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 d9a2e41..15a4f34 100644
--- a/include/Win_GParted.h
+++ b/include/Win_GParted.h
@@ -259,8 +259,7 @@ private:
 	std::vector<Gtk::Label *> 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 dd314e8..6e3fe2f 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( "<i>" + label_current_sub_text + "</i>\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<Gtk::TreePath>( 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<Gtk::TreeRow>( *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<Dialog_Progress *>( 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 c26f7f9..62ad11b 100644
--- a/src/Win_GParted.cc
+++ b/src/Win_GParted.cc
@@ -53,7 +53,6 @@ Win_GParted::Win_GParted( const std::vector<Glib::ustring> & 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 = "<i>" + Glib::build_path( "\n", errors ) + "</i>" ;
 
-	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<bool *, Glib::ustring *>( 
-			sigc::mem_fun( *this, &Win_GParted::thread_toggle_swap ), &succes, &error ), true ) ;
+		Glib::Thread::create( sigc::bind<bool *, Glib::ustring *>( 
+			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<bool *, Glib::ustring *>(
-			sigc::mem_fun( *this, &Win_GParted::thread_toggle_lvm2_pv ), &succes, &error ), true ) ;
+		Glib::Thread::create( sigc::bind<bool *, Glib::ustring *>(
+			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<bool *, Glib::ustring *>( 
-			sigc::mem_fun( *this, &Win_GParted::thread_unmount_partition ), &succes, &error ), true ) ;
+		Glib::Thread::create( sigc::bind<bool *, Glib::ustring *>( 
+			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::ustring, bool *, Glib::ustring *>( 
+	Glib::Thread::create( sigc::bind<Glib::ustring, bool *, Glib::ustring *>( 
 						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()));



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]