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

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2releng/10.0.3releng/10.1
Last change on this file since 1fbc840 was 30e98ce, checked in by Kris Moore <kris@…>, 18 months ago

Fix an issue when we mount / umount /dev during install, causes a panic in some cases and
its not necessary anyway

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