File indexing completed on 2024-04-14 03:55:39
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2002 John Firebaugh <jfirebaugh@kde.org> 0004 SPDX-FileCopyrightText: 2001 Anders Lund <anders@alweb.dk> 0005 SPDX-FileCopyrightText: 2001 Christoph Cullmann <cullmann@kde.org> 0006 SPDX-FileCopyrightText: 2017-2018 Friedrich W. H. Kossebau <kossebau@kde.org> 0007 0008 SPDX-License-Identifier: LGPL-2.0-only 0009 */ 0010 0011 #ifndef KATE_VIEW_HELPERS_H 0012 #define KATE_VIEW_HELPERS_H 0013 0014 #include <KActionMenu> 0015 #include <KLineEdit> 0016 #include <KSelectAction> 0017 0018 #include <QColor> 0019 #include <QHash> 0020 #include <QLayout> 0021 #include <QPixmap> 0022 #include <QPointer> 0023 #include <QScrollBar> 0024 #include <QTimer> 0025 0026 #include "katetextline.h" 0027 #include <ktexteditor/cursor.h> 0028 #include <ktexteditor/message.h> 0029 0030 namespace KTextEditor 0031 { 0032 class ViewPrivate; 0033 class DocumentPrivate; 0034 class Command; 0035 class AnnotationModel; 0036 class MovingRange; 0037 class AbstractAnnotationItemDelegate; 0038 class StyleOptionAnnotationItem; 0039 } 0040 0041 class KateViewInternal; 0042 class KateTextLayout; 0043 0044 #define MAXFOLDINGCOLORS 16 0045 0046 class KateLineInfo; 0047 class KateTextPreview; 0048 0049 namespace Kate 0050 { 0051 class TextRange; 0052 } 0053 0054 class QTimer; 0055 class QVBoxLayout; 0056 class QStackedWidget; 0057 0058 /** 0059 * Class to layout KTextEditor::Message%s in KateView. Only the floating 0060 * positions TopInView, CenterInView, and BottomInView are supported. 0061 * AboveView and BelowView are not supported and ASSERT. 0062 */ 0063 class KateMessageLayout : public QLayout 0064 { 0065 public: 0066 explicit KateMessageLayout(QWidget *parent); 0067 ~KateMessageLayout() override; 0068 0069 void addWidget(QWidget *widget, KTextEditor::Message::MessagePosition pos); 0070 int count() const override; 0071 QLayoutItem *itemAt(int index) const override; 0072 void setGeometry(const QRect &rect) override; 0073 QSize sizeHint() const override; 0074 QLayoutItem *takeAt(int index) override; 0075 0076 void add(QLayoutItem *item, KTextEditor::Message::MessagePosition pos); 0077 0078 private: 0079 void addItem(QLayoutItem *item) override; // never called publically 0080 0081 struct ItemWrapper { 0082 ItemWrapper() = default; 0083 ItemWrapper(QLayoutItem *i, KTextEditor::Message::MessagePosition pos) 0084 : item(i) 0085 , position(pos) 0086 { 0087 } 0088 0089 QLayoutItem *item = nullptr; 0090 KTextEditor::Message::MessagePosition position = KTextEditor::Message::AboveView; 0091 }; 0092 0093 QList<ItemWrapper> m_items; 0094 }; 0095 0096 /** 0097 * This class is required because QScrollBar's sliderMoved() signal is 0098 * really supposed to be a sliderDragged() signal... so this way we can capture 0099 * MMB slider moves as well 0100 * 0101 * Also, it adds some useful indicators on the scrollbar. 0102 */ 0103 class KateScrollBar : public QScrollBar 0104 { 0105 Q_OBJECT 0106 0107 public: 0108 KateScrollBar(Qt::Orientation orientation, class KateViewInternal *parent); 0109 ~KateScrollBar() override; 0110 QSize sizeHint() const override; 0111 0112 void showEvent(QShowEvent *event) override; 0113 0114 inline bool showMarks() const 0115 { 0116 return m_showMarks; 0117 } 0118 inline void setShowMarks(bool b) 0119 { 0120 m_showMarks = b; 0121 update(); 0122 } 0123 0124 inline bool showMiniMap() const 0125 { 0126 return m_showMiniMap; 0127 } 0128 void setShowMiniMap(bool b); 0129 0130 inline bool miniMapAll() const 0131 { 0132 return m_miniMapAll; 0133 } 0134 inline void setMiniMapAll(bool b) 0135 { 0136 m_miniMapAll = b; 0137 updateGeometry(); 0138 update(); 0139 } 0140 0141 inline bool miniMapWidth() const 0142 { 0143 return m_miniMapWidth; 0144 } 0145 inline void setMiniMapWidth(int width) 0146 { 0147 m_miniMapWidth = width; 0148 updateGeometry(); 0149 update(); 0150 } 0151 0152 inline void queuePixmapUpdate() 0153 { 0154 m_updateTimer.start(); 0155 } 0156 0157 Q_SIGNALS: 0158 void sliderMMBMoved(int value); 0159 0160 protected: 0161 void mousePressEvent(QMouseEvent *e) override; 0162 void mouseReleaseEvent(QMouseEvent *e) override; 0163 void mouseMoveEvent(QMouseEvent *e) override; 0164 void leaveEvent(QEvent *event) override; 0165 bool eventFilter(QObject *object, QEvent *event) override; 0166 void paintEvent(QPaintEvent *e) override; 0167 void resizeEvent(QResizeEvent *) override; 0168 void sliderChange(SliderChange change) override; 0169 0170 protected Q_SLOTS: 0171 void sliderMaybeMoved(int value); 0172 void marksChanged(); 0173 0174 public Q_SLOTS: 0175 void updatePixmap(); 0176 0177 private Q_SLOTS: 0178 void showTextPreview(); 0179 0180 private: 0181 void showTextPreviewDelayed(); 0182 void hideTextPreview(); 0183 0184 void redrawMarks(); 0185 void recomputeMarksPositions(); 0186 0187 void miniMapPaintEvent(QPaintEvent *e); 0188 void normalPaintEvent(QPaintEvent *e); 0189 0190 int minimapYToStdY(int y); 0191 0192 struct ColumnRangeWithColor { 0193 int penIndex = -1; 0194 int startColumn; 0195 int endColumn; 0196 }; 0197 void getCharColorRanges(const QList<Kate::TextLine::Attribute> &attributes, 0198 const QList<Kate::TextRange *> &decorations, 0199 const QString &text, 0200 QList<KateScrollBar::ColumnRangeWithColor> &ranges, 0201 QVarLengthArray<std::pair<QRgb, QPen>, 20> &penCache); 0202 0203 bool m_middleMouseDown; 0204 bool m_leftMouseDown; 0205 0206 KTextEditor::ViewPrivate *m_view; 0207 KTextEditor::DocumentPrivate *m_doc; 0208 class KateViewInternal *m_viewInternal; 0209 QPointer<KateTextPreview> m_textPreview; 0210 QTimer m_delayTextPreviewTimer; 0211 0212 QHash<int, QColor> m_lines; 0213 0214 bool m_showMarks; 0215 bool m_showMiniMap; 0216 bool m_miniMapAll; 0217 bool m_needsUpdateOnShow; 0218 int m_miniMapWidth; 0219 0220 QPixmap m_pixmap; 0221 int m_grooveHeight; 0222 QRect m_stdGroveRect; 0223 QRect m_mapGroveRect; 0224 QRect m_sliderRect; 0225 QTimer m_updateTimer; 0226 QPoint m_toolTipPos; 0227 0228 // lists of lines added/removed recently to avoid scrollbar flickering 0229 QHash<int, int> m_linesAdded; 0230 0231 static const unsigned char characterOpacity[256]; 0232 }; 0233 0234 class KateIconBorder : public QWidget 0235 { 0236 Q_OBJECT 0237 0238 public: 0239 KateIconBorder(KateViewInternal *internalView, QWidget *parent); 0240 ~KateIconBorder() override; 0241 // VERY IMPORTANT ;) 0242 QSize sizeHint() const override; 0243 0244 void updateFont(); 0245 int lineNumberWidth() const; 0246 0247 void setIconBorderOn(bool enable); 0248 void setLineNumbersOn(bool enable); 0249 void setRelLineNumbersOn(bool enable); 0250 void setAnnotationBorderOn(bool enable); 0251 void setDynWrapIndicators(int state); 0252 int dynWrapIndicators() const 0253 { 0254 return m_dynWrapIndicators; 0255 } 0256 bool dynWrapIndicatorsOn() const 0257 { 0258 return m_dynWrapIndicatorsOn; 0259 } 0260 void setFoldingMarkersOn(bool enable); 0261 void toggleIconBorder() 0262 { 0263 setIconBorderOn(!iconBorderOn()); 0264 } 0265 void toggleLineNumbers() 0266 { 0267 setLineNumbersOn(!lineNumbersOn()); 0268 } 0269 void toggleFoldingMarkers() 0270 { 0271 setFoldingMarkersOn(!foldingMarkersOn()); 0272 } 0273 inline bool iconBorderOn() const 0274 { 0275 return m_iconBorderOn; 0276 } 0277 inline bool lineNumbersOn() const 0278 { 0279 return m_lineNumbersOn; 0280 } 0281 inline bool viRelNumbersOn() const 0282 { 0283 return m_relLineNumbersOn; 0284 } 0285 inline bool foldingMarkersOn() const 0286 { 0287 return m_foldingMarkersOn; 0288 } 0289 inline bool annotationBorderOn() const 0290 { 0291 return m_annotationBorderOn; 0292 } 0293 0294 void updateForCursorLineChange(); 0295 0296 enum BorderArea { None, LineNumbers, IconBorder, FoldingMarkers, AnnotationBorder, ModificationBorder }; 0297 BorderArea positionToArea(const QPoint &) const; 0298 0299 KTextEditor::AbstractAnnotationItemDelegate *annotationItemDelegate() const; 0300 void setAnnotationItemDelegate(KTextEditor::AbstractAnnotationItemDelegate *delegate); 0301 inline bool uniformAnnotationItemSizes() const 0302 { 0303 return m_hasUniformAnnotationItemSizes; 0304 } 0305 inline void setAnnotationUniformItemSizes(bool enable) 0306 { 0307 m_hasUniformAnnotationItemSizes = enable; 0308 } 0309 0310 public Q_SLOTS: 0311 void updateAnnotationBorderWidth(); 0312 void updateAnnotationLine(int line); 0313 void annotationModelChanged(KTextEditor::AnnotationModel *oldmodel, KTextEditor::AnnotationModel *newmodel); 0314 void displayRangeChanged(); 0315 0316 private: 0317 void dragEnterEvent(QDragEnterEvent *) override; 0318 void dragMoveEvent(QDragMoveEvent *event) override; 0319 void dropEvent(QDropEvent *event) override; 0320 void paintEvent(QPaintEvent *) override; 0321 void paintBorder(int x, int y, int width, int height); 0322 0323 void mousePressEvent(QMouseEvent *) override; 0324 void mouseMoveEvent(QMouseEvent *) override; 0325 void mouseReleaseEvent(QMouseEvent *) override; 0326 void mouseDoubleClickEvent(QMouseEvent *) override; 0327 void contextMenuEvent(QContextMenuEvent *e) override; 0328 void leaveEvent(QEvent *event) override; 0329 void wheelEvent(QWheelEvent *e) override; 0330 0331 void enterEvent(QEnterEvent *e) override; 0332 0333 void showMarkMenu(uint line, const QPoint &pos); 0334 0335 void hideAnnotationTooltip(); 0336 void removeAnnotationHovering(); 0337 void showAnnotationMenu(int line, const QPoint &pos); 0338 void calcAnnotationBorderWidth(); 0339 0340 void initStyleOption(KTextEditor::StyleOptionAnnotationItem *styleOption) const; 0341 void setStyleOptionLineData(KTextEditor::StyleOptionAnnotationItem *styleOption, 0342 int y, 0343 int realLine, 0344 const KTextEditor::AnnotationModel *model, 0345 const QString &annotationGroupIdentifier) const; 0346 QRect annotationLineRectInView(int line) const; 0347 0348 private: 0349 KTextEditor::ViewPrivate *m_view; 0350 KTextEditor::DocumentPrivate *m_doc; 0351 KateViewInternal *m_viewInternal; 0352 0353 bool m_iconBorderOn : 1; 0354 bool m_lineNumbersOn : 1; 0355 bool m_relLineNumbersOn : 1; 0356 bool m_updateRelLineNumbers : 1; 0357 bool m_foldingMarkersOn : 1; 0358 bool m_dynWrapIndicatorsOn : 1; 0359 bool m_annotationBorderOn : 1; 0360 bool m_updatePositionToArea : 1; 0361 bool m_mouseOver = false; 0362 0363 typedef QPair<int, KateIconBorder::BorderArea> AreaPosition; 0364 std::vector<AreaPosition> m_positionToArea; 0365 0366 const int m_separatorWidth = 2; 0367 const int m_modAreaWidth = 3; 0368 qreal m_maxCharWidth = 0.0; 0369 int m_lineNumberAreaWidth = 0; 0370 int m_iconAreaWidth = 0; 0371 int m_foldingAreaWidth = 0; 0372 int m_annotationAreaWidth = 0; 0373 const QChar m_dynWrapIndicatorChar = QChar(0x21AA); 0374 int m_dynWrapIndicators = 0; 0375 int m_lastClickedLine = -1; 0376 0377 KTextEditor::AbstractAnnotationItemDelegate *m_annotationItemDelegate; 0378 bool m_hasUniformAnnotationItemSizes = false; 0379 bool m_isDefaultAnnotationItemDelegate = true; 0380 0381 QPointer<KateTextPreview> m_foldingPreview; 0382 KTextEditor::MovingRange *m_foldingRange = nullptr; 0383 int m_currentLine = -1; 0384 QTimer m_antiFlickerTimer; 0385 void highlightFoldingDelayed(int line); 0386 void hideFolding(); 0387 0388 private Q_SLOTS: 0389 void highlightFolding(); 0390 void handleDestroyedAnnotationItemDelegate(); 0391 void delayedUpdateOfSizeWithRepaint(); 0392 0393 private: 0394 QString m_hoveredAnnotationGroupIdentifier; 0395 }; 0396 0397 class KateViewEncodingAction : public KSelectAction 0398 { 0399 public: 0400 KateViewEncodingAction(KTextEditor::DocumentPrivate *_doc, KTextEditor::ViewPrivate *_view, const QString &text, QObject *parent, bool saveAsMode = false); 0401 0402 bool setCurrentCodec(const QString &codec); 0403 0404 private: 0405 void init(); 0406 void subActionTriggered(QAction *); 0407 0408 KTextEditor::DocumentPrivate *doc; 0409 KTextEditor::ViewPrivate *view; 0410 QAction *currentSubAction; 0411 const bool m_saveAsMode; 0412 0413 private: 0414 void setEncoding(const QString &e); 0415 void slotAboutToShow(); 0416 }; 0417 0418 class KateViewBar; 0419 0420 class KateViewBarWidget : public QWidget 0421 { 0422 Q_OBJECT 0423 friend class KateViewBar; 0424 0425 public: 0426 explicit KateViewBarWidget(bool addCloseButton, QWidget *parent = nullptr); 0427 0428 virtual void closed() 0429 { 0430 } 0431 0432 /// returns the currently associated KateViewBar and 0, if it is not associated 0433 KateViewBar *viewBar() 0434 { 0435 return m_viewBar; 0436 } 0437 0438 protected: 0439 /** 0440 * @return widget that should be used to add controls to bar widget 0441 */ 0442 QWidget *centralWidget() 0443 { 0444 return m_centralWidget; 0445 } 0446 0447 /** 0448 * @return close button, if there 0449 */ 0450 QToolButton *closeButton() 0451 { 0452 return m_closeButton; 0453 } 0454 0455 Q_SIGNALS: 0456 void hideMe(); 0457 0458 // for friend class KateViewBar 0459 private: 0460 void setAssociatedViewBar(KateViewBar *bar) 0461 { 0462 m_viewBar = bar; 0463 } 0464 0465 private: 0466 QWidget *m_centralWidget = nullptr; 0467 KateViewBar *m_viewBar = nullptr; // 0-pointer, if not added to a view bar 0468 QToolButton *m_closeButton = nullptr; 0469 }; 0470 0471 class KateViewBar : public QWidget 0472 { 0473 Q_OBJECT 0474 0475 public: 0476 KateViewBar(bool external, QWidget *parent, KTextEditor::ViewPrivate *view); 0477 0478 /** 0479 * Adds a widget to this viewbar. 0480 * Widget is initially invisible, you should call showBarWidget, to show it. 0481 * Several widgets can be added to the bar, but only one can be visible 0482 */ 0483 void addBarWidget(KateViewBarWidget *newBarWidget); 0484 0485 /** 0486 * Removes a widget from this viewbar. 0487 * Removing a widget makes sense if it takes a lot of space vertically, 0488 * because we use a QStackedWidget to maintain the same height for all 0489 * widgets in the viewbar. 0490 */ 0491 void removeBarWidget(KateViewBarWidget *barWidget); 0492 0493 /** 0494 * @return if viewbar has widget @p barWidget 0495 */ 0496 bool hasBarWidget(KateViewBarWidget *barWidget) const; 0497 0498 /** 0499 * Shows barWidget that was previously added with addBarWidget. 0500 * @see hideCurrentBarWidget 0501 */ 0502 void showBarWidget(KateViewBarWidget *barWidget); 0503 0504 /** 0505 * Adds widget that will be always shown in the viewbar. 0506 * After adding permanent widget viewbar is immediately shown. 0507 * ViewBar with permanent widget won't hide itself 0508 * until permanent widget is removed. 0509 * OTOH showing/hiding regular barWidgets will work as usual 0510 * (they will be shown above permanent widget) 0511 * 0512 * If permanent widget already exists, asserts! 0513 */ 0514 void addPermanentBarWidget(KateViewBarWidget *barWidget); 0515 0516 /** 0517 * Removes permanent bar widget from viewbar. 0518 * If no other viewbar widgets are shown, viewbar gets hidden. 0519 * 0520 * barWidget is not deleted, caller must do it if it wishes 0521 */ 0522 void removePermanentBarWidget(KateViewBarWidget *barWidget); 0523 0524 /** 0525 * @return true if the a KateViewBar is visible*/ 0526 bool barWidgetVisible() const; 0527 0528 public Q_SLOTS: 0529 /** 0530 * Hides currently shown bar widget 0531 */ 0532 void hideCurrentBarWidget(); 0533 0534 protected: 0535 void keyPressEvent(QKeyEvent *event) override; 0536 void hideEvent(QHideEvent *event) override; 0537 0538 private: 0539 /** 0540 * Shows or hides whole viewbar 0541 */ 0542 void setViewBarVisible(bool visible); 0543 0544 bool m_external; 0545 0546 private: 0547 KTextEditor::ViewPrivate *m_view; 0548 QStackedWidget *m_stack; 0549 KateViewBarWidget *m_permanentBarWidget; 0550 QVBoxLayout *m_layout; 0551 }; 0552 0553 class KateCommandLineBar : public KateViewBarWidget 0554 { 0555 public: 0556 explicit KateCommandLineBar(KTextEditor::ViewPrivate *view, QWidget *parent = nullptr); 0557 ~KateCommandLineBar() override; 0558 0559 void setText(const QString &text, bool selected = true); 0560 void execute(const QString &text); 0561 0562 public: 0563 static void showHelpPage(); 0564 0565 private: 0566 class KateCmdLineEdit *m_lineEdit; 0567 }; 0568 0569 class KateCmdLineEdit : public KLineEdit 0570 { 0571 Q_OBJECT 0572 0573 public: 0574 KateCmdLineEdit(KateCommandLineBar *bar, KTextEditor::ViewPrivate *view); 0575 bool event(QEvent *e) override; 0576 0577 void hideEvent(QHideEvent *e) override; 0578 0579 Q_SIGNALS: 0580 void hideRequested(); 0581 0582 public Q_SLOTS: 0583 void slotReturnPressed(const QString &cmd); 0584 0585 private Q_SLOTS: 0586 void hideLineEdit(); 0587 0588 protected: 0589 void focusInEvent(QFocusEvent *ev) override; 0590 void keyPressEvent(QKeyEvent *ev) override; 0591 0592 private: 0593 /** 0594 * Parse an expression denoting a position in the document. 0595 * Return the position as an integer. 0596 * Examples of expressions are "10" (the 10th line), 0597 * "$" (the last line), "." (the current line), 0598 * "'a" (the mark 'a), "/foo/" (a forwards search for "foo"), 0599 * and "?bar?" (a backwards search for "bar"). 0600 * @param string the expression to parse 0601 * @return the position, an integer 0602 */ 0603 void fromHistory(bool up); 0604 QString helptext(const QPoint &) const; 0605 0606 KTextEditor::ViewPrivate *m_view; 0607 KateCommandLineBar *m_bar; 0608 bool m_msgMode; 0609 QString m_oldText; 0610 uint m_histpos; ///< position in the history 0611 uint m_cmdend; ///< the point where a command ends in the text, if we have a valid one. 0612 KTextEditor::Command *m_command; ///< For completing flags/args and interactiveness 0613 class KateCmdLnWhatsThis *m_help; 0614 0615 QTimer *m_hideTimer; 0616 }; 0617 0618 class KateViewSchemaAction : public KActionMenu 0619 { 0620 public: 0621 KateViewSchemaAction(const QString &text, QObject *parent) 0622 : KActionMenu(text, parent) 0623 { 0624 init(); 0625 setPopupMode(QToolButton::InstantPopup); 0626 } 0627 0628 void updateMenu(KTextEditor::ViewPrivate *view); 0629 0630 private: 0631 void init(); 0632 0633 QPointer<KTextEditor::ViewPrivate> m_view; 0634 QStringList names; 0635 QActionGroup *m_group; 0636 int last; 0637 0638 public: 0639 void slotAboutToShow(); 0640 0641 private: 0642 void setSchema(); 0643 }; 0644 0645 #endif