2 Copyright 2007-2008 by Robert Knight <robertknight@gmail.com>
3 Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 #ifndef TERMINALDISPLAY_H
22 #define TERMINALDISPLAY_H
25 #include <QtGui/QColor>
26 #include <QtCore/QPointer>
27 #include <QtGui/QWidget>
31 #include "Character.h"
34 class QDragEnterEvent
;
53 extern unsigned short vt100_graphics
[32];
58 * A widget which displays output from a terminal emulation and sends input keypresses and mouse activity
61 * When the terminal emulation receives new output from the program running in the terminal,
62 * it will update the display by calling updateImage().
64 * TODO More documentation
66 class TerminalDisplay
: public QWidget
71 /** Constructs a new terminal display widget with the specified parent. */
72 TerminalDisplay(QWidget
*parent
=0);
73 virtual ~TerminalDisplay();
75 /** Returns the terminal color palette used by the display. */
76 const ColorEntry
* colorTable() const;
77 /** Sets the terminal color palette used by the display. */
78 void setColorTable(const ColorEntry table
[]);
80 * Sets the seed used to generate random colors for the display
81 * (in color schemes that support them).
83 void setRandomSeed(uint seed
);
85 * Returns the seed used to generate random colors for the display
86 * (in color schemes that support them).
88 uint
randomSeed() const;
90 /** Sets the opacity of the terminal display. */
91 void setOpacity(qreal opacity
);
94 * This enum describes the location where the scroll bar is positioned in the display widget.
96 enum ScrollBarPosition
98 /** Do not show the scroll bar. */
100 /** Show the scroll bar on the left side of the display. */
102 /** Show the scroll bar on the right side of the display. */
106 * Specifies whether the terminal display has a vertical scroll bar, and if so whether it
107 * is shown on the left or right side of the display.
109 void setScrollBarPosition(ScrollBarPosition position
);
112 * Sets the current position and range of the display's scroll bar.
114 * @param cursor The position of the scroll bar's thumb.
115 * @param lines The maximum value of the scroll bar.
117 void setScroll(int cursor
, int lines
);
120 * Returns the display's filter chain. When the image for the display is updated,
121 * the text is passed through each filter in the chain. Each filter can define
122 * hotspots which correspond to certain strings (such as URLs or particular words).
123 * Depending on the type of the hotspots created by the filter ( returned by Filter::Hotspot::type() )
124 * the view will draw visual cues such as underlines on mouse-over for links or translucent
125 * rectangles for markers.
127 * To add a new filter to the view, call:
128 * viewWidget->filterChain()->addFilter( filterObject );
130 FilterChain
* filterChain() const;
133 * Updates the filters in the display's filter chain. This will cause
134 * the hotspots to be updated to match the current image.
136 * WARNING: This function can be expensive depending on the
137 * image size and number of filters in the filterChain()
139 * TODO - This API does not really allow efficient usage. Revise it so
140 * that the processing can be done in a better way.
143 * - Area of interest may be known ( eg. mouse cursor hovering
146 void processFilters();
149 * Returns a list of menu actions created by the filters for the content
150 * at the given @p position.
152 QList
<QAction
*> filterActions(const QPoint
& position
);
154 /** Returns true if the cursor is set to blink or false otherwise. */
155 bool blinkingCursor() { return _hasBlinkingCursor
; }
156 /** Specifies whether or not the cursor blinks. */
157 void setBlinkingCursor(bool blink
);
159 void setCtrlDrag(bool enable
) { _ctrlDrag
=enable
; }
160 bool ctrlDrag() { return _ctrlDrag
; }
163 * This enum describes the methods for selecting text when
164 * the user triple-clicks within the display.
168 /** Select the whole line underneath the cursor. */
170 /** Select from the current cursor position to the end of the line. */
171 SelectForwardsFromCursor
173 /** Sets how the text is selected when the user triple clicks within the display. */
174 void setTripleClickMode(TripleClickMode mode
) { _tripleClickMode
= mode
; }
175 /** See setTripleClickSelectionMode() */
176 TripleClickMode
tripleClickMode() { return _tripleClickMode
; }
178 void setLineSpacing(uint
);
179 uint
lineSpacing() const;
181 void emitSelection(bool useXselection
,bool appendReturn
);
184 * This enum describes the available shapes for the keyboard cursor.
185 * See setKeyboardCursorShape()
187 enum KeyboardCursorShape
189 /** A rectangular block which covers the entire area of the cursor character. */
192 * A single flat line which occupies the space at the bottom of the cursor
197 * An cursor shaped like the capital letter 'I', similar to the IBeam
198 * cursor used in Qt/KDE text editors.
203 * Sets the shape of the keyboard cursor. This is the cursor drawn
204 * at the position in the terminal where keyboard input will appear.
206 * In addition the terminal display widget also has a cursor for
207 * the mouse pointer, which can be set using the QWidget::setCursor()
210 * Defaults to BlockCursor
212 void setKeyboardCursorShape(KeyboardCursorShape shape
);
214 * Returns the shape of the keyboard cursor. See setKeyboardCursorShape()
216 KeyboardCursorShape
keyboardCursorShape() const;
219 * Sets the color used to draw the keyboard cursor.
221 * The keyboard cursor defaults to using the foreground color of the character
224 * @param useForegroundColor If true, the cursor color will change to match
225 * the foreground color of the character underneath it as it is moved, in this
226 * case, the @p color parameter is ignored and the color of the character
227 * under the cursor is inverted to ensure that it is still readable.
228 * @param color The color to use to draw the cursor. This is only taken into
229 * account if @p useForegroundColor is false.
231 void setKeyboardCursorColor(bool useForegroundColor
, const QColor
& color
);
234 * Returns the color of the keyboard cursor, or an invalid color if the keyboard
235 * cursor color is set to change according to the foreground color of the character
238 QColor
keyboardCursorColor() const;
241 * Returns the number of lines of text which can be displayed in the widget.
243 * This will depend upon the height of the widget and the current font.
246 int lines() { return _lines
; }
248 * Returns the number of characters of text which can be displayed on
249 * each line in the widget.
251 * This will depend upon the width of the widget and the current font.
254 int columns() { return _columns
; }
257 * Returns the height of the characters in the font used to draw the text in the display.
259 int fontHeight() { return _fontHeight
; }
261 * Returns the width of the characters in the display.
262 * This assumes the use of a fixed-width font.
264 int fontWidth() { return _fontWidth
; }
266 void setSize(int cols
, int lins
);
267 void setFixedSize(int cols
, int lins
);
270 QSize
sizeHint() const;
273 * Sets which characters, in addition to letters and numbers,
274 * are regarded as being part of a word for the purposes
275 * of selecting words in the display by double clicking on them.
277 * The word boundaries occur at the first and last characters which
278 * are either a letter, number, or a character in @p wc
280 * @param wc An array of characters which are to be considered parts
281 * of a word ( in addition to letters and numbers ).
283 void setWordCharacters(const QString
& wc
);
285 * Returns the characters which are considered part of a word for the
286 * purpose of selecting words in the display with the mouse.
288 * @see setWordCharacters()
290 QString
wordCharacters() { return _wordCharacters
; }
293 * Sets the type of effect used to alert the user when a 'bell' occurs in the
296 * The terminal session can trigger the bell effect by calling bell() with
299 void setBellMode(int mode
);
301 * Returns the type of effect used to alert the user when a 'bell' occurs in
302 * the terminal session.
306 int bellMode() { return _bellMode
; }
309 * This enum describes the different types of sounds and visual effects which
310 * can be used to alert the user when a 'bell' occurs in the terminal
315 /** A system beep. */
318 * KDE notification. This may play a sound, show a passive popup
319 * or perform some other action depending on the user's settings.
322 /** A silent, visual bell (eg. inverting the display's colors briefly) */
324 /** No bell effects */
328 void setSelection(const QString
&t
);
331 * Reimplemented. Has no effect. Use setVTFont() to change the font
332 * used to draw characters in the display.
334 virtual void setFont(const QFont
&);
336 /** Returns the font used to draw characters in the display */
337 QFont
getVTFont() { return font(); }
340 * Sets the font used to draw the display. Has no effect if @p font
341 * is larger than the size of the display itself.
343 void setVTFont(const QFont
& font
);
346 * Specified whether anti-aliasing of text in the terminal display
347 * is enabled or not. Defaults to enabled.
349 static void setAntialias( bool antialias
) { _antialiasText
= antialias
; }
351 * Returns true if anti-aliasing of text in the terminal is enabled.
353 static bool antialias() { return _antialiasText
; }
356 * Sets whether or not the current height and width of the
357 * terminal in lines and columns is displayed whilst the widget
360 void setTerminalSizeHint(bool on
) { _terminalSizeHint
=on
; }
362 * Returns whether or not the current height and width of
363 * the terminal in lines and columns is displayed whilst the widget
366 bool terminalSizeHint() { return _terminalSizeHint
; }
368 * Sets whether the terminal size display is shown briefly
369 * after the widget is first shown.
371 * See setTerminalSizeHint() , isTerminalSizeHint()
373 void setTerminalSizeStartup(bool on
) { _terminalSizeStartup
=on
; }
376 * Sets the status of the BiDi rendering inside the terminal display.
377 * Defaults to disabled.
379 void setBidiEnabled(bool set
) { _bidiEnabled
=set
; }
381 * Returns the status of the BiDi rendering in this widget.
383 bool isBidiEnabled() { return _bidiEnabled
; }
386 * Sets the terminal screen section which is displayed in this widget.
387 * When updateImage() is called, the display fetches the latest character image from the
388 * the associated terminal screen window.
390 * In terms of the model-view paradigm, the ScreenWindow is the model which is rendered
391 * by the TerminalDisplay.
393 void setScreenWindow( ScreenWindow
* window
);
394 /** Returns the terminal screen section which is displayed in this widget. See setScreenWindow() */
395 ScreenWindow
* screenWindow() const;
397 static bool HAVE_TRANSPARENCY
;
402 * Causes the terminal display to fetch the latest character image from the associated
403 * terminal screen ( see setScreenWindow() ) and redraw the display.
407 * Causes the terminal display to fetch the latest line status flags from the
408 * associated terminal screen ( see setScreenWindow() ).
410 void updateLineProperties();
412 /** Copies the selected text to the clipboard. */
413 void copyClipboard();
415 * Pastes the content of the clipboard into the
418 void pasteClipboard();
420 * Pastes the content of the selection into the
423 void pasteSelection();
426 * Changes whether the flow control warning box should be shown when the flow control
427 * stop key (Ctrl+S) are pressed.
429 void setFlowControlWarningEnabled(bool enabled
);
431 * Returns true if the flow control warning box is enabled.
432 * See outputSuspended() and setFlowControlWarningEnabled()
434 bool flowControlWarningEnabled() const
435 { return _flowControlWarningEnabled
; }
438 * Causes the widget to display or hide a message informing the user that terminal
439 * output has been suspended (by using the flow control key combination Ctrl+S)
441 * @param suspended True if terminal output has been suspended and the warning message should
442 * be shown or false to indicate that terminal output has been resumed and that
443 * the warning message should disappear.
445 void outputSuspended(bool suspended
);
448 * Sets whether the program whoose output is being displayed in the view
449 * is interested in mouse events.
451 * If this is set to true, mouse signals will be emitted by the view when the user clicks, drags
452 * or otherwise moves the mouse inside the view.
453 * The user interaction needed to create selections will also change, and the user will be required
454 * to hold down the shift key to create a selection or perform other mouse activities inside the
455 * view area - since the program running in the terminal is being allowed to handle normal mouse
458 * @param usesMouse Set to true if the program running in the terminal is interested in mouse events
459 * or false otherwise.
461 void setUsesMouse(bool usesMouse
);
463 /** See setUsesMouse() */
464 bool usesMouse() const;
467 * Shows a notification that a bell event has occurred in the terminal.
468 * TODO: More documentation here
470 void bell(const QString
& message
);
473 * Sets the background of the display to the specified color.
474 * @see setColorTable(), setForegroundColor()
476 void setBackgroundColor(const QColor
& color
);
479 * Sets the text of the display to the specified color.
480 * @see setColorTable(), setBackgroundColor()
482 void setForegroundColor(const QColor
& color
);
487 * Emitted when the user presses a key whilst the terminal widget has focus.
489 void keyPressedSignal(QKeyEvent
*e
);
492 * A mouse event occurred.
493 * @param button The mouse button (0 for left button, 1 for middle button, 2 for right button, 3 for release)
494 * @param column The character column where the event occurred
495 * @param line The character row where the event occurred
496 * @param eventType The type of event. 0 for a mouse press / release or 1 for mouse motion
498 void mouseSignal(int button
, int column
, int line
, int eventType
);
499 void changedFontMetricSignal(int height
, int width
);
500 void changedContentSizeSignal(int height
, int width
);
503 * Emitted when the user right clicks on the display, or right-clicks with the Shift
504 * key held down if usesMouse() is true.
506 * This can be used to display a context menu.
508 void configureRequest(const QPoint
& position
);
511 * When a shortcut which is also a valid terminal key sequence is pressed while
512 * the terminal widget has focus, this signal is emitted to allow the host to decide
513 * whether the shortcut should be overridden.
514 * When the shortcut is overridden, the key sequence will be sent to the terminal emulation instead
515 * and the action associated with the shortcut will not be triggered.
517 * @p override is set to false by default and the shortcut will be triggered as normal.
519 void overrideShortcutCheck(QKeyEvent
* keyEvent
,bool& override
);
521 void isBusySelecting(bool);
522 void sendStringToEmu(const char*);
525 virtual bool event( QEvent
* );
527 virtual void paintEvent( QPaintEvent
* );
529 virtual void showEvent(QShowEvent
*);
530 virtual void hideEvent(QHideEvent
*);
531 virtual void resizeEvent(QResizeEvent
*);
533 virtual void fontChange(const QFont
&font
);
534 virtual void focusInEvent(QFocusEvent
* event
);
535 virtual void focusOutEvent(QFocusEvent
* event
);
536 virtual void keyPressEvent(QKeyEvent
* event
);
537 virtual void mouseDoubleClickEvent(QMouseEvent
* ev
);
538 virtual void mousePressEvent( QMouseEvent
* );
539 virtual void mouseReleaseEvent( QMouseEvent
* );
540 virtual void mouseMoveEvent( QMouseEvent
* );
541 virtual void extendSelection( const QPoint
& pos
);
542 virtual void wheelEvent( QWheelEvent
* );
544 virtual bool focusNextPrevChild( bool next
);
547 virtual void dragEnterEvent(QDragEnterEvent
* event
);
548 virtual void dropEvent(QDropEvent
* event
);
550 enum DragState
{ diNone
, diPending
, diDragging
};
558 // classifies the 'ch' into one of three categories
559 // and returns a character to indicate which category it is in
561 // - A space (returns ' ')
562 // - Part of a word (returns 'a')
563 // - Other characters (returns the input character)
564 QChar
charClass(QChar ch
) const;
568 void mouseTripleClickEvent(QMouseEvent
* ev
);
571 virtual void inputMethodEvent ( QInputMethodEvent
* event
);
572 virtual QVariant
inputMethodQuery( Qt::InputMethodQuery query
) const;
576 void scrollBarPositionChanged(int value
);
578 void blinkCursorEvent();
580 //Renables bell noises and visuals. Used to disable further bells for a short period of time
581 //after emitting the first in a sequence of bell events.
586 void swapColorTable();
587 void tripleClickTimeout(); // resets possibleTripleClick
591 // -- Drawing helpers --
593 // divides the part of the display specified by 'rect' into
594 // fragments according to their colors and styles and calls
595 // drawTextFragment() to draw the fragments
596 void drawContents(QPainter
&paint
, const QRect
&rect
);
597 // draws a section of text, all the text in this section
598 // has a common color and style
599 void drawTextFragment(QPainter
& painter
, const QRect
& rect
,
600 const QString
& text
, const Character
* style
);
601 // draws the background for a text fragment
602 // if useOpacitySetting is true then the color's alpha value will be set to
603 // the display's transparency (set with setOpacity()), otherwise the background
604 // will be drawn fully opaque
605 void drawBackground(QPainter
& painter
, const QRect
& rect
, const QColor
& color
,
606 bool useOpacitySetting
);
607 // draws the cursor character
608 void drawCursor(QPainter
& painter
, const QRect
& rect
, const QColor
& foregroundColor
,
609 const QColor
& backgroundColor
, bool& invertColors
);
610 // draws the characters or line graphics in a text fragment
611 void drawCharacters(QPainter
& painter
, const QRect
& rect
, const QString
& text
,
612 const Character
* style
, bool invertCharacterColor
);
613 // draws a string of line graphics
614 void drawLineCharString(QPainter
& painter
, int x
, int y
,
615 const QString
& str
, const Character
* attributes
);
617 // draws the preedit string for input methods
618 void drawInputMethodPreeditString(QPainter
& painter
, const QRect
& rect
);
622 // maps an area in the character image to an area on the widget
623 QRect
imageToWidget(const QRect
& imageArea
) const;
625 // maps a point on the widget to the position ( ie. line and column )
626 // of the character at that point.
627 void getCharacterPosition(const QPoint
& widgetPoint
,int& line
,int& column
) const;
629 // the area where the preedit string for input methods will be draw
630 QRect
preeditRect() const;
632 // shows a notification window in the middle of the widget indicating the terminal's
633 // current size in columns and lines
634 void showResizeNotification();
636 // scrolls the image by a number of lines.
637 // 'lines' may be positive ( to scroll the image down )
638 // or negative ( to scroll the image up )
639 // 'region' is the part of the image to scroll - currently only
640 // the top, bottom and height of 'region' are taken into account,
641 // the left and right are ignored.
642 void scrollImage(int lines
, const QRect
& region
);
645 void propagateSize();
646 void updateImageSize();
649 void paintFilters(QPainter
& painter
);
651 // returns a region covering all of the areas of the widget which contain
653 QRegion
hotSpotRegion() const;
655 // returns the position of the cursor in columns and lines
656 QPoint
cursorPosition() const;
658 // redraws the cursor
661 bool handleShortcutOverrideEvent(QKeyEvent
* event
);
663 // the window onto the terminal screen which this display
664 // is currently showing.
665 QPointer
<ScreenWindow
> _screenWindow
;
669 QGridLayout
* _gridLayout
;
671 bool _fixedFont
; // has fixed pitch
672 int _fontHeight
; // height
673 int _fontWidth
; // width
674 int _fontAscent
; // ascend
676 int _leftMargin
; // offset
677 int _topMargin
; // offset
679 int _lines
; // the number of lines that can be displayed in the widget
680 int _columns
; // the number of columns that can be displayed in the widget
682 int _usedLines
; // the number of lines that are actually being used, this will be less
683 // than 'lines' if the character image provided with setImage() is smaller
684 // than the maximum image size which can be displayed
686 int _usedColumns
; // the number of columns that are actually being used, this will be less
687 // than 'columns' if the character image provided with setImage() is smaller
688 // than the maximum image size which can be displayed
692 Character
* _image
; // [lines][columns]
693 // only the area [usedLines][usedColumns] in the image contains valid data
696 QVector
<LineProperty
> _lineProperties
;
698 ColorEntry _colorTable
[TABLE_COLORS
];
702 bool _terminalSizeHint
;
703 bool _terminalSizeStartup
;
707 QPoint _iPntSel
; // initial selection point
708 QPoint _pntSel
; // current selection point
709 QPoint _tripleSelBegin
; // help avoid flicker
710 int _actSel
; // selection state
711 bool _wordSelectionMode
;
712 bool _lineSelectionMode
;
713 bool _preserveLineBreaks
;
714 bool _columnSelectionMode
;
716 QClipboard
* _clipboard
;
717 QScrollBar
* _scrollBar
;
718 ScrollBarPosition _scrollbarLocation
;
719 QString _wordCharacters
;
722 bool _blinking
; // hide text in paintEvent
723 bool _hasBlinker
; // has characters to blink
724 bool _cursorBlinking
; // hide cursor in paintEvent
725 bool _hasBlinkingCursor
; // has blinking cursor enabled
726 bool _ctrlDrag
; // require Ctrl key for drag
727 TripleClickMode _tripleClickMode
;
728 bool _isFixedSize
; //Columns / lines are locked.
729 QTimer
* _blinkTimer
; // active when hasBlinker
730 QTimer
* _blinkCursorTimer
; // active when hasBlinkingCursor
736 bool _possibleTripleClick
; // is set in mouseDoubleClickEvent and deleted
737 // after QApplication::doubleClickInterval() delay
740 QLabel
* _resizeWidget
;
741 QTimer
* _resizeTimer
;
743 bool _flowControlWarningEnabled
;
745 //widgets related to the warning message that appears when the user presses Ctrl+S to suspend
746 //terminal output - informing them what has happened and how to resume output
747 QLabel
* _outputSuspendedLabel
;
751 bool _colorsInverted
; // true during visual bell
757 // list of filters currently applied to the display. used for links and
759 TerminalImageFilterChain
* _filterChain
;
760 QRegion _mouseOverHotspotArea
;
762 KeyboardCursorShape _cursorShape
;
764 // custom cursor color. if this is invalid then the foreground
765 // color of the character under the cursor is used
769 struct InputMethodData
771 QString preeditString
;
772 QRect previousPreeditRect
;
774 InputMethodData _inputMethodData
;
776 static bool _antialiasText
; // do we antialias or not
778 //the delay in milliseconds between redrawing blinking text
779 static const int BLINK_DELAY
= 500;
780 static const int DEFAULT_LEFT_MARGIN
= 1;
781 static const int DEFAULT_TOP_MARGIN
= 1;
784 static void setTransparencyEnabled(bool enable
)
786 HAVE_TRANSPARENCY
= enable
;
790 class AutoScrollHandler
: public QObject
795 AutoScrollHandler(QWidget
* parent
);
797 virtual void timerEvent(QTimerEvent
* event
);
798 virtual bool eventFilter(QObject
* watched
,QEvent
* event
);
800 QWidget
* widget() const { return static_cast<QWidget
*>(parent()); }
806 #endif // TERMINALDISPLAY_H