gparted/src/Dialog_Partition_Resize_Mov...

226 lines
8.2 KiB
C++

/* Copyright (C) 2004 Bart
*
* 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "../include/Dialog_Partition_Resize_Move.h"
namespace GParted
{
Dialog_Partition_Resize_Move::Dialog_Partition_Resize_Move( const FS & fs, long cylinder_size )
{
this ->fs = fs ;
BUF = cylinder_size *2 ;
}
void Dialog_Partition_Resize_Move::Set_Data( const Partition & selected_partition, const std::vector <Partition> & partitions )
{
GRIP = true ; //prevents on spinbutton_changed from getting activated prematurely
this ->selected_partition = selected_partition ;
if ( selected_partition .type == GParted::TYPE_EXTENDED )
{
Set_Resizer( true ) ;
Resize_Move_Extended( partitions ) ;
}
else
{
Set_Resizer( false ) ;
Resize_Move_Normal( partitions ) ;
}
//set partition color
frame_resizer_base ->set_rgb_partition_color( selected_partition .color ) ;
//store the original values
ORIG_BEFORE = spinbutton_before .get_value_as_int( ) ;
ORIG_SIZE = spinbutton_size .get_value_as_int( ) ;
ORIG_AFTER = spinbutton_after .get_value_as_int( ) ;
GRIP = false ;
Set_Confirm_Button( RESIZE_MOVE ) ;
this ->show_all_children( ) ;
}
void Dialog_Partition_Resize_Move::Resize_Move_Normal( const std::vector <Partition> & partitions )
{
if ( ! selected_partition .error .empty( ) )
fs .shrink = GParted::FS::NONE ;
//see if we need a fixed_start
if ( fs .move )
{
this ->set_title( String::ucompose( _("Resize/Move %1"), selected_partition .partition ) ) ;
frame_resizer_base ->set_fixed_start( false ) ;
}
else
{
this ->set_title( String::ucompose( _("Resize %1"), selected_partition .partition) ) ;
this ->fixed_start = true;
frame_resizer_base ->set_fixed_start( true ) ;
spinbutton_before .set_sensitive( false ) ;
}
//calculate total size in MB's of previous, current and next partition
//first find index of partition
unsigned int t;
for ( t = 0 ; t < partitions .size( ) ; t++ )
if ( partitions[ t ] .sector_start == selected_partition .sector_start )
break;
Sector previous, next ;
previous = next = 0 ;
//also check the partitions filesystem ( if this is a 'resize-only' then previous should be 0 )
if ( t >= 1 && partitions[t -1].type == GParted::TYPE_UNALLOCATED && ! this ->fixed_start )
{
previous = partitions[t -1] .sector_end - partitions[t -1] .sector_start ;
START = partitions[t -1] .sector_start ;
}
else
START = selected_partition .sector_start ;
if ( t +1 < partitions .size() && partitions[t +1] .type == GParted::TYPE_UNALLOCATED )
next = partitions[t +1].sector_end - partitions[t +1].sector_start ;
total_length = previous + (selected_partition.sector_end - selected_partition.sector_start) + next;
TOTAL_MB = Utils::Sector_To_MB( total_length ) ;
MB_PER_PIXEL = TOTAL_MB / 500.00 ;
//now calculate proportional length of partition
frame_resizer_base ->set_x_start( Utils::Round( previous / ( total_length / 500.00 ) ) ) ;
frame_resizer_base ->set_x_end( Utils::Round( (selected_partition .sector_end - selected_partition .sector_start) / ( total_length / 500.00 ) ) + frame_resizer_base ->get_x_start( ) ) ;
frame_resizer_base ->set_used( Utils::Round( selected_partition.sectors_used / ( total_length / 500.00 ) ) ) ;
if ( fs .shrink )
{
//since some filesystems have lower limits we need to check for this
if ( selected_partition .Get_Used_MB( ) > fs .MIN )
fs .MIN = selected_partition .Get_Used_MB( ) ;
//if fs. MIN is 0 here (means used == 0 as well) it's safe to have BUF / 2
fs .MIN += fs .MIN ? BUF : BUF/2 ;
//in certain (rare) cases fs .MIN is a bit too high...
if ( fs .MIN > selected_partition .Get_Length_MB( ) )
fs .MIN = selected_partition .Get_Length_MB( ) ;
}
else //only grow..
fs .MIN = selected_partition .Get_Length_MB( ) ;
fs .MAX = ( ! fs .MAX || fs .MAX > TOTAL_MB ) ? TOTAL_MB : fs .MAX -= BUF/2 ;
//set values of spinbutton_before
if ( ! fixed_start )
{
spinbutton_before .set_range( 0, TOTAL_MB - fs .MIN ) ;
spinbutton_before .set_value( Utils::Sector_To_MB( previous ) ) ;
}
//set values of spinbutton_size
spinbutton_size .set_range( fs .MIN, fs .MAX ) ;
spinbutton_size .set_value( selected_partition .Get_Length_MB( ) ) ;
//set values of spinbutton_after
spinbutton_after .set_range( 0, TOTAL_MB - fs .MIN ) ;
spinbutton_after .set_value( Utils::Sector_To_MB( next ) ) ;
frame_resizer_base ->set_size_limits( Utils::Round( fs .MIN / MB_PER_PIXEL ), Utils::Round( fs .MAX / MB_PER_PIXEL ) +1 ) ;
//set contents of label_minmax
Set_MinMax_Text( fs .MIN, fs .MAX ) ;
}
void Dialog_Partition_Resize_Move::Resize_Move_Extended( const std::vector <Partition> & partitions )
{
//calculate total size in MB's of previous, current and next partition
//first find index of partition
unsigned int t = 0;
while ( t < partitions .size( ) && partitions[ t ] .type != GParted::TYPE_EXTENDED ) t++ ;
Sector previous, next ;
previous = next = 0 ;
//calculate length and start of previous
if ( t > 0 && partitions[t -1].type == GParted::TYPE_UNALLOCATED )
{
previous = partitions[t -1].sector_end - partitions[t -1].sector_start ;
START = partitions[t -1].sector_start ;
}
else
START = selected_partition .sector_start ;
//calculate length of next
if ( t +1 < partitions .size( ) && partitions[ t +1 ] .type == GParted::TYPE_UNALLOCATED )
next = partitions[ t +1 ] .sector_end - partitions[ t +1 ] .sector_start ;
//now we have enough data to calculate some important values..
total_length = previous + (selected_partition.sector_end - selected_partition.sector_start) + next;
TOTAL_MB = Utils::Sector_To_MB( total_length ) ;
MB_PER_PIXEL = TOTAL_MB / 500.00 ;
//calculate proportional length of partition ( in pixels )
frame_resizer_base ->set_x_start( Utils::Round( previous / ( total_length / 500.00 ) ) ) ;
frame_resizer_base ->set_x_end( Utils::Round( (selected_partition .sector_end - selected_partition .sector_start) / ( total_length / 500.00 ) ) + frame_resizer_base ->get_x_start( ) ) ;
//used is a bit different here... we consider start of first logical to end last logical as used space
Sector first =0, used =0 ;
for ( unsigned int i = 0 ; i < partitions[ t ] .logicals .size( ) ; i++ )
{
if ( partitions[ t ] .logicals[ i ] .type == GParted::TYPE_LOGICAL )
{
if ( first == 0 )
first = partitions[ t ] .logicals[ i ] .sector_start ;
used = partitions[ t ] .logicals[ i ] .sector_end - first;
}
}
frame_resizer_base ->set_used_start( Utils::Round( (first - START) / ( total_length / 500.00 ) ) ) ;
frame_resizer_base ->set_used( Utils::Round( used / ( total_length / 500.00 ) ) ) ;
//set values of spinbutton_before (we assume there is no fixed start.)
if ( first == 0 ) //no logicals
spinbutton_before .set_range( 0, TOTAL_MB - BUF/2 ) ;
else
spinbutton_before .set_range( 0, Utils::Sector_To_MB (first - START) ) ;
spinbutton_before .set_value( Utils::Sector_To_MB ( previous ) ) ;
//set values of spinbutton_size
if ( first == 0 ) //no logicals
spinbutton_size .set_range( BUF/2, TOTAL_MB ) ;
else
spinbutton_size .set_range( Utils::Sector_To_MB( used ), TOTAL_MB ) ;
spinbutton_size .set_value( selected_partition .Get_Length_MB( ) ) ;
//set values of spinbutton_after
if ( first == 0 ) //no logicals
spinbutton_after .set_range( 0, TOTAL_MB - BUF/2 ) ;
else
spinbutton_after .set_range( 0, Utils::Sector_To_MB( total_length + START - first - used) ) ;
spinbutton_after .set_value( Utils::Sector_To_MB( next ) ) ;
//set contents of label_minmax
Set_MinMax_Text( first == 0 ? BUF/2 : Utils::Sector_To_MB( used ), Utils::Sector_To_MB( total_length ) ) ;
}
} //GParted