File indexing completed on 2024-04-28 11:45:49

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 &note) const;
0563 };
0564 
0565 #endif