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

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

Fix VirtualBox? Detection
Fix a bug running the server wizard too many times

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