source: src-qt4/pc-installgui/wizardDisk.cpp

Last change on this file was 6ea50a2, checked in by Kris Moore <kris@…>, 13 days ago

When specifying zpool names, make sure they start with a-z, not
with a number

  • Property mode set to 100644
File size: 38.9 KB
Line 
1/****************************************************************************
2** ui.h extension file, included from the uic-generated form implementation.
3**
4** If you want to add, delete, or rename functions or slots, use
5** Qt Designer to update this file, preserving your code.
6**
7** You should not define a constructor or destructor in this file.
8** Instead, write your code in functions called init() and destroy().
9** These will automatically be called by the form's constructor and
10** destructor.
11*****************************************************************************/
12#include <QDebug>
13#include <QInputDialog>
14#include <QMessageBox>
15#include "wizardDisk.h"
16#include "ui_wizardDisk.h"
17
18void wizardDisk::programInit()
19{
20  prevID = 0;
21  restoreMode=false;
22
23  populateDiskInfo();
24
25  //connect(pushClose, SIGNAL(clicked()), this, SLOT(slotClose()));
26  connect(checkGPT, SIGNAL(clicked()), this, SLOT(slotGPTClicked()));
27  connect(pushSwapSize, SIGNAL(clicked()), this, SLOT(slotSwapSize()));
28  connect(pushRemoveMount, SIGNAL(clicked()), this, SLOT(slotRemoveFS()));
29  connect(pushAddMount, SIGNAL(clicked()), this, SLOT(slotAddFS()));
30  connect(this,SIGNAL(currentIdChanged(int)),this,SLOT(slotCheckComplete()));
31  connect(lineZpoolName,SIGNAL(textChanged ( const QString & )),this,SLOT(slotCheckComplete()));
32  connect(groupZFSPool,SIGNAL( clicked(bool)),this,SLOT(slotCheckComplete()));
33  connect(comboDisk,SIGNAL(currentIndexChanged(int)),this,SLOT(slotCheckComplete()));
34  connect(comboDisk,SIGNAL(currentIndexChanged(int)),this,SLOT(slotChangedDisk()));
35  connect(comboPartition,SIGNAL(currentIndexChanged(int)),this,SLOT(slotCheckComplete()));
36  connect(treeMounts,SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),this,SLOT(slotTreeDiskChanged()));
37  treeMounts->setContextMenuPolicy(Qt::CustomContextMenu);
38  connect(treeMounts,SIGNAL(customContextMenuRequested(const QPoint &)),this,SLOT(slotTreeMountsRightClick()));
39  connect(pushTerminal, SIGNAL(clicked()), this, SLOT(slotTerminal()));
40
41  // ZFS Mode Page
42  connect(comboZFSMode,SIGNAL(currentIndexChanged(int)),this,SLOT(slotCheckComplete()));
43  connect(groupZFSOpts,SIGNAL(clicked(bool)),this,SLOT(slotCheckComplete()));
44  connect(listZFSDisks,SIGNAL(itemClicked(QListWidgetItem *)),this,SLOT(slotCheckComplete()));
45  connect(listZFSDisks,SIGNAL(itemActivated(QListWidgetItem *)),this,SLOT(slotCheckComplete()));
46  connect(listZFSDisks,SIGNAL(itemChanged(QListWidgetItem *)),this,SLOT(slotCheckComplete()));
47  connect(groupZFSCache,SIGNAL(clicked(bool)),this,SLOT(slotCheckComplete()));
48  connect(listZFSCache,SIGNAL(itemClicked(QListWidgetItem *)),this,SLOT(slotCheckComplete()));
49  connect(listZFSCache,SIGNAL(itemActivated(QListWidgetItem *)),this,SLOT(slotCheckComplete()));
50  connect(listZFSCache,SIGNAL(itemChanged(QListWidgetItem *)),this,SLOT(slotCheckComplete()));
51  connect(groupZFSLog,SIGNAL(clicked(bool)),this,SLOT(slotCheckComplete()));
52  connect(listZFSLog,SIGNAL(itemClicked(QListWidgetItem *)),this,SLOT(slotCheckComplete()));
53  connect(listZFSLog,SIGNAL(itemActivated(QListWidgetItem *)),this,SLOT(slotCheckComplete()));
54  connect(listZFSLog,SIGNAL(itemChanged(QListWidgetItem *)),this,SLOT(slotCheckComplete()));
55  connect(groupEncrypt,SIGNAL(clicked(bool)),this,SLOT(slotCheckComplete()));
56  connect(lineEncPass,SIGNAL(textChanged(const QString &)),this,SLOT(slotCheckComplete()));
57  connect(lineEncPass2,SIGNAL(textChanged(const QString &)),this,SLOT(slotCheckComplete()));
58
59}
60
61void wizardDisk::populateDiskInfo()
62{
63  qDebug() << "Loading Disk Info";
64  sysDisks = Scripts::Backend::hardDrives();
65
66  // load drives
67  comboDisk->clear();
68  for (int i=0; i < sysDisks.count(); ++i) {
69    // Make sure to only add the drives to the comboDisk
70    if ( sysDisks.at(i).at(0) == "DRIVE" )
71      comboDisk->addItem(sysDisks.at(i).at(1) + " - " + sysDisks.at(i).at(2) + "MB " + sysDisks.at(i).at(3));
72  }
73
74  // Reload the slice list box
75  slotChangedDisk();
76}
77
78void wizardDisk::slotChangedDisk()
79{
80  QString ptag;
81
82  if ( comboDisk->currentText().isEmpty())
83    return;
84
85  comboPartition->clear();
86  comboPartition->addItem(tr("Use entire disk"));
87       
88  QString disk = comboDisk->currentText();
89  disk.truncate(disk.indexOf(" -"));
90  for (int i=0; i < sysDisks.count(); ++i) {
91    // Make sure to only add the slices to the listDiskSlices
92    if ( sysDisks.at(i).at(0) == "SLICE" && disk == sysDisks.at(i).at(1) && sysDisks.at(i).at(4) != "Unused Space") {
93      ptag = sysDisks.at(i).at(4).section(",", 0, 0);
94      ptag = ptag.section("/", 0, 0);
95      ptag.truncate(15);
96      if ( ptag.indexOf(")") == -1 )
97        ptag += ")";
98      comboPartition->addItem(sysDisks.at(i).at(2) + ": " +  sysDisks.at(i).at(3) + "MB " + ptag );
99    }
100  }
101
102}
103
104void wizardDisk::slotClose()
105{
106  close();
107}
108
109void wizardDisk::accept()
110{
111  QString bootLoader;
112  bool useGPT = false;
113  bool force4K = false;
114  QString zpoolName;
115  if (comboPartition->currentIndex() == 0 )
116    useGPT = checkGPT->isChecked();
117
118  // Get the boot-loader
119  bootLoader = comboBootLoader->currentText();
120  if ( radioBasic->isChecked() )
121     bootLoader="GRUB";
122
123  if ( comboPartition->currentIndex() != 0 && bootLoader == "NONE"  ) {
124     QMessageBox::warning(this, tr("No boot-loader!"),
125     tr("You have chosen not to install a boot-loader. You will need to manually setup your own loader."),
126     QMessageBox::Ok,
127     QMessageBox::Ok);
128  }
129     
130  // When doing advanced ZFS setups, make sure to use GPT
131  if ( radioAdvanced->isChecked() && groupZFSOpts->isChecked() )
132    useGPT = true;
133
134  // When doing advanced ZFS setups, check if 4K is enabled
135  if ( radioAdvanced->isChecked() && checkForce4K->isChecked() )
136    force4K = true;
137
138  if ( radioAdvanced->isChecked() && groupZFSPool->isChecked() )
139     zpoolName = lineZpoolName->text();
140
141  if ( radioExpert->isChecked() )
142    emit saved(sysFinalDiskLayout, QString("NONE"), false, zpoolName, force4K);
143  else
144    emit saved(sysFinalDiskLayout, bootLoader, useGPT, zpoolName, force4K);
145  close();
146}
147
148int wizardDisk::nextId() const
149{
150  switch (currentId()) {
151     case Page_Intro:
152       if (radioExpert->isChecked())
153         return Page_Expert;
154       if (radioBasic->isChecked()) {
155         checkGPT->setVisible(false);
156         comboBootLoader->setVisible(false);
157         textBootLoader->setVisible(false);
158         checkForce4K->setVisible(false);
159         groupZFSPool->setVisible(false);
160       }
161       if (radioAdvanced->isChecked()) {
162         checkGPT->setVisible(true);
163         comboBootLoader->setVisible(true);
164         textBootLoader->setVisible(true);
165         checkForce4K->setVisible(true);
166         groupZFSPool->setVisible(true);
167       }
168        break;
169     case Page_BasicDisk:
170       if (checkSSD->isChecked())
171         pushSwapSize->setVisible(false);
172       else
173         pushSwapSize->setVisible(true);
174
175       if (radioBasic->isChecked())
176         return Page_Confirmation;
177       if (comboPartition->currentIndex() != 0 ) {
178         groupZFSOpts->setEnabled(false);
179         return Page_Mounts;
180       } else {
181         if ( checkGPT->isChecked() )
182           groupEncrypt->setEnabled(true);
183         else
184           groupEncrypt->setEnabled(false);
185         groupZFSOpts->setEnabled(true);
186         return Page_ZFS;
187       }
188       break;
189     case Page_ZFS:
190       return Page_ZFS2;
191       break;
192     case Page_ZFS2:
193       return Page_Enc;
194       break;
195     case Page_Enc:
196       return Page_Mounts;
197       break;
198     case Page_Mounts:
199       return Page_Confirmation;
200       break;
201     case Page_Confirmation:
202       return -1;
203       break;
204     default:
205        return currentId() + 1;
206  }
207  return currentId() + 1;
208}
209
210// Logic checks to see if we are ready to move onto next page
211bool wizardDisk::validatePage()
212{
213
214  bool found;
215
216  // Generate suggested disk layout and show disk tree
217  if ( prevID == Page_BasicDisk && currentId() == Page_Mounts) {
218    generateDiskLayout();
219    populateDiskTree();
220  }
221
222  // Generate suggested disk layout and show disk tree
223  if ( prevID == Page_Enc && currentId() == Page_Mounts) {
224    generateDiskLayout();
225    populateDiskTree();
226  } 
227
228  // Show the other disks available
229  if ( prevID == Page_BasicDisk && currentId() == Page_ZFS)
230     populateZFSDisks();
231
232  // Show the other disks available
233  if ( prevID == Page_ZFS && currentId() == Page_ZFS2)
234     populateZFSDisks2();
235
236  // Basic mode, generate a disk layout and show summary
237  if ( prevID == Page_BasicDisk && currentId() == Page_Confirmation) {
238    generateDiskLayout();
239    generateConfirmationText();
240  }
241
242  // Create the final disk layout from user options
243  if ( prevID == Page_Mounts && currentId() == Page_Confirmation) {
244    generateCustomDiskLayout();
245    generateConfirmationText();
246  }
247
248  // Create the final disk layout from user options
249  if ( prevID == Page_Expert && currentId() == Page_Confirmation) {
250    generateConfirmationText();
251  }
252 
253 
254  // Reset the prevID
255  prevID = currentId();
256
257  switch (currentId()) {
258     case Page_Intro:
259         button(QWizard::NextButton)->setEnabled(true);
260         return true;
261     case Page_BasicDisk:
262       
263         if ( ! radioAdvanced->isChecked() ) {
264           checkGPT->setChecked(false);
265           checkGPT->setVisible(false);
266           checkForce4K->setVisible(false);
267           checkForce4K->setChecked(false);
268         } else {
269           checkGPT->setVisible(true);
270           checkForce4K->setVisible(true);
271         } 
272
273         // Doing a Advanced install
274         if ( radioAdvanced->isChecked() && groupZFSPool->isChecked() )
275         {
276            if ( lineZpoolName->text().isEmpty() ) {
277              button(QWizard::NextButton)->setEnabled(false);
278              return false;
279            }
280            if ( lineZpoolName->text() == "root" ) {
281              button(QWizard::NextButton)->setEnabled(false);
282              return false;
283            }
284            if ( lineZpoolName->text().contains(" ") ) {
285              button(QWizard::NextButton)->setEnabled(false);
286              return false;
287            }
288            QRegExp *re = new QRegExp("^[-'a-zA-Z][a-zA-Z0-9]*$"); 
289            if (! re->exactMatch(lineZpoolName->text()) ) {
290              button(QWizard::NextButton)->setEnabled(false);
291              return false;
292            }
293
294         }
295
296         // If the select partition is just too small, we can stop here
297         if ( ! checkDiskSpace() ) {
298           button(QWizard::NextButton)->setEnabled(false);
299           return false;
300         }
301       
302         // if we get this far, all the fields are filled in
303         button(QWizard::NextButton)->setEnabled(true);
304         return true;
305     case Page_ZFS:
306         // Check if we have valid ZFS disk options specified
307         if ( ! groupZFSOpts->isChecked() ) {
308           button(QWizard::NextButton)->setEnabled(true);
309           return true;
310         }
311         // Need at least one other disk for mirroring
312         if ( comboZFSMode->currentText() == "mirror" ) {
313            labelZFSMsg->setText(tr("Please select at least 1 other drive for mirroring"));
314            for ( int i = 0; i < listZFSDisks->count(); ++i )
315            {
316                if ( listZFSDisks->item(i)->checkState() == Qt::Checked ) {
317                   button(QWizard::NextButton)->setEnabled(true);
318                   return true;
319                }
320            }
321         }
322         if ( comboZFSMode->currentText() == "raidz1" ) {
323            labelZFSMsg->setText(tr("Please select 2 or 4 additional drives for raidz1"));
324            int numChecked = 0;
325            for ( int i = 0; i < listZFSDisks->count(); ++i )
326                if ( listZFSDisks->item(i)->checkState() == Qt::Checked )
327                   numChecked++;
328            if ( numChecked == 2 || numChecked == 4 ) {
329              button(QWizard::NextButton)->setEnabled(true);
330              return true;
331            }
332         }
333         if ( comboZFSMode->currentText() == "raidz2" ) {
334            labelZFSMsg->setText(tr("Please select 3, 5, or 9 additional drives for raidz2"));
335            int numChecked = 0;
336            for ( int i = 0; i < listZFSDisks->count(); ++i )
337                if ( listZFSDisks->item(i)->checkState() == Qt::Checked )
338                   numChecked++;
339            if ( numChecked == 3 || numChecked == 5 || numChecked == 9 ) {
340              button(QWizard::NextButton)->setEnabled(true);
341              return true;
342            }
343         }
344         if ( comboZFSMode->currentText() == "raidz3" ) {
345            labelZFSMsg->setText(tr("Please select 4, 6, or 10 additional drives for raidz3"));
346            int numChecked = 0;
347            for ( int i = 0; i < listZFSDisks->count(); ++i )
348                if ( listZFSDisks->item(i)->checkState() == Qt::Checked )
349                   numChecked++;
350            if ( numChecked == 4 || numChecked == 6 || numChecked == 10 ) {
351              button(QWizard::NextButton)->setEnabled(true);
352              return true;
353            }
354         }
355
356         // Disable the next button until we get a working config
357         button(QWizard::NextButton)->setEnabled(false);
358         return false;
359     case Page_ZFS2:
360         // Not using log / cache?
361         if ( !groupZFSCache->isChecked() && ! groupZFSLog->isChecked() )
362         {
363           button(QWizard::NextButton)->setEnabled(true);
364           return true;
365         }
366         // Using both? See if we have any duplicates
367         if ( groupZFSCache->isChecked() && groupZFSLog->isChecked() )
368         {
369            // Check for any matches
370            for ( int i = 0; i < listZFSCache->count(); ++i ) {
371                if ( listZFSCache->item(i)->checkState() == Qt::Checked )
372                  for ( int z = 0; z < listZFSLog->count(); ++z ) {
373                    if ( listZFSLog->item(z)->checkState() == Qt::Checked )
374                       if ( listZFSLog->item(z)->text() == listZFSCache->item(i)->text() ) {
375                          button(QWizard::NextButton)->setEnabled(false);
376                          return false;
377                       }
378                  }
379            }
380         }
381
382         // Check that we have at least one item checked
383         found = false;
384         if ( groupZFSCache->isChecked() )
385         {
386            for ( int i = 0; i < listZFSCache->count(); ++i )
387                if ( listZFSCache->item(i)->checkState() == Qt::Checked )
388                   found = true;
389            if ( found == false) {
390              button(QWizard::NextButton)->setEnabled(false);
391              return false;
392            }
393         }
394         if ( groupZFSLog->isChecked() )
395         {
396            for ( int i = 0; i < listZFSLog->count(); ++i )
397                if ( listZFSLog->item(i)->checkState() == Qt::Checked )
398                   found = true;
399            if ( found == false) {
400              button(QWizard::NextButton)->setEnabled(false);
401              return false;
402            }
403         }
404
405         button(QWizard::NextButton)->setEnabled(true);
406         return true;
407     case Page_Enc:
408         if ( ! groupEncrypt->isChecked() ) {
409           button(QWizard::NextButton)->setEnabled(true);
410           return true;
411         }
412         if ( lineEncPass->text().isEmpty() || lineEncPass->text() != lineEncPass2->text() ) {
413           button(QWizard::NextButton)->setEnabled(false);
414           return false;
415         }
416
417         button(QWizard::NextButton)->setEnabled(true);
418         return true;
419     case Page_Confirmation:
420         button(QWizard::FinishButton)->setEnabled(true);
421         return true;
422     default:
423         button(QWizard::NextButton)->setEnabled(true);
424         return true;
425  }
426
427  return true;
428}
429
430void wizardDisk::populateZFSDisks()
431{
432   qDebug() << "Adding ZFS disks...";
433   listZFSDisks->clear();
434
435   QString curDisk = comboDisk->currentText();
436   curDisk.truncate(curDisk.indexOf(" -"));
437
438   for (int z=0; z < sysDisks.count(); ++z)
439     if ( sysDisks.at(z).at(0) == "DRIVE" && sysDisks.at(z).at(1) != curDisk  )
440     {
441        QListWidgetItem *dItem = new QListWidgetItem(sysDisks.at(z).at(1) + " - " + sysDisks.at(z).at(2) + "MB " + sysDisks.at(z).at(3));
442        dItem->setCheckState(Qt::Unchecked);
443        listZFSDisks->addItem(dItem);
444     }
445}
446
447void wizardDisk::populateZFSDisks2()
448{
449   qDebug() << "Adding ZFS2 disks...";
450   listZFSCache->clear();
451   listZFSLog->clear();
452
453   // What is the primary target disk
454   QString curDisk = comboDisk->currentText();
455   curDisk.truncate(curDisk.indexOf(" -"));
456
457   // Get a list of other disks being used
458   QStringList usedDisks;
459   if ( groupZFSOpts->isChecked() ) {
460     for ( int i = 0; i < listZFSDisks->count(); ++i )
461        if ( listZFSDisks->item(i)->checkState() == Qt::Checked ) {
462           QString zDisk = listZFSDisks->item(i)->text();
463           zDisk.truncate(zDisk.indexOf(" -"));
464           usedDisks << zDisk;
465        }
466   }
467
468   // Now add any available disks to the combo boxes
469   for (int z=0; z < sysDisks.count(); ++z)
470     if ( sysDisks.at(z).at(0) == "DRIVE" && sysDisks.at(z).at(1) != curDisk && ! usedDisks.contains(sysDisks.at(z).at(1))  )
471     {
472        QListWidgetItem *dItem = new QListWidgetItem(sysDisks.at(z).at(1) + " - " + sysDisks.at(z).at(2) + "MB " + sysDisks.at(z).at(3));
473        dItem->setCheckState(Qt::Unchecked);
474        listZFSCache->addItem(dItem);
475        QListWidgetItem *dItem2 = new QListWidgetItem(sysDisks.at(z).at(1) + " - " + sysDisks.at(z).at(2) + "MB " + sysDisks.at(z).at(3));
476        dItem2->setCheckState(Qt::Unchecked);
477        listZFSLog->addItem(dItem2);
478     }
479}
480
481bool wizardDisk::checkDiskSpace()
482{
483  if ( getDiskSliceSize() < 4000 )
484    return false;
485
486  return true;
487}
488
489void wizardDisk::slotCheckComplete()
490{
491   // Validate this page
492   validatePage();
493}
494
495
496void wizardDisk::generateDiskLayout()
497{
498  QString targetType, tmp;
499  int targetLoc, totalSize = 0;
500  QString targetDisk, targetSlice, tmpPass, fsType, target;
501
502  // Clear out the original disk layout
503  sysFinalDiskLayout.clear();
504  QStringList fileSystem;
505  qDebug() << "Generating disk layout";
506
507  if ( comboPartition->currentIndex() == 0) {
508    targetType = "DRIVE";
509    targetSlice = "ALL";
510    targetDisk = comboDisk->currentText();
511    targetDisk.truncate(targetDisk.indexOf(" -"));
512    target = targetDisk;
513    targetLoc = 1;
514  } else {
515    targetType = "SLICE";
516    targetDisk = comboDisk->currentText();
517    targetDisk.truncate(targetDisk.indexOf(" -"));
518    targetSlice = comboPartition->currentText();
519    targetSlice.truncate(targetSlice.indexOf(":"));
520    targetSlice = targetSlice.remove(0, targetSlice.size() -2);
521    target = targetDisk + targetSlice;
522    targetLoc = 2;
523  }
524
525  // Get the size of the slice we are working on
526  totalSize = getDiskSliceSize();
527
528  // Setup some swap space
529  if ( totalSize > 30000 ) {
530    // 2GB if over 30GB of disk space, 512MB otherwise
531    swapsize = 2000;
532  } else {
533    swapsize = 512;
534  }
535  totalSize = totalSize - swapsize;
536
537
538  if ( totalSize != -1 )
539  {
540     fsType= "ZFS";
541     if ( groupEncrypt->isChecked() ) {
542        fsType="ZFS.eli";
543        tmpPass=lineEncPass->text();
544     }
545
546    QString rootOpts="";
547    if ( checkSSD->isChecked() )
548        rootOpts="(compress=lz4|atime=off)";
549    else
550        rootOpts="(compress=lz4)";
551
552     // This lets the user do nifty stuff like a mirror/raid post-install with a single zpool command
553    fileSystem << targetDisk << targetSlice << "/" + rootOpts + ",/tmp(compress=lz4|setuid=off|exec=off),/usr(canmount=off),/usr/home(compress=lz4),/usr/jails(compress=lz4),/usr/obj(compress=lz4),/usr/pbi(compress=lz4),/usr/ports(compress=lz4),/usr/ports/distfiles(compress=lz4),/usr/src(compress=lz4),/var(canmount=off),/var/audit(compress=lz4),/var/log(compress=lz4|exec=off|setuid=off),/var/tmp(compress=lz4|exec=off|setuid=off)" << fsType << tmp.setNum(totalSize) << "" << tmpPass;
554    sysFinalDiskLayout << fileSystem;
555    fileSystem.clear();
556
557    // Now add swap space if NOT on a SSD
558    if ( ! checkSSD->isChecked() ) {
559      fileSystem << targetDisk << targetSlice << "SWAP.eli" << "SWAP.eli" << tmp.setNum(swapsize) << "" << "";
560      sysFinalDiskLayout << fileSystem;
561      fileSystem.clear();
562    }
563
564    //qDebug() << "Auto-Gen FS:" <<  fileSystem;
565  }
566 
567  qDebug() << "AutoLayout:" <<  sysFinalDiskLayout;
568}
569
570void wizardDisk::populateDiskTree()
571{
572  QStringList tmpList, zMnts;
573  QString tmp, opts;
574
575  treeMounts->clear();
576  treeMounts->setHeaderLabels(QStringList() << "ID" << tr("ZFS Mounts") << tr("ZFS Options") );
577  treeMounts->setColumnCount(3);
578  labelFreeSpace->setVisible(false);
579  lineFreeMB->setVisible(false);
580
581  treeMounts->header()->setSectionHidden(0, true);
582  treeMounts->header()->setDefaultSectionSize(150);
583
584
585  zMnts = sysFinalDiskLayout.at(0).at(2).split(",");
586
587  // Now loop through ZFS mounts
588  for (int i=0; i < zMnts.count(); ++i) {
589    tmpList.clear();
590    opts = zMnts.at(i).section("(", 1, 1).section(")", 0, 0); 
591    tmpList << tmp.setNum(i+1) << zMnts.at(i).split("(").at(0) << opts ;
592    QTreeWidgetItem *mItem = new QTreeWidgetItem(treeMounts, tmpList);
593    mItem->setToolTip(2, opts);
594  }
595
596  treeMounts->setCurrentItem(treeMounts->findItems("0", Qt::MatchFixedString).at(0));
597  slotTreeDiskChanged(); 
598
599  if ( restoreMode ) {
600     treeMounts->setEnabled(false);
601     pushRemoveMount->setEnabled(false);
602     pushAddMount->setEnabled(false);
603     labelMounts->setText(tr("The original system datasets / mount-points will be automatically restored."));
604  }
605
606}
607
608int wizardDisk::getDiskSliceSize()
609{
610  bool ok;
611  QString disk = comboDisk->currentText();
612  disk.truncate(disk.indexOf(" -"));
613
614  int safeBuf = 10;
615
616  // Check the full disk
617  if ( comboPartition->currentIndex() == 0) {
618    for (int i=0; i < sysDisks.count(); ++i) {
619      // Make sure to only add the drives to the comboDiskList
620      if ( sysDisks.at(i).at(0) == "DRIVE" && sysDisks.at(i).at(1) == disk ) {
621        //qDebug() << "Selected Disk Size: " +  sysDisks.at(i).at(2);
622        sysDisks.at(i).at(2).toInt(&ok);
623        if( ok )
624          return sysDisks.at(i).at(2).toInt(&ok) - safeBuf;
625        else
626          return -1;
627      }
628    }
629  } else {
630    // Check the selected partition
631    QString slice = comboPartition->currentText();
632    slice.truncate(slice.indexOf(":"));
633    for (int i=0; i < sysDisks.count(); ++i) {
634      // Make sure to only add the slices to the listDiskSlices
635      if ( sysDisks.at(i).at(0) == "SLICE" && slice == sysDisks.at(i).at(2)) {
636        //qDebug() << "Selected Slice Size: " +  sysDisks.at(i).at(3);
637        sysDisks.at(i).at(3).toInt(&ok);
638        if( ok )
639          return sysDisks.at(i).at(3).toInt(&ok) - safeBuf;
640        else
641          return -1;
642      }
643    }
644  }
645
646  return -1;
647}
648
649void wizardDisk::slotTreeDiskChanged()
650{
651   if ( ! treeMounts->currentItem() )
652     return;
653
654   pushRemoveMount->setEnabled(true);
655   pushAddMount->setEnabled(true);
656
657   if ( treeMounts->currentItem()->text(1) == "/boot" || treeMounts->currentItem()->text(1) == "/")
658     pushRemoveMount->setEnabled(false);
659
660   if ( lineFreeMB->text() == "0" )
661     pushAddMount->setEnabled(false);
662}
663
664void wizardDisk::slotResizeFS()
665{
666  if ( ! treeMounts->currentItem() )
667  return;
668
669  QString mnt = treeMounts->currentItem()->text(1);
670  bool ok;
671  int curSize, availSize, minSize; 
672  curSize =  treeMounts->currentItem()->text(2).toInt(&ok);
673  availSize = curSize + lineFreeMB->text().toInt(&ok);
674
675  minSize = 100;
676
677  // See if we need some other sanity check on sizes
678  if ( mnt == "SWAP.eli" )
679    minSize = 256;
680  if ( mnt == "/" )
681    minSize = 2000;
682  if ( mnt == "/boot" )
683    minSize = 1000;
684
685  addingMount="";
686  rFS = new dialogFSSize();
687  rFS->programInit(QString(tr("Resizing") + " " + mnt), curSize, availSize, minSize);
688  rFS->setWindowModality(Qt::ApplicationModal);
689  connect(rFS, SIGNAL(saved(int)), this, SLOT(slotSaveFSResize(int)));
690  rFS->show();
691  rFS->raise();
692}
693
694void wizardDisk::slotRemoveFS()
695{
696  if ( ! treeMounts->currentItem() )
697  return;
698
699  int ret = QMessageBox::question(this, tr("Remove mount-point"),
700              tr("Are you sure you want to remove this mount point?"),
701              QMessageBox::Yes | QMessageBox::No,
702              QMessageBox::No);
703
704  if ( ret != QMessageBox::Yes )
705    return;
706 
707  QTreeWidgetItem *rmItem = treeMounts->currentItem();
708  treeMounts->setCurrentItem(treeMounts->findItems("0", Qt::MatchFixedString).at(0));
709
710  delete rmItem;
711}
712
713void wizardDisk::slotAddFS()
714{
715  bool ok;
716  QString tmp;
717  QString nMount = QInputDialog::getText(this, tr("Enter mount-point"),
718                                          tr("Please enter the new mount-point:"), QLineEdit::Normal,
719                                          "/", &ok);
720  if (!ok || nMount.isEmpty())
721    return;
722
723  // Sanity checks
724  ////////////////////////////////////////
725  if ( nMount.indexOf("/") != 0 ) {
726      QMessageBox::critical(this, tr("Invalid Mount"),
727              tr("Mount point should start with '/'"),
728              QMessageBox::Ok,
729              QMessageBox::Ok);
730      return;
731  }
732  // End sanity checks
733  ////////////////////////////////////////
734
735  // Make sure this mount doesn't already exist
736  QList<QTreeWidgetItem *> mItems = treeMounts->findItems("*", Qt::MatchWildcard);
737  for ( int i = 0; i < mItems.size(); ++i) {
738    if ( mItems.at(i)->text(1) == nMount )
739      return;
740  }
741
742  new QTreeWidgetItem(treeMounts, QStringList() << tmp.setNum(mItems.size() + 1) << nMount );
743}
744
745void wizardDisk::slotSaveFSResize(int newSize)
746{
747
748  QString tmp, tmp2;
749  bool ok;
750  int oSize, availSize, tSize, newAvailSize;
751
752  // If adding a new mount point
753  if ( ! addingMount.isEmpty() ) {
754    QList<QTreeWidgetItem *> mItems = treeMounts->findItems("*", Qt::MatchWildcard);
755    new QTreeWidgetItem(treeMounts, QStringList() << tmp.setNum(mItems.size() + 1) << addingMount << tmp2.setNum(newSize) << "UFS+SUJ" );
756    addingMount="";
757    availSize = lineFreeMB->text().toInt(&ok); 
758    newAvailSize = availSize - newSize;
759    lineFreeMB->setText(tmp.setNum(newAvailSize));
760    return;
761  } 
762
763  if ( ! treeMounts->currentItem() )
764    return;
765
766  // Just resizing an existing partition
767  oSize = treeMounts->currentItem()->text(2).toInt(&ok); 
768  treeMounts->currentItem()->setText(2, tmp.setNum(newSize));
769
770  // Set the available size
771  if ( oSize > newSize ) {
772    tSize = oSize - newSize;
773    availSize = lineFreeMB->text().toInt(&ok); 
774    newAvailSize = availSize + tSize;
775  } else {
776    tSize = newSize - oSize;
777    availSize = lineFreeMB->text().toInt(&ok); 
778    newAvailSize = availSize - tSize;
779  }
780  lineFreeMB->setText(tmp.setNum(newAvailSize));
781
782  // Check if we need to enable the add button
783  if ( newAvailSize >= 100 )
784    pushAddMount->setEnabled(true);
785  else
786    pushAddMount->setEnabled(false);
787}
788
789void wizardDisk::slotTreeMountsRightClick()
790{
791  if ( ! treeMounts->currentItem() )
792    return;
793
794  popup = new QMenu();
795  popup->setTitle(tr("Editing:") + " " + treeMounts->currentItem()->text(1));
796  popup->addSeparator();
797
798  // Create atime sub-menu
799  popupAT = popup->addMenu("atime");
800  popupAT->addAction( "on", this, SLOT(slotZATON()));
801  popupAT->addAction( "off", this, SLOT(slotZATOFF()));
802
803  // Create canmount sub-menu
804  popupCM = popup->addMenu("canmount");
805  popupCM->addAction( "on", this, SLOT(slotZCMON()));
806  popupCM->addAction( "off", this, SLOT(slotZCMOFF()));
807  popupCM->addAction( "noauto", this, SLOT(slotZCMNOAUTO()));
808
809  // Create Checksum sub-menu
810  popupCH = popup->addMenu("checksum");
811  popupCH->addAction( "on", this, SLOT(slotZChkON()));
812  popupCH->addAction( "off", this, SLOT(slotZChkOFF()));
813
814  // Create compression sub-menu
815  popupCmp = popup->addMenu("compression");
816  popupCmp->addAction( "off", this, SLOT(slotZCmpOFF()));
817  popupCmp->addAction( "on", this, SLOT(slotZCmpON()));
818  popupCmp->addAction( "lz4", this, SLOT(slotZCmpLZ4()));
819  popupCmp->addAction( "lzjb", this, SLOT(slotZCmpLZJB()));
820  popupCmp->addAction( "gzip", this, SLOT(slotZCmpGZIP()));
821  popupCmp->addAction( "zle", this, SLOT(slotZCmpZLE()));
822
823  // Create dedup sub-menu
824  // dedup is disabled for now, until such time as it is safe in all cases
825  //popupDD = popup->addMenu("dedup");
826  //popupDD->addAction( "off", this, SLOT(slotZDDOFF()));
827  //popupDD->addAction( "on", this, SLOT(slotZDDON()));
828  //popupDD->addAction( "verify", this, SLOT(slotZDDVERIFY()));
829
830  // Create exec sub-menu
831  popupNE = popup->addMenu("exec");
832  popupNE->addAction( "on", this, SLOT(slotZEXON()));
833  popupNE->addAction( "off", this, SLOT(slotZEXOFF()));
834
835  // Add setuid sub-menu
836  popupNE = popup->addMenu("setuid");
837  popupNE->addAction( "on", this, SLOT(slotZSUIDON()));
838  popupNE->addAction( "off", this, SLOT(slotZSUIDOFF()));
839
840  popup->exec( QCursor::pos() );
841
842}
843
844void wizardDisk::slotZCMNOAUTO()
845{
846  toggleZFSOpt(QString("canmount=noauto"));
847}
848
849void wizardDisk::slotZCMOFF()
850{
851  toggleZFSOpt(QString("canmount=off"));
852}
853
854void wizardDisk::slotZCMON()
855{
856  toggleZFSOpt(QString("canmount=on"));
857}
858
859void wizardDisk::slotZDDVERIFY()
860{
861  toggleZFSOpt(QString("dedup=verify"));
862}
863
864void wizardDisk::slotZDDON()
865{
866  toggleZFSOpt(QString("dedup=on"));
867}
868
869void wizardDisk::slotZDDOFF()
870{
871  toggleZFSOpt(QString("dedup=off"));
872}
873
874void wizardDisk::slotZCmpZLE()
875{
876  toggleZFSOpt(QString("compress=zle"));
877}
878
879void wizardDisk::slotZCmpGZIP()
880{
881  toggleZFSOpt(QString("compress=gzip"));
882}
883
884void wizardDisk::slotZCmpLZ4()
885{
886  toggleZFSOpt(QString("compress=lz4"));
887}
888
889void wizardDisk::slotZCmpLZJB()
890{
891  toggleZFSOpt(QString("compress=lzjb"));
892}
893
894void wizardDisk::slotZCmpOFF()
895{
896  toggleZFSOpt(QString("compress=off"));
897}
898
899void wizardDisk::slotZCmpON()
900{
901  toggleZFSOpt(QString("compress=on"));
902}
903
904void wizardDisk::slotZChkOFF()
905{
906  toggleZFSOpt(QString("checksum=off"));
907}
908
909void wizardDisk::slotZChkON()
910{
911  toggleZFSOpt(QString("checksum=on"));
912}
913
914void wizardDisk::slotZATON()
915{
916  toggleZFSOpt(QString("atime=on"));
917}
918
919void wizardDisk::slotSwapSize()
920{
921  bool ok;
922  QString tmp;
923  int size = QInputDialog::getInt(this, tr("Enter SWAP size"),
924                                  tr("Size (MB)"), swapsize, 0, 1000000, 1, &ok);
925  if ( ok )
926    swapsize = size;
927}
928
929void wizardDisk::slotZATOFF()
930{
931  toggleZFSOpt(QString("atime=off"));
932}
933
934void wizardDisk::slotZEXOFF()
935{
936  toggleZFSOpt(QString("exec=off"));
937}
938
939void wizardDisk::slotZEXON()
940{
941  toggleZFSOpt(QString("exec=on"));
942}
943
944void wizardDisk::slotZSUIDOFF()
945{
946  toggleZFSOpt(QString("setuid=off"));
947}
948
949void wizardDisk::slotZSUIDON()
950{
951  toggleZFSOpt(QString("setuid=on"));
952}
953
954// Toggle an option being on / off for ZFS
955void wizardDisk::toggleZFSOpt(QString option)
956{
957  if ( ! treeMounts->currentItem() )
958    return;
959
960  bool found = false;
961  QString optTag = option.section("=", 0, 0);
962  QString tmpTag;
963  QStringList newOpts;
964  QStringList curOpts = treeMounts->currentItem()->text(2).split("|");
965  for (int i=0; i < curOpts.count(); ++i) {
966    tmpTag=curOpts.at(i).section("=", 0, 0);
967    if ( optTag == tmpTag ) {
968      found = true;
969      // Only save option if setting to new value
970      if ( option != curOpts.at(i) )
971        newOpts << option;
972    } else {
973      if ( !curOpts.at(i).isEmpty() )
974        newOpts << curOpts.at(i);
975    }
976  }
977
978  if ( ! found )
979      newOpts << option;
980
981  QString optString;
982  if ( newOpts.count() <= 1)
983    optString = newOpts.join("");
984  else
985    optString = newOpts.join("|");
986
987  treeMounts->currentItem()->setText(2, optString);
988  treeMounts->currentItem()->setToolTip(2, optString);
989}
990
991void wizardDisk::generateCustomDiskLayout()
992{
993  QString targetType, tmp;
994  int targetLoc;
995  QString targetDisk, targetSlice, tmpPass, fsType, target;
996
997  // Clear out the original disk layout
998  sysFinalDiskLayout.clear();
999  QStringList fileSystem;
1000  qDebug() << "Generating custom disk layout";
1001       
1002  if ( comboPartition->currentIndex() == 0) {
1003    targetType = "DRIVE";
1004    targetSlice = "ALL";
1005    targetDisk = comboDisk->currentText();
1006    targetDisk.truncate(targetDisk.indexOf(" -"));
1007    target = targetDisk;
1008    targetLoc = 1;
1009  } else {
1010    targetType = "SLICE";
1011    targetDisk = comboDisk->currentText();
1012    targetDisk.truncate(targetDisk.indexOf(" -"));
1013    targetSlice = comboPartition->currentText();
1014    targetSlice.truncate(targetSlice.indexOf(":"));
1015    targetSlice = targetSlice.remove(0, targetSlice.size() -2);
1016    target = targetDisk + targetSlice;
1017    targetLoc = 2;
1018  }
1019
1020  // Start building the ZFS file-systems
1021  QStringList zMnts;
1022  fsType = "ZFS";
1023  if ( groupEncrypt->isChecked() ) {
1024    fsType="ZFS.eli";
1025    tmpPass=lineEncPass->text();
1026  }
1027  int zpoolSize = getDiskSliceSize();
1028
1029  // Deduct any swap space
1030  zpoolSize = zpoolSize - swapsize;
1031
1032  // Get the zfs mounts
1033  QList<QTreeWidgetItem *> mItems = treeMounts->findItems("*", Qt::MatchWildcard);
1034  for ( int i = 0; i < mItems.size(); ++i) {
1035    if ( mItems.at(i)->text(2).isEmpty() )
1036      zMnts << mItems.at(i)->text(1);
1037    else
1038      zMnts << mItems.at(i)->text(1) + "(" + mItems.at(i)->text(2) + ")";
1039  }
1040
1041  // If we have any additional ZFS mirror / raidz devices set it up now
1042  QString zOpts, zDisk;
1043  if ( groupZFSOpts->isChecked() && comboPartition->currentIndex() == 0 ) {
1044     zOpts = comboZFSMode->currentText() + ":";
1045     for ( int i = 0; i < listZFSDisks->count(); ++i )
1046        if ( listZFSDisks->item(i)->checkState() == Qt::Checked ) {
1047           zDisk = listZFSDisks->item(i)->text();
1048           zDisk.truncate(zDisk.indexOf(" -"));
1049           zOpts = zOpts + " " + zDisk;
1050        }
1051  }
1052  // Any additional ZFS cache devices?
1053  if ( groupZFSCache->isChecked() ) {
1054     zOpts+=" cache";
1055     for ( int i = 0; i < listZFSCache->count(); ++i )
1056        if ( listZFSCache->item(i)->checkState() == Qt::Checked ) {
1057           zDisk = listZFSCache->item(i)->text();
1058           zDisk.truncate(zDisk.indexOf(" -"));
1059           zOpts = zOpts + " " + zDisk;
1060        }
1061  }
1062  // Any additional ZFS log devices?
1063  if ( groupZFSLog->isChecked() ) {
1064     zOpts+=" log";
1065     for ( int i = 0; i < listZFSLog->count(); ++i )
1066        if ( listZFSLog->item(i)->checkState() == Qt::Checked ) {
1067           zDisk = listZFSLog->item(i)->text();
1068           zDisk.truncate(zDisk.indexOf(" -"));
1069           zOpts = zOpts + " " + zDisk;
1070        }
1071  }
1072
1073  // Save the final disk layout
1074  fileSystem.clear();
1075  fileSystem << targetDisk << targetSlice << zMnts.join(",") << fsType << tmp.setNum(zpoolSize) << zOpts << tmpPass;
1076  sysFinalDiskLayout << fileSystem;
1077
1078  fileSystem.clear();
1079  if ( ! checkSSD->isChecked() ) {
1080    fileSystem << targetDisk << targetSlice << "SWAP.eli" << "SWAP.eli" << tmp.setNum(swapsize) << "" << "";
1081    sysFinalDiskLayout << fileSystem;
1082  }
1083
1084  qDebug() <<"AutoLayout:" << sysFinalDiskLayout;
1085}
1086
1087void wizardDisk::generateConfirmationText()
1088{
1089  // If running in expert mode, we just create a simple config / confirmation
1090  if ( radioExpert->isChecked() ) {
1091    QStringList filesystem;
1092    filesystem << "MANUAL" << "/mnt" ;
1093    sysFinalDiskLayout << filesystem;
1094    textConfirmation->setText(tr("Installing to file-system mounted at /mnt"));
1095    return;
1096  }
1097
1098  QList<QStringList> copyList;
1099  QStringList summaryList;
1100  QString tmp, workingDisk, workingSlice, tmpSlice, XtraTmp, startPart, sliceSize;
1101  int disk = 0;
1102
1103  // Copy over the list to a new variable we can mangle without modifying the original
1104  copyList = sysFinalDiskLayout;
1105
1106  // Start our summary
1107  summaryList << "";
1108  summaryList << "<b>" + tr("The disk will be setup with the following configuration:") + "</b>";
1109
1110  while ( ! copyList.empty() )
1111  {
1112    workingDisk = copyList.at(0).at(0);
1113    workingSlice = copyList.at(0).at(1);
1114    tmpSlice = workingSlice;
1115
1116    // Check if this is an install to "Unused Space"
1117    for (int z=0; z < sysDisks.count(); ++z)
1118      if ( sysDisks.at(z).at(0) == "SLICE" \
1119        && sysDisks.at(z).at(2) == workingDisk + workingSlice \
1120        && sysDisks.at(z).at(4) == "Unused Space" )
1121          tmpSlice = "free";
1122
1123    // Check for any mirror for this device
1124    for (int i=0; i < copyList.count(); ++i) {
1125       if ( copyList.at(i).at(2).indexOf("MIRROR(" + workingDisk + ")") != -1 )
1126       {
1127         summaryList << tr("Disk:") + copyList.at(i).at(0) + " " + tr("Mirroring:") + workingDisk;
1128         copyList.removeAt(i);
1129         break;
1130       }
1131    }
1132
1133    // If after doing the mirror, our list is empty, break out
1134    if ( copyList.empty() )
1135      break;
1136   
1137    // If there is a dedicated /boot partition, need to list that first, see what is found
1138    for (int i=0; i < copyList.count(); ++i) {
1139      QStringList mounts = copyList.at(i).at(2).split(",");
1140      for (int z = 0; z < mounts.size(); ++z) {
1141        if ( copyList.at(i).at(0) == workingDisk \
1142          && copyList.at(i).at(1) == workingSlice \
1143          && mounts.at(z) == "/boot" )
1144                startPart="/boot";
1145      }
1146    }
1147
1148    // If no dedicated /boot partition, then lets list "/" first
1149    if(startPart.isEmpty())
1150        startPart="/";
1151
1152    // Start by looking for the root partition
1153    for (int i=0; i < copyList.count(); ++i) {
1154      QStringList mounts = copyList.at(i).at(2).split(",");
1155      for (int z = 0; z < mounts.size(); ++z) {
1156        if ( copyList.at(i).at(0) == workingDisk \
1157          && copyList.at(i).at(1) == workingSlice \
1158          && mounts.at(z) == startPart ) {
1159
1160          // Check if we have any extra arguments to throw on the end
1161          XtraTmp="";
1162          if ( ! copyList.at(i).at(5).isEmpty() )
1163            XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1164
1165          // Write the user summary
1166          summaryList << "";
1167          summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
1168          summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
1169          summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
1170
1171          if ( copyList.at(i).at(3) == "ZFS" || copyList.at(i).at(3) == "ZFS.eli" ) {
1172            QStringList zDS = copyList.at(i).at(2).split(",/");
1173            QString zTMP;
1174            for (int ds = 0; ds < zDS.size(); ++ds) {
1175              if ( zDS.at(ds) != "/" )
1176                zDS.replace(ds, "/" + zDS.at(ds));
1177              if ( zDS.at(ds).indexOf("(") != -1 ) {
1178                zTMP = zDS.at(ds);
1179                zTMP.replace("(", " (");
1180                zDS.replace(ds, zTMP );
1181              }
1182            }
1183            summaryList << tr("ZFS Datasets:<br>") + " " + zDS.join("<br>");
1184          } else {
1185            summaryList << tr("Mount:") + " " + copyList.at(i).at(2);
1186          }
1187          if ( ! XtraTmp.isEmpty() ) {
1188            summaryList << tr("Options:") + " " + copyList.at(i).at(5);
1189          }
1190
1191          // Done with this item, remove it now
1192          copyList.removeAt(i);
1193          break;
1194        }
1195      }
1196    }
1197
1198
1199    // Now look for SWAP
1200    for (int i=0; i < copyList.count(); ++i) {
1201      if ( copyList.at(i).at(0) == workingDisk \
1202        && copyList.at(i).at(1) == workingSlice \
1203        && copyList.at(i).at(2) == "SWAP.eli" ) {
1204
1205        // Write the user summary
1206        summaryList << "";
1207        summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
1208        summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
1209        summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
1210
1211        // Done with this item, remove it now
1212        copyList.removeAt(i);
1213        break;
1214      }
1215    }
1216
1217 
1218    // Now look for any other partitions
1219    int count = copyList.count();
1220    for (int i=0; i < count; ++i) {
1221      if ( copyList.at(i).at(0) == workingDisk \
1222        && copyList.at(i).at(1) == workingSlice ) {
1223
1224        // Check if we have any extra arguments to throw on the end
1225        XtraTmp="";
1226        if ( ! copyList.at(i).at(5).isEmpty() )
1227          XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1228
1229        // If we are working on the last partition, set the size to 0 to use remaining disk
1230        if ( i == (count - 1) ) 
1231                sliceSize = "0";
1232        else
1233                sliceSize=copyList.at(i).at(4);
1234
1235        // Write the user summary
1236        summaryList << "";
1237        summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
1238        summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
1239        summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
1240        summaryList << tr("Mount:") + " " + copyList.at(i).at(2);
1241        if ( ! XtraTmp.isEmpty() ) {
1242          summaryList << tr("Options:") + " " + copyList.at(i).at(5);
1243        }
1244
1245        // Done with this item, remove it now
1246        copyList.removeAt(i);
1247        i--;
1248        count--;
1249      }
1250    }
1251
1252    // Increment our disk counter
1253    disk++;
1254  }
1255
1256  textConfirmation->setText(summaryList.join("<br>"));
1257}
1258
1259void wizardDisk::slotTerminal()
1260{
1261  system("xterm &");
1262}
1263
1264void wizardDisk::setRestoreMode()
1265{
1266  restoreMode=true;
1267}
1268
1269void wizardDisk::slotGPTClicked()
1270{
1271   // Right now we can't do the dirty "gnop" trick on GPT
1272   // Mangles the partitions and fails to boot
1273   if ( checkGPT->isChecked() )
1274   {
1275     checkForce4K->setChecked(false);
1276     checkForce4K->setEnabled(false);
1277   } else {
1278     checkForce4K->setEnabled(true);
1279   }
1280}
Note: See TracBrowser for help on using the repository browser.