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

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

Show GB on recommended disk sizes

  • Property mode set to 100644
File size: 50.3 KB
Line 
1#include <QCloseEvent>
2#include <QProcess>
3#include <QTimer>
4#include <QTranslator>
5#include <QGraphicsPixmapItem>
6
7#include "backend.h"
8#include "installer.h"
9#include "helpText.h"
10
11Installer::Installer(QWidget *parent) : QMainWindow(parent)
12{
13    setupUi(this);
14    translator = new QTranslator();
15    haveWarnedSpace=false;
16
17    connect(abortButton, SIGNAL(clicked()), this, SLOT(slotAbort()));
18    connect(backButton, SIGNAL(clicked()), this, SLOT(slotBack()));
19    connect(nextButton, SIGNAL(clicked()), this, SLOT(slotNext()));
20
21    connect(helpButton, SIGNAL(clicked()), this, SLOT(slotHelp()));
22    connect(pushTouchKeyboard, SIGNAL(clicked()), this, SLOT(slotPushVirtKeyboard()));
23    connect(pushChangeKeyLayout, SIGNAL(clicked()), this, SLOT(slotPushKeyLayout()));
24    connect(pushHardware, SIGNAL(clicked()), this, SLOT(slotCheckHardware()));
25
26    abortButton->setText(tr("&Cancel"));
27    backButton->setText(tr("&Back"));
28    nextButton->setText(tr("&Next"));
29
30    // Init the MBR to yes
31    loadMBR = true;
32    // Init the GPT to no
33    loadGPT = false;
34
35    // No optional components by default
36    fSRC=false;
37    fPORTS=false;
38
39    // Load the keyboard info
40    keyModels = Scripts::Backend::keyModels();
41    keyLayouts = Scripts::Backend::keyLayouts();
42
43    // Set the arch name
44    setArch();
45
46    // Start on the first screen
47    installStackWidget->setCurrentIndex(0);
48    backButton->setVisible(false);
49}
50
51Installer::~Installer()
52{
53    //delete ui;
54}
55
56bool Installer::isInstalled()
57{
58    return false;
59}
60
61void Installer::setArch()
62{
63   QProcess m;
64   m.start(QString("uname"), QStringList() << "-m");
65   while(m.state() == QProcess::Starting || m.state() == QProcess::Running) {
66      m.waitForFinished(200);
67      QCoreApplication::processEvents();
68   }
69
70   // Get output
71   Arch = m.readLine().simplified();
72   qDebug() << Arch;
73}
74
75void Installer::slotCheckHardware()
76{
77  pcHardware = new dialogCheckHardware();
78  pcHardware->programInit();
79  pcHardware->setWindowModality(Qt::ApplicationModal);
80  pcHardware->show();
81  pcHardware->raise();
82}
83
84void Installer::slotPushKeyLayout()
85{
86  wKey = new widgetKeyboard();
87  wKey->programInit(keyModels, keyLayouts);
88  wKey->setWindowModality(Qt::ApplicationModal);
89  wKey->show();
90  wKey->raise();
91}
92
93void Installer::initInstall()
94{
95    // load languages
96    comboLanguage->clear();
97    languages = Scripts::Backend::languages();
98    for (int i=0; i < languages.count(); ++i) {
99        QString languageStr = languages.at(i);
100        QString language = languageStr.split("-").at(0);
101        comboLanguage->addItem(language.trimmed());
102    }
103    connect(comboLanguage, SIGNAL(currentIndexChanged(QString)), this, SLOT(slotChangeLanguage()));
104
105    // Load any package scheme data
106    listDeskPkgs = Scripts::Backend::getPackageData(availDesktopPackageData, QString());
107    listServerPkgs = Scripts::Backend::getPackageData(availServerPackageData, QString("trueos"));
108
109    // Do check for available meta-pkgs on boot media
110    if ( QFile::exists("/tmp/no-meta-pkgs") )
111        hasPkgsOnMedia = false;
112    else
113        hasPkgsOnMedia = true;
114
115    qDebug() << "Package Media:" << availDesktopPackageData << hasPkgsOnMedia;
116
117    // See if this media has a freebsd release on it
118    if ( QFile::exists("/tmp/no-fbsd-release") ) {
119        hasFreeBSDOnMedia = false;
120    } else {
121        hasFreeBSDOnMedia = true;
122    }
123       
124    // Do check for install pkgs on boot media
125    if ( QFile::exists("/tmp/no-install-pkgs") ) {
126        hasInstallOnMedia = false;
127    } else {
128        hasInstallOnMedia = true;
129    }
130
131    // Set the key toggle
132    toggleKeyLayout = true;
133
134    // Is this a LIVE disk?
135    if ( QFile::exists("/usr/pcbsd-live") )
136        isLiveMode = true;
137    else
138        isLiveMode = false;
139
140    // Get available memory
141    systemMemory = Scripts::Backend::systemMemory();
142
143    // Load up the keyboard information
144    //connectKeyboardSlots();
145
146    // Connect the disk slots
147    connect(pushDiskCustomize,SIGNAL(clicked()), this, SLOT(slotDiskCustomizeClicked()));
148
149    // Load the disks
150    loadDiskInfo();
151   
152
153    // Init the desktop wheel
154    initDesktopSelector();
155}
156
157void Installer::loadDiskInfo()
158{
159   sysDisks = Scripts::Backend::hardDrives();
160   if ( sysDisks.empty() ) {
161      QMessageBox::critical(this, tr("PC-BSD Installer"),
162                                tr("Unable to detect any disk drives! The install will now exit."),
163                                QMessageBox::Ok,
164                                QMessageBox::Ok);
165      exit(1);
166   }
167
168   // For now use the first disk we find
169   if ( ! autoGenPartitionLayout(sysDisks.at(0).at(1), true) )
170   {
171      QMessageBox::critical(this, tr("PC-BSD Installer"),
172        tr("Unable to suggest a partition for the detected disk."),
173        QMessageBox::Ok,
174        QMessageBox::Ok);
175   }
176
177   textEditDiskSummary->clear();
178   QStringList summary = getDiskSummary();
179   for ( int i=0; i < summary.count(); ++i)
180     textEditDiskSummary->append(summary.at(i));
181
182   textEditDiskSummary->moveCursor(QTextCursor::Start);
183
184}
185
186// Function which will auto-generate a partition layout based upon the target disk / slice
187bool Installer::autoGenPartitionLayout(QString target, bool isDisk)
188{
189  QString targetType, tmp;
190  int targetLoc, totalSize = 0, mntsize;
191  QString targetDisk, targetSlice, tmpPass, fsType;
192  bool ok;
193  ok = false;
194
195  // Clear out the original disk layout
196  sysFinalDiskLayout.clear();
197  QStringList fileSystem;
198  qDebug() << "Generating disk layout";
199
200
201  if ( isDisk ) {
202    targetType = "DRIVE";
203    targetSlice = "ALL";
204    targetDisk = target;
205    targetLoc = 1;
206  } else {
207    targetType = "SLICE";
208    targetDisk = target;
209    targetDisk.truncate(targetDisk.size() -2);
210    targetSlice = target;
211    targetSlice = targetSlice.remove(0, targetSlice.size() -2);
212    targetLoc = 2;
213  }
214 
215  // Lets get the size for this disk / partition
216  for (int i=0; i < sysDisks.count(); ++i) {
217      // Make sure to only add the slices to the listDiskSlices
218      if ( sysDisks.at(i).at(0) == targetType && target == sysDisks.at(i).at(targetLoc))
219        totalSize = sysDisks.at(i).at(targetLoc + 1).toInt(&ok);
220  }
221
222  // Give us a small buffer for rounding errors
223  totalSize = totalSize - 10;
224
225  // We got a valid size for this disk / slice, lets generate the layout now
226  if( !ok )
227    return false;
228
229
230  // If on amd64 lets use ZFS, it rox
231  if ( Arch == "amd64" ) {
232    // Add the main zfs pool with standard partitions
233    fsType= "ZFS";
234    fileSystem << targetDisk << targetSlice << "/,/tmp(compress=lzjb),/usr(canmount=off),/usr/home,/usr/jails,/usr/obj(compress=lzjb),/usr/pbi,/usr/ports(compress=gzip),/usr/ports/distfiles(compress=off),/usr/src(compress=gzip),/var(canmount=off),/var/audit(compress=lzjb),/var/log(compress=gzip),/var/tmp(compress=lzjb)" << fsType << tmp.setNum(totalSize) << "" << "";
235    //qDebug() << "Auto-Gen FS:" <<  fileSystem;
236    sysFinalDiskLayout << fileSystem;
237    fileSystem.clear();
238    return true;
239  }
240
241  // Looks like not on amd64, fallback to UFS+SUJ and print a nice
242  // warning for the user explaining they *really* want to be on amd64
243  QMessageBox::warning(this, tr("PC-BSD Installer"),
244      tr("Detected that you are running the 32bit version. If your system is 64bit capable (most systems made after 2005), you really should be running the 64bit version"),
245      QMessageBox::Ok,
246      QMessageBox::Ok);
247
248  // Start the UFS layout now
249  mntsize = 2000;
250  fsType="UFS+SUJ";
251
252  fileSystem << targetDisk << targetSlice << "/" << fsType << tmp.setNum(mntsize) << "" << "";
253  totalSize = totalSize - mntsize;
254  //qDebug() << "Auto-Gen FS:" <<  fileSystem;
255  sysFinalDiskLayout << fileSystem;
256  fileSystem.clear();
257   
258
259  // Figure out the swap size, try for 2xPhysMem first, fallback to 256 if not enough space
260  mntsize = systemMemory * 2;
261  if ( totalSize - mntsize < 3000 )
262     mntsize = 256;
263
264  // Cap the swap size to 2GB
265  if ( mntsize > 2000 )
266     mntsize = 2000;
267
268  fileSystem << targetDisk << targetSlice << "SWAP" << "SWAP" << tmp.setNum(mntsize) << "" << "";
269  totalSize = totalSize - mntsize;
270  //qDebug() << "Auto-Gen FS:" <<  fileSystem;
271  sysFinalDiskLayout << fileSystem;
272  fileSystem.clear();
273
274  // If less than 3GB, skip /var and leave on /
275  if ( totalSize > 3000 ) {
276    // Figure out the default size for /var if we are on FreeBSD / PC-BSD
277    mntsize = 2048;
278    fileSystem << targetDisk << targetSlice << "/var" << fsType << tmp.setNum(mntsize) << "" << "";
279    totalSize = totalSize - mntsize;
280    //qDebug() << "Auto-Gen FS:" <<  fileSystem;
281    sysFinalDiskLayout << fileSystem;
282    fileSystem.clear();
283  }
284
285  // Now use the rest of the disk / slice for /usr
286  fileSystem << targetDisk << targetSlice << "/usr" << fsType << tmp.setNum(totalSize) << "" << "";
287  //qDebug() << "Auto-Gen FS:" <<  fileSystem;
288  sysFinalDiskLayout << fileSystem;
289  fileSystem.clear();
290
291  return true; 
292 
293}
294
295// Function which returns the pc-sysinstall cfg data
296QStringList Installer::getDiskSummary()
297{
298  QList<QStringList> copyList;
299  QStringList summaryList;
300  QString tmp, workingDisk, workingSlice, tmpSlice, XtraTmp, startPart, sliceSize;
301  int disk = 0;
302
303  // Copy over the list to a new variable we can mangle without modifying the original
304  copyList = sysFinalDiskLayout;
305
306  if ( copyList.at(0).at(0) == "MANUAL" )
307  {
308    summaryList << "";
309    summaryList << tr("Installing to file-system mounted at /mnt");
310    return summaryList;
311  }
312
313  // Start our summary
314  summaryList << "";
315  summaryList << "<b>" + tr("The disk will be setup with the following configuration:") + "</b>";
316
317  while ( ! copyList.empty() )
318  {
319    workingDisk = copyList.at(0).at(0);
320    workingSlice = copyList.at(0).at(1);
321    tmpSlice = workingSlice;
322
323    // Check if this is an install to "Unused Space"
324    for (int z=0; z < sysDisks.count(); ++z)
325      if ( sysDisks.at(z).at(0) == "SLICE" \
326        && sysDisks.at(z).at(2) == workingDisk + workingSlice \
327        && sysDisks.at(z).at(4) == "Unused Space" )
328          tmpSlice = "free";
329
330    // Check for any mirror for this device
331    for (int i=0; i < copyList.count(); ++i) {
332       if ( copyList.at(i).at(2).indexOf("MIRROR(" + workingDisk + ")") != -1 )
333       {
334         summaryList << tr("Disk:") + copyList.at(i).at(0) + " " + tr("Mirroring:") + workingDisk;
335         copyList.removeAt(i);
336         break;
337       }
338    }
339
340    // If after doing the mirror, our list is empty, break out
341    if ( copyList.empty() )
342      break;
343   
344    // If there is a dedicated /boot partition, need to list that first, see what is found
345    for (int i=0; i < copyList.count(); ++i) {
346      QStringList mounts = copyList.at(i).at(2).split(",");
347      for (int z = 0; z < mounts.size(); ++z) {
348        if ( copyList.at(i).at(0) == workingDisk \
349          && copyList.at(i).at(1) == workingSlice \
350          && mounts.at(z) == "/boot" )
351                startPart="/boot";
352      }
353    }
354
355    // If no dedicated /boot partition, then lets list "/" first
356    if(startPart.isEmpty())
357        startPart="/";
358
359    // Start by looking for the root partition
360    for (int i=0; i < copyList.count(); ++i) {
361      QStringList mounts = copyList.at(i).at(2).split(",");
362      for (int z = 0; z < mounts.size(); ++z) {
363        if ( copyList.at(i).at(0) == workingDisk \
364          && copyList.at(i).at(1) == workingSlice \
365          && mounts.at(z) == startPart ) {
366
367          // Check if we have any extra arguments to throw on the end
368          XtraTmp="";
369          if ( ! copyList.at(i).at(5).isEmpty() )
370            XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
371
372          // Write the user summary
373          summaryList << "";
374          summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
375          summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
376          summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
377          if ( copyList.at(i).at(3) == "ZFS" ) {
378            QStringList zDS = copyList.at(i).at(2).split(",/");
379            QString zTMP;
380            for (int ds = 0; ds < zDS.size(); ++ds) {
381              if ( zDS.at(ds) != "/" )
382                zDS.replace(ds, "/" + zDS.at(ds));
383              if ( zDS.at(ds).indexOf("(") != -1 ) {
384                zTMP = zDS.at(ds);
385                zTMP.replace("(", " (");
386                zDS.replace(ds, zTMP );
387              }
388            } 
389            summaryList << tr("ZFS Datasets:<br>") + " " + zDS.join("<br>");
390          } else {
391            summaryList << tr("Mount:") + " " + copyList.at(i).at(2);
392          }
393          if ( ! XtraTmp.isEmpty() ) {
394            summaryList << tr("Options:") + " " + copyList.at(i).at(5);
395          }
396
397          // Done with this item, remove it now
398          copyList.removeAt(i);
399          break;
400        }
401      }
402    }
403
404
405    // Now look for SWAP
406    for (int i=0; i < copyList.count(); ++i) {
407      if ( copyList.at(i).at(0) == workingDisk \
408        && copyList.at(i).at(1) == workingSlice \
409        && copyList.at(i).at(2) == "SWAP" ) {
410
411        // Write the user summary
412        summaryList << "";
413        summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
414        summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
415        summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
416
417        // Done with this item, remove it now
418        copyList.removeAt(i);
419        break;
420      }
421    }
422
423 
424    // Now look for any other partitions
425    int count = copyList.count();
426    for (int i=0; i < count; ++i) {
427      if ( copyList.at(i).at(0) == workingDisk \
428        && copyList.at(i).at(1) == workingSlice ) {
429
430        // Check if we have any extra arguments to throw on the end
431        XtraTmp="";
432        if ( ! copyList.at(i).at(5).isEmpty() )
433          XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
434
435        // If we are working on the last partition, set the size to 0 to use remaining disk
436        if ( i == (count - 1) ) 
437                sliceSize = "0";
438        else
439                sliceSize=copyList.at(i).at(4);
440
441        // Write the user summary
442        summaryList << "";
443        summaryList << tr("Partition:") + " " + workingDisk + "(" + workingSlice + "):";
444        summaryList << tr("FileSystem:") + " " + copyList.at(i).at(3);
445        summaryList << tr("Size:") + " " + copyList.at(i).at(4) + "MB ";
446        if ( copyList.at(i).at(3) != "ZFS" )
447          summaryList << tr("Mount:") + " " + copyList.at(i).at(2);
448        if ( ! XtraTmp.isEmpty() ) {
449          summaryList << tr("Options:") + " " + copyList.at(i).at(5);
450        }
451
452        // Done with this item, remove it now
453        copyList.removeAt(i);
454        i--;
455        count--;
456      }
457    }
458
459    // Increment our disk counter
460    disk++;
461  }
462
463  return summaryList;
464}
465
466void Installer::slotDiskCustomizeClicked()
467{
468  wDisk = new wizardDisk();
469  wDisk->programInit();
470  wDisk->setWindowModality(Qt::ApplicationModal);
471  connect(wDisk, SIGNAL(saved(QList<QStringList>, bool, bool)), this, SLOT(slotSaveDiskChanges(QList<QStringList>, bool, bool)));
472  wDisk->show();
473  wDisk->raise();
474}
475
476void Installer::slotDesktopCustomizeClicked()
477{
478  desks = new desktopSelection();
479  if ( wheelCurItem != wPCSERVER && wheelCurItem != 11 && wheelCurItem != 12)
480     desks->programInit(listDeskPkgs,selectedPkgs);
481  else
482     desks->programInit(listServerPkgs,selectedPkgs);
483  desks->setWindowModality(Qt::ApplicationModal);
484  connect(desks, SIGNAL(saved(QStringList)), this, SLOT(slotSaveMetaChanges(QStringList)));
485  desks->show();
486  desks->raise();
487}
488
489void Installer::slotSaveMetaChanges(QStringList sPkgs)
490{
491  selectedPkgs = sPkgs;
492
493  // Only add +10 if we are not already on the custom screen
494  if ( wheelCurItem < 10 )
495    wheelCurItem= wheelCurItem + 10;
496
497  switch (wheelCurItem) {
498    case 12:
499        groupDeskSummary->setTitle(tr("TrueOS Package Selection"));
500        break;
501    case 11:
502        groupDeskSummary->setTitle(tr("FreeBSD Package Selection"));
503        break;
504    default:
505        groupDeskSummary->setTitle(tr("PC-BSD Package Selection"));
506        break;
507  }
508
509  textDeskSummary->setText(tr("The following meta-pkgs will be installed:") + "<br>" + selectedPkgs.join("<br>"));
510  graphicsViewOS->setScene(customScene);
511}
512
513void Installer::slotSaveDiskChanges(QList<QStringList> newSysDisks, bool MBR, bool GPT)
514{
515  // Save the new disk layout
516  loadMBR = MBR;
517  loadGPT = GPT;
518  sysFinalDiskLayout = newSysDisks;
519  textEditDiskSummary->clear();
520  QStringList summary = getDiskSummary();
521  for ( int i=0; i < summary.count(); ++i)
522    textEditDiskSummary->append(summary.at(i));
523               
524  textEditDiskSummary->moveCursor(QTextCursor::Start);
525 
526  // Regenerate the config
527  startConfigGen();
528}
529
530void Installer::slotDesktopLeftClicked()
531{
532  if ( wheelCurItem >= 10 ) {
533    int ret = QMessageBox::question(this, tr("PC-BSD Installer"),
534                              tr("You currently have a custom package set configured. Continue changing to a default set?"),
535                              QMessageBox::No | QMessageBox::Yes,
536                              QMessageBox::No);
537    switch (ret) {
538    case QMessageBox::Yes:
539        break;
540    case QMessageBox::No: // :)
541        return;
542        break;
543    }
544    wheelCurItem = wheelCurItem - 10;
545    graphicsViewOS->setScene(defaultScene);
546  }
547  moveDesktopWheel(false);
548}
549
550void Installer::slotDesktopRightClicked()
551{
552  if ( wheelCurItem >= 10 ) {
553    int ret = QMessageBox::question(this, tr("PC-BSD Installer"),
554                              tr("You currently have a custom package set configured. Continue changing to a default set?"),
555                              QMessageBox::No | QMessageBox::Yes,
556                              QMessageBox::No);
557    switch (ret) {
558    case QMessageBox::Yes:
559        break;
560    case QMessageBox::No: // :)
561        return;
562        break;
563    }
564    wheelCurItem = wheelCurItem - 10;
565    graphicsViewOS->setScene(defaultScene);
566  }
567  moveDesktopWheel(true);
568}
569
570void Installer::moveDesktopWheel(bool direction)
571{
572  qDebug() << wheelCurItem << direction;
573  // Make sure we aren't scrolling too far
574  if ( direction && wheelCurItem >= wheelIcons.size() )
575    return;
576  if ( ! direction && wheelCurItem <= 2 )
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/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 == 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 ) {
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 != 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 != wPCSERVER && wheelCurItem != 12 ) {
1018    // Doing PC-BSD Install
1019
1020    QString lang;
1021    if ( comboLanguage->currentIndex() != 0 )
1022      lang = languages.at(comboLanguage->currentIndex());
1023    else
1024      lang="en_US";
1025
1026    // Setup the desktop
1027    cfgList << "runCommand=sh /usr/local/share/pcbsd/scripts/sys-init.sh desktop " + lang;
1028
1029    // Setup for a fresh system first boot
1030    cfgList << "# Touch flags to enable PC-BSD setup at first boot";
1031    cfgList << "runCommand=touch /var/.runxsetup";
1032    cfgList << "runCommand=touch /var/.pcbsd-firstboot";
1033    cfgList << "runCommand=touch /var/.pcbsd-firstgui";
1034
1035  } else if ( wheelCurItem == wPCSERVER || wheelCurItem == 12 ) {
1036    // Doing TrueOS Install
1037    cfgList+=getUsersCfgSettings();
1038
1039    // Enable SSH?
1040    if ( fSSH )
1041      cfgList << "runCommand=echo 'sshd_enable=\"YES\"' >>/etc/rc.conf";
1042
1043    // Setup the TrueOS server
1044    cfgList << "runCommand=sh /usr/local/share/pcbsd/scripts/sys-init.sh server";
1045
1046  } 
1047
1048  // Run newaliases to fix mail errors
1049  cfgList << "runCommand=newaliases";
1050
1051  // Now write out the cfgList to file
1052  QFile cfgfile( PCSYSINSTALLCFG );
1053  if ( cfgfile.open( QIODevice::WriteOnly ) ) {
1054    QTextStream stream( &cfgfile );
1055    for ( int i=0; i < cfgList.count(); ++i) {
1056      stream <<  cfgList.at(i) << "\n";
1057    }
1058    cfgfile.close();
1059  }
1060}
1061
1062void Installer::slotHelp()
1063{
1064        pcHelp = new dialogHelp();
1065        switch (installStackWidget->currentIndex()) {
1066        case 0:
1067                pcHelp->dialogInit(HELPTEXT0);
1068                break;
1069        case 1:
1070                pcHelp->dialogInit(HELPTEXT1);
1071                break;
1072        case 2:
1073                pcHelp->dialogInit(HELPTEXT2);
1074                break;
1075        case 3:
1076                pcHelp->dialogInit(HELPTEXT3);
1077                break;
1078        default:
1079                pcHelp->dialogInit("No help text...");
1080                break;
1081        }
1082        pcHelp->show();
1083}
1084
1085// Function which returns the pc-sysinstall cfg data
1086QStringList Installer::getDiskCfgSettings()
1087{
1088  QStringList tmpList;
1089  QList<QStringList> copyList;
1090  QString tmp, workingDisk, workingSlice, tmpSlice, XtraTmp, startPart, sliceSize;
1091  int disk = 0;
1092
1093  // Copy over the list to a new variable we can mangle without modifying the original
1094  copyList = sysFinalDiskLayout;
1095
1096  // Doing manual extraction
1097  if ( copyList.at(0).at(0) == "MANUAL" )
1098    return QStringList();
1099
1100  while ( ! copyList.empty() )
1101  {
1102    workingDisk = copyList.at(0).at(0);
1103    workingSlice = copyList.at(0).at(1);
1104    tmpSlice = workingSlice;
1105    tmpList << "# Disk Setup for " + workingDisk ;
1106
1107    // Check if this is an install to "Unused Space"
1108    for (int z=0; z < sysDisks.count(); ++z)
1109      if ( sysDisks.at(z).at(0) == "SLICE" \
1110        && sysDisks.at(z).at(2) == workingDisk + workingSlice \
1111        && sysDisks.at(z).at(4) == "Unused Space" )
1112          tmpSlice = "free";
1113
1114    tmpList << "disk" + tmp.setNum(disk) + "=" + workingDisk;
1115    tmpList << "partition=" + tmpSlice;
1116
1117    // Are we loading a boot-loader?
1118    if ( loadMBR )
1119      tmpList << "bootManager=bsd";
1120    else
1121      tmpList << "bootManager=none";
1122
1123    // Set the GPT/MBR options
1124    if ( loadGPT ) 
1125      tmpList << "partscheme=GPT";
1126    else
1127      tmpList << "partscheme=MBR";
1128
1129    tmpList << "commitDiskPart";
1130    tmpList << "";
1131
1132    // If after doing the mirror, our list is empty, break out
1133    if ( copyList.empty() )
1134      break;
1135   
1136    // Now print the partition section for this slice
1137    tmpList << "# Partition Setup for " + workingDisk + "(" + workingSlice + ")";
1138    tmpList << "# All sizes are expressed in MB";
1139    tmpList << "# Avail FS Types, UFS, UFS+S, UFS+SUJ, UFS+J, ZFS, SWAP";
1140    tmpList << "# UFS.eli, UFS+S.eli, UFS+SUJ, UFS+J.eli, ZFS.eli, SWAP.eli";
1141
1142    // If there is a dedicated /boot partition, need to list that first, see what is found
1143    for (int i=0; i < copyList.count(); ++i) {
1144      QStringList mounts = copyList.at(i).at(2).split(",");
1145      for (int z = 0; z < mounts.size(); ++z) {
1146        if ( copyList.at(i).at(0) == workingDisk \
1147          && copyList.at(i).at(1) == workingSlice \
1148          && mounts.at(z) == "/boot" )
1149                startPart="/boot";
1150      }
1151    }
1152
1153    // If no dedicated /boot partition, then lets list "/" first
1154    if(startPart.isEmpty())
1155        startPart="/";
1156
1157    // Start by looking for the root partition
1158    for (int i=0; i < copyList.count(); ++i) {
1159      QStringList mounts = copyList.at(i).at(2).split(",");
1160      for (int z = 0; z < mounts.size(); ++z) {
1161        if ( copyList.at(i).at(0) == workingDisk \
1162          && copyList.at(i).at(1) == workingSlice \
1163          && mounts.at(z) == startPart ) {
1164
1165          // Check if we have any extra arguments to throw on the end
1166          XtraTmp="";
1167          if ( ! copyList.at(i).at(5).isEmpty() )
1168            XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1169
1170          // Write out the partition line
1171          tmpList << "disk" + tmp.setNum(disk) + "-part=" \
1172                   + copyList.at(i).at(3) + " " + copyList.at(i).at(4) \
1173                   + " " + copyList.at(i).at(2) + XtraTmp;
1174
1175          // Check if we have an encryption passphrase to use
1176          if ( ! copyList.at(i).at(6).isEmpty() )
1177            tmpList << "encpass=" + copyList.at(i).at(6);
1178
1179          // Done with this item, remove it now
1180          copyList.removeAt(i);
1181          break;
1182        }
1183      }
1184    }
1185
1186    // Now look for SWAP
1187    for (int i=0; i < copyList.count(); ++i) {
1188      if ( copyList.at(i).at(0) == workingDisk \
1189        && copyList.at(i).at(1) == workingSlice \
1190        && copyList.at(i).at(2) == "SWAP" ) {
1191
1192        // Write the partition line
1193        tmpList << "disk" + tmp.setNum(disk) + "-part=" \
1194                 + copyList.at(i).at(3) + " " + copyList.at(i).at(4) \
1195                 + " none";
1196
1197        // Done with this item, remove it now
1198        copyList.removeAt(i);
1199        break;
1200      }
1201    }
1202 
1203    // Now look for any other partitions
1204    int count = copyList.count();
1205    for (int i=0; i < count; ++i) {
1206      if ( copyList.at(i).at(0) == workingDisk \
1207        && copyList.at(i).at(1) == workingSlice ) {
1208
1209        // Check if we have any extra arguments to throw on the end
1210        XtraTmp="";
1211        if ( ! copyList.at(i).at(5).isEmpty() )
1212          XtraTmp=" (" + copyList.at(i).at(5) + ")" ;
1213
1214        // If we are working on the last partition, set the size to 0 to use remaining disk
1215        if ( i == (count - 1) ) 
1216                sliceSize = "0";
1217        else
1218                sliceSize=copyList.at(i).at(4);
1219
1220        // Write the partition line
1221        tmpList << "disk" + tmp.setNum(disk) + "-part=" \
1222                 + copyList.at(i).at(3) + " " + sliceSize \
1223                 + " " + copyList.at(i).at(2) + XtraTmp;
1224
1225        // Check if we have an encryption passphrase to use
1226        if ( ! copyList.at(i).at(6).isEmpty() )
1227          tmpList << "encpass=" + copyList.at(i).at(6);
1228
1229        // Done with this item, remove it now
1230        copyList.removeAt(i);
1231        i--;
1232        count--;
1233      }
1234    }
1235
1236
1237    // Close out this partition section
1238    tmpList << "commitDiskLabel";
1239    tmpList << "";
1240
1241    // Increment our disk counter
1242    disk++;
1243  }
1244
1245  return tmpList;
1246}
1247
1248// Slot which checks any disk requirements before procceding to the next page
1249bool Installer::checkDiskRequirements()
1250{
1251  // For now just return true, the wizard should handle making sure
1252  // the user doesn't shoot themselves in the foot during disk setup
1253  return true;
1254}
1255
1256// Function which begins the backend install, and connects slots to monitor it
1257void Installer::startInstall()
1258{
1259  // Disable the back / next buttons until we are finished
1260  nextButton->setEnabled(false);
1261  backButton->setEnabled(false);
1262  progressBarInstall->setValue(0); 
1263  installFoundCounter = false;
1264  installFoundMetaCounter = false;
1265  installFoundFetchOutput = false;
1266
1267  // Setup some defaults for the secondary progress bar
1268  progressBarInstall2->setValue(0); 
1269  progressBarInstall2->setHidden(true); 
1270  labelInstallStatus2->setText("");
1271  labelInstallStatus2->setHidden(true);
1272
1273  // Kill any hald instances, which causes failures to install when it
1274  // tries to mount our new partitions
1275  QProcess::execute("killall", QStringList() << "hald");
1276
1277  // Start our process to begin the install
1278  QString PCSYSINSTALL;
1279  if ( QFile::exists("/root/pc-sysinstall/pc-sysinstall") ) 
1280     PCSYSINSTALL = "/root/pc-sysinstall/pc-sysinstall";
1281  else 
1282     PCSYSINSTALL = "/usr/local/sbin/pc-sysinstall";
1283
1284  QString program = PCSYSINSTALL;
1285  QStringList arguments;
1286  arguments << "-c" << PCSYSINSTALLCFG;
1287
1288  installProc = new QProcess();
1289  installProc->setProcessChannelMode(QProcess::MergedChannels);
1290  connect(installProc,SIGNAL(finished( int, QProcess::ExitStatus)),this,SLOT(slotInstallProcFinished( int, QProcess::ExitStatus)));
1291  connect(installProc,SIGNAL(readyRead()),this,SLOT(slotReadInstallerOutput()));
1292  installProc->start(program, arguments);
1293
1294}
1295
1296// Function run when the install failed to prompt user for course of action
1297void Installer::installFailed()
1298{
1299   QString sysLog;
1300   labelInstallStatus->setText(tr("Failed!"));
1301
1302   QMessageBox msgBox;
1303   msgBox.setWindowTitle(tr("PC-BSD Installer"));
1304   msgBox.setIcon(QMessageBox::Critical);
1305   msgBox.setText(tr("The installer has encountered an error and has been halted."));
1306   msgBox.setInformativeText(tr("Do you want to generate an error report?"));
1307   msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1308   msgBox.setDefaultButton(QMessageBox::Yes);
1309
1310   // If we have a log, show it in the detailed view button
1311   if ( QFile::exists("/tmp/.pc-sysinstall/pc-sysinstall.log") )
1312   {
1313     QFile logFile("/tmp/.pc-sysinstall/pc-sysinstall.log");
1314     if (logFile.open(QIODevice::ReadOnly | QIODevice::Text))
1315         while (!logFile.atEnd())
1316           sysLog = sysLog + logFile.readLine() + "\n";
1317     msgBox.setDetailedText(sysLog);
1318   }
1319   int ret = msgBox.exec();
1320
1321   switch (ret) {
1322   case QMessageBox::Yes:
1323       // Generate the error report
1324       Scripts::Backend::createErrorReport();
1325       break;
1326   case QMessageBox::No: // :)
1327       break;
1328   }
1329
1330   QMessageBox msgBox2;
1331   msgBox2.setWindowTitle(tr("PC-BSD Installer"));
1332   msgBox2.setIcon(QMessageBox::Critical);
1333   msgBox2.setText(tr("Restart the system now?") );
1334   msgBox2.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1335   msgBox2.setDefaultButton(QMessageBox::Yes);
1336   msgBox2.setDetailedText(sysLog);
1337
1338   ret = msgBox2.exec();
1339
1340   switch (ret) {
1341   case QMessageBox::Yes:
1342       close();
1343       break;
1344   case QMessageBox::No: // :)
1345       break;
1346   }
1347
1348}
1349
1350// Slot which is called when the installation has finished
1351void Installer::slotInstallProcFinished( int exitCode, QProcess::ExitStatus status)
1352{
1353  QString tmp;
1354  if ( status != QProcess::NormalExit || exitCode != 0 )
1355  {
1356     installFailed();
1357  } else {
1358    // Move to the final page, and show a finish button
1359    proceed(true);
1360    nextButton->setEnabled(true);
1361    nextButton->setText(tr("&Finish"));
1362    nextButton->disconnect();
1363    connect(nextButton, SIGNAL(clicked()), this, SLOT(slotFinished()));
1364    backButton->setEnabled(false);
1365    abortButton->setEnabled(false);
1366  }
1367}
1368
1369// Slot which reads the output of the installer
1370void Installer::slotReadInstallerOutput()
1371{
1372  QString tmp, line;
1373  int range;
1374  bool ok;
1375
1376
1377  while ( installProc->canReadLine() )
1378  {
1379     tmp = installProc->readLine();
1380     tmp.truncate(75);
1381     //qDebug() << tmp;
1382
1383     // If doing a restore, don't bother checking for other values
1384     //if ( radioRestore->isChecked() ) {
1385     //   labelInstallStatus->setText(tmp);
1386     // continue;
1387     //}
1388
1389     // Parse fetch output
1390     if ( installFoundFetchOutput ) {
1391       if ( tmp.indexOf("SIZE: ") != -1 ) {
1392
1393          // Get the total range first
1394          line = tmp;
1395          tmp = tmp.remove(0, tmp.indexOf(":") + 2 );
1396          tmp.truncate(tmp.indexOf(" ")); 
1397          range = tmp.toInt(&ok);
1398          if ( ok )
1399             progressBarInstall->setRange(0, range + 1);
1400
1401          // Now get the current progress
1402          tmp = line;
1403          tmp = tmp.remove(0, tmp.indexOf(":") + 2 );
1404          tmp = tmp.remove(0, tmp.indexOf(":") + 2 );
1405          range = tmp.toInt(&ok);
1406          if ( ok )
1407             progressBarInstall->setValue(range);
1408           
1409          continue;
1410        } else {
1411          installFoundFetchOutput = false;
1412          break;
1413        }
1414     } 
1415
1416     // Unknown point in install
1417     if ( ! installFoundCounter && ! installFoundMetaCounter ) {
1418
1419        // Check if we've found fetch output to update the progress bar with
1420        if ( tmp.indexOf("FETCH: ") != -1 ) {
1421          installFoundFetchOutput = true;
1422          break;
1423        }
1424
1425        if ( tmp.indexOf("INSTALLCOUNT: ") != -1 ) {
1426          tmp = tmp.remove(0, tmp.indexOf(":") + 1 ); 
1427          range = tmp.toInt(&ok);
1428          if ( ok ) {
1429             range = range + 50;
1430             progressBarInstall->setRange(0, range + 1); 
1431             installFoundCounter = true;
1432             if ( availDesktopPackageData )
1433                labelInstallStatus->setText(tr("Extracting system...")); 
1434             else
1435                labelInstallStatus->setText(tr("Installing system... This may take a while...")); 
1436          }
1437
1438          break;
1439
1440        } 
1441
1442        // Check if we are on the meta-pkg installation
1443        if ( tmp.indexOf("Packages to install: ") != -1 ) {
1444          tmp = tmp.remove(0, tmp.indexOf(":") + 1 ); 
1445          range = tmp.toInt(&ok);
1446          if ( ok ) {
1447             progressBarInstall->setRange(0, range + 1); 
1448             progressBarInstall->setValue(0); 
1449             progressBarInstall2->setRange(0, 0); 
1450             labelInstallStatus2->setHidden(false);
1451             progressBarInstall2->setHidden(false); 
1452             installFoundMetaCounter = true;
1453             installFoundCounter = false;
1454             labelInstallStatus->setText(tr("Installing packages... This may take a while...")); 
1455             continue;
1456          }
1457
1458        } 
1459
1460        labelInstallStatus->setText(tmp);
1461        continue; 
1462     } 
1463
1464     // Doing file-extraction still
1465     if ( installFoundCounter ) {
1466
1467       // Doing dist-files, may have multiple images to extract
1468       if ( tmp.indexOf("INSTALLCOUNT: ") != -1 ) {
1469         tmp = tmp.remove(0, tmp.indexOf(":") + 1 ); 
1470         range = tmp.toInt(&ok);
1471         if ( ok ) {
1472            progressBarInstall->setRange(0, range + 1); 
1473            installFoundCounter = true;
1474            if ( availDesktopPackageData )
1475              labelInstallStatus->setText(tr("Extracting system...")); 
1476            else
1477              labelInstallStatus->setText(tr("Installing system... This may take a while...")); 
1478         }
1479         break;
1480       } 
1481
1482
1483       // Increment the progress
1484       progressBarInstall->setValue(progressBarInstall->value() + 1); 
1485
1486       // We've reached the end of this counted section
1487       if ( tmp.indexOf("Extraction Finished") != -1 ) {
1488         installFoundCounter = false;
1489         progressBarInstall->setRange(0, 0); 
1490       }
1491
1492       continue;
1493     }
1494
1495     // Doing meta-pkgs
1496     if ( installFoundMetaCounter ) {
1497        if ( tmp.indexOf("Package installation complete!") != -1 ) {
1498           installFoundMetaCounter = false;
1499           progressBarInstall->setRange(0, 0); 
1500           progressBarInstall2->setHidden(true);
1501           labelInstallStatus2->setHidden(true);
1502           continue;
1503        }
1504
1505        // If we are installing a package, show details to user
1506        if ( tmp.indexOf("Installing") == 0 )
1507          labelInstallStatus2->setText(tmp.section("...", 0, 0));
1508     }
1509
1510  } // end of while loop
1511}
1512
1513// Return list of components to install
1514QStringList Installer::getComponentCfgSettings()
1515{
1516  QStringList componentList, com;
1517  if ( fSRC )
1518    com << "src";
1519  if ( fPORTS )
1520    com << "ports";
1521
1522  if ( ! com.isEmpty() ) {
1523    componentList << "";
1524    componentList << "# Optional Components";
1525    componentList << "installComponents=" + com.join(",");
1526  }
1527
1528  return componentList;
1529}
1530
1531// Start xvkbd
1532void Installer::slotPushVirtKeyboard()
1533{
1534   system("killall -9 xvkbd; xvkbd -compact &");
1535}
1536
1537// Return the configuration for desktop packages
1538QStringList Installer::getDeskPkgCfg()
1539{
1540   QStringList cfgList, pkgList;
1541   QString line;
1542
1543   QList<QStringList> curList;
1544
1545   if ( wheelCurItem != wPCSERVER && wheelCurItem != 11 && wheelCurItem != 12) {
1546     curList = listDeskPkgs;
1547     pkgList << "pcbsd-base";
1548   } else {
1549     curList = listServerPkgs;
1550     pkgList << "trueos-base";
1551   }
1552
1553   // Loop though list of pkgs, see what to install
1554   for ( int d=0; d < curList.count(); ++d) {
1555     for ( int i=0; i < selectedPkgs.count(); ++i)
1556        // Is the package selected or the base-system?
1557        if ( curList.at(d).at(0) == selectedPkgs.at(i) || curList.at(d).at(0) == "base-system" ) {
1558
1559           // Yay! Lets get a list of packages to install
1560           QFile mFile;
1561           mFile.setFileName(curList.at(d).at(6));
1562           if ( ! mFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
1563              qDebug() << "Invalid meta-pkg list:" << curList.at(d).at(6);
1564              break;
1565           }
1566 
1567           // Read in the meta pkg list
1568           QTextStream in(&mFile);
1569           while ( !in.atEnd() ) {
1570             line = in.readLine().simplified();
1571             if ( line.isEmpty() )
1572                 continue; 
1573             
1574             pkgList << line.section(":", 0,0);
1575           }
1576           mFile.close();
1577           break;
1578        }
1579   }
1580
1581   cfgList << "installPackages=" + pkgList.join(" ");
1582   return cfgList;
1583}
1584
1585// Return list of users in cfg format
1586QStringList Installer::getUsersCfgSettings()
1587{
1588   QStringList userList;
1589 
1590   userList << "";
1591   userList << "# Root Password";
1592   userList << "rootPass=" + fRootPW;
1593
1594   userList << "";
1595   userList << "# Users";
1596   userList << "userName=" + fUserName;
1597   userList << "userComment=" + fName;
1598   userList << "userPass=" + fUserPW;
1599   userList << "userShell=" + fShell;
1600   userList << "userHome=/home/" + fUserName;
1601   userList << "userGroups=wheel,operator";
1602   userList << "commitUser";
1603   userList << "";
1604 
1605   return userList;
1606}
1607
1608void Installer::closeEvent(QCloseEvent *event)
1609{
1610    int ret = QMessageBox::question(this, tr("PC-BSD Installer"),
1611                                tr("Are you sure you want to abort this installation?"),
1612                                QMessageBox::No | QMessageBox::Yes,
1613                                QMessageBox::No);
1614    switch (ret) {
1615    case QMessageBox::Yes:
1616        //exit the installer :(
1617        break;
1618    case QMessageBox::No: // :)
1619        event->ignore();
1620        break;
1621    }
1622}
1623
1624void Installer::checkSpaceWarning()
1625{
1626  int totalSize = -1;
1627  int targetSize;
1628  int targetLoc;
1629  bool ok;
1630  QString workingDisk = sysFinalDiskLayout.at(0).at(0);
1631  QString workingSlice = sysFinalDiskLayout.at(0).at(1);
1632  QString targetType;
1633  QString target;
1634  //qDebug() << "Disk layout:" << workingDisk << workingSlice;
1635
1636  if ( workingSlice == "ALL" ) {
1637    targetType = "DRIVE";
1638    target = workingDisk;
1639    targetLoc = 1;
1640  } else {
1641    targetType = "SLICE";
1642    target = workingDisk + workingSlice;
1643    targetLoc = 2;
1644  }
1645 
1646  // Lets get the size for this disk / partition
1647  for (int i=0; i < sysDisks.count(); ++i) {
1648      // Make sure to only add the slices to the listDiskSlices
1649      if ( sysDisks.at(i).at(0) == targetType && target == sysDisks.at(i).at(targetLoc))
1650        totalSize = sysDisks.at(i).at(targetLoc + 1).toInt(&ok);
1651  }
1652
1653  //qDebug() << totalSize;
1654
1655  if ( installStackWidget->currentIndex() == 1 && (wheelCurItem == wPCSERVER || wheelCurItem == 12) )
1656     targetSize=20000;
1657  else
1658     targetSize=50000;
1659
1660  int tGB = targetSize / 1000;
1661
1662  qDebug() << totalSize << targetSize;
1663
1664  // Lets print a nice handy warning for users with possible
1665  // low disk space issues
1666  if ( totalSize < targetSize ) {
1667  QMessageBox::warning(this, tr("PC-BSD Installer"),
1668      QString(tr("The selected disk / partition is less than recommended %1GB. The installation may fail...")).arg(tGB),
1669      QMessageBox::Ok,
1670      QMessageBox::Ok);
1671      haveWarnedSpace = true;     
1672  }
1673
1674  return;
1675}
Note: See TracBrowser for help on using the repository browser.