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

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

Change some wording in how we load USB config

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