source: calamares/trunk/fuentes/src/modules/partition/gui/ReplaceWidget.cpp

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

sync with github

File size: 14.3 KB
Line 
1/* === This file is part of Calamares - <https://github.com/calamares> ===
2 *
3 *   Copyright 2014-2015, Teo Mrnjavac <teo@kde.org>
4 *   Copyright 2014, Aurélien Gâteau <agateau@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 "ReplaceWidget.h"
21#include "ui_ReplaceWidget.h"
22
23#include "core/DeviceModel.h"
24#include "core/PartitionCoreModule.h"
25#include "core/PartitionActions.h"
26#include "core/PartitionInfo.h"
27
28#include "Branding.h"
29#include "GlobalStorage.h"
30#include "JobQueue.h"
31#include "utils/CalamaresUtilsGui.h"
32#include "utils/Retranslator.h"
33
34#include <kpmcore/core/partition.h>
35#include <kpmcore/fs/filesystem.h>
36
37#include <QComboBox>
38
39ReplaceWidget::ReplaceWidget( PartitionCoreModule* core,
40                              QComboBox* devicesComboBox,
41                              QWidget* parent )
42    : QWidget( parent )
43    , m_ui( new Ui_ReplaceWidget )
44    , m_core( core )
45    , m_isEfi( false )
46{
47    m_ui->setupUi( this );
48
49    m_ui->bootComboBox->hide();
50    m_ui->bootComboBox->clear();
51    m_ui->bootStatusLabel->hide();
52    m_ui->bootStatusLabel->clear();
53
54    updateFromCurrentDevice( devicesComboBox );
55    connect( devicesComboBox, &QComboBox::currentTextChanged,
56             this, [=]( const QString& /* text */ )
57    {
58        updateFromCurrentDevice( devicesComboBox );
59    } );
60
61    CALAMARES_RETRANSLATE(
62        onPartitionSelected();
63    )
64}
65
66
67ReplaceWidget::~ReplaceWidget()
68{}
69
70
71bool
72ReplaceWidget::isNextEnabled() const
73{
74    return m_nextEnabled;
75}
76
77
78void
79ReplaceWidget::reset()
80{
81    //moo;
82}
83
84
85void
86ReplaceWidget::applyChanges()
87{
88    PartitionModel* model = qobject_cast< PartitionModel* >( m_ui->partitionTreeView->model() );
89    if ( model )
90    {
91        Partition* partition = model->partitionForIndex( m_ui->partitionTreeView->currentIndex() );
92        if ( partition )
93        {
94            Device* dev = model->device();
95
96            PartitionActions::doReplacePartition( m_core, dev, partition );
97
98            if ( m_isEfi )
99            {
100                QList< Partition* > efiSystemPartitions = m_core->efiSystemPartitions();
101                if ( efiSystemPartitions.count() == 1 )
102                {
103                    PartitionInfo::setMountPoint(
104                            efiSystemPartitions.first(),
105                            Calamares::JobQueue::instance()->
106                                globalStorage()->
107                                    value( "efiSystemPartition" ).toString() );
108                }
109                else if ( efiSystemPartitions.count() > 1 )
110                {
111                    PartitionInfo::setMountPoint(
112                            efiSystemPartitions.at( m_ui->bootComboBox->currentIndex() ),
113                            Calamares::JobQueue::instance()->
114                                globalStorage()->
115                                    value( "efiSystemPartition" ).toString() );
116                }
117            }
118
119            m_core->dumpQueue();
120        }
121    }
122}
123
124
125void
126ReplaceWidget::onPartitionSelected()
127{
128    if ( Calamares::JobQueue::instance()->globalStorage()->value( "firmwareType" ) == "efi" )
129        m_isEfi = true;
130
131    if ( m_ui->partitionTreeView->currentIndex() == QModelIndex() )
132    {
133        updateStatus( CalamaresUtils::PartitionPartition,
134                      tr( "Select where to install %1.<br/>"
135                          "<font color=\"red\">Warning: </font>this will delete all files "
136                          "on the selected partition." )
137                          .arg( *Calamares::Branding::VersionedName ) );
138        setNextEnabled( false );
139        return;
140    }
141
142    bool ok = false;
143    double requiredSpaceB = Calamares::JobQueue::instance()
144                            ->globalStorage()
145                            ->value( "requiredStorageGB" )
146                            .toDouble( &ok ) * 1024 * 1024 * 1024;
147
148    PartitionModel* model = qobject_cast< PartitionModel* >( m_ui->partitionTreeView->model() );
149    if ( model && ok )
150    {
151        const QStringList osproberLines = Calamares::JobQueue::instance()
152                                    ->globalStorage()
153                                    ->value( "osproberLines" ).toStringList();
154
155        Partition* partition = model->partitionForIndex( m_ui->partitionTreeView->currentIndex() );
156        if ( !partition ||
157             partition->state() != Partition::StateNone )
158        {
159            updateStatus( CalamaresUtils::Fail,
160                          tr( "The selected item does not appear to be a valid partition." ) );
161            setNextEnabled( false );
162            return;
163        }
164
165        if ( partition->roles().has( PartitionRole::Unallocated ) )
166        {
167            updateStatus( CalamaresUtils::Fail,
168                          tr( "%1 cannot be installed on empty space. Please select an "
169                              "existing partition." )
170                          .arg( *Calamares::Branding::VersionedName ) );
171            setNextEnabled( false );
172            return;
173        }
174
175        if ( partition->roles().has( PartitionRole::Extended ) )
176        {
177            updateStatus( CalamaresUtils::Fail,
178                          tr( "%1 cannot be installed on an extended partition. Please select an "
179                              "existing primary or logical partition." )
180                          .arg( *Calamares::Branding::VersionedName ) );
181            setNextEnabled( false );
182            return;
183        }
184
185        if ( partition->partitionPath().isEmpty() )
186        {
187            updateStatus( CalamaresUtils::Fail,
188                          tr( "%1 cannot be installed on this partition." )
189                          .arg( *Calamares::Branding::VersionedName ) );
190            setNextEnabled( false );
191            return;
192        }
193
194        QString prettyName = tr( "Data partition (%1)" )
195                             .arg( partition->fileSystem().name() );
196        for ( const QString& line : osproberLines )
197        {
198            QStringList lineColumns = line.split( ':' );
199
200            QString path = lineColumns.value( 0 ).simplified();
201            if ( path == partition->partitionPath() )
202            {
203                QString osName;
204                if ( !lineColumns.value( 1 ).simplified().isEmpty() )
205                    osName = lineColumns.value( 1 ).simplified();
206                else if ( !lineColumns.value( 2 ).simplified().isEmpty() )
207                    osName = lineColumns.value( 2 ).simplified();
208
209                if ( osName.isEmpty() )
210                {
211                    prettyName = tr( "Unknown system partition (%1)" )
212                                 .arg( partition->fileSystem().name() );
213                }
214                else
215                {
216                    prettyName = tr ( "%1 system partition (%2)" )
217                                 .arg( osName.replace( 0, 1, osName.at( 0 ).toUpper() ) )
218                                 .arg( partition->fileSystem().name() );
219                }
220                break;
221            }
222        }
223
224        if ( partition->capacity() < requiredSpaceB )
225        {
226            updateStatus( CalamaresUtils::Fail,
227                          tr( "<strong>%4</strong><br/><br/>"
228                              "The partition %1 is too small for %2. Please select a partition "
229                              "with capacity at least %3 GiB." )
230                          .arg( partition->partitionPath() )
231                          .arg( *Calamares::Branding::VersionedName )
232                          .arg( requiredSpaceB / ( 1024. * 1024. * 1024. ),
233                                0, 'f', 1 )
234                          .arg( prettyName ) );
235            setNextEnabled( false );
236            return;
237        }
238
239        m_ui->bootComboBox->hide();
240        m_ui->bootComboBox->clear();
241        m_ui->bootStatusLabel->hide();
242        m_ui->bootStatusLabel->clear();
243
244        if ( m_isEfi )
245        {
246            QList< Partition* > efiSystemPartitions = m_core->efiSystemPartitions();
247            if ( efiSystemPartitions.count() == 0 )
248            {
249                updateStatus( CalamaresUtils::Fail,
250                              tr( "<strong>%2</strong><br/><br/>"
251                                  "An EFI system partition cannot be found anywhere "
252                                  "on this system. Please go back and use manual "
253                                  "partitioning to set up %1." )
254                              .arg( *Calamares::Branding::ShortProductName )
255                              .arg( prettyName ) );
256                setNextEnabled( false );
257            }
258            else if ( efiSystemPartitions.count() == 1 )
259            {
260                updateStatus( CalamaresUtils::PartitionPartition,
261                              tr( "<strong>%3</strong><br/><br/>"
262                                  "%1 will be installed on %2.<br/>"
263                                  "<font color=\"red\">Warning: </font>all data on partition "
264                                  "%2 will be lost.")
265                                .arg( *Calamares::Branding::VersionedName )
266                                .arg( partition->partitionPath() )
267                                .arg( prettyName ) );
268                m_ui->bootStatusLabel->show();
269                m_ui->bootStatusLabel->setText(
270                    tr( "The EFI system partition at %1 will be used for starting %2." )
271                        .arg( efiSystemPartitions.first()->partitionPath() )
272                        .arg( *Calamares::Branding::ShortProductName ) );
273                setNextEnabled( true );
274            }
275            else
276            {
277                updateStatus( CalamaresUtils::PartitionPartition,
278                              tr( "<strong>%3</strong><br/><br/>"
279                                  "%1 will be installed on %2.<br/>"
280                                  "<font color=\"red\">Warning: </font>all data on partition "
281                                  "%2 will be lost.")
282                                .arg( *Calamares::Branding::VersionedName )
283                                .arg( partition->partitionPath() )
284                                .arg( prettyName ) );
285                m_ui->bootStatusLabel->show();
286                m_ui->bootStatusLabel->setText( tr( "EFI system partition:" ) );
287                m_ui->bootComboBox->show();
288                for ( int i = 0; i < efiSystemPartitions.count(); ++i )
289                {
290                    Partition* efiPartition = efiSystemPartitions.at( i );
291                    m_ui->bootComboBox->addItem( efiPartition->partitionPath(), i );
292                    if ( efiPartition->devicePath() == partition->devicePath() &&
293                         efiPartition->number() == 1 )
294                        m_ui->bootComboBox->setCurrentIndex( i );
295                }
296                setNextEnabled( true );
297            }
298        }
299        else
300        {
301            updateStatus( CalamaresUtils::PartitionPartition,
302                          tr( "<strong>%3</strong><br/><br/>"
303                              "%1 will be installed on %2.<br/>"
304                              "<font color=\"red\">Warning: </font>all data on partition "
305                              "%2 will be lost.")
306                            .arg( *Calamares::Branding::VersionedName )
307                            .arg( partition->partitionPath() )
308                            .arg( prettyName ) );
309            setNextEnabled( true );
310        }
311    }
312}
313
314
315void
316ReplaceWidget::setNextEnabled( bool enabled )
317{
318    if ( enabled == m_nextEnabled )
319        return;
320
321    m_nextEnabled = enabled;
322    emit nextStatusChanged( enabled );
323}
324
325
326void
327ReplaceWidget::updateStatus( CalamaresUtils::ImageType imageType, const QString& text )
328{
329    int iconSize = CalamaresUtils::defaultFontHeight() * 6;
330    m_ui->selectedIconLabel->setPixmap( CalamaresUtils::defaultPixmap( imageType,
331                                                                       CalamaresUtils::Original,
332                                                                       QSize( iconSize, iconSize ) ) );
333    m_ui->selectedIconLabel->setFixedHeight( iconSize );
334    m_ui->selectedStatusLabel->setText( text );
335}
336
337
338
339void
340ReplaceWidget::updateFromCurrentDevice( QComboBox* devicesComboBox )
341{
342    QModelIndex index = m_core->deviceModel()->index( devicesComboBox->currentIndex(), 0 );
343    if ( !index.isValid() )
344        return;
345
346    Device* device = m_core->deviceModel()->deviceForIndex( index );
347
348    QAbstractItemModel* oldModel = m_ui->partitionTreeView->model();
349    if ( oldModel )
350        disconnect( oldModel, nullptr, this, nullptr );
351
352    PartitionModel* model = m_core->partitionModelForDevice( device );
353    m_ui->partitionTreeView->setModel( model );
354    m_ui->partitionTreeView->expandAll();
355
356    // Must be done here because we need to have a model set to define
357    // individual column resize mode
358    QHeaderView* header = m_ui->partitionTreeView->header();
359    header->setSectionResizeMode( QHeaderView::ResizeToContents );
360    header->setSectionResizeMode( 0, QHeaderView::Stretch );
361
362    //updateButtons();
363    // Establish connection here because selection model is destroyed when
364    // model changes
365    connect( m_ui->partitionTreeView->selectionModel(), &QItemSelectionModel::currentRowChanged,
366             this, &ReplaceWidget::onPartitionViewActivated );
367
368    connect( model, &QAbstractItemModel::modelReset, this, &ReplaceWidget::onPartitionModelReset );
369}
370
371
372void
373ReplaceWidget::onPartitionViewActivated()
374{
375    QModelIndex index = m_ui->partitionTreeView->currentIndex();
376    if ( !index.isValid() )
377        return;
378
379    const PartitionModel* model = static_cast< const PartitionModel* >( index.model() );
380    Q_ASSERT( model );
381    Partition* partition = model->partitionForIndex( index );
382    Q_ASSERT( partition );
383
384    onPartitionSelected();
385}
386
387
388void
389ReplaceWidget::onPartitionModelReset()
390{
391    m_ui->partitionTreeView->expandAll();
392    onPartitionSelected();
393}
Note: See TracBrowser for help on using the repository browser.