Tulip  4.4.0
Better Visualization Through Research
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Groups Pages
ConsoleHandlers.h
1 /*
2  *
3  * This file is part of Tulip (www.tulip-software.org)
4  *
5  * Authors: David Auber and the Tulip development Team
6  * from LaBRI, University of Bordeaux 1 and Inria Bordeaux - Sud Ouest
7  *
8  * Tulip is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation, either version 3
11  * of the License, or (at your option) any later version.
12  *
13  * Tulip is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU General Public License for more details.
17  *
18  */
19 
20 #ifndef CONSOLE_OUTPUT_HANDLER_H
21 #define CONSOLE_OUTPUT_HANDLER_H
22 
23 #include <QPlainTextEdit>
24 #include <QTextBrowser>
25 #include <QTextBlock>
26 #include <QApplication>
27 #include <QTime>
28 #include <QScrollBar>
29 
30 #include <iostream>
31 
32 class ConsoleOutputHandler : public QObject {
33 
34  Q_OBJECT
35 
36 public:
37 
38  ConsoleOutputHandler() {
39  timer.start();
40  }
41 
42 
43 public slots :
44 
45  void writeToConsole(QAbstractScrollArea *consoleWidget, const QString &output, bool errorOutput) {
46 
47  if (!consoleWidget)
48  return;
49 
50  QTextBrowser *textBrowser = dynamic_cast<QTextBrowser*>(consoleWidget);
51  QPlainTextEdit *textEdit = dynamic_cast<QPlainTextEdit*>(consoleWidget);
52 
53  QBrush brush(Qt::SolidPattern);
54 
55  if (errorOutput) {
56  brush.setColor(Qt::red);
57  }
58  else {
59  brush.setColor(Qt::black);
60  }
61 
62  QTextCursor cursor;
63  QTextCharFormat formt;
64 
65  if (textEdit) {
66  formt = textEdit->textCursor().charFormat();
67  formt.setForeground(brush);
68  textEdit->moveCursor(QTextCursor::End);
69  cursor = textEdit->textCursor();
70  }
71  else {
72  formt = textBrowser->textCursor().charFormat();
73  formt.setForeground(brush);
74  formt.setAnchor(false);
75  formt.setUnderlineStyle(QTextCharFormat::NoUnderline);
76  formt.setAnchorHref("");
77  textBrowser->moveCursor(QTextCursor::End);
78  cursor = textBrowser->textCursor();
79  }
80 
81  cursor.insertText(output, formt);
82 
83  if (textBrowser) {
84  QRegExp rx("^.*File.*\"(.*)\".*line.*(\\d+).*$");
85  QRegExp rx2("^.*File.*\"(.*)\".*line.*(\\d+).*in (.*)$");
86  cursor = textBrowser->document()->find(rx, QTextCursor(textBrowser->document()->begin()));
87 
88  while (!cursor.isNull()) {
89  rx.indexIn(cursor.selectedText());
90  rx2.indexIn(cursor.selectedText());
91 
92  if (rx.cap(1) != "<string>" && rx2.cap(3) != "tlpimporthook") {
93  formt = cursor.charFormat();
94  formt.setAnchor(true);
95  formt.setUnderlineStyle(QTextCharFormat::SingleUnderline);
96  formt.setAnchorHref(rx.cap(1) + ":" + rx.cap(2));
97  cursor.setCharFormat(formt);
98  }
99 
100  cursor = textBrowser->document()->find(rx, cursor);
101  }
102 
103  if (timer.elapsed() >= 50) {
104  QApplication::processEvents();
105  timer.start();
106  }
107  }
108  }
109 
110 private:
111 
112  QTime timer;
113 
114 };
115 
116 class ConsoleOutputEmitter : public QObject {
117 
118  Q_OBJECT
119 
120 public:
121 
122  ConsoleOutputEmitter() : _consoleWidget(NULL), _outputActivated(true) {}
123 
124  void sendOutputToConsole(const QString &output, bool errorOutput) {
125  if (_outputActivated) {
126  emit consoleOutput(_consoleWidget, output, errorOutput);
127  }
128  }
129 
130  void setConsoleWidget(QAbstractScrollArea *consoleWidget) {
131  _consoleWidget = consoleWidget;
132  }
133 
134  QAbstractScrollArea *consoleWidget() const {
135  return _consoleWidget;
136  }
137 
138  void setOutputActivated(bool outputActivated) {
139  _outputActivated = outputActivated;
140  }
141 
142 signals:
143 
144  void consoleOutput(QAbstractScrollArea *consoleWidget, const QString &output, bool errorOutput);
145 
146 private :
147 
148  QAbstractScrollArea *_consoleWidget;
149  bool _outputActivated;
150 };
151 
152 class ConsoleInputHandler : public QObject {
153 
154  Q_OBJECT
155 
156 public:
157 
158  ConsoleInputHandler() : _startReadCol(-1), _consoleWidget(NULL), _lineRead(false), _wasReadOnly(false) {}
159 
160  void setConsoleWidget(QAbstractScrollArea *consoleWidget) {
161  _consoleWidget = consoleWidget;
162  }
163 
164  QAbstractScrollArea *consoleWidget() const {
165  return _consoleWidget;
166  }
167 
168  void startReadLine() {
169  if (_consoleWidget) {
170  _consoleWidget->installEventFilter(this);
171  qApp->installEventFilter(this);
172  _consoleWidget->setFocus();
173  }
174  else {
175  _lineRead = true;
176  return;
177  }
178 
179  _lineRead = false;
180  QTextBrowser *textBrowser = dynamic_cast<QTextBrowser*>(_consoleWidget);
181  QPlainTextEdit *textEdit = dynamic_cast<QPlainTextEdit*>(_consoleWidget);
182  QColor lineColor = QColor(Qt::green).lighter(160);
183 
184  if (textBrowser) {
185  _readPos = textBrowser->textCursor();
186  _wasReadOnly = textBrowser->isReadOnly();
187  textBrowser->setReadOnly(false);
188  textBrowser->verticalScrollBar()->setValue(textBrowser->verticalScrollBar()->maximum());
189  }
190  else if (textEdit) {
191  _readPos = textEdit->textCursor();
192  _wasReadOnly = textEdit->isReadOnly();
193  textEdit->setReadOnly(false);
194  }
195 
196  _startReadCol = _readPos.columnNumber();
197  QTextBlockFormat format = _blockFormat = _readPos.blockFormat();
198  format.setBackground(lineColor);
199  format.setProperty(QTextFormat::FullWidthSelection, true);
200  _readPos.setBlockFormat(format);
201  }
202 
203  bool lineRead() const {
204  return _lineRead;
205  }
206 
207  QString line() const {
208  return _line;
209  }
210 
211  bool eventFilter(QObject *, QEvent *event) {
212  QTextBrowser *textBrowser = dynamic_cast<QTextBrowser*>(_consoleWidget);
213  QPlainTextEdit *textEdit = dynamic_cast<QPlainTextEdit*>(_consoleWidget);
214  QTextCursor curCursor;
215 
216  if (textBrowser) {
217  curCursor = textBrowser->textCursor();
218  }
219  else {
220  curCursor = textEdit->textCursor();
221  }
222 
223  if (event->type() == QEvent::KeyPress) {
224  QKeyEvent *kev = static_cast<QKeyEvent *>(event);
225  int key = kev->key();
226 
227  if ((key == Qt::Key_Enter || key == Qt::Key_Return) && kev->modifiers() == Qt::NoModifier) {
228  _lineRead = true;
229  _line = _readPos.block().text().mid(_startReadCol);
230  _line.append("\n");
231  _readPos.insertText("\n");
232  _readPos.setBlockFormat(_blockFormat);
233 
234  if (textBrowser) {
235  textBrowser->setReadOnly(_wasReadOnly);
236  }
237  else {
238  textEdit->setReadOnly(_wasReadOnly);
239  }
240 
241  _consoleWidget->removeEventFilter(this);
242  qApp->removeEventFilter(this);
243  return true;
244  }
245  else if (key == Qt::Key_Up || key == Qt::Key_Down) {
246  return true;
247  }
248  else if (key == Qt::Key_Left) {
249  if (curCursor.columnNumber() > _startReadCol) {
250  if (textEdit) {
251  textEdit->moveCursor(QTextCursor::Left);
252  }
253  else {
254  textBrowser->moveCursor(QTextCursor::Left);
255  }
256  }
257 
258  return true;
259  }
260  else if (key == Qt::Key_Right) {
261  if (textEdit) {
262  textEdit->moveCursor(QTextCursor::Right);
263  }
264  else {
265  textBrowser->moveCursor(QTextCursor::Right);
266  }
267  }
268  else if (key == Qt::Key_Backspace) {
269  if (curCursor.columnNumber() > _startReadCol) {
270  curCursor.deletePreviousChar();
271  }
272 
273  return true;
274  }
275  }
276  else if (event->type() == QEvent::MouseButtonDblClick || event->type() == QEvent::MouseButtonPress ||
277  event->type() == QEvent::MouseButtonRelease) {
278  return true;
279  }
280 
281  return false;
282  }
283 
284 private:
285 
286  QTextCursor _readPos;
287  int _startReadCol;
288  QAbstractScrollArea *_consoleWidget;
289  bool _lineRead;
290  QString _line;
291  bool _wasReadOnly;
292  QTextBlockFormat _blockFormat;
293 
294 };
295 
296 
297 
298 #endif