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