]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiLog.cpp
If we are in a closeEvent, we don't want to close all buffers, because these may...
[lyx.git] / src / frontends / qt4 / GuiLog.cpp
1 /**
2  * \file GuiLog.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Levon
7  * \author Angus Leeming
8  * \author Jürgen Spitzmüller
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "GuiLog.h"
16
17 #include "GuiApplication.h"
18 #include "qt_helpers.h"
19 #include "Lexer.h"
20
21 #include "support/docstring.h"
22 #include "support/gettext.h"
23
24 #include <QTextBrowser>
25 #include <QSyntaxHighlighter>
26 #include <QClipboard>
27
28 #include <fstream>
29 #include <sstream>
30
31 using namespace std;
32 using namespace lyx::support;
33
34 namespace lyx {
35 namespace frontend {
36
37
38 // Regular expressions needed at several places
39 // Information
40 QRegExp exprInfo("^(Document Class:|LaTeX Font Info:|File:|Package:|Language:|Underfull|Overfull|\\(|\\\\).*$");
41 // Warnings
42 QRegExp exprWarning("^(LaTeX Warning|Package \\w+ Warning).*$");
43 // Errors
44 QRegExp exprError("^!.*$");
45
46
47 /////////////////////////////////////////////////////////////////////
48 //
49 // LogHighlighter
50 //
51 ////////////////////////////////////////////////////////////////////
52
53 class LogHighlighter : public QSyntaxHighlighter
54 {
55 public:
56         LogHighlighter(QTextDocument * parent);
57
58 private:
59         void highlightBlock(QString const & text);
60
61 private:
62         QTextCharFormat infoFormat;
63         QTextCharFormat warningFormat;
64         QTextCharFormat errorFormat;
65 };
66
67
68
69 LogHighlighter::LogHighlighter(QTextDocument * parent)
70         : QSyntaxHighlighter(parent)
71 {
72         infoFormat.setForeground(Qt::darkGray);
73         warningFormat.setForeground(Qt::darkBlue);
74         errorFormat.setForeground(Qt::red);
75 }
76
77
78 void LogHighlighter::highlightBlock(QString const & text)
79 {
80         // Info
81         int index = exprInfo.indexIn(text);
82         while (index >= 0) {
83                 int length = exprInfo.matchedLength();
84                 setFormat(index, length, infoFormat);
85                 index = exprInfo.indexIn(text, index + length);
86         }
87         // LaTeX Warning:
88         index = exprWarning.indexIn(text);
89         while (index >= 0) {
90                 int length = exprWarning.matchedLength();
91                 setFormat(index, length, warningFormat);
92                 index = exprWarning.indexIn(text, index + length);
93         }
94         // ! error
95         index = exprError.indexIn(text);
96         while (index >= 0) {
97                 int length = exprError.matchedLength();
98                 setFormat(index, length, errorFormat);
99                 index = exprError.indexIn(text, index + length);
100         }
101 }
102
103
104 /////////////////////////////////////////////////////////////////////
105 //
106 // GuiLog
107 //
108 /////////////////////////////////////////////////////////////////////
109
110 GuiLog::GuiLog(GuiView & lv)
111         : GuiDialog(lv, "log", qt_("LaTeX Log")), type_(LatexLog)
112 {
113         setupUi(this);
114
115         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
116         connect(updatePB, SIGNAL(clicked()), this, SLOT(updateContents()));
117         connect(findPB, SIGNAL(clicked()), this, SLOT(find()));
118         // FIXME: find via returnPressed() does not work!
119         connect(findLE, SIGNAL(returnPressed()), this, SLOT(find()));
120
121         bc().setPolicy(ButtonPolicy::OkCancelPolicy);
122
123         // set syntax highlighting
124         highlighter = new LogHighlighter(logTB->document());
125
126         logTB->setReadOnly(true);
127         QFont font(guiApp->typewriterFontName());
128         font.setKerning(false);
129         font.setFixedPitch(true);
130         font.setStyleHint(QFont::TypeWriter);
131         logTB->setFont(font);
132 }
133
134
135 void GuiLog::updateContents()
136 {
137         setTitle(toqstr(title()));
138
139         ostringstream ss;
140         getContents(ss);
141
142         logTB->setPlainText(toqstr(ss.str()));
143
144         nextErrorPB->setEnabled(contains(exprError));
145         nextWarningPB->setEnabled(contains(exprWarning));
146 }
147
148
149 void GuiLog::find()
150 {
151         logTB->find(findLE->text());
152 }
153
154
155 void GuiLog::on_nextErrorPB_clicked()
156 {
157         goTo(exprError);
158 }
159
160
161 void GuiLog::on_nextWarningPB_clicked()
162 {
163         goTo(exprWarning);
164 }
165
166
167 void GuiLog::goTo(QRegExp const & exp) const
168 {
169         QTextCursor const newc =
170                 logTB->document()->find(exp, logTB->textCursor());
171         logTB->setTextCursor(newc);
172 }
173
174
175 bool GuiLog::contains(QRegExp const & exp) const
176 {
177         return !logTB->document()->find(exp, logTB->textCursor()).isNull();
178 }
179
180
181 bool GuiLog::initialiseParams(string const & data)
182 {
183         istringstream is(data);
184         Lexer lex;
185         lex.setStream(is);
186
187         string logtype, logfile;
188         lex >> logtype;
189         if (lex) {
190                 lex.next(true);
191                 logfile = lex.getString();
192         }
193         if (!lex)
194                 // Parsing of the data failed.
195                 return false;
196
197         if (logtype == "latex")
198                 type_ = LatexLog;
199         // FIXME: not sure "literate" still works.
200         else if (logtype == "literate")
201                 type_ = LiterateLog;
202         else if (logtype == "lyx2lyx")
203                 type_ = Lyx2lyxLog;
204         else if (logtype == "vc")
205                 type_ = VCLog;
206         else
207                 return false;
208
209         logfile_ = FileName(logfile);
210
211         updateContents();
212
213         return true;
214 }
215
216
217 void GuiLog::clearParams()
218 {
219         logfile_.erase();
220 }
221
222
223 docstring GuiLog::title() const
224 {
225         switch (type_) {
226         case LatexLog:
227                 return _("LaTeX Log");
228         case LiterateLog:
229                 return _("Literate Programming Build Log");
230         case Lyx2lyxLog:
231                 return _("lyx2lyx Error Log");
232         case VCLog:
233                 return _("Version Control Log");
234         default:
235                 return docstring();
236         }
237 }
238
239
240 void GuiLog::getContents(ostream & ss) const
241 {
242         ifstream in(logfile_.toFilesystemEncoding().c_str());
243
244         bool success = false;
245
246         // FIXME UNICODE
247         // Our caller interprets the file contents as UTF8, but is that
248         // correct?
249         if (in) {
250                 ss << in.rdbuf();
251                 success = ss.good();
252         }
253
254         if (success)
255                 return;
256
257         switch (type_) {
258         case LatexLog:
259                 ss << to_utf8(_("No LaTeX log file found."));
260                 break;
261         case LiterateLog:
262                 ss << to_utf8(_("No literate programming build log file found."));
263                 break;
264         case Lyx2lyxLog:
265                 ss << to_utf8(_("No lyx2lyx error log file found."));
266                 break;
267         case VCLog:
268                 ss << to_utf8(_("No version control log file found."));
269                 break;
270         }
271 }
272
273
274 void GuiLog::on_copyPB_clicked()
275 {
276         qApp->clipboard()->setText(logTB->toPlainText());
277 }
278
279
280 Dialog * createGuiLog(GuiView & lv) { return new GuiLog(lv); }
281
282
283 } // namespace frontend
284 } // namespace lyx
285
286 #include "moc_GuiLog.cpp"