Add a single ProgressBar for all OperationDetail objects (#760709)

1) Multiple progress bars

The OperationDetail class contains member fraction which is used to feed
data to the current operation progress bar shown in the Applying pending
operations dialog.  Dialog_Progress::on_signal_update() gets called for
every updated OperationDetail object and depending on whether fraction
is > 0.0 or not, switches between showing a growing or pulsing progress
bar.  This leads to the conclusion that every OperationDetail object
currently being updated is effectively driving the single on screen
progress bar with different data.

The Copy_Blocks code is careful to update text and faction in a single
OperationDetail object and everything is good.  The on screen progress
bar is switched into growing mode and then grows to 100%.

Since external command output is updated in real time [1] there are two
OperationDetail objects, one for stdout and one for stderr, which are
updated whenever data is read from the relevant stream.  Also now that
progress is interpreted from some external command output [2][3][4] a
separate OperationDetail object is getting updated with the progress
fraction.  (Actually the grandparent OperationDetail of the ones
receiving stdout and stderr updates as used by the file system specific
*_progress() methods).  In the normal case of an external command
which is reporting it's progress two OperationDetails are constantly
being updated together, the OperationDetail object tracking stdout and
it's grandparent receiving progress fraction updates.  This causes the
the code in Dialog_Progress::on_signal_update() to constantly switch
between growing and pulsing progress bar mode.  The only reason this
doesn't flash the progress bar is because the stdout OperationDetail
object is updated first and before the 100 ms timeout fires to pulse the
bar, it's grandparent is updated with the new fraction to keep growing
the bar instead.

2) Common code

The Copy_Blocks code currently tracks the progress of blocks copied
against target amount, which it has to do anyway.  That information is
then used to generate the text and fraction to update into the
OperationDetail object and drive the on screen progress bar.  This same
level of tracking is wanted for the XFS and ext2/3/4 file system
specific copy methods.

Conclusion and solution

Having multiple sources of progress bar data is a problem and makes it
clear that there must be only one source of progress data.  Also some
code can be shared for tracking the amount of blocks copied and
generating the display.

Therefore have a single ProgressBar object which is used everywhere.

This commit

It just creates a single ProgressBar object which is available via all
OperationDetail objects and Copy_Blocks is updated accordingly.  Note
that the ProgressBar still contains debugging and that the GUI progress
bar of the current operation is still driven via the fraction member in
any OperationDetail object.

Referenced commits:

[1] 52a2a9b00a
    Reduce threading (#685740)

[2] ae434579e1
    Display progress for e2fsck (#467925)
[3] baea186138
    Display progress for mke2fs (#467925)
[4] 57b028bb8e
    Display progress during resize (#467925)

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-11 13:58:45 +00:00 committed by Curtis Gedak
parent 0ca8ed7369
commit c3669c3a96
4 changed files with 17 additions and 5 deletions

View file

@ -18,7 +18,6 @@
#define GPARTED_COPY_BLOCKS_H
#include "../include/OperationDetail.h"
#include "../include/ProgressBar.h"
#include "../include/Utils.h"
#include <glibmm/ustring.h>
@ -45,7 +44,6 @@ class copy_blocks {
void copy_thread();
bool cancel;
bool cancel_safe;
ProgressBar progressbar;
void set_cancel( bool force );
public:
bool set_progress_info();

View file

@ -18,6 +18,8 @@
#ifndef GPARTED_OPERATIONDETAIL_H
#define GPARTED_OPERATIONDETAIL_H
#include "../include/ProgressBar.h"
#include <glibmm/ustring.h>
#include <glibmm/markup.h>
@ -63,6 +65,7 @@ public:
std::vector<OperationDetail*> & get_childs() ;
const std::vector<OperationDetail*> & get_childs() const ;
OperationDetail & get_last_child() ;
ProgressBar & get_progressbar() const;
double fraction ;
Glib::ustring progress_text ;

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);
progressbar.update( (double)done );
operationdetail.get_progressbar().update( (double)done );
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 ) ) ) );
progressbar.start( (double)length, PROGRESSBAR_TEXT_COPY_BYTES );
operationdetail.get_progressbar().start( (double)length, PROGRESSBAR_TEXT_COPY_BYTES );
done = length % blocksize;
@ -202,7 +202,7 @@ bool copy_blocks::copy()
else
error_message = Glib::strerror( errno );
progressbar.stop();
operationdetail.get_progressbar().stop();
operationdetail.get_last_child().set_status( success ? STATUS_SUCCES : STATUS_ERROR );
return success;
}

View file

@ -16,11 +16,15 @@
#include "../include/OperationDetail.h"
#include "../include/ProgressBar.h"
#include "../include/Utils.h"
namespace GParted
{
// The single progress bar for the current operation
static ProgressBar single_progressbar;
OperationDetail::OperationDetail() : fraction( -1 ), cancelflag( 0 ), status( STATUS_NONE ), time_start( -1 ),
time_elapsed( -1 )
{
@ -156,6 +160,13 @@ OperationDetail & OperationDetail::get_last_child()
return *sub_details[sub_details.size() - 1];
}
ProgressBar & OperationDetail::get_progressbar() const
{
return single_progressbar;
}
// Private methods
void OperationDetail::on_update( const OperationDetail & operationdetail )
{
if ( ! treepath .empty() )