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 | |