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
This commit is contained in:
Phillip Susi 2013-01-14 21:20:49 -05:00 committed by Curtis Gedak
parent f5a5c9cdb9
commit 124342e979
4 changed files with 60 additions and 63 deletions

View File

@ -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 ;
};

View File

@ -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

View File

@ -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 ;
}
}

View File

@ -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()));