1 /************************************************************************ 2 ** 3 ** Copyright (C) 2015-2021 Kevin B. Hendricks Stratford, ON Canada 4 ** Copyright (C) 2009-2011 Strahinja Markovic <strahinja.markovic@gmail.com> 5 ** 6 ** This file is part of Sigil. 7 ** 8 ** Sigil is free software: you can redistribute it and/or modify 9 ** it under the terms of the GNU General Public License as published by 10 ** the Free Software Foundation, either version 3 of the License, or 11 ** (at your option) any later version. 12 ** 13 ** Sigil is distributed in the hope that it will be useful, 14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 ** GNU General Public License for more details. 17 ** 18 ** You should have received a copy of the GNU General Public License 19 ** along with Sigil. If not, see <http://www.gnu.org/licenses/>. 20 ** 21 *************************************************************************/ 22 23 #pragma once 24 #ifndef CODEVIEWEDITOR_H 25 #define CODEVIEWEDITOR_H 26 27 #include <QtCore/QList> 28 #include <QtCore/QStack> 29 #include <QtWidgets/QPlainTextEdit> 30 #include <QtGui/QStandardItem> 31 #include <QtCore/QUrl> 32 33 #include "Parsers/CSSInfo.h" 34 #include "Parsers/HTMLStyleInfo.h" 35 #include "Misc/PasteTarget.h" 36 #include "Misc/SettingsStore.h" 37 #include "Misc/Utility.h" 38 #include "Widgets/TextDocument.h" 39 #include "Parsers/TagLister.h" 40 #include "MiscEditors/ClipEditorModel.h" 41 #include "MiscEditors/IndexEditorModel.h" 42 #include "ViewEditors/ViewEditor.h" 43 44 class QResizeEvent; 45 class QSize; 46 class QWidget; 47 class QPrinter; 48 class QShortcut; 49 class LineNumberArea; 50 class QSyntaxHighlighter; 51 class QContextMenuEvent; 52 class QSignalMapper; 53 54 /** 55 * A text editor for source code. 56 * Also called the "Code View" because it shows 57 * the code of a section of the book. Provides syntax highlighting. 58 */ 59 class CodeViewEditor : public QPlainTextEdit, public ViewEditor, public PasteTarget 60 { 61 Q_OBJECT 62 63 public: 64 65 /** 66 * What type of syntax highlighting to use. 67 */ 68 enum HighlighterType { 69 Highlight_NONE, /**< No source code highlighting */ 70 Highlight_XHTML, /**< XHTML source code highlighting */ 71 Highlight_CSS /**< CSS source code highlighting */ 72 }; 73 74 /** 75 * Constructor. 76 * 77 * @param highlighter_type Which syntax highlighter to use. 78 * @param parent The object's parent. 79 */ 80 CodeViewEditor(HighlighterType highlighter_type, bool check_spelling = false, QWidget *parent = 0); 81 ~CodeViewEditor(); 82 83 void SetAppearance(); 84 85 QSize sizeHint() const; 86 87 /** 88 * A custom implementation of QPlainTextEdit::setDocument() 89 * since that doesn't do everything we want it to. 90 * 91 * @param document The new text document. 92 */ 93 void CustomSetDocument(TextDocument &document); 94 95 void DeleteLine(); 96 97 void HighlightMarkedText(); 98 99 bool MoveToMarkedText(Searchable::Direction direction, bool wrap); 100 101 /** 102 * Routines to handle cutting code tags from selected text 103 */ 104 void CutCodeTags(); 105 bool IsCutCodeTagsAllowed(); 106 107 void CutTagPair(); 108 bool IsCutTagPairAllowed(); 109 110 bool TextIsSelected(); 111 bool TextIsSelectedAndNotInStartOrEndTag(); 112 113 // No Longer Exists? 114 // bool TextIsSelectedAndNotContainingTag(); 115 116 QString StripCodeTags(QString text); 117 118 bool IsSelectionOK(); 119 120 void InsertClosingTag(); 121 bool IsInsertClosingTagAllowed(); 122 123 void GoToStyleDefinition(); 124 125 void AddMisspelledWord(); 126 void IgnoreMisspelledWord(); 127 128 void AddToIndex(); 129 bool IsAddToIndexAllowed(); 130 131 bool MarkForIndex(const QString &title); 132 133 bool IsInsertFileAllowed(); 134 135 bool InsertId(const QString &attribute_value); 136 bool InsertHyperlink(const QString &attribute_value); 137 bool IsInsertIdAllowed(); 138 bool IsInsertHyperlinkAllowed(); 139 bool InsertTagAttribute(const QString &element_name, const QString &attribute_name, 140 const QString &attribute_value, const QStringList &tag_list, 141 bool ignore_seletion = false); 142 143 /** 144 * Splits the section and returns the "upper" content. 145 * The current flow is split at the caret point. 146 * 147 * @return The content of the section up to the section break point. 148 * 149 * @note What we actually do when the user wants to split the loaded section 150 * is create a new tab with the XHTML content \em above the split point. 151 * The new tab is actually the "old" section, and this tab becomes the 152 * "new" section. 153 * \par 154 * Why? Because we can only avoid a tab render in the tab from which 155 * we remove elements. Since the users move from the top of a large HTML 156 * file down, the new section will be the one with the most content. 157 * So this way we \em try to avoid the painful render time on the biggest 158 * section, but there is still some render time left... 159 */ 160 QString SplitSection(); 161 162 /** 163 * Inserts the SGF section marker code at the current caret location. 164 */ 165 void InsertSGFSectionMarker(); 166 167 /** 168 * Paints the line number area. 169 * Receives the event directly from the area's paintEvent() handler. 170 * 171 * @param event The paint event to process. 172 */ 173 void LineNumberAreaPaintEvent(QPaintEvent *event); 174 175 /** 176 * Selects the line that was clicked on. 177 * Receives the event directly from the area's mouseEvent() handler. 178 * 179 * @param event The mouse event to process. 180 */ 181 void LineNumberAreaMouseEvent(QMouseEvent *event); 182 183 /** 184 * Returns the width the LinuNumberArea should take (in pixels). 185 * 186 * @return The width in pixels. 187 */ 188 int CalculateLineNumberAreaWidth(); 189 190 /** 191 * Replaces the text of the entire document with the new text. 192 * Records the replacement as one action for the undo stack. 193 * 194 * @param new_text The new text of the document. 195 */ 196 void ReplaceDocumentText(const QString &new_text); 197 198 /** 199 * Scrolls the entire view to the top. 200 */ 201 void ScrollToTop(); 202 203 void ScrollToPosition(int cursor_position, bool center_screen = true); 204 205 /** 206 * Scrolls the view to the specified line. 207 * 208 * @param line The line to scroll to. 209 */ 210 void ScrollToLine(int line); 211 212 void ScrollToFragment(const QString &fragment); 213 214 // get length of plain text 215 int textLength() const; 216 217 // override and hide the toPlainText() call to prevent 218 // issues with lost non-breaking spaces (improperly 219 // converted to normal spaces) 220 QString toPlainText() const; 221 222 // override the createMimeDataFromSelection() to 223 // prevent copy and cut from losing nbsp 224 // ala Kovid's solution in calibre PlainTextEdit 225 virtual QMimeData *createMimeDataFromSelection() const; 226 227 // inherited 228 bool IsLoadingFinished(); 229 230 int GetCursorPosition() const; 231 int GetCursorLine() const; 232 int GetCursorColumn() const; 233 234 void SetZoomFactor(float factor); 235 236 float GetZoomFactor() const; 237 238 void Zoom(); 239 240 void UpdateDisplay(); 241 242 SPCRE::MatchInfo GetMisspelledWord(const QString &text, 243 int start_offset, 244 int end_offset, 245 const QString &search_regex, 246 Searchable::Direction search_direction); 247 248 bool FindNext(const QString &search_regex, 249 Searchable::Direction search_direction, 250 bool misspelled_words = false, 251 bool ignore_selection_offset = false, 252 bool wrap = true, 253 bool selected_text = false); 254 255 int Count(const QString &search_regex, Searchable::Direction direction, bool wrap, bool selected_text = false); 256 257 bool ReplaceSelected(const QString &search_regex, 258 const QString &replacement, 259 Searchable::Direction direction = Searchable::Direction_Down, 260 bool replace_current = false); 261 262 int ReplaceAll(const QString &search_regex, 263 const QString &replacement, 264 Searchable::Direction direction, 265 bool wrap, 266 bool selected_text = false); 267 268 QString GetSelectedText(); 269 270 void SetUpFindForSelectedText(const QString &search_regex); 271 272 /** 273 * Sets flag to execute a centerCursor() call later 274 * with m_DelayedCursorScreenCenteringRequired. 275 */ 276 void SetDelayedCursorScreenCenteringRequired(); 277 278 QString GetCaretElementName(); 279 280 // inherited 281 QList<ElementIndex> GetCaretLocation(); 282 283 // inherited 284 void StoreCaretLocationUpdate(const QList<ElementIndex> &hierarchy); 285 286 // inherited 287 bool ExecuteCaretUpdate(bool default_to_top = false); 288 289 /** 290 * Find the containing block for the cursor location and apply a new 291 * element tag name to it. 292 * 293 * @param element_name The name of the element to format the block to. 294 * @param preserve_attributes Whether to keep any existing attributes on the previous block tag. 295 */ 296 void FormatBlock(const QString &element_name, bool preserve_attributes); 297 298 /** 299 * Given the current cursor position/selection, look to toggle a format style tag 300 * around it. The rule on whether to insert a new tag or remove an existing one is 301 * attempting to emulate what would happen in BookView. If there is the same tag 302 * immediately adjacent to the selection (inside or outside it) then it is removed. 303 * Otherwise a new tag is inserted around the selection. 304 * 305 * @param element_name The name of the element to toggle the format of the selection. 306 * @param property_name If caret is in an inline CSS style instead of the body, property to change 307 * @param property_value If caret is in an inline CSS style instead of the body, value of property to change 308 */ 309 void ToggleFormatSelection(const QString &element_name, const QString property_name = "", const QString property_value = ""); 310 311 /** 312 * Based on the cursor location (in html file) add/replace as 313 * appropriate a style="property_name: property_value" attribute. 314 * 315 * @param property_name The name of the style property to be inserted/replaced. 316 * @param property_value The new value to be assigned to this property. 317 */ 318 void FormatStyle(const QString &property_name, const QString &property_value); 319 320 /** 321 * Based on the cursor location (in html file) add/replace as 322 * appropriate a text direction dir="property_value" attribute. 323 * 324 * @param property_value The new value to be assigned to this property. 325 */ 326 void FormatTextDir(const QString &attribute_value); 327 328 329 /** 330 * Based on the cursor location (in CSS file or inlined in HTML file) 331 * add/replace as appropriate a property_name: property_value property in 332 * the currently selected CSS style if any. 333 * 334 * @param property_name The name of the style property to be inserted/replaced. 335 * @param property_value The new value to be assigned to this property. 336 */ 337 void FormatCSSStyle(const QString &property_name, const QString &property_value); 338 339 bool IsSelectionValid(const QString &text); 340 341 void WrapSelectionInElement(const QString &element, bool unwrap = false); 342 343 void ApplyListToSelection(const QString &element); 344 345 void ApplyCaseChangeToSelection(const Utility::Casing &casing); 346 347 QString GetAttributeId(); 348 349 /** 350 * Based on the cursor location (in html file) 351 * get appropriate attribute_value for attribute_name. 352 * 353 */ 354 QString GetAttribute(const QString &attribute_name, QStringList tag_list = QStringList(), 355 bool must_be_in_attribute = false, bool skip_paired_tags = false, 356 bool must_be_in_body = true); 357 358 359 QString SetAttribute(const QString &attribute_name, QStringList tag_list = QStringList(), const QString &attribute_value = QString(), bool must_be_in_attribute = false, bool skip_paired_tags = false); 360 361 /** 362 * Based on the cursor location (in html file) add/replace as 363 * appropriate an attribute_name="attribute_value". 364 * 365 * @param attribute_name The name of the attribute to be inserted/replaced. 366 * @param attribute_value The new value to be assigned to this attribute. 367 */ 368 QString ProcessAttribute(const QString &attribute_name, QStringList tag_list = QStringList(), 369 const QString &attribute_value = QString(), bool set_attribute = false, 370 bool must_be_in_attribute = false, bool skip_paired_tags = false, 371 bool must_be_in_body = true); 372 373 /** 374 * Control whether the Reformat CSS submenu is available on the context menu. 375 */ 376 bool ReformatCSSEnabled(); 377 void SetReformatCSSEnabled(bool value); 378 379 /** 380 * Control wheter the Reformat (clean) HTML submenu is avaliable on the context menu. 381 */ 382 bool ReformatHTMLEnabled(); 383 void SetReformatHTMLEnabled(bool value); 384 385 bool PasteClipNumber(int clip_number); 386 387 void HighlightWord(const QString &word, int pos); 388 389 signals: 390 391 /** 392 * Emitted whenever the zoom factor changes. 393 * 394 * @param new_zoom_factor The new zoom factor of the View. 395 */ 396 void ZoomFactorChanged(float new_zoom_factor); 397 398 /** 399 * Emitted when the focus is lost. 400 */ 401 void FocusLost(QWidget *editor); 402 403 /** 404 * Emitted when the focus is gained. 405 */ 406 void FocusGained(QWidget *editor); 407 408 void FilteredCursorMoved(); 409 void PageClicked(); 410 void PageUpdated(); 411 412 /** 413 * A filtered version of the QPlainTextEdit::textChnaged signal. 414 * We use it to prevent our syntax highlighter from emitting that signal. 415 */ 416 void FilteredTextChanged(); 417 418 void OpenClipEditorRequest(ClipEditorModel::clipEntry *); 419 420 void OpenIndexEditorRequest(IndexEditorModel::indexEntry *); 421 422 void LinkClicked(const QUrl &url); 423 424 void ViewImage(const QUrl &url); 425 426 void GoToLinkedStyleDefinitionRequest(const QString &element_name, const QString &style_class_name); 427 428 void BookmarkLinkOrStyleLocationRequest(); 429 430 void SpellingHighlightRefreshRequest(); 431 432 void ShowStatusMessageRequest(const QString &message); 433 434 void DocumentSet(); 435 436 void MarkSelectionRequest(); 437 void ClearMarkedTextRequest(); 438 439 public slots: 440 441 /** 442 * A slot wrapper around the base class print() function. 443 * 444 * @param printer The printer interface to use for printing. 445 */ 446 void print(QPagedPaintDevice *printer); 447 448 // Implementations for PasteTarget.h 449 void PasteText(const QString &text); 450 bool PasteClipEntries(const QList<ClipEditorModel::clipEntry *> &clips); 451 452 void RefreshSpellingHighlighting(); 453 454 void OpenImageAction(); 455 456 void GoToLinkOrStyle(); 457 458 bool MarkSelection(); 459 460 bool ClearMarkedText(); 461 462 void RehighlightDocument(); 463 464 protected: 465 466 /** 467 * The global event processing function. 468 * 469 * @param event The event to process. 470 */ 471 bool event(QEvent *event); 472 473 /** 474 * Handles the resize event for the editor. 475 * 476 * @param event The event to process. 477 */ 478 void resizeEvent(QResizeEvent *event); 479 480 /** 481 * Handles the mouse press event for the editor. 482 * 483 * @param event The event to process. 484 */ 485 void mousePressEvent(QMouseEvent *event); 486 487 void mouseReleaseEvent(QMouseEvent *event); 488 489 void mouseDoubleClickEvent(QMouseEvent *event); 490 491 /** 492 * Handles the content menu event for the editor. 493 * 494 * @param event The event to process. 495 */ 496 void contextMenuEvent(QContextMenuEvent *event); 497 498 /** 499 * Handles the focus in event for the editor. 500 * 501 * @param event The event to process. 502 */ 503 void focusInEvent(QFocusEvent *event); 504 505 /** 506 * Handles the focus out event for the editor. 507 * 508 * @param event The event to process. 509 */ 510 void focusOutEvent(QFocusEvent *event); 511 512 private slots: 513 void ResetLastFindMatch(); 514 515 void EmitFilteredCursorMoved(); 516 517 /** 518 * Filters the textChanged signal. 519 * It does this based on the availability of undo. 520 */ 521 void TextChangedFilter(); 522 523 void PasteClipEntryFromName(const QString &name); 524 525 /** 526 * Used solely to update the m_isUndoAvailable variable 527 * on undo availability change. 528 * 529 * @param available The current availability of the undo action. 530 */ 531 void UpdateUndoAvailable(bool available); 532 533 /** 534 * Creates a margin where the line number are can sit. 535 * Called whenever the number of lines changes. 536 */ 537 void UpdateLineNumberAreaMargin(); 538 539 /** 540 * Repaints a part of the line number area as needed. 541 * 542 * @param rectangle Represents the area that the editor needs an update of. 543 * @param vertical_delta The amount of pixels the viewport has been vertically scrolled. 544 */ 545 void UpdateLineNumberArea(const QRect &rectangle, int vertical_delta); 546 547 /** 548 * Highlights the line the user is editing. 549 */ 550 void HighlightCurrentLine(bool highlight_tags=true); 551 552 /** 553 * Wrapper slot for the Scroll One Line Up shortcut. 554 */ 555 void ScrollOneLineUp(); 556 557 /** 558 * Wrapper slot for the Scroll One Line Down shortcut. 559 */ 560 void ScrollOneLineDown(); 561 562 void InsertText(const QString &text); 563 564 void addToUserDictionary(const QString &text); 565 void addToDefaultDictionary(const QString &text); 566 void ignoreWord(const QString &text); 567 568 void SaveClipAction(); 569 570 void GoToLinkOrStyleAction(); 571 572 void ReformatCSSMultiLineAction(); 573 void ReformatCSSSingleLineAction(); 574 575 void ReformatHTMLCleanAction(); 576 void ReformatHTMLCleanAllAction(); 577 void ReformatHTMLToValidAction(); 578 void ReformatHTMLToValidAllAction(); 579 580 private: 581 bool IsMarkedText(); 582 583 void MaybeRegenerateTagList(); 584 585 QString RemoveFirstTag(const QString &text, const QString &tagname); 586 QString RemoveLastTag(const QString &text, const QString &tagname); 587 588 QString GetCurrentWordAtCaret(bool select_word); 589 590 bool PasteClipEntry(ClipEditorModel::clipEntry *clip); 591 592 /** 593 * Resets the currently used font. 594 */ 595 void ResetFont(); 596 597 /** 598 * Updates the font used in the line number area 599 * and also repaints it. 600 * 601 * @param font The new font to use. 602 */ 603 void UpdateLineNumberAreaFont(const QFont &font); 604 605 void SetAppearanceColors(); 606 607 /** 608 * Executes a centerCursor() call if requested 609 * with m_DelayedCursorScreenCenteringRequired. 610 */ 611 void DelayedCursorScreenCentering(); 612 613 /** 614 * Returns the selection offset from the start of the 615 * document depending on the search direction specified 616 * 617 * @param search_direction Depending on this, the anchor or the focus position is returned. 618 * @param ignore_selection_offset Should the selection offset be ignored. 619 */ 620 int GetSelectionOffset(Searchable::Direction search_direction, bool ignore_selection_offset, bool marked_text) const; 621 622 /** 623 * Scrolls the whole screen by one line. 624 * Used for ScrollOneLineUp and ScrollOneLineDown shortcuts. 625 * It will also move the cursor position if the 626 * scroll would make it "fall of the screen". 627 * 628 * @param down If \c true, we scroll down. Otherwise, we scroll up. 629 */ 630 void ScrollByLine(bool down); 631 632 /** 633 * Connects all the required signals to their respective slots. 634 */ 635 void ConnectSignalsToSlots(); 636 637 void AddReformatCSSContextMenu(QMenu *menu); 638 639 void AddReformatHTMLContextMenu(QMenu *menu); 640 641 void AddGoToLinkOrStyleContextMenu(QMenu *menu); 642 643 void AddClipContextMenu(QMenu *menu); 644 645 void AddMarkSelectionMenu(QMenu *menu); 646 647 bool AddSpellCheckContextMenu(QMenu *menu); 648 649 void AddViewImageContextMenu(QMenu *menu); 650 651 bool CreateMenuEntries(QMenu *parent_menu, QAction *topAction, QStandardItem *item); 652 653 bool InViewableImage(); 654 655 /** 656 * An element on the stack when searching for 657 * the current caret location. 658 */ 659 struct StackElement { 660 /** 661 * The tag name. 662 */ 663 QString name; 664 665 /** 666 * The number of child elements 667 * detected for the element, so far. 668 */ 669 int num_children; 670 }; 671 672 /** 673 * Returns a stack of elements representing the 674 * current location of the caret in the document. 675 * 676 * @param offset The number of characters from document start to the end of 677 * the start tag of the element the caret is residing in. 678 * @return The element location stack. 679 */ 680 QStack<StackElement> GetCaretLocationStack(int offset) const; 681 682 /** 683 * Takes the stack provided by GetCaretLocationStack() 684 * and converts it into the element location hierarchy 685 * used by other ViewEditors. 686 * 687 * @param stack The StackElement stack. 688 * @return The converted ElementIndex hierarchy. 689 */ 690 QList<ElementIndex> ConvertStackToHierarchy(const QStack<StackElement> stack) const; 691 692 693 // Used to convert Hierarchy to QWedPath used by BV and Gumbo 694 QString ConvertHierarchyToQWebPath(const QList<ElementIndex>& hierarchy) const; 695 696 /** 697 * Converts a ViewEditor element hierarchy to a tuple describing necessary caret moves. 698 * The tuple contains the vertical lines and horizontal chars move deltas 699 * 700 * @param hierarchy The caret location as ElementIndex hierarchy. 701 * @return The info needed to move the caret to the new location. 702 */ 703 std::tuple<int, int> ConvertHierarchyToCaretMove(const QList<ElementIndex> &hierarchy) const; 704 705 /** 706 * Insert HTML tags around the current selection. 707 */ 708 void InsertHTMLTagAroundSelection(const QString &left_element_name, const QString &right_element_name, const QString &attributes = QString()); 709 710 void InsertHTMLTagAroundText(const QString &left_element_name, const QString &right_element_name, const QString &attributes, const QString &text); 711 712 /** 713 * Is this position within the <body> tag of this text. 714 */ 715 bool IsPositionInBody(int pos); 716 bool IsPositionInTag(int pos); 717 bool IsPositionInOpeningTag(int pos); 718 bool IsPositionInClosingTag(int pos); 719 QString GetOpeningTagName(int pos); 720 QString GetClosingTagName(int pos); 721 722 void FormatSelectionWithinElement(const QString &element_name, int tagno, const QString &text); 723 724 void ReplaceTags(const int &opening_tag_start, const int &opening_tag_end, const QString &opening_tag_text, 725 const int &closing_tag_start, const int &closing_tag_end, const QString &closing_tag_text); 726 727 /** 728 * An element on the stack when searching for 729 * the current caret location. 730 */ 731 struct StyleTagElement { StyleTagElementStyleTagElement732 StyleTagElement() { 733 name = QString(); 734 classStyle = QString(); 735 } 736 /** 737 * The tag name. 738 */ 739 QString name; 740 741 /** 742 * The class style under the caret location if cursor in the class section. 743 * If cursor is on the tag element, is the first style class of this element if any. 744 */ 745 QString classStyle; 746 }; 747 748 StyleTagElement GetSelectedStyleTagElement(); 749 750 /** 751 * Given a list of CSS properties perform any pruning/replacing/adding as necessary to 752 * ensure that property_name:property_value is added (or removed if it already exists). 753 */ 754 void ApplyChangeToProperties(QList<HTMLStyleInfo::CSSProperty> &css_properties, const QString &property_name, const QString &property_value); 755 756 void ReformatCSS(bool multiple_line_format); 757 758 void ReformatHTML(bool all, bool to_valid); 759 760 QStringList GetUnmatchedTagsForBlock(int pos); 761 762 void SelectAndScrollIntoView(int start_position, int end_position, Searchable::Direction direction, bool wrapped); 763 764 /////////////////////////////// 765 // PRIVATE MEMBER VARIABLES 766 /////////////////////////////// 767 768 /** 769 * \c true when an undo action can be performed. 770 */ 771 bool m_isUndoAvailable; 772 773 /** 774 * Keeps track of the last block count. 775 * Needed because QTextDocument::setPlainText sets 776 * this back to 1 before updating it. 777 */ 778 int m_LastBlockCount; 779 780 /** 781 * Keep tack of the currenlt selected line number when selected 782 * by by clicking on the LineNumberArea. 783 */ 784 int m_LineNumberAreaBlockNumber; 785 786 /** 787 * The line number area widget of the code view. 788 */ 789 LineNumberArea *m_LineNumberArea; 790 791 /** 792 * The syntax highlighter. 793 */ 794 QSyntaxHighlighter *m_Highlighter; 795 796 /** 797 * The view's current zoom factor. 798 */ 799 float m_CurrentZoomFactor; 800 801 /** 802 * Catches when the user wants to scroll the view by one line up. 803 */ 804 QShortcut *m_ScrollOneLineUp; 805 806 /** 807 * Catches when the user wants to scroll the view by one line down. 808 */ 809 QShortcut *m_ScrollOneLineDown; 810 811 /** 812 * Set to \c false whenever the page is loading content. 813 */ 814 bool m_isLoadFinished; 815 816 /** 817 * When \c true, a centerCursor() call will be executed 818 * once after the View is repainted. 819 */ 820 bool m_DelayedCursorScreenCenteringRequired; 821 822 int m_caretLocation; 823 824 /** 825 * Stores the update for the caret location 826 * when switching from BookView to CodeView. 827 */ 828 QList<ElementIndex> m_CaretUpdate; 829 830 /** 831 * Whether spell checking is enabled on this view. 832 * Misspellings are marked by the QSyntaxHighlighter used. 833 */ 834 bool m_checkSpelling; 835 836 /** 837 * Whether reformat CSS context menu option is enabled on this view. 838 */ 839 bool m_reformatCSSEnabled; 840 841 /** 842 * Whether reformat (clean) HTML context menu option is enabled on this view. 843 */ 844 bool m_reformatHTMLEnabled; 845 846 /** 847 * Store the last match when doing a find so we can determine if 848 * found text is selected for doing a replace. We also need to store the 849 * match because we can't run the selected text though the PCRE engine 850 * (we don't want to because it's slower than caching) because it will fail 851 * if a look ahead or behind expression is in use. 852 */ 853 SPCRE::MatchInfo m_lastMatch; 854 QString m_lastFindRegex; 855 856 /** 857 * Map spelling suggestion actions from the context menu to the 858 * ReplaceSelected slot. 859 */ 860 QSignalMapper *m_spellingMapper; 861 QSignalMapper *m_addSpellingMapper; 862 QSignalMapper *m_addDictMapper; 863 QSignalMapper *m_ignoreSpellingMapper; 864 QSignalMapper *m_clipMapper; 865 866 int m_MarkedTextStart; 867 int m_MarkedTextEnd; 868 bool m_ReplacingInMarkedText; 869 870 /** 871 * The fonts and colors for appearance of xhtml and text. 872 */ 873 SettingsStore::CodeViewAppearance m_codeViewAppearance; 874 875 /** 876 * Whether spelling highlighting should be reapplied when this tab is next given focus. 877 */ 878 bool m_pendingSpellingHighlighting; 879 QString m_element_name; 880 881 TagLister m_TagList; 882 bool m_regen_taglist; 883 }; 884 885 #endif // CODEVIEWEDITOR_H 886 887