mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-24 10:52:51 +00:00
377 lines
12 KiB
C++
377 lines
12 KiB
C++
/* This file is part of the Kate project.
|
|
*
|
|
* Copyright (C) 2013 Christoph Cullmann <cullmann@kde.org>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#ifndef KATE_TEXTFOLDING_H
|
|
#define KATE_TEXTFOLDING_H
|
|
|
|
#include "katepartinterfaces_export.h"
|
|
|
|
#include "ktexteditor/range.h"
|
|
|
|
#include <QObject>
|
|
#include <QVariant>
|
|
|
|
namespace Kate {
|
|
|
|
class TextBuffer;
|
|
class TextCursor;
|
|
|
|
/**
|
|
* Class representing the folding information for a TextBuffer.
|
|
* The interface allows to arbitrary fold given regions of a buffer as long
|
|
* as they are well nested.
|
|
* Multiple instances of this class can exist for the same buffer.
|
|
*/
|
|
class KATEPARTINTERFACES_EXPORT TextFolding : public QObject {
|
|
Q_OBJECT
|
|
|
|
public:
|
|
/**
|
|
* Create folding object for given buffer.
|
|
* @param buffer text buffer we want to provide folding info for
|
|
*/
|
|
TextFolding (TextBuffer &buffer);
|
|
|
|
/**
|
|
* Cleanup
|
|
*/
|
|
~TextFolding ();
|
|
|
|
/**
|
|
* Folding state of a range
|
|
*/
|
|
enum FoldingRangeFlag {
|
|
/**
|
|
* Range is persistent, e.g. it should not auto-delete after unfolding!
|
|
*/
|
|
Persistent = 0x1,
|
|
|
|
/**
|
|
* Range is folded away
|
|
*/
|
|
Folded = 0x2
|
|
};
|
|
Q_DECLARE_FLAGS(FoldingRangeFlags, FoldingRangeFlag)
|
|
|
|
/**
|
|
* Create a new folding range.
|
|
* @param range folding range
|
|
* @param flags initial flags for the new folding range
|
|
* @return on success, id of new range >= 0, else -1, we return no pointer as folding ranges might be auto-deleted internally!
|
|
* the ids are stable for one Kate::TextFolding, e.g. you can rely in unit tests that you get 0,1,.... for successfully created ranges!
|
|
*/
|
|
qint64 newFoldingRange (const KTextEditor::Range &range, FoldingRangeFlags flags = FoldingRangeFlags());
|
|
|
|
/**
|
|
* Returns the folding range associated with @p id.
|
|
* If @p id is not a valid id, the returned range matches KTextEditor::Range::invalid().
|
|
* @note This works for either persistend ranges or folded ranges.
|
|
* Note, that the highlighting does not add folds unless text is folded.
|
|
*
|
|
* @return the folding range for @p id
|
|
*/
|
|
KTextEditor::Range foldingRange(qint64 id) const;
|
|
|
|
/**
|
|
* Fold the given range.
|
|
* @param id id of the range to fold
|
|
* @return success
|
|
*/
|
|
bool foldRange (qint64 id);
|
|
|
|
/**
|
|
* Unfold the given range.
|
|
* In addition it can be forced to remove the region, even if it is persistent.
|
|
* @param id id of the range to unfold
|
|
* @param remove should the range be removed from the folding after unfolding? ranges that are not persistent auto-remove themself on unfolding
|
|
* @return success
|
|
*/
|
|
bool unfoldRange (qint64 id, bool remove = false);
|
|
|
|
/**
|
|
* Query if a given line is visible.
|
|
* Very fast, if nothing is folded, else does binary search
|
|
* log(n) for n == number of folded ranges
|
|
* @param line line to query
|
|
* @param foldedRangeId if the line is not visible and that pointer is not 0, will be filled with id of range hiding the line or -1
|
|
* @return is that line visible?
|
|
*/
|
|
bool isLineVisible (int line, qint64 *foldedRangeId = 0) const;
|
|
|
|
/**
|
|
* Ensure that a given line will be visible.
|
|
* Potentially unfold recursively all folds hiding this line, else just returns.
|
|
* @param line line to make visible
|
|
*/
|
|
void ensureLineIsVisible (int line);
|
|
|
|
/**
|
|
* Query number of visible lines.
|
|
* Very fast, if nothing is folded, else walks over all folded regions
|
|
* O(n) for n == number of folded ranges
|
|
*/
|
|
int visibleLines () const;
|
|
|
|
/**
|
|
* Convert a text buffer line to a visible line number.
|
|
* Very fast, if nothing is folded, else walks over all folded regions
|
|
* O(n) for n == number of folded ranges
|
|
* @param line line index in the text buffer
|
|
* @return index in visible lines
|
|
*/
|
|
int lineToVisibleLine (int line) const;
|
|
|
|
/**
|
|
* Convert a visible line number to a line number in the text buffer.
|
|
* Very fast, if nothing is folded, else walks over all folded regions
|
|
* O(n) for n == number of folded ranges
|
|
* @param visibleLine visible line index
|
|
* @return index in text buffer lines
|
|
*/
|
|
int visibleLineToLine (int visibleLine) const;
|
|
|
|
/**
|
|
* Queries which folding ranges start at the given line and returns the id + flags for all
|
|
* of them. Very fast if nothing is folded, else binary search.
|
|
* @param line line to query starting folding ranges
|
|
* @return vector of id's + flags
|
|
*/
|
|
QVector<QPair<qint64, FoldingRangeFlags> > foldingRangesStartingOnLine (int line) const;
|
|
|
|
/**
|
|
* Return the current known folding ranges a QVariantList to store in configs.
|
|
* @return current folds as variant list
|
|
*/
|
|
QVariantList exportFoldingRanges () const;
|
|
|
|
/**
|
|
* Import the folding ranges given as a QVariantList like read from configs.
|
|
* @param folds list of folds to import
|
|
*/
|
|
void importFoldingRanges (const QVariantList &folds);
|
|
|
|
/**
|
|
* Dump folding state as string, for unit testing and debugging
|
|
* @return current state as text
|
|
*/
|
|
QString debugDump () const;
|
|
|
|
/**
|
|
* Print state to stdout for testing
|
|
*/
|
|
void debugPrint (const QString &title) const;
|
|
|
|
public Q_SLOTS:
|
|
/**
|
|
* Clear the complete folding.
|
|
* This is automatically triggered if the buffer is cleared.
|
|
*/
|
|
void clear ();
|
|
|
|
Q_SIGNALS:
|
|
/**
|
|
* If the folding state of existing ranges changes or
|
|
* ranges are added/removed, this signal is emitted.
|
|
*/
|
|
void foldingRangesChanged ();
|
|
|
|
private:
|
|
/**
|
|
* Data holder for text folding range and its nested children
|
|
*/
|
|
class FoldingRange {
|
|
public:
|
|
/**
|
|
* Construct new one
|
|
* @param buffer text buffer to use
|
|
* @param range folding range
|
|
* @param flags flags for the new folding range
|
|
*/
|
|
FoldingRange (TextBuffer &buffer, const KTextEditor::Range &range, FoldingRangeFlags flags);
|
|
|
|
/**
|
|
* Cleanup
|
|
*/
|
|
~FoldingRange ();
|
|
|
|
/**
|
|
* Vector of range pointers
|
|
*/
|
|
typedef QVector<FoldingRange*> Vector;
|
|
|
|
/**
|
|
* start moving cursor
|
|
* NO range to be more efficient
|
|
*/
|
|
Kate::TextCursor *start;
|
|
|
|
/**
|
|
* end moving cursor
|
|
* NO range to be more efficient
|
|
*/
|
|
Kate::TextCursor *end;
|
|
|
|
/**
|
|
* parent range, if any
|
|
*/
|
|
FoldingRange *parent;
|
|
|
|
/**
|
|
* nested ranges, if any
|
|
* this will always be sorted and non-overlapping
|
|
* nested ranges are inside these ranges
|
|
*/
|
|
FoldingRange::Vector nestedRanges;
|
|
|
|
/**
|
|
* Folding range flags
|
|
*/
|
|
FoldingRangeFlags flags;
|
|
|
|
/**
|
|
* id of this range
|
|
*/
|
|
qint64 id;
|
|
};
|
|
|
|
/**
|
|
* Fill known folding ranges in a QVariantList to store in configs.
|
|
* @param ranges ranges vector to dump
|
|
* @param folds current folds as variant list, will be filled
|
|
*/
|
|
static void exportFoldingRanges (const TextFolding::FoldingRange::Vector &ranges, QVariantList &folds);
|
|
|
|
/**
|
|
* Dump folding state of given vector as string, for unit testing and debugging.
|
|
* Will recurse if wanted.
|
|
* @param ranges ranges vector to dump
|
|
* @param recurse recurse to nestedRanges?
|
|
* @return current state as text
|
|
*/
|
|
static QString debugDump (const TextFolding::FoldingRange::Vector &ranges, bool recurse);
|
|
|
|
/**
|
|
* Helper to insert folding range into existing ones.
|
|
* Might fail, if not correctly nested.
|
|
* Then the outside must take care of the passed pointer, e.g. delete it.
|
|
* Will sanitize the ranges vectors, purge invalid/empty ranges.
|
|
* @param parent parent folding range if any
|
|
* @param existingRanges ranges into which we want to insert the new one
|
|
* @param newRange new folding range
|
|
* @return success, if false, newRange should be deleted afterwards, else it is registered internally
|
|
*/
|
|
bool insertNewFoldingRange (FoldingRange *parent, TextFolding::FoldingRange::Vector &existingRanges, TextFolding::FoldingRange *newRange);
|
|
|
|
/**
|
|
* Helper to update the folded ranges if we insert a new range into the tree.
|
|
* @param newRange new folding range that was inserted, will already contain its new nested ranges, if any!
|
|
* @return any updated done? if yes, the foldingRangesChanged() signal got emitted!
|
|
*/
|
|
bool updateFoldedRangesForNewRange (TextFolding::FoldingRange *newRange);
|
|
|
|
/**
|
|
* Helper to update the folded ranges if we remove a new range from the tree.
|
|
* @param oldRange new folding range that is removed, will still contain its new nested ranges, if any!
|
|
* @return any updated done? if yes, the foldingRangesChanged() signal got emitted!
|
|
*/
|
|
bool updateFoldedRangesForRemovedRange (TextFolding::FoldingRange *oldRange);
|
|
|
|
/**
|
|
* Helper to append recursively topmost folded ranges from input to output vector.
|
|
* @param newFoldedFoldingRanges output vector for folded ranges
|
|
* @param ranges input vector to search recursively folded ranges inside
|
|
*/
|
|
void appendFoldedRanges (TextFolding::FoldingRange::Vector &newFoldedFoldingRanges, const TextFolding::FoldingRange::Vector &ranges) const;
|
|
|
|
/**
|
|
* Compare two ranges by their start cursor.
|
|
* @param a first range
|
|
* @param b second range
|
|
*/
|
|
static bool compareRangeByStart (FoldingRange *a, FoldingRange *b);
|
|
|
|
/**
|
|
* Compare two ranges by their end cursor.
|
|
* @param a first range
|
|
* @param b second range
|
|
*/
|
|
static bool compareRangeByEnd (FoldingRange *a, FoldingRange *b);
|
|
|
|
/**
|
|
* Compare range start with line
|
|
* @param line line
|
|
* @param range range
|
|
*/
|
|
static bool compareRangeByStartWithLine (int line, FoldingRange *range);
|
|
|
|
/**
|
|
* Compare range start with line
|
|
* @param range range
|
|
* @param line line
|
|
*/
|
|
static bool compareRangeByLineWithStart (FoldingRange *range, int line);
|
|
|
|
/**
|
|
* Internal helper that queries which folding ranges start at the given line and returns the id + flags for all
|
|
* of them. Will recursively dive down starting with given vector
|
|
* @param results vector that is filled with id's + flags
|
|
* @param ranges ranges vector to search in
|
|
* @param line line to query starting folding ranges
|
|
*/
|
|
void foldingRangesStartingOnLine (QVector<QPair<qint64, FoldingRangeFlags> > &results, const TextFolding::FoldingRange::Vector &ranges, int line) const;
|
|
|
|
private:
|
|
/**
|
|
* parent text buffer
|
|
* is a reference, and no pointer, as this must always exist and can't change
|
|
* can't be const, as we create text cursors!
|
|
*/
|
|
TextBuffer &m_buffer;
|
|
|
|
/**
|
|
* toplevel folding ranges
|
|
* this will always be sorted and non-overlapping
|
|
* nested ranges are inside these ranges
|
|
*/
|
|
FoldingRange::Vector m_foldingRanges;
|
|
|
|
/**
|
|
* folded folding ranges
|
|
* this is a sorted vector of ranges
|
|
* all non-overlapping
|
|
*/
|
|
FoldingRange::Vector m_foldedFoldingRanges;
|
|
|
|
/**
|
|
* global id counter for the created ranges
|
|
*/
|
|
qint64 m_idCounter;
|
|
|
|
/**
|
|
* mapping: id => range
|
|
*/
|
|
QHash<qint64, FoldingRange *> m_idToFoldingRange;
|
|
};
|
|
|
|
}
|
|
|
|
Q_DECLARE_OPERATORS_FOR_FLAGS(Kate::TextFolding::FoldingRangeFlags)
|
|
|
|
#endif
|