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
This commit is contained in:
parent
27e30a570f
commit
c00927c23d
|
@ -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 ) ;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
35
src/ext2.cc
35
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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue