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

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

When installing TrueOS use correct sys type in pc-sysinstall config

  • Property mode set to 100644
File size: 49.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
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  connect(desks, SIGNAL(saved(QStringList)), this, SLOT(slotSaveMetaChanges(QStringList)));
489  desks->show();
490  desks->raise();
491}
492
493void Installer::slotSaveMetaChanges(QStringList sPkgs)
494{
495  selectedPkgs = sPkgs;
496
497  if ( radioDesktop->isChecked() )
498     groupDeskSummary->setTitle(tr("PC-BSD Package Selection"));
499  else
500     groupDeskSummary->setTitle(tr("TrueOS Package Selection"));
501
502  textDeskSummary->setText(tr("The following meta-pkgs will be installed:") + "<br>" + selectedPkgs.join("<br>"));
503}
504
505void Installer::slotSaveDiskChanges(QList<QStringList> newSysDisks, bool MBR, bool GPT)
506{
507  // Save the new disk layout
508  loadMBR = MBR;
509  loadGPT = GPT;
510  sysFinalDiskLayout = newSysDisks;
511  textEditDiskSummary->clear();
512  QStringList summary = getDiskSummary();
513  for ( int i=0; i < summary.count(); ++i)
514    textEditDiskSummary->append(summary.at(i));
515               
516  textEditDiskSummary->moveCursor(QTextCursor::Start);
517 
518  // Regenerate the config
519  startConfigGen();
520}
521
522void Installer::slotChangedMetaPkgSelection()
523{
524
525  selectedPkgs.clear();
526
527  // Set the default desktop meta-pkgs based upon the selection
528  if ( radioDesktop->isChecked() )
529  {
530      selectedPkgs << "KDE" << "KDE-Accessibility" << "KDE-Artwork" << "KDE-Education" << "KDE-Games" << "KDE-Graphics" << "KDE-Multimedia" << "KDE-Network" << "KDE-PIM";
531
532      // Include i18n stuff?
533      if ( comboLanguage->currentIndex() != 0 ) 
534         selectedPkgs << "KDE-L10N";
535
536      // Check if we are using NVIDIA driver and include it automatically
537      QFile file("/etc/X11/xorg.conf");
538      if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
539         
540        QTextStream in(&file);
541        while (!in.atEnd()) {
542           QString line = in.readLine();
543           if ( line.indexOf("nvidia") != -1 ) {
544             selectedPkgs << "NVIDIA";
545             break;
546           }
547        }     
548        file.close();
549      } // Done with NVIDIA check
550
551      // Are we on VirtualBox?
552      QFile filev("/var/log/Xorg.0.log");
553      if (filev.open(QIODevice::ReadOnly | QIODevice::Text)) {
554         
555        QTextStream inv(&filev);
556        while (!inv.atEnd()) {
557           QString line = inv.readLine();
558           if ( line.indexOf("VirtualBox") != -1 ) {
559             selectedPkgs << "VirtualBoxGuest";
560             break;
561           }
562        }     
563        filev.close();
564      } // End of virtualbox check
565  }
566
567  slotSaveMetaChanges(selectedPkgs);
568  qDebug() << selectedPkgs;
569
570}
571
572void Installer::initDesktopSelector()
573{
574    connect(pushDeskCustomize,SIGNAL(clicked()), this, SLOT(slotDesktopCustomizeClicked()));
575    connect(radioDesktop,SIGNAL(clicked()), this, SLOT(slotChangedMetaPkgSelection()));
576    connect(radioServer,SIGNAL(clicked()), this, SLOT(slotChangedMetaPkgSelection()));
577    slotChangedMetaPkgSelection();
578}
579
580void Installer::proceed(bool forward)
581{
582    int count = installStackWidget->count() - 1;
583    int index = installStackWidget->currentIndex();
584
585    index = forward ?
586            (index == count ? count : index + 1) :
587            (index == 0 ? 0 : index - 1);
588
589    if ( index > 0 && index != 4)
590      backButton->setVisible(true);
591    else
592      backButton->setVisible(false);
593
594    installStackWidget->setCurrentIndex(index);
595}
596
597// Slot which is called when the Finish button is clicked
598void Installer::slotFinished()
599{
600  qApp->quit();
601}
602
603void Installer::slotSaveFBSDSettings(QString rootPW, QString name, QString userName, QString userPW, QString shell, QString hostname, bool ssh, bool src, bool ports, QStringList netSettings)
604{
605  fRootPW = rootPW;
606  fName = name;
607  fUserName = userName;
608  fUserPW = userPW;
609  fShell = shell;
610  fHost = hostname;
611  fSSH = ssh;
612  fSRC = src;
613  fPORTS = ports;
614  fNetSettings = netSettings;
615  installStackWidget->setCurrentIndex(installStackWidget->currentIndex() + 1);
616
617  // Generate the pc-sysinstall config
618  startConfigGen();
619}
620
621void Installer::slotNext()
622{
623   QString tmp;
624
625   // If no pkgs on media
626   if ( installStackWidget->currentIndex() == 0 && ! hasPkgsOnMedia) {
627     installStackWidget->setCurrentIndex(2);
628     return;
629   }
630
631   // Start the TrueOS wizard
632   if ( radioServer->isChecked() && installStackWidget->currentIndex() == 1 ) { 
633     bool tOS;
634     tOS = true;
635
636     wFBSD = new wizardFreeBSD();
637     wFBSD->setWindowModality(Qt::ApplicationModal);
638     wFBSD->programInit(tOS);
639     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)));
640     wFBSD->show();
641     wFBSD->raise();
642     return ;
643   }
644
645   // Create the pc-sysinstall config
646   if ( installStackWidget->currentIndex() == 1 )
647     startConfigGen();
648
649   // If the chosen disk is too small or partition is invalid, don't continue
650   if ( installStackWidget->currentIndex() == 2 && ! checkDiskRequirements())
651      return;
652
653   if ( installStackWidget->currentIndex() == 2 )
654   {
655      startConfigGen();
656      int ret = QMessageBox::question(this, tr("PC-BSD Installer"),
657                                tr("Start the installation now?"),
658                                QMessageBox::No | QMessageBox::Yes,
659                                QMessageBox::No);
660      switch (ret) {
661      case QMessageBox::Yes:
662          startInstall();
663          break;
664      case QMessageBox::No: // :)
665          return;
666          break;
667      }
668   }
669
670   proceed(true);
671}
672
673void Installer::slotBack()
674{
675   // If no pkgs on media
676   if ( installStackWidget->currentIndex() == 2 && ! hasPkgsOnMedia) {
677        installStackWidget->setCurrentIndex(0);
678        return;
679   }
680
681   proceed(false);
682}
683
684void Installer::slotAbort()
685{
686   close();
687}
688
689void Installer::slotChangeLanguage()
690{
691    if ( comboLanguage->currentIndex() == -1 )
692      return;
693
694    // Figure out the language code
695    QString langCode = languages.at(comboLanguage->currentIndex());
696   
697    // Grab the language code
698    langCode.truncate(langCode.lastIndexOf(")"));
699    langCode.remove(0, langCode.lastIndexOf("(") + 1); 
700
701    // Check what directory our app is in
702    QString appDir;
703    if ( QFile::exists("/usr/local/bin/pc-sysinstaller") )
704      appDir = "/usr/local/share/pcbsd";
705    else
706      appDir = QCoreApplication::applicationDirPath();
707
708    //QTranslator *translator = new QTranslator();
709    qDebug() << "Remove the translator";
710    if ( ! translator->isEmpty() )
711      QCoreApplication::removeTranslator(translator);
712
713    if (translator->load( QString("SysInstaller_") + langCode, appDir + "/i18n/" )) {
714      qDebug() << "Load new Translator" << langCode;
715      QCoreApplication::installTranslator(translator);
716      this->retranslateUi(this);
717    }
718}
719
720void Installer::changeLang(QString code)
721{
722   // Change the language in the combobox with the current running one
723   comboLanguage->disconnect();
724
725   for (int i=0; i < languages.count(); ++i) {
726      if ( languages.at(i).indexOf("(" + code + ")" ) != -1 ) {
727        comboLanguage->setCurrentIndex(i); 
728      }
729   }
730
731   connect(comboLanguage, SIGNAL(currentIndexChanged(QString)), this, SLOT(slotChangeLanguage()));
732}
733
734QStringList Installer::getGlobalCfgSettings()
735{
736
737  QStringList tmpList;
738  QString tmp, upDrive;
739
740  tmpList << "# Auto-Generated pc-sysinstall configuration";
741  tmpList << "installInteractive=no";
742
743  if ( sysFinalDiskLayout.at(0).at(0) == "MANUAL" )
744  {
745    tmpList << "installMode=extract";
746    tmpList << "installLocation=/mnt";
747  } else {
748    // Doing a fresh install
749    tmpList << "installMode=fresh";
750  }
751 
752  QString distFiles;
753  distFiles="base doc games kernel";
754  if ( Arch == "amd64" )
755     distFiles+=" lib32";
756
757  // System type we are installing
758  if ( radioDesktop->isChecked() )
759    tmpList << "installType=PCBSD";
760  else
761    tmpList << "installType=FreeBSD";
762
763  tmpList << "packageType=dist";
764
765  // Set the distFiles being used
766  tmpList << "distFiles=" + distFiles;
767  tmpList << "";
768
769  // If we have a custom hostname, add it to the config
770  if ( ! fHost.isEmpty() )
771    tmpList << "hostname=" + fHost;
772
773 
774  // Networking setup
775  if ( radioDesktop->isChecked() ) {
776    // PC-BSD network setup
777    tmpList << "netSaveDev=AUTO-DHCP-SLAAC";
778  } else {
779    // FreeBSD network setup
780    if ( fNetSettings.at(0) == "AUTO-DHCP" )
781      tmpList << "netSaveDev=AUTO-DHCP";
782    else if ( fNetSettings.at(0) == "AUTO-DHCP-SLAAC" ) {
783      tmpList << "netSaveDev=AUTO-DHCP-SLAAC";
784      // We cannot rely on SLAAC to provide DNS for example.  The same is true
785      // for DHCP but the worls seems to have forgotten...
786      tmpList << "netSaveIPv6=" + fNetSettings.at(5);
787      tmpList << "netSaveIPv6NameServer=" + fNetSettings.at(6);
788      tmpList << "netSaveIPv6DefaultRouter=" + fNetSettings.at(7);
789    } else if ( fNetSettings.at(0) == "IPv6-SLAAC" ) {
790       tmpList << "netSaveDev=IPv6-SLAAC";
791      // We cannot rely on SLAAC to provide DNS for example.  The same is true
792      // for DHCP but the worls seems to have forgotten...
793      tmpList << "netSaveIPv6=" + fNetSettings.at(5);
794      tmpList << "netSaveIPv6NameServer=" + fNetSettings.at(6);
795      tmpList << "netSaveIPv6DefaultRouter=" + fNetSettings.at(7);
796    } 
797    else
798    {
799      tmp = fNetSettings.at(0);
800      if ( tmp.indexOf(":") > 0 )
801        tmp.truncate(tmp.indexOf(":"));
802      tmpList << "netSaveDev=" + tmp;
803      tmpList << "netSaveIP_" + tmp + "=" + fNetSettings.at(1); 
804      tmpList << "netSaveMask_" + tmp + "=" + fNetSettings.at(2);
805      tmpList << "netSaveNameServer=" + fNetSettings.at(3);
806      tmpList << "netSaveDefaultRouter=" + fNetSettings.at(4);
807      tmpList << "netSaveIPv6=" + fNetSettings.at(5);
808      tmpList << "netSaveIPv6NameServer=" + fNetSettings.at(6);
809      tmpList << "netSaveIPv6DefaultRouter=" + fNetSettings.at(7);
810    }
811  }
812
813
814  // Doing install from /dist directory
815  tmpList << "installMedium=local"; 
816  tmpList << "localPath=/dist";
817
818  if ( comboLanguage->currentIndex() != 0 ) {
819    QString lang = languages.at(comboLanguage->currentIndex());
820    // Grab the language code
821    lang.truncate(lang.lastIndexOf(")"));
822    lang.remove(0, lang.lastIndexOf("(") + 1);
823    tmpList << "";
824    tmpList << "localizeLang=" + lang;
825  }
826
827  // Setup custom keyboard layouts
828  /* KPM
829  tmpList << "";
830  tmpList << "# Keyboard Layout Options";
831  tmp = comboBoxKeyboardModel->currentText();
832  tmp.truncate(tmp.indexOf(")"));
833  tmp = tmp.remove(0, tmp.indexOf(" (") + 2 );
834  tmpList << "localizeKeyModel=" + tmp;
835
836  tmp = listKbLayouts->currentItem()->text();
837  tmp.truncate(tmp.indexOf(")"));
838  tmp = tmp.remove(0, tmp.indexOf(" (") + 2 );
839  tmpList << "localizeKeyLayout=" + tmp;
840
841  tmp = listKbVariants->currentItem()->text();
842  if ( tmp != "<none>" ) {
843    tmp.truncate(tmp.indexOf(")"));
844    tmp = tmp.remove(0, tmp.indexOf(" (") + 2 );
845    tmpList << "localizeKeyVariant=" + tmp;
846  }
847  */
848
849  tmpList << " ";
850
851  return tmpList;
852}
853
854void Installer::startConfigGen()
855{
856
857  if ( ! haveWarnedSpace )
858     checkSpaceWarning();
859
860  QStringList cfgList;
861
862  // Generate the config file now
863  cfgList+=getGlobalCfgSettings();
864
865  cfgList+=getDiskCfgSettings();
866
867  cfgList+=getComponentCfgSettings();
868
869  // Save the install config script to disk
870  cfgList << "runExtCommand=/root/save-config.sh";
871
872  cfgList+= "";
873
874  // If doing install from package disk
875  if ( hasPkgsOnMedia )
876    cfgList+=getDeskPkgCfg();
877
878  cfgList+= "";
879
880  if ( radioDesktop->isChecked() ) {
881    // Doing PC-BSD Install
882
883    QString lang;
884    if ( comboLanguage->currentIndex() != 0 )
885      lang = languages.at(comboLanguage->currentIndex());
886    else
887      lang="en_US";
888
889    // Setup the desktop
890    cfgList << "runCommand=sh /usr/local/share/pcbsd/scripts/sys-init.sh desktop " + lang;
891
892    // Setup for a fresh system first boot
893    cfgList << "# Touch flags to enable PC-BSD setup at first boot";
894    cfgList << "runCommand=touch /var/.runxsetup";
895    cfgList << "runCommand=touch /var/.pcbsd-firstboot";
896    cfgList << "runCommand=touch /var/.pcbsd-firstgui";
897
898  } else {
899    // Doing TrueOS Install
900    cfgList+=getUsersCfgSettings();
901
902    // Enable SSH?
903    if ( fSSH )
904      cfgList << "runCommand=echo 'sshd_enable=\"YES\"' >>/etc/rc.conf";
905
906    // Setup the TrueOS server
907    cfgList << "runCommand=sh /usr/local/share/pcbsd/scripts/sys-init.sh server";
908
909  } 
910
911  // Run newaliases to fix mail errors
912  cfgList << "runCommand=newaliases";
913
914  // Now write out the cfgList to file
915  QFile cfgfile( PCSYSINSTALLCFG );
916  if ( cfgfile.open( QIODevice::WriteOnly ) ) {
917    QTextStream stream( &cfgfile );
918    for ( int i=0; i < cfgList.count(); ++i) {
919      stream <<  cfgList.at(i) << "\n";
920    }
921    cfgfile.close();
922  }
923}
924
925void Installer::slotHelp()
926{
927        pcHelp = new dialogHelp();
928        switch (installStackWidget->currentIndex()) {
929        case 0:
930                pcHelp->dialogInit(HELPTEXT0);
931                break;
932        case 1:
933                pcHelp->dialogInit(HELPTEXT1);
934                break;
935        case 2:
936                pcHelp->dialogInit(HELPTEXT2);
937                break;
938        case 3:
939                pcHelp->dialogInit(HELPTEXT3);
940                break;
941        default:
942                pcHelp->dialogInit("No help text...");
943                break;
944        }
945        pcHelp->show();
946}
947
948// Function which returns the pc-sysinstall cfg data
949QStringList Installer::getDiskCfgSettings()
950{
951  QStringList tmpList;
952  QList<QStringList> copyList;
953  QString tmp, workingDisk, workingSlice, tmpSlice, XtraTmp, startPart, sliceSize;
954  int disk = 0;
955
956  // Copy over the list to a new variable we can mangle without modifying the original
957  copyList = sysFinalDiskLayout;
958
959  // Doing manual extraction
960  if ( copyList.at(0).at(0) == "MANUAL" )
961    return QStringList();
962
963  while ( ! copyList.empty() )
964  {
965    workingDisk = copyList.at(0).at(0);
966    workingSlice = copyList.at(0).at(1);
967    tmpSlice = workingSlice;
968    tmpList << "# Disk Setup for " + workingDisk ;
969
970    // Check if this is an install to "Unused Space"
971    for (int z=0; z < sysDisks.count(); ++z)
972      if ( sysDisks.at(z).at(0) == "SLICE" \
973        && sysDisks.at(z).at(2) == workingDisk + workingSlice \
974        && sysDisks.at(z).at(4) == "Unused Space" )
975          tmpSlice = "free";
976
977    tmpList << "disk" + tmp.setNum(disk) + "=" + workingDisk;
978    tmpList << "partition=" + tmpSlice;
979
980    // Are we loading a boot-loader?
981    if ( loadMBR )
982      tmpList << "bootManager=GRUB";
983    else
984      tmpList << "bootManager=none";
985
986    // Set the GPT/MBR options
987    if ( loadGPT ) 
988      tmpList << "partscheme=GPT";
989    else
990      tmpList << "partscheme=MBR";
991
992    tmpList << "commitDiskPart";
993    tmpList << "";
994
995    // If after doing the mirror, our list is empty, break out
996    if ( copyList.empty() )
997      break;
998   
999    // Now print the partition section for this slice
1000    tmpList << "# Partition Setup for " + workingDisk + "(" + workingSlice + ")";
1001    tmpList << "# All sizes are expressed in MB";
1002    tmpList << "# Avail FS Types, UFS, UFS+S, UFS+SUJ, UFS+J, ZFS, SWAP";
1003    tmpList << "# UFS.eli, UFS+S.eli, UFS+SUJ, UFS+J.eli, ZFS.eli, SWAP.eli";
1004
1005    // If there is a dedicated /boot partition, need to list that first, see what is found
1006    for (int i=0; i < copyList.count(); ++i) {
1007      QStringList mounts = copyList.at(i).at(2).split(",");
1008      for (int z = 0; z < mounts.size(); ++z) {
1009        if ( copyList.at(i).at(0) == workingDisk \
1010          && copyList.at(i).at(1) == workingSlice \
1011          && mounts.at(z) == "/boot" )
1012                startPart="/boot";
1013      }
1014    }
1015
1016    // If no dedicated /boot partition, then lets list "/" first
1017    if(startPart.isEmpty())
1018        startPart="/";
1019
1020    // Start by looking for the root partition
1021    for (int i=0; i < copyList.count(); ++i) {
1022      QStringList mounts = copyList.at(i).at(2).split(",");
1023      for (int z = 0; z < mounts.size(); ++z) {
1024        if ( copyList.at(i).at(0) == workingDisk \
1025          && copyList.at(i).at(1) == workingSlice \
1026          && mounts.at(z) == startPart ) {
1027
1028          // Check if we have any extra arguments to throw on the end
1029          XtraTmp="";
1030          if ( ! copyList.at(i).at(5).isEmpty() )
1031            XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1032
1033          // Write out the partition line
1034          tmpList << "disk" + tmp.setNum(disk) + "-part=" \
1035                   + copyList.at(i).at(3) + " " + copyList.at(i).at(4) \
1036                   + " " + copyList.at(i).at(2) + XtraTmp;
1037
1038          // Check if we have an encryption passphrase to use
1039          if ( ! copyList.at(i).at(6).isEmpty() )
1040            tmpList << "encpass=" + copyList.at(i).at(6);
1041
1042          // Done with this item, remove it now
1043          copyList.removeAt(i);
1044          break;
1045        }
1046      }
1047    }
1048
1049    // Now look for SWAP
1050    for (int i=0; i < copyList.count(); ++i) {
1051      if ( copyList.at(i).at(0) == workingDisk \
1052        && copyList.at(i).at(1) == workingSlice \
1053        && copyList.at(i).at(2) == "SWAP" ) {
1054
1055        // Write the partition line
1056        tmpList << "disk" + tmp.setNum(disk) + "-part=" \
1057                 + copyList.at(i).at(3) + " " + copyList.at(i).at(4) \
1058                 + " none";
1059
1060        // Done with this item, remove it now
1061        copyList.removeAt(i);
1062        break;
1063      }
1064    }
1065 
1066    // Now look for any other partitions
1067    int count = copyList.count();
1068    for (int i=0; i < count; ++i) {
1069      if ( copyList.at(i).at(0) == workingDisk \
1070        && copyList.at(i).at(1) == workingSlice ) {
1071
1072        // Check if we have any extra arguments to throw on the end
1073        XtraTmp="";
1074        if ( ! copyList.at(i).at(5).isEmpty() )
1075          XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1076
1077        // If we are working on the last partition, set the size to 0 to use remaining disk
1078        if ( i == (count - 1) ) 
1079                sliceSize = "0";
1080        else
1081                sliceSize=copyList.at(i).at(4);
1082
1083        // Write the partition line
1084        tmpList << "disk" + tmp.setNum(disk) + "-part=" \
1085                 + copyList.at(i).at(3) + " " + sliceSize \
1086                 + " " + copyList.at(i).at(2) + XtraTmp;
1087
1088        // Check if we have an encryption passphrase to use
1089        if ( ! copyList.at(i).at(6).isEmpty() )
1090          tmpList << "encpass=" + copyList.at(i).at(6);
1091
1092        // Done with this item, remove it now
1093        copyList.removeAt(i);
1094        i--;
1095        count--;
1096      }
1097    }
1098
1099
1100    // Close out this partition section
1101    tmpList << "commitDiskLabel";
1102    tmpList << "";
1103
1104    // Increment our disk counter
1105    disk++;
1106  }
1107
1108  return tmpList;
1109}
1110
1111// Slot which checks any disk requirements before procceding to the next page
1112bool Installer::checkDiskRequirements()
1113{
1114  // For now just return true, the wizard should handle making sure
1115  // the user doesn't shoot themselves in the foot during disk setup
1116  return true;
1117}
1118
1119// Function which begins the backend install, and connects slots to monitor it
1120void Installer::startInstall()
1121{
1122  QString cfgFile;
1123  if (customCfgFile.isEmpty() )
1124    cfgFile = PCSYSINSTALLCFG;
1125  else
1126    cfgFile = customCfgFile;
1127
1128  // Disable the back / next buttons until we are finished
1129  nextButton->setEnabled(false);
1130  backButton->setEnabled(false);
1131  progressBarInstall->setValue(0); 
1132  installFoundCounter = false;
1133  installFoundMetaCounter = false;
1134  installFoundFetchOutput = false;
1135
1136  // Setup some defaults for the secondary progress bar
1137  progressBarInstall2->setValue(0); 
1138  progressBarInstall2->setHidden(true); 
1139  labelInstallStatus2->setText("");
1140  labelInstallStatus2->setHidden(true);
1141
1142  // Kill any hald instances, which causes failures to install when it
1143  // tries to mount our new partitions
1144  QProcess::execute("killall", QStringList() << "hald");
1145
1146  // Start our process to begin the install
1147  QString PCSYSINSTALL;
1148  if ( QFile::exists("/root/pc-sysinstall/pc-sysinstall") ) 
1149     PCSYSINSTALL = "/root/pc-sysinstall/pc-sysinstall";
1150  else 
1151     PCSYSINSTALL = "/usr/local/sbin/pc-sysinstall";
1152
1153  QString program = PCSYSINSTALL;
1154  QStringList arguments;
1155  arguments << "-c" << cfgFile;
1156
1157  installProc = new QProcess();
1158  installProc->setProcessChannelMode(QProcess::MergedChannels);
1159  connect(installProc,SIGNAL(finished( int, QProcess::ExitStatus)),this,SLOT(slotInstallProcFinished( int, QProcess::ExitStatus)));
1160  connect(installProc,SIGNAL(readyRead()),this,SLOT(slotReadInstallerOutput()));
1161  installProc->start(program, arguments);
1162
1163}
1164
1165// Function run when the install failed to prompt user for course of action
1166void Installer::installFailed()
1167{
1168   QString sysLog;
1169   labelInstallStatus->setText(tr("Failed!"));
1170
1171   QMessageBox msgBox;
1172   msgBox.setWindowTitle(tr("PC-BSD Installer"));
1173   msgBox.setIcon(QMessageBox::Critical);
1174   msgBox.setText(tr("The installer has encountered an error and has been halted."));
1175   msgBox.setInformativeText(tr("Do you want to generate an error report?"));
1176   msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1177   msgBox.setDefaultButton(QMessageBox::Yes);
1178
1179   // If we have a log, show it in the detailed view button
1180   if ( QFile::exists("/tmp/.pc-sysinstall/pc-sysinstall.log") )
1181   {
1182     QFile logFile("/tmp/.pc-sysinstall/pc-sysinstall.log");
1183     if (logFile.open(QIODevice::ReadOnly | QIODevice::Text))
1184         while (!logFile.atEnd())
1185           sysLog = sysLog + logFile.readLine() + "\n";
1186     msgBox.setDetailedText(sysLog);
1187   }
1188   int ret = msgBox.exec();
1189
1190   switch (ret) {
1191   case QMessageBox::Yes:
1192       // Generate the error report
1193       Scripts::Backend::createErrorReport();
1194       break;
1195   case QMessageBox::No: // :)
1196       break;
1197   }
1198
1199   QMessageBox msgBox2;
1200   msgBox2.setWindowTitle(tr("PC-BSD Installer"));
1201   msgBox2.setIcon(QMessageBox::Critical);
1202   msgBox2.setText(tr("Restart the system now?") );
1203   msgBox2.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1204   msgBox2.setDefaultButton(QMessageBox::Yes);
1205   msgBox2.setDetailedText(sysLog);
1206
1207   ret = msgBox2.exec();
1208
1209   switch (ret) {
1210   case QMessageBox::Yes:
1211       close();
1212       break;
1213   case QMessageBox::No: // :)
1214       break;
1215   }
1216
1217}
1218
1219// Slot which is called when the installation has finished
1220void Installer::slotInstallProcFinished( int exitCode, QProcess::ExitStatus status)
1221{
1222  QString tmp;
1223  if ( status != QProcess::NormalExit || exitCode != 0 )
1224  {
1225     installFailed();
1226  } else {
1227    // Move to the final page, and show a finish button
1228    proceed(true);
1229    nextButton->setEnabled(true);
1230    nextButton->setText(tr("&Finish"));
1231    nextButton->disconnect();
1232    connect(nextButton, SIGNAL(clicked()), this, SLOT(slotFinished()));
1233    backButton->setEnabled(false);
1234    abortButton->setEnabled(false);
1235  }
1236}
1237
1238// Slot which reads the output of the installer
1239void Installer::slotReadInstallerOutput()
1240{
1241  QString tmp, line;
1242  int range;
1243  bool ok;
1244
1245
1246  while ( installProc->canReadLine() )
1247  {
1248     tmp = installProc->readLine();
1249     tmp.truncate(75);
1250     //qDebug() << tmp;
1251
1252     // If doing a restore, don't bother checking for other values
1253     //if ( radioRestore->isChecked() ) {
1254     //   labelInstallStatus->setText(tmp);
1255     // continue;
1256     //}
1257
1258     // Parse fetch output
1259     if ( installFoundFetchOutput ) {
1260       if ( tmp.indexOf("SIZE: ") != -1 ) {
1261
1262          // Get the total range first
1263          line = tmp;
1264          tmp = tmp.remove(0, tmp.indexOf(":") + 2 );
1265          tmp.truncate(tmp.indexOf(" ")); 
1266          range = tmp.toInt(&ok);
1267          if ( ok )
1268             progressBarInstall->setRange(0, range + 1);
1269
1270          // Now get the current progress
1271          tmp = line;
1272          tmp = tmp.remove(0, tmp.indexOf(":") + 2 );
1273          tmp = tmp.remove(0, tmp.indexOf(":") + 2 );
1274          range = tmp.toInt(&ok);
1275          if ( ok )
1276             progressBarInstall->setValue(range);
1277           
1278          continue;
1279        } else {
1280          installFoundFetchOutput = false;
1281          break;
1282        }
1283     } 
1284
1285     // Unknown point in install
1286     if ( ! installFoundCounter && ! installFoundMetaCounter ) {
1287
1288        // Check if we've found fetch output to update the progress bar with
1289        if ( tmp.indexOf("FETCH: ") != -1 ) {
1290          installFoundFetchOutput = true;
1291          break;
1292        }
1293
1294        if ( tmp.indexOf("INSTALLCOUNT: ") != -1 ) {
1295          tmp = tmp.remove(0, tmp.indexOf(":") + 1 ); 
1296          range = tmp.toInt(&ok);
1297          if ( ok ) {
1298             range = range + 50;
1299             progressBarInstall->setRange(0, range + 1); 
1300             installFoundCounter = true;
1301             if ( availDesktopPackageData )
1302                labelInstallStatus->setText(tr("Extracting system...")); 
1303             else
1304                labelInstallStatus->setText(tr("Installing system... This may take a while...")); 
1305          }
1306
1307          break;
1308
1309        } 
1310
1311        // Check if we are on the meta-pkg installation
1312        if ( tmp.indexOf("Packages to install: ") != -1 ) {
1313          tmp = tmp.remove(0, tmp.indexOf(":") + 1 ); 
1314          range = tmp.toInt(&ok);
1315          if ( ok ) {
1316             progressBarInstall->setRange(0, range + 1); 
1317             progressBarInstall->setValue(0); 
1318             progressBarInstall2->setRange(0, 0); 
1319             labelInstallStatus2->setHidden(false);
1320             progressBarInstall2->setHidden(false); 
1321             installFoundMetaCounter = true;
1322             installFoundCounter = false;
1323             labelInstallStatus->setText(tr("Installing packages... This may take a while...")); 
1324             continue;
1325          }
1326
1327        } 
1328
1329        labelInstallStatus->setText(tmp);
1330        continue; 
1331     } 
1332
1333     // Doing file-extraction still
1334     if ( installFoundCounter ) {
1335
1336       // Doing dist-files, may have multiple images to extract
1337       if ( tmp.indexOf("INSTALLCOUNT: ") != -1 ) {
1338         tmp = tmp.remove(0, tmp.indexOf(":") + 1 ); 
1339         range = tmp.toInt(&ok);
1340         if ( ok ) {
1341            progressBarInstall->setRange(0, range + 1); 
1342            installFoundCounter = true;
1343            if ( availDesktopPackageData )
1344              labelInstallStatus->setText(tr("Extracting system...")); 
1345            else
1346              labelInstallStatus->setText(tr("Installing system... This may take a while...")); 
1347         }
1348         break;
1349       } 
1350
1351
1352       // Increment the progress
1353       progressBarInstall->setValue(progressBarInstall->value() + 1); 
1354
1355       // We've reached the end of this counted section
1356       if ( tmp.indexOf("Extraction Finished") != -1 ) {
1357         installFoundCounter = false;
1358         progressBarInstall->setRange(0, 0); 
1359       }
1360
1361       continue;
1362     }
1363
1364     // Doing meta-pkgs
1365     if ( installFoundMetaCounter ) {
1366        if ( tmp.indexOf("Package installation complete!") != -1 ) {
1367           installFoundMetaCounter = false;
1368           progressBarInstall->setRange(0, 0); 
1369           progressBarInstall2->setHidden(true);
1370           labelInstallStatus2->setHidden(true);
1371           continue;
1372        }
1373
1374        // If we are installing a package, show details to user
1375        if ( tmp.indexOf("Installing") == 0 )
1376          labelInstallStatus2->setText(tmp.section("...", 0, 0));
1377     }
1378
1379  } // end of while loop
1380}
1381
1382// Return list of components to install
1383QStringList Installer::getComponentCfgSettings()
1384{
1385  QStringList componentList, com;
1386  if ( fSRC )
1387    com << "src";
1388  if ( fPORTS )
1389    com << "ports";
1390
1391  if ( ! com.isEmpty() ) {
1392    componentList << "";
1393    componentList << "# Optional Components";
1394    componentList << "installComponents=" + com.join(",");
1395  }
1396
1397  return componentList;
1398}
1399
1400// Start xvkbd
1401void Installer::slotPushVirtKeyboard()
1402{
1403   system("killall -9 xvkbd; xvkbd -compact &");
1404}
1405
1406// Return the configuration for desktop packages
1407QStringList Installer::getDeskPkgCfg()
1408{
1409   QStringList cfgList, pkgList;
1410   QString line;
1411
1412   QList<QStringList> curList;
1413
1414   if ( radioDesktop->isChecked() ) {
1415     curList = listDeskPkgs;
1416     pkgList << "pcbsd-base";
1417   } else {
1418     curList = listServerPkgs;
1419     pkgList << "trueos-base";
1420   }
1421
1422   // Loop though list of pkgs, see what to install
1423   for ( int d=0; d < curList.count(); ++d) {
1424     for ( int i=0; i < selectedPkgs.count(); ++i)
1425        // Is the package selected or the base-system?
1426        if ( curList.at(d).at(0) == selectedPkgs.at(i) || curList.at(d).at(0) == "base-system" ) {
1427
1428           // Yay! Lets get a list of packages to install
1429           QFile mFile;
1430           mFile.setFileName(curList.at(d).at(6));
1431           if ( ! mFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
1432              qDebug() << "Invalid meta-pkg list:" << curList.at(d).at(6);
1433              break;
1434           }
1435 
1436           // Read in the meta pkg list
1437           QTextStream in(&mFile);
1438           while ( !in.atEnd() ) {
1439             line = in.readLine().simplified();
1440             if ( line.isEmpty() )
1441                 continue; 
1442             
1443             pkgList << line.section(":", 0,0);
1444           }
1445           mFile.close();
1446           break;
1447        }
1448   }
1449
1450   cfgList << "installPackages=" + pkgList.join(" ");
1451   return cfgList;
1452}
1453
1454// Return list of users in cfg format
1455QStringList Installer::getUsersCfgSettings()
1456{
1457   QStringList userList;
1458 
1459   userList << "";
1460   userList << "# Root Password";
1461   userList << "rootPass=" + fRootPW;
1462
1463   userList << "";
1464   userList << "# Users";
1465   userList << "userName=" + fUserName;
1466   userList << "userComment=" + fName;
1467   userList << "userPass=" + fUserPW;
1468   userList << "userShell=" + fShell;
1469   userList << "userHome=/home/" + fUserName;
1470   userList << "userGroups=wheel,operator";
1471   userList << "commitUser";
1472   userList << "";
1473 
1474   return userList;
1475}
1476
1477void Installer::closeEvent(QCloseEvent *event)
1478{
1479    int ret = QMessageBox::question(this, tr("PC-BSD Installer"),
1480                                tr("Are you sure you want to abort this installation?"),
1481                                QMessageBox::No | QMessageBox::Yes,
1482                                QMessageBox::No);
1483    switch (ret) {
1484    case QMessageBox::Yes:
1485        //exit the installer :(
1486        break;
1487    case QMessageBox::No: // :)
1488        event->ignore();
1489        break;
1490    }
1491}
1492
1493void Installer::checkSpaceWarning()
1494{
1495  int totalSize = -1;
1496  int targetSize;
1497  int targetLoc;
1498  bool ok;
1499  QString workingDisk = sysFinalDiskLayout.at(0).at(0);
1500  QString workingSlice = sysFinalDiskLayout.at(0).at(1);
1501  QString targetType;
1502  QString target;
1503  //qDebug() << "Disk layout:" << workingDisk << workingSlice;
1504
1505  if ( workingSlice == "ALL" ) {
1506    targetType = "DRIVE";
1507    target = workingDisk;
1508    targetLoc = 1;
1509  } else {
1510    targetType = "SLICE";
1511    target = workingDisk + workingSlice;
1512    targetLoc = 2;
1513  }
1514 
1515  // Lets get the size for this disk / partition
1516  for (int i=0; i < sysDisks.count(); ++i) {
1517      // Make sure to only add the slices to the listDiskSlices
1518      if ( sysDisks.at(i).at(0) == targetType && target == sysDisks.at(i).at(targetLoc))
1519        totalSize = sysDisks.at(i).at(targetLoc + 1).toInt(&ok);
1520  }
1521
1522  //qDebug() << totalSize;
1523
1524  if ( radioServer->isChecked() )
1525     targetSize=20000;
1526  else
1527     targetSize=50000;
1528
1529  int tGB = targetSize / 1000;
1530
1531  qDebug() << totalSize << targetSize;
1532
1533  // Lets print a nice handy warning for users with possible
1534  // low disk space issues
1535  if ( totalSize < targetSize ) {
1536  QMessageBox::warning(this, tr("PC-BSD Installer"),
1537      QString(tr("The selected disk / partition is less than recommended %1GB. The installation may fail...")).arg(tGB),
1538      QMessageBox::Ok,
1539      QMessageBox::Ok);
1540      haveWarnedSpace = true;     
1541  }
1542
1543  return;
1544}
1545
1546void Installer::slotSaveConfigUSB()
1547{
1548  int ret = QMessageBox::question(this, tr("PC-BSD Installer"),
1549           tr("This will save your installation configuration to a MSDOSFS/FAT32 formatted USB stick. Continue?"),
1550           QMessageBox::No | QMessageBox::Yes,
1551           QMessageBox::No);
1552  switch (ret) {
1553  case QMessageBox::Yes:
1554      break;
1555  case QMessageBox::No: // :)
1556      return;
1557      break;
1558  }
1559
1560  // Prompt to insert USB stick
1561  QMessageBox::information(this, tr("PC-BSD Installer"),
1562          tr("Please insert a USB stick now, and click OK to continue."),
1563          QMessageBox::Ok,
1564          QMessageBox::Ok);
1565
1566  // While USB is settling, this is a good time to ask for the config nickname
1567  bool ok;
1568  QString cfgName = QInputDialog::getText(this, tr("PC-BSD Installer"),
1569                 tr("Please enter the nickname you want to save this configuration as."), 
1570                 QLineEdit::Normal,
1571                 QString("default"), &ok);
1572  if (!ok || cfgName.isEmpty())
1573     return;
1574
1575  // Now lets try to save the media
1576  qDebug() << "Running: /root/save-to-usb.sh" << cfgName;
1577  QProcess m;
1578  m.start(QString("/root/save-to-usb.sh"), QStringList() << cfgName);
1579  while(m.state() == QProcess::Starting || m.state() == QProcess::Running) {
1580     m.waitForFinished(200);
1581     QCoreApplication::processEvents();
1582  }
1583
1584  if ( m.exitCode() != 0 ) {
1585     QMessageBox::critical(this, tr("PC-BSD Installer"),
1586          tr("Failed saving config to USB media. Is the device working and formatted MSDOSFS/FAT32?"),
1587          QMessageBox::Ok,
1588          QMessageBox::Ok);
1589
1590  } else {
1591     QMessageBox::information(this, tr("PC-BSD Installer"),
1592          tr("Configuration saved! You may now safely remove the USB media."),
1593          QMessageBox::Ok,
1594          QMessageBox::Ok);
1595  }
1596 
1597}
1598
1599void Installer::slotLoadConfigUSB()
1600{
1601  int ret = QMessageBox::question(this, tr("PC-BSD Installer"),
1602           tr("This will load any installation configuration files your MSDOSFS/FAT32 formatted USB stick. Continue?"),
1603           QMessageBox::No | QMessageBox::Yes,
1604           QMessageBox::No);
1605  switch (ret) {
1606  case QMessageBox::Yes:
1607      break;
1608  case QMessageBox::No: // :)
1609      return;
1610      break;
1611  }
1612
1613  // Prompt to insert USB stick
1614  QMessageBox::information(this, tr("PC-BSD Installer"),
1615          tr("Please insert the USB stick now, and click OK to continue."),
1616          QMessageBox::Ok,
1617          QMessageBox::Ok);
1618
1619  // Now lets try to load the config files
1620  qDebug() << "Running: /root/get-from-usb.sh";
1621  QProcess m;
1622  m.start(QString("/root/get-from-usb.sh"), QStringList());
1623  while(m.state() == QProcess::Starting || m.state() == QProcess::Running) {
1624     m.waitForFinished(200);
1625     QCoreApplication::processEvents();
1626  }
1627
1628  if ( m.exitCode() != 0 ) {
1629     QMessageBox::critical(this, tr("PC-BSD Installer"),
1630          tr("Failed loading saved config files from the USB media. Is the device working and formatted MSDOSFS/FAT32?"),
1631          QMessageBox::Ok,
1632          QMessageBox::Ok);
1633     return;
1634
1635  } else {
1636     QMessageBox::information(this, tr("PC-BSD Installer"),
1637          tr("Configurations loaded! You may now safely remove the USB media."),
1638          QMessageBox::Ok,
1639          QMessageBox::Ok);
1640  }
1641
1642 
1643  // Yay! Now lets prompt the user as to which config to use
1644  QDir cDir;
1645  cDir.setPath("/tmp/pc-sys");
1646  QStringList cfgs = cDir.entryList(QDir::Files);
1647
1648  bool ok;
1649  QString cfgFile = QInputDialog::getItem(this, tr("PC-BSD Installer"),
1650                                       tr("Config File:"), cfgs, 0, false, &ok);
1651  if (!ok || cfgFile.isEmpty())
1652    return;
1653 
1654  ret = QMessageBox::question(this, tr("PC-BSD Installer"),
1655           tr("Start the install using this config file?") + "\n" + cfgFile,
1656           QMessageBox::No | QMessageBox::Yes,
1657           QMessageBox::No);
1658  switch (ret) {
1659  case QMessageBox::Yes:
1660      break;
1661  case QMessageBox::No: // :)
1662      return;
1663      break;
1664  }
1665
1666  // Time to start the installation with our custom config file
1667  qDebug() << cfgFile;
1668  customCfgFile = "/tmp/pc-sys/" + cfgFile;
1669  installStackWidget->setCurrentIndex(3);
1670  startInstall();
1671}
Note: See TracBrowser for help on using the repository browser.