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

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

Fix up the FreeBSD installation option, now GUI will respect no-fbsd flag
and hide the option if the media isn't on the disk

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