summaryrefslogtreecommitdiffstats
path: root/src/arkollon/wizard.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/arkollon/wizard.cpp')
-rw-r--r--src/arkollon/wizard.cpp950
1 files changed, 950 insertions, 0 deletions
diff --git a/src/arkollon/wizard.cpp b/src/arkollon/wizard.cpp
new file mode 100644
index 0000000..8e92ebf
--- /dev/null
+++ b/src/arkollon/wizard.cpp
@@ -0,0 +1,950 @@
+/***************************************************************************
+ * Copyright (C) 2004 by David Sansome *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+#include "wizard.h"
+
+#include <qfiledialog.h>
+#include <qwidgetstack.h>
+#include <qpushbutton.h>
+#include <qpainter.h>
+#include <qheader.h>
+#include <qapplication.h>
+#include <qmessagebox.h>
+#include <qprogressbar.h>
+#include <qradiobutton.h>
+#include <qtextedit.h>
+#include <qlineedit.h>
+#include <qpopupmenu.h>
+#include <qhbox.h>
+#include <qfileinfo.h>
+#include <qlabel.h>
+#include <qfontmetrics.h>
+#include <qcheckbox.h>
+
+#include "data.h"
+
+#include "rcparser.h"
+#include "headerlistitem.h"
+
+typedef QValueVector<CompileError> CompileErrorVector;
+CompileErrorVector errs( 5 ); // vector of 3 Employees
+
+
+ComponentListItem::ComponentListItem(struct Component c, QListView* parent)
+ : QCheckListItem(parent, "", QCheckListItem::CheckBox)
+{
+ component = c;
+ setText(0, c.niceName);
+ setOn(true);
+
+ if (c.gnomeOnly)
+ section=2;
+ else if (c.kdeOnly)
+ section=3;
+ else if (c.optional)
+ section=1;
+ else
+ section=0;
+
+
+}
+
+int ComponentListItem::compare(QListViewItem* i, int col, bool ascending) const
+{
+ switch (i->rtti())
+ {
+ case 1001: // Component
+ {
+ ComponentListItem* item = (ComponentListItem*) i;
+ if (section < item->section)
+ return -1;
+ if (section > item->section)
+ return 1;
+ return QListViewItem::compare(i, col, ascending);
+ }
+ break;
+
+ case 1002: // Header
+ {
+ HeaderListItem* item = (HeaderListItem*) i;
+ if (section < item->section)
+ return -1;
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
+
+
+Wizard::Wizard(QWidget *parent, const char *name)
+ : WizardBase(parent, name, false, WDestructiveClose)
+{
+ componentInfo->setMaximumSize(32767,70);
+ componentList->header()->hide();
+ //progressLabel2->setMaximumSize(32767, progressLabel2->fontMetrics().height()*2);
+ externalProcess = new QProcess(this);
+ connect(externalProcess, SIGNAL(processExited()), SLOT(processExited()));
+ connect(externalProcess, SIGNAL(readyReadStdout()), SLOT(readyReadStdout()));
+ connect(externalProcess, SIGNAL(readyReadStderr()), SLOT(readyReadStderr()));
+
+ logDialog = new LogDialog(this);
+ logDialog->hide();
+ previousButton->hide();
+
+ createActionFormats();
+
+ kdeDirProcess = new QProcess(this);
+ connect(kdeDirProcess, SIGNAL(readyReadStdout()), SLOT(kdeDirReady()));
+ connect(kdeDirProcess, SIGNAL(processExited()), SLOT(getInstalledComponents()));
+ kdeDirProcess->addArgument("kde-config");
+ kdeDirProcess->addArgument("--prefix");
+ if (!kdeDirProcess->start())
+ getInstalledComponents();
+
+ errs[0] = CompileError( "libevent", "The installation process finished with an error because it needs a "
+ " component missing on your system. To correct this, "
+ "do the following: <br> 1. Download and install the package for your distribution with the word 'libevent' in its title. <br> 2. Retry installation." );
+ errs[1] = CompileError( "X includes", "The installation process finished with an error because it needs a "
+ " component missing on your system. To correct this, "
+ "do the following: <br> 1. Download and install any packages for your distribution with (i) 'X' and "
+ " either 'devel' or 'lib' in their name. <br> 2. Retry installation. " );
+ errs[2] = CompileError( "There is no user 'privoxy' on this system", "The installation reported an"
+ "error because you need to create the 'privoxy' user. To correct this, "
+ "do the following: <br> 1. As root, enter the following command: useradd privoxy. <br> 2. Retry installation. " );
+ errs[3] = CompileError( "installing config files as root", "The installation reported an"
+ "error because I attempted to install the privoxy config files as root. <b> There is no "
+ "need to take any action on your part. Privoxy has been installed and you can now use it with TorK. " );
+ errs[4] = CompileError( "Qt (>= ", "The installation process finished with an error because it needs a "
+ " component missing on your system. To correct this, "
+ "do the following: <br> 1. Download and install any packages for your distribution with (i) 'qt' and "
+ " either 'devel' or 'lib' in their name. <br> 2. Retry installation. " );
+
+
+
+
+}
+
+void Wizard::createActionFormats()
+{
+ // Taken from KDevelop
+ actionFormats.clear();
+ actionFormats.append(ActionFormat( tr("compiling"), "g++", "g\\+\\+\\S* (?:\\S* )*-c (?:\\S* )*`[^`]*`(?:[^/\\s;]*/)*([^/\\s;]+)", 1 ));
+ actionFormats.append(ActionFormat( tr("compiling"), "g++", "g\\+\\+\\S* (?:\\S* )*-c (?:\\S* )*(?:[^/]*/)*([^/\\s;]*)", 1 ));
+ actionFormats.append(ActionFormat( tr("compiling"), "gcc", "gcc\\S* (?:\\S* )*-c (?:\\S* )*`[^`]*`(?:[^/\\s;]*/)*([^/\\s;]+)", 1 ));
+ actionFormats.append(ActionFormat( tr("compiling"), "gcc", "gcc\\S* (?:\\S* )*-c (?:\\S* )*(?:[^/]*/)*([^/\\s;]*)", 1 ));
+ actionFormats.append(ActionFormat( tr("compiling"), "distcc", "distcc (?:\\S* )*-c (?:\\S* )*`[^`]*`(?:[^/\\s;]*/)*([^/\\s;]+)", 1 ));
+ actionFormats.append(ActionFormat( tr("compiling"), "distcc", "distcc (?:\\S* )*-c (?:\\S* )*(?:[^/]*/)*([^/\\s;]*)", 1 ));
+ actionFormats.append(ActionFormat( tr("compiling"), "unknown", "^compiling (.*)", 1 ));
+ actionFormats.append(ActionFormat( tr("generating"), "moc", "/moc\\b.*\\s-o\\s([^\\s;]+)", 1 ));
+ actionFormats.append(ActionFormat( tr("generating"), "uic", "/uic\\b.*\\s-o\\s([^\\s;]+)", 1 ));
+ actionFormats.append(ActionFormat( tr("linking"), "libtool", "/+bin/+sh\\s.*libtool.*--mode=link\\s.*\\s-o\\s([^\\s;]+)", 1 ));
+ actionFormats.append(ActionFormat( tr("linking"), "g++", "g\\+\\+\\S* (?:\\S* )*-o ([^\\s;]+)", 1 ));
+ actionFormats.append(ActionFormat( tr("linking"), "gcc", "gcc\\S* (?:\\S* )*-o ([^\\s;]+)", 1 ));
+ actionFormats.append(ActionFormat( tr("creating"), "", "/(?:bin/+sh\\s.*mkinstalldirs).*\\s([^\\s;]+)", 1 ));
+ actionFormats.append(ActionFormat( tr("installing"), "", "/(?:usr/+bin/+install|bin/+sh\\s.*mkinstalldirs|bin/+sh\\s.*libtool.*--mode=install).*\\s\\'?([^\\s;\\']+)\\'?", 1 ));
+ actionFormats.append(ActionFormat( tr("generating"), "dcopidl", "dcopidl .* > ([^\\s;]+)", 1 ));
+ actionFormats.append(ActionFormat( tr("compiling"), "dcopidl2cpp", "dcopidl2cpp (?:\\S* )*([^\\s;]+)", 1 ));
+}
+
+void Wizard::kdeDirReady()
+{
+ while (kdeDirProcess->canReadLineStdout())
+ {
+ QString line = kdeDirProcess->readLineStdout();
+ if (!line.isEmpty())
+ kdeDir = line;
+ }
+}
+
+void Wizard::getInstalledComponents()
+{
+ QFile uninstallScript("/tmp/arkollon-uninstall.sh");
+ if (uninstallScript.exists())
+ uninstallScript.remove();
+ uninstallScript.open(IO_WriteOnly);
+ QDataStream stream(&uninstallScript);
+ stream.writeRawBytes((const char*)uninstaller_sh_data, uninstaller_sh_len);
+ uninstallScript.close();
+
+ installedComponentsProcess = new QProcess(this);
+ connect(installedComponentsProcess, SIGNAL(readyReadStdout()), SLOT(installedComponentsReady()));
+ connect(installedComponentsProcess, SIGNAL(processExited()), SLOT(setup()));
+ installedComponentsProcess->addArgument("/bin/sh");
+ installedComponentsProcess->addArgument("/tmp/arkollon-uninstall.sh");
+ installedComponentsProcess->addArgument("--list");
+ if (!installedComponentsProcess->start())
+ setup();
+}
+
+void Wizard::installedComponentsReady()
+{
+ while (installedComponentsProcess->canReadLineStdout())
+ {
+ QString line = installedComponentsProcess->readLineStdout();
+ if (line.isEmpty())
+ continue;
+
+ // See if it already exists
+ if (installedComponents.find(line.lower()) != installedComponents.end())
+ continue;
+
+ installedComponents.append(line.lower());
+ //printf("Found installed component %s\n", parser.cap(3).latin1());
+ }
+}
+
+void Wizard::setup()
+{
+ QFile uninstallScript("/tmp/arkollon-uninstall.sh");
+ if (uninstallScript.exists())
+ uninstallScript.remove();
+
+ if (kdeDir.isEmpty())
+ kdeDir = "/usr";
+
+ // Firstly check if there's an arkollonrc file in the current directory
+ // If there is, use it.
+ dir = QDir::currentDirPath();
+ if (qApp->argc() > 1)
+ {
+ // The directory specified on the command line overrides the current dir.
+ QDir d(qApp->argv()[1]);
+ dir = d.absPath();
+ }
+ if (QFile::exists(dir + "/arkollonrc"))
+ {
+ setupFromRc();
+ }
+ else
+ {
+ if (!setupFromDir())
+ {
+ QMessageBox::critical(NULL, "Error", "This directory does not contain any recognised buildsystem", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
+ reject();
+ return;
+ }
+ }
+ show();
+}
+
+void Wizard::setupFromRc()
+{
+ RcParser parser;
+ parser.addSearchDir(dir);
+ if (!parser.openFile("arkollonrc"))
+ {
+ QMessageBox::critical(NULL, "Error", "The \"arkollonrc\" file in this directory could not be read", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
+ reject();
+ return;
+ }
+
+ parser.setSection("Arkollon");
+ QString appName = parser.readString("AppName");
+ if (appName.isEmpty())
+ {
+ QMessageBox::critical(NULL, "Error", "The \"arkollonrc\" file in this directory contains no application name!", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
+ reject();
+ return;
+ }
+ setAppName(appName);
+
+ QString icon32Path = parser.readString("Icon32");
+ QString icon16Path = parser.readString("Icon16");
+ if ((!icon32Path.isEmpty()) && (QFile::exists(dir + "/" + icon32Path)))
+ {
+ QPixmap icon32(dir + "/" + icon32Path);
+ appIcon->setPixmap(icon32);
+ }
+ if ((!icon16Path.isEmpty()) && (QFile::exists(dir + "/" + icon16Path)))
+ {
+ QPixmap icon16(dir + "/" + icon16Path);
+ setIcon(icon16);
+ }
+
+ buildOrder = parser.readList("BuildOrder");
+ QStringList compNames = parser.readList("Components");
+ QStringList::Iterator it = compNames.begin();
+ while( it != compNames.end() )
+ {
+ parser.setSection(*it);
+
+ struct Component c;
+ c.name = *it;
+ c.niceName = parser.readString("NiceName");
+ c.subDir = parser.readString("SubDir");
+ c.forceDir = sub(parser.readString("ForceDir"));
+ c.optional = parser.readBool("Optional", false);
+ c.kdeOnly = parser.readBool("KDEOnly", false);
+ c.gnomeOnly = parser.readBool("GnomeOnly", false);
+ c.description = sub(parser.readString("Description"));
+ c.confOptions = parser.readString("ConfigureOptions");
+ c.alreadyInstalled = false;
+
+ // Load the buildtimes data
+ if (QFile::exists(dir + "/" + c.subDir + "/buildtimes"))
+ {
+ QRegExp re("([^,]*,[^,]*),(\\d*)");
+ QFile file(dir + "/" + c.subDir + "/buildtimes");
+ file.open(IO_ReadOnly);
+ QTextStream stream(&file);
+ for (;;)
+ {
+ QString line = stream.readLine();
+ if (line.isNull())
+ break;
+ if (re.search(line) == -1)
+ continue;
+ c.buildTimes.insert(re.cap(1), re.cap(2).toInt());
+ }
+ }
+
+ // Add the header for this component
+ ComponentListItem* item = new ComponentListItem(c, componentList);
+ if (!headers.contains(item->section))
+ {
+ headers[item->section] = new HeaderListItem(componentList);
+ ((HeaderListItem*)headers[item->section])->section = item->section;
+
+ switch(item->section)
+ {
+ case 0: headers[item->section]->setText(0, "Required components"); break;
+ case 1: headers[item->section]->setText(0, "Optional components"); break;
+ case 2: headers[item->section]->setText(0, "Gnome specific components"); break;
+ case 3: headers[item->section]->setText(0, "KDE specific components"); break;
+ }
+ }
+
+ // Check if it's already installed
+ QStringList::Iterator it2 = installedComponents.begin();
+ while( it2 != installedComponents.end() )
+ {
+ int dashPos = c.subDir.findRev('-');
+ if (dashPos < 0)
+ dashPos = c.subDir.length();
+ QString version = c.subDir.left(dashPos) + ":" + c.subDir.right(c.subDir.length() - dashPos - 1);
+ if (*it2 == version.lower())
+ {
+ item->setOn(false);
+ item->component.alreadyInstalled = true;
+ }
+ ++it2;
+ }
+
+ ++it;
+ }
+ parser.setSection("Arkollon");
+ exec = sub(parser.readString("Exec"));
+ desktop = sub(parser.readString("Desktop"));
+}
+
+bool Wizard::setupFromDir()
+{
+ if ((!QFile::exists(dir + "/configure")) &&
+ (!QFile::exists(dir + "/autogen.sh")) &&
+ (!QFile::exists(dir + "/auto-gen.sh")))
+ {
+ QDir myDir(dir + "/" + selectedComponents[currentComponent].subDir);
+ if (myDir.entryList("*.pro", QDir::Files).count() <= 0)
+ return false;
+ }
+
+ // Use the directory name as the appname
+ QDir myDir2(dir);
+ QString dirName = myDir2.dirName();
+ setAppName(makeDirNice(dirName));
+
+ buildOrder.append(dirName);
+ struct Component c;
+ c.name = dirName;
+ c.niceName = makeDirNice(dirName);
+ c.optional = false;
+ c.subDir = "";
+ c.gnomeOnly = false;
+ c.kdeOnly = false;
+ c.description = "<i>No description is associated with this component.</i>";
+ c.alreadyInstalled = false;
+ ComponentListItem* item = new ComponentListItem(c, componentList);
+ HeaderListItem* header = new HeaderListItem(componentList);
+ header->setText(0, "Required components");
+ header->section = 0;
+
+ QStringList::Iterator it2 = installedComponents.begin();
+ while( it2 != installedComponents.end() )
+ {
+ int dashPos = dirName.findRev('-');
+ if (dashPos < 0)
+ dashPos = dirName.length();
+ QString version = dirName.left(dashPos) + ":" + dirName.right(dirName.length() - dashPos - 1);
+ if (*it2 == version.lower())
+ item->component.alreadyInstalled = true;
+ ++it2;
+ }
+
+ return true;
+}
+
+
+Wizard::~Wizard()
+{
+}
+
+
+void Wizard::componentSelected(QListViewItem* item)
+{
+ if (item->rtti() != 1001)
+ return;
+
+ ComponentListItem* i = (ComponentListItem*) item;
+ QString text = "<p><b>" + item->text(0) + "</b>";
+ if (i->component.alreadyInstalled)
+ text += " <i>(Already installed)</i>";
+ text += "</p><p>";
+ text += i->component.description;
+ text += "</p>";
+
+ componentInfo->setText(text);
+}
+
+
+QString Wizard::makeDirNice(QString name)
+{
+ int dashPos = name.findRev('-');
+ if (dashPos < 0)
+ dashPos = name.length();
+
+ QString ret = name.left(dashPos);
+ ret = ret.left(1).upper() + ret.right(ret.length()-1);
+
+ return ret;
+}
+
+
+void Wizard::cancelPressed()
+{
+ if (externalProcess->isRunning())
+ externalProcess->tryTerminate();
+
+ reject();
+}
+
+void Wizard::nextPressed()
+{
+ int currentId = installStack->id(installStack->visibleWidget());
+ if (currentId == 3)
+ {
+ QDir d(kdeDir);
+ d.mkdir("share/apps/kdesktop/Desktop");
+ if (shortcutBox->isChecked())
+ {
+ QFile source(dir + "/" + desktop);
+ QString destDir = kdeDir + "/share/apps/kdesktop/Desktop";
+ int slashPos = desktop.findRev('/');
+ if (slashPos < 0)
+ slashPos = 0;
+ QFile dest(destDir + "/" + desktop.right(desktop.length() - slashPos));
+ source.open(IO_ReadOnly);
+ dest.open(IO_WriteOnly | IO_Truncate);
+ QDataStream destStream(&dest);
+ QByteArray data = source.readAll();
+ destStream.writeRawBytes(data.data(), data.size());
+ source.close();
+ dest.close();
+ }
+ if (uninstallBox->isChecked())
+ {
+ QFile source(dir + "/Uninstall TorK.desktop");
+ QFile dest(kdeDir + "/share/apps/kdesktop/Desktop/Uinstall TorK.desktop");
+ source.open(IO_ReadOnly);
+ dest.open(IO_WriteOnly | IO_Truncate);
+ QDataStream destStream(&dest);
+ QByteArray data = source.readAll();
+ destStream.writeRawBytes(data.data(), data.size());
+ source.close();
+ dest.close();
+ }
+ accept();
+ return;
+ }
+ if ((currentId == 2) && (exec.isEmpty()))
+ {
+ accept();
+ return;
+ }
+
+ if (currentId == 1)
+ {
+ bool itemsSelected = false;
+
+ QListViewItemIterator it( componentList );
+ while ( it.current() )
+ {
+ if (it.current()->rtti() != 1001)
+ {
+ ++it;
+ continue;
+ }
+ ComponentListItem* item = (ComponentListItem*) it.current();
+ if (item->isOn())
+ itemsSelected = true;
+ ++it;
+ }
+ if (!itemsSelected)
+ {
+ QMessageBox::warning(this, "Warning", "You need to select at least one component", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
+ return;
+ }
+ }
+
+ installStack->raiseWidget(++currentId);
+
+ if (currentId == 2)
+ {
+ pleaseWaitLabel->setText("Please wait while the software is compiled and installed");
+ timeRemaining->setText("Estimated time remaining: <b>Calculating...</b>");
+ startProcess();
+ nextButton->setEnabled(false);
+ previousButton->setEnabled(false);
+ }
+ else if (currentId == 3)
+ {
+ nextButton->setText("Finish");
+ }
+ else
+ previousButton->setEnabled(true);
+}
+
+void Wizard::previousPressed()
+{
+ int currentId = installStack->id(installStack->visibleWidget());
+ if (currentId == 0)
+ return;
+
+ installStack->raiseWidget(--currentId);
+
+ if (currentId == 0)
+ previousButton->setEnabled(false);
+ nextButton->setEnabled(true);
+}
+
+
+void Wizard::startProcess()
+{
+ selectedComponents.clear();
+
+ totalBTime = 0;
+ elapsedTime = 0;
+ elapsedBTime = 0;
+ for ( QStringList::Iterator it = buildOrder.begin(); it != buildOrder.end(); ++it )
+ {
+ QListViewItemIterator it2( componentList );
+ while ( it2.current() )
+ {
+ if (it2.current()->rtti() != 1001)
+ {
+ ++it2;
+ continue;
+ }
+ ComponentListItem* item = (ComponentListItem*) it2.current();
+ if (item->component.name == *it)
+ {
+ if (item->isOn())
+ {
+ selectedComponents.append(item->component);
+ QMap<QString, uint>::iterator it3;
+ for ( it3 = item->component.buildTimes.begin(); it3 != item->component.buildTimes.end(); ++it3 )
+ totalBTime += it3.data();
+ }
+ }
+ ++it2;
+ }
+ }
+
+ progressBar->setProgress(0);
+ progressBar->setTotalSteps(totalBTime);
+
+ currentComponent = 0;
+ currentStage = None;
+ currentIsQMake = false;
+
+ nextStep();
+}
+
+void Wizard::nextStep()
+{
+ externalProcess->clearArguments();
+
+ switch (currentStage)
+ {
+ case None:
+ {
+ logLine(selectedComponents[currentComponent].niceName);
+ progressLabel1->setText("<b>Running autogen for " + selectedComponents[currentComponent].niceName + "</b>");
+ setProgress2Text("");
+ //progressLabel2->setCursorPosition(0);
+ currentStage = Autogen;
+ QDir myDir(dir + "/" + selectedComponents[currentComponent].subDir);
+ if (myDir.entryList("*.pro", QDir::Files).count() > 0)
+ {
+ currentIsQMake = true;
+ nextStep();
+ return;
+ }
+
+ if (QFile::exists(dir + "/" + selectedComponents[currentComponent].subDir + "/configure"))
+ {
+ nextStep();
+ return;
+ }
+
+ QString autogenName;
+ if (QFile::exists(dir + "/" + selectedComponents[currentComponent].subDir + "/autogen.sh"))
+ autogenName = "autogen.sh";
+ else if (QFile::exists(dir + "/" + selectedComponents[currentComponent].subDir + "/auto-gen.sh"))
+ autogenName = "auto-gen.sh";
+ else
+ {
+ logLine("No configure, autogen, or qmake scripts found");
+ errorOccured();
+ return;
+ }
+
+ externalProcess->addArgument(dir + "/" + selectedComponents[currentComponent].subDir + autogenName);
+ externalProcess->setWorkingDirectory(dir + "/" + selectedComponents[currentComponent].subDir);
+ logLine("Running autogen...");
+ externalProcess->start();
+ break;
+ }
+ case Autogen:
+ {
+ //progressBar->setProgress(progressBar->progress() + 1);
+ currentStage = Configure;
+ if (currentIsQMake)
+ {
+ progressLabel1->setText("<b>Running qmake for " + selectedComponents[currentComponent].niceName + "</b>");
+ setProgress2Text("");
+ //progressLabel2->setCursorPosition(0);
+ externalProcess->addArgument("qmake");
+ externalProcess->setWorkingDirectory(dir + "/" + selectedComponents[currentComponent].subDir);
+ if (!externalProcess->start())
+ {
+ logLine("Error: qmake was not found. Try installing the Qt-devel libraries.");
+ errorOccured();
+ return;
+ }
+ logLine("Running qmake...");
+ break;
+ }
+
+ if (!selectedComponents[currentComponent].forceDir.isEmpty())
+ prefix = selectedComponents[currentComponent].forceDir;
+ else
+ prefix = "/usr/local";
+
+ externalProcess->addArgument("./configure");
+ //externalProcess->addArgument("--prefix=" + prefix);
+ if (!selectedComponents[currentComponent].confOptions.isEmpty())
+ {
+ QStringList extraArgs = QStringList::split(" ", sub(selectedComponents[currentComponent].confOptions));
+ for ( QStringList::Iterator it = extraArgs.begin(); it != extraArgs.end(); ++it )
+ externalProcess->addArgument(*it);
+ }
+ externalProcess->setWorkingDirectory(dir + "/" + selectedComponents[currentComponent].subDir);
+ logLine("Running configure (" + externalProcess->arguments().join(" ") + ")...");
+ progressLabel1->setText("<b>Configuring " + selectedComponents[currentComponent].niceName + "</b>");
+ setProgress2Text("");
+ timer.start();
+ externalProcess->start();
+ break;
+ }
+ case Configure:
+ {
+ updateTime("configure,");
+
+ currentStage = Compile;
+
+ externalProcess->addArgument("make");
+ externalProcess->setWorkingDirectory(dir + "/" + selectedComponents[currentComponent].subDir);
+ logLine("Running make...");
+ progressLabel1->setText("<b>Compiling " + selectedComponents[currentComponent].niceName + "</b>");
+ setProgress2Text("");
+ timer.setHMS(0, 0, 0);
+ externalProcess->start();
+ break;
+ }
+ case Compile:
+ {
+ currentStage = Install;
+
+ logLine("Installing...");
+ progressLabel1->setText("<b>Installing " + selectedComponents[currentComponent].niceName + "</b>");
+ setProgress2Text("");
+
+ installedFiles.clear();
+
+ externalProcess->addArgument("make");
+ externalProcess->addArgument("install");
+ externalProcess->setWorkingDirectory(dir + "/" + selectedComponents[currentComponent].subDir);
+ externalProcess->start();
+
+ break;
+ }
+ case Install:
+ {
+ currentStage = WriteUninstallInfo;
+ logLine("Writing uninstall information...");
+ progressLabel1->setText("<b>Writing uninstall information for " + selectedComponents[currentComponent].niceName + "</b>");
+ setProgress2Text("");
+
+ QFile postInstallScript("/tmp/arkollon-postinstall.sh");
+ if (postInstallScript.exists())
+ postInstallScript.remove();
+ postInstallScript.open(IO_WriteOnly);
+ QDataStream stream(&postInstallScript);
+ stream.writeRawBytes((const char*)postinstall_sh_data, postinstall_sh_len);
+ postInstallScript.close();
+
+ QFile fileList("/tmp/arkollon-filelist");
+ if (fileList.exists())
+ fileList.remove();
+ fileList.open(IO_WriteOnly);
+ QTextStream fileStream(&fileList);
+ QStringList doneFiles;
+ for ( QStringList::Iterator it = installedFiles.begin(); it != installedFiles.end(); ++it )
+ {
+ if (doneFiles.find(*it) != doneFiles.end())
+ continue;
+ QFileInfo fileInfo(*it);
+ if (fileInfo.isDir())
+ continue;
+ fileStream << (*it) << '\n';
+ doneFiles.append(*it);
+ }
+ fileList.close();
+
+ struct Component c = selectedComponents[currentComponent];
+ int dashPos = c.subDir.findRev('-');
+ if (dashPos < 0)
+ dashPos = c.subDir.length();
+ QString appname = c.subDir.left(dashPos);
+ QString version = c.subDir.right(c.subDir.length() - dashPos - 1);
+
+ externalProcess->addArgument("/bin/sh");
+ externalProcess->addArgument("/tmp/arkollon-postinstall.sh");
+ externalProcess->addArgument("--appname");
+ externalProcess->addArgument(appname);
+ externalProcess->addArgument("--version");
+ externalProcess->addArgument(version);
+ externalProcess->addArgument("--filelist");
+ externalProcess->addArgument("/tmp/arkollon-filelist");
+ externalProcess->start();
+ break;
+ }
+ case WriteUninstallInfo:
+ {
+ currentStage = None;
+ currentComponent++;
+ currentIsQMake = false;
+ if (currentComponent >= selectedComponents.count())
+ {
+ progressLabel1->setText("<b>Installation completed!</b>");
+ pleaseWaitLabel->setText("Installation complete");
+ timeRemaining->setText("");
+ progressBar->setProgress(totalBTime);
+ nextButton->setEnabled(true);
+ if (exec.isEmpty())
+ {
+ nextButton->setText("Finish");
+ setProgress2Text("");
+ }
+ else
+ {
+ setProgress2Text("Click \"next\" to continue");
+ }
+
+ return;
+ }
+ nextStep();
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void Wizard::processExited()
+{
+ if (currentStage == WriteUninstallInfo)
+ {
+ // Remove temp files from the last stage
+ QFile postInstallScript("/tmp/arkollon-postinstall.sh");
+ if (postInstallScript.exists())
+ postInstallScript.remove();
+
+ QFile fileList("/tmp/arkollon-filelist");
+ if (fileList.exists())
+ fileList.remove();
+ }
+ if (!externalProcess->normalExit())
+ {
+ logLine("Process was killed");
+ errorOccured();
+ return;
+ }
+ if (externalProcess->exitStatus() != 0)
+ {
+ logLine("Return value " + QString::number(externalProcess->exitStatus()));
+ errorOccured();
+ return;
+ }
+ if (currentStage == Compile)
+ updateTime(lastTimeLine);
+ nextStep();
+}
+
+void Wizard::readyReadStderr()
+{
+ while (externalProcess->canReadLineStderr())
+ {
+ QString line = externalProcess->readLineStderr().latin1();
+ CompileErrorVector::iterator it;
+ for( it = errs.begin(); it != errs.end(); ++it ){
+ if (line.contains((*it).type()))
+ QMessageBox::information( this, (*it).type(), (*it).message() );
+ }
+ logDialog->logBox->append(" * "+line);
+ }
+}
+
+void Wizard::readyReadStdout()
+{
+ while (externalProcess->canReadLineStdout())
+ {
+ QString line = externalProcess->readLineStdout().latin1();
+ logDialog->logBox->append(line);
+
+ if (currentStage == Configure)
+ {
+ setProgress2Text(line);
+ continue;
+ }
+ commandLine += line;
+ if (line.right(1) == "\\")
+ continue;
+ commandLine = commandLine.left(commandLine.find(';'));
+ for ( QValueList<ActionFormat>::Iterator it = actionFormats.begin(); it != actionFormats.end(); ++it )
+ {
+ if ((*it).regExp.search(commandLine) == -1)
+ continue;
+ setProgress2Text((*it).action + " <b>" + (*it).regExp.cap(1) + "</b> (" + (*it).tool + ")");
+ if ((currentStage == Install) && ((*it).action == "installing"))
+ installedFiles.append((*it).regExp.cap(1));
+ else
+ updateTime(lastTimeLine);
+ lastTimeLine = (*it).tool + "," + (*it).regExp.cap(1);
+ }
+ commandLine = "";
+ }
+}
+
+void Wizard::updateTime(QString key)
+{
+ if (!timer.isNull())
+ {
+ elapsedBTime += selectedComponents[currentComponent].buildTimes[key];
+ elapsedTime += timer.elapsed();
+ float ratio = (float)elapsedTime / (float)elapsedBTime;
+ int remainingTime = (int)((float)(totalBTime - elapsedBTime) * ratio) / 60000;
+ if (remainingTime < 0)
+ remainingTime = 0;
+ QString text = QString::number(remainingTime + 1) + " minutes";
+ if (remainingTime == 0)
+ text = "1 minute";
+ timeRemaining->setText("Estimated time remaining: <b>" + text + "</b>");
+ progressBar->setProgress(elapsedBTime);
+ }
+ timer.start();
+}
+
+void Wizard::logLine(QString line)
+{
+ QString tmp = line;
+ QStringList lines = QStringList::split("\n", tmp);
+ for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it )
+ {
+ if ((*it).isEmpty())
+ continue;
+ logDialog->logBox->append("***** "+*it);
+ }
+}
+
+void Wizard::setProgress2Text(QString text)
+{
+ QString croppedText = text;
+ int i = croppedText.length();
+
+ QFont boldFont = progressLabel2->font();
+ boldFont.setBold(true);
+ QFontMetrics boldFontMetrics(boldFont);
+ while (boldFontMetrics.width(croppedText) > progressLabel2->width())
+ {
+ croppedText = croppedText.left(--i);
+ }
+
+ progressLabel2->setText(croppedText);
+}
+
+void Wizard::errorOccured()
+{
+ //logFrame->show();
+ pleaseWaitLabel->setText("An error occured");
+ progressLabel1->setText("<b>An error occured</b>");
+ setProgress2Text("See the log file for more information");
+ previousButton->setEnabled(true);
+}
+
+QString Wizard::sub(QString s)
+{
+ QString tmp = s;
+ tmp.replace(QRegExp("\\$KDEDIR"), kdeDir);
+ tmp.replace(QRegExp("\\$HOMEDIR"), QDir::homeDirPath());
+ tmp.replace(QRegExp("~"), QDir::homeDirPath());
+ tmp.replace(QRegExp("\\$PREFIX"), "/usr/local");
+
+ return tmp;
+}
+
+void Wizard::runPressed()
+{
+ QProcess* proc = new QProcess(this);
+ proc->addArgument(exec);
+ if (!proc->start())
+ {
+ QMessageBox::warning(this, "Warning", "The application could not be started<br>"+exec, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
+ }
+}
+
+void Wizard::logPressed()
+{
+ logDialog->show();
+}
+
+#include "wizard.moc"
+