[gparted/psusi/refactor: 1/19] Refactor Win_GParted::show_pulsebar



commit e32fc1d595c4d20b0244db57cfc8d0fc9f8e168f
Author: Phillip Susi <psusi ubuntu com>
Date:   Tue Jan 24 19:16:28 2012 -0500

    Refactor Win_GParted::show_pulsebar
    
    Refactor Win_GParted::show_pulsebar and callers to set a timer to drive
    the pulsebar.pulse() calls instead of a nested main loop with usleeps.
    Now show_pulsebar performs initialization, sets a timer to call pulse, and
    returns.  Callers save a member function pointer in Win_GParted::
    pulsebar_completion to be called when the background thread is finished.
    When the background thread finishes, it calls pulsebar_invoke_completion,
    which queues an idle callback to be called in the main thread to cleanup
    and call the pulsebar_completion callback.

 include/Win_GParted.h |   22 ++++-
 src/Win_GParted.cc    |  196 +++++++++++++++++++++++--------------------------
 2 files changed, 108 insertions(+), 110 deletions(-)
---
diff --git a/include/Win_GParted.h b/include/Win_GParted.h
index 6738347..448f915 100644
--- a/include/Win_GParted.h
+++ b/include/Win_GParted.h
@@ -127,9 +127,9 @@ private:
 		
 	//threads..
 	void thread_refresh_devices() ;
-	void thread_unmount_partition( bool * succes, Glib::ustring * error ) ;
-	void thread_mount_partition( Glib::ustring mountpoint, bool * succes, Glib::ustring * error ) ;
-	void thread_toggle_swap( bool * succes, Glib::ustring * error ) ;
+	void thread_unmount_partition() ;
+	void thread_mount_partition( Glib::ustring mountpoint ) ;
+	void thread_toggle_swap() ;
 	void thread_guess_partition_table();
 		
 	//signal handlers
@@ -142,6 +142,7 @@ private:
 	void on_show() ;
 		
 	void menu_gparted_refresh_devices();
+	void menu_gparted_refresh_devices_completion();
 	void menu_gparted_features();
 	void menu_gparted_quit();
 	void menu_view_harddisk_info();
@@ -165,9 +166,12 @@ private:
 	void activate_info();
 	void activate_format( GParted::FILESYSTEM new_fs );
 	void toggle_swap_mount_state() ;
+	void toggle_swap_mount_state_completion() ;
 	void activate_mount_partition( unsigned int index ) ;
+	void activate_mount_partition_completion() ;
 	void activate_disklabel() ;
 	void activate_attempt_rescue_data();
+	void activate_attempt_rescue_data_completion();
 	void activate_manage_flags() ;
 	void activate_check() ;
 	void activate_change_uuid() ;
@@ -257,8 +261,16 @@ private:
 	std::vector<Gtk::Label *> device_info ;
 					
 	//stuff for progress overview and pulsebar
-	Glib::Thread *thread ;
-	bool pulse ;
+	sigc::connection pulsetimer;
+	bool pulsebar_pulse();
+	void (Win_GParted::*pulsebarcompletion)();
+	bool thread_succes;
+	Glib::ustring thread_error;
+	void pulsebar_complete();
+	void pulsebar_invoke_completion() {
+		Glib::signal_idle().connect_once (sigc::mem_fun (*this, &Win_GParted::pulsebar_complete));
+	}
+	unsigned int threadactivateindex;
 };
 
 } //GParted
diff --git a/src/Win_GParted.cc b/src/Win_GParted.cc
index 2706c1b..651704a 100644
--- a/src/Win_GParted.cc
+++ b/src/Win_GParted.cc
@@ -51,7 +51,7 @@ Win_GParted::Win_GParted( const std::vector<Glib::ustring> & user_devices )
 	selected_partition .Reset() ;
 	new_count = 1;
 	current_device = 0 ;
