[gparted] Use a full fledged nested main loop while waiting and pulsing progress bars (#685740)



commit 124342e9791f995a6cd6f7bc09405a859054d6dd
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 0c8302d..4e3e859 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]