You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tork/src/arkollon/wizard.cpp

951 lines
28 KiB

/***************************************************************************
* Copyright (C) 2004 by David Sansome *
* me@davidsansome.com *
* *
* 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 <tqfiledialog.h>
#include <tqwidgetstack.h>
#include <tqpushbutton.h>
#include <tqpainter.h>
#include <tqheader.h>
#include <tqapplication.h>
#include <tqmessagebox.h>
#include <tqprogressbar.h>
#include <tqradiobutton.h>
#include <tqtextedit.h>
#include <tqlineedit.h>
#include <tqpopupmenu.h>
#include <tqhbox.h>
#include <tqfileinfo.h>
#include <tqlabel.h>
#include <tqfontmetrics.h>
#include <tqcheckbox.h>
#include "wizard.h"
#include "data.h"
#include "rcparser.h"
#include "headerlistitem.h"
typedef TQValueVector<CompileError> CompileErrorVector;
CompileErrorVector errs( 5 ); // vector of 3 Employees
ComponentListItem::ComponentListItem(struct Component c, TQListView* parent)
: TQCheckListItem(parent, "", TQCheckListItem::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(TQListViewItem* 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 TQListViewItem::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(TQWidget *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 TQProcess(this);
connect(externalProcess, TQ_SIGNAL(processExited()), TQ_SLOT(processExited()));
connect(externalProcess, TQ_SIGNAL(readyReadStdout()), TQ_SLOT(readyReadStdout()));
connect(externalProcess, TQ_SIGNAL(readyReadStderr()), TQ_SLOT(readyReadStderr()));
logDialog = new LogDialog(this);
logDialog->hide();
previousButton->hide();
createActionFormats();
kdeDirProcess = new TQProcess(this);
connect(kdeDirProcess, TQ_SIGNAL(readyReadStdout()), TQ_SLOT(kdeDirReady()));
connect(kdeDirProcess, TQ_SIGNAL(processExited()), TQ_SLOT(getInstalledComponents()));
kdeDirProcess->addArgument("tde-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( "TQt (>= ", "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) 'tqt' 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())
{
TQString line = kdeDirProcess->readLineStdout();
if (!line.isEmpty())
kdeDir = line;
}
}
void Wizard::getInstalledComponents()
{
TQFile uninstallScript("/tmp/arkollon-uninstall.sh");
if (uninstallScript.exists())
uninstallScript.remove();
uninstallScript.open(IO_WriteOnly);
TQDataStream stream(&uninstallScript);
stream.writeRawBytes((const char*)uninstaller_sh_data, uninstaller_sh_len);
uninstallScript.close();
installedComponentsProcess = new TQProcess(this);
connect(installedComponentsProcess, TQ_SIGNAL(readyReadStdout()), TQ_SLOT(installedComponentsReady()));
connect(installedComponentsProcess, TQ_SIGNAL(processExited()), TQ_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())
{
TQString 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()
{
TQFile 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 = TQDir::currentDirPath();
if (tqApp->argc() > 1)
{
// The directory specified on the command line overrides the current dir.
TQDir d(tqApp->argv()[1]);
dir = d.absPath();
}
if (TQFile::exists(dir + "/arkollonrc"))
{
setupFromRc();
}
else
{
if (!setupFromDir())
{
TQMessageBox::critical(NULL, "Error", "This directory does not contain any recognised buildsystem", TQMessageBox::Ok, TQMessageBox::NoButton, TQMessageBox::NoButton);
reject();
return;
}
}
show();
}
void Wizard::setupFromRc()
{
RcParser parser;
parser.addSearchDir(dir);
if (!parser.openFile("arkollonrc"))
{
TQMessageBox::critical(NULL, "Error", "The \"arkollonrc\" file in this directory could not be read", TQMessageBox::Ok, TQMessageBox::NoButton, TQMessageBox::NoButton);
reject();
return;
}
parser.setSection("Arkollon");
TQString appName = parser.readString("AppName");
if (appName.isEmpty())
{
TQMessageBox::critical(NULL, "Error", "The \"arkollonrc\" file in this directory contains no application name!", TQMessageBox::Ok, TQMessageBox::NoButton, TQMessageBox::NoButton);
reject();
return;
}
setAppName(appName);
TQString icon32Path = parser.readString("Icon32");
TQString icon16Path = parser.readString("Icon16");
if ((!icon32Path.isEmpty()) && (TQFile::exists(dir + "/" + icon32Path)))
{
TQPixmap icon32(dir + "/" + icon32Path);
appIcon->setPixmap(icon32);
}
if ((!icon16Path.isEmpty()) && (TQFile::exists(dir + "/" + icon16Path)))
{
TQPixmap icon16(dir + "/" + icon16Path);
setIcon(icon16);
}
buildOrder = parser.readList("BuildOrder");
TQStringList compNames = parser.readList("Components");
TQStringList::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("TDEOnly", 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 (TQFile::exists(dir + "/" + c.subDir + "/buildtimes"))
{
TQRegExp re("([^,]*,[^,]*),(\\d*)");
TQFile file(dir + "/" + c.subDir + "/buildtimes");
file.open(IO_ReadOnly);
TQTextStream stream(&file);
for (;;)
{
TQString 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, "TDE specific components"); break;
}
}
// Check if it's already installed
TQStringList::Iterator it2 = installedComponents.begin();
while( it2 != installedComponents.end() )
{
int dashPos = c.subDir.findRev('-');
if (dashPos < 0)
dashPos = c.subDir.length();
TQString 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 ((!TQFile::exists(dir + "/configure")) &&
(!TQFile::exists(dir + "/autogen.sh")) &&
(!TQFile::exists(dir + "/auto-gen.sh")))
{
TQDir myDir(dir + "/" + selectedComponents[currentComponent].subDir);
if (myDir.entryList("*.pro", TQDir::Files).count() <= 0)
return false;
}
// Use the directory name as the appname
TQDir myDir2(dir);
TQString 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;
TQStringList::Iterator it2 = installedComponents.begin();
while( it2 != installedComponents.end() )
{
int dashPos = dirName.findRev('-');
if (dashPos < 0)
dashPos = dirName.length();
TQString 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(TQListViewItem* item)
{
if (item->rtti() != 1001)
return;
ComponentListItem* i = (ComponentListItem*) item;
TQString 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);
}
TQString Wizard::makeDirNice(TQString name)
{
int dashPos = name.findRev('-');
if (dashPos < 0)
dashPos = name.length();
TQString 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)
{
TQDir d(kdeDir);
d.mkdir("share/apps/kdesktop/Desktop");
if (shortcutBox->isChecked())
{
TQFile source(dir + "/" + desktop);
TQString destDir = kdeDir + "/share/apps/kdesktop/Desktop";
int slashPos = desktop.findRev('/');
if (slashPos < 0)
slashPos = 0;
TQFile dest(destDir + "/" + desktop.right(desktop.length() - slashPos));
source.open(IO_ReadOnly);
dest.open(IO_WriteOnly | IO_Truncate);
TQDataStream destStream(&dest);
TQByteArray data = source.readAll();
destStream.writeRawBytes(data.data(), data.size());
source.close();
dest.close();
}
if (uninstallBox->isChecked())
{
TQFile source(dir + "/Uninstall TorK.desktop");
TQFile dest(kdeDir + "/share/apps/kdesktop/Desktop/Uinstall TorK.desktop");
source.open(IO_ReadOnly);
dest.open(IO_WriteOnly | IO_Truncate);
TQDataStream destStream(&dest);
TQByteArray 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;
TQListViewItemIterator 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)
{
TQMessageBox::warning(this, "Warning", "You need to select at least one component", TQMessageBox::Ok, TQMessageBox::NoButton, TQMessageBox::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 ( TQStringList::Iterator it = buildOrder.begin(); it != buildOrder.end(); ++it )
{
TQListViewItemIterator 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);
TQMap<TQString, 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;
currentIsTQMake = 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;
TQDir myDir(dir + "/" + selectedComponents[currentComponent].subDir);
if (myDir.entryList("*.pro", TQDir::Files).count() > 0)
{
currentIsTQMake = true;
nextStep();
return;
}
if (TQFile::exists(dir + "/" + selectedComponents[currentComponent].subDir + "/configure"))
{
nextStep();
return;
}
TQString autogenName;
if (TQFile::exists(dir + "/" + selectedComponents[currentComponent].subDir + "/autogen.sh"))
autogenName = "autogen.sh";
else if (TQFile::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 (currentIsTQMake)
{
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 TQt-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())
{
TQStringList extraArgs = TQStringList::split(" ", sub(selectedComponents[currentComponent].confOptions));
for ( TQStringList::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("");
TQFile postInstallScript("/tmp/arkollon-postinstall.sh");
if (postInstallScript.exists())
postInstallScript.remove();
postInstallScript.open(IO_WriteOnly);
TQDataStream stream(&postInstallScript);
stream.writeRawBytes((const char*)postinstall_sh_data, postinstall_sh_len);
postInstallScript.close();
TQFile fileList("/tmp/arkollon-filelist");
if (fileList.exists())
fileList.remove();
fileList.open(IO_WriteOnly);
TQTextStream fileStream(&fileList);
TQStringList doneFiles;
for ( TQStringList::Iterator it = installedFiles.begin(); it != installedFiles.end(); ++it )
{
if (doneFiles.find(*it) != doneFiles.end())
continue;
TQFileInfo 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();
TQString appname = c.subDir.left(dashPos);
TQString 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++;
currentIsTQMake = 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
TQFile postInstallScript("/tmp/arkollon-postinstall.sh");
if (postInstallScript.exists())
postInstallScript.remove();
TQFile 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 " + TQString::number(externalProcess->exitStatus()));
errorOccured();
return;
}
if (currentStage == Compile)
updateTime(lastTimeLine);
nextStep();
}
void Wizard::readyReadStderr()
{
while (externalProcess->canReadLineStderr())
{
TQString line = externalProcess->readLineStderr().latin1();
CompileErrorVector::iterator it;
for( it = errs.begin(); it != errs.end(); ++it ){
if (line.contains((*it).type()))
TQMessageBox::information( this, (*it).type(), (*it).message() );
}
logDialog->logBox->append(" * "+line);
}
}
void Wizard::readyReadStdout()
{
while (externalProcess->canReadLineStdout())
{
TQString 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 ( TQValueList<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(TQString 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;
TQString text = TQString::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(TQString line)
{
TQString tmp = line;
TQStringList lines = TQStringList::split("\n", tmp);
for ( TQStringList::Iterator it = lines.begin(); it != lines.end(); ++it )
{
if ((*it).isEmpty())
continue;
logDialog->logBox->append("***** "+*it);
}
}
void Wizard::setProgress2Text(TQString text)
{
TQString croppedText = text;
int i = croppedText.length();
TQFont boldFont = progressLabel2->font();
boldFont.setBold(true);
TQFontMetrics 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);
}
TQString Wizard::sub(TQString s)
{
TQString tmp = s;
tmp.replace(TQRegExp("\\$TDEDIR"), kdeDir);
tmp.replace(TQRegExp("\\$HOMEDIR"), TQDir::homeDirPath());
tmp.replace(TQRegExp("~"), TQDir::homeDirPath());
tmp.replace(TQRegExp("\\$PREFIX"), "/usr/local");
return tmp;
}
void Wizard::runPressed()
{
TQProcess* proc = new TQProcess(this);
proc->addArgument(exec);
if (!proc->start())
{
TQMessageBox::warning(this, "Warning", "The application could not be started<br>"+exec, TQMessageBox::Ok, TQMessageBox::NoButton, TQMessageBox::NoButton);
}
}
void Wizard::logPressed()
{
logDialog->show();
}
#include "wizard.moc"