-	pulse = false ; 
+	pulsebarcompletion = 0;
 	OPERATIONSLIST_OPEN = true ;
 	gparted_core .set_user_devices( user_devices ) ;
 	
@@ -121,7 +121,7 @@ Win_GParted::Win_GParted( const std::vector<Glib::ustring> & user_devices )
 	vpaned_main .pack2( hbox_operations, true, true ) ;
 
 	//statusbar... 
-	pulsebar .set_pulse_step( 0.01 );
+	pulsebar .set_pulse_step( 0.02 );
 	statusbar .add( pulsebar );
 	vbox_main .pack_start( statusbar, Gtk::PACK_SHRINK );
 	
@@ -607,6 +607,17 @@ void Win_GParted::refresh_combo_devices()
 	combo_devices .set_active( current_device ) ;
 }
 
+bool Win_GParted::pulsebar_pulse()
+{
+	gdk_threads_enter();
+	pulsebar.pulse();
+	Glib::ustring tmp_msg = gparted_core .get_thread_status_message() ;
+	if ( tmp_msg != "" )
+		statusbar .push( tmp_msg ) ;
+	gdk_threads_leave();
+	return true;
+}
+
 void Win_GParted::show_pulsebar( const Glib::ustring & status_message ) 
 {
 	pulsebar .show();
@@ -620,22 +631,13 @@ 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();
-		gdk_threads_leave();
-		usleep( 100000 );
-		gdk_threads_enter();
-		Glib::ustring tmp_msg = gparted_core .get_thread_status_message() ;
-		if ( tmp_msg != "" )
-			statusbar .push( tmp_msg ) ;
-	}
-	
-	thread ->join() ;
-	
+	pulsetimer = Glib::signal_timeout().connect( sigc::mem_fun(*this, &Win_GParted::pulsebar_pulse), 50 );
+}
+
+void Win_GParted::pulsebar_complete()
+{
+	gdk_threads_enter();
+	pulsetimer.disconnect();
 	pulsebar .hide();
 	statusbar .pop() ;
 		
@@ -646,6 +648,9 @@ void Win_GParted::show_pulsebar( const Glib::ustring & status_message )
 	menu_partition .set_sensitive( true ) ;
 	treeview_detail .set_sensitive( true ) ;
 	drawingarea_visualdisk .set_sensitive( true ) ;
+	(this->*pulsebarcompletion)();
+	pulsebarcompletion = 0;
+	gdk_threads_leave();
 }
 
 void Win_GParted::Fill_Label_Device_Info( bool clear ) 
@@ -1182,16 +1187,18 @@ void Win_GParted::on_show()
 void Win_GParted::thread_refresh_devices() 
 {
 	gparted_core .set_devices( devices ) ;
-	pulse = false ;
+	pulsebar_invoke_completion();
 }
 
 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 ) ;
+	pulsebarcompletion = &Win_GParted::menu_gparted_refresh_devices_completion;
 	show_pulsebar( _("Scanning all devices...") ) ;
-	
+}
+
+void Win_GParted::menu_gparted_refresh_devices_completion()
+{
 	//check if current_device is still available (think about hotpluggable stuff like usbdevices)
 	if ( current_device >= devices .size() )
 		current_device = 0 ;
@@ -1903,12 +1910,12 @@ void Win_GParted::activate_format( GParted::FILESYSTEM new_fs )
 	}
 }
 
