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

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

Update Installer with new icon to launch the network manager

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