gparted/include/OperationDetail.h

103 lines
3.1 KiB
C
Raw Permalink Normal View History

/* Copyright (C) 2004 Bart 'plors' Hakvoort
* Copyright (C) 2008 Curtis Gedak
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GPARTED_OPERATIONDETAIL_H
#define GPARTED_OPERATIONDETAIL_H
#include "ProgressBar.h"
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] 52a2a9b00a32996921ace055e71d0e09fb33c5fe Reduce threading (#685740) [2] ae434579e160ca2c306921b12d4211bf9abacef7 Display progress for e2fsck (#467925) [3] baea186138cc08cac1f13f28300ca0f4b09ae16d Display progress for mke2fs (#467925) [4] 57b028bb8e7c9fa5e750624f405cc268dfa3b4af Display progress during resize (#467925) Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific copy methods
2016-01-11 06:58:45 -07:00
#include <glibmm/ustring.h>
#include <glibmm/markup.h>
#include <vector>
#include <ctime>
namespace GParted
{
enum OperationDetailStatus {
STATUS_NONE = 0,
STATUS_EXECUTE = 1,
STATUS_SUCCESS = 2,
STATUS_ERROR = 3,
STATUS_INFO = 4,
STATUS_WARNING = 5
};
enum Font {
FONT_NORMAL = 0,
FONT_BOLD = 1,
FONT_ITALIC = 2,
FONT_BOLD_ITALIC = 3
} ;
class OperationDetail
{
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
2016-01-17 05:38:58 -07:00
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();
OperationDetail( const Glib::ustring & description,
OperationDetailStatus status = STATUS_EXECUTE,
Font font = FONT_NORMAL ) ;
void set_description( const Glib::ustring & description, Font font = FONT_NORMAL ) ;
const Glib::ustring& get_description() const;
void set_status( OperationDetailStatus status ) ;
void set_success_and_capture_errors( bool success );
OperationDetailStatus get_status() const ;
void set_treepath( const Glib::ustring & treepath ) ;
const Glib::ustring& get_treepath() const;
Glib::ustring get_elapsed_time() const ;
void add_child( const OperationDetail & operationdetail ) ;
std::vector<OperationDetail*> & get_childs() ;
const std::vector<OperationDetail*> & get_childs() const ;
OperationDetail & get_last_child() ;
void run_progressbar(double progress, double target, ProgressBar_Text text_mode = PROGRESSBAR_TEXT_TIME_REMAINING);
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
2016-01-17 05:38:58 -07:00
void stop_progressbar();
sigc::signal< void, const OperationDetail & > signal_update ;
sigc::signal< void, bool > signal_cancel;
sigc::signal< void, OperationDetail &, bool > signal_capture_errors;
char cancelflag;
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
2016-01-17 05:38:58 -07:00
private:
Add mechanism to stop adding more child OperationDetails (#790842) 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
2017-11-25 03:37:52 -07:00
void add_child_implement( const OperationDetail & operationdetail );
void on_update( const OperationDetail & operationdetail ) ;
void cancel( bool force );
const ProgressBar& get_progressbar() const;
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
2016-01-17 05:38:58 -07:00
Glib::ustring description ;
OperationDetailStatus status ;
Glib::ustring treepath ;
std::vector<OperationDetail*> sub_details;
std::time_t time_start, time_elapsed ;
Add mechanism to stop adding more child OperationDetails (#790842) 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
2017-11-25 03:37:52 -07:00
bool no_more_children; // Disallow adding more children to ensure captured errors
// remain the last child of this operation detail.
sigc::connection cancelconnection;
};
} //GParted
#endif /* GPARTED_OPERATIONDETAIL_H */