-void Win_GParted::thread_unmount_partition( bool * succes, Glib::ustring * error ) 
+void Win_GParted::thread_unmount_partition()
 {
 	std::vector<Glib::ustring> errors, failed_mountpoints, mountpoints = gparted_core .get_all_mountpoints() ;
 	Glib::ustring dummy ;
 
-	*succes = true ; 
+	thread_succes = true ;
 	for ( unsigned int t = 0 ; t < selected_partition .get_mountpoints() .size() ; t++ )
 		if ( std::count( mountpoints .begin(),
 				 mountpoints .end(),
@@ -1916,55 +1923,55 @@ void Win_GParted::thread_unmount_partition( bool * succes, Glib::ustring * error
 		{
 			if ( Utils::execute_command( "umount -v \"" + selected_partition .get_mountpoints()[ t ] + "\"",
 						     dummy,
-						     *error ) )
+						     thread_error ) )
 			{
-				*succes = false ;
-				errors .push_back( *error ) ;	
+				thread_succes = false ;
+				errors .push_back( thread_error ) ;
 			}
 		}
 		else
 			failed_mountpoints .push_back( selected_partition .get_mountpoints()[ t ] ) ;
 
 	
-	if ( *succes && failed_mountpoints .size() )
+	if ( thread_succes && failed_mountpoints .size() )
 	{
-		*succes = false ;
-		*error = _("The partition could not be unmounted from the following mount points:") ;
-		*error += "\n\n<i>" + Glib::build_path( "\n", failed_mountpoints ) + "</i>\n\n" ;
-		*error +=  _("Most likely other partitions are also mounted on these mount points. You are advised to unmount them manually.") ;
+		thread_succes = false ;
+		thread_error = _("The partition could not be unmounted from the following mount points:") ;
+		thread_error += "\n\n<i>" + Glib::build_path( "\n", failed_mountpoints ) + "</i>\n\n" ;
+		thread_error +=  _("Most likely other partitions are also mounted on these mount points. You are advised to unmount them manually.") ;
 	}
 	else
-		*error = "<i>" + Glib::build_path( "\n", errors ) + "</i>" ;
+		thread_error = "<i>" + Glib::build_path( "\n", errors ) + "</i>" ;
 
-	pulse = false ;
+	pulsebar_invoke_completion();
 }
 	
-void Win_GParted::thread_mount_partition( Glib::ustring mountpoint, bool * succes, Glib::ustring * error ) 
+void Win_GParted::thread_mount_partition( Glib::ustring mountpoint )
 {
 	Glib::ustring dummy ;
 	std::vector<Glib::ustring> errors ;
 	
-	*succes = ! Utils::execute_command( "mount -v " + selected_partition .get_path() + " \"" + mountpoint + "\"",
+	thread_succes = ! Utils::execute_command( "mount -v " + selected_partition .get_path() + " \"" + mountpoint + "\"",
 					    dummy,
-					    *error ) ;
+					    thread_error ) ;
 
-	pulse = false ;
+	pulsebar_invoke_completion();
 }
 
-void Win_GParted::thread_toggle_swap( bool * succes, Glib::ustring * error ) 
+void Win_GParted::thread_toggle_swap()
 {	
 	Glib::ustring dummy ;
 	
 	if ( selected_partition .busy )
-		*succes = ! Utils::execute_command( "swapoff -v " + selected_partition .get_path() + " && sync",
-						    dummy,
-						    *error ) ;
+		thread_succes = ! Utils::execute_command( "swapoff -v " + selected_partition .get_path() + " && sync",
+							  dummy,
+							  thread_error ) ;
 	else
-		*succes = ! Utils::execute_command( "swapon -v " + selected_partition .get_path() + " && sync",
-						    dummy,
-						    *error ) ;
+		thread_succes = ! Utils::execute_command( "swapon -v " + selected_partition .get_path() + " && sync",
+							  dummy,
+							  thread_error ) ;
 
-	pulse = false ;
+	pulsebar_invoke_completion();
 }
 
 // Runs gpart in a thread
@@ -1972,7 +1979,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;
+	pulsebar_invoke_completion();
 }
 
 void Win_GParted::toggle_swap_mount_state()
@@ -2010,59 +2017,39 @@ void Win_GParted::toggle_swap_mount_state()
 		return ;
 	}
 
-	bool succes = false ;
-	Glib::ustring error ;
-
-	pulse = true ;
+	thread_succes = false ;
 
 	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::mem_fun( *this, &Win_GParted::thread_toggle_swap ), false ) ;
