Simplify use of the progress bar via OperationDetail (#760709)

Most of the file system specific command progress trackers followed this
pattern:

    void {CLASS}::{NAME}_progress( OperationDetail *operationdetail )
    {
            ProgressBar & progressbar = operationdetail->get_progressbar();
            // parse output for progress and target values
            if ( // have progress and target values )
            {
                    if ( ! progressbar.running() )
                            progressbar.start( target );
                    progressbar.update( progress );
                    operationdetail->signal_update( *operationdetail );
            }
            else if ( // found progress finished )
            {
                    if ( progressbar.running() )
                            progressbar.stop();
                    operationdetail->signal_update( *operationdetail );
            }
    }

That is a lot of repetition handling progress bar updates and
OperationDetail object update signalling.  Remove the need for direct
access to the single ProgressBar object and provide these two
OperationDetail methods instead:
    // Start and update in one
    run_progressbar( progress, target, optional text_mode );
    stop_progressbar();

Now the file system specific command progress trackers can become:

    void {CLASS}::{NAME}_progress( OperationDetail *operationdetail )
    {
            // parse output for progress and target values
            if ( // have progress and target values )
            {
                    operationdetail->run_progressbar( progress, target );
            }
            else if ( // found progress finished )
            {
                    operationdetail->stop_progressbar();
            }
    }

Make ProgressBar::get_progressbar() a private method to enforce use of
the new way to access the progress bar via the run_progress() and
stop_progressbar() methods.  Then make the Dialog_Progress a friend
class to OperationDetail so that the Apply pending operations dialog can
still access the single ProgressBar object for its querying needs.

Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
             copy methods
This commit is contained in:
Mike Fleetwood 2016-01-17 12:38:58 +00:00 committed by Curtis Gedak
parent 32622f4d57
commit b1313281bd
6 changed files with 47 additions and 56 deletions

View File

@ -47,6 +47,10 @@ enum Font {
class OperationDetail
{
friend class Dialog_Progress; // To allow Dialog_Progress::on_signal_update() to call
// get_progressbar() and get direct access to the progress bar.
public:
OperationDetail() ;
~OperationDetail();
@ -65,7 +69,8 @@ public:
std::vector<OperationDetail*> & get_childs() ;
const std::vector<OperationDetail*> & get_childs() const ;
OperationDetail & get_last_child() ;
ProgressBar & get_progressbar() const;
void run_progressbar( double progress, double target, ProgressBar_Text text_mode = PROGRESSBAR_TEXT_NONE );
void stop_progressbar();
double fraction ;
Glib::ustring progress_text ;
@ -73,9 +78,12 @@ public:
sigc::signal< void, const OperationDetail & > signal_update ;
sigc::signal< void, bool > signal_cancel;
char cancelflag;
private:
void on_update( const OperationDetail & operationdetail ) ;
void cancel( bool force );
ProgressBar & get_progressbar() const;
Glib::ustring description ;
OperationDetailStatus status ;

View File

@ -62,7 +62,7 @@ copy_blocks::copy_blocks( const Glib::ustring & in_src_device,
bool copy_blocks::set_progress_info()
{
Byte_Value done = llabs(this->done);
operationdetail.get_progressbar().update( (double)done );
operationdetail.run_progressbar( (double)done, (double)length, PROGRESSBAR_TEXT_COPY_BYTES );
OperationDetail &operationdetail = this->operationdetail.get_last_child().get_last_child();
operationdetail.fraction = done / static_cast<double>( length );
@ -166,7 +166,7 @@ bool copy_blocks::copy()
String::ucompose( _("copy %1 using a block size of %2"),
Utils::format_size( length, 1 ),
Utils::format_size( blocksize, 1 ) ) ) );
operationdetail.get_progressbar().start( (double)length, PROGRESSBAR_TEXT_COPY_BYTES );
operationdetail.run_progressbar( 0.0, (double)length, PROGRESSBAR_TEXT_COPY_BYTES );
done = length % blocksize;
@ -202,7 +202,7 @@ bool copy_blocks::copy()
else
error_message = Glib::strerror( errno );
operationdetail.get_progressbar().stop();
operationdetail.stop_progressbar();
operationdetail.get_last_child().set_status( success ? STATUS_SUCCES : STATUS_ERROR );
return success;
}

View File

@ -160,9 +160,21 @@ OperationDetail & OperationDetail::get_last_child()
return *sub_details[sub_details.size() - 1];
}
ProgressBar & OperationDetail::get_progressbar() const
void OperationDetail::run_progressbar( double progress, double target, ProgressBar_Text text_mode )
{
return single_progressbar;
if ( ! single_progressbar.running() )
single_progressbar.start( target, text_mode );
single_progressbar.update( progress );
signal_update.emit( *this );
}
void OperationDetail::stop_progressbar()
{
if ( single_progressbar.running() )
{
single_progressbar.stop();
signal_update.emit( *this );
}
}
// Private methods
@ -182,4 +194,9 @@ void OperationDetail::cancel( bool force )
signal_cancel(force);
}
ProgressBar & OperationDetail::get_progressbar() const
{
return single_progressbar;
}
} //GParted

View File

@ -296,7 +296,6 @@ bool ext2::copy( const Partition & src_part,
void ext2::resize_progress( OperationDetail *operationdetail )
{
ProgressBar & progressbar = operationdetail->get_progressbar();
Glib::ustring line = Utils::last_line( output );
size_t llen = line.length();
// There may be multiple text progress bars on subsequent last lines which look
@ -317,46 +316,34 @@ void ext2::resize_progress( OperationDetail *operationdetail )
q = llen;
size_t xlen = q - p;
if ( ! progressbar.running() )
progressbar.start( (double)barlen );
progressbar.update( (double)xlen );
operationdetail->signal_update( *operationdetail );
operationdetail->run_progressbar( (double)xlen, (double)barlen );
}
// Ending summary line looks like:
// "The filesystem on /dev/sdb3 is now 256000 block long."
else if ( output.find( " is now " ) != output.npos )
{
if ( progressbar.running() )
progressbar.stop();
operationdetail->signal_update( *operationdetail );
operationdetail->stop_progressbar();
}
}
void ext2::create_progress( OperationDetail *operationdetail )
{
ProgressBar & progressbar = operationdetail->get_progressbar();
Glib::ustring line = Utils::last_line( output );
// Text progress on the LAST LINE looks like "Writing inode tables: 105/1600"
long long progress, target;
if ( sscanf( line.c_str(), "Writing inode tables: %Ld/%Ld", &progress, &target ) == 2 )
{
if ( ! progressbar.running() )
progressbar.start( (double)target );
progressbar.update( (double)progress );
operationdetail->signal_update( *operationdetail );
operationdetail->run_progressbar( (double)progress, (double)target );
}
// Or when finished, on any line, ...
else if ( output.find( "Writing inode tables: done" ) != output.npos )
{
if ( progressbar.running() )
progressbar.stop();
operationdetail->signal_update( *operationdetail );
operationdetail->stop_progressbar();
}
}
void ext2::check_repair_progress( OperationDetail *operationdetail )
{
ProgressBar & progressbar = operationdetail->get_progressbar();
Glib::ustring line = Utils::last_line( output );
// Text progress on the LAST LINE looks like
// "/dev/sdd3: |===================================================== \ 95.1% "
@ -367,10 +354,7 @@ void ext2::check_repair_progress( OperationDetail *operationdetail )
float progress;
if ( line.find( ": |" ) != line.npos && sscanf( pct.c_str(), "%f", &progress ) == 1 )
{
if ( ! progressbar.running() )
progressbar.start( 100.0 );
progressbar.update( progress );
operationdetail->signal_update( *operationdetail );
operationdetail->run_progressbar( progress, 100.0 );
}
// Only allow stopping the progress bar after seeing "non-contiguous" in the
// summary at the end to prevent the GUI progress bar flashing back to pulsing
@ -378,31 +362,25 @@ void ext2::check_repair_progress( OperationDetail *operationdetail )
// output is fully updated when switching from one pass to the next.
else if ( output.find( "non-contiguous" ) != output.npos )
{
if ( progressbar.running() )
progressbar.stop();
operationdetail->signal_update( *operationdetail );
operationdetail->stop_progressbar();
}
}
void ext2::copy_progress( OperationDetail *operationdetail )
{
ProgressBar & progressbar = operationdetail->get_progressbar();
Glib::ustring line = Utils::last_line( error );
// Text progress on the LAST LINE of STDERR looks like "Copying 146483 / 258033 blocks ..."
long long progress, target;
if ( sscanf( line.c_str(), "Copying %Ld / %Ld blocks", &progress, &target ) == 2 )
{
if ( ! progressbar.running() )
progressbar.start( (double)(target * fs_block_size), PROGRESSBAR_TEXT_COPY_BYTES );
progressbar.update( (double)(progress * fs_block_size) );
operationdetail->signal_update( *operationdetail );
operationdetail->run_progressbar( (double)(progress * fs_block_size),
(double)(target * fs_block_size),
PROGRESSBAR_TEXT_COPY_BYTES );
}
// Or when finished, on any line of STDERR, looks like "Copied 258033 / 258033 blocks ..."
else if ( error.find( "\nCopied " ) != error.npos )
{
if ( progressbar.running() )
progressbar.stop();
operationdetail->signal_update( *operationdetail );
operationdetail->stop_progressbar();
}
}

View File

@ -19,7 +19,6 @@
#include "../include/ntfs.h"
#include "../include/OperationDetail.h"
#include "../include/Partition.h"
#include "../include/ProgressBar.h"
#include "../include/Utils.h"
#include <glibmm/ustring.h>
@ -274,7 +273,6 @@ bool ntfs::check_repair( const Partition & partition, OperationDetail & operatio
void ntfs::resize_progress( OperationDetail *operationdetail )
{
ProgressBar & progressbar = operationdetail->get_progressbar();
Glib::ustring line = Utils::last_line( output );
// Text progress on the LAST LINE looks like " 15.24 percent completed"
// NOTE:
@ -289,17 +287,12 @@ void ntfs::resize_progress( OperationDetail *operationdetail )
float percent;
if ( line.find( "percent completed" ) != line.npos && sscanf( line.c_str(), "%f", &percent ) == 1 )
{
if ( ! progressbar.running() )
progressbar.start( 100.0 );
progressbar.update( percent );
operationdetail->signal_update( *operationdetail );
operationdetail->run_progressbar( percent, 100.0 );
}
// Or when finished, on any line, ...
else if ( output.find( "Successfully resized NTFS on device" ) != output.npos )
{
if ( progressbar.running() )
progressbar.stop();
operationdetail->signal_update( *operationdetail );
operationdetail->stop_progressbar();
}
}

View File

@ -254,11 +254,10 @@ bool xfs::copy( const Partition & src_part,
if ( success )
{
ProgressBar & progressbar = operationdetail.get_progressbar();
sigc::connection c;
if ( src_used > 0LL )
{
progressbar.start( (double)src_used, PROGRESSBAR_TEXT_COPY_BYTES );
operationdetail.run_progressbar( 0.0, (double)src_used, PROGRESSBAR_TEXT_COPY_BYTES );
// Get xfs::copy_progress() called every 500 ms to update progress
c = Glib::signal_timeout().connect(
sigc::bind<OperationDetail*>( sigc::mem_fun( *this, &xfs::copy_progress ),
@ -269,8 +268,7 @@ bool xfs::copy( const Partition & src_part,
" | xfsrestore -J - " + dest_mount_point + "'",
operationdetail, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE );
c.disconnect();
if ( progressbar.running() )
progressbar.stop();
operationdetail.stop_progressbar();
success &= ! execute_command( "umount -v " + dest_part.get_path(), operationdetail,
EXEC_CHECK_STATUS );
@ -298,20 +296,17 @@ bool xfs::check_repair( const Partition & partition, OperationDetail & operation
// recorded source FS used bytes.
bool xfs::copy_progress( OperationDetail * operationdetail )
{
ProgressBar & progressbar = operationdetail->get_progressbar();
Byte_Value fs_size;
Byte_Value fs_free;
Byte_Value dst_used;
if ( Utils::get_mounted_filesystem_usage( dest_mount_point, fs_size, fs_free, error ) != 0 )
{
if ( progressbar.running() )
progressbar.stop();
operationdetail->stop_progressbar();
// Failed to get destination FS used bytes. Remove this timed callback early.
return false;
}
dst_used = fs_size - fs_free;
progressbar.update( (double)dst_used );
operationdetail->signal_update.emit( *operationdetail );
operationdetail->run_progressbar( (double)dst_used, (double)src_used, PROGRESSBAR_TEXT_COPY_BYTES );
return true;
}