add progress view of system calls

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22026 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Peter Kümmel 2007-12-08 20:46:03 +00:00
parent b95a68d476
commit 3af56311a7
14 changed files with 382 additions and 34 deletions

View File

@ -297,7 +297,9 @@ src_support_header_files = Split('''
RandomAccessList.h
SignalSlot.h
SignalSlotPrivate.h
ProgressInterface.h
Systemcall.h
SystemcallPrivate.h
Timeout.h
Translator.h
convert.h
@ -338,6 +340,7 @@ src_support_files = Split('''
Path.cpp
SignalSlot.cpp
Systemcall.cpp
SystemcallPrivate.cpp
Timeout.cpp
abort.cpp
convert.cpp
@ -755,6 +758,7 @@ src_frontends_qt4_header_files = Split('''
GuiPopupMenu.h
GuiPrefs.h
GuiPrint.h
GuiProgress.h
GuiRef.h
GuiSearch.h
GuiSelection.h
@ -841,6 +845,7 @@ src_frontends_qt4_files = Split('''
GuiParagraph.cpp
GuiPopupMenu.cpp
GuiPrefs.cpp
GuiProgress.cpp
GuiPrint.cpp
GuiRef.cpp
GuiSearch.cpp

View File

@ -286,6 +286,7 @@ Menuset
Item "Fold Math Macro" "math-macro-fold"
Separator
Item "View Source|S" "dialog-toggle view-source"
Item "View LaTeX Progress|" "dialog-toggle latex-progress"
Submenu "Update|U" "view_update"
ViewFormats
Separator

View File

@ -1097,8 +1097,7 @@ void Buffer::writeLaTeXSource(odocstream & os,
if (output_preamble) {
if (!runparams.nice) {
// code for usual, NOT nice-latex-file
os << "\\batchmode\n"; // changed
// from \nonstopmode
os << "\\nonstopmode\n";
d->texrow.newline();
}
if (!original_path.empty()) {

View File

@ -415,11 +415,9 @@ int LaTeX::run(TeXErrors & terr)
int LaTeX::startscript()
{
// onlyFilename() is needed for cygwin
string tmp = cmd + ' '
+ quoteName(onlyFilename(file.toFilesystemEncoding()))
+ " > " + os::nulldev();
Systemcall one;
return one.startscript(Systemcall::Wait, tmp);
string tmp = cmd + ' ' + "-max-print-line=200 "
+ quoteName(onlyFilename(file.toFilesystemEncoding()));
return Systemcall().startscript(Systemcall::Wait, tmp);
}

View File

@ -0,0 +1,64 @@
// -*- C++ -*-
/**
* \file GuiProgress.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Peter Kümmel
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "GuiProgress.h"
#include "support/Systemcall.h"
#include <QApplication>
namespace lyx {
namespace frontend {
GuiProgress::GuiProgress(GuiView & parent, Qt::DockWidgetArea area,
Qt::WindowFlags flags) : DockView(parent, "latex-progress", area, flags)
{
setWindowTitle(qt_("LaTeX Progress"));
setWidget(&text_edit);
lyx::support::Systemcall::registerProgressInterface(this);
}
void GuiProgress::appendMessage(QString const & msg)
{
text_edit.append(msg);
// QEventLoop::ExcludeUserInputEvents:
// don't allow user inputs while processing a document
// if we allow it, we open will Pandora's Box of multithreading
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
void GuiProgress::clearMessages()
{
text_edit.clear();
}
Dialog * createGuiProgress(GuiView & lv)
{
GuiView & guiview = static_cast<GuiView &>(lv);
#ifdef Q_WS_MACX
// TODO where to show up on the Mac?
//return new GuiProgress(guiview, Qt::RightDockWidgetArea, Qt::Drawer);
#else
return new GuiProgress(guiview, Qt::BottomDockWidgetArea);
#endif
}
} // namespace frontend
} // namespace lyx

View File

@ -0,0 +1,62 @@
// -*- C++ -*-
/**
* \file GuiProgress.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Peter Kümmel
*
* Full author contact details are available in file CREDITS.
*/
#ifndef GUIPROGRESS_H
#define GUIPROGRESS_H
#include "support/ProgressInterface.h"
#include "DockView.h"
#include <QTextEdit>
#include <string>
namespace lyx {
namespace frontend {
class GuiProgress :
public DockView,
public lyx::support::ProgressInterface
{
public:
GuiProgress(
GuiView & parent, ///< the main window where to dock.
Qt::DockWidgetArea area, ///< Position of the dock (and also drawer)
Qt::WindowFlags flags = 0);
void appendMessage(QString const &);
void clearMessages();
/// Controller inherited method.
///@{
bool initialiseParams(std::string const & source) { return true; }
void clearParams() {}
void dispatchParams() {}
bool isBufferDependent() const { return true; }
bool canApply() const { return true; }
bool canApplyToReadOnly() const { return true; }
void updateView() {}
///@}
private:
QTextEdit text_edit;
};
} // namespace frontend
} // namespace lyx
#endif

View File

@ -23,6 +23,7 @@
#include "GuiMenubar.h"
#include "GuiToolbar.h"
#include "GuiToolbars.h"
#include "GuiProgress.h"
#include "qt_helpers.h"
@ -1569,7 +1570,7 @@ char const * const dialognames[] = {
"thesaurus",
#endif
"texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
"texinfo", "toc", "href", "view-source", "latex-progress", "vspace", "wrap", "listings" };
char const * const * const end_dialognames =
dialognames + (sizeof(dialognames) / sizeof(char *));
@ -1793,6 +1794,7 @@ Dialog * createGuiThesaurus(GuiView & lv);
Dialog * createGuiHyperlink(GuiView & lv);
Dialog * createGuiVSpace(GuiView & lv);
Dialog * createGuiViewSource(GuiView & lv);
Dialog * createGuiProgress(GuiView & lv);
Dialog * createGuiWrap(GuiView & lv);
@ -1844,6 +1846,8 @@ Dialog * GuiView::build(string const & name)
return createGuiLog(*this);
if (name == "view-source")
return createGuiViewSource(*this);
if (name == "latex-progress")
return createGuiProgress(*this);
if (name == "mathdelimiter")
return createGuiDelimiter(*this);
if (name == "mathmatrix")

View File

@ -101,6 +101,7 @@ SOURCEFILES = \
GuiPopupMenu.cpp \
GuiPrefs.cpp \
GuiPrint.cpp \
GuiProgress.cpp \
GuiRef.cpp \
GuiSearch.cpp \
GuiSelection.cpp \
@ -187,6 +188,7 @@ MOCHEADER = \
GuiPopupMenu.h \
GuiPrefs.h \
GuiPrint.h \
GuiProgress.h \
GuiRef.h \
GuiSearch.h \
GuiSelection.h \

View File

@ -75,6 +75,9 @@ liblyxsupport_la_SOURCES = \
strfwd.h \
Systemcall.cpp \
Systemcall.h \
SystemcallPrivate.cpp \
SystemcallPrivate.h \
ProgressInterface.h \
SignalSlot.cpp \
SignalSlot.h \
SignalSlotPrivate.h \

View File

@ -0,0 +1,38 @@
// -*- C++ -*-
/**
* \file ProgressInterface.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Peter Kümmel
*
* Full author contact details are available in file CREDITS.
*/
#ifndef LYX_SUPPORT_PROGRESSINTERFACE_H
#define LYX_SUPPORT_PROGRESSINTERFACE_H
class QString;
namespace lyx {
namespace support {
class ProgressInterface
{
public:
virtual ~ProgressInterface() {}
virtual void appendMessage(QString const &) = 0;
virtual void clearMessages() = 0;
protected:
ProgressInterface() {}
};
} // namespace support
} // namespace lyx
#endif // LYX_SUPPORT_PROGRESSINTERFACE_H

View File

@ -4,6 +4,7 @@
* Licence details can be found in the file COPYING.
*
* \author Asger Alstrup
* \author Peter Kümmel
*
* Interface cleaned up by
* \author Angus Leeming
@ -14,37 +15,36 @@
#include <config.h>
#include "support/Systemcall.h"
#include "support/os.h"
#include <cstdlib>
using std::string;
#ifndef CXX_GLOBAL_CSTD
using std::system;
#endif
#include "support/SystemcallPrivate.h"
#include "support/ProgressInterface.h"
namespace lyx {
namespace support {
// Reuse of instance
int Systemcall::startscript(Starttype how, string const & what)
static ProgressInterface* progress_impl = 0;
void Systemcall::registerProgressInterface(ProgressInterface* p)
{
string command = what;
if (how == DontWait) {
switch (os::shell()) {
case os::UNIX:
command += " &";
break;
case os::CMD_EXE:
command = "start /min " + command;
break;
}
}
return ::system(command.c_str());
progress_impl = p;
}
ProgressInterface* Systemcall::progress()
{
return progress_impl;
}
int Systemcall::startscript(Starttype how, std::string const & what)
{
// TODO Reuse of instance?
SystemcallPrivate* process = new SystemcallPrivate;
if (how == Wait)
return process->start(what, true);
return process->start(what, false);
}
} // namespace support
} // namespace lyx

View File

@ -5,6 +5,7 @@
* Licence details can be found in the file COPYING.
*
* \author Asger Alstrup
* \author Peter Kümmel
*
* Interface cleaned up by
* \author Angus Leeming
@ -20,10 +21,12 @@
namespace lyx {
namespace support {
class ProgressInterface;
/**
* An instance of Class Systemcall represents a single child process.
*
* Class Systemcall uses system() to launch the child process.
* Class Systemcall uses SystemcallPrivate to launch the child process.
* The user can choose to wait or not wait for the process to complete, but no
* callback is invoked upon completion of the child.
*
@ -43,6 +46,9 @@ public:
* by spaces.
*/
int startscript(Starttype how, std::string const & what);
static void registerProgressInterface(ProgressInterface*);
static ProgressInterface* progress();
};
} // namespace support

View File

@ -0,0 +1,115 @@
// -*- C++ -*-
/**
* \file SystemcallPrivate.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Peter Kümmel
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "SystemcallPrivate.h"
#include "Systemcall.h"
#include "ProgressInterface.h"
#include "gettext.h"
#include "qstring_helpers.h"
namespace lyx {
namespace support {
// TODO should we move qt_ to qstring_helpers?
static
QString const qt_(char const * str)
{
return toqstr(_(str));
}
SystemcallPrivate::SystemcallPrivate()
{
ProgressInterface* progress = Systemcall::progress();
if (progress) {
connect(&process, SIGNAL(readyReadStandardOutput()), this, SLOT(newProcessOutput()));
connect(&process, SIGNAL(started()), this, SLOT(processStarted()));
connect(&process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)),
this, SLOT(processFinished(int, QProcess::ExitStatus)));
}
}
int SystemcallPrivate::start(const std::string& cmd, bool waitForFinished)
{
ProgressInterface* progress = Systemcall::progress();
if (progress) {
progress->clearMessages();
progress->appendMessage(qt_("Starting LaTex with command "));
progress->appendMessage(cmd.c_str());
}
process.setReadChannel(QProcess::StandardOutput);
process.start(cmd.c_str(), QStringList(), QIODevice::ReadOnly);
// wait some seconds until the process has started
process.waitForStarted(10 * 1000);
if (waitForFinished) {
// with waitForFinished(-1); we only get one signal per run
while (process.state() == QProcess::Running)
process.waitForFinished(500);
return process.exitCode();
}
if (process.state() != QProcess::Running) {
process.kill();
// TODO this needs more testing
deleteLater();
return -1;
}
return 0;
}
void SystemcallPrivate::newProcessOutput()
{
ProgressInterface* progress = Systemcall::progress();
if (progress) {
const QString output = QString::fromLocal8Bit(process.readAllStandardOutput());
progress->appendMessage(output);
}
}
void SystemcallPrivate::processStarted()
{
ProgressInterface* progress = Systemcall::progress();
if (progress) {
progress->appendMessage(qt_("LaTex started\n"));
}
}
void SystemcallPrivate::processError(QProcess::ProcessError)
{
ProgressInterface* progress = Systemcall::progress();
if (progress) {
progress->appendMessage(qt_("LaTex error\n"));
}
}
void SystemcallPrivate::processFinished(int, QProcess::ExitStatus)
{
deleteLater();
}
} // namespace support
} // namespace lyx
#include "SystemcallPrivate_moc.cpp"

View File

@ -0,0 +1,51 @@
// -*- C++ -*-
/**
* \file SystemcallPrivate.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Peter Kümmel
*
* Full author contact details are available in file CREDITS.
*/
#ifndef LYX_SUPPORT_SYSTEMCALLPRIVATE_H
#define LYX_SUPPORT_SYSTEMCALLPRIVATE_H
#include <QObject>
#include <QProcess>
#include <string>
namespace lyx {
namespace support {
class ProgressInterface;
class SystemcallPrivate : public QObject
{
Q_OBJECT
public:
SystemcallPrivate();
// When waitForFinished == true : returns the exit code of the process
// When waitForFinished == false: returns 0 if the process could be started
int start(const std::string& cmd, bool waitForFinished);
public Q_SLOTS:
void newProcessOutput();
void processStarted();
void processError(QProcess::ProcessError);
void processFinished(int, QProcess::ExitStatus);
private:
QProcess process;
};
} // namespace support
} // namespace lyx
#endif // LYX_SUPPORT_SYSTEMCALLPRIVATE_H