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