The only use of the reference returned from
OperationDetail::get_progressbar() is to call const methods
ProgressBar::running(), ::get_fraction() and ::get_text(). Therefore
make OperationDetail::get_progressbar() return a const reference.
As described in the previous commit "Clear progress bar text when
starting the bar (#230)" progress bar data is either reporting bytes
copied or fraction complete. The bytes copied case gets in progress
text like this:
544.00 MiB of 1.00 GiB copied (00:00:11 remaining)
But the fraction complete gets no text.
Now also generate time remaining text for progress bars only reporting
fraction complete. As with the bytes copied text only add the time
remaining estimate after 5 seconds have passed. Looks like:
(00:01:59 remaining)
This is most useful for NTFS partition copy and resize operations which
can take a while depending on the amount of data involved.
All uses of get_description() copy construct to a local variable, not
assign to a reference, so this doesn't save anything. It is just being
done to be consistent with making other getters return a constant
reference.
Closes!94 - Make more getter methods use return-by-constant-reference
All libparted messages were reported as informational, even for a step
which failed. Instead identify libparted messages as either
informational or errors depending on whether this step was successful
or not respectively.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
All code implementing a step of an operation follows this pattern:
od.add_child(OperationDetail("Step heading"));
od.get_last_child().add_child(OperationDetail("More details"));
// Do step
success = ...
od.get_last_child().set_status(success ? STATUS_SUCCESS
: STATUS_ERROR);
At this point any libparted messages reported via exceptions need to be
added into the OperationDetail tree. Also adding further children into
the tree after collecting those errors needs to be prohibited (as much
as the previous patch prohibited it).
Add a new method which will replace the final set_status() call above
like this which set the status, captures the errors and flags that
further children shouldn't be added:
...
od.get_last_child().set_success_and_capture_errors(status);
It emits a callback to capture the errors to provide flexibility and so
that the OperationDetail class doesn't have to get into the details of
how GParted_Core saves libparted exception messages.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
Want functionality to prevent further child details being added to an
OperationDetail. This is so that the captured libparted error messages
are always the last child in the list, and more details (at that point
in the tree) can't be added.
For example we want GParted to report like this:
Move /dev/sdb3 to the right and shrink it from 1.14 GiB to...(SUCCESS)
...
* shrink partition from 1.14 GiB to 1.00 GiB (SUCCESS)
* old start: 4464640
old end: 6856703
old size: 2392064 (1.14 GiB)
* new start: 4464640
new end: 6561791
new size: 2097152 (1.00 GiB)
* libparted messages (INFO)
* DEBUG: GParted generated synthetic libparted excepti...
and not like this:
Move /dev/sdb3 to the right and shrink it from 1.14 GiB to...(SUCCESS)
...
* shrink partition from 1.14 GiB to 1.00 GiB (SUCCESS)
* old start: 4464640
old end: 6856703
old size: 2392064 (1.14 GiB)
* libparted messages (INFO)
* DEBUG: GParted generated synthetic libparted excepti...
* new start: 4464640
new end: 6561791
new size: 2097152 (1.00 GiB)
So actually preventing the addition of more child details would stop
users seeing information they should see. So instead just report a bug
message into the operation details. This doesn't stop anything, but the
bug message will be seen and allow us to fix GParted.
So far nothing is enforced. This patch just adds the mechanism to
report a bug when a new child detail is added when prohibited.
Bug 790842 - Report libparted messages into operation details at the
point at which they occur
It made the code look a little messy, is easily resolved in the build
system and made the dependencies more complicated than needed. Each
GParted header was tracked via multiple different names (different
numbers of "../include/" prefixes). For example just looking at how
DialogFeatures.o depends on Utils.h:
$ cd src
$ make DialogFeatures.o
$ egrep ' [^ ]*Utils.h' .deps/DialogFeatures.Po
../include/DialogFeatures.h ../include/../include/Utils.h \
../include/../include/../include/../include/../include/../include/Utils.h \
../include/../include/../include/Utils.h \
After removing "../include/" from the GParted header #includes, just
need to add "-I../include" to the compile command via the AM_CPPFLAGS in
src/Makefile.am. Now the dependencies on GParted header files are
tracked under a single name (with a single "../include/" prefix). Now
DialogFeatures.o only depends on a single name to Utils.h:
$ make DialogFeatures.o
$ egrep ' [^ ]*Utils.h' .deps/DialogFeatures.Po
../include/DialogFeatures.h ../include/Utils.h ../include/i18n.h \
Remove unused members: fraction and progress_text from the
OperationDetail class now that the ProgressBar class has superseded
their use. This also allows removal of timer_global member from the
copy_blocks class. Timer_global was only used to track the elapsed time
copying blocks and allow the remaining time to be estimated and written
into progress_text. The ProgressBar class also does this itself
internally.
Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific
copy methods
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
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
OperationDetail was storing its children in a std::vector. This means they
can be moved around in memory arbitrarily, going through indeterminate
lifetimes. This is generally a bad thing for any non trivial object and
in the case of OperationDetail, it created havoc with the way it maintains
pointers between parent/child objects for signal connections. It will now
keep only pointers to children in a std::vector instead, so their lifetime
can be controlled, fixing various crashes.
Bug 729139 - Refactor OperationDetail to address random behavior
This is part of parent bug:
Bug #721455 - Obsolete info in license text on multiple modules
and GNOME Goal:
https://wiki.gnome.org/Initiatives/GnomeGoals/Proposals
* verify all source files to make sure they have a license and a
copyright, and that both are up-to-date
Bug #721565 - License text contains obsolete FSF postal address
Include guards need to be unique within GParted code and all included
library header files.
http://en.wikipedia.org/wiki/Include_guard#Difficulties
Use this model for all include guards:
#ifndef GPARTED_FILE_NAME_H
#define GPARTED_FILE_NAME_H
...
#endif /* GPARTED_FILE_NAME_H */
Closes Bug #539297 - Make include guards unique
Interested operations can now connect a signal to their OperationDetail
to be notified of a cancelation request. The internal copy/move code
will now cleanly stop on cancelation, allowing the partition to be
rolled back to its previous state. This makes canceling a move
perfectly safe.
After clicking cancel, the button changes to "Force Cancel" and is
disabled for 5 seconds. Operations that are safe to cancel will do so
and those that are not will continue to run. Clicking force cancel
asks operations to cancel, even if doing so is unsafe. For the
internal copy/move algorithm, canceling is always safe because an
error results in a rollback operation. Canceling the rollback is
unsafe. For external commands, filesystem modules may indicate
that the command is safe to cancel or not. Canceled commands will
be terminated with SIGINT.
As a result of the new safe cancel vs force cancel distinction, the
scary warning about cancl causing corruption has been moved to
after clicking the force cancel button.
Part of Bug #601239 - Please allow 'Cancel after current operation'
Restore copyright entries by original author to those of his last
known repository commit titled "released gparted-0.3.4 on
LarryT's request." on Feb 25, 2007.
Add my own copyright entries for files in which I changed source
code. Files in which I only made spelling changes do not have my
copyright entry added.
* include/Utils.h,
src/Utils.cc: added format_time()
* include/OperationDetail.h,
src/OperationDetail.cc: keep track of elapsed time between
STATUS_EXECUTE and STATUS_[ERROR|SUCCES]
* include/Dialog_Progress.h,
src/Dialog_Progress.cc: show elapsed time in the details per (sub)
process
* src/GParted_Core.cc: use Utils::format_time()
* improved errorhandling a bit. At the initialscan we store
errors/warnings now in a list per partition and show the in the
partitioninfo dialog.
While executing an operation we collect all libparted exceptions in
a list and attach this list to the operationdetails when everything
is done.