[gparted] Connect output progress tracking callbacks inside execute_command() (#760709)



commit c00927c23d7b569078473734a3685b5d449d0f70
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Sat Jan 23 09:27:38 2016 +0000

    Connect output progress tracking callbacks inside execute_command() (#760709)
    
    All the output progress tracking callbacks for execution of ext2/3/4 and
    ntfs file system specific commands followed this pattern:
    
        sigc::connection c = signal_progress.connect( sigc::mem_fun( *this, &ext2::..._progress ) );
        bool success = ! execute_command( ... );
        c.disconnect();
        return success;
    
    Instead, pass the callback slot and a flag into execute_command() and
    connect the callback inside.  This simplifies the pattern to:
    
        return ! execute_command( ...|EXEC_PROGRESS_STDOUT,
                                  sigc::mem_fun( *this, &ext2::..._progress ) );
    
    Note that as the progress tracking callbacks are only registered against
    updates to the relevant stream from the tracked commands they won't be
    called when the other stream is updated any more.
    
    Also note that signal_progress is a member of the FileSystem class and
    derived objects so lives as long as GParted is running, therefore the
    progress tracking callbacks need explicitly disconnecting at the end of
    execute_command().  However signal_update is a member of the PipeCapture
    class of which the output and error local variables in execute_command()
    are types.  Therefore there is no need to explicitly disconnect the
    signal_update callbacks as they will be destructed along with the
    callback slots when they go out of scope at the end of the
    execute_command() method.
    
    Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
                 copy methods

 include/FileSystem.h |   30 ++++++++++++++++++++++--------
 src/FileSystem.cc    |   25 ++++++++++++++++++++-----
 src/ext2.cc          |   35 +++++++++++++----------------------
 src/ntfs.cc          |    5 ++---
 4 files changed, 57 insertions(+), 38 deletions(-)
---
diff --git a/include/FileSystem.h b/include/FileSystem.h
index 215bf65..bce53d3 100644
--- a/include/FileSystem.h
+++ b/include/FileSystem.h
@@ -25,19 +25,23 @@
 
 #include <fstream>
 #include <sys/stat.h>
+#include <sigc++/slot.h>
 
 namespace GParted
 {
 
 enum ExecFlags
 {
-       EXEC_NONE         = 1 << 0,
-       EXEC_CHECK_STATUS = 1 << 1,  // Set the status of the command in the operation
-                                    // details based on the exit status being zero or
-                                    // non-zero.  Must either use this flag when calling
-                                    // ::execute_command() or call ::set_status()
-                                    // afterwards.
-       EXEC_CANCEL_SAFE  = 1 << 2
+       EXEC_NONE            = 1 << 0,
+       EXEC_CHECK_STATUS    = 1 << 1,  // Set the status of the command in the operation
+                                       // details based on the exit status being zero or
+                                       // non-zero.  Must either use this flag when calling
+                                       // ::execute_command() or call ::set_status()
+                                       // afterwards.
+       EXEC_CANCEL_SAFE     = 1 << 2,
+       EXEC_PROGRESS_STDOUT = 1 << 3,  // Run progress tracking callback after reading new
+                                       // data on stdout from command.
+       EXEC_PROGRESS_STDERR = 1 << 4   // Same but for stderr.
 };
 
 inline ExecFlags operator|( ExecFlags lhs, ExecFlags rhs )
@@ -77,8 +81,18 @@ public:
        virtual bool remove( const Partition & partition, OperationDetail & operationdetail ) { return true; 
};
 
 protected:
+       typedef sigc::slot<void, OperationDetail *> StreamSlot;
+
+       // Use sigc::slot<> class default constructor, via StreamSlot typedef, to create
+       // an empty, unconnected slot to use as the default stream_progress_slot parameter
+       // for when none is provided.
+       // References:
+       // *   How to set default parameter as class object in c++?
+       //     http://stackoverflow.com/questions/12121645/how-to-set-default-parameter-as-class-object-in-c
+       // *   C++ function, what default value can I give for an object?
+       //     
http://stackoverflow.com/questions/9909444/c-function-what-default-value-can-i-give-for-an-object
        int execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
-                            ExecFlags flags = EXEC_NONE );
+                            ExecFlags flags = EXEC_NONE, StreamSlot stream_progress_slot = StreamSlot() );
        void set_status( OperationDetail & operationdetail, bool success );
        void execute_command_eof();
        Glib::ustring mk_temp_dir( const Glib::ustring & infix, OperationDetail & operationdetail ) ;
diff --git a/src/FileSystem.cc b/src/FileSystem.cc
index 0b4b9e1..10870b5 100644
--- a/src/FileSystem.cc
+++ b/src/FileSystem.cc
@@ -23,6 +23,7 @@
 #include <gtkmm/main.h>
 #include <signal.h>
 #include <fcntl.h>
+#include <sigc++/slot.h>
 
 namespace GParted
 {
@@ -80,7 +81,7 @@ static void setup_child()
 }
 
 int FileSystem::execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
-                                 ExecFlags flags )
+                                 ExecFlags flags, StreamSlot stream_progress_slot )
 {
        operationdetail.add_child( OperationDetail( command, STATUS_EXECUTE, FONT_BOLD_ITALIC ) );
        Glib::Pid pid;
@@ -122,13 +123,24 @@ int FileSystem::execute_command( const Glib::ustring & command, OperationDetail
        outputcapture.signal_update.connect( sigc::bind( sigc::ptr_fun( update_command_output ),
                                                         children[children.size() - 2],
                                                         &output ) );
-       outputcapture.signal_update.connect( sigc::bind( sigc::mem_fun( *this, 
&FileSystem::update_command_progress ),
-                                                        &operationdetail ) );
        errorcapture.signal_update.connect( sigc::bind( sigc::ptr_fun( update_command_output ),
                                                        children[children.size() - 1],
                                                        &error ) );
-       errorcapture.signal_update.connect( sigc::bind( sigc::mem_fun( *this, 
&FileSystem::update_command_progress ),
-                                                       &operationdetail ) );
+       sigc::connection c;
+       if ( flags & EXEC_PROGRESS_STDOUT && ! stream_progress_slot.empty() )
+       {
+               // Call progress tracking callback when stdout updates
+               outputcapture.signal_update.connect( sigc::bind( sigc::mem_fun( *this, 
&FileSystem::update_command_progress ),
+                                                                &operationdetail ) );
+               c = signal_progress.connect( stream_progress_slot );
+       }
+       else if ( flags & EXEC_PROGRESS_STDERR && ! stream_progress_slot.empty() )
+       {
+               // Call progress tracking callback when stderr updates
+               errorcapture.signal_update.connect( sigc::bind( sigc::mem_fun( *this, 
&FileSystem::update_command_progress ),
+                                                               &operationdetail ) );
+               c = signal_progress.connect( stream_progress_slot );
+       }
        outputcapture.connect_signal();
        errorcapture.connect_signal();
 
@@ -148,6 +160,9 @@ int FileSystem::execute_command( const Glib::ustring & command, OperationDetail
        }
        close( out );
        close( err );
+       if ( c.connected() )
+               c.disconnect();
+       operationdetail.stop_progressbar();
        return exit_status;
 }
 
diff --git a/src/ext2.cc b/src/ext2.cc
index 1e89a41..cb2b873 100644
--- a/src/ext2.cc
+++ b/src/ext2.cc
@@ -228,12 +228,10 @@ bool ext2::write_uuid( const Partition & partition, OperationDetail & operationd
 
 bool ext2::create( const Partition & new_partition, OperationDetail & operationdetail )
 {
-       sigc::connection c = signal_progress.connect( sigc::mem_fun( *this, &ext2::create_progress ) );
-       bool ret = ! execute_command( mkfs_cmd + " -F -L \"" + new_partition.get_filesystem_label() + "\" " +
-                                     new_partition.get_path(),
-                                     operationdetail, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE );
-       c.disconnect();
-       return ret;
+       return ! execute_command( mkfs_cmd + " -F -L \"" + new_partition.get_filesystem_label() + "\" " +
+                                 new_partition.get_path(),
+                                 operationdetail, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE|EXEC_PROGRESS_STDOUT,
+                                 sigc::mem_fun( *this, &ext2::create_progress ) );
 }
 
 bool ext2::resize( const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition )
@@ -244,18 +242,15 @@ bool ext2::resize( const Partition & partition_new, OperationDetail & operationd
                str_temp += " " + Utils::num_to_str( floor( Utils::sector_to_unit(
                                        partition_new .get_sector_length(), partition_new .sector_size, 
UNIT_KIB ) ) ) + "K";
 
-       sigc::connection c = signal_progress.connect( sigc::mem_fun( *this, &ext2::resize_progress ) );
-       bool ret = ! execute_command( str_temp, operationdetail, EXEC_CHECK_STATUS );
-       c.disconnect();
-       return ret;
+       return ! execute_command( str_temp, operationdetail, EXEC_CHECK_STATUS|EXEC_PROGRESS_STDOUT,
+                                 sigc::mem_fun( *this, &ext2::resize_progress ) );
 }
 
 bool ext2::check_repair( const Partition & partition, OperationDetail & operationdetail )
 {
-       sigc::connection c = signal_progress.connect( sigc::mem_fun( *this, &ext2::check_repair_progress ) );
        exit_status = execute_command( fsck_cmd + " -f -y -v -C 0 " + partition.get_path(), operationdetail,
-                                      EXEC_CANCEL_SAFE );
-       c.disconnect();
+                                      EXEC_CANCEL_SAFE|EXEC_PROGRESS_STDOUT,
+                                      sigc::mem_fun( *this, &ext2::check_repair_progress ) );
        bool success = ( exit_status == 0 || exit_status == 1 || exit_status == 2 );
        set_status( operationdetail, success );
        return success;
@@ -274,10 +269,8 @@ bool ext2::move( const Partition & partition_new,
                cmd = image_cmd + " -ra -p -O " + offset + " " + partition_new.get_path();
 
        fs_block_size = partition_old.fs_block_size;
-       sigc::connection c = signal_progress.connect( sigc::mem_fun( *this, &ext2::copy_progress ) );
-       bool success = ! execute_command( cmd, operationdetail, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE );
-       c.disconnect();
-       return success;
+       return ! execute_command( cmd, operationdetail, 
EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE|EXEC_PROGRESS_STDERR,
+                                 sigc::mem_fun( *this, &ext2::copy_progress ) );
 }
 
 bool ext2::copy( const Partition & src_part,
@@ -285,11 +278,9 @@ bool ext2::copy( const Partition & src_part,
                  OperationDetail & operationdetail )
 {
        fs_block_size = src_part.fs_block_size;
-       sigc::connection c = signal_progress.connect( sigc::mem_fun( *this, &ext2::copy_progress ) );
-       bool success = ! execute_command( image_cmd + " -ra -p " + src_part.get_path() + " " + 
dest_part.get_path(),
-                                         operationdetail, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE );
-       c.disconnect();
-       return success;
+       return ! execute_command( image_cmd + " -ra -p " + src_part.get_path() + " " + dest_part.get_path(),
+                                 operationdetail, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE|EXEC_PROGRESS_STDERR,
+                                 sigc::mem_fun( *this, &ext2::copy_progress ) );
 }
 
 //Private methods
diff --git a/src/ntfs.cc b/src/ntfs.cc
index 0a75bdf..d5d6700 100644
--- a/src/ntfs.cc
+++ b/src/ntfs.cc
@@ -234,9 +234,9 @@ bool ntfs::resize( const Partition & partition_new, OperationDetail & operationd
                //real resize
                operationdetail .add_child( OperationDetail( _("real resize") ) ) ;
 
-               sigc::connection c = signal_progress.connect( sigc::mem_fun( *this, &ntfs::resize_progress ) 
);
                if ( ! execute_command( cmd + " " + partition_new.get_path(),
-                                       operationdetail.get_last_child(), EXEC_CHECK_STATUS ) )
+                                       operationdetail.get_last_child(), 
EXEC_CHECK_STATUS|EXEC_PROGRESS_STDOUT,
+                                       sigc::mem_fun( *this, &ntfs::resize_progress ) ) )
                {
                        operationdetail .get_last_child() .set_status( STATUS_SUCCES ) ;
                        return_value = true ;
@@ -245,7 +245,6 @@ bool ntfs::resize( const Partition & partition_new, OperationDetail & operationd
                {
                        operationdetail .get_last_child() .set_status( STATUS_ERROR ) ;
                }
-               c.disconnect();
        }
        else
        {


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