GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
TerminalView.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>
3  Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
4 
5  Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
6  Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@googlemail.com>
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program 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. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301 USA.
22 */
23 
24 #ifndef TERMINALVIEW_H
25 #define TERMINALVIEW_H
26 
27 // Qt
28 #include <QColor>
29 #include <QtCore/QPointer>
30 #include <QWidget>
31 
32 // Konsole
33 #include "unix/Filter.h"
34 #include "unix/Character.h"
35 
36 class QDrag;
37 class QDragEnterEvent;
38 class QDropEvent;
39 class QLabel;
40 class QTimer;
41 class QEvent;
42 class QFrame;
43 class QGridLayout;
44 class QKeyEvent;
45 class QScrollBar;
46 class QShowEvent;
47 class QHideEvent;
48 class QWidget;
49 
50 extern unsigned short vt100_graphics[32];
51 
52 class ScreenWindow;
53 
54 /**
55  * A widget which displays output from a terminal emulation and sends input keypresses and mouse activity
56  * to the terminal.
57  *
58  * When the terminal emulation receives new output from the program running in the terminal,
59  * it will update the display by calling updateImage().
60  *
61  * TODO More documentation
62  */
63 class TerminalView : public QWidget
64 {
65  Q_OBJECT
66 
67 public:
68  /** Constructs a new terminal display widget with the specified parent. */
69  TerminalView(QWidget *parent = 0);
70  virtual ~TerminalView();
71 
72  /** Returns the terminal color palette used by the display. */
73  const ColorEntry* colorTable() const;
74  /** Sets the terminal color palette used by the display. */
75  void setColorTable(const ColorEntry table[]);
76  /**
77  * Sets the seed used to generate random colors for the display
78  * (in color schemes that support them).
79  */
80  void setRandomSeed(uint seed);
81  /**
82  * Returns the seed used to generate random colors for the display
83  * (in color schemes that support them).
84  */
85  uint randomSeed() const;
86 
87 
88  /**
89  * This enum describes the location where the scroll bar is positioned in the display widget.
90  */
92  {
93  /** Do not show the scroll bar. */
95  /** Show the scroll bar on the left side of the display. */
97  /** Show the scroll bar on the right side of the display. */
99  };
100  /**
101  * Specifies whether the terminal display has a vertical scroll bar, and if so whether it
102  * is shown on the left or right side of the display.
103  */
105 
106  /**
107  * Sets the current position and range of the display's scroll bar.
108  *
109  * @param cursor The position of the scroll bar's thumb.
110  * @param lines The maximum value of the scroll bar.
111  */
112  void setScroll(int cursor, int lines);
113 
114  /**
115  * Returns the display's filter chain. When the image for the display is updated,
116  * the text is passed through each filter in the chain. Each filter can define
117  * hotspots which correspond to certain strings (such as URLs or particular words).
118  * Depending on the type of the hotspots created by the filter ( returned by Filter::Hotspot::type() )
119  * the view will draw visual cues such as underlines on mouse-over for links or translucent
120  * rectangles for markers.
121  *
122  * To add a new filter to the view, call:
123  * viewWidget->filterChain()->addFilter( filterObject );
124  */
125  FilterChain* filterChain() const;
126 
127  /**
128  * Updates the filters in the display's filter chain. This will cause
129  * the hotspots to be updated to match the current image.
130  *
131  * WARNING: This function can be expensive depending on the
132  * image size and number of filters in the filterChain()
133  *
134  * TODO - This API does not really allow efficient usage. Revise it so
135  * that the processing can be done in a better way.
136  *
137  * eg:
138  * - Area of interest may be known ( eg. mouse cursor hovering
139  * over an area )
140  */
141  void processFilters();
142 
143  /**
144  * Returns a list of menu actions created by the filters for the content
145  * at the given @p position.
146  */
147  QList<QAction*> filterActions(const QPoint& position);
148 
149  /** Returns true if the cursor is set to blink or false otherwise. */
151  /** Specifies whether or not the cursor blinks. */
152  void setBlinkingCursor(bool blink);
153  void setBlinkingCursorState(bool blink);
154 
155  void setCtrlDrag(bool enable) { _ctrlDrag=enable; }
156  bool ctrlDrag() { return _ctrlDrag; }
157 
158  /**
159  * This enum describes the methods for selecting text when
160  * the user triple-clicks within the display.
161  */
163  {
164  /** Select the whole line underneath the cursor. */
166  /** Select from the current cursor position to the end of the line. */
168  };
169  /** Sets how the text is selected when the user triple clicks within the display. */
171  /** See setTripleClickSelectionMode() */
173 
174  void setLineSpacing(uint);
175  uint lineSpacing() const;
176 
177  void emitSelection(bool useXselection,bool appendReturn);
178 
179  /**
180  * This enum describes the available shapes for the keyboard cursor.
181  * See setKeyboardCursorShape()
182  */
184  {
185  /** A rectangular block which covers the entire area of the cursor character. */
187  /**
188  * A single flat line which occupies the space at the bottom of the cursor
189  * character's area.
190  */
192  /**
193  * An cursor shaped like the capital letter 'I', similar to the IBeam
194  * cursor used in Qt/KDE text editors.
195  */
197  };
198  /**
199  * Sets the shape of the keyboard cursor. This is the cursor drawn
200  * at the position in the terminal where keyboard input will appear.
201  *
202  * In addition the terminal display widget also has a cursor for
203  * the mouse pointer, which can be set using the QWidget::setCursor()
204  * method.
205  *
206  * Defaults to BlockCursor
207  */
209  /**
210  * Returns the shape of the keyboard cursor. See setKeyboardCursorShape()
211  */
213 
214  /**
215  * Sets the color used to draw the keyboard cursor.
216  *
217  * The keyboard cursor defaults to using the foreground color of the character
218  * underneath it.
219  *
220  * @param useForegroundColor If true, the cursor color will change to match
221  * the foreground color of the character underneath it as it is moved, in this
222  * case, the @p color parameter is ignored and the color of the character
223  * under the cursor is inverted to ensure that it is still readable.
224  * @param color The color to use to draw the cursor. This is only taken into
225  * account if @p useForegroundColor is false.
226  */
227  void setKeyboardCursorColor(bool useForegroundColor , const QColor& color);
228 
229  /**
230  * Returns the color of the keyboard cursor, or an invalid color if the keyboard
231  * cursor color is set to change according to the foreground color of the character
232  * underneath it.
233  */
234  QColor keyboardCursorColor() const;
235 
236  /**
237  * Returns the number of lines of text which can be displayed in the widget.
238  *
239  * This will depend upon the height of the widget and the current font.
240  * See fontHeight()
241  */
242  int lines() { return _lines; }
243  /**
244  * Returns the number of characters of text which can be displayed on
245  * each line in the widget.
246  *
247  * This will depend upon the width of the widget and the current font.
248  * See fontWidth()
249  */
250  int columns() { return _columns; }
251 
252  /**
253  * Returns the height of the characters in the font used to draw the text in the display.
254  */
255  int fontHeight() { return _fontHeight; }
256  /**
257  * Returns the width of the characters in the display.
258  * This assumes the use of a fixed-width font.
259  */
260  int fontWidth() { return _fontWidth; }
261 
262  void setSize(int cols, int lins);
263  void setFixedSize(int cols, int lins);
264 
265  // reimplemented
266  QSize sizeHint() const;
267 
268  /**
269  * Sets which characters, in addition to letters and numbers,
270  * are regarded as being part of a word for the purposes
271  * of selecting words in the display by double clicking on them.
272  *
273  * The word boundaries occur at the first and last characters which
274  * are either a letter, number, or a character in @p wc
275  *
276  * @param wc An array of characters which are to be considered parts
277  * of a word ( in addition to letters and numbers ).
278  */
279  void setWordCharacters(const QString& wc);
280  /**
281  * Returns the characters which are considered part of a word for the
282  * purpose of selecting words in the display with the mouse.
283  *
284  * @see setWordCharacters()
285  */
286  QString wordCharacters() { return _wordCharacters; }
287 
288  /**
289  * Sets the type of effect used to alert the user when a 'bell' occurs in the
290  * terminal session.
291  *
292  * The terminal session can trigger the bell effect by calling bell() with
293  * the alert message.
294  */
295  void setBellMode(int mode);
296  /**
297  * Returns the type of effect used to alert the user when a 'bell' occurs in
298  * the terminal session.
299  *
300  * See setBellMode()
301  */
302  int bellMode() { return _bellMode; }
303 
304  /**
305  * This enum describes the different types of sounds and visual effects which
306  * can be used to alert the user when a 'bell' occurs in the terminal
307  * session.
308  */
309  enum BellMode
310  {
311  /** A system beep. */
313  /**
314  * KDE notification. This may play a sound, show a passive popup
315  * or perform some other action depending on the user's settings.
316  */
318  /** A silent, visual bell (eg. inverting the display's colors briefly) */
320  /** No bell effects */
322  };
323 
324  void setSelection(const QString &t);
325 
326  QString selectedText ();
327 
328  /**
329  * Reimplemented. Has no effect. Use setVTFont() to change the font
330  * used to draw characters in the display.
331  */
332  virtual void setFont(const QFont &);
333 
334 
335  /** Returns the font used to draw characters in the display */
336  QFont getVTFont() { return font(); }
337 
338  /**
339  * Sets the font used to draw the display. Has no effect if @p font
340  * is larger than the size of the display itself.
341  */
342  void setVTFont(const QFont& font);
343 
344 
345  /**
346  * Specified whether terminal widget should be at read-only mode
347  * Defaults to false.
348  */
349  void setReadOnly( bool readonly) { _readonly = readonly; }
350 
351  /**
352  * Specified whether anti-aliasing of text in the terminal display
353  * is enabled or not. Defaults to enabled.
354  */
355  static void setAntialias( bool antialias ) { _antialiasText = antialias; }
356  /**
357  * Returns true if anti-aliasing of text in the terminal is enabled.
358  */
359  static bool antialias() { return _antialiasText; }
360 
361  /**
362  * Sets whether or not the current height and width of the
363  * terminal in lines and columns is displayed whilst the widget
364  * is being resized.
365  */
367  /**
368  * Returns whether or not the current height and width of
369  * the terminal in lines and columns is displayed whilst the widget
370  * is being resized.
371  */
373  /**
374  * Sets whether the terminal size display is shown briefly
375  * after the widget is first shown.
376  *
377  * See setTerminalSizeHint() , isTerminalSizeHint()
378  */
380 
381  /**
382  * Sets the terminal screen section which is displayed in this widget.
383  * When updateImage() is called, the display fetches the latest character image from the
384  * the associated terminal screen window.
385  *
386  * In terms of the model-view paradigm, the ScreenWindow is the model which is rendered
387  * by the TerminalDisplay.
388  */
389  void setScreenWindow( ScreenWindow* window );
390  /** Returns the terminal screen section which is displayed in this widget. See setScreenWindow() */
391  ScreenWindow* screenWindow() const;
392 
393 public slots:
394 
395  /**
396  * Causes the terminal display to fetch the latest character image from the associated
397  * terminal screen ( see setScreenWindow() ) and redraw the display.
398  */
399  void updateImage();
400  /**
401  * Causes the terminal display to fetch the latest line status flags from the
402  * associated terminal screen ( see setScreenWindow() ).
403  */
404  void updateLineProperties();
405 
406  /** Copies the selected text to the clipboard. */
407  void copyClipboard();
408  /**
409  * Pastes the content of the clipboard into the
410  * display.
411  */
412  void pasteClipboard();
413  /**
414  * Pastes the content of the selection into the
415  * display.
416  */
417  void pasteSelection();
418 
419  /**
420  * Causes the widget to display or hide a message informing the user that terminal
421  * output has been suspended (by using the flow control key combination Ctrl+S)
422  *
423  * @param suspended True if terminal output has been suspended and the warning message should
424  * be shown or false to indicate that terminal output has been resumed and that
425  * the warning message should disappear.
426  */
427  void outputSuspended(bool suspended);
428 
429  /**
430  * Sets whether the program whoose output is being displayed in the view
431  * is interested in mouse events.
432  *
433  * If this is set to true, mouse signals will be emitted by the view when the user clicks, drags
434  * or otherwise moves the mouse inside the view.
435  * The user interaction needed to create selections will also change, and the user will be required
436  * to hold down the shift key to create a selection or perform other mouse activities inside the
437  * view area - since the program running in the terminal is being allowed to handle normal mouse
438  * events itself.
439  *
440  * @param usesMouse Set to true if the program running in the terminal is interested in mouse events
441  * or false otherwise.
442  */
443  void setUsesMouse(bool usesMouse);
444 
445  /** See setUsesMouse() */
446  bool usesMouse() const;
447 
448 signals:
449 
450  void interrupt_signal (void);
451 
452  /**
453  * Emitted when the user presses a key whilst the terminal widget has focus.
454  */
455  void keyPressedSignal(QKeyEvent *e);
456 
457  /**
458  * A mouse event occurred.
459  * @param button The mouse button (0 for left button, 1 for middle button, 2 for right button, 3 for release)
460  * @param column The character column where the event occurred
461  * @param line The character row where the event occurred
462  * @param eventType The type of event. 0 for a mouse press / release or 1 for mouse motion
463  */
464  void mouseSignal(int button, int column, int line, int eventType);
465  void changedFontMetricSignal(int height, int width);
466  void changedContentSizeSignal(int height, int width);
467 
468  /**
469  * Emitted when the user right clicks on the display, or right-clicks with the Shift
470  * key held down if usesMouse() is true.
471  *
472  * This can be used to display a context menu.
473  */
474  void configureRequest( TerminalView*, int state, const QPoint& position );
475 
476  void isBusySelecting(bool);
477  void sendStringToEmu(const char*);
478 
479  void tripleClicked( const QString& text );
480 
481  /**
482  * Emitted when focus changes
483  */
484  void set_global_shortcuts_signal (bool);
485 
486 
487 protected:
488  virtual bool event( QEvent * );
489 
490  virtual void paintEvent( QPaintEvent * );
491 
492  void focusInEvent(QFocusEvent *focusEvent);
493  void focusOutEvent(QFocusEvent *focusEvent);
494 
495  virtual void showEvent(QShowEvent*);
496  virtual void hideEvent(QHideEvent*);
497  virtual void resizeEvent(QResizeEvent*);
498 
499  virtual void fontChange(const QFont &font);
500 
501  virtual void keyPressEvent(QKeyEvent* event);
502  virtual void mouseDoubleClickEvent(QMouseEvent* ev);
503  virtual void mousePressEvent( QMouseEvent* );
504  virtual void mouseReleaseEvent( QMouseEvent* );
505  virtual void mouseMoveEvent( QMouseEvent* );
506  virtual void extendSelection( const QPoint& pos );
507  virtual void wheelEvent( QWheelEvent* );
508 
509  virtual bool focusNextPrevChild( bool next );
510 
511  // drag and drop
512  virtual void dragEnterEvent(QDragEnterEvent* event);
513  virtual void dropEvent(QDropEvent* event);
514  void doDrag();
516 
517  struct _dragInfo {
519  QPoint start;
520  QDrag *dragObject;
521  } dragInfo;
522 
523  virtual int charClass(quint16) const;
524 
525  void clearImage();
526 
527  void mouseTripleClickEvent(QMouseEvent* ev);
528 
529  // reimplemented
530  virtual void inputMethodEvent ( QInputMethodEvent* event );
531  virtual QVariant inputMethodQuery( Qt::InputMethodQuery query ) const;
532 
533 protected slots:
534 
535  void scrollBarPositionChanged(int value);
536  void blinkEvent();
537  void blinkCursorEvent();
538 
539  //Renables bell noises and visuals. Used to disable further bells for a short period of time
540  //after emitting the first in a sequence of bell events.
541  void enableBell();
542 
543 private slots:
544 
545  void swapColorTable();
546  void tripleClickTimeout(); // resets possibleTripleClick
547 
548 private:
549 
550  // -- Drawing helpers --
551 
552  // divides the part of the display specified by 'rect' into
553  // fragments according to their colors and styles and calls
554  // drawTextFragment() to draw the fragments
555  void drawContents(QPainter &paint, const QRect &rect);
556  // draws a section of text, all the text in this section
557  // has a common color and style
558  void drawTextFragment(QPainter& painter, const QRect& rect,
559  const QString& text, const Character* style);
560  // draws the background for a text fragment
561  // if useOpacitySetting is true then the color's alpha value will be set to
562  // the display's transparency (set with setOpacity()), otherwise the background
563  // will be drawn fully opaque
564  void drawBackground(QPainter& painter, const QRect& rect, const QColor& color);
565  // draws the cursor character
566  void drawCursor(QPainter& painter, const QRect& rect , const QColor& foregroundColor,
567  const QColor& backgroundColor , bool& invertColors);
568  // draws the characters or line graphics in a text fragment
569  void drawCharacters(QPainter& painter, const QRect& rect, const QString& text,
570  const Character* style, bool invertCharacterColor);
571  // draws a string of line graphics
572  void drawLineCharString(QPainter& painter, int x, int y,
573  const QString& str, const Character* attributes);
574 
575  // draws the preedit string for input methods
576  void drawInputMethodPreeditString(QPainter& painter , const QRect& rect);
577 
578  // --
579 
580  // maps an area in the character image to an area on the widget
581  QRect imageToWidget(const QRect& imageArea) const;
582 
583  // maps a point on the widget to the position ( ie. line and column )
584  // of the character at that point.
585  void getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const;
586 
587  // the area where the preedit string for input methods will be draw
588  QRect preeditRect() const;
589 
590  // shows a notification window in the middle of the widget indicating the terminal's
591  // current size in columns and lines
592  void showResizeNotification();
593 
594  // scrolls the image by a number of lines.
595  // 'lines' may be positive ( to scroll the image down )
596  // or negative ( to scroll the image up )
597  // 'region' is the part of the image to scroll - currently only
598  // the top, bottom and height of 'region' are taken into account,
599  // the left and right are ignored.
600  void scrollImage(int lines , const QRect& region);
601 
602  void calcGeometry();
603  void propagateSize();
604  void updateImageSize();
605  void makeImage();
606 
607  void paintFilters(QPainter& painter);
608 
609  // returns a region covering all of the areas of the widget which contain
610  // a hotspot
611  QRegion hotSpotRegion() const;
612 
613  // returns the position of the cursor in columns and lines
614  QPoint cursorPosition() const;
615 
616  // the window onto the terminal screen which this display
617  // is currently showing.
618  QPointer<ScreenWindow> _screenWindow;
619 
621 
622  QGridLayout* _gridLayout;
623 
624  bool _fixedFont; // has fixed pitch
625 
626  double _fontHeight; // height
627  double _fontWidth; // width
628  //type double to decrease rounding errors
629 
630  int _fontAscent; // ascend
631 
632  int _leftMargin; // offset
633  int _topMargin; // offset
634 
635  int _lines; // the number of lines that can be displayed in the widget
636  int _columns; // the number of columns that can be displayed in the widget
637 
638  int _usedLines; // the number of lines that are actually being used, this will be less
639  // than 'lines' if the character image provided with setImage() is smaller
640  // than the maximum image size which can be displayed
641 
642  int _usedColumns; // the number of columns that are actually being used, this will be less
643  // than 'columns' if the character image provided with setImage() is smaller
644  // than the maximum image size which can be displayed
645 
648  Character* _image; // [lines][columns]
649  // only the area [usedLines][usedColumns] in the image contains valid data
650 
652  QVector<LineProperty> _lineProperties;
653 
656 
657  bool _resizing;
661 
662  QPoint _iPntSel; // initial selection point
663  QPoint _pntSel; // current selection point
664  QPoint _tripleSelBegin; // help avoid flicker
665  int _actSel; // selection state
670 
671  QClipboard* _clipboard;
672  QScrollBar* _scrollBar;
676 
677  bool _blinking; // hide text in paintEvent
678  bool _hasBlinker; // has characters to blink
679  bool _cursorBlinking; // hide cursor in paintEvent
680  bool _hasBlinkingCursor; // has blinking cursor enabled
681  bool _ctrlDrag; // require Ctrl key for drag
683  bool _isFixedSize; //Columns / lines are locked.
684  QTimer* _blinkTimer; // active when hasBlinker
685  QTimer* _blinkCursorTimer; // active when hasBlinkingCursor
686 
687 // KMenu* _drop;
688  QString _dropText;
690 
691  bool _possibleTripleClick; // is set in mouseDoubleClickEvent and deleted
692  // after QApplication::doubleClickInterval() delay
693 
694 
695  QLabel* _resizeWidget;
696  QTimer* _resizeTimer;
697 
699 
700  //widgets related to the warning message that appears when the user presses Ctrl+S to suspend
701  //terminal output - informing them what has happened and how to resume output
703 
705 
706  bool _colorsInverted; // true during visual bell
707 
708  QSize _size;
709 
711 
712  // list of filters currently applied to the display. used for links and
713  // search highlight
716 
718 
719  // custom cursor color. if this is invalid then the foreground
720  // color of the character under the cursor is used
721  QColor _cursorColor;
722 
723 
725  {
726  QString preeditString;
728  };
730 
731  static bool _antialiasText; // do we antialias or not
732 
733  //the delay in milliseconds between redrawing blinking text
734  static const int BLINK_DELAY = 500;
735  static const int DEFAULT_LEFT_MARGIN = 2;
736  static const int DEFAULT_TOP_MARGIN = 2;
737 
738  bool _readonly;
739 };
740 
741 #endif // TERMINALVIEW_H