source: src-qt4/pc-installgui/installer.cpp @ 0ece806

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2releng/10.0.3releng/10.1
Last change on this file since 0ece806 was 0ece806, checked in by Kris Moore <kris@…>, 16 months ago

Update installer GUI

  • Allow user to specify a SWAP size
  • Allow user to enable / disable stamping GRUB
  • Property mode set to 100644
File size: 50.4 KB
Line 
1#include <QCloseEvent>
2#include <QDir>
3#include <QProcess>
4#include <QTimer>
5#include <QTranslator>
6#include <QInputDialog>
7#include <QGraphicsPixmapItem>
8
9#include "backend.h"
10#include "installer.h"
11#include "helpText.h"
12
13Installer::Installer(QWidget *parent) : QMainWindow(parent)
14{
15    setupUi(this);
16    translator = new QTranslator();
17    haveWarnedSpace=false;
18    force4K = false;
19
20    connect(abortButton, SIGNAL(clicked()), this, SLOT(slotAbort()));
21    connect(backButton, SIGNAL(clicked()), this, SLOT(slotBack()));
22    connect(nextButton, SIGNAL(clicked()), this, SLOT(slotNext()));
23
24    connect(helpButton, SIGNAL(clicked()), this, SLOT(slotHelp()));
25    connect(pushTouchKeyboard, SIGNAL(clicked()), this, SLOT(slotPushVirtKeyboard()));
26    connect(pushChangeKeyLayout, SIGNAL(clicked()), this, SLOT(slotPushKeyLayout()));
27    connect(pushHardware, SIGNAL(clicked()), this, SLOT(slotCheckHardware()));
28    connect(pushLoadConfig, SIGNAL(clicked()), this, SLOT(slotLoadConfigUSB()));
29    connect(pushSaveConfig, SIGNAL(clicked()), this, SLOT(slotSaveConfigUSB()));
30    connect(pushSaveConfig2, SIGNAL(clicked()), this, SLOT(slotSaveConfigUSB()));
31
32    abortButton->setText(tr("&Cancel"));
33    backButton->setText(tr("&Back"));
34    nextButton->setText(tr("&Next"));
35
36    // Init the MBR to yes
37    loadMBR = true;
38    // Init the GPT to no
39    loadGPT = false;
40
41    // No optional components by default
42    fSRC=false;
43    fPORTS=false;
44
45    // Load the keyboard info
46    keyModels = Scripts::Backend::keyModels();
47    keyLayouts = Scripts::Backend::keyLayouts();
48
49    // Set the arch name
50    setArch();
51
52    // Start on the first screen
53    installStackWidget->setCurrentIndex(0);
54    backButton->setVisible(false);
55}
56
57Installer::~Installer()
58{
59    //delete ui;
60}
61
62bool Installer::isInstalled()
63{
64    return false;
65}
66
67void Installer::setArch()
68{
69   QProcess m;
70   m.start(QString("uname"), QStringList() << "-m");
71   while(m.state() == QProcess::Starting || m.state() == QProcess::Running) {
72      m.waitForFinished(200);
73      QCoreApplication::processEvents();
74   }
75
76   // Get output
77   Arch = m.readLine().simplified();
78   qDebug() << Arch;
79}
80
81void Installer::slotCheckHardware()
82{
83  pcHardware = new dialogCheckHardware();
84  pcHardware->programInit();
85  pcHardware->setWindowModality(Qt::ApplicationModal);
86  pcHardware->show();
87  pcHardware->raise();
88}
89
90void Installer::slotPushKeyLayout()
91{
92  wKey = new widgetKeyboard();
93  wKey->programInit(keyModels, keyLayouts);
94  wKey->setWindowModality(Qt::ApplicationModal);
95  wKey->show();
96  wKey->raise();
97}
98
99void Installer::initInstall()
100{
101    // load languages
102    comboLanguage->clear();
103    languages = Scripts::Backend::languages();
104    for (int i=0; i < languages.count(); ++i) {
105        QString languageStr = languages.at(i);
106        QString language = languageStr.split("-").at(0);
107        comboLanguage->addItem(language.trimmed());
108    }
109    connect(comboLanguage, SIGNAL(currentIndexChanged(QString)), this, SLOT(slotChangeLanguage()));
110
111    // Load any package scheme data
112    listDeskPkgs = Scripts::Backend::getPackageData(availDesktopPackageData, QString());
113    listServerPkgs = Scripts::Backend::getPackageData(availServerPackageData, QString("trueos"));
114
115    // Do check for available meta-pkgs on boot media
116    if ( QFile::exists("/tmp/no-meta-pkgs") )
117        hasPkgsOnMedia = false;
118    else
119        hasPkgsOnMedia = true;
120
121    qDebug() << "Package Media:" << availDesktopPackageData << hasPkgsOnMedia;
122
123    // See if this media has a freebsd release on it
124    if ( QFile::exists("/tmp/no-fbsd-release") ) {
125        hasFreeBSDOnMedia = false;
126    } else {
127        hasFreeBSDOnMedia = true;
128    }
129       
130    // Do check for install pkgs on boot media
131    if ( QFile::exists("/tmp/no-install-pkgs") ) {
132        hasInstallOnMedia = false;
133    } else {
134        hasInstallOnMedia = true;
135    }
136
137    // Set the key toggle
138    toggleKeyLayout = true;
139
140    // Is this a LIVE disk?
141    if ( QFile::exists("/usr/pcbsd-live") )
142        isLiveMode = true;
143    else
144        isLiveMode = false;
145
146    // Get available memory
147    systemMemory = Scripts::Backend::systemMemory();
148
149    // Load up the keyboard information
150    //connectKeyboardSlots();
151
152    // Connect the disk slots
153    connect(pushDiskCustomize,SIGNAL(clicked()), this, SLOT(slotDiskCustomizeClicked()));
154
155    // Load the disks
156    loadDiskInfo();
157   
158    // Init the desktop wheel
159    initDesktopSelector();
160}
161
162void Installer::loadDiskInfo()
163{
164   sysDisks = Scripts::Backend::hardDrives();
165   if ( sysDisks.empty() ) {
166      QMessageBox::critical(this, tr("PC-BSD Installer"),
167                                tr("Unable to detect any disk drives! The install will now exit."),
168                                QMessageBox::Ok,
169                                QMessageBox::Ok);
170      exit(1);
171   }
172
173   // For now use the first disk we find
174   if ( ! autoGenPartitionLayout(sysDisks.at(0).at(1), true) )
175   {
176      QMessageBox::critical(this, tr("PC-BSD Installer"),
177        tr("Unable to suggest a partition for the detected disk."),
178        QMessageBox::Ok,
179        QMessageBox::Ok);
180   }
181
182   textEditDiskSummary->clear();
183   QStringList summary = getDiskSummary();
184   for ( int i=0; i < summary.count(); ++i)
185     textEditDiskSummary->append(summary.at(i));
186
187   textEditDiskSummary->moveCursor(QTextCursor::Start);
188
189}
190
191// Function which will auto-generate a partition layout based upon the target disk / slice
192bool Installer::autoGenPartitionLayout(QString target, bool isDisk)
193{
194  QString targetType, tmp;
195  int targetLoc, totalSize = 0, mntsize, swapsize;
196  QString targetDisk, targetSlice, tmpPass, fsType;
197  bool ok;
198  ok = false;
199
200  // Clear out the original disk layout
201  sysFinalDiskLayout.clear();
202  QStringList fileSystem;
203  qDebug() << "Generating disk layout";
204
205
206  if ( isDisk ) {
207    targetType = "DRIVE";
208    targetSlice = "ALL";
209    targetDisk = target;
210    targetLoc = 1;
211  } else {
212    targetType = "SLICE";
213    targetDisk = target;
214    targetDisk.truncate(targetDisk.size() -2);
215    targetSlice = target;
216    targetSlice = targetSlice.remove(0, targetSlice.size() -2);
217    targetLoc = 2;
218  }
219 
220  // Lets get the size for this disk / partition
221  for (int i=0; i < sysDisks.count(); ++i) {
222      // Make sure to only add the slices to the listDiskSlices
223      if ( sysDisks.at(i).at(0) == targetType && target == sysDisks.at(i).at(targetLoc))
224        totalSize = sysDisks.at(i).at(targetLoc + 1).toInt(&ok);
225  }
226
227  // Give us a small buffer for rounding errors
228  totalSize = totalSize - 10;
229
230  // Setup some swap space
231  if ( totalSize > 30000 ) {
232    // 2GB if over 30GB of disk space, 512MB otherwise
233    swapsize = 2048;
234  } else {
235    swapsize = 512;
236  }
237  totalSize = totalSize - swapsize;
238
239  // We got a valid size for this disk / slice, lets generate the layout now
240  if( !ok )
241    return false;
242
243
244  // If on amd64 lets use ZFS, it rox
245  if ( Arch == "amd64" ) {
246    // Add the main zfs pool with standard partitions
247    fsType= "ZFS";
248    fileSystem << targetDisk << targetSlice << "/,/tmp(compress=lzjb),/usr(canmount=off),/usr/home,/usr/jails,/usr/obj(compress=lzjb),/usr/pbi,/usr/ports(compress=gzip),/usr/ports/distfiles(compress=off),/usr/src(compress=gzip),/var(canmount=off),/var/audit(compress=lzjb),/var/log(compress=gzip),/var/tmp(compress=lzjb)" << fsType << tmp.setNum(totalSize) << "" << "";
249    sysFinalDiskLayout << fileSystem;
250    fileSystem.clear();
251   
252    // Now add swap space
253    fileSystem << targetDisk << targetSlice << "SWAP" << "SWAP" << tmp.setNum(swapsize) << "" << "";
254    sysFinalDiskLayout << fileSystem;
255    fileSystem.clear();
256
257    //qDebug() << "Auto-Gen FS:" <<  fileSystem;
258    return true;
259  }
260
261  // Looks like not on amd64, fallback to UFS+SUJ and print a nice
262  // warning for the user explaining they *really* want to be on amd64
263  QMessageBox::warning(this, tr("PC-BSD Installer"),
264      tr("Detected that you are running the 32bit version. If your system is 64bit capable (most systems made after 2005), you really should be running the 64bit version"),
265      QMessageBox::Ok,
266      QMessageBox::Ok);
267
268  // Start the UFS layout now
269  mntsize = 2000;
270  fsType="UFS+SUJ";
271
272  fileSystem << targetDisk << targetSlice << "/" << fsType << tmp.setNum(mntsize) << "" << "";
273  totalSize = totalSize - mntsize;
274  //qDebug() << "Auto-Gen FS:" <<  fileSystem;
275  sysFinalDiskLayout << fileSystem;
276  fileSystem.clear();
277   
278
279  fileSystem << targetDisk << targetSlice << "SWAP" << "SWAP" << tmp.setNum(swapsize) << "" << "";
280  totalSize = totalSize - mntsize;
281  //qDebug() << "Auto-Gen FS:" <<  fileSystem;
282  sysFinalDiskLayout << fileSystem;
283  fileSystem.clear();
284
285  // If less than 3GB, skip /var and leave on /
286  if ( totalSize > 3000 ) {
287    // Figure out the default size for /var if we are on FreeBSD / PC-BSD
288    mntsize = 2048;
289    fileSystem << targetDisk << targetSlice << "/var" << fsType << tmp.setNum(mntsize) << "" << "";
290    totalSize = totalSize - mntsize;
291    //qDebug() << "Auto-Gen FS:" <<  fileSystem;
292    sysFinalDiskLayout << fileSystem;
293    fileSystem.clear();
294  }
295
296  // Now use the rest of the disk / slice for /usr
297  fileSystem << targetDisk << targetSlice << "/usr" << fsType << tmp.setNum(totalSize) << "" << "";
298  //qDebug() << "Auto-Gen FS:" <<  fileSystem;
299  sysFinalDiskLayout << fileSystem;
300  fileSystem.clear();
301
302  return true; 
303 
304}
305
306// Function which returns the pc-sysinstall cfg data
307QStringList Installer::getDiskSummary()
308{
309  QList<QStringList> copyList;
310  QStringList summaryList;
311  QString tmp, workingDisk, workingSlice, tmpSlice, XtraTmp, startPart, sliceSize;
312  int disk = 0;
313
314  // Copy over the list to a new variable we can mangle without modifying the original
315  copyList = sysFinalDiskLayout;
316
317  if ( copyList.at(0).at(0) == "MANUAL" )
318  {
319    summaryList << "";
320    summaryList << tr("Installing to file-system mounted at /mnt");
321    return summaryList;
322  }
323
324  // Start our summary
325  summaryList << "";
326  summaryList << "<b>" + tr("The disk will be setup with the following configuration:") + "</b>";
327
328  while ( ! copyList.empty() )
329  {
330    workingDisk = copyList.at(0).at(0);
331    workingSlice = copyList.at(0).at(1);
332    tmpSlice = workingSlice;
333
334    // Check if this is an install to "Unused Space"
335    for (int z=0; z < sysDisks.count(); ++z)
336      if ( sysDisks.at(z).at(0) == "SLICE" \
337        && sysDisks.at(z).at(2) == workingDisk + workingSlice \
338        && sysDisks.at(z).at(4) == "Unused Space" )
339          tmpSlice = "free";
340
341    // Check for any mirror for this device
342    for (int i=0; i < copyList.count(); ++i) {
343       if ( copyList.at(i).at(2).indexOf("MIRROR(" + workingDisk + ")") != -1 )
344       {
345         summaryList << tr("Disk:") + copyList.at(i).at(0) + " " + tr("Mirroring:") + workingDisk;
346         copyList.removeAt(i);
347         break;
348       }
349    }
350
351    // If after doing the mirror, our list is empty, break out
352    if ( copyList.empty() )
353      break;
354   
355    // If there is a dedicated /boot partition, need to list that first, see what is found
356    for (int i=0; i < copyList.count(); ++i) {
357      QStringList mounts = copyList.at(i).at(2).split(",");
358      for (int z = 0; z < mounts.size(); ++z) {
359        if ( copyList.at(i).at(0) == workingDisk \
360          && copyList.at(i).at(1) == workingSlice \
361          && mounts.at(z) == "/boot" )
362                startPart="/boot";
363      }
364    }
365
366    // If no dedicated /boot partition, then lets list "/" first
367    if(startPart.isEmpty())
368        startPart="/";
369
370    // Start by looking for the root partition
371    for (int i=0; i < copyList.count(); ++i) {
372      QStringList mounts = copyList.at(i).at(2).split(",");
373      for (int z = 0; z < mounts.size(); ++z) {
374        if ( copyList.at(i).at(0) == workingDisk \
375          && copyList.at(i).at(1) == workingSlice \
376          && (mounts.at(z) == startPart || mounts.at(z).contains(startPart + "(") ) ) {
377
378          // Check if we have any extra arguments to throw on the end
379          XtraTmp="";
380          if ( ! copyList.at(i).at(5).isEmpty() )
381            XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
382
383          // Write the user summary
384          summaryList << "";
385          summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
386          summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
387          summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
388          if ( copyList.at(i).at(3) == "ZFS" ) {
389            QStringList zDS = copyList.at(i).at(2).split(",");
390            QString zTMP;
391            for (int ds = 0; ds < zDS.size(); ++ds) {
392              //if ( zDS.at(ds) != "/" )
393               // zDS.replace(ds, "/" + zDS.at(ds));
394              if ( zDS.at(ds).indexOf("(") != -1 ) {
395                zTMP = zDS.at(ds);
396                zTMP.replace("(", " (");
397                zDS.replace(ds, zTMP );
398              }
399            } 
400            summaryList << tr("ZFS Datasets:<br>") + " " + zDS.join("<br>");
401          } else {
402            summaryList << tr("Mount:") + " " + copyList.at(i).at(2);
403          }
404          if ( ! XtraTmp.isEmpty() ) {
405            summaryList << tr("Options:") + " " + copyList.at(i).at(5);
406          }
407
408          // Done with this item, remove it now
409          copyList.removeAt(i);
410          break;
411        }
412      }
413    }
414
415
416    // Now look for SWAP
417    for (int i=0; i < copyList.count(); ++i) {
418      if ( copyList.at(i).at(0) == workingDisk \
419        && copyList.at(i).at(1) == workingSlice \
420        && copyList.at(i).at(2) == "SWAP" ) {
421
422        // Write the user summary
423        summaryList << "";
424        summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
425        summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
426        summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
427
428        // Done with this item, remove it now
429        copyList.removeAt(i);
430        break;
431      }
432    }
433
434 
435    // Now look for any other partitions
436    int count = copyList.count();
437    for (int i=0; i < count; ++i) {
438      if ( copyList.at(i).at(0) == workingDisk \
439        && copyList.at(i).at(1) == workingSlice ) {
440
441        // Check if we have any extra arguments to throw on the end
442        XtraTmp="";
443        if ( ! copyList.at(i).at(5).isEmpty() )
444          XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
445
446        // If we are working on the last partition, set the size to 0 to use remaining disk
447        if ( i == (count - 1) ) 
448                sliceSize = "0";
449        else
450                sliceSize=copyList.at(i).at(4);
451
452        // Write the user summary
453        summaryList << "";
454        summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
455        summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
456        summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
457        if ( copyList.at(i).at(3) != "ZFS" )
458          summaryList << tr("Mount:") + " " + copyList.at(i).at(2);
459        if ( ! XtraTmp.isEmpty() ) {
460          summaryList << tr("Options:") + " " + copyList.at(i).at(5);
461        }
462
463        // Done with this item, remove it now
464        copyList.removeAt(i);
465        i--;
466        count--;
467      }
468    }
469
470    // Increment our disk counter
471    disk++;
472  }
473
474  return summaryList;
475}
476
477void Installer::slotDiskCustomizeClicked()
478{
479  wDisk = new wizardDisk();
480  wDisk->programInit();
481  wDisk->setWindowModality(Qt::ApplicationModal);
482  connect(wDisk, SIGNAL(saved(QList<QStringList>, bool, bool, QString, bool)), this, SLOT(slotSaveDiskChanges(QList<QStringList>, bool, bool, QString, bool)));
483  wDisk->show();
484  wDisk->raise();
485}
486
487void Installer::slotDesktopCustomizeClicked()
488{
489  desks = new desktopSelection();
490  if ( radioDesktop->isChecked() )
491     desks->programInit(listDeskPkgs,selectedPkgs);
492  else
493     desks->programInit(listServerPkgs,selectedPkgs);
494  desks->setWindowModality(Qt::ApplicationModal);
495  customPkgsSet = true;
496  connect(desks, SIGNAL(saved(QStringList)), this, SLOT(slotSaveMetaChanges(QStringList)));
497  desks->show();
498  desks->raise();
499}
500
501void Installer::slotSaveMetaChanges(QStringList sPkgs)
502{
503  selectedPkgs = sPkgs;
504
505  if ( radioDesktop->isChecked() )
506     groupDeskSummary->setTitle(tr("PC-BSD Package Selection"));
507  else
508     groupDeskSummary->setTitle(tr("TrueOS Package Selection"));
509
510  textDeskSummary->setText(tr("The following meta-pkgs will be installed:") + "<br>" + selectedPkgs.join("<br>"));
511}
512
513void Installer::slotSaveDiskChanges(QList<QStringList> newSysDisks, bool MBR, bool GPT, QString zName, bool zForce )
514{
515
516  zpoolName = zName; 
517  force4K = zForce;
518
519  // Save the new disk layout
520  loadMBR = MBR;
521  loadGPT = GPT;
522  sysFinalDiskLayout = newSysDisks;
523  textEditDiskSummary->clear();
524  QStringList summary = getDiskSummary();
525  for ( int i=0; i < summary.count(); ++i)
526    textEditDiskSummary->append(summary.at(i));
527               
528  textEditDiskSummary->moveCursor(QTextCursor::Start);
529 
530  // Regenerate the config
531  startConfigGen();
532}
533
534void Installer::slotChangedMetaPkgSelection()
535{
536
537  selectedPkgs.clear();
538
539  // Set the default desktop meta-pkgs based upon the selection
540  if ( radioDesktop->isChecked() )
541  {
542      selectedPkgs << "KDE" << "KDE-Accessibility" << "KDE-Artwork" << "KDE-Graphics" << "KDE-Multimedia" << "KDE-Network" << "KDE-PIM";
543
544      // Include i18n stuff?
545      if ( comboLanguage->currentIndex() != 0 ) 
546         selectedPkgs << "KDE-L10N";
547
548      // Check if we are using NVIDIA driver and include it automatically
549      QFile file("/etc/X11/xorg.conf");
550      if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
551         
552        QTextStream in(&file);
553        while (!in.atEnd()) {
554           QString line = in.readLine();
555           if ( line.indexOf("nvidia") != -1 ) {
556             selectedPkgs << "NVIDIA";
557             break;
558           }
559        }     
560        file.close();
561      } // Done with NVIDIA check
562
563      // Are we on VirtualBox or VMware?
564      QFile filev("/var/log/Xorg.0.log");
565      if (filev.open(QIODevice::ReadOnly | QIODevice::Text)) {
566         
567        QTextStream inv(&filev);
568        while (!inv.atEnd()) {
569           QString line = inv.readLine();
570           if ( line.indexOf("VirtualBox") != -1 ) {
571             selectedPkgs << "VirtualBoxGuest";
572             break;
573           }
574           if ( line.indexOf("VMware") != -1 ) {
575             selectedPkgs << "VMwareGuest";
576             break;
577           }
578        }     
579        filev.close();
580      } // End of VM checks
581  }
582
583  slotSaveMetaChanges(selectedPkgs);
584  qDebug() << selectedPkgs;
585
586}
587
588void Installer::initDesktopSelector()
589{
590    // Using default pkg sets for now
591    customPkgsSet = false;
592    connect(pushDeskCustomize,SIGNAL(clicked()), this, SLOT(slotDesktopCustomizeClicked()));
593    connect(radioDesktop,SIGNAL(clicked()), this, SLOT(slotChangedMetaPkgSelection()));
594    connect(radioServer,SIGNAL(clicked()), this, SLOT(slotChangedMetaPkgSelection()));
595    slotChangedMetaPkgSelection();
596}
597
598void Installer::proceed(bool forward)
599{
600    int count = installStackWidget->count() - 1;
601    int index = installStackWidget->currentIndex();
602
603    index = forward ?
604            (index == count ? count : index + 1) :
605            (index == 0 ? 0 : index - 1);
606
607    if ( index > 0 && index != 4)
608      backButton->setVisible(true);
609    else
610      backButton->setVisible(false);
611
612    installStackWidget->setCurrentIndex(index);
613}
614
615// Slot which is called when the Finish button is clicked
616void Installer::slotFinished()
617{
618  qApp->quit();
619}
620
621void Installer::slotSaveFBSDSettings(QString rootPW, QString name, QString userName, QString userPW, QString shell, QString hostname, bool ssh, bool src, bool ports, QStringList netSettings)
622{
623  fRootPW = rootPW;
624  fName = name;
625  fUserName = userName;
626  fUserPW = userPW;
627  fShell = shell;
628  fHost = hostname;
629  fSSH = ssh;
630  fSRC = src;
631  fPORTS = ports;
632  fNetSettings = netSettings;
633  installStackWidget->setCurrentIndex(installStackWidget->currentIndex() + 1);
634
635  // Generate the pc-sysinstall config
636  startConfigGen();
637}
638
639void Installer::slotNext()
640{
641   QString tmp;
642
643   // Update package selection in case user changed language, etc
644   if ( installStackWidget->currentIndex() == 0 && hasPkgsOnMedia && !customPkgsSet) {
645     slotChangedMetaPkgSelection();
646   }
647
648   // If no pkgs on media
649   if ( installStackWidget->currentIndex() == 0 && ! hasPkgsOnMedia) {
650     installStackWidget->setCurrentIndex(2);
651     return;
652   }
653
654   // Start the TrueOS wizard
655   if ( radioServer->isChecked() && installStackWidget->currentIndex() == 1 ) { 
656     bool tOS;
657     tOS = true;
658
659     wFBSD = new wizardFreeBSD();
660     wFBSD->setWindowModality(Qt::ApplicationModal);
661     wFBSD->programInit(tOS);
662     connect(wFBSD, SIGNAL(saved(QString, QString, QString, QString, QString, QString, bool, bool, bool, QStringList)), this, SLOT(slotSaveFBSDSettings(QString, QString, QString, QString, QString, QString, bool, bool, bool, QStringList)));
663     wFBSD->show();
664     wFBSD->raise();
665     return ;
666   }
667
668   // Create the pc-sysinstall config
669   if ( installStackWidget->currentIndex() == 1 )
670     startConfigGen();
671
672   // If the chosen disk is too small or partition is invalid, don't continue
673   if ( installStackWidget->currentIndex() == 2 && ! checkDiskRequirements())
674      return;
675
676   if ( installStackWidget->currentIndex() == 2 )
677   {
678      startConfigGen();
679      int ret = QMessageBox::question(this, tr("PC-BSD Installer"),
680                                tr("Start the installation now?"),
681                                QMessageBox::No | QMessageBox::Yes,
682                                QMessageBox::No);
683      switch (ret) {
684      case QMessageBox::Yes:
685          startInstall();
686          break;
687      case QMessageBox::No: // :)
688          return;
689          break;
690      }
691   }
692
693   proceed(true);
694}
695
696void Installer::slotBack()
697{
698   // If no pkgs on media
699   if ( installStackWidget->currentIndex() == 2 && ! hasPkgsOnMedia) {
700        installStackWidget->setCurrentIndex(0);
701        return;
702   }
703
704   proceed(false);
705}
706
707void Installer::slotAbort()
708{
709   close();
710}
711
712void Installer::slotChangeLanguage()
713{
714    if ( comboLanguage->currentIndex() == -1 )
715      return;
716
717    // Figure out the language code
718    QString langCode = languages.at(comboLanguage->currentIndex());
719   
720    // Grab the language code
721    langCode.truncate(langCode.lastIndexOf(")"));
722    langCode.remove(0, langCode.lastIndexOf("(") + 1); 
723
724    // Check what directory our app is in
725    QString appDir;
726    if ( QFile::exists("/usr/local/bin/pc-sysinstaller") )
727      appDir = "/usr/local/share/pcbsd";
728    else
729      appDir = QCoreApplication::applicationDirPath();
730
731    //QTranslator *translator = new QTranslator();
732    qDebug() << "Remove the translator";
733    if ( ! translator->isEmpty() )
734      QCoreApplication::removeTranslator(translator);
735
736    if (translator->load( QString("SysInstaller_") + langCode, appDir + "/i18n/" )) {
737      qDebug() << "Load new Translator" << langCode;
738      QCoreApplication::installTranslator(translator);
739      this->retranslateUi(this);
740    }
741}
742
743void Installer::changeLang(QString code)
744{
745   // Change the language in the combobox with the current running one
746   comboLanguage->disconnect();
747
748   for (int i=0; i < languages.count(); ++i) {
749      if ( languages.at(i).indexOf("(" + code + ")" ) != -1 ) {
750        comboLanguage->setCurrentIndex(i); 
751      }
752   }
753
754   connect(comboLanguage, SIGNAL(currentIndexChanged(QString)), this, SLOT(slotChangeLanguage()));
755}
756
757QStringList Installer::getGlobalCfgSettings()
758{
759
760  QStringList tmpList;
761  QString tmp, upDrive;
762
763  tmpList << "# Auto-Generated pc-sysinstall configuration";
764  tmpList << "installInteractive=no";
765
766  if ( sysFinalDiskLayout.at(0).at(0) == "MANUAL" )
767  {
768    tmpList << "installMode=extract";
769    tmpList << "installLocation=/mnt";
770  } else {
771    // Doing a fresh install
772    tmpList << "installMode=fresh";
773  }
774 
775  QString distFiles;
776  distFiles="base doc games kernel";
777  if ( Arch == "amd64" )
778     distFiles+=" lib32";
779
780  // System type we are installing
781  if ( radioDesktop->isChecked() )
782    tmpList << "installType=PCBSD";
783  else
784    tmpList << "installType=FreeBSD";
785
786  tmpList << "packageType=dist";
787
788  // Set the distFiles being used
789  tmpList << "distFiles=" + distFiles;
790  tmpList << "";
791
792  // If we have a custom hostname, add it to the config
793  if ( ! fHost.isEmpty() )
794    tmpList << "hostname=" + fHost;
795
796  // Using a custom zpool name?
797  if ( ! zpoolName.isEmpty() )
798    tmpList << "zpoolName=" + zpoolName;
799
800  // Are we force enabling ZFS 4K block sizes?
801  if ( force4K )
802    tmpList << "zfsForce4k=YES";
803 
804  // Networking setup
805  if ( radioDesktop->isChecked() ) {
806    // PC-BSD network setup
807    tmpList << "netSaveDev=AUTO-DHCP-SLAAC";
808  } else {
809    // FreeBSD network setup
810    if ( fNetSettings.at(0) == "AUTO-DHCP" )
811      tmpList << "netSaveDev=AUTO-DHCP";
812    else if ( fNetSettings.at(0) == "AUTO-DHCP-SLAAC" ) {
813      tmpList << "netSaveDev=AUTO-DHCP-SLAAC";
814      // We cannot rely on SLAAC to provide DNS for example.  The same is true
815      // for DHCP but the worls seems to have forgotten...
816      tmpList << "netSaveIPv6=" + fNetSettings.at(5);
817      tmpList << "netSaveIPv6NameServer=" + fNetSettings.at(6);
818      tmpList << "netSaveIPv6DefaultRouter=" + fNetSettings.at(7);
819    } else if ( fNetSettings.at(0) == "IPv6-SLAAC" ) {
820       tmpList << "netSaveDev=IPv6-SLAAC";
821      // We cannot rely on SLAAC to provide DNS for example.  The same is true
822      // for DHCP but the worls seems to have forgotten...
823      tmpList << "netSaveIPv6=" + fNetSettings.at(5);
824      tmpList << "netSaveIPv6NameServer=" + fNetSettings.at(6);
825      tmpList << "netSaveIPv6DefaultRouter=" + fNetSettings.at(7);
826    } 
827    else
828    {
829      tmp = fNetSettings.at(0);
830      if ( tmp.indexOf(":") > 0 )
831        tmp.truncate(tmp.indexOf(":"));
832      tmpList << "netSaveDev=" + tmp;
833      tmpList << "netSaveIP_" + tmp + "=" + fNetSettings.at(1); 
834      tmpList << "netSaveMask_" + tmp + "=" + fNetSettings.at(2);
835      tmpList << "netSaveNameServer=" + fNetSettings.at(3);
836      tmpList << "netSaveDefaultRouter=" + fNetSettings.at(4);
837      tmpList << "netSaveIPv6=" + fNetSettings.at(5);
838      tmpList << "netSaveIPv6NameServer=" + fNetSettings.at(6);
839      tmpList << "netSaveIPv6DefaultRouter=" + fNetSettings.at(7);
840    }
841  }
842
843
844  // Doing install from /dist directory
845  tmpList << "installMedium=local"; 
846  tmpList << "localPath=/dist";
847
848  if ( comboLanguage->currentIndex() != 0 ) {
849    QString lang = languages.at(comboLanguage->currentIndex());
850    // Grab the language code
851    lang.truncate(lang.lastIndexOf(")"));
852    lang.remove(0, lang.lastIndexOf("(") + 1);
853    tmpList << "";
854    tmpList << "localizeLang=" + lang;
855  }
856
857  // Setup custom keyboard layouts
858  /* KPM
859  tmpList << "";
860  tmpList << "# Keyboard Layout Options";
861  tmp = comboBoxKeyboardModel->currentText();
862  tmp.truncate(tmp.indexOf(")"));
863  tmp = tmp.remove(0, tmp.indexOf(" (") + 2 );
864  tmpList << "localizeKeyModel=" + tmp;
865
866  tmp = listKbLayouts->currentItem()->text();
867  tmp.truncate(tmp.indexOf(")"));
868  tmp = tmp.remove(0, tmp.indexOf(" (") + 2 );
869  tmpList << "localizeKeyLayout=" + tmp;
870
871  tmp = listKbVariants->currentItem()->text();
872  if ( tmp != "<none>" ) {
873    tmp.truncate(tmp.indexOf(")"));
874    tmp = tmp.remove(0, tmp.indexOf(" (") + 2 );
875    tmpList << "localizeKeyVariant=" + tmp;
876  }
877  */
878
879  tmpList << " ";
880
881  return tmpList;
882}
883
884void Installer::startConfigGen()
885{
886
887  if ( ! haveWarnedSpace )
888     checkSpaceWarning();
889
890  QStringList cfgList;
891
892  // Generate the config file now
893  cfgList+=getGlobalCfgSettings();
894
895  cfgList+=getDiskCfgSettings();
896
897  cfgList+=getComponentCfgSettings();
898
899  // Save the install config script to disk
900  cfgList << "runExtCommand=/root/save-config.sh";
901
902  cfgList+= "";
903
904  // If doing install from package disk
905  if ( hasPkgsOnMedia )
906    cfgList+=getDeskPkgCfg();
907
908  cfgList+= "";
909
910  if ( radioDesktop->isChecked() ) {
911    // Doing PC-BSD Install
912
913    QString lang;
914    if ( comboLanguage->currentIndex() != 0 )
915      lang = languages.at(comboLanguage->currentIndex()).section("(",1,1).section(")",0,0);
916    else
917      lang="en_US";
918
919    // Setup the desktop
920    cfgList << "runCommand=sh /usr/local/share/pcbsd/scripts/sys-init.sh desktop " + lang;
921
922    // Setup for a fresh system first boot
923    cfgList << "# Touch flags to enable PC-BSD setup at first boot";
924    cfgList << "runCommand=touch /var/.runxsetup";
925    cfgList << "runCommand=touch /var/.pcbsd-firstboot";
926    cfgList << "runCommand=touch /var/.pcbsd-firstgui";
927
928  } else {
929    // Doing TrueOS Install
930    cfgList+=getUsersCfgSettings();
931
932    // Enable SSH?
933    if ( fSSH )
934      cfgList << "runCommand=echo 'sshd_enable=\"YES\"' >>/etc/rc.conf";
935
936    // Setup the TrueOS server
937    cfgList << "runCommand=sh /usr/local/share/pcbsd/scripts/sys-init.sh server";
938
939  } 
940
941  // Run newaliases to fix mail errors
942  cfgList << "runCommand=newaliases";
943
944  // Now write out the cfgList to file
945  QFile cfgfile( PCSYSINSTALLCFG );
946  if ( cfgfile.open( QIODevice::WriteOnly ) ) {
947    QTextStream stream( &cfgfile );
948    for ( int i=0; i < cfgList.count(); ++i) {
949      stream <<  cfgList.at(i) << "\n";
950    }
951    cfgfile.close();
952  }
953}
954
955void Installer::slotHelp()
956{
957        pcHelp = new dialogHelp();
958        switch (installStackWidget->currentIndex()) {
959        case 0:
960                pcHelp->dialogInit(HELPTEXT0);
961                break;
962        case 1:
963                pcHelp->dialogInit(HELPTEXT1);
964                break;
965        case 2:
966                pcHelp->dialogInit(HELPTEXT2);
967                break;
968        case 3:
969                pcHelp->dialogInit(HELPTEXT3);
970                break;
971        default:
972                pcHelp->dialogInit("No help text...");
973                break;
974        }
975        pcHelp->show();
976}
977
978// Function which returns the pc-sysinstall cfg data
979QStringList Installer::getDiskCfgSettings()
980{
981  QStringList tmpList;
982  QList<QStringList> copyList;
983  QString tmp, workingDisk, workingSlice, tmpSlice, XtraTmp, startPart, sliceSize;
984  int disk = 0;
985
986  // Copy over the list to a new variable we can mangle without modifying the original
987  copyList = sysFinalDiskLayout;
988
989  // Doing manual extraction
990  if ( copyList.at(0).at(0) == "MANUAL" )
991    return QStringList();
992
993  while ( ! copyList.empty() )
994  {
995    workingDisk = copyList.at(0).at(0);
996    workingSlice = copyList.at(0).at(1);
997    tmpSlice = workingSlice;
998    tmpList << "# Disk Setup for " + workingDisk ;
999
1000    // Check if this is an install to "Unused Space"
1001    for (int z=0; z < sysDisks.count(); ++z)
1002      if ( sysDisks.at(z).at(0) == "SLICE" \
1003        && sysDisks.at(z).at(2) == workingDisk + workingSlice \
1004        && sysDisks.at(z).at(4) == "Unused Space" )
1005          tmpSlice = "free";
1006
1007    tmpList << "disk" + tmp.setNum(disk) + "=" + workingDisk;
1008    tmpList << "partition=" + tmpSlice;
1009
1010    // Are we loading a boot-loader?
1011    if ( loadMBR )
1012      tmpList << "bootManager=GRUB";
1013    else
1014      tmpList << "bootManager=none";
1015
1016    // Set the GPT/MBR options
1017    if ( loadGPT ) 
1018      tmpList << "partscheme=GPT";
1019    else
1020      tmpList << "partscheme=MBR";
1021
1022    tmpList << "commitDiskPart";
1023    tmpList << "";
1024
1025    // If after doing the mirror, our list is empty, break out
1026    if ( copyList.empty() )
1027      break;
1028   
1029    // Now print the partition section for this slice
1030    tmpList << "# Partition Setup for " + workingDisk + "(" + workingSlice + ")";
1031    tmpList << "# All sizes are expressed in MB";
1032    tmpList << "# Avail FS Types, UFS, UFS+S, UFS+SUJ, UFS+J, ZFS, SWAP";
1033    tmpList << "# UFS.eli, UFS+S.eli, UFS+SUJ, UFS+J.eli, ZFS.eli, SWAP.eli";
1034
1035    // If there is a dedicated /boot partition, need to list that first, see what is found
1036    for (int i=0; i < copyList.count(); ++i) {
1037      QStringList mounts = copyList.at(i).at(2).split(",");
1038      for (int z = 0; z < mounts.size(); ++z) {
1039        if ( copyList.at(i).at(0) == workingDisk \
1040          && copyList.at(i).at(1) == workingSlice \
1041          && mounts.at(z) == "/boot" )
1042                startPart="/boot";
1043      }
1044    }
1045
1046    // If no dedicated /boot partition, then lets list "/" first
1047    if(startPart.isEmpty())
1048        startPart="/";
1049
1050    // Start by looking for the root partition
1051    for (int i=0; i < copyList.count(); ++i) {
1052      QStringList mounts = copyList.at(i).at(2).split(",");
1053      for (int z = 0; z < mounts.size(); ++z) {
1054        if ( copyList.at(i).at(0) == workingDisk \
1055          && copyList.at(i).at(1) == workingSlice \
1056          && mounts.at(z) == startPart ) {
1057
1058          // Check if we have any extra arguments to throw on the end
1059          XtraTmp="";
1060          if ( ! copyList.at(i).at(5).isEmpty() )
1061            XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1062
1063          // Write out the partition line
1064          tmpList << "disk" + tmp.setNum(disk) + "-part=" \
1065                   + copyList.at(i).at(3) + " " + copyList.at(i).at(4) \
1066                   + " " + copyList.at(i).at(2) + XtraTmp;
1067
1068          // Check if we have an encryption passphrase to use
1069          if ( ! copyList.at(i).at(6).isEmpty() )
1070            tmpList << "encpass=" + copyList.at(i).at(6);
1071
1072          // Done with this item, remove it now
1073          copyList.removeAt(i);
1074          break;
1075        }
1076      }
1077    }
1078
1079    // Now look for SWAP
1080    for (int i=0; i < copyList.count(); ++i) {
1081      if ( copyList.at(i).at(0) == workingDisk \
1082        && copyList.at(i).at(1) == workingSlice \
1083        && copyList.at(i).at(2) == "SWAP" ) {
1084
1085        // Write the partition line
1086        tmpList << "disk" + tmp.setNum(disk) + "-part=" \
1087                 + copyList.at(i).at(3) + " " + copyList.at(i).at(4) \
1088                 + " none";
1089
1090        // Done with this item, remove it now
1091        copyList.removeAt(i);
1092        break;
1093      }
1094    }
1095 
1096    // Now look for any other partitions
1097    int count = copyList.count();
1098    for (int i=0; i < count; ++i) {
1099      if ( copyList.at(i).at(0) == workingDisk \
1100        && copyList.at(i).at(1) == workingSlice ) {
1101
1102        // Check if we have any extra arguments to throw on the end
1103        XtraTmp="";
1104        if ( ! copyList.at(i).at(5).isEmpty() )
1105          XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1106
1107        // If we are working on the last partition, set the size to 0 to use remaining disk
1108        if ( i == (count - 1) ) 
1109                sliceSize = "0";
1110        else
1111                sliceSize=copyList.at(i).at(4);
1112
1113        // Write the partition line
1114        tmpList << "disk" + tmp.setNum(disk) + "-part=" \
1115                 + copyList.at(i).at(3) + " " + sliceSize \
1116                 + " " + copyList.at(i).at(2) + XtraTmp;
1117
1118        // Check if we have an encryption passphrase to use
1119        if ( ! copyList.at(i).at(6).isEmpty() )
1120          tmpList << "encpass=" + copyList.at(i).at(6);
1121
1122        // Done with this item, remove it now
1123        copyList.removeAt(i);
1124        i--;
1125        count--;
1126      }
1127    }
1128
1129
1130    // Close out this partition section
1131    tmpList << "commitDiskLabel";
1132    tmpList << "";
1133
1134    // Increment our disk counter
1135    disk++;
1136  }
1137
1138  return tmpList;
1139}
1140
1141// Slot which checks any disk requirements before procceding to the next page
1142bool Installer::checkDiskRequirements()
1143{
1144  // For now just return true, the wizard should handle making sure
1145  // the user doesn't shoot themselves in the foot during disk setup
1146  return true;
1147}
1148
1149// Function which begins the backend install, and connects slots to monitor it
1150void Installer::startInstall()
1151{
1152  QString cfgFile;
1153  if (customCfgFile.isEmpty() )
1154    cfgFile = PCSYSINSTALLCFG;
1155  else
1156    cfgFile = customCfgFile;
1157
1158  // Disable the back / next buttons until we are finished
1159  nextButton->setEnabled(false);
1160  backButton->setEnabled(false);
1161  progressBarInstall->setValue(0); 
1162  installFoundCounter = false;
1163  installFoundMetaCounter = false;
1164  installFoundFetchOutput = false;
1165
1166  // Setup some defaults for the secondary progress bar
1167  progressBarInstall2->setValue(0); 
1168  progressBarInstall2->setHidden(true); 
1169  labelInstallStatus2->setText("");
1170  labelInstallStatus2->setHidden(true);
1171
1172  // Kill any hald instances, which causes failures to install when it
1173  // tries to mount our new partitions
1174  QProcess::execute("killall", QStringList() << "hald");
1175
1176  // Start our process to begin the install
1177  QString PCSYSINSTALL;
1178  if ( QFile::exists("/root/pc-sysinstall/pc-sysinstall") ) 
1179     PCSYSINSTALL = "/root/pc-sysinstall/pc-sysinstall";
1180  else 
1181     PCSYSINSTALL = "/usr/local/sbin/pc-sysinstall";
1182
1183  QString program = PCSYSINSTALL;
1184  QStringList arguments;
1185  arguments << "-c" << cfgFile;
1186
1187  installProc = new QProcess();
1188  installProc->setProcessChannelMode(QProcess::MergedChannels);
1189  connect(installProc,SIGNAL(finished( int, QProcess::ExitStatus)),this,SLOT(slotInstallProcFinished( int, QProcess::ExitStatus)));
1190  connect(installProc,SIGNAL(readyRead()),this,SLOT(slotReadInstallerOutput()));
1191  installProc->start(program, arguments);
1192
1193}
1194
1195// Function run when the install failed to prompt user for course of action
1196void Installer::installFailed()
1197{
1198   QString sysLog;
1199   labelInstallStatus->setText(tr("Failed!"));
1200
1201   QMessageBox msgBox;
1202   msgBox.setWindowTitle(tr("PC-BSD Installer"));
1203   msgBox.setIcon(QMessageBox::Critical);
1204   msgBox.setText(tr("The installer has encountered an error and has been halted."));
1205   msgBox.setInformativeText(tr("Do you want to generate an error report?"));
1206   msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1207   msgBox.setDefaultButton(QMessageBox::Yes);
1208
1209   // If we have a log, show it in the detailed view button
1210   if ( QFile::exists("/tmp/.pc-sysinstall/pc-sysinstall.log") )
1211   {
1212     QFile logFile("/tmp/.pc-sysinstall/pc-sysinstall.log");
1213     if (logFile.open(QIODevice::ReadOnly | QIODevice::Text))
1214         while (!logFile.atEnd())
1215           sysLog = sysLog + logFile.readLine() + "\n";
1216     msgBox.setDetailedText(sysLog);
1217   }
1218   int ret = msgBox.exec();
1219
1220   switch (ret) {
1221   case QMessageBox::Yes:
1222       // Generate the error report
1223       Scripts::Backend::createErrorReport();
1224       break;
1225   case QMessageBox::No: // :)
1226       break;
1227   }
1228
1229   QMessageBox msgBox2;
1230   msgBox2.setWindowTitle(tr("PC-BSD Installer"));
1231   msgBox2.setIcon(QMessageBox::Critical);
1232   msgBox2.setText(tr("Restart the system now?") );
1233   msgBox2.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1234   msgBox2.setDefaultButton(QMessageBox::Yes);
1235   msgBox2.setDetailedText(sysLog);
1236
1237   ret = msgBox2.exec();
1238
1239   switch (ret) {
1240   case QMessageBox::Yes:
1241       close();
1242       break;
1243   case QMessageBox::No: // :)
1244       break;
1245   }
1246
1247}
1248
1249// Slot which is called when the installation has finished
1250void Installer::slotInstallProcFinished( int exitCode, QProcess::ExitStatus status)
1251{
1252  QString tmp;
1253  if ( status != QProcess::NormalExit || exitCode != 0 )
1254  {
1255     installFailed();
1256  } else {
1257    // Move to the final page, and show a finish button
1258    proceed(true);
1259    nextButton->setEnabled(true);
1260    nextButton->setText(tr("&Finish"));
1261    nextButton->disconnect();
1262    connect(nextButton, SIGNAL(clicked()), this, SLOT(slotFinished()));
1263    backButton->setEnabled(false);
1264    abortButton->setEnabled(false);
1265  }
1266}
1267
1268// Slot which reads the output of the installer
1269void Installer::slotReadInstallerOutput()
1270{
1271  QString tmp, line;
1272  int range;
1273  bool ok;
1274
1275
1276  while ( installProc->canReadLine() )
1277  {
1278     tmp = installProc->readLine();
1279     tmp.truncate(75);
1280     //qDebug() << tmp;
1281
1282     // If doing a restore, don't bother checking for other values
1283     //if ( radioRestore->isChecked() ) {
1284     //   labelInstallStatus->setText(tmp);
1285     // continue;
1286     //}
1287
1288     // Parse fetch output
1289     if ( installFoundFetchOutput ) {
1290       if ( tmp.indexOf("SIZE: ") != -1 ) {
1291
1292          // Get the total range first
1293          line = tmp;
1294          tmp = tmp.remove(0, tmp.indexOf(":") + 2 );
1295          tmp.truncate(tmp.indexOf(" ")); 
1296          range = tmp.toInt(&ok);
1297          if ( ok )
1298             progressBarInstall->setRange(0, range + 1);
1299
1300          // Now get the current progress
1301          tmp = line;
1302          tmp = tmp.remove(0, tmp.indexOf(":") + 2 );
1303          tmp = tmp.remove(0, tmp.indexOf(":") + 2 );
1304          range = tmp.toInt(&ok);
1305          if ( ok )
1306             progressBarInstall->setValue(range);
1307           
1308          continue;
1309        } else {
1310          installFoundFetchOutput = false;
1311          break;
1312        }
1313     } 
1314
1315     // Unknown point in install
1316     if ( ! installFoundCounter && ! installFoundMetaCounter ) {
1317
1318        // Check if we've found fetch output to update the progress bar with
1319        if ( tmp.indexOf("FETCH: ") != -1 ) {
1320          installFoundFetchOutput = true;
1321          break;
1322        }
1323
1324        if ( tmp.indexOf("INSTALLCOUNT: ") != -1 ) {
1325          tmp = tmp.remove(0, tmp.indexOf(":") + 1 ); 
1326          range = tmp.toInt(&ok);
1327          if ( ok ) {
1328             range = range + 50;
1329             progressBarInstall->setRange(0, range + 1); 
1330             installFoundCounter = true;
1331             if ( availDesktopPackageData )
1332                labelInstallStatus->setText(tr("Extracting system...")); 
1333             else
1334                labelInstallStatus->setText(tr("Installing system... This may take a while...")); 
1335          }
1336
1337          break;
1338
1339        } 
1340
1341        // Check if we are on the meta-pkg installation
1342        if ( tmp.indexOf("Packages to install: ") != -1 ) {
1343          tmp = tmp.remove(0, tmp.indexOf(":") + 1 ); 
1344          range = tmp.toInt(&ok);
1345          if ( ok ) {
1346             progressBarInstall->setRange(0, range + 1); 
1347             progressBarInstall->setValue(0); 
1348             progressBarInstall2->setRange(0, 0); 
1349             labelInstallStatus2->setHidden(false);
1350             progressBarInstall2->setHidden(false); 
1351             installFoundMetaCounter = true;
1352             installFoundCounter = false;
1353             labelInstallStatus->setText(tr("Installing packages... This may take a while...")); 
1354             continue;
1355          }
1356
1357        } 
1358
1359        labelInstallStatus->setText(tmp);
1360        continue; 
1361     } 
1362
1363     // Doing file-extraction still
1364     if ( installFoundCounter ) {
1365
1366       // Doing dist-files, may have multiple images to extract
1367       if ( tmp.indexOf("INSTALLCOUNT: ") != -1 ) {
1368         tmp = tmp.remove(0, tmp.indexOf(":") + 1 ); 
1369         range = tmp.toInt(&ok);
1370         if ( ok ) {
1371            progressBarInstall->setRange(0, range + 1); 
1372            installFoundCounter = true;
1373            if ( availDesktopPackageData )
1374              labelInstallStatus->setText(tr("Extracting system...")); 
1375            else
1376              labelInstallStatus->setText(tr("Installing system... This may take a while...")); 
1377         }
1378         break;
1379       } 
1380
1381
1382       // Increment the progress
1383       progressBarInstall->setValue(progressBarInstall->value() + 1); 
1384
1385       // We've reached the end of this counted section
1386       if ( tmp.indexOf("Extraction Finished") != -1 ) {
1387         installFoundCounter = false;
1388         progressBarInstall->setRange(0, 0); 
1389       }
1390
1391       continue;
1392     }
1393
1394     // Doing meta-pkgs
1395     if ( installFoundMetaCounter ) {
1396        if ( tmp.indexOf("Package installation complete!") != -1 ) {
1397           installFoundMetaCounter = false;
1398           progressBarInstall->setRange(0, 0); 
1399           progressBarInstall2->setHidden(true);
1400           labelInstallStatus2->setHidden(true);
1401           continue;
1402        }
1403
1404        // If we are installing a package, show details to user
1405        if ( tmp.indexOf("Installing") == 0 )
1406          labelInstallStatus2->setText(tmp.section("...", 0, 0));
1407     }
1408
1409  } // end of while loop
1410}
1411
1412// Return list of components to install
1413QStringList Installer::getComponentCfgSettings()
1414{
1415  QStringList componentList, com;
1416  if ( fSRC )
1417    com << "src";
1418  if ( fPORTS )
1419    com << "ports";
1420
1421  if ( ! com.isEmpty() ) {
1422    componentList << "";
1423    componentList << "# Optional Components";
1424    componentList << "installComponents=" + com.join(",");
1425  }
1426
1427  return componentList;
1428}
1429
1430// Start xvkbd
1431void Installer::slotPushVirtKeyboard()
1432{
1433   system("killall -9 xvkbd; xvkbd -compact &");
1434}
1435
1436// Return the configuration for desktop packages
1437QStringList Installer::getDeskPkgCfg()
1438{
1439   QStringList cfgList, pkgList;
1440   QString line;
1441
1442   QList<QStringList> curList;
1443
1444   if ( radioDesktop->isChecked() ) {
1445     curList = listDeskPkgs;
1446     pkgList << "pcbsd-base";
1447   } else {
1448     curList = listServerPkgs;
1449     pkgList << "trueos-base";
1450   }
1451
1452   // Loop though list of pkgs, see what to install
1453   for ( int d=0; d < curList.count(); ++d) {
1454     for ( int i=0; i < selectedPkgs.count(); ++i)
1455        // Is the package selected or the base-system?
1456        if ( curList.at(d).at(0) == selectedPkgs.at(i) || curList.at(d).at(0) == "base-system" ) {
1457
1458           // Yay! Lets get a list of packages to install
1459           QFile mFile;
1460           mFile.setFileName(curList.at(d).at(6));
1461           if ( ! mFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
1462              qDebug() << "Invalid meta-pkg list:" << curList.at(d).at(6);
1463              break;
1464           }
1465 
1466           // Read in the meta pkg list
1467           QTextStream in(&mFile);
1468           while ( !in.atEnd() ) {
1469             line = in.readLine().simplified();
1470             if ( line.isEmpty() )
1471                 continue; 
1472             
1473             pkgList << line.section(":", 0,0);
1474           }
1475           mFile.close();
1476           break;
1477        }
1478   }
1479
1480   cfgList << "installPackages=" + pkgList.join(" ");
1481   return cfgList;
1482}
1483
1484// Return list of users in cfg format
1485QStringList Installer::getUsersCfgSettings()
1486{
1487   QStringList userList;
1488 
1489   userList << "";
1490   userList << "# Root Password";
1491   userList << "rootPass=" + fRootPW;
1492
1493   userList << "";
1494   userList << "# Users";
1495   userList << "userName=" + fUserName;
1496   userList << "userComment=" + fName;
1497   userList << "userPass=" + fUserPW;
1498   userList << "userShell=" + fShell;
1499   userList << "userHome=/home/" + fUserName;
1500   userList << "userGroups=wheel,operator,vboxusers";
1501   userList << "commitUser";
1502   userList << "";
1503 
1504   return userList;
1505}
1506
1507void Installer::closeEvent(QCloseEvent *event)
1508{
1509    int ret = QMessageBox::question(this, tr("PC-BSD Installer"),
1510                                tr("Are you sure you want to abort this installation?"),
1511                                QMessageBox::No | QMessageBox::Yes,
1512                                QMessageBox::No);
1513    switch (ret) {
1514    case QMessageBox::Yes:
1515        //exit the installer :(
1516        break;
1517    case QMessageBox::No: // :)
1518        event->ignore();
1519        break;
1520    }
1521}
1522
1523void Installer::checkSpaceWarning()
1524{
1525  int totalSize = -1;
1526  int targetSize;
1527  int targetLoc;
1528  bool ok;
1529  QString workingDisk = sysFinalDiskLayout.at(0).at(0);
1530  QString workingSlice = sysFinalDiskLayout.at(0).at(1);
1531  QString targetType;
1532  QString target;
1533  //qDebug() << "Disk layout:" << workingDisk << workingSlice;
1534
1535  if ( workingSlice == "ALL" ) {
1536    targetType = "DRIVE";
1537    target = workingDisk;
1538    targetLoc = 1;
1539  } else {
1540    targetType = "SLICE";
1541    target = workingDisk + workingSlice;
1542    targetLoc = 2;
1543  }
1544 
1545  // Lets get the size for this disk / partition
1546  for (int i=0; i < sysDisks.count(); ++i) {
1547      // Make sure to only add the slices to the listDiskSlices
1548      if ( sysDisks.at(i).at(0) == targetType && target == sysDisks.at(i).at(targetLoc))
1549        totalSize = sysDisks.at(i).at(targetLoc + 1).toInt(&ok);
1550  }
1551
1552  //qDebug() << totalSize;
1553
1554  if ( radioServer->isChecked() )
1555     targetSize=20000;
1556  else
1557     targetSize=50000;
1558
1559  int tGB = targetSize / 1000;
1560
1561  qDebug() << totalSize << targetSize;
1562
1563  // Lets print a nice handy warning for users with possible
1564  // low disk space issues
1565  if ( totalSize < targetSize ) {
1566  QMessageBox::warning(this, tr("PC-BSD Installer"),
1567      QString(tr("The selected disk / partition is less than recommended %1GB. The installation may fail...")).arg(tGB),
1568      QMessageBox::Ok,
1569      QMessageBox::Ok);
1570      haveWarnedSpace = true;     
1571  }
1572
1573  return;
1574}
1575
1576void Installer::slotSaveConfigUSB()
1577{
1578  int ret = QMessageBox::question(this, tr("PC-BSD Installer"),
1579           tr("This will save your installation configuration to a MSDOSFS/FAT32 formatted USB stick. Continue?"),
1580           QMessageBox::No | QMessageBox::Yes,
1581           QMessageBox::No);
1582  switch (ret) {
1583  case QMessageBox::Yes:
1584      break;
1585  case QMessageBox::No: // :)
1586      return;
1587      break;
1588  }
1589
1590  // Prompt to insert USB stick
1591  QMessageBox::information(this, tr("PC-BSD Installer"),
1592          tr("Please insert a USB stick now, and click OK to continue."),
1593          QMessageBox::Ok,
1594          QMessageBox::Ok);
1595
1596  // While USB is settling, this is a good time to ask for the config nickname
1597  bool ok;
1598  QString cfgName = QInputDialog::getText(this, tr("PC-BSD Installer"),
1599                 tr("Please enter the nickname you want to save this configuration as."), 
1600                 QLineEdit::Normal,
1601                 QString("default"), &ok);
1602  if (!ok || cfgName.isEmpty())
1603     return;
1604
1605  // Now lets try to save the media
1606  qDebug() << "Running: /root/save-to-usb.sh" << cfgName;
1607  QProcess m;
1608  m.start(QString("/root/save-to-usb.sh"), QStringList() << cfgName);
1609  while(m.state() == QProcess::Starting || m.state() == QProcess::Running) {
1610     m.waitForFinished(200);
1611     QCoreApplication::processEvents();
1612  }
1613
1614  if ( m.exitCode() != 0 ) {
1615     QMessageBox::critical(this, tr("PC-BSD Installer"),
1616          tr("Failed saving config to USB media. Is the device working and formatted MSDOSFS/FAT32?"),
1617          QMessageBox::Ok,
1618          QMessageBox::Ok);
1619
1620  } else {
1621     QMessageBox::information(this, tr("PC-BSD Installer"),
1622          tr("Configuration saved! You may now safely remove the USB media."),
1623          QMessageBox::Ok,
1624          QMessageBox::Ok);
1625  }
1626 
1627}
1628
1629void Installer::slotLoadConfigUSB()
1630{
1631  int ret = QMessageBox::question(this, tr("PC-BSD Installer"),
1632           tr("This will load a installation configuration file your MSDOSFS/FAT32 formatted USB stick. Continue?"),
1633           QMessageBox::No | QMessageBox::Yes,
1634           QMessageBox::No);
1635  switch (ret) {
1636  case QMessageBox::Yes:
1637      break;
1638  case QMessageBox::No: // :)
1639      return;
1640      break;
1641  }
1642
1643  // Prompt to insert USB stick
1644  QMessageBox::information(this, tr("PC-BSD Installer"),
1645          tr("Please insert the USB stick now, and click OK to continue."),
1646          QMessageBox::Ok,
1647          QMessageBox::Ok);
1648
1649  // Now lets try to load the config files
1650  qDebug() << "Running: /root/get-from-usb.sh";
1651  QProcess m;
1652  m.start(QString("/root/get-from-usb.sh"), QStringList());
1653  while(m.state() == QProcess::Starting || m.state() == QProcess::Running) {
1654     m.waitForFinished(200);
1655     QCoreApplication::processEvents();
1656  }
1657
1658  if ( m.exitCode() != 0 ) {
1659     QMessageBox::critical(this, tr("PC-BSD Installer"),
1660          tr("Failed loading saved config file from the USB media. Is the device working and formatted MSDOSFS/FAT32?"),
1661          QMessageBox::Ok,
1662          QMessageBox::Ok);
1663     return;
1664
1665  } else {
1666     QMessageBox::information(this, tr("PC-BSD Installer"),
1667          tr("Configuration loaded! You may now safely remove the USB media."),
1668          QMessageBox::Ok,
1669          QMessageBox::Ok);
1670  }
1671
1672 
1673  // Yay! Now lets prompt the user as to which config to use
1674  QDir cDir;
1675  cDir.setPath("/tmp/pc-sys");
1676  QStringList cfgs = cDir.entryList(QDir::Files);
1677
1678  bool ok;
1679  QString cfgFile = QInputDialog::getItem(this, tr("PC-BSD Installer"),
1680                                       tr("Config File:"), cfgs, 0, false, &ok);
1681  if (!ok || cfgFile.isEmpty())
1682    return;
1683 
1684  ret = QMessageBox::question(this, tr("PC-BSD Installer"),
1685           tr("Start the install using this config file?") + "\n" + cfgFile,
1686           QMessageBox::No | QMessageBox::Yes,
1687           QMessageBox::No);
1688  switch (ret) {
1689  case QMessageBox::Yes:
1690      break;
1691  case QMessageBox::No: // :)
1692      return;
1693      break;
1694  }
1695
1696  // Time to start the installation with our custom config file
1697  qDebug() << cfgFile;
1698  customCfgFile = "/tmp/pc-sys/" + cfgFile;
1699  installStackWidget->setCurrentIndex(3);
1700  startInstall();
1701}
Note: See TracBrowser for help on using the repository browser.