diff options
Diffstat (limited to 'src/arkollon/wizard.cpp')
-rw-r--r-- | src/arkollon/wizard.cpp | 950 |
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 * + * [email protected] * + * * + * 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" + |