| 1 | /* |
| 2 | SPDX-FileCopyrightText: 2001-2004 Christoph Cullmann <cullmann@kde.org> |
| 3 | SPDX-FileCopyrightText: 2001 Joseph Wenninger <jowenn@kde.org> |
| 4 | SPDX-FileCopyrightText: 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de> |
| 5 | SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org> |
| 6 | |
| 7 | SPDX-License-Identifier: LGPL-2.0-or-later |
| 8 | */ |
| 9 | |
| 10 | #ifndef _KATE_DOCUMENT_H_ |
| 11 | #define _KATE_DOCUMENT_H_ |
| 12 | |
| 13 | #include <QPointer> |
| 14 | #include <QStack> |
| 15 | #include <QTimer> |
| 16 | |
| 17 | #include <ktexteditor/document.h> |
| 18 | #include <ktexteditor/mainwindow.h> |
| 19 | #include <ktexteditor/movingrangefeedback.h> |
| 20 | |
| 21 | #include "katetextline.h" |
| 22 | #include <ktexteditor_export.h> |
| 23 | |
| 24 | #include <span> |
| 25 | |
| 26 | class KJob; |
| 27 | class KateTemplateHandler; |
| 28 | namespace KTextEditor |
| 29 | { |
| 30 | class Plugin; |
| 31 | class Attribute; |
| 32 | class TemplateScript; |
| 33 | } |
| 34 | |
| 35 | namespace KIO |
| 36 | { |
| 37 | class TransferJob; |
| 38 | } |
| 39 | |
| 40 | namespace Kate |
| 41 | { |
| 42 | class SwapFile; |
| 43 | } |
| 44 | |
| 45 | class KateBuffer; |
| 46 | namespace KTextEditor |
| 47 | { |
| 48 | class Message; |
| 49 | class ViewPrivate; |
| 50 | } |
| 51 | class KateDocumentConfig; |
| 52 | class KateHighlighting; |
| 53 | class KateUndoManager; |
| 54 | class KateOnTheFlyChecker; |
| 55 | class KateDocumentTest; |
| 56 | |
| 57 | class KateAutoIndent; |
| 58 | class KateModOnHdPrompt; |
| 59 | class KToggleAction; |
| 60 | |
| 61 | /** |
| 62 | * @brief Backend of KTextEditor::Document related public KTextEditor interfaces. |
| 63 | * |
| 64 | * @warning This file is @e private API and not part of the public |
| 65 | * KTextEditor interfaces. |
| 66 | */ |
| 67 | class KTEXTEDITOR_EXPORT KTextEditor::DocumentPrivate final : public KTextEditor::Document, private KTextEditor::MovingRangeFeedback |
| 68 | { |
| 69 | Q_OBJECT |
| 70 | |
| 71 | friend class KTextEditor::Document; |
| 72 | friend class ::KateDocumentTest; |
| 73 | friend class ::KateBuffer; |
| 74 | |
| 75 | public: |
| 76 | explicit DocumentPrivate(const KPluginMetaData &data, |
| 77 | bool bSingleViewMode = false, |
| 78 | bool bReadOnly = false, |
| 79 | QWidget *parentWidget = nullptr, |
| 80 | QObject * = nullptr); |
| 81 | explicit DocumentPrivate(bool bSingleViewMode = false, bool bReadOnly = false, QWidget *parentWidget = nullptr, QObject * = nullptr) |
| 82 | : DocumentPrivate(KPluginMetaData(), bSingleViewMode, bReadOnly, parentWidget) |
| 83 | { |
| 84 | } |
| 85 | ~DocumentPrivate() override; |
| 86 | |
| 87 | using ReadWritePart::closeUrl; |
| 88 | bool closeUrl() override; |
| 89 | |
| 90 | bool openUrl(const QUrl &url) override; |
| 91 | |
| 92 | KTextEditor::Range rangeOnLine(KTextEditor::Range range, int line) const; |
| 93 | |
| 94 | private: |
| 95 | KTEXTEDITOR_NO_EXPORT |
| 96 | void showAndSetOpeningErrorAccess(); |
| 97 | /* |
| 98 | * Overload this to have on-demand view creation |
| 99 | */ |
| 100 | public: |
| 101 | /** |
| 102 | * @return The widget defined by this part, set by setWidget(). |
| 103 | */ |
| 104 | QWidget *widget() override; |
| 105 | |
| 106 | public: |
| 107 | bool readOnly() const |
| 108 | { |
| 109 | return m_bReadOnly; |
| 110 | } |
| 111 | bool singleViewMode() const |
| 112 | { |
| 113 | return m_bSingleViewMode; |
| 114 | } |
| 115 | |
| 116 | private: |
| 117 | // only to make part work, don't change it ! |
| 118 | const bool m_bSingleViewMode; |
| 119 | const bool m_bReadOnly; |
| 120 | |
| 121 | // |
| 122 | // KTextEditor::Document stuff |
| 123 | // |
| 124 | public: |
| 125 | KTextEditor::View *createView(QWidget *parent, KTextEditor::MainWindow *mainWindow = nullptr) override; |
| 126 | |
| 127 | QList<KTextEditor::View *> views() const override |
| 128 | { |
| 129 | return m_views; |
| 130 | } |
| 131 | |
| 132 | KTextEditor::View *activeView() const |
| 133 | { |
| 134 | return m_activeView; |
| 135 | } |
| 136 | |
| 137 | private: |
| 138 | KTextEditor::View *m_activeView = nullptr; |
| 139 | |
| 140 | // |
| 141 | // KTextEditor::EditInterface stuff |
| 142 | // |
| 143 | public Q_SLOTS: |
| 144 | bool setText(const QString &) override; |
| 145 | bool setText(const QStringList &text) override; |
| 146 | bool clear() override; |
| 147 | |
| 148 | bool insertText(KTextEditor::Cursor position, const QString &s, bool block = false) override; |
| 149 | bool insertText(KTextEditor::Cursor position, const QStringList &text, bool block = false) override; |
| 150 | |
| 151 | bool insertLine(int line, const QString &s) override; |
| 152 | bool insertLines(int line, const QStringList &s) override; |
| 153 | |
| 154 | bool removeText(KTextEditor::Range range, bool block = false) override; |
| 155 | bool removeLine(int line) override; |
| 156 | |
| 157 | bool replaceText(KTextEditor::Range range, const QString &s, bool block = false) override; |
| 158 | |
| 159 | // unhide method... |
| 160 | bool replaceText(KTextEditor::Range r, const QStringList &l, bool b) override |
| 161 | { |
| 162 | return KTextEditor::Document::replaceText(range: r, text: l, block: b); |
| 163 | } |
| 164 | |
| 165 | public: |
| 166 | bool isEditingTransactionRunning() const override; |
| 167 | QString text(KTextEditor::Range range, bool blockwise = false) const override; |
| 168 | QStringList textLines(KTextEditor::Range range, bool block = false) const override; |
| 169 | QString text() const override; |
| 170 | QString line(int line) const override; |
| 171 | QChar characterAt(KTextEditor::Cursor position) const override; |
| 172 | QString wordAt(KTextEditor::Cursor cursor) const override; |
| 173 | KTextEditor::Range wordRangeAt(KTextEditor::Cursor cursor) const override; |
| 174 | bool isValidTextPosition(KTextEditor::Cursor cursor) const override; |
| 175 | int lines() const override; |
| 176 | bool isLineModified(int line) const override; |
| 177 | bool isLineSaved(int line) const override; |
| 178 | bool isLineTouched(int line) const override; |
| 179 | KTextEditor::Cursor documentEnd() const override; |
| 180 | qsizetype totalCharacters() const override; |
| 181 | int lineLength(int line) const override; |
| 182 | qsizetype cursorToOffset(KTextEditor::Cursor c) const override; |
| 183 | KTextEditor::Cursor offsetToCursor(qsizetype offset) const override; |
| 184 | |
| 185 | Q_SIGNALS: |
| 186 | void (KTextEditor::Cursor position, const QString &text); |
| 187 | |
| 188 | /** |
| 189 | * The \p document emits this signal whenever text was inserted. The |
| 190 | * insertion occurred at range.start(), and new text now occupies up to |
| 191 | * range.end(). |
| 192 | * \param document document which emitted this signal |
| 193 | * \param range range that the newly inserted text occupies |
| 194 | * \see insertText(), insertLine() |
| 195 | */ |
| 196 | void textInsertedRange(KTextEditor::Document *document, KTextEditor::Range range); |
| 197 | |
| 198 | /** |
| 199 | * The \p document emits this signal whenever \p range was removed, i.e. |
| 200 | * text was removed. |
| 201 | * \param document document which emitted this signal |
| 202 | * \param range range that the removed text previously occupied |
| 203 | * \param oldText the text that has been removed |
| 204 | * \see removeText(), removeLine(), clear() |
| 205 | */ |
| 206 | void textRemoved(KTextEditor::Document *document, KTextEditor::Range range, const QString &oldText); |
| 207 | |
| 208 | public: |
| 209 | // BEGIN editStart/editEnd (start, end, undo, cursor update, view update) |
| 210 | /** |
| 211 | * Enclose editor actions with @p editStart() and @p editEnd() to group |
| 212 | * them. |
| 213 | */ |
| 214 | bool editStart(); |
| 215 | |
| 216 | /** |
| 217 | * End a editor operation. |
| 218 | * @see editStart() |
| 219 | */ |
| 220 | bool editEnd(); |
| 221 | |
| 222 | void pushEditState(); |
| 223 | void popEditState(); |
| 224 | |
| 225 | // END editStart/editEnd |
| 226 | |
| 227 | void inputMethodStart(); |
| 228 | void inputMethodEnd(); |
| 229 | |
| 230 | // BEGIN LINE BASED INSERT/REMOVE STUFF (editStart() and editEnd() included) |
| 231 | /** |
| 232 | * Add a string in the given line/column |
| 233 | * @param line line number |
| 234 | * @param col column |
| 235 | * @param s string to be inserted |
| 236 | * @return true on success |
| 237 | */ |
| 238 | bool editInsertText(int line, int col, const QString &s, bool notify = true); |
| 239 | |
| 240 | /** |
| 241 | * Remove a string in the given line/column |
| 242 | * @param line line number |
| 243 | * @param col column |
| 244 | * @param len length of text to be removed |
| 245 | * @return true on success |
| 246 | */ |
| 247 | bool editRemoveText(int line, int col, int len); |
| 248 | |
| 249 | /** |
| 250 | * Mark @p line as @p autowrapped. This is necessary if static word warp is |
| 251 | * enabled, because we have to know whether to insert a new line or add the |
| 252 | * wrapped words to the following line. |
| 253 | * @param line line number |
| 254 | * @param autowrapped autowrapped? |
| 255 | * @return true on success |
| 256 | */ |
| 257 | bool editMarkLineAutoWrapped(int line, bool autowrapped); |
| 258 | |
| 259 | /** |
| 260 | * Wrap @p line. If @p newLine is true, ignore the textline's flag |
| 261 | * KateTextLine::flagAutoWrapped and force a new line. Whether a new line |
| 262 | * was needed/added you can grab with @p newLineAdded. |
| 263 | * @param line line number |
| 264 | * @param col column |
| 265 | * @param newLine if true, force a new line |
| 266 | * @param newLineAdded return value is true, if new line was added (may be 0) |
| 267 | * @return true on success |
| 268 | */ |
| 269 | bool editWrapLine(int line, int col, bool newLine = true, bool *newLineAdded = nullptr, bool notify = true); |
| 270 | |
| 271 | /** |
| 272 | * Unwrap @p line. If @p removeLine is true, we force to join the lines. If |
| 273 | * @p removeLine is true, @p length is ignored (eg not needed). |
| 274 | * @param line line number |
| 275 | * @param removeLine if true, force to remove the next line |
| 276 | * @return true on success |
| 277 | */ |
| 278 | bool editUnWrapLine(int line, bool removeLine = true, int length = 0); |
| 279 | |
| 280 | /** |
| 281 | * Insert a string at the given line. |
| 282 | * @param line line number |
| 283 | * @param s string to insert |
| 284 | * @return true on success |
| 285 | */ |
| 286 | bool editInsertLine(int line, const QString &s, bool notify = true); |
| 287 | |
| 288 | /** |
| 289 | * Remove a line |
| 290 | * @param line line number |
| 291 | * @return true on success |
| 292 | */ |
| 293 | bool editRemoveLine(int line); |
| 294 | |
| 295 | bool editRemoveLines(int from, int to); |
| 296 | |
| 297 | /** |
| 298 | * Warp a line |
| 299 | * @param startLine line to begin wrapping |
| 300 | * @param endLine line to stop wrapping |
| 301 | * @return true on success |
| 302 | */ |
| 303 | bool wrapText(int startLine, int endLine); |
| 304 | |
| 305 | /** |
| 306 | * Wrap lines touched by the selection with respect of existing paragraphs. |
| 307 | * To do so will the paragraph prior to the wrap joined as one single line |
| 308 | * which cause an almost perfect wrapped paragraph as long as there are no |
| 309 | * unneeded spaces exist or some formatting like this comment block. |
| 310 | * Without any selection the current line is wrapped. |
| 311 | * Empty lines around each paragraph are untouched. |
| 312 | * @param first line to begin wrapping |
| 313 | * @param last line to stop wrapping |
| 314 | * @return true on success |
| 315 | */ |
| 316 | bool wrapParagraph(int first, int last); |
| 317 | // END LINE BASED INSERT/REMOVE STUFF |
| 318 | |
| 319 | Q_SIGNALS: |
| 320 | /** |
| 321 | * Emitted when text from @p line was wrapped at position pos onto line @p nextLine. |
| 322 | */ |
| 323 | void editLineWrapped(int line, int col, int len); |
| 324 | |
| 325 | /** |
| 326 | * Emitted each time text from @p nextLine was upwrapped onto @p line. |
| 327 | */ |
| 328 | void editLineUnWrapped(int line, int col); |
| 329 | |
| 330 | public: |
| 331 | bool isEditRunning() const; |
| 332 | |
| 333 | void setUndoMergeAllEdits(bool merge); |
| 334 | |
| 335 | enum EditingPositionKind { |
| 336 | Previous, |
| 337 | Next |
| 338 | }; |
| 339 | |
| 340 | /** |
| 341 | *Returns the next or previous position cursor in this document from the stack depending on the argument passed. |
| 342 | *@return cursor invalid if m_editingStack empty |
| 343 | */ |
| 344 | KTextEditor::Cursor lastEditingPosition(EditingPositionKind nextOrPrevious, KTextEditor::Cursor); |
| 345 | |
| 346 | private: |
| 347 | int editSessionNumber = 0; |
| 348 | QStack<int> editStateStack; |
| 349 | bool editIsRunning = false; |
| 350 | bool m_undoMergeAllEdits = false; |
| 351 | KTextEditor::Cursor m_editLastChangeStartCursor = KTextEditor::Cursor::invalid(); |
| 352 | QStack<std::shared_ptr<KTextEditor::MovingCursor>> m_editingStack; |
| 353 | int m_editingStackPosition = -1; |
| 354 | |
| 355 | // |
| 356 | // KTextEditor::UndoInterface stuff |
| 357 | // |
| 358 | public Q_SLOTS: |
| 359 | void undo(); |
| 360 | void redo(); |
| 361 | |
| 362 | /** |
| 363 | * Removes all the elements in m_editingStack of the respective document. |
| 364 | */ |
| 365 | void clearEditingPosStack(); |
| 366 | |
| 367 | /** |
| 368 | * Saves the editing positions into the stack. |
| 369 | * If the consecutive editings happens in the same line, then remove |
| 370 | * the previous and add the new one with updated column no. |
| 371 | */ |
| 372 | void saveEditingPositions(const KTextEditor::Cursor cursor); |
| 373 | |
| 374 | public: |
| 375 | uint undoCount() const; |
| 376 | uint redoCount() const; |
| 377 | |
| 378 | KateUndoManager *undoManager() |
| 379 | { |
| 380 | return m_undoManager; |
| 381 | } |
| 382 | |
| 383 | protected: |
| 384 | KateUndoManager *const m_undoManager; |
| 385 | |
| 386 | public: |
| 387 | QList<KTextEditor::Range> searchText(KTextEditor::Range range, const QString &pattern, const KTextEditor::SearchOptions options) const; |
| 388 | |
| 389 | private: |
| 390 | /** |
| 391 | * Return a widget suitable to be used as a dialog parent. |
| 392 | */ |
| 393 | KTEXTEDITOR_NO_EXPORT |
| 394 | QWidget *dialogParent(); |
| 395 | |
| 396 | /** |
| 397 | * Wrapper around QFileDialog::getSaveFileUrl, will use proper dialogParent |
| 398 | * and try it's best to find a good directory as start |
| 399 | * @param dialogTitle dialog title string |
| 400 | * @return url to save to or empty url if aborted |
| 401 | */ |
| 402 | KTEXTEDITOR_NO_EXPORT |
| 403 | QUrl getSaveFileUrl(const QString &dialogTitle); |
| 404 | |
| 405 | /* |
| 406 | * Access to the mode/highlighting subsystem |
| 407 | */ |
| 408 | public: |
| 409 | /** |
| 410 | * @copydoc KTextEditor::Document::defaultStyleAt() |
| 411 | */ |
| 412 | KSyntaxHighlighting::Theme::TextStyle defaultStyleAt(KTextEditor::Cursor position) const override; |
| 413 | |
| 414 | /** |
| 415 | * Return the name of the currently used mode |
| 416 | * \return name of the used mode |
| 417 | */ |
| 418 | QString mode() const override; |
| 419 | |
| 420 | /** |
| 421 | * Return the name of the currently used mode |
| 422 | * \return name of the used mode |
| 423 | */ |
| 424 | QString highlightingMode() const override; |
| 425 | |
| 426 | /** |
| 427 | * Return a list of the names of all possible modes |
| 428 | * \return list of mode names |
| 429 | */ |
| 430 | QStringList modes() const override; |
| 431 | |
| 432 | /** |
| 433 | * Return a list of the names of all possible modes |
| 434 | * \return list of mode names |
| 435 | */ |
| 436 | QStringList highlightingModes() const override; |
| 437 | |
| 438 | /** |
| 439 | * Set the current mode of the document by giving its name |
| 440 | * \param name name of the mode to use for this document |
| 441 | * \return \e true on success, otherwise \e false |
| 442 | */ |
| 443 | bool setMode(const QString &name) override; |
| 444 | |
| 445 | /** |
| 446 | * Set the current mode of the document by giving its name |
| 447 | * \param name name of the mode to use for this document |
| 448 | * \return \e true on success, otherwise \e false |
| 449 | */ |
| 450 | bool setHighlightingMode(const QString &name) override; |
| 451 | /** |
| 452 | * Returns the name of the section for a highlight given its @p index in the highlight |
| 453 | * list (as returned by highlightModes()). |
| 454 | * You can use this function to build a tree of the highlight names, organized in sections. |
| 455 | * \param index in the highlight list for which to find the section name. |
| 456 | */ |
| 457 | QString highlightingModeSection(int index) const override; |
| 458 | |
| 459 | /** |
| 460 | * Returns the name of the section for a mode given its @p index in the highlight |
| 461 | * list (as returned by modes()). |
| 462 | * You can use this function to build a tree of the mode names, organized in sections. |
| 463 | * \param index index in the highlight list for which to find the section name. |
| 464 | */ |
| 465 | QString modeSection(int index) const override; |
| 466 | |
| 467 | /* |
| 468 | * Helpers.... |
| 469 | */ |
| 470 | public: |
| 471 | void bufferHlChanged(); |
| 472 | |
| 473 | /** |
| 474 | * allow to mark, that we changed hl on user wish and should not reset it |
| 475 | * atm used for the user visible menu to select highlightings |
| 476 | */ |
| 477 | void setDontChangeHlOnSave(); |
| 478 | |
| 479 | /** |
| 480 | * Set that the BOM marker is forced via the tool menu |
| 481 | */ |
| 482 | void bomSetByUser(); |
| 483 | |
| 484 | public: |
| 485 | /** |
| 486 | * Read session settings from the given \p config. |
| 487 | * |
| 488 | * Known flags: |
| 489 | * "SkipUrl" => don't save/restore the file |
| 490 | * "SkipMode" => don't save/restore the mode |
| 491 | * "SkipHighlighting" => don't save/restore the highlighting |
| 492 | * "SkipEncoding" => don't save/restore the encoding |
| 493 | * |
| 494 | * \param config read the session settings from this KConfigGroup |
| 495 | * \param flags additional flags |
| 496 | * \see writeSessionConfig() |
| 497 | */ |
| 498 | void readSessionConfig(const KConfigGroup &config, const QSet<QString> &flags = QSet<QString>()) override; |
| 499 | |
| 500 | /** |
| 501 | * Write session settings to the \p config. |
| 502 | * See readSessionConfig() for more details. |
| 503 | * |
| 504 | * \param config write the session settings to this KConfigGroup |
| 505 | * \param flags additional flags |
| 506 | * \see readSessionConfig() |
| 507 | */ |
| 508 | void writeSessionConfig(KConfigGroup &config, const QSet<QString> &flags = QSet<QString>()) override; |
| 509 | |
| 510 | // |
| 511 | // KTextEditor::MarkInterface |
| 512 | // |
| 513 | public Q_SLOTS: |
| 514 | void setMark(int line, uint markType) override; |
| 515 | void clearMark(int line) override; |
| 516 | |
| 517 | void addMark(int line, uint markType) override; |
| 518 | void removeMark(int line, uint markType) override; |
| 519 | |
| 520 | void clearMarks() override; |
| 521 | |
| 522 | void requestMarkTooltip(int line, QPoint position); |
| 523 | |
| 524 | /// Returns true if the click on the mark should not be further processed |
| 525 | bool handleMarkClick(int line); |
| 526 | |
| 527 | /// Returns true if the context-menu event should not further be processed |
| 528 | bool handleMarkContextMenu(int line, QPoint position); |
| 529 | |
| 530 | void setMarkDescription(Document::MarkTypes, const QString &) override; |
| 531 | |
| 532 | void setEditableMarks(uint markMask) override; |
| 533 | void setMarkIcon(Document::MarkTypes markType, const QIcon &icon) override; |
| 534 | |
| 535 | public: |
| 536 | uint mark(int line) override; |
| 537 | const QHash<int, KTextEditor::Mark *> &marks() override; |
| 538 | QString markDescription(Document::MarkTypes) const override; |
| 539 | virtual QColor markColor(Document::MarkTypes) const; |
| 540 | uint editableMarks() const override; |
| 541 | QIcon markIcon(Document::MarkTypes markType) const override; |
| 542 | |
| 543 | private: |
| 544 | QHash<int, KTextEditor::Mark *> m_marks; |
| 545 | QHash<int, QIcon> m_markIcons; |
| 546 | QHash<int, QString> m_markDescriptions; |
| 547 | uint m_editableMarks = markType01; |
| 548 | |
| 549 | // |
| 550 | // KTextEditor::PrintInterface |
| 551 | // |
| 552 | public Q_SLOTS: |
| 553 | bool print() override; |
| 554 | void printPreview() override; |
| 555 | |
| 556 | // |
| 557 | // KTextEditor::DocumentInfoInterface ( ### unfinished ) |
| 558 | // |
| 559 | public: |
| 560 | /** |
| 561 | * Tries to detect mime-type based on file name and content of buffer. |
| 562 | * |
| 563 | * @return the name of the mimetype for the document. |
| 564 | */ |
| 565 | QString mimeType() override; |
| 566 | |
| 567 | // |
| 568 | // once was KTextEditor::VariableInterface |
| 569 | // |
| 570 | public: |
| 571 | /** |
| 572 | * Returns the value for the variable @p name. |
| 573 | * If the Document does not have a variable called @p name, |
| 574 | * an empty QString() is returned. |
| 575 | * |
| 576 | * // TODO KF6: expose in KTextEditor::Document? |
| 577 | * |
| 578 | * @param name variable to query |
| 579 | * @return value of the variable @p name |
| 580 | * @see setVariable() |
| 581 | */ |
| 582 | virtual QString variable(const QString &name) const; |
| 583 | |
| 584 | /** |
| 585 | * Set the variable @p name to @p value. Setting and changing a variable |
| 586 | * has immediate effect on the Document. For instance, setting the variable |
| 587 | * @e indent-mode to @e cstyle will immediately cause the Document to load |
| 588 | * the C Style indenter. |
| 589 | * |
| 590 | * // TODO KF6: expose in KTextEditor::Document? |
| 591 | * |
| 592 | * @param name the variable name |
| 593 | * @param value the value to be set |
| 594 | * @see variable() |
| 595 | */ |
| 596 | virtual void setVariable(const QString &name, const QString &value); |
| 597 | |
| 598 | private: |
| 599 | std::map<QString, QString> m_storedVariables; |
| 600 | |
| 601 | // |
| 602 | // MovingInterface API |
| 603 | // |
| 604 | public: |
| 605 | /** |
| 606 | * Create a new moving cursor for this document. |
| 607 | * @param position position of the moving cursor to create |
| 608 | * @param insertBehavior insertion behavior |
| 609 | * @return new moving cursor for the document |
| 610 | */ |
| 611 | KTextEditor::MovingCursor *newMovingCursor(KTextEditor::Cursor position, |
| 612 | KTextEditor::MovingCursor::InsertBehavior insertBehavior = KTextEditor::MovingCursor::MoveOnInsert) override; |
| 613 | |
| 614 | /** |
| 615 | * Create a new moving range for this document. |
| 616 | * @param range range of the moving range to create |
| 617 | * @param insertBehaviors insertion behaviors |
| 618 | * @param emptyBehavior behavior on becoming empty |
| 619 | * @return new moving range for the document |
| 620 | */ |
| 621 | KTextEditor::MovingRange *newMovingRange(KTextEditor::Range range, |
| 622 | KTextEditor::MovingRange::InsertBehaviors insertBehaviors = KTextEditor::MovingRange::DoNotExpand, |
| 623 | KTextEditor::MovingRange::EmptyBehavior emptyBehavior = KTextEditor::MovingRange::AllowEmpty) override; |
| 624 | |
| 625 | /** |
| 626 | * Current revision |
| 627 | * @return current revision |
| 628 | */ |
| 629 | qint64 revision() const override; |
| 630 | |
| 631 | /** |
| 632 | * Last revision the buffer got successful saved |
| 633 | * @return last revision buffer got saved, -1 if none |
| 634 | */ |
| 635 | qint64 lastSavedRevision() const override; |
| 636 | |
| 637 | /** |
| 638 | * Lock a revision, this will keep it around until released again. |
| 639 | * But all revisions will always be cleared on buffer clear() (and therefor load()) |
| 640 | * @param revision revision to lock |
| 641 | */ |
| 642 | void lockRevision(qint64 revision) override; |
| 643 | |
| 644 | /** |
| 645 | * Release a revision. |
| 646 | * @param revision revision to release |
| 647 | */ |
| 648 | void unlockRevision(qint64 revision) override; |
| 649 | |
| 650 | /** |
| 651 | * Transform a cursor from one revision to an other. |
| 652 | * @param cursor cursor to transform |
| 653 | * @param insertBehavior behavior of this cursor on insert of text at its position |
| 654 | * @param fromRevision from this revision we want to transform |
| 655 | * @param toRevision to this revision we want to transform, default of -1 is current revision |
| 656 | */ |
| 657 | void transformCursor(KTextEditor::Cursor &cursor, |
| 658 | KTextEditor::MovingCursor::InsertBehavior insertBehavior, |
| 659 | qint64 fromRevision, |
| 660 | qint64 toRevision = -1) override; |
| 661 | |
| 662 | /** |
| 663 | * Transform a cursor from one revision to an other. |
| 664 | * @param line line number of the cursor to transform |
| 665 | * @param column column number of the cursor to transform |
| 666 | * @param insertBehavior behavior of this cursor on insert of text at its position |
| 667 | * @param fromRevision from this revision we want to transform |
| 668 | * @param toRevision to this revision we want to transform, default of -1 is current revision |
| 669 | */ |
| 670 | void |
| 671 | transformCursor(int &line, int &column, KTextEditor::MovingCursor::InsertBehavior insertBehavior, qint64 fromRevision, qint64 toRevision = -1) override; |
| 672 | |
| 673 | /** |
| 674 | * Transform a range from one revision to an other. |
| 675 | * @param range range to transform |
| 676 | * @param insertBehaviors behavior of this range on insert of text at its position |
| 677 | * @param emptyBehavior behavior on becoming empty |
| 678 | * @param fromRevision from this revision we want to transform |
| 679 | * @param toRevision to this revision we want to transform, default of -1 is current revision |
| 680 | */ |
| 681 | void transformRange(KTextEditor::Range &range, |
| 682 | KTextEditor::MovingRange::InsertBehaviors insertBehaviors, |
| 683 | KTextEditor::MovingRange::EmptyBehavior emptyBehavior, |
| 684 | qint64 fromRevision, |
| 685 | qint64 toRevision = -1) override; |
| 686 | |
| 687 | // |
| 688 | // Annotation Interface |
| 689 | // |
| 690 | public: |
| 691 | void setAnnotationModel(KTextEditor::AnnotationModel *model) override; |
| 692 | KTextEditor::AnnotationModel *annotationModel() const override; |
| 693 | |
| 694 | Q_SIGNALS: |
| 695 | void annotationModelChanged(KTextEditor::AnnotationModel *, KTextEditor::AnnotationModel *); |
| 696 | |
| 697 | private: |
| 698 | KTextEditor::AnnotationModel *m_annotationModel = nullptr; |
| 699 | |
| 700 | // |
| 701 | // KParts::ReadWrite stuff |
| 702 | // |
| 703 | public: |
| 704 | /** |
| 705 | * open the file obtained by the kparts framework |
| 706 | * the framework abstracts the loading of remote files |
| 707 | * @return success |
| 708 | */ |
| 709 | bool openFile() override; |
| 710 | |
| 711 | /** |
| 712 | * save the file obtained by the kparts framework |
| 713 | * the framework abstracts the uploading of remote files |
| 714 | * @return success |
| 715 | */ |
| 716 | bool saveFile() override; |
| 717 | |
| 718 | void setReadWrite(bool rw = true) override; |
| 719 | |
| 720 | void setModified(bool m) override; |
| 721 | |
| 722 | bool isAutoReload(); |
| 723 | KToggleAction *autoReloadToggleAction() |
| 724 | { |
| 725 | return m_autoReloadMode; |
| 726 | }; |
| 727 | void delayAutoReload(); |
| 728 | |
| 729 | private Q_SLOTS: |
| 730 | void autoReloadToggled(bool b); |
| 731 | |
| 732 | private: |
| 733 | KTEXTEDITOR_NO_EXPORT |
| 734 | void activateDirWatch(const QString &useFileName = QString()); |
| 735 | KTEXTEDITOR_NO_EXPORT |
| 736 | void deactivateDirWatch(); |
| 737 | |
| 738 | QString m_dirWatchFile; |
| 739 | |
| 740 | /** |
| 741 | * Make backup copy during saveFile, if configured that way. |
| 742 | * @return success? else saveFile should return false and not write the file |
| 743 | */ |
| 744 | KTEXTEDITOR_NO_EXPORT |
| 745 | bool createBackupFile(); |
| 746 | |
| 747 | public: |
| 748 | /** |
| 749 | * Type chars in a view. |
| 750 | * Characters are filtered in KateViewInternal::isAcceptableInput() before calling typeChars. |
| 751 | * |
| 752 | * @param view view that received the input |
| 753 | * @param chars characters to type |
| 754 | */ |
| 755 | void typeChars(KTextEditor::ViewPrivate *view, QString chars); |
| 756 | |
| 757 | /** |
| 758 | * gets the last line number (lines() - 1) |
| 759 | */ |
| 760 | inline int lastLine() const |
| 761 | { |
| 762 | return lines() - 1; |
| 763 | } |
| 764 | |
| 765 | // Repaint all of all of the views |
| 766 | void repaintViews(bool paintOnlyDirty = true); |
| 767 | |
| 768 | KateHighlighting *highlight() const; |
| 769 | |
| 770 | public Q_SLOTS: |
| 771 | void tagLines(KTextEditor::LineRange lineRange); |
| 772 | void tagLine(int line); |
| 773 | |
| 774 | private Q_SLOTS: |
| 775 | void internalHlChanged(); |
| 776 | |
| 777 | public: |
| 778 | void addView(KTextEditor::View *); |
| 779 | /** removes the view from the list of views. The view is *not* deleted. |
| 780 | * That's your job. Or, easier, just delete the view in the first place. |
| 781 | * It will remove itself. TODO: this could be converted to a private slot |
| 782 | * connected to the view's destroyed() signal. It is not currently called |
| 783 | * anywhere except from the KTextEditor::ViewPrivate destructor. |
| 784 | */ |
| 785 | void removeView(KTextEditor::View *); |
| 786 | void setActiveView(KTextEditor::View *); |
| 787 | |
| 788 | bool ownedView(KTextEditor::ViewPrivate *); |
| 789 | |
| 790 | int toVirtualColumn(int line, int column) const; |
| 791 | int toVirtualColumn(const KTextEditor::Cursor) const; |
| 792 | int fromVirtualColumn(int line, int column) const; |
| 793 | int fromVirtualColumn(const KTextEditor::Cursor) const; |
| 794 | |
| 795 | enum NewLineIndent { |
| 796 | Indent, |
| 797 | NoIndent |
| 798 | }; |
| 799 | enum NewLinePos { |
| 800 | Normal, |
| 801 | Above, |
| 802 | Below |
| 803 | }; |
| 804 | |
| 805 | void newLine(KTextEditor::ViewPrivate *view, NewLineIndent indent = NewLineIndent::Indent, NewLinePos newLinePos = Normal); // Changes input |
| 806 | void backspace(KTextEditor::ViewPrivate *view); |
| 807 | void del(KTextEditor::ViewPrivate *view, const KTextEditor::Cursor); |
| 808 | void transpose(const KTextEditor::Cursor); |
| 809 | void (KTextEditor::Range firstWord, KTextEditor::Range secondWord); |
| 810 | bool multiPaste(KTextEditor::ViewPrivate *view, const QStringList &texts); |
| 811 | void paste(KTextEditor::ViewPrivate *view, const QString &text); |
| 812 | |
| 813 | public: |
| 814 | enum { |
| 815 | = -1, |
| 816 | = 0, |
| 817 | = 1, |
| 818 | }; |
| 819 | |
| 820 | private: |
| 821 | // Helper function for use with multiple cursors |
| 822 | KTEXTEDITOR_NO_EXPORT |
| 823 | KTextEditor::Cursor backspaceAtCursor(KTextEditor::ViewPrivate *v, KTextEditor::Cursor c); |
| 824 | void (KTextEditor::Range selection, KTextEditor::Cursor c, bool blockSelect, CommentType changeType); |
| 825 | // exported for katedocument_test |
| 826 | KTEXTEDITOR_NO_EXPORT |
| 827 | bool skipAutoBrace(QChar closingBracket, KTextEditor::Cursor pos); |
| 828 | |
| 829 | public: |
| 830 | void indent(KTextEditor::Range range, int change); |
| 831 | void (KTextEditor::ViewPrivate *view, uint line, uint column, CommentType change); |
| 832 | void align(KTextEditor::ViewPrivate *view, KTextEditor::Range range); |
| 833 | void alignOn(KTextEditor::Range range, const QString &pattern, bool blockwise); |
| 834 | void insertTab(KTextEditor::ViewPrivate *view, const KTextEditor::Cursor); |
| 835 | |
| 836 | enum TextTransform { |
| 837 | Uppercase, |
| 838 | Lowercase, |
| 839 | Capitalize |
| 840 | }; |
| 841 | |
| 842 | /** |
| 843 | Handling uppercase, lowercase and capitalize for the view. |
| 844 | |
| 845 | If there is a selection, that is transformed, otherwise for uppercase or |
| 846 | lowercase the character right of the cursor is transformed, for capitalize |
| 847 | the word under the cursor is transformed. |
| 848 | */ |
| 849 | void transform(KTextEditor::ViewPrivate *view, KTextEditor::Cursor, TextTransform); |
| 850 | /** |
| 851 | Unwrap a range of lines. |
| 852 | */ |
| 853 | void joinLines(uint first, uint last); |
| 854 | |
| 855 | private: |
| 856 | KTEXTEDITOR_NO_EXPORT |
| 857 | void transformCursorOrRange(KTextEditor::ViewPrivate *view, const KTextEditor::Cursor, KTextEditor::Range selection, TextTransform); |
| 858 | |
| 859 | KTEXTEDITOR_NO_EXPORT |
| 860 | bool removeStringFromBeginning(int line, const QString &str); |
| 861 | KTEXTEDITOR_NO_EXPORT |
| 862 | bool removeStringFromEnd(int line, const QString &str); |
| 863 | |
| 864 | /** |
| 865 | Expand tabs to spaces in typed text, if enabled. |
| 866 | @param cursorPos The current cursor position for the inserted characters. |
| 867 | @param str The typed characters to expand. |
| 868 | */ |
| 869 | KTEXTEDITOR_NO_EXPORT |
| 870 | QString eventuallyReplaceTabs(const KTextEditor::Cursor cursorPos, const QString &str) const; |
| 871 | |
| 872 | /** |
| 873 | Find the position (line and col) of the next char |
| 874 | that is not a space. If found line and col point to the found character. |
| 875 | Otherwise they have both the value -1. |
| 876 | @param line Line of the character which is examined first. |
| 877 | @param col Column of the character which is examined first. |
| 878 | @return True if the specified or a following character is not a space |
| 879 | Otherwise false. |
| 880 | */ |
| 881 | KTEXTEDITOR_NO_EXPORT |
| 882 | bool nextNonSpaceCharPos(int &line, int &col); |
| 883 | |
| 884 | /** |
| 885 | Find the position (line and col) of the previous char |
| 886 | that is not a space. If found line and col point to the found character. |
| 887 | Otherwise they have both the value -1. |
| 888 | @return True if the specified or a preceding character is not a space. |
| 889 | Otherwise false. |
| 890 | */ |
| 891 | KTEXTEDITOR_NO_EXPORT |
| 892 | bool previousNonSpaceCharPos(int &line, int &col); |
| 893 | |
| 894 | /** |
| 895 | * Sets a comment marker as defined by the language providing the attribute |
| 896 | * @p attrib on the line @p line |
| 897 | */ |
| 898 | KTEXTEDITOR_NO_EXPORT |
| 899 | void (int line, int attrib = 0); |
| 900 | /** |
| 901 | * Removes a comment marker as defined by the language providing the attribute |
| 902 | * @p attrib on the line @p line |
| 903 | */ |
| 904 | KTEXTEDITOR_NO_EXPORT |
| 905 | bool (int line, int attrib = 0); |
| 906 | |
| 907 | /** |
| 908 | * @see addStartLineCommentToSingleLine. |
| 909 | */ |
| 910 | KTEXTEDITOR_NO_EXPORT |
| 911 | void (int line, int attrib = 0); |
| 912 | /** |
| 913 | *@see removeStartLineCommentFromSingleLine. |
| 914 | */ |
| 915 | KTEXTEDITOR_NO_EXPORT |
| 916 | bool (int line, int attrib = 0); |
| 917 | /** |
| 918 | *@see removeStartLineCommentFromSingleLine. |
| 919 | */ |
| 920 | KTEXTEDITOR_NO_EXPORT |
| 921 | bool (const KTextEditor::Cursor start, const KTextEditor::Cursor end, int attrib = 0); |
| 922 | |
| 923 | /** |
| 924 | * Add a comment marker as defined by the language providing the attribute |
| 925 | * @p attrib to each line in the selection. |
| 926 | */ |
| 927 | KTEXTEDITOR_NO_EXPORT |
| 928 | void (KTextEditor::Range, bool blockSelection, int attrib = 0); |
| 929 | /** |
| 930 | * @see addStartStopCommentToSelection. |
| 931 | */ |
| 932 | KTEXTEDITOR_NO_EXPORT |
| 933 | void (KTextEditor::Range, int attrib = 0); |
| 934 | |
| 935 | /** |
| 936 | * Removes comment markers relevant to the language providing |
| 937 | * the attribute @p attrib from each line in the selection. |
| 938 | * |
| 939 | * @return whether the operation succeeded. |
| 940 | */ |
| 941 | KTEXTEDITOR_NO_EXPORT |
| 942 | bool (KTextEditor::Range, int attrib = 0); |
| 943 | /** |
| 944 | * @see removeStartStopCommentFromSelection. |
| 945 | */ |
| 946 | KTEXTEDITOR_NO_EXPORT |
| 947 | bool (KTextEditor::Range, int attrib, bool ); |
| 948 | |
| 949 | public: |
| 950 | KTextEditor::Range findMatchingBracket(const KTextEditor::Cursor start, int maxLines); |
| 951 | |
| 952 | public: |
| 953 | QString documentName() const override |
| 954 | { |
| 955 | return m_docName; |
| 956 | } |
| 957 | |
| 958 | private: |
| 959 | KTEXTEDITOR_NO_EXPORT |
| 960 | void updateDocName(); |
| 961 | KTEXTEDITOR_NO_EXPORT |
| 962 | static void uniquifyDocNames(const std::vector<KTextEditor::DocumentPrivate *> &docs); |
| 963 | |
| 964 | public: |
| 965 | /** |
| 966 | * @return whether the document is modified on disk since last saved |
| 967 | */ |
| 968 | bool isModifiedOnDisc() |
| 969 | { |
| 970 | return m_modOnHd; |
| 971 | } |
| 972 | |
| 973 | void setModifiedOnDisk(ModifiedOnDiskReason reason) override; |
| 974 | |
| 975 | void setModifiedOnDiskWarning(bool on) override; |
| 976 | |
| 977 | public Q_SLOTS: |
| 978 | /** |
| 979 | * Ask the user what to do, if the file has been modified on disk. |
| 980 | * Reimplemented from KTextEditor::Document. |
| 981 | */ |
| 982 | virtual void slotModifiedOnDisk(KTextEditor::View *v = nullptr); |
| 983 | |
| 984 | /** |
| 985 | * Reloads the current document from disk if possible |
| 986 | */ |
| 987 | bool documentReload() override; |
| 988 | |
| 989 | bool documentSave() override; |
| 990 | bool documentSaveAs() override; |
| 991 | bool documentSaveAsWithEncoding(const QString &encoding); |
| 992 | void documentSaveCopyAs(); |
| 993 | |
| 994 | bool save() override; |
| 995 | |
| 996 | public: |
| 997 | bool saveAs(const QUrl &url) override; |
| 998 | |
| 999 | private: |
| 1000 | // helper to handle the embedded notification for externally modified files |
| 1001 | QPointer<KateModOnHdPrompt> m_modOnHdHandler; |
| 1002 | |
| 1003 | private Q_SLOTS: |
| 1004 | void onModOnHdSaveAs(); |
| 1005 | void onModOnHdClose(); |
| 1006 | void onModOnHdReload(); |
| 1007 | void onModOnHdAutoReload(); |
| 1008 | void onModOnHdIgnore(); |
| 1009 | |
| 1010 | public: |
| 1011 | bool setEncoding(const QString &e) override; |
| 1012 | QString encoding() const override; |
| 1013 | |
| 1014 | public Q_SLOTS: |
| 1015 | void setWordWrap(bool on); |
| 1016 | void setWordWrapAt(uint col); |
| 1017 | |
| 1018 | public: |
| 1019 | bool wordWrap() const; |
| 1020 | uint wordWrapAt() const; |
| 1021 | |
| 1022 | public Q_SLOTS: |
| 1023 | void setPageUpDownMovesCursor(bool on); |
| 1024 | |
| 1025 | public: |
| 1026 | bool pageUpDownMovesCursor() const; |
| 1027 | |
| 1028 | // code folding |
| 1029 | public: |
| 1030 | /** |
| 1031 | * Same as plainKateTextLine(), except that it is made sure |
| 1032 | * the line is highlighted. |
| 1033 | */ |
| 1034 | Kate::TextLine kateTextLine(int i); |
| 1035 | |
| 1036 | //! @copydoc KateBuffer::plainLine() |
| 1037 | Kate::TextLine plainKateTextLine(int i); |
| 1038 | |
| 1039 | Q_SIGNALS: |
| 1040 | void aboutToRemoveText(KTextEditor::Range); |
| 1041 | |
| 1042 | private Q_SLOTS: |
| 1043 | void slotModOnHdDirty(const QString &path); |
| 1044 | void slotModOnHdCreated(const QString &path); |
| 1045 | void slotModOnHdDeleted(const QString &path); |
| 1046 | void slotDelayedHandleModOnHd(); |
| 1047 | |
| 1048 | private: |
| 1049 | /** |
| 1050 | * Create a git compatible sha1 checksum of the file, if it is a local file. |
| 1051 | * The result can be accessed through KateBuffer::digest(). |
| 1052 | * |
| 1053 | * @return whether the operation was attempted and succeeded. |
| 1054 | */ |
| 1055 | bool createDigest(); |
| 1056 | // exported for katedocument_test |
| 1057 | |
| 1058 | /** |
| 1059 | * create a string for the modonhd warnings, giving the reason. |
| 1060 | */ |
| 1061 | KTEXTEDITOR_NO_EXPORT |
| 1062 | QString reasonedMOHString() const; |
| 1063 | |
| 1064 | /** |
| 1065 | * Removes all trailing whitespace in the document and add new line at eof |
| 1066 | * if configured that way. |
| 1067 | */ |
| 1068 | KTEXTEDITOR_NO_EXPORT |
| 1069 | void removeTrailingSpacesAndAddNewLineAtEof(); |
| 1070 | |
| 1071 | public: |
| 1072 | /** |
| 1073 | * This function doesn't check for config and is |
| 1074 | * available for use all the time via an action |
| 1075 | */ |
| 1076 | void removeAllTrailingSpaces(); |
| 1077 | |
| 1078 | /** |
| 1079 | * Returns a git compatible sha1 checksum of this document on disk. |
| 1080 | * @return checksum for this document on disk |
| 1081 | */ |
| 1082 | QByteArray checksum() const override; |
| 1083 | |
| 1084 | /** |
| 1085 | * @return false if @p newType is an invalid mode. |
| 1086 | */ |
| 1087 | bool updateFileType(const QString &newType, bool user = false); |
| 1088 | |
| 1089 | QString fileType() const |
| 1090 | { |
| 1091 | return m_fileType; |
| 1092 | } |
| 1093 | |
| 1094 | /** |
| 1095 | * Get access to buffer of this document. |
| 1096 | * Is needed to create cursors and ranges for example. |
| 1097 | * @return document buffer |
| 1098 | */ |
| 1099 | KateBuffer &buffer() |
| 1100 | { |
| 1101 | return *m_buffer; |
| 1102 | } |
| 1103 | |
| 1104 | /** |
| 1105 | * set indentation mode by user |
| 1106 | * this will remember that a user did set it and will avoid reset on save |
| 1107 | */ |
| 1108 | void rememberUserDidSetIndentationMode() |
| 1109 | { |
| 1110 | m_indenterSetByUser = true; |
| 1111 | } |
| 1112 | |
| 1113 | /** |
| 1114 | * User did set encoding for next reload => enforce it! |
| 1115 | */ |
| 1116 | void userSetEncodingForNextReload() |
| 1117 | { |
| 1118 | m_userSetEncodingForNextReload = true; |
| 1119 | } |
| 1120 | |
| 1121 | // |
| 1122 | // REALLY internal data ;) |
| 1123 | // |
| 1124 | // |
| 1125 | public: |
| 1126 | // File Dialog Helper |
| 1127 | QUrl startUrlForFileDialog(); |
| 1128 | |
| 1129 | private: |
| 1130 | // text buffer |
| 1131 | KateBuffer *const m_buffer; |
| 1132 | |
| 1133 | // indenter |
| 1134 | KateAutoIndent *const m_indenter; |
| 1135 | |
| 1136 | bool m_hlSetByUser = false; |
| 1137 | bool m_bomSetByUser = false; |
| 1138 | bool m_indenterSetByUser = false; |
| 1139 | bool m_userSetEncodingForNextReload = false; |
| 1140 | |
| 1141 | bool m_modOnHd = false; |
| 1142 | KToggleAction *m_autoReloadMode; |
| 1143 | QTimer m_autoReloadThrottle; |
| 1144 | ModifiedOnDiskReason m_modOnHdReason = OnDiskUnmodified; |
| 1145 | ModifiedOnDiskReason m_prevModOnHdReason = OnDiskUnmodified; |
| 1146 | |
| 1147 | QString m_docName; |
| 1148 | int = 0; |
| 1149 | |
| 1150 | // file type !!! |
| 1151 | QString m_fileType; |
| 1152 | bool m_fileTypeSetByUser = false; |
| 1153 | |
| 1154 | /** |
| 1155 | * document is still reloading a file |
| 1156 | */ |
| 1157 | bool m_reloading = false; |
| 1158 | |
| 1159 | public Q_SLOTS: |
| 1160 | void slotQueryClose_save(bool *handled, bool *abortClosing); |
| 1161 | |
| 1162 | public: |
| 1163 | bool queryClose() override; |
| 1164 | |
| 1165 | /** |
| 1166 | * Configuration |
| 1167 | */ |
| 1168 | public: |
| 1169 | KateDocumentConfig *config() |
| 1170 | { |
| 1171 | return m_config.get(); |
| 1172 | } |
| 1173 | KateDocumentConfig *config() const |
| 1174 | { |
| 1175 | return m_config.get(); |
| 1176 | } |
| 1177 | |
| 1178 | void updateConfig(); |
| 1179 | |
| 1180 | private: |
| 1181 | KTEXTEDITOR_NO_EXPORT |
| 1182 | void makeAttribs(bool needInvalidate = true); |
| 1183 | |
| 1184 | std::unique_ptr<KateDocumentConfig> const m_config; |
| 1185 | |
| 1186 | /** |
| 1187 | * Variable Reader |
| 1188 | * TODO add register functionality/ktexteditor interface |
| 1189 | */ |
| 1190 | private: |
| 1191 | /** |
| 1192 | * read dir config file |
| 1193 | * |
| 1194 | * if @p view is set, then variables will |
| 1195 | * only be applied to the given view and nothing else. |
| 1196 | */ |
| 1197 | KTEXTEDITOR_NO_EXPORT |
| 1198 | void readDirConfig(KTextEditor::ViewPrivate *v = nullptr); |
| 1199 | |
| 1200 | /** |
| 1201 | Reads all the variables in the document. |
| 1202 | Called when opening/saving a document |
| 1203 | Returns true if variables were read |
| 1204 | if @p view is set, then variables will |
| 1205 | only be applied to the given view and nothing else. |
| 1206 | */ |
| 1207 | bool readVariables(KTextEditor::ViewPrivate *view = nullptr); |
| 1208 | // exported for katedocument_test |
| 1209 | |
| 1210 | /** |
| 1211 | Reads and applies the variables in a single line |
| 1212 | TODO registered variables gets saved in a [map] |
| 1213 | |
| 1214 | if @p view is set, then variables will |
| 1215 | only be applied to the given view and nothing else. |
| 1216 | */ |
| 1217 | void readVariableLine(const QString &t, KTextEditor::ViewPrivate *view = nullptr); |
| 1218 | // exported for katedocument_test |
| 1219 | /** |
| 1220 | Sets a view variable in all the views. |
| 1221 | */ |
| 1222 | KTEXTEDITOR_NO_EXPORT |
| 1223 | void setViewVariable(const QString &var, const QString &val, std::span<KTextEditor::View *> views); |
| 1224 | /** |
| 1225 | @return weather a string value could be converted |
| 1226 | to a bool value as supported. |
| 1227 | The value is put in *result. |
| 1228 | */ |
| 1229 | KTEXTEDITOR_NO_EXPORT |
| 1230 | static bool checkBoolValue(QString value, bool *result); |
| 1231 | /** |
| 1232 | @return weather a string value could be converted |
| 1233 | to a integer value. |
| 1234 | The value is put in *result. |
| 1235 | */ |
| 1236 | KTEXTEDITOR_NO_EXPORT |
| 1237 | static bool checkIntValue(const QString &value, int *result); |
| 1238 | /** |
| 1239 | Feeds value into @p col using QColor::fromString() and returns |
| 1240 | whether the color is valid |
| 1241 | */ |
| 1242 | KTEXTEDITOR_NO_EXPORT |
| 1243 | static bool checkColorValue(const QString &value, QColor &col); |
| 1244 | |
| 1245 | bool m_fileChangedDialogsActivated = false; |
| 1246 | |
| 1247 | // |
| 1248 | // KTextEditor::ConfigInterface |
| 1249 | // |
| 1250 | public: |
| 1251 | QStringList configKeys() const override; |
| 1252 | QVariant configValue(const QString &key) override; |
| 1253 | void setConfigValue(const QString &key, const QVariant &value) override; |
| 1254 | |
| 1255 | // |
| 1256 | // KTextEditor::RecoveryInterface |
| 1257 | // |
| 1258 | public: |
| 1259 | bool isDataRecoveryAvailable() const override; |
| 1260 | void recoverData() override; |
| 1261 | void discardDataRecovery() override; |
| 1262 | |
| 1263 | // |
| 1264 | // Highlighting information |
| 1265 | // |
| 1266 | public: |
| 1267 | QStringList embeddedHighlightingModes() const override; |
| 1268 | QString highlightingModeAt(KTextEditor::Cursor position) override; |
| 1269 | |
| 1270 | // |
| 1271 | // BEGIN: KTextEditor::MessageInterface |
| 1272 | // |
| 1273 | public: |
| 1274 | bool postMessage(KTextEditor::Message *message) override; |
| 1275 | |
| 1276 | public Q_SLOTS: |
| 1277 | void messageDestroyed(KTextEditor::Message *message); |
| 1278 | |
| 1279 | private: |
| 1280 | QHash<KTextEditor::Message *, QList<std::shared_ptr<QAction>>> m_messageHash; |
| 1281 | // END KTextEditor::MessageInterface |
| 1282 | |
| 1283 | public: |
| 1284 | QString defaultDictionary() const; |
| 1285 | QList<QPair<KTextEditor::MovingRange *, QString>> dictionaryRanges() const; |
| 1286 | bool isOnTheFlySpellCheckingEnabled() const; |
| 1287 | KateOnTheFlyChecker *onTheFlySpellChecker() const |
| 1288 | { |
| 1289 | return m_onTheFlyChecker; |
| 1290 | } |
| 1291 | |
| 1292 | QString dictionaryForMisspelledRange(KTextEditor::Range range) const; |
| 1293 | void clearMisspellingForWord(const QString &word); |
| 1294 | |
| 1295 | public Q_SLOTS: |
| 1296 | void clearDictionaryRanges(); |
| 1297 | void setDictionary(const QString &dict, KTextEditor::Range range, bool blockmode); |
| 1298 | void setDictionary(const QString &dict, KTextEditor::Range range); |
| 1299 | void setDefaultDictionary(const QString &dict); |
| 1300 | void onTheFlySpellCheckingEnabled(bool enable); |
| 1301 | void refreshOnTheFlyCheck(KTextEditor::Range range = KTextEditor::Range::invalid()); |
| 1302 | |
| 1303 | Q_SIGNALS: |
| 1304 | void dictionaryRangesPresent(bool yesNo); |
| 1305 | void defaultDictionaryChanged(KTextEditor::DocumentPrivate *document); |
| 1306 | |
| 1307 | public: |
| 1308 | bool containsCharacterEncoding(KTextEditor::Range range); |
| 1309 | |
| 1310 | typedef QList<QPair<int, int>> OffsetList; |
| 1311 | |
| 1312 | static int computePositionWrtOffsets(const OffsetList &offsetList, int pos); |
| 1313 | |
| 1314 | /** |
| 1315 | * The first OffsetList is from decoded to encoded, and the second OffsetList from |
| 1316 | * encoded to decoded. |
| 1317 | **/ |
| 1318 | QString decodeCharacters(KTextEditor::Range range, |
| 1319 | KTextEditor::DocumentPrivate::OffsetList &decToEncOffsetList, |
| 1320 | KTextEditor::DocumentPrivate::OffsetList &encToDecOffsetList); |
| 1321 | void replaceCharactersByEncoding(KTextEditor::Range range); |
| 1322 | |
| 1323 | protected: |
| 1324 | KateOnTheFlyChecker *m_onTheFlyChecker = nullptr; |
| 1325 | QString m_defaultDictionary; |
| 1326 | QList<QPair<KTextEditor::MovingRange *, QString>> m_dictionaryRanges; |
| 1327 | |
| 1328 | // from KTextEditor::MovingRangeFeedback |
| 1329 | void rangeInvalid(KTextEditor::MovingRange *movingRange) override; |
| 1330 | void rangeEmpty(KTextEditor::MovingRange *movingRange) override; |
| 1331 | |
| 1332 | void deleteDictionaryRange(KTextEditor::MovingRange *movingRange); |
| 1333 | |
| 1334 | private: |
| 1335 | Kate::SwapFile *m_swapfile; |
| 1336 | |
| 1337 | public: |
| 1338 | Kate::SwapFile *swapFile(); |
| 1339 | |
| 1340 | // helpers for scripting and codefolding |
| 1341 | KSyntaxHighlighting::Theme::TextStyle defStyleNum(int line, int column); |
| 1342 | bool (int line, int column); |
| 1343 | |
| 1344 | public: |
| 1345 | /** |
| 1346 | * Find the next modified/saved line, starting at @p startLine. If @p down |
| 1347 | * is \e true, the search is performed downwards, otherwise upwards. |
| 1348 | * @return the touched line in the requested search direction, or -1 if not found |
| 1349 | */ |
| 1350 | int findTouchedLine(int startLine, bool down); |
| 1351 | |
| 1352 | private Q_SLOTS: |
| 1353 | /** |
| 1354 | * watch for all started io jobs to remember if file is perhaps loading atm |
| 1355 | * @param job started job |
| 1356 | */ |
| 1357 | void slotStarted(KIO::Job *job); |
| 1358 | void slotCompleted(); |
| 1359 | void slotCanceled(); |
| 1360 | |
| 1361 | /** |
| 1362 | * trigger display of loading message, after 1000 ms |
| 1363 | */ |
| 1364 | void slotTriggerLoadingMessage(); |
| 1365 | |
| 1366 | /** |
| 1367 | * Abort loading |
| 1368 | */ |
| 1369 | void slotAbortLoading(); |
| 1370 | |
| 1371 | void slotUrlChanged(const QUrl &url); |
| 1372 | |
| 1373 | private: |
| 1374 | /** |
| 1375 | * different possible states |
| 1376 | */ |
| 1377 | enum DocumentStates { |
| 1378 | /** |
| 1379 | * Idle |
| 1380 | */ |
| 1381 | DocumentIdle, |
| 1382 | |
| 1383 | /** |
| 1384 | * Loading |
| 1385 | */ |
| 1386 | DocumentLoading, |
| 1387 | |
| 1388 | /** |
| 1389 | * Saving |
| 1390 | */ |
| 1391 | DocumentSaving, |
| 1392 | |
| 1393 | /** |
| 1394 | * Pre Saving As, this is between ::saveAs is called and ::save |
| 1395 | */ |
| 1396 | DocumentPreSavingAs, |
| 1397 | |
| 1398 | /** |
| 1399 | * Saving As |
| 1400 | */ |
| 1401 | DocumentSavingAs |
| 1402 | }; |
| 1403 | |
| 1404 | /** |
| 1405 | * current state |
| 1406 | */ |
| 1407 | DocumentStates m_documentState = DocumentIdle; |
| 1408 | |
| 1409 | /** |
| 1410 | * read-write state before loading started |
| 1411 | */ |
| 1412 | bool m_readWriteStateBeforeLoading = false; |
| 1413 | |
| 1414 | /** |
| 1415 | * if the document is untitled |
| 1416 | */ |
| 1417 | bool m_isUntitled = true; |
| 1418 | /** |
| 1419 | * loading job, we want to cancel with cancel in the loading message |
| 1420 | */ |
| 1421 | QPointer<KJob> m_loadingJob; |
| 1422 | |
| 1423 | /** |
| 1424 | * message to show during loading |
| 1425 | */ |
| 1426 | QPointer<KTextEditor::Message> m_loadingMessage; |
| 1427 | |
| 1428 | /** |
| 1429 | * Was there any open error on last file loading? |
| 1430 | */ |
| 1431 | bool m_openingError = false; |
| 1432 | |
| 1433 | public: |
| 1434 | /** |
| 1435 | * reads the line length limit from config, if it is not overridden |
| 1436 | */ |
| 1437 | int lineLengthLimit() const; |
| 1438 | |
| 1439 | public Q_SLOTS: |
| 1440 | void openWithLineLengthLimitOverride(); |
| 1441 | |
| 1442 | private: |
| 1443 | /** |
| 1444 | * timer for delayed handling of mod on hd |
| 1445 | */ |
| 1446 | QTimer m_modOnHdTimer; |
| 1447 | |
| 1448 | private: |
| 1449 | /** |
| 1450 | * currently active template handler; there can be only one |
| 1451 | */ |
| 1452 | QPointer<KateTemplateHandler> m_activeTemplateHandler; |
| 1453 | |
| 1454 | private: |
| 1455 | /** |
| 1456 | * current autobrace range |
| 1457 | */ |
| 1458 | std::unique_ptr<KTextEditor::MovingRange> m_currentAutobraceRange; |
| 1459 | /** |
| 1460 | * current autobrace closing character (e.g. ']') |
| 1461 | */ |
| 1462 | QChar m_currentAutobraceClosingChar; |
| 1463 | |
| 1464 | private Q_SLOTS: |
| 1465 | void checkCursorForAutobrace(KTextEditor::View *view, const KTextEditor::Cursor newPos); |
| 1466 | |
| 1467 | public: |
| 1468 | void setActiveTemplateHandler(KateTemplateHandler *handler); |
| 1469 | |
| 1470 | Q_SIGNALS: |
| 1471 | void loaded(KTextEditor::DocumentPrivate *document); |
| 1472 | |
| 1473 | private: |
| 1474 | QList<KTextEditor::View *> m_views; |
| 1475 | QTimer m_autoSaveTimer; |
| 1476 | }; |
| 1477 | |
| 1478 | #endif |
| 1479 | |