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

9.1-release9.2-releasereleng/10.0releng/10.0.1releng/10.0.2
Last change on this file since 1620346 was 1620346, checked in by Kris Moore <kris@…>, 16 months ago

Initial import of PC-BSD /current/ SVN repo

  • 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 << "/,/swap(volsize=2G|org.freebsd:swap=on|checksum=off),/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    // First mount /dev inside chroot
1021    cfgList << "runExtCommand=mount -t devfs devfs ${FSMNT}/dev";
1022
1023    QString lang;
1024    if ( comboLanguage->currentIndex() != 0 )
1025      lang = languages.at(comboLanguage->currentIndex());
1026    else
1027      lang="en_US";
1028
1029    // Setup the desktop
1030    cfgList << "runCommand=sh /usr/local/share/pcbsd/scripts/sys-init.sh desktop " + lang;
1031
1032    // Setup for a fresh system first boot
1033    cfgList << "# Touch flags to enable PC-BSD setup at first boot";
1034    cfgList << "runCommand=touch /var/.runxsetup";
1035    cfgList << "runCommand=touch /var/.pcbsd-firstboot";
1036    cfgList << "runCommand=touch /var/.pcbsd-firstgui";
1037
1038    // Unmount our /dev
1039    cfgList << "runExtCommand=umount -f ${FSMNT}/dev";
1040  } else if ( wheelCurItem == wPCSERVER || wheelCurItem == 12 ) {
1041    // Doing TrueOS Install
1042    cfgList+=getUsersCfgSettings();
1043
1044    // Enable SSH?
1045    if ( fSSH )
1046      cfgList << "runCommand=echo 'sshd_enable=\"YES\"' >>/etc/rc.conf";
1047
1048    // Setup the TrueOS server
1049    cfgList << "runCommand=sh /usr/local/share/pcbsd/scripts/sys-init.sh server";
1050
1051  } else { // End of PC-BSD specific setup
1052    // Doing FreeBSD Install
1053    cfgList+=getUsersCfgSettings();
1054
1055    // First mount /dev inside chroot
1056    cfgList << "runExtCommand=mount -t devfs devfs ${FSMNT}/dev";
1057
1058    // Enable SSH?
1059    if ( fSSH )
1060      cfgList << "runCommand=echo 'sshd_enable=\"YES\"' >>/etc/rc.conf";
1061
1062    // Unmount our /dev
1063    cfgList << "runExtCommand=umount -f ${FSMNT}/dev";
1064  }
1065
1066  // Run newaliases to fix mail errors
1067  cfgList << "runCommand=newaliases";
1068
1069  // Now write out the cfgList to file
1070  QFile cfgfile( PCSYSINSTALLCFG );
1071  if ( cfgfile.open( QIODevice::WriteOnly ) ) {
1072    QTextStream stream( &cfgfile );
1073    for ( int i=0; i < cfgList.count(); ++i) {
1074      stream <<  cfgList.at(i) << "\n";
1075    }
1076    cfgfile.close();
1077  }
1078}
1079
1080void Installer::slotHelp()
1081{
1082        pcHelp = new dialogHelp();
1083        switch (installStackWidget->currentIndex()) {
1084        case 0:
1085                pcHelp->dialogInit(HELPTEXT0);
1086                break;
1087        case 1:
1088                pcHelp->dialogInit(HELPTEXT1);
1089                break;
1090        case 2:
1091                pcHelp->dialogInit(HELPTEXT2);
1092                break;
1093        case 3:
1094                pcHelp->dialogInit(HELPTEXT3);
1095                break;
1096        default:
1097                pcHelp->dialogInit("No help text...");
1098                break;
1099        }
1100        pcHelp->show();
1101}
1102
1103// Function which returns the pc-sysinstall cfg data
1104QStringList Installer::getDiskCfgSettings()
1105{
1106  QStringList tmpList;
1107  QList<QStringList> copyList;
1108  QString tmp, workingDisk, workingSlice, tmpSlice, XtraTmp, startPart, sliceSize;
1109  int disk = 0;
1110
1111  // Copy over the list to a new variable we can mangle without modifying the original
1112  copyList = sysFinalDiskLayout;
1113
1114  // Doing manual extraction
1115  if ( copyList.at(0).at(0) == "MANUAL" )
1116    return QStringList();
1117
1118  while ( ! copyList.empty() )
1119  {
1120    workingDisk = copyList.at(0).at(0);
1121    workingSlice = copyList.at(0).at(1);
1122    tmpSlice = workingSlice;
1123    tmpList << "# Disk Setup for " + workingDisk ;
1124
1125    // Check if this is an install to "Unused Space"
1126    for (int z=0; z < sysDisks.count(); ++z)
1127      if ( sysDisks.at(z).at(0) == "SLICE" \
1128        && sysDisks.at(z).at(2) == workingDisk + workingSlice \
1129        && sysDisks.at(z).at(4) == "Unused Space" )
1130          tmpSlice = "free";
1131
1132    tmpList << "disk" + tmp.setNum(disk) + "=" + workingDisk;
1133    tmpList << "partition=" + tmpSlice;
1134
1135    // Are we loading a boot-loader?
1136    if ( loadMBR )
1137      tmpList << "bootManager=bsd";
1138    else
1139      tmpList << "bootManager=none";
1140
1141    // Set the GPT/MBR options
1142    if ( loadGPT ) 
1143      tmpList << "partscheme=GPT";
1144    else
1145      tmpList << "partscheme=MBR";
1146
1147    tmpList << "commitDiskPart";
1148    tmpList << "";
1149
1150    // If after doing the mirror, our list is empty, break out
1151    if ( copyList.empty() )
1152      break;
1153   
1154    // Now print the partition section for this slice
1155    tmpList << "# Partition Setup for " + workingDisk + "(" + workingSlice + ")";
1156    tmpList << "# All sizes are expressed in MB";
1157    tmpList << "# Avail FS Types, UFS, UFS+S, UFS+SUJ, UFS+J, ZFS, SWAP";
1158    tmpList << "# UFS.eli, UFS+S.eli, UFS+SUJ, UFS+J.eli, ZFS.eli, SWAP.eli";
1159
1160    // If there is a dedicated /boot partition, need to list that first, see what is found
1161    for (int i=0; i < copyList.count(); ++i) {
1162      QStringList mounts = copyList.at(i).at(2).split(",");
1163      for (int z = 0; z < mounts.size(); ++z) {
1164        if ( copyList.at(i).at(0) == workingDisk \
1165          && copyList.at(i).at(1) == workingSlice \
1166          && mounts.at(z) == "/boot" )
1167                startPart="/boot";
1168      }
1169    }
1170
1171    // If no dedicated /boot partition, then lets list "/" first
1172    if(startPart.isEmpty())
1173        startPart="/";
1174
1175    // Start by looking for the root partition
1176    for (int i=0; i < copyList.count(); ++i) {
1177      QStringList mounts = copyList.at(i).at(2).split(",");
1178      for (int z = 0; z < mounts.size(); ++z) {
1179        if ( copyList.at(i).at(0) == workingDisk \
1180          && copyList.at(i).at(1) == workingSlice \
1181          && mounts.at(z) == startPart ) {
1182
1183          // Check if we have any extra arguments to throw on the end
1184          XtraTmp="";
1185          if ( ! copyList.at(i).at(5).isEmpty() )
1186            XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1187
1188          // Write out the partition line
1189          tmpList << "disk" + tmp.setNum(disk) + "-part=" \
1190                   + copyList.at(i).at(3) + " " + copyList.at(i).at(4) \
1191                   + " " + copyList.at(i).at(2) + XtraTmp;
1192
1193          // Check if we have an encryption passphrase to use
1194          if ( ! copyList.at(i).at(6).isEmpty() )
1195            tmpList << "encpass=" + copyList.at(i).at(6);
1196
1197          // Done with this item, remove it now
1198          copyList.removeAt(i);
1199          break;
1200        }
1201      }
1202    }
1203
1204    // Now look for SWAP
1205    for (int i=0; i < copyList.count(); ++i) {
1206      if ( copyList.at(i).at(0) == workingDisk \
1207        && copyList.at(i).at(1) == workingSlice \
1208        && copyList.at(i).at(2) == "SWAP" ) {
1209
1210        // Write the partition line
1211        tmpList << "disk" + tmp.setNum(disk) + "-part=" \
1212                 + copyList.at(i).at(3) + " " + copyList.at(i).at(4) \
1213                 + " none";
1214
1215        // Done with this item, remove it now
1216        copyList.removeAt(i);
1217        break;
1218      }
1219    }
1220 
1221    // Now look for any other partitions
1222    int count = copyList.count();
1223    for (int i=0; i < count; ++i) {
1224      if ( copyList.at(i).at(0) == workingDisk \
1225        && copyList.at(i).at(1) == workingSlice ) {
1226
1227        // Check if we have any extra arguments to throw on the end
1228        XtraTmp="";
1229        if ( ! copyList.at(i).at(5).isEmpty() )
1230          XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1231
1232        // If we are working on the last partition, set the size to 0 to use remaining disk
1233        if ( i == (count - 1) ) 
1234                sliceSize = "0";
1235        else
1236                sliceSize=copyList.at(i).at(4);
1237
1238        // Write the partition line
1239        tmpList << "disk" + tmp.setNum(disk) + "-part=" \
1240                 + copyList.at(i).at(3) + " " + sliceSize \
1241                 + " " + copyList.at(i).at(2) + XtraTmp;
1242
1243        // Check if we have an encryption passphrase to use
1244        if ( ! copyList.at(i).at(6).isEmpty() )
1245          tmpList << "encpass=" + copyList.at(i).at(6);
1246
1247        // Done with this item, remove it now
1248        copyList.removeAt(i);
1249        i--;
1250        count--;
1251      }
1252    }
1253
1254
1255    // Close out this partition section
1256    tmpList << "commitDiskLabel";
1257    tmpList << "";
1258
1259    // Increment our disk counter
1260    disk++;
1261  }
1262
1263  return tmpList;
1264}
1265
1266// Slot which checks any disk requirements before procceding to the next page
1267bool Installer::checkDiskRequirements()
1268{
1269  // For now just return true, the wizard should handle making sure
1270  // the user doesn't shoot themselves in the foot during disk setup
1271  return true;
1272}
1273
1274// Function which begins the backend install, and connects slots to monitor it
1275void Installer::startInstall()
1276{
1277  // Disable the back / next buttons until we are finished
1278  nextButton->setEnabled(false);
1279  backButton->setEnabled(false);
1280  progressBarInstall->setValue(0); 
1281  installFoundCounter = false;
1282  installFoundMetaCounter = false;
1283  installFoundFetchOutput = false;
1284
1285  // Setup some defaults for the secondary progress bar
1286  progressBarInstall2->setValue(0); 
1287  progressBarInstall2->setHidden(true); 
1288  labelInstallStatus2->setText("");
1289  labelInstallStatus2->setHidden(true);
1290
1291  // Kill any hald instances, which causes failures to install when it
1292  // tries to mount our new partitions
1293  QProcess::execute("killall", QStringList() << "hald");
1294
1295  // Start our process to begin the install
1296  QString program = PCSYSINSTALL;
1297  QStringList arguments;
1298  arguments << "-c" << PCSYSINSTALLCFG;
1299
1300  installProc = new QProcess();
1301  installProc->setProcessChannelMode(QProcess::MergedChannels);
1302  connect(installProc,SIGNAL(finished( int, QProcess::ExitStatus)),this,SLOT(slotInstallProcFinished( int, QProcess::ExitStatus)));
1303  connect(installProc,SIGNAL(readyRead()),this,SLOT(slotReadInstallerOutput()));
1304  installProc->start(program, arguments);
1305
1306}
1307
1308// Function run when the install failed to prompt user for course of action
1309void Installer::installFailed()
1310{
1311   QString sysLog;
1312   labelInstallStatus->setText(tr("Failed!"));
1313
1314   QMessageBox msgBox;
1315   msgBox.setWindowTitle(tr("PC-BSD Installer"));
1316   msgBox.setIcon(QMessageBox::Critical);
1317   msgBox.setText(tr("The installer has encountered an error and has been halted."));
1318   msgBox.setInformativeText(tr("Do you want to generate an error report?"));
1319   msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1320   msgBox.setDefaultButton(QMessageBox::Yes);
1321
1322   // If we have a log, show it in the detailed view button
1323   if ( QFile::exists("/tmp/.pc-sysinstall/pc-sysinstall.log") )
1324   {
1325     QFile logFile("/tmp/.pc-sysinstall/pc-sysinstall.log");
1326     if (logFile.open(QIODevice::ReadOnly | QIODevice::Text))
1327         while (!logFile.atEnd())
1328           sysLog = sysLog + logFile.readLine() + "\n";
1329     msgBox.setDetailedText(sysLog);
1330   }
1331   int ret = msgBox.exec();
1332
1333   switch (ret) {
1334   case QMessageBox::Yes:
1335       // Generate the error report
1336       Scripts::Backend::createErrorReport();
1337       break;
1338   case QMessageBox::No: // :)
1339       break;
1340   }
1341
1342   QMessageBox msgBox2;
1343   msgBox2.setWindowTitle(tr("PC-BSD Installer"));
1344   msgBox2.setIcon(QMessageBox::Critical);
1345   msgBox2.setText(tr("Restart the system now?") );
1346   msgBox2.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1347   msgBox2.setDefaultButton(QMessageBox::Yes);
1348   msgBox2.setDetailedText(sysLog);
1349
1350   ret = msgBox2.exec();
1351
1352   switch (ret) {
1353   case QMessageBox::Yes:
1354       close();
1355       break;
1356   case QMessageBox::No: // :)
1357       break;
1358   }
1359
1360}
1361
1362// Slot which is called when the installation has finished
1363void Installer::slotInstallProcFinished( int exitCode, QProcess::ExitStatus status)
1364{
1365  QString tmp;
1366  if ( status != QProcess::NormalExit || exitCode != 0 )
1367  {
1368     installFailed();
1369  } else {
1370    // Move to the final page, and show a finish button
1371    proceed(true);
1372    nextButton->setEnabled(true);
1373    nextButton->setText(tr("&Finish"));
1374    nextButton->disconnect();
1375    connect(nextButton, SIGNAL(clicked()), this, SLOT(slotFinished()));
1376    backButton->setEnabled(false);
1377    abortButton->setEnabled(false);
1378  }
1379}
1380
1381// Slot which reads the output of the installer
1382void Installer::slotReadInstallerOutput()
1383{
1384  QString tmp, line;
1385  int range;
1386  bool ok;
1387
1388
1389  while ( installProc->canReadLine() )
1390  {
1391     tmp = installProc->readLine();
1392     tmp.truncate(75);
1393     //qDebug() << tmp;
1394
1395     // If doing a restore, don't bother checking for other values
1396     //if ( radioRestore->isChecked() ) {
1397     //   labelInstallStatus->setText(tmp);
1398     // continue;
1399     //}
1400
1401     // Parse fetch output
1402     if ( installFoundFetchOutput ) {
1403       if ( tmp.indexOf("SIZE: ") != -1 ) {
1404
1405          // Get the total range first
1406          line = tmp;
1407          tmp = tmp.remove(0, tmp.indexOf(":") + 2 );
1408          tmp.truncate(tmp.indexOf(" ")); 
1409          range = tmp.toInt(&ok);
1410          if ( ok )
1411             progressBarInstall->setRange(0, range + 1);
1412
1413          // Now get the current progress
1414          tmp = line;
1415          tmp = tmp.remove(0, tmp.indexOf(":") + 2 );
1416          tmp = tmp.remove(0, tmp.indexOf(":") + 2 );
1417          range = tmp.toInt(&ok);
1418          if ( ok )
1419             progressBarInstall->setValue(range);
1420           
1421          continue;
1422        } else {
1423          installFoundFetchOutput = false;
1424          break;
1425        }
1426     } 
1427
1428     // Unknown point in install
1429     if ( ! installFoundCounter && ! installFoundMetaCounter ) {
1430
1431        // Check if we've found fetch output to update the progress bar with
1432        if ( tmp.indexOf("FETCH: ") != -1 ) {
1433          installFoundFetchOutput = true;
1434          break;
1435        }
1436
1437        if ( tmp.indexOf("INSTALLCOUNT: ") != -1 ) {
1438          tmp = tmp.remove(0, tmp.indexOf(":") + 1 ); 
1439          range = tmp.toInt(&ok);
1440          if ( ok ) {
1441             range = range + 50;
1442             progressBarInstall->setRange(0, range + 1); 
1443             installFoundCounter = true;
1444             if ( availDesktopPackageData )
1445                labelInstallStatus->setText(tr("Extracting system...")); 
1446             else
1447                labelInstallStatus->setText(tr("Installing system... This may take a while...")); 
1448          }
1449
1450          break;
1451
1452        } 
1453
1454        // Check if we are on the meta-pkg installation
1455        if ( tmp.indexOf("Packages to install: ") != -1 ) {
1456          tmp = tmp.remove(0, tmp.indexOf(":") + 1 ); 
1457          range = tmp.toInt(&ok);
1458          if ( ok ) {
1459             progressBarInstall->setRange(0, range + 1); 
1460             progressBarInstall->setValue(0); 
1461             progressBarInstall2->setRange(0, 0); 
1462             labelInstallStatus2->setHidden(false);
1463             progressBarInstall2->setHidden(false); 
1464             installFoundMetaCounter = true;
1465             installFoundCounter = false;
1466             labelInstallStatus->setText(tr("Installing packages... This may take a while...")); 
1467             continue;
1468          }
1469
1470        } 
1471
1472        labelInstallStatus->setText(tmp);
1473        continue; 
1474     } 
1475
1476     // Doing file-extraction still
1477     if ( installFoundCounter ) {
1478
1479       // Doing dist-files, may have multiple images to extract
1480       if ( tmp.indexOf("INSTALLCOUNT: ") != -1 ) {
1481         tmp = tmp.remove(0, tmp.indexOf(":") + 1 ); 
1482         range = tmp.toInt(&ok);
1483         if ( ok ) {
1484            progressBarInstall->setRange(0, range + 1); 
1485            installFoundCounter = true;
1486            if ( availDesktopPackageData )
1487              labelInstallStatus->setText(tr("Extracting system...")); 
1488            else
1489              labelInstallStatus->setText(tr("Installing system... This may take a while...")); 
1490         }
1491         break;
1492       } 
1493
1494
1495       // Increment the progress
1496       progressBarInstall->setValue(progressBarInstall->value() + 1); 
1497
1498       // We've reached the end of this counted section
1499       if ( tmp.indexOf("Extraction Finished") != -1 ) {
1500         installFoundCounter = false;
1501         progressBarInstall->setRange(0, 0); 
1502       }
1503
1504       continue;
1505     }
1506
1507     // Doing meta-pkgs
1508     if ( installFoundMetaCounter ) {
1509        if ( tmp.indexOf("Package installation complete!") != -1 ) {
1510           installFoundMetaCounter = false;
1511           progressBarInstall->setRange(0, 0); 
1512           progressBarInstall2->setHidden(true);
1513           labelInstallStatus2->setHidden(true);
1514           continue;
1515        }
1516
1517        // Got this far, increment the pkg-sub count
1518        progressBarInstall->setValue(progressBarInstall->value() + 1); 
1519        labelInstallStatus2->setText(tmp);
1520     }
1521
1522  } // end of while loop
1523}
1524
1525// Return list of components to install
1526QStringList Installer::getComponentCfgSettings()
1527{
1528  QStringList componentList, com;
1529  if ( fSRC )
1530    com << "src";
1531  if ( fPORTS )
1532    com << "ports";
1533
1534  if ( ! com.isEmpty() ) {
1535    componentList << "";
1536    componentList << "# Optional Components";
1537    componentList << "installComponents=" + com.join(",");
1538  }
1539
1540  return componentList;
1541}
1542
1543// Start xvkbd
1544void Installer::slotPushVirtKeyboard()
1545{
1546   system("killall -9 xvkbd; xvkbd -compact &");
1547}
1548
1549// Return the configuration for desktop packages
1550QStringList Installer::getDeskPkgCfg()
1551{
1552   if ( wheelCurItem == wFREEBSD )
1553      return QStringList();
1554
1555   QStringList cfgList, pkgList;
1556   QString line;
1557
1558   QList<QStringList> curList;
1559
1560   if ( wheelCurItem != wPCSERVER && wheelCurItem != 11 && wheelCurItem != 12) {
1561     curList = listDeskPkgs;
1562     pkgList << "pcbsd-base";
1563   } else {
1564     curList = listServerPkgs;
1565     pkgList << "trueos-base";
1566   }
1567
1568   // Loop though list of pkgs, see what to install
1569   for ( int d=0; d < curList.count(); ++d) {
1570     for ( int i=0; i < selectedPkgs.count(); ++i)
1571        // Is the package selected or the base-system?
1572        if ( curList.at(d).at(0) == selectedPkgs.at(i) || curList.at(d).at(0) == "base-system" ) {
1573
1574           // Yay! Lets get a list of packages to install
1575           QFile mFile;
1576           mFile.setFileName(curList.at(d).at(6));
1577           if ( ! mFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
1578              qDebug() << "Invalid meta-pkg list:" << curList.at(d).at(6);
1579              break;
1580           }
1581 
1582           // Read in the meta pkg list
1583           QTextStream in(&mFile);
1584           while ( !in.atEnd() ) {
1585             line = in.readLine().simplified();
1586             if ( line.isEmpty() )
1587                 continue; 
1588             
1589             pkgList << line.section(":", 0,0);
1590           }
1591           mFile.close();
1592           break;
1593        }
1594   }
1595
1596   cfgList << "installPackages=" + pkgList.join(" ");
1597   return cfgList;
1598}
1599
1600// Return list of users in cfg format
1601QStringList Installer::getUsersCfgSettings()
1602{
1603   QStringList userList;
1604 
1605   userList << "";
1606   userList << "# Root Password";
1607   userList << "rootPass=" + fRootPW;
1608
1609   userList << "";
1610   userList << "# Users";
1611   userList << "userName=" + fUserName;
1612   userList << "userComment=" + fName;
1613   userList << "userPass=" + fUserPW;
1614   userList << "userShell=" + fShell;
1615   userList << "userHome=/home/" + fUserName;
1616   userList << "userGroups=wheel,operator";
1617   userList << "commitUser";
1618   userList << "";
1619 
1620   return userList;
1621}
1622
1623void Installer::closeEvent(QCloseEvent *event)
1624{
1625    int ret = QMessageBox::question(this, tr("PC-BSD Installer"),
1626                                tr("Are you sure you want to abort this installation?"),
1627                                QMessageBox::No | QMessageBox::Yes,
1628                                QMessageBox::No);
1629    switch (ret) {
1630    case QMessageBox::Yes:
1631        //exit the installer :(
1632        break;
1633    case QMessageBox::No: // :)
1634        event->ignore();
1635        break;
1636    }
1637}
1638
1639void Installer::checkSpaceWarning()
1640{
1641  int totalSize = -1;
1642  int targetSize;
1643  int targetLoc;
1644  bool ok;
1645  QString workingDisk = sysFinalDiskLayout.at(0).at(0);
1646  QString workingSlice = sysFinalDiskLayout.at(0).at(1);
1647  QString targetType;
1648  QString target;
1649  //qDebug() << "Disk layout:" << workingDisk << workingSlice;
1650
1651  if ( workingSlice == "ALL" ) {
1652    targetType = "DRIVE";
1653    target = workingDisk;
1654    targetLoc = 1;
1655  } else {
1656    targetType = "SLICE";
1657    target = workingDisk + workingSlice;
1658    targetLoc = 2;
1659  }
1660 
1661  // Lets get the size for this disk / partition
1662  for (int i=0; i < sysDisks.count(); ++i) {
1663      // Make sure to only add the slices to the listDiskSlices
1664      if ( sysDisks.at(i).at(0) == targetType && target == sysDisks.at(i).at(targetLoc))
1665        totalSize = sysDisks.at(i).at(targetLoc + 1).toInt(&ok);
1666  }
1667
1668  //qDebug() << totalSize;
1669
1670  if ( installStackWidget->currentIndex() == 1 && (wheelCurItem == wFREEBSD || wheelCurItem == wPCSERVER || wheelCurItem == 12) )
1671     targetSize=20000;
1672  else
1673     targetSize=50000;
1674
1675  qDebug() << totalSize << targetSize;
1676
1677  // Lets print a nice handy warning for users with possible
1678  // low disk space issues
1679  if ( totalSize < targetSize ) {
1680  QMessageBox::warning(this, tr("PC-BSD Installer"),
1681      QString(tr("The selected disk / partition is less than recommended %1MB. The installation may fail...")).arg(targetSize),
1682      QMessageBox::Ok,
1683      QMessageBox::Ok);
1684      haveWarnedSpace = true;     
1685  }
1686
1687  return;
1688}
Note: See TracBrowser for help on using the repository browser.