Qt 4.8
qscriptdebuggerconsolewidget.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtSCriptTools module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
47 
48 #include <QtCore/qdebug.h>
49 #include <QtGui/qplaintextedit.h>
50 #include <QtGui/qlabel.h>
51 #include <QtGui/qlineedit.h>
52 #include <QtGui/qlistview.h>
53 #include <QtGui/qscrollbar.h>
54 #include <QtGui/qboxlayout.h>
55 #include <QtGui/qcompleter.h>
56 
58 
59 namespace {
60 
61 class PromptLabel : public QLabel
62 {
63 public:
64  PromptLabel(QWidget *parent = 0)
65  : QLabel(parent)
66  {
68  setIndent(2);
69  setMargin(2);
70  setSizePolicy(QSizePolicy::Minimum, sizePolicy().verticalPolicy());
72 #ifndef QT_NO_STYLE_STYLESHEET
73  setStyleSheet(QLatin1String("background: white;"));
74 #endif
75  }
76 
77  QSize sizeHint() const {
78  QFontMetrics fm(font());
79  return fm.size(0, text()) + QSize(8, 0);
80  }
81 };
82 
83 class InputEdit : public QLineEdit
84 {
85 public:
86  InputEdit(QWidget *parent = 0)
87  : QLineEdit(parent)
88  {
89  setFrame(false);
90  setSizePolicy(QSizePolicy::MinimumExpanding, sizePolicy().verticalPolicy());
91  }
92 };
93 
94 class CommandLine : public QWidget
95 {
96  Q_OBJECT
97 public:
98  CommandLine(QWidget *parent = 0)
99  : QWidget(parent)
100  {
101  promptLabel = new PromptLabel();
102  inputEdit = new InputEdit();
103  QHBoxLayout *hbox = new QHBoxLayout(this);
104  hbox->setSpacing(0);
105  hbox->setMargin(0);
106  hbox->addWidget(promptLabel);
107  hbox->addWidget(inputEdit);
108 
109  QObject::connect(inputEdit, SIGNAL(returnPressed()),
110  this, SLOT(onReturnPressed()));
111  QObject::connect(inputEdit, SIGNAL(textEdited(QString)),
112  this, SIGNAL(lineEdited(QString)));
113 
114  setFocusProxy(inputEdit);
115  }
116 
117  QString prompt() const
118  {
119  return promptLabel->text();
120  }
121  void setPrompt(const QString &prompt)
122  {
123  promptLabel->setText(prompt);
124  }
125 
126  QString input() const
127  {
128  return inputEdit->text();
129  }
130  void setInput(const QString &input)
131  {
132  inputEdit->setText(input);
133  }
134 
135  int cursorPosition() const
136  {
137  return inputEdit->cursorPosition();
138  }
139  void setCursorPosition(int position)
140  {
141  inputEdit->setCursorPosition(position);
142  }
143 
144  QWidget *editor() const
145  {
146  return inputEdit;
147  }
148 
149 Q_SIGNALS:
150  void lineEntered(const QString &contents);
151  void lineEdited(const QString &contents);
152 
153 private Q_SLOTS:
154  void onReturnPressed()
155  {
156  QString text = inputEdit->text();
157  inputEdit->clear();
158  emit lineEntered(text);
159  }
160 
161 private:
162  PromptLabel *promptLabel;
163  InputEdit *inputEdit;
164 };
165 
166 class QScriptDebuggerConsoleWidgetOutputEdit : public QPlainTextEdit
167 {
168 public:
169  QScriptDebuggerConsoleWidgetOutputEdit(QWidget *parent = 0)
170  : QPlainTextEdit(parent)
171  {
172  setFrameShape(QFrame::NoFrame);
173  setReadOnly(true);
174 // ### there's no context menu when the edit can't have focus,
175 // even though you can select text in it.
176 // setFocusPolicy(Qt::NoFocus);
177  setMaximumBlockCount(2500);
178  }
179 
180  void scrollToBottom()
181  {
182  QScrollBar *bar = verticalScrollBar();
183  bar->setValue(bar->maximum());
184  }
185 
186  int charactersPerLine() const
187  {
188  QFontMetrics fm(font());
189  return width() / fm.maxWidth();
190  }
191 };
192 
193 } // namespace
194 
197 {
199 public:
202 
203  // private slots
204  void _q_onLineEntered(const QString &contents);
205  void _q_onLineEdited(const QString &contents);
206  void _q_onCompletionTaskFinished();
207 
208  CommandLine *commandLine;
209  QScriptDebuggerConsoleWidgetOutputEdit *outputEdit;
212 };
213 
215 {
216  historyIndex = -1;
217 }
218 
220 {
221 }
222 
224 {
226  outputEdit->appendPlainText(QString::fromLatin1("%0 %1").arg(commandLine->prompt()).arg(contents));
227  outputEdit->scrollToBottom();
228  historyIndex = -1;
229  newInput.clear();
230  emit q->lineEntered(contents);
231 }
232 
234 {
235  if (historyIndex != -1) {
236  // ### try to get the bash behavior...
237 #if 0
238  historian->changeHistoryAt(historyIndex, contents);
239 #endif
240  } else {
241  newInput = contents;
242  }
243 }
244 
245 static bool lengthLessThan(const QString &s1, const QString &s2)
246 {
247  return s1.length() < s2.length();
248 }
249 
250 // input must be sorted by length already
252 {
253  QString result = lst.last();
254  for (int i = lst.size() - 2; (i >= 0) && !result.isEmpty(); --i) {
255  const QString &s = lst.at(i);
256  int j = 0;
257  for ( ; (j < qMin(s.length(), result.length())) && (s.at(j) == result.at(j)); ++j)
258  ;
259  result = result.left(j);
260  }
261  return result;
262 }
263 
265 {
267  task = qobject_cast<QScriptCompletionTaskInterface*>(q_func()->sender());
268  if (task->resultCount() == 1) {
269  QString completion = task->resultAt(0);
270  completion.append(task->appendix());
271  QString tmp = commandLine->input();
272  tmp.remove(task->position(), task->length());
273  tmp.insert(task->position(), completion);
274  commandLine->setInput(tmp);
275  } else if (task->resultCount() > 1) {
276  {
277  QStringList lst;
278  for (int i = 0; i < task->resultCount(); ++i)
279  lst.append(task->resultAt(i).mid(task->length()));
280  qSort(lst.begin(), lst.end(), lengthLessThan);
281  QString lcp = longestCommonPrefix(lst);
282  if (!lcp.isEmpty()) {
283  QString tmp = commandLine->input();
284  tmp.insert(task->position() + task->length(), lcp);
285  commandLine->setInput(tmp);
286  }
287  }
288 
289  outputEdit->appendPlainText(QString::fromLatin1("%0 %1")
290  .arg(commandLine->prompt()).arg(commandLine->input()));
291  int maxLength = 0;
292  for (int i = 0; i < task->resultCount(); ++i)
293  maxLength = qMax(maxLength, task->resultAt(i).length());
294  Q_ASSERT(maxLength > 0);
295  int tab = 8;
296  int columns = qMax(1, outputEdit->charactersPerLine() / (maxLength + tab));
297  QString msg;
298  for (int i = 0; i < task->resultCount(); ++i) {
299  if (i != 0) {
300  if ((i % columns) == 0) {
301  outputEdit->appendPlainText(msg);
302  msg.clear();
303  } else {
304  int pad = maxLength + tab - (msg.length() % (maxLength + tab));
305  msg.append(QString(pad, QLatin1Char(' ')));
306  }
307  }
308  msg.append(task->resultAt(i));
309  }
310  if (!msg.isEmpty())
311  outputEdit->appendPlainText(msg);
312  outputEdit->scrollToBottom();
313  }
314  task->deleteLater();
315 }
316 
319 {
321  d->commandLine = new CommandLine();
322  d->commandLine->setPrompt(QString::fromLatin1("qsdb>"));
323  d->outputEdit = new QScriptDebuggerConsoleWidgetOutputEdit();
324  QVBoxLayout *vbox = new QVBoxLayout(this);
325  vbox->setSpacing(0);
326  vbox->setMargin(0);
327  vbox->addWidget(d->outputEdit);
328  vbox->addWidget(d->commandLine);
329 
330 #if 0
331  QString sheet = QString::fromLatin1("background-color: black;"
332  "color: aquamarine;"
333  "font-size: 14px;"
334  "font-family: \"Monospace\"");
335 #endif
336 #ifndef QT_NO_STYLE_STYLESHEET
337  QString sheet = QString::fromLatin1("font-size: 14px; font-family: \"Monospace\";");
338  setStyleSheet(sheet);
339 #endif
340 
341  QObject::connect(d->commandLine, SIGNAL(lineEntered(QString)),
342  this, SLOT(_q_onLineEntered(QString)));
343  QObject::connect(d->commandLine, SIGNAL(lineEdited(QString)),
344  this, SLOT(_q_onLineEdited(QString)));
345 }
346 
348 {
349 }
350 
352  QtMsgType type, const QString &text, const QString &fileName,
353  int lineNumber, int columnNumber, const QVariant &/*data*/)
354 {
356  QString msg;
357  if (!fileName.isEmpty() || (lineNumber != -1)) {
358  if (!fileName.isEmpty())
359  msg.append(fileName);
360  else
361  msg.append(QLatin1String("<noname>"));
362  if (lineNumber != -1) {
363  msg.append(QLatin1Char(':'));
364  msg.append(QString::number(lineNumber));
365  if (columnNumber != -1) {
366  msg.append(QLatin1Char(':'));
367  msg.append(QString::number(columnNumber));
368  }
369  }
370  msg.append(QLatin1String(": "));
371  }
372  msg.append(text);
373  QTextCharFormat oldFmt = d->outputEdit->currentCharFormat();
374  QTextCharFormat fmt(oldFmt);
375  if (type == QtCriticalMsg) {
376  fmt.setForeground(Qt::red);
377  d->outputEdit->setCurrentCharFormat(fmt);
378  }
379  d->outputEdit->appendPlainText(msg);
380  d->outputEdit->setCurrentCharFormat(oldFmt);
381  d->outputEdit->scrollToBottom();
382 }
383 
385 {
387  QString prompt = enabled
388  ? QString::fromLatin1("....")
389  : QString::fromLatin1("qsdb>");
390  d->commandLine->setPrompt(prompt);
391 }
392 
394 {
396  d->outputEdit->clear();
397 }
398 
400 {
402  if (event->key() == Qt::Key_Up) {
403  if (d->historyIndex+1 == d->historian->historyCount())
404  return;
405  QString cmd = d->historian->historyAt(++d->historyIndex);
406  d->commandLine->setInput(cmd);
407  } else if (event->key() == Qt::Key_Down) {
408  if (d->historyIndex == -1) {
409  // nothing to do
410  } else if (d->historyIndex == 0) {
411  d->commandLine->setInput(d->newInput);
412  --d->historyIndex;
413  } else {
414  QString cmd = d->historian->historyAt(--d->historyIndex);
415  d->commandLine->setInput(cmd);
416  }
417  } else if (event->key() == Qt::Key_Tab) {
419  task = d->completionProvider->createCompletionTask(
420  d->commandLine->input(), d->commandLine->cursorPosition(),
421  /*frameIndex=*/-1, // current frame
423  QObject::connect(task, SIGNAL(finished()),
424  this, SLOT(_q_onCompletionTaskFinished()));
425  task->start();
426  } else {
428  }
429 }
430 
432 {
434  if (d->outputEdit->hasFocus())
436  else
437  return false;
438 }
439 
441 
442 #include "qscriptdebuggerconsolewidget.moc"
443 
444 #include "moc_qscriptdebuggerconsolewidget_p.cpp"
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
T qobject_cast(QObject *object)
Definition: qobject.h:375
double d
Definition: qnumeric_p.h:62
bool enabled
whether the widget is enabled
Definition: qwidget.h:157
The QKeyEvent class describes a key event.
Definition: qevent.h:224
void message(QtMsgType type, const QString &text, const QString &fileName=QString(), int lineNumber=-1, int columnNumber=-1, const QVariant &data=QVariant())
int type
Definition: qmetatype.cpp:239
The QTextCharFormat class provides formatting information for characters in a QTextDocument.
Definition: qtextformat.h:372
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
The QFontMetrics class provides font metrics information.
Definition: qfontmetrics.h:65
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
static QString longestCommonPrefix(const QStringList &lst)
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
#define SLOT(a)
Definition: qobjectdefs.h:226
static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
iterator begin()
Returns an STL-style iterator pointing to the first item in the list.
Definition: qlist.h:267
QSize sizeHint() const
em>Reimplemented Function
Definition: qlabel.cpp:947
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
#define Q_SLOTS
Definition: qobjectdefs.h:71
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
QtMsgType
This enum describes the messages that can be sent to a message handler (QtMsgHandler).
Definition: qglobal.h:1881
#define Q_D(Class)
Definition: qglobal.h:2482
#define Q_SIGNALS
Definition: qobjectdefs.h:72
void addWidget(QWidget *, int stretch=0, Qt::Alignment alignment=0)
Adds widget to the end of this box layout, with a stretch factor of stretch and alignment alignment...
static bool lengthLessThan(const QString &s1, const QString &s2)
bool focusNextPrevChild(bool)
Finds a new widget to give the keyboard focus to, as appropriate for Tab and Shift+Tab, and returns true if it can find a new widget, or false if it can&#39;t.
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
#define Q_Q(Class)
Definition: qglobal.h:2483
QSizePolicy sizePolicy() const
int key() const
Returns the code of the key that was pressed or released.
Definition: qevent.h:231
#define SIGNAL(a)
Definition: qobjectdefs.h:227
The QScrollBar widget provides a vertical or horizontal scroll bar.
Definition: qscrollbar.h:59
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
QString text() const
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:270
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define emit
Definition: qobjectdefs.h:76
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
The QPlainTextEdit class provides a widget that is used to edit and display plain text...
void setFrameShape(Shape)
Definition: qframe.cpp:284
QScriptDebuggerConsoleWidgetOutputEdit * outputEdit
virtual void keyPressEvent(QKeyEvent *)
This event handler, for event event, can be reimplemented in a subclass to receive key press events f...
Definition: qwidget.cpp:9375
void qSort(RandomAccessIterator start, RandomAccessIterator end)
Definition: qalgorithms.h:177
#define Q_OBJECT
Definition: qobjectdefs.h:157
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
#define Q_DECLARE_PUBLIC(Class)
Definition: qglobal.h:2477
QString & append(QChar c)
Definition: qstring.cpp:1777
void setMargin(int)
Definition: qlabel.cpp:654
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
void setSpacing(int spacing)
Reimplements QLayout::setSpacing().
Definition: qboxlayout.cpp:667
T & last()
Returns a reference to the last item in the list.
Definition: qlist.h:284
virtual bool focusNextPrevChild(bool next)
Finds a new widget to give the keyboard focus to, as appropriate for Tab and Shift+Tab, and returns true if it can find a new widget, or false if it can&#39;t.
Definition: qwidget.cpp:6836
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
The QLabel widget provides a text or image display.
Definition: qlabel.h:55
The QHBoxLayout class lines up widgets horizontally.
Definition: qboxlayout.h:129
The QLineEdit widget is a one-line text editor.
Definition: qlineedit.h:66
void setForeground(const QBrush &brush)
Sets the foreground brush to the specified brush.
Definition: qtextformat.h:350
const QFont & font() const
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
The QVBoxLayout class lines up widgets vertically.
Definition: qboxlayout.h:149
bool event(QEvent *)
This is the main event handler; it handles event event.
Definition: qwidget.cpp:8636
QString & remove(int i, int len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition: qstring.cpp:1867
void setStyleSheet(const QString &styleSheet)
Definition: qwidget.cpp:2709
int maximum() const
void setSizePolicy(QSizePolicy)
Definition: qwidget.cpp:10198
void setMargin(int)
Definition: qlayout.cpp:464
QString & insert(int i, QChar c)
Definition: qstring.cpp:1671
static QString fileName(const QString &fileUrl)
void setAlignment(Qt::Alignment)
Without this function, a call to e.
Definition: qlabel.cpp:532
void deleteLater()
Schedules this object for deletion.
Definition: qobject.cpp:2145
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
void keyPressEvent(QKeyEvent *event)
This event handler, for event event, can be reimplemented in a subclass to receive key press events f...
#define text
Definition: qobjectdefs.h:80
void setIndent(int)
Definition: qlabel.cpp:620
void lineEntered(const QString &contents)