File indexing completed on 2024-04-28 15:31:09
0001 /* 0002 SPDX-FileCopyrightText: 2002-2007 Hamish Rodda <rodda@kde.org> 0003 SPDX-FileCopyrightText: 2002 John Firebaugh <jfirebaugh@kde.org> 0004 SPDX-FileCopyrightText: 2002 Joseph Wenninger <jowenn@kde.org> 0005 SPDX-FileCopyrightText: 2002 Christoph Cullmann <cullmann@kde.org> 0006 SPDX-FileCopyrightText: 2007 Mirko Stocker <me@misto.ch> 0007 0008 Based on KWriteView: 0009 SPDX-FileCopyrightText: 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de> 0010 0011 SPDX-License-Identifier: LGPL-2.0-or-later 0012 */ 0013 #ifndef _KATE_VIEW_INTERNAL_ 0014 #define _KATE_VIEW_INTERNAL_ 0015 0016 #include <ktexteditor/attribute.h> 0017 #include <ktexteditor/view.h> 0018 0019 #include "inlinenotedata.h" 0020 #include "katetextcursor.h" 0021 #include "katetextline.h" 0022 0023 #include <QDrag> 0024 #include <QElapsedTimer> 0025 #include <QPoint> 0026 #include <QPointer> 0027 #include <QSet> 0028 #include <QTime> 0029 #include <QTimer> 0030 #include <QWidget> 0031 0032 #include <array> 0033 #include <memory> 0034 0035 namespace KTextEditor 0036 { 0037 class MovingRange; 0038 class TextHintProvider; 0039 class DocumentPrivate; 0040 class ViewPrivate; 0041 } 0042 0043 class KateIconBorder; 0044 class KateScrollBar; 0045 class KateAnnotationItemDelegate; 0046 class KateAnnotationGroupPositionState; 0047 class KateTextLayout; 0048 class KateTextAnimation; 0049 class KateAbstractInputMode; 0050 class ZoomEventFilter; 0051 class KateRenderer; 0052 class KateTextPreview; 0053 class KateViewTest; 0054 0055 class QScrollBar; 0056 class QScroller; 0057 class QScrollEvent; 0058 class QScrollPrepareEvent; 0059 0060 class KTEXTEDITOR_EXPORT KateViewInternal final : public QWidget 0061 { 0062 Q_OBJECT 0063 0064 friend class KTextEditor::ViewPrivate; 0065 friend class KateIconBorder; 0066 friend class KateScrollBar; 0067 friend class KateAnnotationGroupPositionState; 0068 friend class CalculatingCursor; 0069 friend class BoundedCursor; 0070 friend class WrappingCursor; 0071 friend class CamelCursor; 0072 friend class KateAbstractInputMode; 0073 friend class ::KateTextPreview; 0074 friend class KateViewTest; 0075 0076 public: 0077 enum Bias { left = -1, none = 0, right = 1 }; 0078 0079 public: 0080 explicit KateViewInternal(KTextEditor::ViewPrivate *view); 0081 ~KateViewInternal() override; 0082 KTextEditor::ViewPrivate *view() const 0083 { 0084 return m_view; 0085 } 0086 0087 // BEGIN EDIT STUFF 0088 public: 0089 void editStart(); 0090 void editEnd(int editTagLineStart, int editTagLineEnd, bool tagFrom); 0091 0092 void editSetCursor(const KTextEditor::Cursor cursor); 0093 0094 private: 0095 uint editSessionNumber; 0096 bool editIsRunning; 0097 KTextEditor::Cursor editOldCursor; 0098 KTextEditor::Range editOldSelection; 0099 // END 0100 0101 // BEGIN TAG & CLEAR & UPDATE STUFF 0102 public: 0103 bool tagLine(const KTextEditor::Cursor virtualCursor); 0104 0105 bool tagLines(int start, int end, bool realLines = false); 0106 // cursors not const references as they are manipulated within 0107 bool tagLines(KTextEditor::Cursor start, KTextEditor::Cursor end, bool realCursors = false); 0108 0109 bool tagRange(KTextEditor::Range range, bool realCursors); 0110 0111 void tagAll(); 0112 0113 void updateDirty(); 0114 0115 void clear(); 0116 // END 0117 0118 private Q_SLOTS: 0119 // Updates the view and requests a redraw. 0120 void updateView(bool changed = false, int viewLinesScrolled = 0); 0121 0122 private: 0123 KTEXTEDITOR_NO_EXPORT 0124 void makeVisible(const KTextEditor::Cursor c, int endCol, bool force = false, bool center = false, bool calledExternally = false); 0125 0126 public: 0127 // Start Position is a virtual cursor 0128 KTextEditor::Cursor startPos() const 0129 { 0130 return m_startPos; 0131 } 0132 int startLine() const 0133 { 0134 return m_startPos.line(); 0135 } 0136 int startX() const 0137 { 0138 return m_startX; 0139 } 0140 0141 KTextEditor::Cursor endPos() const; 0142 int endLine() const; 0143 0144 KateTextLayout yToKateTextLayout(int y) const; 0145 0146 void dynWrapChanged(); 0147 0148 public Q_SLOTS: 0149 void slotIncFontSizes(qreal step = 1.0); 0150 void slotDecFontSizes(qreal step = 1.0); 0151 void slotResetFontSizes(); 0152 0153 void paintCursor(); 0154 0155 private Q_SLOTS: 0156 void scrollLines(int line); // connected to the sliderMoved of the m_lineScroll 0157 void scrollViewLines(int offset); 0158 void scrollAction(int action); 0159 void scrollNextPage(); 0160 void scrollPrevPage(); 0161 void scrollPrevLine(); 0162 void scrollNextLine(); 0163 void scrollColumns(int x); // connected to the valueChanged of the m_columnScroll 0164 void viewSelectionChanged(); 0165 0166 public: 0167 void cursorPrevChar(bool sel = false); 0168 void cursorNextChar(bool sel = false); 0169 void wordPrev(bool sel = false); 0170 void wordNext(bool sel = false); 0171 void home(bool sel = false); 0172 void end(bool sel = false); 0173 void cursorUp(bool sel = false); 0174 void cursorDown(bool sel = false); 0175 void cursorToMatchingBracket(bool sel = false); 0176 void scrollUp(); 0177 void scrollDown(); 0178 void topOfView(bool sel = false); 0179 void bottomOfView(bool sel = false); 0180 void pageUp(bool sel = false, bool half = false); 0181 void pageDown(bool sel = false, bool half = false); 0182 void top(bool sel = false); 0183 void bottom(bool sel = false); 0184 void top_home(bool sel = false); 0185 void bottom_end(bool sel = false); 0186 0187 private: 0188 // Takes as input @p c and applies the home command on it 0189 KTEXTEDITOR_NO_EXPORT 0190 KTextEditor::Cursor moveCursorToLineStart(KTextEditor::Cursor c); 0191 // Takes as input @p c and applies the end command on it 0192 KTEXTEDITOR_NO_EXPORT 0193 KTextEditor::Cursor moveCursorToLineEnd(KTextEditor::Cursor c); 0194 0195 public: 0196 /** 0197 * Accessor to the current caret position 0198 * @return position of the caret as @c KTextEditor::Cursor 0199 * @see KTextEditor::Cursor 0200 */ 0201 KTextEditor::Cursor cursorPosition() const 0202 { 0203 return m_cursor; 0204 } 0205 0206 /** 0207 * Accessor to the current mouse position 0208 * @return position of the mouse as @c KTextEditor::Cursor 0209 * @see KTextEditor::Cursor 0210 */ 0211 KTextEditor::Cursor mousePosition() const 0212 { 0213 return m_mouse; 0214 } 0215 0216 QPoint cursorToCoordinate(const KTextEditor::Cursor cursor, bool realCursor = true, bool includeBorder = true) const; 0217 // by default, works on coordinates of the whole widget, eg. offsetted by the border 0218 KTextEditor::Cursor coordinatesToCursor(const QPoint &coord, bool includeBorder = true) const; 0219 QPoint cursorCoordinates(bool includeBorder = true) const; 0220 KTextEditor::Cursor findMatchingBracket(); 0221 0222 KTextEditor::Range findMatchingFoldingMarker(const KTextEditor::Cursor current_cursor_pos, const int value, const int maxLines); 0223 void updateFoldingMarkersHighlighting(); 0224 0225 inline int getStartOffset(int direction, int offset, int length) const 0226 { 0227 return direction == 1 ? offset - length : offset; 0228 } 0229 0230 inline int getEndOffset(int direction, int offset, int length) const 0231 { 0232 return direction == 1 ? offset : offset + length; 0233 } 0234 0235 KateIconBorder *iconBorder() const 0236 { 0237 return m_leftBorder; 0238 } 0239 0240 // EVENT HANDLING STUFF - IMPORTANT 0241 private: 0242 KTEXTEDITOR_NO_EXPORT 0243 void fixDropEvent(QDropEvent *event); 0244 0245 KTEXTEDITOR_NO_EXPORT 0246 static bool isAcceptableInput(const QKeyEvent *e); 0247 0248 protected: 0249 void hideEvent(QHideEvent *e) override; 0250 void paintEvent(QPaintEvent *e) override; 0251 bool eventFilter(QObject *obj, QEvent *e) override; 0252 void keyPressEvent(QKeyEvent *) override; 0253 void keyReleaseEvent(QKeyEvent *) override; 0254 void resizeEvent(QResizeEvent *) override; 0255 void moveEvent(QMoveEvent *) override; 0256 void mousePressEvent(QMouseEvent *) override; 0257 void mouseDoubleClickEvent(QMouseEvent *) override; 0258 void mouseReleaseEvent(QMouseEvent *) override; 0259 void mouseMoveEvent(QMouseEvent *) override; 0260 void leaveEvent(QEvent *) override; 0261 void dragEnterEvent(QDragEnterEvent *) override; 0262 void dragMoveEvent(QDragMoveEvent *) override; 0263 void dropEvent(QDropEvent *) override; 0264 void showEvent(QShowEvent *) override; 0265 void wheelEvent(QWheelEvent *e) override; 0266 void scrollPrepareEvent(QScrollPrepareEvent *); 0267 void scrollEvent(QScrollEvent *); 0268 void focusInEvent(QFocusEvent *) override; 0269 void focusOutEvent(QFocusEvent *) override; 0270 void inputMethodEvent(QInputMethodEvent *e) override; 0271 0272 void contextMenuEvent(QContextMenuEvent *e) override; 0273 0274 private Q_SLOTS: 0275 void tripleClickTimeout(); 0276 0277 Q_SIGNALS: 0278 // emitted when KateViewInternal is not handling its own URI drops 0279 void dropEventPass(QDropEvent *); 0280 0281 private Q_SLOTS: 0282 void slotRegionVisibilityChanged(); 0283 void slotRegionBeginEndAddedRemoved(unsigned int); 0284 0285 private: 0286 KTEXTEDITOR_NO_EXPORT 0287 void moveChar(Bias bias, bool sel); 0288 KTEXTEDITOR_NO_EXPORT 0289 void moveEdge(Bias bias, bool sel); 0290 KTEXTEDITOR_NO_EXPORT 0291 KTextEditor::Cursor maxStartPos(bool changed = false); 0292 KTEXTEDITOR_NO_EXPORT 0293 void scrollPos(KTextEditor::Cursor &c, bool force = false, bool calledExternally = false, bool emitSignals = true); 0294 KTEXTEDITOR_NO_EXPORT 0295 void scrollLines(int lines, bool sel); 0296 0297 KTEXTEDITOR_NO_EXPORT 0298 KTextEditor::Attribute::Ptr attributeAt(const KTextEditor::Cursor position) const; 0299 KTEXTEDITOR_NO_EXPORT 0300 int linesDisplayed() const; 0301 0302 KTEXTEDITOR_NO_EXPORT 0303 int lineToY(int viewLine) const; 0304 0305 KTEXTEDITOR_NO_EXPORT 0306 void updateSecondarySelection(int cursorIdx, KTextEditor::Cursor old, KTextEditor::Cursor newPos); 0307 KTEXTEDITOR_NO_EXPORT 0308 void updateSelection(const KTextEditor::Cursor, bool keepSel); 0309 KTEXTEDITOR_NO_EXPORT 0310 void setSelection(KTextEditor::Range); 0311 KTEXTEDITOR_NO_EXPORT 0312 void moveCursorToSelectionEdge(bool scroll = true); 0313 KTEXTEDITOR_NO_EXPORT 0314 void updateCursor(const KTextEditor::Cursor newCursor, bool force = false, bool center = false, bool calledExternally = false, bool scroll = true); 0315 KTEXTEDITOR_NO_EXPORT 0316 void updateBracketMarks(); 0317 KTEXTEDITOR_NO_EXPORT 0318 void beginSelectLine(const QPoint &pos); 0319 0320 struct CursorPair { 0321 KTextEditor::Cursor oldPos; 0322 KTextEditor::Cursor newPos; 0323 }; 0324 // @brief updates the secondary cursor, schedules repaint 0325 // MUST setPosition of the corresponding moving cursors before calling this 0326 KTEXTEDITOR_NO_EXPORT 0327 void updateSecondaryCursors(const QVarLengthArray<CursorPair, 16> &cursors, bool sel); 0328 KTEXTEDITOR_NO_EXPORT 0329 void mergeSelections(); 0330 0331 KTEXTEDITOR_NO_EXPORT 0332 KTextEditor::Cursor cursorForPoint(QPoint p); 0333 KTEXTEDITOR_NO_EXPORT 0334 void placeCursor(const QPoint &p, bool keepSelection = false, bool updateSelection = true); 0335 KTEXTEDITOR_NO_EXPORT 0336 bool isTargetSelected(const QPoint &p); 0337 // Returns whether the given range affects the area currently visible in the view 0338 KTEXTEDITOR_NO_EXPORT 0339 bool rangeAffectsView(KTextEditor::Range range, bool realCursors) const; 0340 0341 KTEXTEDITOR_NO_EXPORT 0342 void doDrag(); 0343 0344 KTEXTEDITOR_NO_EXPORT 0345 KateRenderer *renderer() const; 0346 0347 KTEXTEDITOR_NO_EXPORT 0348 bool sendMouseEventToInputContext(QMouseEvent *e); 0349 KTEXTEDITOR_NO_EXPORT 0350 void commitPreedit(); 0351 0352 KTextEditor::ViewPrivate *m_view; 0353 class KateIconBorder *m_leftBorder; 0354 0355 int m_mouseX; 0356 int m_mouseY; 0357 int m_scrollX; 0358 int m_scrollY; 0359 0360 std::unique_ptr<ZoomEventFilter> m_zoomEventFilter; 0361 0362 Qt::CursorShape m_mouseCursor; 0363 0364 Kate::TextCursor m_cursor; 0365 KTextEditor::Cursor m_mouse; 0366 KTextEditor::Cursor m_displayCursor; 0367 0368 bool m_possibleTripleClick; 0369 0370 // Bracket mark and corresponding decorative ranges 0371 std::unique_ptr<KTextEditor::MovingRange> m_bm, m_bmStart, m_bmEnd; 0372 std::unique_ptr<KTextEditor::MovingCursor> m_bmLastFlashPos; 0373 std::unique_ptr<KateTextPreview> m_bmPreview; 0374 KTEXTEDITOR_NO_EXPORT 0375 void updateBracketMarkAttributes(); 0376 0377 // Folding mark 0378 std::unique_ptr<KTextEditor::MovingRange> m_fmStart, m_fmEnd; 0379 0380 enum DragState { diNone, diPending, diDragging }; 0381 0382 struct _dragInfo { 0383 DragState state; 0384 QPoint start; 0385 QDrag *dragObject; 0386 } m_dragInfo; 0387 0388 // 0389 // line scrollbar + first visible (virtual) line in the current view 0390 // 0391 KateScrollBar *m_lineScroll; 0392 qreal m_accumulatedScroll = 0.0; 0393 QWidget *m_dummy; 0394 0395 // These are now cursors to account for word-wrap. 0396 // Start Position is a virtual cursor 0397 Kate::TextCursor m_startPos; 0398 // Count of lines that are visible behind m_startPos. 0399 // This does not respect dynamic word wrap, so take it as an approximation. 0400 uint m_visibleLineCount; 0401 0402 // This is set to false on resize or scroll (other than that called by makeVisible), 0403 // so that makeVisible is again called when a key is pressed and the cursor is in the same spot 0404 bool m_madeVisible; 0405 bool m_shiftKeyPressed; 0406 0407 // How many lines to should be kept visible above/below the cursor when possible 0408 KTEXTEDITOR_NO_EXPORT 0409 void setAutoCenterLines(int viewLines, bool updateView = true); 0410 int m_autoCenterLines; 0411 int m_minLinesVisible; 0412 0413 // 0414 // column scrollbar + x position 0415 // 0416 QScrollBar *m_columnScroll; 0417 QScroller *m_scroller; 0418 int m_startX; 0419 0420 // has selection changed while your mouse or shift key is pressed 0421 bool m_selChangedByUser; 0422 KTextEditor::Cursor m_selectAnchor; 0423 0424 enum SelectionMode { Default = 0, Mouse, Word, Line }; ///< for drag selection. 0425 uint m_selectionMode; 0426 // when drag selecting after double/triple click, keep the initial selected 0427 // word/line independent of direction. 0428 // They get set in the event of a double click, and is used with mouse move + leftbutton 0429 KTextEditor::Range m_selectionCached; 0430 0431 // maximal length of textlines visible from given startLine 0432 KTEXTEDITOR_NO_EXPORT 0433 int maxLen(int startLine); 0434 0435 // are we allowed to scroll columns? 0436 KTEXTEDITOR_NO_EXPORT 0437 bool columnScrollingPossible(); 0438 0439 // the same for lines 0440 KTEXTEDITOR_NO_EXPORT 0441 bool lineScrollingPossible(); 0442 0443 // returns the maximum X value / col value a cursor can take for a specific line range 0444 KTEXTEDITOR_NO_EXPORT 0445 int lineMaxCursorX(const KateTextLayout &line); 0446 KTEXTEDITOR_NO_EXPORT 0447 static int lineMaxCol(const KateTextLayout &line); 0448 0449 KTEXTEDITOR_NO_EXPORT 0450 class KateLayoutCache *cache() const; 0451 KateLayoutCache *m_layoutCache; 0452 0453 // convenience methods 0454 0455 /// returns layout for the line c.line() 0456 KTEXTEDITOR_NO_EXPORT 0457 KateTextLayout currentLayout(KTextEditor::Cursor c) const; 0458 // returns layout for the line previous to @p c 0459 KTEXTEDITOR_NO_EXPORT 0460 KateTextLayout previousLayout(KTextEditor::Cursor c) const; 0461 // returns layout for the line next to @p c 0462 KTEXTEDITOR_NO_EXPORT 0463 KateTextLayout nextLayout(KTextEditor::Cursor c) const; 0464 0465 // find the cursor offset by (offset) view lines from a cursor. 0466 // when keepX is true, the column position will be calculated based on the x 0467 // position of the specified cursor. 0468 KTEXTEDITOR_NO_EXPORT 0469 KTextEditor::Cursor viewLineOffset(const KTextEditor::Cursor virtualCursor, int offset, bool keepX = false); 0470 0471 KTEXTEDITOR_NO_EXPORT 0472 KTextEditor::Cursor toRealCursor(const KTextEditor::Cursor virtualCursor) const; 0473 KTEXTEDITOR_NO_EXPORT 0474 KTextEditor::Cursor toVirtualCursor(const KTextEditor::Cursor realCursor) const; 0475 0476 // These variable holds the most recent maximum real & visible column number 0477 bool m_preserveX; 0478 int m_preservedX; 0479 0480 KTextEditor::Cursor m_cachedMaxStartPos; 0481 0482 // 0483 // implementation details for KTextEditor::FlashTextInterface 0484 // 0485 public: 0486 void flashChar(const KTextEditor::Cursor pos, KTextEditor::Attribute::Ptr attribute); 0487 void showBracketMatchPreview(); 0488 void hideBracketMatchPreview(); 0489 0490 private: 0491 QPointer<KateTextAnimation> m_textAnimation; 0492 0493 private Q_SLOTS: 0494 void doDragScroll(); 0495 void startDragScroll(); 0496 void stopDragScroll(); 0497 0498 private: 0499 // Timers 0500 QTimer m_dragScrollTimer; 0501 QTimer m_scrollTimer; 0502 QTimer m_cursorTimer; 0503 QTimer m_textHintTimer; 0504 0505 static const int s_scrollTime = 30; 0506 static const int s_scrollMargin = 16; 0507 0508 private Q_SLOTS: 0509 void scrollTimeout(); 0510 void cursorTimeout(); 0511 void textHintTimeout(); 0512 0513 void documentTextInserted(KTextEditor::Document *document, KTextEditor::Range range); 0514 void documentTextRemoved(KTextEditor::Document *document, KTextEditor::Range range, const QString &oldText); 0515 0516 // 0517 // KTE::TextHintInterface 0518 // 0519 public: 0520 void registerTextHintProvider(KTextEditor::TextHintProvider *provider); 0521 void unregisterTextHintProvider(KTextEditor::TextHintProvider *provider); 0522 void setTextHintDelay(int delay); 0523 int textHintDelay() const; 0524 bool textHintsEnabled(); // not part of the interface 0525 0526 private: 0527 std::vector<KTextEditor::TextHintProvider *> m_textHintProviders; 0528 int m_textHintDelay; 0529 QPoint m_textHintPos; 0530 0531 // 0532 // IM input stuff 0533 // 0534 public: 0535 QVariant inputMethodQuery(Qt::InputMethodQuery query) const override; 0536 0537 private: 0538 std::unique_ptr<KTextEditor::MovingRange> m_imPreeditRange; 0539 std::vector<std::unique_ptr<KTextEditor::MovingRange>> m_imPreeditRangeChildren; 0540 0541 private: 0542 KTEXTEDITOR_NO_EXPORT 0543 void mouseMoved(); 0544 KTEXTEDITOR_NO_EXPORT 0545 void cursorMoved(); 0546 0547 private: 0548 KTEXTEDITOR_NO_EXPORT 0549 KTextEditor::DocumentPrivate *doc(); 0550 KTEXTEDITOR_NO_EXPORT 0551 KTextEditor::DocumentPrivate *doc() const; 0552 0553 // input modes 0554 private: 0555 std::array<std::unique_ptr<KateAbstractInputMode>, KTextEditor::View::ViInputMode + 1> m_inputModes; 0556 KateAbstractInputMode *m_currentInputMode; 0557 0558 KateInlineNoteData m_activeInlineNote; 0559 KTEXTEDITOR_NO_EXPORT 0560 KateInlineNoteData inlineNoteAt(const QPoint &globalPos) const; 0561 KTEXTEDITOR_NO_EXPORT 0562 QRect inlineNoteRect(const KateInlineNoteData ¬e) const; 0563 }; 0564 0565 #endif