+		pulsebarcompletion = &Win_GParted::toggle_swap_mount_state_completion;
 		show_pulsebar( 
 			String::ucompose( 
 				selected_partition .busy ? _("Deactivating swap on %1") : _("Activating swap on %1"),
 				selected_partition .get_path() ) ) ;
 
-		if ( ! succes )
-		{
-			Gtk::MessageDialog dialog( 
-				*this,
-				selected_partition .busy ? _("Could not deactivate swap") : _("Could not activate swap"),
-				false,
-				Gtk::MESSAGE_ERROR,
-				Gtk::BUTTONS_OK,
-				true ) ;
-
-			dialog .set_secondary_text( error ) ;
-			
-			dialog.run() ;
-		}
 	}
-	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 ) ;
+	/* else shouldn't this be an error? */
 
-		show_pulsebar( String::ucompose( _("Unmounting %1"), selected_partition .get_path() ) ) ;
-	
-		if ( ! succes )
-		{
-			Gtk::MessageDialog dialog( *this, 
-						   String::ucompose( _("Could not unmount %1"), selected_partition .get_path() ),
-						   false,
-						   Gtk::MESSAGE_ERROR,
-						   Gtk::BUTTONS_OK,
-						   true );
+	menu_gparted_refresh_devices() ;
+}
+
+void Win_GParted::toggle_swap_mount_state_completion()
+{
+	if ( ! thread_succes )
+	{
+		Gtk::MessageDialog dialog(
+			*this,
+			selected_partition .busy ? _("Could not deactivate swap") : _("Could not activate swap"),
+			false,
+			Gtk::MESSAGE_ERROR,
+			Gtk::BUTTONS_OK,
+			true ) ;
 
-			dialog .set_secondary_text( error, true ) ;
+		dialog .set_secondary_text( thread_error ) ;
 		
-			dialog.run() ;
-		}
+		dialog.run() ;
 	}
-
-	menu_gparted_refresh_devices() ;
 }
 
 void Win_GParted::activate_mount_partition( unsigned int index ) 
@@ -2094,34 +2081,31 @@ void Win_GParted::activate_mount_partition( unsigned int index )
 		return ;
 	}
 
-	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>(
 						sigc::mem_fun( *this, &Win_GParted::thread_mount_partition ),
-						selected_partition .get_mountpoints()[ index ],
-						&succes,
-						&error ),
-				       true ) ;
-
+						selected_partition .get_mountpoints()[ index ] ),
+				       false ) ;
+	pulsebarcompletion = &Win_GParted::activate_mount_partition_completion;
+	threadactivateindex = index;
 	show_pulsebar( String::ucompose( _("mounting %1 on %2"),
 					 selected_partition .get_path(),
 					 selected_partition .get_mountpoints()[ index ] ) ) ;
+}
 
-	if ( ! succes )
+void Win_GParted::activate_mount_partition_completion()
+{
+	if ( ! thread_succes )
 	{
 		Gtk::MessageDialog dialog( *this, 
 					   String::ucompose( _("Could not mount %1 on %2"),
 						   	     selected_partition .get_path(),
-							     selected_partition .get_mountpoints()[ index ] ),
+							     selected_partition .get_mountpoints()[ threadactivateindex ] ),
 					   false,
 					   Gtk::MESSAGE_ERROR,
 					   Gtk::BUTTONS_OK,
 					   true );
 
-		dialog .set_secondary_text( error, true ) ;
+		dialog .set_secondary_text( thread_error, true ) ;
 	
 		dialog.run() ;
 	}
@@ -2249,12 +2233,14 @@ 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 ) ;
+	pulsebarcompletion = &Win_GParted::activate_attempt_rescue_data_completion;
 	/*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()));
+}
 
+void Win_GParted::activate_attempt_rescue_data_completion()
+{
 	Dialog_Rescue_Data dialog;
 	dialog .set_transient_for( *this );
 



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