File indexing completed on 2024-04-28 15:30:29

0001 /*
0002     SPDX-FileCopyrightText: 2001-2004 Christoph Cullmann <cullmann@kde.org>
0003     SPDX-FileCopyrightText: 2001 Joseph Wenninger <jowenn@kde.org>
0004     SPDX-FileCopyrightText: 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>
0005     SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #ifndef _KATE_DOCUMENT_H_
0011 #define _KATE_DOCUMENT_H_
0012 
0013 #include <QPointer>
0014 #include <QStack>
0015 #include <QTimer>
0016 
0017 #include <KJob>
0018 
0019 #include <ktexteditor/annotationinterface.h>
0020 #include <ktexteditor/configinterface.h>
0021 #include <ktexteditor/document.h>
0022 #include <ktexteditor/inlinenoteinterface.h>
0023 #include <ktexteditor/mainwindow.h>
0024 #include <ktexteditor/markinterface.h>
0025 #include <ktexteditor/message.h>
0026 #include <ktexteditor/modificationinterface.h>
0027 #include <ktexteditor/movinginterface.h>
0028 
0029 #include "katetextline.h"
0030 #include <ktexteditor_export.h>
0031 
0032 class KateTemplateHandler;
0033 namespace KTextEditor
0034 {
0035 class Plugin;
0036 class Attribute;
0037 class TemplateScript;
0038 }
0039 
0040 namespace KIO
0041 {
0042 class TransferJob;
0043 }
0044 
0045 namespace Kate
0046 {
0047 class SwapFile;
0048 }
0049 
0050 class KateBuffer;
0051 namespace KTextEditor
0052 {
0053 class ViewPrivate;
0054 }
0055 class KateDocumentConfig;
0056 class KateHighlighting;
0057 class KateUndoManager;
0058 class KateOnTheFlyChecker;
0059 class KateDocumentTest;
0060 
0061 class KateAutoIndent;
0062 class KateModOnHdPrompt;
0063 class KToggleAction;
0064 
0065 /**
0066  * @brief Backend of KTextEditor::Document related public KTextEditor interfaces.
0067  *
0068  * @warning This file is @e private API and not part of the public
0069  *          KTextEditor interfaces.
0070  */
0071 class KTEXTEDITOR_EXPORT KTextEditor::DocumentPrivate final : public KTextEditor::Document,
0072                                                               public KTextEditor::MarkInterfaceV2,
0073                                                               public KTextEditor::ModificationInterface,
0074                                                               public KTextEditor::ConfigInterface,
0075                                                               public KTextEditor::AnnotationInterface,
0076                                                               public KTextEditor::MovingInterface,
0077                                                               private KTextEditor::MovingRangeFeedback
0078 {
0079     Q_OBJECT
0080     Q_INTERFACES(KTextEditor::MarkInterface)
0081     Q_INTERFACES(KTextEditor::MarkInterfaceV2)
0082     Q_INTERFACES(KTextEditor::ModificationInterface)
0083     Q_INTERFACES(KTextEditor::AnnotationInterface)
0084     Q_INTERFACES(KTextEditor::ConfigInterface)
0085     Q_INTERFACES(KTextEditor::MovingInterface)
0086 
0087     friend class KTextEditor::Document;
0088     friend class ::KateDocumentTest;
0089     friend class ::KateBuffer;
0090 
0091 public:
0092     explicit DocumentPrivate(bool bSingleViewMode = false, bool bReadOnly = false, QWidget *parentWidget = nullptr, QObject * = nullptr);
0093     ~DocumentPrivate() override;
0094 
0095     using ReadWritePart::closeUrl;
0096     bool closeUrl() override;
0097 
0098     bool openUrl(const QUrl &url) override;
0099 
0100     KTextEditor::Range rangeOnLine(KTextEditor::Range range, int line) const;
0101 
0102     void setMetaData(const KPluginMetaData &metaData);
0103 
0104 private:
0105     KTEXTEDITOR_NO_EXPORT
0106     void showAndSetOpeningErrorAccess();
0107     /*
0108      * Overload this to have on-demand view creation
0109      */
0110 public:
0111     /**
0112      * @return The widget defined by this part, set by setWidget().
0113      */
0114     QWidget *widget() override;
0115 
0116 public:
0117     bool readOnly() const
0118     {
0119         return m_bReadOnly;
0120     }
0121     bool singleViewMode() const
0122     {
0123         return m_bSingleViewMode;
0124     }
0125 
0126 private:
0127     // only to make part work, don't change it !
0128     const bool m_bSingleViewMode;
0129     const bool m_bReadOnly;
0130 
0131     //
0132     // KTextEditor::Document stuff
0133     //
0134 public:
0135     KTextEditor::View *createView(QWidget *parent, KTextEditor::MainWindow *mainWindow = nullptr) override;
0136 
0137     QList<KTextEditor::View *> views() const override
0138     {
0139         return m_viewsCache;
0140     }
0141 
0142     virtual KTextEditor::View *activeView() const
0143     {
0144         return m_activeView;
0145     }
0146 
0147 private:
0148     QHash<KTextEditor::View *, KTextEditor::ViewPrivate *> m_views;
0149     KTextEditor::View *m_activeView = nullptr;
0150 
0151     //
0152     // KTextEditor::EditInterface stuff
0153     //
0154 public Q_SLOTS:
0155     bool setText(const QString &) override;
0156     bool setText(const QStringList &text) override;
0157     bool clear() override;
0158 
0159     bool insertText(const KTextEditor::Cursor &position, const QString &s, bool block = false) override;
0160     bool insertText(const KTextEditor::Cursor &position, const QStringList &text, bool block = false) override;
0161 
0162     bool insertLine(int line, const QString &s) override;
0163     bool insertLines(int line, const QStringList &s) override;
0164 
0165     bool removeText(const KTextEditor::Range &range, bool block = false) override;
0166     bool removeLine(int line) override;
0167 
0168     bool replaceText(const KTextEditor::Range &range, const QString &s, bool block = false) override;
0169 
0170     // unhide method...
0171     bool replaceText(const KTextEditor::Range &r, const QStringList &l, bool b) override
0172     {
0173         return KTextEditor::Document::replaceText(r, l, b);
0174     }
0175 
0176 public:
0177     bool isEditingTransactionRunning() const override;
0178     QString text(const KTextEditor::Range &range, bool blockwise = false) const override;
0179     QStringList textLines(const KTextEditor::Range &range, bool block = false) const override;
0180     QString text() const override;
0181     QString line(int line) const override;
0182     QChar characterAt(const KTextEditor::Cursor &position) const override;
0183     QString wordAt(const KTextEditor::Cursor &cursor) const override;
0184     KTextEditor::Range wordRangeAt(const KTextEditor::Cursor &cursor) const override;
0185     bool isValidTextPosition(const KTextEditor::Cursor &cursor) const override;
0186     int lines() const override;
0187     bool isLineModified(int line) const override;
0188     bool isLineSaved(int line) const override;
0189     bool isLineTouched(int line) const override;
0190     KTextEditor::Cursor documentEnd() const override;
0191     int totalCharacters() const override;
0192     int lineLength(int line) const override;
0193 
0194 Q_SIGNALS:
0195     void charactersSemiInteractivelyInserted(const KTextEditor::Cursor &position, const QString &text);
0196 
0197     /**
0198      * The \p document emits this signal whenever text was inserted.  The
0199      * insertion occurred at range.start(), and new text now occupies up to
0200      * range.end().
0201      * \param document document which emitted this signal
0202      * \param range range that the newly inserted text occupies
0203      * \see insertText(), insertLine()
0204      */
0205     void textInsertedRange(KTextEditor::Document *document, const KTextEditor::Range &range);
0206 
0207     /**
0208      * The \p document emits this signal whenever \p range was removed, i.e.
0209      * text was removed.
0210      * \param document document which emitted this signal
0211      * \param range range that the removed text previously occupied
0212      * \param oldText the text that has been removed
0213      * \see removeText(), removeLine(), clear()
0214      */
0215     void textRemoved(KTextEditor::Document *document, const KTextEditor::Range &range, const QString &oldText);
0216 
0217 public:
0218     // BEGIN editStart/editEnd (start, end, undo, cursor update, view update)
0219     /**
0220      * Enclose editor actions with @p editStart() and @p editEnd() to group
0221      * them.
0222      */
0223     bool editStart();
0224 
0225     /**
0226      * Alias for @p editStart()
0227      */
0228     void editBegin()
0229     {
0230         editStart();
0231     }
0232 
0233     /**
0234      * End a editor operation.
0235      * @see editStart()
0236      */
0237     bool editEnd();
0238 
0239     void pushEditState();
0240     void popEditState();
0241 
0242     virtual bool startEditing()
0243     {
0244         return editStart();
0245     }
0246     virtual bool finishEditing()
0247     {
0248         return editEnd();
0249     }
0250 
0251     // END editStart/editEnd
0252 
0253     void inputMethodStart();
0254     void inputMethodEnd();
0255 
0256     // BEGIN LINE BASED INSERT/REMOVE STUFF (editStart() and editEnd() included)
0257     /**
0258      * Add a string in the given line/column
0259      * @param line line number
0260      * @param col column
0261      * @param s string to be inserted
0262      * @return true on success
0263      */
0264     bool editInsertText(int line, int col, const QString &s);
0265 
0266     /**
0267      * Remove a string in the given line/column
0268      * @param line line number
0269      * @param col column
0270      * @param len length of text to be removed
0271      * @return true on success
0272      */
0273     bool editRemoveText(int line, int col, int len);
0274 
0275     /**
0276      * Mark @p line as @p autowrapped. This is necessary if static word warp is
0277      * enabled, because we have to know whether to insert a new line or add the
0278      * wrapped words to the following line.
0279      * @param line line number
0280      * @param autowrapped autowrapped?
0281      * @return true on success
0282      */
0283     bool editMarkLineAutoWrapped(int line, bool autowrapped);
0284 
0285     /**
0286      * Wrap @p line. If @p newLine is true, ignore the textline's flag
0287      * KateTextLine::flagAutoWrapped and force a new line. Whether a new line
0288      * was needed/added you can grab with @p newLineAdded.
0289      * @param line line number
0290      * @param col column
0291      * @param newLine if true, force a new line
0292      * @param newLineAdded return value is true, if new line was added (may be 0)
0293      * @return true on success
0294      */
0295     bool editWrapLine(int line, int col, bool newLine = true, bool *newLineAdded = nullptr);
0296 
0297     /**
0298      * Unwrap @p line. If @p removeLine is true, we force to join the lines. If
0299      * @p removeLine is true, @p length is ignored (eg not needed).
0300      * @param line line number
0301      * @param removeLine if true, force to remove the next line
0302      * @return true on success
0303      */
0304     bool editUnWrapLine(int line, bool removeLine = true, int length = 0);
0305 
0306     /**
0307      * Insert a string at the given line.
0308      * @param line line number
0309      * @param s string to insert
0310      * @return true on success
0311      */
0312     bool editInsertLine(int line, const QString &s);
0313 
0314     /**
0315      * Remove a line
0316      * @param line line number
0317      * @return true on success
0318      */
0319     bool editRemoveLine(int line);
0320 
0321     bool editRemoveLines(int from, int to);
0322 
0323     /**
0324      * Warp a line
0325      * @param startLine line to begin wrapping
0326      * @param endLine line to stop wrapping
0327      * @return true on success
0328      */
0329     bool wrapText(int startLine, int endLine);
0330 
0331     /**
0332      * Wrap lines touched by the selection with respect of existing paragraphs.
0333      * To do so will the paragraph prior to the wrap joined as one single line
0334      * which cause an almost perfect wrapped paragraph as long as there are no
0335      * unneeded spaces exist or some formatting like this comment block.
0336      * Without any selection the current line is wrapped.
0337      * Empty lines around each paragraph are untouched.
0338      * @param first line to begin wrapping
0339      * @param last line to stop wrapping
0340      * @return true on success
0341      */
0342     bool wrapParagraph(int first, int last);
0343     // END LINE BASED INSERT/REMOVE STUFF
0344 
0345 Q_SIGNALS:
0346     /**
0347      * Emitted when text from @p line was wrapped at position pos onto line @p nextLine.
0348      */
0349     void editLineWrapped(int line, int col, int len);
0350 
0351     /**
0352      * Emitted each time text from @p nextLine was upwrapped onto @p line.
0353      */
0354     void editLineUnWrapped(int line, int col);
0355 
0356 public:
0357     bool isEditRunning() const;
0358 
0359     void setUndoMergeAllEdits(bool merge);
0360 
0361     enum EditingPositionKind { Previous, Next };
0362 
0363     /**
0364      *Returns the next or previous position cursor in this document from the stack depending on the argument passed.
0365      *@return cursor invalid if m_editingStack empty
0366      */
0367     KTextEditor::Cursor lastEditingPosition(EditingPositionKind nextOrPrevious, KTextEditor::Cursor);
0368 
0369 private:
0370     int editSessionNumber = 0;
0371     QStack<int> editStateStack;
0372     bool editIsRunning = false;
0373     bool m_undoMergeAllEdits = false;
0374     KTextEditor::Cursor m_editLastChangeStartCursor = KTextEditor::Cursor::invalid();
0375     QStack<QSharedPointer<KTextEditor::MovingCursor>> m_editingStack;
0376     int m_editingStackPosition = -1;
0377 
0378     //
0379     // KTextEditor::UndoInterface stuff
0380     //
0381 public Q_SLOTS:
0382     void undo();
0383     void redo();
0384 
0385     /**
0386      * Removes all the elements in m_editingStack of the respective document.
0387      */
0388     void clearEditingPosStack();
0389 
0390     /**
0391      * Saves the editing positions into the stack.
0392      * If the consecutive editings happens in the same line, then remove
0393      * the previous and add the new one with updated column no.
0394      */
0395     void saveEditingPositions(const KTextEditor::Cursor cursor);
0396 
0397 public:
0398     uint undoCount() const;
0399     uint redoCount() const;
0400 
0401     KateUndoManager *undoManager()
0402     {
0403         return m_undoManager;
0404     }
0405 
0406 protected:
0407     KateUndoManager *const m_undoManager;
0408 
0409 Q_SIGNALS:
0410     void undoChanged();
0411 
0412 public:
0413     QVector<KTextEditor::Range> searchText(KTextEditor::Range range, const QString &pattern, const KTextEditor::SearchOptions options) const;
0414 
0415 private:
0416     /**
0417      * Return a widget suitable to be used as a dialog parent.
0418      */
0419     KTEXTEDITOR_NO_EXPORT
0420     QWidget *dialogParent();
0421 
0422     /**
0423      * Wrapper around QFileDialog::getSaveFileUrl, will use proper dialogParent
0424      * and try it's best to find a good directory as start
0425      * @param dialogTitle dialog title string
0426      * @return url to save to or empty url if aborted
0427      */
0428     KTEXTEDITOR_NO_EXPORT
0429     QUrl getSaveFileUrl(const QString &dialogTitle);
0430 
0431     /*
0432      * Access to the mode/highlighting subsystem
0433      */
0434 public:
0435     /**
0436      * @copydoc KTextEditor::Document::defaultStyleAt()
0437      */
0438     KTextEditor::DefaultStyle defaultStyleAt(const KTextEditor::Cursor &position) const override;
0439 
0440     /**
0441      * Return the name of the currently used mode
0442      * \return name of the used mode
0443      */
0444     QString mode() const override;
0445 
0446     /**
0447      * Return the name of the currently used mode
0448      * \return name of the used mode
0449      */
0450     QString highlightingMode() const override;
0451 
0452     /**
0453      * Return a list of the names of all possible modes
0454      * \return list of mode names
0455      */
0456     QStringList modes() const override;
0457 
0458     /**
0459      * Return a list of the names of all possible modes
0460      * \return list of mode names
0461      */
0462     QStringList highlightingModes() const override;
0463 
0464     /**
0465      * Set the current mode of the document by giving its name
0466      * \param name name of the mode to use for this document
0467      * \return \e true on success, otherwise \e false
0468      */
0469     bool setMode(const QString &name) override;
0470 
0471     /**
0472      * Set the current mode of the document by giving its name
0473      * \param name name of the mode to use for this document
0474      * \return \e true on success, otherwise \e false
0475      */
0476     bool setHighlightingMode(const QString &name) override;
0477     /**
0478      * Returns the name of the section for a highlight given its @p index in the highlight
0479      * list (as returned by highlightModes()).
0480      * You can use this function to build a tree of the highlight names, organized in sections.
0481      * \param index in the highlight list for which to find the section name.
0482      */
0483     QString highlightingModeSection(int index) const override;
0484 
0485     /**
0486      * Returns the name of the section for a mode given its @p index in the highlight
0487      * list (as returned by modes()).
0488      * You can use this function to build a tree of the mode names, organized in sections.
0489      * \param index index in the highlight list for which to find the section name.
0490      */
0491     QString modeSection(int index) const override;
0492 
0493     /*
0494      * Helpers....
0495      */
0496 public:
0497     void bufferHlChanged();
0498 
0499     /**
0500      * allow to mark, that we changed hl on user wish and should not reset it
0501      * atm used for the user visible menu to select highlightings
0502      */
0503     void setDontChangeHlOnSave();
0504 
0505     /**
0506      * Set that the BOM marker is forced via the tool menu
0507      */
0508     void bomSetByUser();
0509 
0510 public:
0511     /**
0512      * Read session settings from the given \p config.
0513      *
0514      * Known flags:
0515      *  "SkipUrl" => don't save/restore the file
0516      *  "SkipMode" => don't save/restore the mode
0517      *  "SkipHighlighting" => don't save/restore the highlighting
0518      *  "SkipEncoding" => don't save/restore the encoding
0519      *
0520      * \param config read the session settings from this KConfigGroup
0521      * \param flags additional flags
0522      * \see writeSessionConfig()
0523      */
0524     void readSessionConfig(const KConfigGroup &config, const QSet<QString> &flags = QSet<QString>()) override;
0525 
0526     /**
0527      * Write session settings to the \p config.
0528      * See readSessionConfig() for more details.
0529      *
0530      * \param config write the session settings to this KConfigGroup
0531      * \param flags additional flags
0532      * \see readSessionConfig()
0533      */
0534     void writeSessionConfig(KConfigGroup &config, const QSet<QString> &flags = QSet<QString>()) override;
0535 
0536     //
0537     // KTextEditor::MarkInterface
0538     //
0539 public Q_SLOTS:
0540     void setMark(int line, uint markType) override;
0541     void clearMark(int line) override;
0542 
0543     void addMark(int line, uint markType) override;
0544     void removeMark(int line, uint markType) override;
0545 
0546     void clearMarks() override;
0547 
0548     void requestMarkTooltip(int line, QPoint position);
0549 
0550     /// Returns true if the click on the mark should not be further processed
0551     bool handleMarkClick(int line);
0552 
0553     /// Returns true if the context-menu event should not further be processed
0554     bool handleMarkContextMenu(int line, QPoint position);
0555 
0556     void setMarkPixmap(MarkInterface::MarkTypes, const QPixmap &) override;
0557 
0558     void setMarkDescription(MarkInterface::MarkTypes, const QString &) override;
0559 
0560     void setEditableMarks(uint markMask) override;
0561 
0562 public:
0563     uint mark(int line) override;
0564     const QHash<int, KTextEditor::Mark *> &marks() override;
0565     QPixmap markPixmap(MarkInterface::MarkTypes) const override;
0566     QString markDescription(MarkInterface::MarkTypes) const override;
0567     virtual QColor markColor(MarkInterface::MarkTypes) const;
0568     uint editableMarks() const override;
0569 
0570 Q_SIGNALS:
0571     void markToolTipRequested(KTextEditor::Document *document, KTextEditor::Mark mark, QPoint position, bool &handled);
0572 
0573     void markContextMenuRequested(KTextEditor::Document *document, KTextEditor::Mark mark, QPoint pos, bool &handled);
0574 
0575     void markClicked(KTextEditor::Document *document, KTextEditor::Mark mark, bool &handled);
0576 
0577     void marksChanged(KTextEditor::Document *) override;
0578     void markChanged(KTextEditor::Document *, KTextEditor::Mark, KTextEditor::MarkInterface::MarkChangeAction) override;
0579 
0580 private:
0581     QHash<int, KTextEditor::Mark *> m_marks;
0582     QHash<int, QVariant> m_markIcons; // QPixmap or QIcon, KF6: remove QPixmap support
0583     QHash<int, QString> m_markDescriptions;
0584     uint m_editableMarks = markType01;
0585 
0586     //
0587     // KTextEditor::MarkInterfaceV2
0588     //
0589 public Q_SLOTS:
0590     void setMarkIcon(MarkInterface::MarkTypes markType, const QIcon &icon) override;
0591 
0592 public:
0593     QIcon markIcon(MarkInterface::MarkTypes markType) const override;
0594 
0595     // KTextEditor::PrintInterface
0596     //
0597 public Q_SLOTS:
0598     bool print() override;
0599     void printPreview() override;
0600 
0601     //
0602     // KTextEditor::DocumentInfoInterface ( ### unfinished )
0603     //
0604 public:
0605     /**
0606      * Tries to detect mime-type based on file name and content of buffer.
0607      *
0608      * @return the name of the mimetype for the document.
0609      */
0610     QString mimeType() override;
0611 
0612     //
0613     // once was KTextEditor::VariableInterface
0614     //
0615 public:
0616     /**
0617      * Returns the value for the variable @p name.
0618      * If the Document does not have a variable called @p name,
0619      * an empty QString() is returned.
0620      *
0621      * // TODO KF6: expose in KTextEditor::Document?
0622      *
0623      * @param name variable to query
0624      * @return value of the variable @p name
0625      * @see setVariable()
0626      */
0627     virtual QString variable(const QString &name) const;
0628 
0629     /**
0630      * Set the variable @p name to @p value. Setting and changing a variable
0631      * has immediate effect on the Document. For instance, setting the variable
0632      * @e indent-mode to @e cstyle will immediately cause the Document to load
0633      * the C Style indenter.
0634      *
0635      * // TODO KF6: expose in KTextEditor::Document?
0636      *
0637      * @param name the variable name
0638      * @param value the value to be set
0639      * @see variable()
0640      */
0641     virtual void setVariable(const QString &name, const QString &value);
0642 
0643 private:
0644     std::map<QString, QString> m_storedVariables;
0645 
0646     //
0647     // MovingInterface API
0648     //
0649 public:
0650     /**
0651      * Create a new moving cursor for this document.
0652      * @param position position of the moving cursor to create
0653      * @param insertBehavior insertion behavior
0654      * @return new moving cursor for the document
0655      */
0656     KTextEditor::MovingCursor *newMovingCursor(const KTextEditor::Cursor &position,
0657                                                KTextEditor::MovingCursor::InsertBehavior insertBehavior = KTextEditor::MovingCursor::MoveOnInsert) override;
0658 
0659     /**
0660      * Create a new moving range for this document.
0661      * @param range range of the moving range to create
0662      * @param insertBehaviors insertion behaviors
0663      * @param emptyBehavior behavior on becoming empty
0664      * @return new moving range for the document
0665      */
0666     KTextEditor::MovingRange *newMovingRange(const KTextEditor::Range &range,
0667                                              KTextEditor::MovingRange::InsertBehaviors insertBehaviors = KTextEditor::MovingRange::DoNotExpand,
0668                                              KTextEditor::MovingRange::EmptyBehavior emptyBehavior = KTextEditor::MovingRange::AllowEmpty) override;
0669 
0670     /**
0671      * Current revision
0672      * @return current revision
0673      */
0674     qint64 revision() const override;
0675 
0676     /**
0677      * Last revision the buffer got successful saved
0678      * @return last revision buffer got saved, -1 if none
0679      */
0680     qint64 lastSavedRevision() const override;
0681 
0682     /**
0683      * Lock a revision, this will keep it around until released again.
0684      * But all revisions will always be cleared on buffer clear() (and therefor load())
0685      * @param revision revision to lock
0686      */
0687     void lockRevision(qint64 revision) override;
0688 
0689     /**
0690      * Release a revision.
0691      * @param revision revision to release
0692      */
0693     void unlockRevision(qint64 revision) override;
0694 
0695     /**
0696      * Transform a cursor from one revision to an other.
0697      * @param cursor cursor to transform
0698      * @param insertBehavior behavior of this cursor on insert of text at its position
0699      * @param fromRevision from this revision we want to transform
0700      * @param toRevision to this revision we want to transform, default of -1 is current revision
0701      */
0702     void transformCursor(KTextEditor::Cursor &cursor,
0703                          KTextEditor::MovingCursor::InsertBehavior insertBehavior,
0704                          qint64 fromRevision,
0705                          qint64 toRevision = -1) override;
0706 
0707     /**
0708      * Transform a cursor from one revision to an other.
0709      * @param line line number of the cursor to transform
0710      * @param column column number of the cursor to transform
0711      * @param insertBehavior behavior of this cursor on insert of text at its position
0712      * @param fromRevision from this revision we want to transform
0713      * @param toRevision to this revision we want to transform, default of -1 is current revision
0714      */
0715     void
0716     transformCursor(int &line, int &column, KTextEditor::MovingCursor::InsertBehavior insertBehavior, qint64 fromRevision, qint64 toRevision = -1) override;
0717 
0718     /**
0719      * Transform a range from one revision to an other.
0720      * @param range range to transform
0721      * @param insertBehaviors behavior of this range on insert of text at its position
0722      * @param emptyBehavior behavior on becoming empty
0723      * @param fromRevision from this revision we want to transform
0724      * @param toRevision to this revision we want to transform, default of -1 is current revision
0725      */
0726     void transformRange(KTextEditor::Range &range,
0727                         KTextEditor::MovingRange::InsertBehaviors insertBehaviors,
0728                         KTextEditor::MovingRange::EmptyBehavior emptyBehavior,
0729                         qint64 fromRevision,
0730                         qint64 toRevision = -1) override;
0731 
0732     //
0733     // MovingInterface Signals
0734     //
0735 Q_SIGNALS:
0736     /**
0737      * This signal is emitted before the cursors/ranges/revisions of a document are destroyed as the document is deleted.
0738      * @param document the document which the interface belongs too which is in the process of being deleted
0739      */
0740     void aboutToDeleteMovingInterfaceContent(KTextEditor::Document *document);
0741 
0742     /**
0743      * 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
0744      * load/reload). While this signal is emitted, still the old document content is around before the clear.
0745      * @param document the document which the interface belongs too which will invalidate its data
0746      */
0747     void aboutToInvalidateMovingInterfaceContent(KTextEditor::Document *document);
0748 
0749     //
0750     // Annotation Interface
0751     //
0752 public:
0753     void setAnnotationModel(KTextEditor::AnnotationModel *model) override;
0754     KTextEditor::AnnotationModel *annotationModel() const override;
0755 
0756 Q_SIGNALS:
0757     void annotationModelChanged(KTextEditor::AnnotationModel *, KTextEditor::AnnotationModel *);
0758 
0759 private:
0760     KTextEditor::AnnotationModel *m_annotationModel = nullptr;
0761 
0762     //
0763     // KParts::ReadWrite stuff
0764     //
0765 public:
0766     /**
0767      * open the file obtained by the kparts framework
0768      * the framework abstracts the loading of remote files
0769      * @return success
0770      */
0771     bool openFile() override;
0772 
0773     /**
0774      * save the file obtained by the kparts framework
0775      * the framework abstracts the uploading of remote files
0776      * @return success
0777      */
0778     bool saveFile() override;
0779 
0780     void setReadWrite(bool rw = true) override;
0781 
0782     void setModified(bool m) override;
0783 
0784     bool isAutoReload();
0785     KToggleAction *autoReloadToggleAction()
0786     {
0787         return m_autoReloadMode;
0788     };
0789     void delayAutoReload();
0790 
0791 private Q_SLOTS:
0792     void autoReloadToggled(bool b);
0793 
0794 private:
0795     KTEXTEDITOR_NO_EXPORT
0796     void activateDirWatch(const QString &useFileName = QString());
0797     KTEXTEDITOR_NO_EXPORT
0798     void deactivateDirWatch();
0799 
0800     QString m_dirWatchFile;
0801 
0802     /**
0803      * Make backup copy during saveFile, if configured that way.
0804      * @return success? else saveFile should return false and not write the file
0805      */
0806     KTEXTEDITOR_NO_EXPORT
0807     bool createBackupFile();
0808 
0809 public:
0810     /**
0811      * Type chars in a view.
0812      * Characters are filtered in KateViewInternal::isAcceptableInput() before calling typeChars.
0813      *
0814      * @param view view that received the input
0815      * @param chars characters to type
0816      */
0817     void typeChars(KTextEditor::ViewPrivate *view, QString chars);
0818 
0819     /**
0820      * gets the last line number (lines() - 1)
0821      */
0822     inline int lastLine() const
0823     {
0824         return lines() - 1;
0825     }
0826 
0827     // Repaint all of all of the views
0828     void repaintViews(bool paintOnlyDirty = true);
0829 
0830     KateHighlighting *highlight() const;
0831 
0832 public Q_SLOTS:
0833     void tagLines(KTextEditor::LineRange lineRange);
0834     void tagLine(int line);
0835 
0836 private Q_SLOTS:
0837     void internalHlChanged();
0838 
0839 public:
0840     void addView(KTextEditor::View *);
0841     /** removes the view from the list of views. The view is *not* deleted.
0842      * That's your job. Or, easier, just delete the view in the first place.
0843      * It will remove itself. TODO: this could be converted to a private slot
0844      * connected to the view's destroyed() signal. It is not currently called
0845      * anywhere except from the KTextEditor::ViewPrivate destructor.
0846      */
0847     void removeView(KTextEditor::View *);
0848     void setActiveView(KTextEditor::View *);
0849 
0850     bool ownedView(KTextEditor::ViewPrivate *);
0851 
0852     int toVirtualColumn(int line, int column) const;
0853     int toVirtualColumn(const KTextEditor::Cursor) const;
0854     int fromVirtualColumn(int line, int column) const;
0855     int fromVirtualColumn(const KTextEditor::Cursor) const;
0856 
0857     enum NewLineIndent { Indent, NoIndent };
0858     enum NewLinePos { Normal, Above, Below };
0859 
0860     void newLine(KTextEditor::ViewPrivate *view, NewLineIndent indent = NewLineIndent::Indent, NewLinePos newLinePos = Normal); // Changes input
0861     void backspace(KTextEditor::ViewPrivate *view);
0862     void del(KTextEditor::ViewPrivate *view, const KTextEditor::Cursor);
0863     void transpose(const KTextEditor::Cursor);
0864     void swapTextRanges(KTextEditor::Range firstWord, KTextEditor::Range secondWord);
0865     bool multiPaste(KTextEditor::ViewPrivate *view, const QStringList &texts);
0866     void paste(KTextEditor::ViewPrivate *view, const QString &text);
0867 
0868 public:
0869     enum CommentType {
0870         UnComment = -1,
0871         ToggleComment = 0,
0872         Comment = 1,
0873     };
0874 
0875 private:
0876     // Helper function for use with multiple cursors
0877     KTEXTEDITOR_NO_EXPORT
0878     KTextEditor::Cursor backspaceAtCursor(KTextEditor::ViewPrivate *v, KTextEditor::Cursor c);
0879     void commentSelection(KTextEditor::Range selection, KTextEditor::Cursor c, bool blockSelect, CommentType changeType);
0880     // exported for katedocument_test
0881     KTEXTEDITOR_NO_EXPORT
0882     bool skipAutoBrace(QChar closingBracket, KTextEditor::Cursor pos);
0883 
0884 public:
0885     void indent(KTextEditor::Range range, int change);
0886     void comment(KTextEditor::ViewPrivate *view, uint line, uint column, CommentType change);
0887     void align(KTextEditor::ViewPrivate *view, KTextEditor::Range range);
0888     void alignOn(KTextEditor::Range range, const QString &pattern, bool blockwise);
0889     void insertTab(KTextEditor::ViewPrivate *view, const KTextEditor::Cursor);
0890 
0891     enum TextTransform { Uppercase, Lowercase, Capitalize };
0892 
0893     /**
0894       Handling uppercase, lowercase and capitalize for the view.
0895 
0896       If there is a selection, that is transformed, otherwise for uppercase or
0897       lowercase the character right of the cursor is transformed, for capitalize
0898       the word under the cursor is transformed.
0899     */
0900     void transform(KTextEditor::ViewPrivate *view, KTextEditor::Cursor, TextTransform);
0901     /**
0902       Unwrap a range of lines.
0903     */
0904     void joinLines(uint first, uint last);
0905 
0906 private:
0907     KTEXTEDITOR_NO_EXPORT
0908     void transformCursorOrRange(KTextEditor::ViewPrivate *view, const KTextEditor::Cursor, KTextEditor::Range selection, TextTransform);
0909 
0910     KTEXTEDITOR_NO_EXPORT
0911     bool removeStringFromBeginning(int line, const QString &str);
0912     KTEXTEDITOR_NO_EXPORT
0913     bool removeStringFromEnd(int line, const QString &str);
0914 
0915     /**
0916       Expand tabs to spaces in typed text, if enabled.
0917       @param cursorPos The current cursor position for the inserted characters.
0918       @param str The typed characters to expand.
0919     */
0920     KTEXTEDITOR_NO_EXPORT
0921     QString eventuallyReplaceTabs(const KTextEditor::Cursor cursorPos, const QString &str) const;
0922 
0923     /**
0924       Find the position (line and col) of the next char
0925       that is not a space. If found line and col point to the found character.
0926       Otherwise they have both the value -1.
0927       @param line Line of the character which is examined first.
0928       @param col Column of the character which is examined first.
0929       @return True if the specified or a following character is not a space
0930                Otherwise false.
0931     */
0932     KTEXTEDITOR_NO_EXPORT
0933     bool nextNonSpaceCharPos(int &line, int &col);
0934 
0935     /**
0936       Find the position (line and col) of the previous char
0937       that is not a space. If found line and col point to the found character.
0938       Otherwise they have both the value -1.
0939       @return True if the specified or a preceding character is not a space.
0940                Otherwise false.
0941     */
0942     KTEXTEDITOR_NO_EXPORT
0943     bool previousNonSpaceCharPos(int &line, int &col);
0944 
0945     /**
0946      * Sets a comment marker as defined by the language providing the attribute
0947      * @p attrib on the line @p line
0948      */
0949     KTEXTEDITOR_NO_EXPORT
0950     void addStartLineCommentToSingleLine(int line, int attrib = 0);
0951     /**
0952      * Removes a comment marker as defined by the language providing the attribute
0953      * @p attrib on the line @p line
0954      */
0955     KTEXTEDITOR_NO_EXPORT
0956     bool removeStartLineCommentFromSingleLine(int line, int attrib = 0);
0957 
0958     /**
0959      * @see addStartLineCommentToSingleLine.
0960      */
0961     KTEXTEDITOR_NO_EXPORT
0962     void addStartStopCommentToSingleLine(int line, int attrib = 0);
0963     /**
0964      *@see removeStartLineCommentFromSingleLine.
0965      */
0966     KTEXTEDITOR_NO_EXPORT
0967     bool removeStartStopCommentFromSingleLine(int line, int attrib = 0);
0968     /**
0969      *@see removeStartLineCommentFromSingleLine.
0970      */
0971     KTEXTEDITOR_NO_EXPORT
0972     bool removeStartStopCommentFromRegion(const KTextEditor::Cursor start, const KTextEditor::Cursor end, int attrib = 0);
0973 
0974     /**
0975      * Add a comment marker as defined by the language providing the attribute
0976      * @p attrib to each line in the selection.
0977      */
0978     KTEXTEDITOR_NO_EXPORT
0979     void addStartStopCommentToSelection(KTextEditor::Range, bool blockSelection, int attrib = 0);
0980     /**
0981      * @see addStartStopCommentToSelection.
0982      */
0983     KTEXTEDITOR_NO_EXPORT
0984     void addStartLineCommentToSelection(KTextEditor::Range, int attrib = 0);
0985 
0986     /**
0987      * Removes comment markers relevant to the language providing
0988      * the attribute @p attrib from each line in the selection.
0989      *
0990      * @return whether the operation succeeded.
0991      */
0992     KTEXTEDITOR_NO_EXPORT
0993     bool removeStartStopCommentFromSelection(KTextEditor::Range, int attrib = 0);
0994     /**
0995      * @see removeStartStopCommentFromSelection.
0996      */
0997     KTEXTEDITOR_NO_EXPORT
0998     bool removeStartLineCommentFromSelection(KTextEditor::Range, int attrib, bool toggleComment);
0999 
1000 public:
1001     KTextEditor::Range findMatchingBracket(const KTextEditor::Cursor start, int maxLines);
1002 
1003 public:
1004     QString documentName() const override
1005     {
1006         return m_docName;
1007     }
1008 
1009 private:
1010     KTEXTEDITOR_NO_EXPORT
1011     void updateDocName();
1012     KTEXTEDITOR_NO_EXPORT
1013     static void uniquifyDocNames(const std::vector<KTextEditor::DocumentPrivate *> &docs);
1014 
1015 public:
1016     /**
1017      * @return whether the document is modified on disk since last saved
1018      */
1019     bool isModifiedOnDisc()
1020     {
1021         return m_modOnHd;
1022     }
1023 
1024     void setModifiedOnDisk(ModifiedOnDiskReason reason) override;
1025 
1026     void setModifiedOnDiskWarning(bool on) override;
1027 
1028 public Q_SLOTS:
1029     /**
1030      * Ask the user what to do, if the file has been modified on disk.
1031      * Reimplemented from KTextEditor::Document.
1032      */
1033     virtual void slotModifiedOnDisk(KTextEditor::View *v = nullptr);
1034 
1035     /**
1036      * Reloads the current document from disk if possible
1037      */
1038     bool documentReload() override;
1039 
1040     bool documentSave() override;
1041     bool documentSaveAs() override;
1042     bool documentSaveAsWithEncoding(const QString &encoding);
1043     void documentSaveCopyAs();
1044 
1045     bool save() override;
1046 
1047 public:
1048     bool saveAs(const QUrl &url) override;
1049 
1050 Q_SIGNALS:
1051     /**
1052      * Indicate this file is modified on disk
1053      * @param doc the KTextEditor::Document object that represents the file on disk
1054      * @param isModified indicates the file was modified rather than created or deleted
1055      * @param reason the reason we are emitting the signal.
1056      */
1057     void modifiedOnDisk(KTextEditor::Document *doc, bool isModified, KTextEditor::ModificationInterface::ModifiedOnDiskReason reason) override;
1058 
1059 private:
1060     // helper to handle the embedded notification for externally modified files
1061     QPointer<KateModOnHdPrompt> m_modOnHdHandler;
1062 
1063 private Q_SLOTS:
1064     void onModOnHdSaveAs();
1065     void onModOnHdClose();
1066     void onModOnHdReload();
1067     void onModOnHdAutoReload();
1068     void onModOnHdIgnore();
1069 
1070 public:
1071     bool setEncoding(const QString &e) override;
1072     QString encoding() const override;
1073 
1074 public Q_SLOTS:
1075     void setWordWrap(bool on);
1076     void setWordWrapAt(uint col);
1077 
1078 public:
1079     bool wordWrap() const;
1080     uint wordWrapAt() const;
1081 
1082 public Q_SLOTS:
1083     void setPageUpDownMovesCursor(bool on);
1084 
1085 public:
1086     bool pageUpDownMovesCursor() const;
1087 
1088     // code folding
1089 public:
1090     /**
1091      * Same as plainKateTextLine(), except that it is made sure
1092      * the line is highlighted.
1093      */
1094     Kate::TextLine kateTextLine(int i);
1095 
1096     //! @copydoc KateBuffer::plainLine()
1097     Kate::TextLine plainKateTextLine(int i);
1098 
1099 Q_SIGNALS:
1100     void aboutToRemoveText(KTextEditor::Range);
1101 
1102 private Q_SLOTS:
1103     void slotModOnHdDirty(const QString &path);
1104     void slotModOnHdCreated(const QString &path);
1105     void slotModOnHdDeleted(const QString &path);
1106     void slotDelayedHandleModOnHd();
1107 
1108 private:
1109     /**
1110      * Create a git compatible sha1 checksum of the file, if it is a local file.
1111      * The result can be accessed through KateBuffer::digest().
1112      *
1113      * @return whether the operation was attempted and succeeded.
1114      */
1115     bool createDigest();
1116     // exported for katedocument_test
1117 
1118     /**
1119      * create a string for the modonhd warnings, giving the reason.
1120      */
1121     KTEXTEDITOR_NO_EXPORT
1122     QString reasonedMOHString() const;
1123 
1124     /**
1125      * Removes all trailing whitespace in the document and add new line at eof
1126      * if configured that way.
1127      */
1128     KTEXTEDITOR_NO_EXPORT
1129     void removeTrailingSpacesAndAddNewLineAtEof();
1130 
1131 public:
1132     /**
1133      * Returns a git compatible sha1 checksum of this document on disk.
1134      * @return checksum for this document on disk
1135      */
1136     QByteArray checksum() const override;
1137 
1138     /**
1139      * @return false if @p newType is an invalid mode.
1140      */
1141     bool updateFileType(const QString &newType, bool user = false);
1142 
1143     QString fileType() const
1144     {
1145         return m_fileType;
1146     }
1147 
1148     /**
1149      * Get access to buffer of this document.
1150      * Is needed to create cursors and ranges for example.
1151      * @return document buffer
1152      */
1153     KateBuffer &buffer()
1154     {
1155         return *m_buffer;
1156     }
1157 
1158     /**
1159      * set indentation mode by user
1160      * this will remember that a user did set it and will avoid reset on save
1161      */
1162     void rememberUserDidSetIndentationMode()
1163     {
1164         m_indenterSetByUser = true;
1165     }
1166 
1167     /**
1168      * User did set encoding for next reload => enforce it!
1169      */
1170     void userSetEncodingForNextReload()
1171     {
1172         m_userSetEncodingForNextReload = true;
1173     }
1174 
1175     //
1176     // REALLY internal data ;)
1177     //
1178 private:
1179     // text buffer
1180     KateBuffer *const m_buffer;
1181 
1182     // indenter
1183     KateAutoIndent *const m_indenter;
1184 
1185     bool m_hlSetByUser = false;
1186     bool m_bomSetByUser = false;
1187     bool m_indenterSetByUser = false;
1188     bool m_userSetEncodingForNextReload = false;
1189 
1190     bool m_modOnHd = false;
1191     KToggleAction *m_autoReloadMode;
1192     QTimer m_autoReloadThrottle;
1193     ModifiedOnDiskReason m_modOnHdReason = OnDiskUnmodified;
1194     ModifiedOnDiskReason m_prevModOnHdReason = OnDiskUnmodified;
1195 
1196     QString m_docName;
1197     int m_docNameNumber = 0;
1198 
1199     // file type !!!
1200     QString m_fileType;
1201     bool m_fileTypeSetByUser = false;
1202 
1203     /**
1204      * document is still reloading a file
1205      */
1206     bool m_reloading = false;
1207 
1208 public Q_SLOTS:
1209     void slotQueryClose_save(bool *handled, bool *abortClosing);
1210 
1211 public:
1212     bool queryClose() override;
1213 
1214     /**
1215      * Configuration
1216      */
1217 public:
1218     KateDocumentConfig *config()
1219     {
1220         return m_config.get();
1221     }
1222     KateDocumentConfig *config() const
1223     {
1224         return m_config.get();
1225     }
1226 
1227     void updateConfig();
1228 
1229 private:
1230     KTEXTEDITOR_NO_EXPORT
1231     void makeAttribs(bool needInvalidate = true);
1232 
1233     std::unique_ptr<KateDocumentConfig> const m_config;
1234 
1235     /**
1236      * Variable Reader
1237      * TODO add register functionality/ktexteditor interface
1238      */
1239 private:
1240     /**
1241      * read dir config file
1242      */
1243     KTEXTEDITOR_NO_EXPORT
1244     void readDirConfig();
1245 
1246     /**
1247       Reads all the variables in the document.
1248       Called when opening/saving a document
1249     */
1250     KTEXTEDITOR_NO_EXPORT
1251     void readVariables(bool onlyViewAndRenderer = false);
1252 
1253     /**
1254       Reads and applies the variables in a single line
1255       TODO registered variables gets saved in a [map]
1256     */
1257     void readVariableLine(const QString &t, bool onlyViewAndRenderer = false);
1258     // exported for katedocument_test
1259     /**
1260       Sets a view variable in all the views.
1261     */
1262     KTEXTEDITOR_NO_EXPORT
1263     void setViewVariable(const QString &var, const QString &val);
1264     /**
1265       @return weather a string value could be converted
1266       to a bool value as supported.
1267       The value is put in *result.
1268     */
1269     KTEXTEDITOR_NO_EXPORT
1270     static bool checkBoolValue(QString value, bool *result);
1271     /**
1272       @return weather a string value could be converted
1273       to a integer value.
1274       The value is put in *result.
1275     */
1276     KTEXTEDITOR_NO_EXPORT
1277     static bool checkIntValue(const QString &value, int *result);
1278     /**
1279       Feeds value into @p col using QColor::setNamedColor() and returns
1280       whether the color is valid
1281     */
1282     KTEXTEDITOR_NO_EXPORT
1283     static bool checkColorValue(const QString &value, QColor &col);
1284 
1285     bool m_fileChangedDialogsActivated = false;
1286 
1287     //
1288     // KTextEditor::ConfigInterface
1289     //
1290 public:
1291     QStringList configKeys() const override;
1292     QVariant configValue(const QString &key) override;
1293     void setConfigValue(const QString &key, const QVariant &value) override;
1294 
1295     //
1296     // KTextEditor::RecoveryInterface
1297     //
1298 public:
1299     bool isDataRecoveryAvailable() const override;
1300     void recoverData() override;
1301     void discardDataRecovery() override;
1302 
1303     //
1304     // Highlighting information
1305     //
1306 public:
1307     QStringList embeddedHighlightingModes() const override;
1308     QString highlightingModeAt(const KTextEditor::Cursor &position) override;
1309 
1310     //
1311     // BEGIN: KTextEditor::MessageInterface
1312     //
1313 public:
1314     bool postMessage(KTextEditor::Message *message) override;
1315 
1316 public Q_SLOTS:
1317     void messageDestroyed(KTextEditor::Message *message);
1318 
1319 private:
1320     QHash<KTextEditor::Message *, QList<QSharedPointer<QAction>>> m_messageHash;
1321     // END KTextEditor::MessageInterface
1322 
1323 public:
1324     QString defaultDictionary() const;
1325     QList<QPair<KTextEditor::MovingRange *, QString>> dictionaryRanges() const;
1326     bool isOnTheFlySpellCheckingEnabled() const;
1327     KateOnTheFlyChecker *onTheFlySpellChecker() const
1328     {
1329         return m_onTheFlyChecker;
1330     }
1331 
1332     QString dictionaryForMisspelledRange(KTextEditor::Range range) const;
1333     void clearMisspellingForWord(const QString &word);
1334 
1335 public Q_SLOTS:
1336     void clearDictionaryRanges();
1337     void setDictionary(const QString &dict, KTextEditor::Range range, bool blockmode);
1338     void setDictionary(const QString &dict, KTextEditor::Range range);
1339     void setDefaultDictionary(const QString &dict);
1340     void onTheFlySpellCheckingEnabled(bool enable);
1341     void refreshOnTheFlyCheck(KTextEditor::Range range = KTextEditor::Range::invalid());
1342 
1343 Q_SIGNALS:
1344     void dictionaryRangesPresent(bool yesNo);
1345     void defaultDictionaryChanged(KTextEditor::DocumentPrivate *document);
1346 
1347 public:
1348     bool containsCharacterEncoding(KTextEditor::Range range);
1349 
1350     typedef QList<QPair<int, int>> OffsetList;
1351 
1352     static int computePositionWrtOffsets(const OffsetList &offsetList, int pos);
1353 
1354     /**
1355      * The first OffsetList is from decoded to encoded, and the second OffsetList from
1356      * encoded to decoded.
1357      **/
1358     QString decodeCharacters(KTextEditor::Range range,
1359                              KTextEditor::DocumentPrivate::OffsetList &decToEncOffsetList,
1360                              KTextEditor::DocumentPrivate::OffsetList &encToDecOffsetList);
1361     void replaceCharactersByEncoding(KTextEditor::Range range);
1362 
1363 protected:
1364     KateOnTheFlyChecker *m_onTheFlyChecker = nullptr;
1365     QString m_defaultDictionary;
1366     QList<QPair<KTextEditor::MovingRange *, QString>> m_dictionaryRanges;
1367 
1368     // from KTextEditor::MovingRangeFeedback
1369     void rangeInvalid(KTextEditor::MovingRange *movingRange) override;
1370     void rangeEmpty(KTextEditor::MovingRange *movingRange) override;
1371 
1372     void deleteDictionaryRange(KTextEditor::MovingRange *movingRange);
1373 
1374 private:
1375     Kate::SwapFile *m_swapfile;
1376 
1377 public:
1378     Kate::SwapFile *swapFile();
1379 
1380     // helpers for scripting and codefolding
1381     int defStyleNum(int line, int column);
1382     bool isComment(int line, int column);
1383 
1384 public:
1385     /**
1386      * Find the next modified/saved line, starting at @p startLine. If @p down
1387      * is \e true, the search is performed downwards, otherwise upwards.
1388      * @return the touched line in the requested search direction, or -1 if not found
1389      */
1390     int findTouchedLine(int startLine, bool down);
1391 
1392 private Q_SLOTS:
1393     /**
1394      * watch for all started io jobs to remember if file is perhaps loading atm
1395      * @param job started job
1396      */
1397     void slotStarted(KIO::Job *job);
1398     void slotCompleted();
1399     void slotCanceled();
1400 
1401     /**
1402      * trigger display of loading message, after 1000 ms
1403      */
1404     void slotTriggerLoadingMessage();
1405 
1406     /**
1407      * Abort loading
1408      */
1409     void slotAbortLoading();
1410 
1411     void slotUrlChanged(const QUrl &url);
1412 
1413 private:
1414     /**
1415      * different possible states
1416      */
1417     enum DocumentStates {
1418         /**
1419          * Idle
1420          */
1421         DocumentIdle,
1422 
1423         /**
1424          * Loading
1425          */
1426         DocumentLoading,
1427 
1428         /**
1429          * Saving
1430          */
1431         DocumentSaving,
1432 
1433         /**
1434          * Pre Saving As, this is between ::saveAs is called and ::save
1435          */
1436         DocumentPreSavingAs,
1437 
1438         /**
1439          * Saving As
1440          */
1441         DocumentSavingAs
1442     };
1443 
1444     /**
1445      * current state
1446      */
1447     DocumentStates m_documentState = DocumentIdle;
1448 
1449     /**
1450      * read-write state before loading started
1451      */
1452     bool m_readWriteStateBeforeLoading = false;
1453 
1454     /**
1455      * if the document is untitled
1456      */
1457     bool m_isUntitled = true;
1458     /**
1459      * loading job, we want to cancel with cancel in the loading message
1460      */
1461     QPointer<KJob> m_loadingJob;
1462 
1463     /**
1464      * message to show during loading
1465      */
1466     QPointer<KTextEditor::Message> m_loadingMessage;
1467 
1468     /**
1469      * Was there any open error on last file loading?
1470      */
1471     bool m_openingError = false;
1472 
1473     /**
1474      * Last open file error message
1475      */
1476     QString m_openingErrorMessage;
1477 
1478 public:
1479     /**
1480      * reads the line length limit from config, if it is not overridden
1481      */
1482     int lineLengthLimit() const;
1483 
1484 public Q_SLOTS:
1485     void openWithLineLengthLimitOverride();
1486 
1487 private:
1488     /**
1489      * timer for delayed handling of mod on hd
1490      */
1491     QTimer m_modOnHdTimer;
1492 
1493 private:
1494     /**
1495      * currently active template handler; there can be only one
1496      */
1497     QPointer<KateTemplateHandler> m_activeTemplateHandler;
1498 
1499 private:
1500     /**
1501      * current autobrace range
1502      */
1503     std::unique_ptr<KTextEditor::MovingRange> m_currentAutobraceRange;
1504     /**
1505      * current autobrace closing character (e.g. ']')
1506      */
1507     QChar m_currentAutobraceClosingChar;
1508 
1509 private Q_SLOTS:
1510     void checkCursorForAutobrace(KTextEditor::View *view, const KTextEditor::Cursor newPos);
1511 
1512 public:
1513     void setActiveTemplateHandler(KateTemplateHandler *handler);
1514 
1515 Q_SIGNALS:
1516     void loaded(KTextEditor::DocumentPrivate *document);
1517 
1518 private:
1519     // To calculate a QHash.keys() is quite expensive,
1520     // better keep a copy of that list updated when a view is added or removed.
1521     QList<KTextEditor::View *> m_viewsCache;
1522 
1523     QTimer m_autoSaveTimer;
1524 };
1525 
1526 #endif