/* === This file is part of Calamares - === * * Copyright 2014, Teo Mrnjavac * * Calamares 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 3 of the License, or * (at your option) any later version. * * Calamares 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 Calamares. If not, see . */ #include "EraseDiskPage.h" #include "core/DeviceModel.h" #include "core/PartitionCoreModule.h" #include "core/partition.h" #include "core/PMUtils.h" #include "core/PartitionInfo.h" #include "core/device.h" #include "fs/filesystem.h" #include "gui/PartitionPreview.h" #include "utils/CalamaresUtilsGui.h" #include "utils/Logger.h" #include "utils/Retranslator.h" #include #include #include #include #include EraseDiskPage::EraseDiskPage( QWidget* parent ) : QWidget( parent ) , m_nextEnabled( false ) , m_core( nullptr ) { QVBoxLayout* mainLayout = new QVBoxLayout; setLayout( mainLayout ); QLabel* driveLabel = new QLabel( this ); mainLayout->addWidget( driveLabel ); CALAMARES_RETRANSLATE( driveLabel->setText( tr( "Select drive:" ) ); ) m_drivesView = new QListView; mainLayout->addWidget( m_drivesView ); m_drivesView->setViewMode( QListView::IconMode ); m_drivesView->setWrapping( false ); m_drivesView->setFlow( QListView::LeftToRight ); m_drivesView->setSelectionRectVisible( false ); m_drivesView->setWordWrap( true ); m_drivesView->setUniformItemSizes( true ); m_drivesView->setSelectionMode( QAbstractItemView::SingleSelection ); m_drivesView->setIconSize( CalamaresUtils::defaultIconSize() * 3 ); m_drivesView->setGridSize( QSize( CalamaresUtils::defaultFontHeight() * 8, m_drivesView->iconSize().height() + CalamaresUtils::defaultFontHeight() * 4 ) ); m_drivesView->setMinimumHeight( m_drivesView->gridSize().height() + CalamaresUtils::defaultFontHeight() / 2 ); m_drivesView->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); m_previewFrame = new QWidget; m_previewFrame->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding ); mainLayout->addWidget( m_previewFrame ); setNextEnabled( false ); } void EraseDiskPage::init( PartitionCoreModule* core ) { if ( m_core ) //this should probably never happen { m_core->revert(); return; } m_core = core; m_drivesView->setModel( core->deviceModel() ); connect( m_drivesView->selectionModel(), &QItemSelectionModel::currentChanged, this, [ this ]( const QModelIndex& index, const QModelIndex& oldIndex ) { setNextEnabled( m_drivesView->selectionModel()->hasSelection() ); if ( m_core->isDirty() ) m_core->clearJobs(); Device* dev = m_core->deviceModel()->deviceForIndex( index ); if ( dev ) doAutopartition( dev ); } ); } bool EraseDiskPage::isNextEnabled() const { return m_nextEnabled; } void EraseDiskPage::setNextEnabled( bool enabled ) { if ( enabled == m_nextEnabled ) return; m_nextEnabled = enabled; emit nextStatusChanged( enabled ); } void EraseDiskPage::doAutopartition( Device* dev ) { bool isEfi = false; if ( QDir( "/sys/firmware/efi/efivars" ).exists() ) isEfi = true; #define MiB * 1024 * 1024 // Partition sizes are expressed in MiB, should be multiples of // the logical sector size (usually 512B). int uefisys_part_size = 0; int empty_space_size = 0; if ( isEfi ) { uefisys_part_size = 100; empty_space_size = 2; } else { // we start with a 1MiB offset before the first partition empty_space_size = 1; } qint64 first_free_sector = empty_space_size MiB / dev->logicalSectorSize() + 1; if ( isEfi ) { qint64 lastSector = first_free_sector + ( uefisys_part_size MiB / dev->logicalSectorSize() ); m_core->createPartitionTable( dev, PartitionTable::gpt ); Partition* efiPartition = PMUtils::createNewPartition( dev->partitionTable(), *dev, PartitionRole( PartitionRole::Primary ), FileSystem::Fat32, first_free_sector, lastSector ); PartitionInfo::setMountPoint( efiPartition, "/boot" ); PartitionInfo::setFormat( efiPartition, true ); m_core->createPartition( dev, efiPartition ); first_free_sector = lastSector + 1; } else { m_core->createPartitionTable( dev, PartitionTable::msdos ); } Partition* rootPartition = PMUtils::createNewPartition( dev->partitionTable(), *dev, PartitionRole( PartitionRole::Primary ), FileSystem::Ext4, first_free_sector, dev->totalSectors() - 1 //last sector ); PartitionInfo::setMountPoint( rootPartition, "/" ); PartitionInfo::setFormat( rootPartition, true ); m_core->createPartition( dev, rootPartition ); { qDeleteAll( m_previewFrame->children() ); m_previewFrame->layout()->deleteLater(); QFormLayout* layout = new QFormLayout; m_previewFrame->setLayout( layout ); layout->setMargin( 0 ); QList< PartitionCoreModule::SummaryInfo > list = m_core->createSummaryInfo(); for ( const auto& info : list ) { PartitionPreview* preview; layout->addRow( new QLabel( info.deviceName ) ); preview = new PartitionPreview; preview->setModel( info.partitionModelBefore ); info.partitionModelBefore->setParent( m_previewFrame ); layout->addRow( tr( "Before:" ), preview ); preview = new PartitionPreview; preview->setModel( info.partitionModelAfter ); info.partitionModelAfter->setParent( m_previewFrame ); layout->addRow( tr( "After:" ), preview ); } } m_core->dumpQueue(); }