mirror of
https://git.lyx.org/repos/lyx.git
synced 2025-01-17 13:26:58 +00:00
c293be56bd
In particular, the directory frontends/qt4 is renamed to frontends/qt. Many configurations file have to be updated. All mentions of qt4 in the source have been audited, and changed to qt if necessary. The only part that has not been updated is the CMake build system.
345 lines
7.5 KiB
C++
345 lines
7.5 KiB
C++
/**
|
|
* \file GuiLog.cpp
|
|
* This file is part of LyX, the document processor.
|
|
* Licence details can be found in the file COPYING.
|
|
*
|
|
* \author John Levon
|
|
* \author Angus Leeming
|
|
* \author Jürgen Spitzmüller
|
|
*
|
|
* Full author contact details are available in file CREDITS.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include "GuiLog.h"
|
|
|
|
#include "GuiApplication.h"
|
|
#include "qt_helpers.h"
|
|
#include "Lexer.h"
|
|
|
|
#include "frontends/Clipboard.h"
|
|
|
|
#include "support/docstring.h"
|
|
#include "support/FileName.h"
|
|
#include "support/gettext.h"
|
|
#include "support/lstrings.h"
|
|
|
|
#include <QDesktopServices>
|
|
#include <QTextBrowser>
|
|
#include <QSyntaxHighlighter>
|
|
#include <QUrl>
|
|
#include <QClipboard>
|
|
|
|
#include <fstream>
|
|
#include <sstream>
|
|
|
|
using namespace std;
|
|
using namespace lyx::support;
|
|
|
|
namespace lyx {
|
|
namespace frontend {
|
|
|
|
|
|
// Regular expressions needed at several places
|
|
// FIXME: These regexes are incomplete. It would be good if we could collect those used in LaTeX::scanLogFile
|
|
// and LaTeX::scanBlgFile and re-use them here!(spitz, 2013-05-27)
|
|
// Information
|
|
QRegExp exprInfo("^(Document Class:|LaTeX Font Info:|File:|Package:|Language:|.*> INFO - |\\(|\\\\).*$");
|
|
// Warnings
|
|
QRegExp exprWarning("^(LaTeX Warning|LaTeX Font Warning|Package [\\w\\.]+ Warning|Class \\w+ Warning|Warning--|Underfull|Overfull|.*> WARN - ).*$");
|
|
// Errors
|
|
QRegExp exprError("^(!|.*---line [0-9]+ of file|.*> FATAL - |.*> ERROR - |Missing character: There is no ).*$");
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LogHighlighter
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
class LogHighlighter : public QSyntaxHighlighter
|
|
{
|
|
public:
|
|
LogHighlighter(QTextDocument * parent);
|
|
|
|
private:
|
|
void highlightBlock(QString const & text);
|
|
|
|
private:
|
|
QTextCharFormat infoFormat;
|
|
QTextCharFormat warningFormat;
|
|
QTextCharFormat errorFormat;
|
|
};
|
|
|
|
|
|
|
|
LogHighlighter::LogHighlighter(QTextDocument * parent)
|
|
: QSyntaxHighlighter(parent)
|
|
{
|
|
infoFormat.setForeground(Qt::darkGray);
|
|
warningFormat.setForeground(Qt::darkBlue);
|
|
errorFormat.setForeground(Qt::red);
|
|
}
|
|
|
|
|
|
void LogHighlighter::highlightBlock(QString const & text)
|
|
{
|
|
// Info
|
|
int index = exprInfo.indexIn(text);
|
|
while (index >= 0) {
|
|
int length = exprInfo.matchedLength();
|
|
setFormat(index, length, infoFormat);
|
|
index = exprInfo.indexIn(text, index + length);
|
|
}
|
|
// LaTeX Warning:
|
|
index = exprWarning.indexIn(text);
|
|
while (index >= 0) {
|
|
int length = exprWarning.matchedLength();
|
|
setFormat(index, length, warningFormat);
|
|
index = exprWarning.indexIn(text, index + length);
|
|
}
|
|
// ! error
|
|
index = exprError.indexIn(text);
|
|
while (index >= 0) {
|
|
int length = exprError.matchedLength();
|
|
setFormat(index, length, errorFormat);
|
|
index = exprError.indexIn(text, index + length);
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GuiLog
|
|
//
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
GuiLog::GuiLog(GuiView & lv)
|
|
: GuiDialog(lv, "log", qt_("LaTeX Log")), type_(LatexLog)
|
|
{
|
|
setupUi(this);
|
|
|
|
connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
|
|
this, SLOT(slotButtonBox(QAbstractButton *)));
|
|
connect(updatePB, SIGNAL(clicked()), this, SLOT(updateContents()));
|
|
connect(findPB, SIGNAL(clicked()), this, SLOT(find()));
|
|
// FIXME: find via returnPressed() does not work!
|
|
connect(findLE, SIGNAL(returnPressed()), this, SLOT(find()));
|
|
connect(logTypeCO, SIGNAL(activated(int)),
|
|
this, SLOT(typeChanged(int)));
|
|
|
|
bc().setPolicy(ButtonPolicy::OkCancelPolicy);
|
|
|
|
// set syntax highlighting
|
|
highlighter = new LogHighlighter(logTB->document());
|
|
|
|
logTB->setReadOnly(true);
|
|
logTB->setFont(guiApp->typewriterSystemFont());
|
|
}
|
|
|
|
|
|
void GuiLog::updateContents()
|
|
{
|
|
setTitle(toqstr(title()));
|
|
|
|
ostringstream ss;
|
|
getContents(ss);
|
|
|
|
logTB->setPlainText(toqstr(ss.str()));
|
|
|
|
nextErrorPB->setEnabled(contains(exprError));
|
|
nextWarningPB->setEnabled(contains(exprWarning));
|
|
}
|
|
|
|
|
|
void GuiLog::typeChanged(int i)
|
|
{
|
|
string const type =
|
|
fromqstr(logTypeCO->itemData(i).toString());
|
|
string ext;
|
|
if (type == "latex")
|
|
ext = "log";
|
|
else if (type == "bibtex")
|
|
ext = "blg";
|
|
else if (type == "index")
|
|
ext = "ilg";
|
|
|
|
if (!ext.empty())
|
|
logfile_.changeExtension(ext);
|
|
|
|
updateContents();
|
|
}
|
|
|
|
|
|
void GuiLog::find()
|
|
{
|
|
logTB->find(findLE->text());
|
|
}
|
|
|
|
|
|
void GuiLog::on_nextErrorPB_clicked()
|
|
{
|
|
goTo(exprError);
|
|
}
|
|
|
|
|
|
void GuiLog::on_nextWarningPB_clicked()
|
|
{
|
|
goTo(exprWarning);
|
|
}
|
|
|
|
|
|
void GuiLog::on_openDirPB_clicked()
|
|
{
|
|
support::FileName dir = logfile_.onlyPath();
|
|
if (!dir.exists())
|
|
return;
|
|
QUrl qdir(QUrl::fromLocalFile(toqstr(from_utf8(dir.absFileName()))));
|
|
// Give hints in case of bugs
|
|
if (!qdir.isValid()) {
|
|
LYXERR0("QUrl is invalid!");
|
|
return;
|
|
}
|
|
if (!QDesktopServices::openUrl(qdir))
|
|
LYXERR0("Unable to open QUrl even though dir exists!");
|
|
}
|
|
|
|
|
|
void GuiLog::goTo(QRegExp const & exp) const
|
|
{
|
|
QTextCursor const newc =
|
|
logTB->document()->find(exp, logTB->textCursor());
|
|
logTB->setTextCursor(newc);
|
|
}
|
|
|
|
|
|
bool GuiLog::contains(QRegExp const & exp) const
|
|
{
|
|
return !logTB->document()->find(exp, logTB->textCursor()).isNull();
|
|
}
|
|
|
|
|
|
bool GuiLog::initialiseParams(string const & sdata)
|
|
{
|
|
istringstream is(sdata);
|
|
Lexer lex;
|
|
lex.setStream(is);
|
|
|
|
string logtype, logfile;
|
|
lex >> logtype;
|
|
if (lex) {
|
|
lex.next(true);
|
|
logfile = lex.getString();
|
|
}
|
|
if (!lex)
|
|
// Parsing of the data failed.
|
|
return false;
|
|
|
|
logTypeCO->setEnabled(logtype == "latex");
|
|
logTypeCO->clear();
|
|
|
|
FileName log(logfile);
|
|
|
|
if (logtype == "latex") {
|
|
type_ = LatexLog;
|
|
logTypeCO->addItem(qt_("LaTeX"), toqstr(logtype));
|
|
FileName tmp = log;
|
|
tmp.changeExtension("blg");
|
|
if (tmp.exists()) {
|
|
if (support::contains(tmp.fileContents("UTF-8"), from_ascii("This is Biber")))
|
|
logTypeCO->addItem(qt_("Biber"), QString("bibtex"));
|
|
else
|
|
logTypeCO->addItem(qt_("BibTeX"), QString("bibtex"));
|
|
}
|
|
tmp.changeExtension("ilg");
|
|
if (tmp.exists())
|
|
logTypeCO->addItem(qt_("Index"), QString("index"));
|
|
// FIXME: not sure "literate" still works.
|
|
} else if (logtype == "literate") {
|
|
type_ = LiterateLog;
|
|
logTypeCO->addItem(qt_("Literate"), toqstr(logtype));
|
|
} else if (logtype == "lyx2lyx") {
|
|
type_ = Lyx2lyxLog;
|
|
logTypeCO->addItem(qt_("LyX2LyX"), toqstr(logtype));
|
|
} else if (logtype == "vc") {
|
|
type_ = VCLog;
|
|
logTypeCO->addItem(qt_("Version Control"), toqstr(logtype));
|
|
} else
|
|
return false;
|
|
|
|
logfile_ = log;
|
|
|
|
updateContents();
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void GuiLog::clearParams()
|
|
{
|
|
logfile_.erase();
|
|
}
|
|
|
|
|
|
docstring GuiLog::title() const
|
|
{
|
|
switch (type_) {
|
|
case LatexLog:
|
|
return _("LaTeX Log");
|
|
case LiterateLog:
|
|
return _("Literate Programming Build Log");
|
|
case Lyx2lyxLog:
|
|
return _("lyx2lyx Error Log");
|
|
case VCLog:
|
|
return _("Version Control Log");
|
|
default:
|
|
return docstring();
|
|
}
|
|
}
|
|
|
|
|
|
void GuiLog::getContents(ostream & ss) const
|
|
{
|
|
ifstream in(logfile_.toFilesystemEncoding().c_str());
|
|
|
|
bool success = false;
|
|
|
|
// FIXME UNICODE
|
|
// Our caller interprets the file contents as UTF8, but is that
|
|
// correct?
|
|
// spitz: No it isn't (generally). The log file encoding depends on the TeX
|
|
// _output_ encoding (T1 etc.). We should account for that. See #10728.
|
|
if (in) {
|
|
ss << in.rdbuf();
|
|
success = ss.good();
|
|
}
|
|
|
|
if (success)
|
|
return;
|
|
|
|
switch (type_) {
|
|
case LatexLog:
|
|
ss << to_utf8(_("Log file not found."));
|
|
break;
|
|
case LiterateLog:
|
|
ss << to_utf8(_("No literate programming build log file found."));
|
|
break;
|
|
case Lyx2lyxLog:
|
|
ss << to_utf8(_("No lyx2lyx error log file found."));
|
|
break;
|
|
case VCLog:
|
|
ss << to_utf8(_("No version control log file found."));
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
Dialog * createGuiLog(GuiView & lv) { return new GuiLog(lv); }
|
|
|
|
|
|
} // namespace frontend
|
|
} // namespace lyx
|
|
|
|
#include "moc_GuiLog.cpp"
|