X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fsupport%2FSystemcall.cpp;h=741feb233843834c95a596e06e2f361edfea39f7;hb=c48091f33a773732fa6c789927e5833e44108d9d;hp=13a000157973ba8e59a66ee54894205902b616fe;hpb=04580d2122271626fd62d2f005e427abbadd7aaf;p=lyx.git diff --git a/src/support/Systemcall.cpp b/src/support/Systemcall.cpp index 13a0001579..741feb2338 100644 --- a/src/support/Systemcall.cpp +++ b/src/support/Systemcall.cpp @@ -14,12 +14,16 @@ #include #include "support/debug.h" +#include "support/environment.h" +#include "support/filetools.h" #include "support/lstrings.h" #include "support/qstring_helpers.h" #include "support/Systemcall.h" #include "support/SystemcallPrivate.h" #include "support/os.h" +#include "support/ProgressInterface.h" +#include "LyXRC.h" #include #include @@ -43,19 +47,78 @@ struct Sleep : QThread + using namespace std; namespace lyx { namespace support { +class ProgressDummy : public ProgressInterface +{ +public: + ProgressDummy() {} + + void processStarted(QString const &) {} + void processFinished(QString const &) {} + void appendMessage(QString const &) {} + void appendError(QString const &) {} + void clearMessages() {} + void lyxerrFlush() {} + + void lyxerrConnect() {} + void lyxerrDisconnect() {} + + void warning(QString const &, QString const &) {} + void toggleWarning(QString const &, QString const &, QString const &) {} + void error(QString const &, QString const &) {} + void information(QString const &, QString const &) {} +}; + + +static ProgressInterface* progress_instance = 0; + +void ProgressInterface::setInstance(ProgressInterface* p) +{ + progress_instance = p; +} + + +ProgressInterface* ProgressInterface::instance() +{ + if (!progress_instance) { + static ProgressDummy dummy; + return &dummy; + } + return progress_instance; +} + + + // Reuse of instance #ifndef USE_QPROCESS int Systemcall::startscript(Starttype how, string const & what, - bool /*process_events*/) + std::string const & path, bool /*process_events*/) { - string command = what; + string command; + string const texinputs = os::latex_path_list( + replaceCurdirPath(path, lyxrc.texinputs_prefix)); + string const sep = string(1, os::path_separator(os::TEXENGINE)); + string const env = getEnv("TEXINPUTS"); + + switch (os::shell()) { + case os::UNIX: + command = path.empty() || lyxrc.texinputs_prefix.empty() ? what + : "env TEXINPUTS='." + sep + texinputs + + sep + env + "' " + what; + break; + case os::CMD_EXE: + command = path.empty() || lyxrc.texinputs_prefix.empty() ? what + : "set TEXINPUTS=." + sep + texinputs + + sep + env + " & " + what; + break; + } if (how == DontWait) { switch (os::shell()) { @@ -161,7 +224,8 @@ string const parsecmd(string const & inputcmd, string & outfile) -int Systemcall::startscript(Starttype how, string const & what, bool process_events) +int Systemcall::startscript(Starttype how, string const & what, + string const & path, bool process_events) { string outfile; QString cmd = toqstr(parsecmd(what, outfile)); @@ -169,7 +233,7 @@ int Systemcall::startscript(Starttype how, string const & what, bool process_eve SystemcallPrivate d(outfile); - d.startProcess(cmd); + d.startProcess(cmd, path); if (!d.waitWhile(SystemcallPrivate::Starting, process_events, -1)) { LYXERR0("Systemcall: '" << cmd << "' did not start!"); LYXERR0("error " << d.errorMessage()); @@ -182,8 +246,9 @@ int Systemcall::startscript(Starttype how, string const & what, bool process_eve return 0; } - if (!d.waitWhile(SystemcallPrivate::Running, process_events, 180000)) { - LYXERR0("Systemcall: '" << cmd << "' did not finished!"); + if (!d.waitWhile(SystemcallPrivate::Running, process_events, + os::timeout_min() * 60 * 1000)) { + LYXERR0("Systemcall: '" << cmd << "' did not finish!"); LYXERR0("error " << d.errorMessage()); LYXERR0("status " << d.exitStatusMessage()); return 20; @@ -198,42 +263,57 @@ int Systemcall::startscript(Starttype how, string const & what, bool process_eve } -SystemcallPrivate::SystemcallPrivate(const std::string& of) : - proc_(new QProcess), outindex_(0), errindex_(0), - outfile(of), showout_(false), showerr_(false), process_events(false) +SystemcallPrivate::SystemcallPrivate(const std::string& of) : + process_(new QProcess), + out_index_(0), + err_index_(0), + out_file_(of), + texinputs_(getEnv("TEXINPUTS")), + process_events_(false) { - if (!outfile.empty()) { + if (!out_file_.empty()) { // Check whether we have to simply throw away the output. - if (outfile != os::nulldev()) - proc_->setStandardOutputFile(toqstr(outfile)); - } else if (os::is_terminal(os::STDOUT)) - showout(); - if (os::is_terminal(os::STDERR)) - showerr(); - - connect(proc_, SIGNAL(readyReadStandardOutput()), SLOT(stdOut())); - connect(proc_, SIGNAL(readyReadStandardError()), SLOT(stdErr())); - connect(proc_, SIGNAL(error(QProcess::ProcessError)), SLOT(processError(QProcess::ProcessError))); - connect(proc_, SIGNAL(started()), this, SLOT(processStarted())); - connect(proc_, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(processFinished(int, QProcess::ExitStatus))); + if (out_file_ != os::nulldev()) + process_->setStandardOutputFile(toqstr(out_file_)); + } + + connect(process_, SIGNAL(readyReadStandardOutput()), SLOT(stdOut())); + connect(process_, SIGNAL(readyReadStandardError()), SLOT(stdErr())); + connect(process_, SIGNAL(error(QProcess::ProcessError)), SLOT(processError(QProcess::ProcessError))); + connect(process_, SIGNAL(started()), this, SLOT(processStarted())); + connect(process_, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(processFinished(int, QProcess::ExitStatus))); } -void SystemcallPrivate::startProcess(const QString& cmd) +void SystemcallPrivate::startProcess(QString const & cmd, string const & path) { - if (proc_) { + cmd_ = cmd; + if (process_) { + if (!path.empty() && !lyxrc.texinputs_prefix.empty()) { + string const texinputs = os::latex_path_list( + replaceCurdirPath(path, lyxrc.texinputs_prefix)); + string const sep = string(1, + os::path_separator(os::TEXENGINE)); + string const prefix = "." + sep + texinputs + sep; + if (prefixIs(texinputs_, prefix)) + texinputs_.clear(); + else + setEnv("TEXINPUTS", prefix + texinputs_); + } state = SystemcallPrivate::Starting; - proc_->start(cmd); + if (os::shell() == os::CMD_EXE) + process_->start(QLatin1String("cmd /d /c ") + cmd_); + else + process_->start(cmd_); } } void SystemcallPrivate::processEvents() { - if(process_events) { - //static int count = 0; qDebug() << count++ << ": waitAndProcessEvents"; - QCoreApplication::processEvents(QEventLoop::AllEvents); + if(process_events_) { + QCoreApplication::processEvents(/*QEventLoop::ExcludeUserInputEvents*/); } } @@ -245,20 +325,20 @@ void SystemcallPrivate::waitAndProcessEvents() } -bool SystemcallPrivate::waitWhile(State waitwhile, bool proc_events, int timeout) +bool SystemcallPrivate::waitWhile(State waitwhile, bool process_events, int timeout) { - if (!proc_) + if (!process_) return false; - process_events = proc_events; + process_events_ = process_events; // Block GUI while waiting, // relay on QProcess' wait functions - if (!process_events) { + if (!process_events_) { if (waitwhile == Starting) - return proc_->waitForStarted(timeout); + return process_->waitForStarted(timeout); if (waitwhile == Running) - return proc_->waitForFinished(timeout); + return process_->waitForFinished(timeout); return false; } @@ -282,18 +362,19 @@ bool SystemcallPrivate::waitWhile(State waitwhile, bool proc_events, int timeout SystemcallPrivate::~SystemcallPrivate() { - flush(); + if (!texinputs_.empty()) + setEnv("TEXINPUTS", texinputs_); - if (outindex_) { - outdata_[outindex_] = '\0'; - outindex_ = 0; - cout << outdata_; + if (out_index_) { + out_data_[out_index_] = '\0'; + out_index_ = 0; + cout << out_data_; } cout.flush(); - if (errindex_) { - errdata_[errindex_] = '\0'; - errindex_ = 0; - cerr << errdata_; + if (err_index_) { + err_data_[err_index_] = '\0'; + err_index_ = 0; + cerr << err_data_; } cerr.flush(); @@ -301,85 +382,74 @@ SystemcallPrivate::~SystemcallPrivate() } -void SystemcallPrivate::flush() -{ - if (proc_) { - // If the output has been redirected, we write it all at once. - // Even if we are not running in a terminal, the output could go - // to some log file, for example ~/.xsession-errors on *nix. - if (!os::is_terminal(os::STDOUT) && outfile.empty()) - cout << fromqstr(QString::fromLocal8Bit( - proc_->readAllStandardOutput().data())); - if (!os::is_terminal(os::STDERR)) - cerr << fromqstr(QString::fromLocal8Bit( - proc_->readAllStandardError().data())); - } -} - - void SystemcallPrivate::stdOut() { - if (proc_ && showout_) { + if (process_) { char c; - proc_->setReadChannel(QProcess::StandardOutput); - while (proc_->getChar(&c)) { - outdata_[outindex_++] = c; - if (c == '\n' || outindex_ + 1 == bufsize_) { - outdata_[outindex_] = '\0'; - outindex_ = 0; - cout << outdata_; + process_->setReadChannel(QProcess::StandardOutput); + while (process_->getChar(&c)) { + out_data_[out_index_++] = c; + if (c == '\n' || out_index_ + 1 == buffer_size_) { + out_data_[out_index_] = '\0'; + out_index_ = 0; + ProgressInterface::instance()->appendMessage(QString::fromLocal8Bit(out_data_)); + cout << out_data_; } } } - processEvents(); } void SystemcallPrivate::stdErr() { - if (proc_ && showerr_) { + if (process_) { char c; - proc_->setReadChannel(QProcess::StandardError); - while (proc_->getChar(&c)) { - errdata_[errindex_++] = c; - if (c == '\n' || errindex_ + 1 == bufsize_) { - errdata_[errindex_] = '\0'; - errindex_ = 0; - cerr << errdata_; + process_->setReadChannel(QProcess::StandardError); + while (process_->getChar(&c)) { + err_data_[err_index_++] = c; + if (c == '\n' || err_index_ + 1 == buffer_size_) { + err_data_[err_index_] = '\0'; + err_index_ = 0; + ProgressInterface::instance()->appendError(QString::fromLocal8Bit(err_data_)); + cerr << err_data_; } } } - processEvents(); } void SystemcallPrivate::processStarted() { - state = Running; - // why do we get two started signals? - //disconnect(proc_, SIGNAL(started()), this, SLOT(processStarted())); + if (state != Running) { + state = Running; + ProgressInterface::instance()->processStarted(cmd_); + } } void SystemcallPrivate::processFinished(int, QProcess::ExitStatus) { - state = Finished; + if (state != Finished) { + state = Finished; + ProgressInterface::instance()->processFinished(cmd_); + } } void SystemcallPrivate::processError(QProcess::ProcessError) { state = Error; + ProgressInterface::instance()->appendError(errorMessage()); } QString SystemcallPrivate::errorMessage() const { - if (!proc_) + if (!process_) return "No QProcess available"; QString message; - switch (proc_->error()) { + switch (process_->error()) { case QProcess::FailedToStart: message = "The process failed to start. Either the invoked program is missing, " "or you may have insufficient permissions to invoke the program."; @@ -409,11 +479,11 @@ QString SystemcallPrivate::errorMessage() const QString SystemcallPrivate::exitStatusMessage() const { - if (!proc_) + if (!process_) return "No QProcess available"; QString message; - switch (proc_->exitStatus()) { + switch (process_->exitStatus()) { case QProcess::NormalExit: message = "The process exited normally."; break; @@ -430,24 +500,24 @@ QString SystemcallPrivate::exitStatusMessage() const int SystemcallPrivate::exitCode() { - if (!proc_) + if (!process_) return -1; - return proc_->exitCode(); + return process_->exitCode(); } QProcess* SystemcallPrivate::releaseProcess() { - QProcess* released = proc_; - proc_ = 0; + QProcess* released = process_; + process_ = 0; return released; } void SystemcallPrivate::killProcess() { - killProcess(proc_); + killProcess(process_); }