source: src-qt4/pc-installgui/installer.cpp @ 5bfd1ee

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2
Last change on this file since 5bfd1ee was 5bfd1ee, checked in by Kris Moore <kris@…>, 12 months ago

When we add a user, make them apart of the vboxusers group

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