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