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

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

Add UI functionality to load a pc-sysinstall config file from USB media, and install with it

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