source: calamares/trunk/fuentes/src/modules/partition/gui/PartitionSizeController.cpp @ 7538

Last change on this file since 7538 was 7538, checked in by kbut, 13 months ago

sync with github

File size: 6.6 KB
Line 
1/* === This file is part of Calamares - <https://github.com/calamares> ===
2 *
3 *   Copyright 2014, Aurélien Gâteau <agateau@kde.org>
4 *   Copyright 2016, Teo Mrnjavac <teo@kde.org>
5 *
6 *   Calamares is free software: you can redistribute it and/or modify
7 *   it under the terms of the GNU General Public License as published by
8 *   the Free Software Foundation, either version 3 of the License, or
9 *   (at your option) any later version.
10 *
11 *   Calamares is distributed in the hope that it will be useful,
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 *   GNU General Public License for more details.
15 *
16 *   You should have received a copy of the GNU General Public License
17 *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "gui/PartitionSizeController.h"
21
22#include "core/ColorUtils.h"
23#include "core/KPMHelpers.h"
24
25#include "utils/Units.h"
26
27// Qt
28#include <QSpinBox>
29
30// KPMcore
31#include <kpmcore/core/device.h>
32#include <kpmcore/gui/partresizerwidget.h>
33
34// stdc++
35#include <limits>
36
37PartitionSizeController::PartitionSizeController( QObject* parent )
38    : QObject( parent )
39{}
40
41void
42PartitionSizeController::init( Device* device, Partition* partition, const QColor& color )
43{
44    m_device = device;
45    m_originalPartition = partition;
46    // PartResizerWidget stores its changes directly in the partition it is
47    // initialized with. We don't want the changes to be committed that way,
48    // because it means we would have to revert them if the user cancel the
49    // dialog the widget is in. Therefore we init PartResizerWidget with a clone
50    // of the original partition.
51    m_partition.reset( KPMHelpers::clonePartition( m_device, partition ) );
52    m_partitionColor = color;
53}
54
55void
56PartitionSizeController::setPartResizerWidget( PartResizerWidget* widget, bool format )
57{
58    Q_ASSERT( m_device );
59
60    if ( m_partResizerWidget )
61        disconnect( m_partResizerWidget, nullptr, this, nullptr );
62
63    m_dirty = false;
64    m_currentSpinBoxValue = -1;
65
66    // Update partition filesystem. This must be done *before* the call to
67    // PartResizerWidget::init() otherwise it will be ignored by the widget.
68    // This is why this method accept a `format` boolean.
69    qint64 used = format ? 0 : m_originalPartition->fileSystem().sectorsUsed();
70    m_partition->fileSystem().setSectorsUsed( used );
71
72    // Init PartResizerWidget
73    m_partResizerWidget = widget;
74    PartitionTable* table = m_device->partitionTable();
75    qint64 minFirstSector = m_originalPartition->firstSector() - table->freeSectorsBefore( *m_originalPartition );
76    qint64 maxLastSector = m_originalPartition->lastSector() + table->freeSectorsAfter( *m_originalPartition );
77    m_partResizerWidget->init( *m_device, *m_partition.data(), minFirstSector, maxLastSector );
78
79    // FIXME: Should be set by PartResizerWidget itself
80    m_partResizerWidget->setFixedHeight( PartResizerWidget::handleHeight() );
81
82    QPalette pal = widget->palette();
83    pal.setColor( QPalette::Base, ColorUtils::freeSpaceColor() );
84    pal.setColor( QPalette::Button, m_partitionColor );
85    m_partResizerWidget->setPalette( pal );
86    connectWidgets();
87
88    if ( !format )
89    {
90        // If we are not formatting, update the widget to make sure the space
91        // between the first and last sectors is big enough to fit the existing
92        // content.
93        m_updating = true;
94
95        qint64 firstSector = m_partition->firstSector();
96        qint64 lastSector = m_partition->lastSector();
97
98        // This first time we call doAAUPRW with real first/last sector,
99        // all further calls will come from updatePartResizerWidget, and
100        // will therefore use values calculated from the SpinBox.
101        doAlignAndUpdatePartResizerWidget( firstSector, lastSector );
102
103        m_updating = false;
104    }
105}
106
107void
108PartitionSizeController::setSpinBox( QSpinBox* spinBox )
109{
110    if ( m_spinBox )
111        disconnect( m_spinBox, nullptr, this, nullptr );
112    m_spinBox = spinBox;
113    m_spinBox->setMaximum( std::numeric_limits< int >::max() );
114    connectWidgets();
115}
116
117void
118PartitionSizeController::connectWidgets()
119{
120    if ( !m_spinBox || !m_partResizerWidget )
121        return;
122
123    connect( m_spinBox, SIGNAL( editingFinished() ), SLOT( updatePartResizerWidget() ) );
124    connect( m_partResizerWidget, SIGNAL( firstSectorChanged( qint64 ) ), SLOT( updateSpinBox() ) );
125    connect( m_partResizerWidget, SIGNAL( lastSectorChanged( qint64 ) ), SLOT( updateSpinBox() ) );
126
127    // Init m_spinBox from m_partResizerWidget
128    updateSpinBox();
129}
130
131void
132PartitionSizeController::updatePartResizerWidget()
133{
134    if ( m_updating )
135        return;
136    if ( m_spinBox->value() == m_currentSpinBoxValue )
137        return;
138
139    m_updating = true;
140    qint64 sectorSize = qint64( m_spinBox->value() ) * 1024 * 1024 / m_device->logicalSize();
141
142    qint64 firstSector = m_partition->firstSector();
143    qint64 lastSector = firstSector + sectorSize - 1;
144
145    doAlignAndUpdatePartResizerWidget( firstSector, lastSector );
146
147    m_updating = false;
148}
149
150void
151PartitionSizeController::doAlignAndUpdatePartResizerWidget( qint64 firstSector,
152                                                            qint64 lastSector )
153{
154    if ( lastSector > m_partResizerWidget->maximumLastSector() )
155    {
156        qint64 delta = lastSector - m_partResizerWidget->maximumLastSector();
157        firstSector -= delta;
158        lastSector -= delta;
159    }
160    if ( lastSector != m_partition->lastSector() )
161    {
162        m_partResizerWidget->updateLastSector( lastSector );
163        m_dirty = true;
164    }
165    if ( firstSector != m_partition->firstSector() )
166    {
167        m_partResizerWidget->updateFirstSector( firstSector );
168        m_dirty = true;
169    }
170
171    // Update spinbox value in case it was an impossible value
172    doUpdateSpinBox();
173}
174
175void
176PartitionSizeController::updateSpinBox()
177{
178    if ( m_updating )
179        return;
180    m_updating = true;
181    doUpdateSpinBox();
182    m_updating = false;
183}
184
185void
186PartitionSizeController::doUpdateSpinBox()
187{
188    if ( !m_spinBox )
189        return;
190    int mbSize = CalamaresUtils::BytesToMiB( m_partition->length() * m_device->logicalSize() );
191    m_spinBox->setValue( mbSize );
192    if ( m_currentSpinBoxValue != -1 &&    //if it's not the first time we're setting it
193         m_currentSpinBoxValue != mbSize ) //and the operation changes the SB value
194        m_dirty = true;
195    m_currentSpinBoxValue = mbSize;
196}
197
198qint64
199PartitionSizeController::firstSector() const
200{
201    return m_partition->firstSector();
202}
203
204qint64
205PartitionSizeController::lastSector() const
206{
207    return m_partition->lastSector();
208}
209
210bool
211PartitionSizeController::isDirty() const
212{
213    return m_dirty;
214}
Note: See TracBrowser for help on using the repository browser.