interfaces: remove unused smart KTextEditor interface classes

replaced with not so smart classes? (see comments in the headers)

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2023-06-28 06:11:00 +03:00
parent f1a36b91e5
commit c3bc63f0f1
31 changed files with 6 additions and 3766 deletions

View file

@ -458,13 +458,6 @@ install(
KTextEditor/Range
KTextEditor/SearchInterface
KTextEditor/SessionConfigInterface
KTextEditor/SmartCursor
KTextEditor/SmartCursorNotifier
KTextEditor/SmartCursorWatcher
KTextEditor/SmartInterface
KTextEditor/SmartRange
KTextEditor/SmartRangeNotifier
KTextEditor/SmartRangeWatcher
KTextEditor/TemplateInterface
KTextEditor/TextHintInterface
KTextEditor/VariableInterface

View file

@ -1 +0,0 @@
#include "../../ktexteditor/smartcursor.h"

View file

@ -1 +0,0 @@
#include "../../ktexteditor/cursorfeedback.h"

View file

@ -1 +0,0 @@
#include "../../ktexteditor/cursorfeedback.h"

View file

@ -1 +0,0 @@
#include "../../ktexteditor/smartinterface.h"

View file

@ -1 +0,0 @@
#include "../../ktexteditor/smartrange.h"

View file

@ -1 +0,0 @@
#include "../../ktexteditor/rangefeedback.h"

View file

@ -1 +0,0 @@
#include "../../ktexteditor/rangefeedback.h"

View file

@ -16,15 +16,10 @@ set(ktexteditor_LIB_SRCS
templateinterface.cpp
editorchooser.cpp
attribute.cpp
cursorfeedback.cpp
rangefeedback.cpp
smartcursor.cpp
smartrange.cpp
codecompletioninterface.cpp
codecompletionmodel.cpp
codecompletionmodelcontrollerinterface.cpp
configinterface.cpp
smartinterface.cpp
highlightinterface.cpp
movinginterface.cpp
movingcursor.cpp
@ -76,16 +71,7 @@ install(
templateinterface.h
modificationinterface.h
commandinterface.h
smartinterface.h
attribute.h
cursorfeedback.h
rangefeedback.h
smartcursor.h
smartcursornotifier.h
smartcursorwatcher.h
smartrange.h
smartrangenotifier.h
smartrangewatcher.h
codecompletioninterface.h
codecompletionmodel.h
codecompletionmodelcontrollerinterface.h

View file

@ -30,8 +30,6 @@ class KAction;
namespace KTextEditor
{
class SmartRange;
/**
* \brief A class which provides customized text decorations.
*
@ -53,14 +51,11 @@ class SmartRange;
* redrawn. Once you have finished changing properties, you should
* call changed() to force redrawing of affected ranges of text.
*
* \sa SmartInterface
*
* \author Hamish Rodda \<rodda@kde.org\>
*/
class KTEXTEDITOR_EXPORT Attribute : public QTextCharFormat, public QSharedData
{
friend class SmartRange;
public:
typedef KSharedPtr<Attribute> Ptr;
@ -326,20 +321,6 @@ class KTEXTEDITOR_EXPORT Attribute : public QTextCharFormat, public QSharedData
*/
Attribute& operator=(const Attribute& a);
protected:
/**
* \internal
* Add a range using this attribute.
* \param range range using this attribute.
*
void addRange(SmartRange* range);
**
* \internal
* Remove a range which is no longer using this attribute.
* \param range range no longer using this attribute.
*
void removeRange(SmartRange* range);*/
private:
class AttributePrivate* const d;
};

View file

@ -21,7 +21,6 @@
#define KDELIBS_KTEXTEDITOR_CODECOMPLETIONMODELCONTROLLERINTERFACE_H
#include <ktexteditor/ktexteditor_export.h>
#include <ktexteditor/smartrange.h>
#include <ktexteditor/cursor.h>
#include "codecompletionmodel.h"
@ -112,9 +111,6 @@ public:
*
* The default implementation does nothing.
*
* The smart-mutex is not locked when this is called.
* @warning Make sure you lock it before you change the range
*
* \param view The view to generate completions for
* \param range Reference to the current range
* \returns the modified range
@ -128,8 +124,6 @@ public:
* The default implementation will return the text from \p range start to
* the cursor \p position.
*
* The smart-mutex is not locked when this is called.
*
* \param view The view to generate completions for
* \param range The completion range
* \param position Current cursor position
@ -143,8 +137,6 @@ public:
*
* The default implementation will return true when any special character was entered, or when the range is empty.
*
* The smart-mutex is not locked when this is called.
*
* \param view The view to generate completions for
* \param range The completion range
* \param currentCompletion The text typed so far

View file

@ -106,11 +106,6 @@ void Cursor::setPosition( const Cursor & pos )
cursorChangedDirectly(old);
}
bool Cursor::isSmartCursor( ) const
{
return false;
}
void Cursor::setPosition(int line, int column)
{
setPosition(Cursor(line, column));
@ -155,9 +150,4 @@ bool KTextEditor::Cursor::atStartOfDocument( ) const
return line() == 0 && m_column == 0;
}
SmartCursor * KTextEditor::Cursor::toSmartCursor( ) const
{
return 0L;
}
// kate: space-indent on; indent-width 2; replace-tabs on;

View file

@ -31,7 +31,6 @@ namespace KTextEditor
{
class Document;
class Range;
class SmartCursor;
/**
* \short An object which represents a position in a Document.
@ -40,12 +39,7 @@ class SmartCursor;
* in a Document. It is very lightweight and maintains no affiliation with a
* particular Document.
*
* If you want additional functionality such as the ability to maintain position
* in a document, see SmartCursor.
*
* \note The Cursor class is designed to be passed via value, while SmartCursor
* and derivatives must be passed via pointer or reference as they maintain a
* connection with their document internally and cannot be copied.
* \note The Cursor class is designed to be passed via value.
*
* \note Lines and columns start at 0.
*
@ -56,7 +50,6 @@ class SmartCursor;
* whenever the cursor (i.e. start or end position) changes its position.
* Read the class documentation about Range%s for further details.
*
* \sa SmartCursor
*/
class KTEXTEDITOR_EXPORT Cursor
{
@ -93,22 +86,9 @@ class KTEXTEDITOR_EXPORT Cursor
/**
* Returns whether the current position of this cursor is a valid position
* (line + column must both be >= 0).
*
* Smart cursors should override this to return whether the cursor is valid
* within the linked document.
*/
virtual bool isValid() const;
/**
* Returns whether this cursor is a SmartCursor.
*/
virtual bool isSmartCursor() const;
/**
* Returns this cursor as a SmartCursor, if it is one.
*/
virtual SmartCursor* toSmartCursor() const;
/**
* Returns an invalid cursor.
*/
@ -129,8 +109,6 @@ class KTEXTEDITOR_EXPORT Cursor
* Set the current cursor position to \e position.
*
* \param position new cursor position
*
* \todo add bool to indicate success or not, for smart cursors?
*/
virtual void setPosition(const Cursor& position);

View file

@ -1,81 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2003-2005 Hamish Rodda <rodda@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.
*/
#include "cursorfeedback.h"
using namespace KTextEditor;
SmartCursorWatcher::SmartCursorWatcher( )
: m_wantDirectChanges(true)
{
}
SmartCursorWatcher::~ SmartCursorWatcher( )
{
}
void SmartCursorWatcher::positionChanged( SmartCursor * )
{
}
void SmartCursorWatcher::positionDeleted( SmartCursor * )
{
}
void SmartCursorWatcher::characterDeleted( SmartCursor * , bool )
{
}
void SmartCursorWatcher::characterInserted( SmartCursor * , bool )
{
}
bool SmartCursorWatcher::wantsDirectChanges( ) const
{
return m_wantDirectChanges;
}
void SmartCursorWatcher::setWantsDirectChanges( bool wantsDirectChanges )
{
m_wantDirectChanges = wantsDirectChanges;
}
SmartCursorNotifier::SmartCursorNotifier( )
: m_wantDirectChanges(true)
{
}
bool SmartCursorNotifier::wantsDirectChanges( ) const
{
return m_wantDirectChanges;
}
void SmartCursorNotifier::setWantsDirectChanges( bool wantsDirectChanges )
{
m_wantDirectChanges = wantsDirectChanges;
}
void SmartCursorWatcher::deleted( SmartCursor * )
{
}
#include "moc_smartcursornotifier.cpp"
// kate: space-indent on; indent-width 2; replace-tabs on;

View file

@ -1,26 +0,0 @@
/* This file is part of the KDE libraries
Copyright (C) 2009 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
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 KDELIBS_KTEXTEDITOR_CURSORFEEDBACK_H
#define KDELIBS_KTEXTEDITOR_CURSORFEEDBACK_H
#include "smartcursornotifier.h"
#include "smartcursorwatcher.h"
#endif // KDELIBS_KTEXTEDITOR_CURSORFEEDBACK_H

View file

@ -104,8 +104,7 @@ class View;
* \see KParts::ReadWritePart, KTextEditor::Editor, KTextEditor::View,
* KTextEditor::MarkInterface,
* KTextEditor::ModificationInterface, KTextEditor::SearchInterface,
* KTextEditor::SessionConfigInterface, KTextEditor::SmartInterface,
* KTextEditor::VariableInterface
* KTextEditor::SessionConfigInterface, KTextEditor::VariableInterface
* \author Christoph Cullmann \<cullmann@kde.org\>
*/
class KTEXTEDITOR_EXPORT Document : public KParts::ReadWritePart
@ -501,7 +500,7 @@ class KTEXTEDITOR_EXPORT Document : public KParts::ReadWritePart
* It can optionally be overridden by an implementation.
* \param cursor which should be checked
* \return \e true, if the cursor is valid, otherwise \e false
* \see SmartCursor::isValid()
* \see Cursor::isValid()
*/
virtual bool cursorInText(const Cursor &cursor);

View file

@ -283,16 +283,6 @@ void KTextEditor::Range::setBothColumns( int column )
setRange(Range(start().line(), column, end().line(), column));
}
bool KTextEditor::Range::isSmartRange( ) const
{
return false;
}
SmartRange* KTextEditor::Range::toSmartRange( ) const
{
return 0L;
}
Cursor& KTextEditor::Range::start()
{
return *m_start;

View file

@ -30,7 +30,6 @@
namespace KTextEditor
{
class SmartRange;
/**
* \short An object representing a section of text, from one Cursor to another.
@ -45,9 +44,9 @@ class SmartRange;
* start and end will be swapped if necessary.
*
* If you want additional functionality such as the ability to maintain position
* in a document, see SmartRange.
* in a document, see Range.
*
* \sa SmartRange
* \sa Range
*
* \author Hamish Rodda \<rodda@kde.org\>
*/
@ -122,16 +121,6 @@ class KTEXTEDITOR_EXPORT Range
*/
static Range invalid();
/**
* Returns whether this range is a SmartRange.
*/
virtual bool isSmartRange() const;
/**
* Returns this range as a SmartRange, if it is one.
*/
virtual SmartRange* toSmartRange() const;
/**
* \name Position
*
@ -161,8 +150,6 @@ class KTEXTEDITOR_EXPORT Range
* Get the start position of this range. This will always be <= end().
*
* \returns a const reference to the start position of this range.
*
* \internal this function is virtual to allow for covariant return of SmartCursor%s.
*/
const Cursor& start() const;
@ -182,8 +169,6 @@ class KTEXTEDITOR_EXPORT Range
* \li any notifications needed will be performed multiple times for no benefit
*
* \returns a reference to the end position of this range.
*
* \internal this function is virtual to allow for covariant return of SmartCursor%s.
*/
Cursor& end();
@ -191,8 +176,6 @@ class KTEXTEDITOR_EXPORT Range
* Get the end position of this range. This will always be >= start().
*
* \returns a const reference to the end position of this range.
*
* \internal this function is virtual to allow for covariant return of SmartCursor%s.
*/
const Cursor& end() const;

View file

@ -1,112 +0,0 @@
/* This file is part of the KDE libraries
* Copyright (C) 2003-2005 Hamish Rodda <rodda@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.*/
#include "rangefeedback.h"
using namespace KTextEditor;
SmartRangeWatcher::~ SmartRangeWatcher( )
{
}
SmartRangeNotifier::SmartRangeNotifier( )
: m_wantDirectChanges(true)
{
}
bool SmartRangeNotifier::wantsDirectChanges( ) const
{
return m_wantDirectChanges;
}
void SmartRangeNotifier::setWantsDirectChanges( bool wantsDirectChanges )
{
m_wantDirectChanges = wantsDirectChanges;
}
SmartRangeWatcher::SmartRangeWatcher( )
: m_wantDirectChanges(true)
{
}
bool SmartRangeWatcher::wantsDirectChanges( ) const
{
return m_wantDirectChanges;
}
void SmartRangeWatcher::setWantsDirectChanges( bool wantsDirectChanges )
{
m_wantDirectChanges = wantsDirectChanges;
}
void SmartRangeWatcher::rangePositionChanged( SmartRange* )
{
}
void SmartRangeWatcher::rangeContentsChanged( SmartRange* )
{
}
void SmartRangeWatcher::rangeContentsChanged( SmartRange*, SmartRange* )
{
}
void SmartRangeWatcher::mouseEnteredRange( SmartRange*, View* )
{
}
void SmartRangeWatcher::mouseExitedRange( SmartRange*, View* )
{
}
void SmartRangeWatcher::caretEnteredRange( SmartRange*, View* )
{
}
void SmartRangeWatcher::caretExitedRange( SmartRange*, View* )
{
}
void SmartRangeWatcher::rangeEliminated( SmartRange* )
{
}
void SmartRangeWatcher::rangeDeleted( SmartRange* )
{
}
void SmartRangeWatcher::childRangeInserted( SmartRange*, SmartRange* )
{
}
void SmartRangeWatcher::childRangeRemoved( SmartRange*, SmartRange* )
{
}
void SmartRangeWatcher::rangeAttributeChanged( SmartRange*, Attribute::Ptr, Attribute::Ptr )
{
}
void SmartRangeWatcher::parentRangeChanged( SmartRange *, SmartRange *, SmartRange * )
{
}
#include "moc_smartrangenotifier.cpp"
// kate: space-indent on; indent-width 2; replace-tabs on;

View file

@ -1,25 +0,0 @@
/* This file is part of the KDE libraries
* Copyright (C) 2009 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
*
* 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 KDELIBS_KTEXTEDITOR_RANGEFEEDBACK_H
#define KDELIBS_KTEXTEDITOR_RANGEFEEDBACK_H
#include "smartrangenotifier.h"
#include "smartrangewatcher.h"
#endif // KDELIBS_KTEXTEDITOR_RANGEFEEDBACK_H

View file

@ -1,142 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2003-2005 Hamish Rodda <rodda@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 version 2 as published by the Free Software Foundation.
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.
*/
#include "smartcursor.h"
#include "document.h"
#include "smartrange.h"
using namespace KTextEditor;
SmartCursor::SmartCursor( const Cursor & position, Document * doc, InsertBehavior insertBehavior )
: Cursor(position)
, m_doc(doc)
, m_moveOnInsert(insertBehavior == MoveOnInsert)
{
Q_ASSERT(m_doc);
}
SmartCursor::~ SmartCursor( )
{
}
bool SmartCursor::isValid( ) const
{
return m_doc->cursorInText(*this);
}
bool SmartCursor::atEndOfDocument( ) const
{
return *this >= m_doc->documentEnd();
}
bool SmartCursor::isSmartCursor( ) const
{
return true;
}
bool SmartCursor::insertText( const QStringList & text, bool block )
{
return document()->insertText(*this, text, block);
}
QChar SmartCursor::character( ) const
{
return document()->character(*this);
}
SmartRange * SmartCursor::smartRange( ) const
{
return static_cast<SmartRange*>(m_range);
}
Document* SmartCursor::document() const
{
return m_doc;
}
bool SmartCursor::atEndOfLine( ) const
{
return column() == m_doc->lineLength(line());
}
SmartCursor::InsertBehavior SmartCursor::insertBehavior( ) const
{
return m_moveOnInsert ? MoveOnInsert : StayOnInsert;
}
void SmartCursor::setInsertBehavior( InsertBehavior insertBehavior )
{
m_moveOnInsert = insertBehavior == MoveOnInsert;
}
SmartCursor * SmartCursor::toSmartCursor( ) const
{
return const_cast<SmartCursor*>(this);
}
bool SmartCursor::advance(int distance, AdvanceMode mode)
{
Cursor c = *this;
if (mode == ByCharacter) {
while (distance) {
int lineLength = document()->lineLength(c.line());
if (distance > 0) {
int advance = qMin(lineLength - c.column(), distance);
if (distance > advance) {
if (c.line() + 1 >= document()->lines())
return false;
c.setPosition(c.line() + 1, 0);
// Account for end of line advancement
distance -= advance + 1;
} else {
c.setColumn(c.column() + distance);
distance = 0;
}
} else {
int back = qMin(c.column(), -distance);
if (-distance > back) {
if (c.line() - 1 < 0)
return false;
c.setPosition(c.line() - 1, document()->lineLength(c.line() - 1));
// Account for end of line advancement
distance += back + 1;
} else {
c.setColumn(c.column() + distance);
distance = 0;
}
}
}
} else {
// Not supported by the interface alone
return false;
}
setPosition(c);
return true;
}
// kate: space-indent on; indent-width 2; replace-tabs on;

View file

@ -1,319 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2003-2005 Hamish Rodda <rodda@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 version 2 as published by the Free Software Foundation.
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 KDELIBS_KTEXTEDITOR_SMARTCURSOR_H
#define KDELIBS_KTEXTEDITOR_SMARTCURSOR_H
#include <ktexteditor/ktexteditor_export.h>
#include <ktexteditor/cursor.h>
namespace KTextEditor
{
class SmartRange;
class SmartCursorWatcher;
class SmartCursorNotifier;
/**
* \short A Cursor which is bound to a specific Document, and maintains its position.
*
* \ingroup kte_group_smart_classes
*
* A SmartCursor is an extension of the basic Cursor class. It maintains its
* position in the document and provides a number of convenience methods,
* including those for accessing and manipulating the content of the associated
* Document. As a result of this, SmartCursor%s may not be copied, as they need
* to maintain a connection to the associated Document.
*
* To receive notifications when the position of the cursor changes, or other
* similar notifications, see either SmartCursorNotifier for QObject signal
* notification via notifier(), or SmartCursorWatcher for virtual inheritance
* notification via setWatcher().
*
* Create a new SmartCursor like this:
* \code
* // Retrieve the SmartInterface
* KTextEditor::SmartInterface* smart =
* qobject_cast<KTextEditor::SmartInterface*>( yourDocument );
*
* if ( smart ) {
* KTextEditor::SmartCursor* cursor = smart->newSmartCursor();
* }
* \endcode
*
* When finished with a SmartCursor, simply delete it.
*
* \sa Cursor, SmartCursorNotifier, SmartCursorWatcher, and SmartInterface.
*
* \author Hamish Rodda \<rodda@kde.org\>
*/
class KTEXTEDITOR_EXPORT SmartCursor : public Cursor
{
friend class SmartRange;
public:
/**
* Virtual destructor.
*
* Subclasses should call SmartCursorNotifier::deleted() and
* SmartCursorWatcher::deleted() methods \e before cleaning themselves up.
*/
virtual ~SmartCursor();
/**
* Returns that this cursor is a SmartCursor.
*/
virtual bool isSmartCursor() const;
/**
* Returns this cursor as a SmartCursor
*/
virtual SmartCursor* toSmartCursor() const;
/**
* Returns the range that this cursor belongs to, if any.
*
* \sa Cursor::range()
*/
SmartRange* smartRange() const;
//BEGIN Functionality present from having this cursor associated with a Document
/**
* \name Document-related functions
*
* The following functions are provided for convenient access to the
* associated Document.
* \{
*/
/**
* Returns the document to which this cursor is attached.
*/
Document* document() const;
/**
* Determine if this cursor is located at the end of the current line.
*
* \return \e true if the cursor is situated at the end of the line, otherwise \e false.
*/
virtual bool atEndOfLine() const;
/**
* Determine if this cursor is located at the end of the document.
*
* \return \e true if the cursor is situated at the end of the document, otherwise \e false.
*/
virtual bool atEndOfDocument() const;
/**
* \reimp
* \sa Document::cursorInText()
*/
virtual bool isValid() const;
/**
* Returns the character in the document immediately after this position,
* ie. from this position to this position plus Cursor(0,1).
*/
QChar character() const;
/**
* Insert \p text into the associated Document.
*
* \param text text to insert
* \param block insert this text as a visual block of text rather than a linear sequence
*
* \return \e true on success, otherwise \e false
*/
virtual bool insertText(const QStringList &text, bool block = false);
/**
* Defines the ways in which the cursor can be advanced.
* Important for languages where multiple characters are required to
* form one letter.
*/
enum AdvanceMode {
/// Movement is calculated on the basis of absolute numbers of characters
ByCharacter,
/// Movement takes into account valid cursor positions only (as defined by bidirectional processing)
ByCursorPosition
};
/**
* Move cursor by specified \a distance along the document buffer.
*
* E.g.:
* \code
* cursor.advance(1);
* \endcode
* will move the cursor forward by one character, or, if the cursor is already
* on the end of the line, will move it to the start of the next line.
*
* \note Negative numbers should be accepted, and move backwards.
* \note Not all \a mode%s are required to be supported.
*
* \param distance distance to advance (or go back if \a distance is negative)
* \param mode whether to move by character, or by number of valid cursor positions
*
* \return true if the position could be reached within the document, otherwise false
* (the cursor should not move if \a distance is beyond the end of the document).
*/
virtual bool advance(int distance, AdvanceMode mode = ByCharacter);
//END
//BEGIN Behavior methods
/**
* \}
*
* \name Behavior
*
* The following functions relate to the behavior of this SmartCursor.
* \{
*/
enum InsertBehavior {
StayOnInsert = 0,
MoveOnInsert
};
/**
* Returns how this cursor behaves when text is inserted at the cursor.
* Defaults to moving on insert.
*/
InsertBehavior insertBehavior() const;
/**
* Change the behavior of the cursor when text is inserted at the cursor.
*
* If \p moveOnInsert is true, the cursor will end up at the end of the insert.
*/
void setInsertBehavior(InsertBehavior insertBehavior);
//END
//BEGIN Notification methods
/**
* \}
*
* \name Notification
*
* The following functions allow for changes related to this cursor to be
* notified to 3rd party programs.
* \{
*/
/**
* Determine if a notifier already exists for this smart cursor.
*
* \return \e true if a notifier already exists, otherwise \e false
*/
virtual bool hasNotifier() const = 0;
/**
* Returns the current SmartCursorNotifier. If one does not already exist,
* it will be created.
*
* Connect to the notifier to receive signals indicating change of state of this cursor.
* The notifier is created at the time it is first requested. If you have finished with
* notifications for a reasonable period of time you can save memory, and potentially
* editor logic processing time, by calling deleteNotifier().
*
* \return a pointer to the current SmartCursorNotifier for this SmartCursor.
* If one does not already exist, it will be created.
*/
virtual SmartCursorNotifier* notifier() = 0;
/**
* Deletes the current SmartCursorNotifier.
*
* When finished with a notifier, call this method to save memory, and potentially
* editor logic processing time, by having the SmartCursorNotifier deleted.
*/
virtual void deleteNotifier() = 0;
/**
* Returns a pointer to the current SmartCursorWatcher, if one has been set.
*
* \return the current SmartCursorWatcher pointer if one exists, otherwise null.
*/
virtual SmartCursorWatcher* watcher() const = 0;
/**
* Provide a SmartCursorWatcher to receive calls indicating change of state of this cursor.
* To finish receiving notifications, call this function with \p watcher set to 0L.
*
* \param watcher the class which will receive notifications about changes to this cursor.
*/
virtual void setWatcher(SmartCursorWatcher* watcher = 0L) = 0;
//!\}
//END
/**
* Assignment operator. Assigns the current position of the provided cursor, \p c, only;
* does not assign watchers, notifiers, behavior, etc.
*
* \note The assignment will be performed even if the provided cursor belongs to
* another Document.
*
* \param cursor the position to assign.
*
* \return a reference to this cursor, after assignment has occurred.
*
* \sa setPosition()
*/
inline SmartCursor& operator=(const SmartCursor& cursor)
{ setPosition(cursor); return *this; }
protected:
/**
* \internal
*
* Constructor for subclasses to utilise. Protected to prevent direct
* instantiation.
*
* \note 3rd party developers: you do not (and should not) need to subclass
* the Smart* classes; instead, use the SmartInterface to create instances.
*
* \param position the cursor position to assign
* \param doc the Document this cursor is associated with
* \param insertBehavior the behavior of this cursor when on the position of an insert.
*/
SmartCursor(const Cursor& position, Document* doc, InsertBehavior insertBehavior);
private:
/**
* \internal
* Copy constructor: Disable copying of this class.
*/
SmartCursor(const SmartCursor&);
/**
* \internal
*
* The document that this cursor is associated with.
*/
Document* m_doc;
/**
* \internal
*
* Retains the behavior of the cursor when an insert takes place at the cursor's position.
*/
bool m_moveOnInsert : 1;
};
}
#endif
// kate: space-indent on; indent-width 2; replace-tabs on;

View file

@ -1,124 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2003-2005 Hamish Rodda <rodda@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 KDELIBS_KTEXTEDITOR_SMARTCURSORNOTIFIER_H
#define KDELIBS_KTEXTEDITOR_SMARTCURSORNOTIFIER_H
#include <ktexteditor/ktexteditor_export.h>
#include <QtCore/QObject>
#include <kdebug.h>
namespace KTextEditor
{
class SmartCursor;
/**
* \short A class which provides notifications of state changes to a SmartCursor via QObject signals.
*
* \ingroup kte_group_smart_classes
*
* This class provides notifications of changes to a SmartCursor such as the
* position in the document, and deletion or insertion of text immediately
* before or after the cursor.
*
* If you prefer to receive notifications via virtual inheritance, see SmartCursorWatcher.
*
* \sa SmartCursor, SmartCursorNotifier
*
* \author Hamish Rodda \<rodda@kde.org\>
*/
class KTEXTEDITOR_EXPORT SmartCursorNotifier : public QObject
{
Q_OBJECT
public:
/**
* Default constructor.
*/
SmartCursorNotifier();
/**
* Returns whether this notifier will notify of changes that happen
* directly to the cursor, e.g. by calls to SmartCursor::setPosition(), rather
* than just when surrounding text changes.
*/
bool wantsDirectChanges() const;
/**
* Set whether this notifier should notify of changes that happen
* directly to the cursor, e.g. by calls to SmartCursor::setPosition(), rather
* than just when surrounding text changes.
*
* \param wantsDirectChanges whether this notifier should provide notifications for direct changes.
*/
void setWantsDirectChanges(bool wantsDirectChanges);
Q_SIGNALS:
/**
* The cursor's position was changed.
*
* \param cursor pointer to the cursor which generated the notification.
*/
void positionChanged(KTextEditor::SmartCursor* cursor);
/**
* The cursor's surrounding characters were both deleted simultaneously.
* The cursor is automatically placed at the start of the deleted region.
*
* \param cursor pointer to the cursor which generated the notification.
*/
void positionDeleted(KTextEditor::SmartCursor* cursor);
/**
* One character immediately surrounding the cursor was deleted.
* If both characters are simultaneously deleted, positionDeleted() is called instead.
*
* \param cursor pointer to the cursor which generated the notification.
* \param deletedBefore \c true if the character immediately before was deleted,
* \c false if the character immediately after was deleted.
*/
void characterDeleted(KTextEditor::SmartCursor* cursor, bool deletedBefore);
/**
* A character was inserted immediately before or after the cursor, as given
* by \p insertedBefore.
*
* \param cursor pointer to the cursor which generated the notification.
* \param insertedBefore \e true if a character was inserted before \p cursor,
* \e false if a character was inserted after
*/
void characterInserted(KTextEditor::SmartCursor* cursor, bool insertedBefore);
/**
* The SmartCursor instance specified by \p cursor is being deleted.
*
* \param cursor pointer to the cursor which is about to be deleted. It is
* still safe to access information at this point.
*/
void deleted(KTextEditor::SmartCursor* cursor);
private:
bool m_wantDirectChanges;
};
}
#endif
// kate: space-indent on; indent-width 2; replace-tabs on;

View file

@ -1,127 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2003-2005 Hamish Rodda <rodda@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 KDELIBS_KTEXTEDITOR_SMARTCURSORWATCHER_H
#define KDELIBS_KTEXTEDITOR_SMARTCURSORWATCHER_H
#include <ktexteditor/ktexteditor_export.h>
#include <QtCore/QObject>
#include <kdebug.h>
namespace KTextEditor
{
class SmartCursor;
/**
* \short A class which provides notifications of state changes to a SmartCursor via virtual inheritance.
*
* \ingroup kte_group_smart_classes
*
* This class provides notifications of changes to a SmartCursor such as the
* position in the document, and deletion or insertion of text immediately
* before or after the cursor.
*
* If you prefer to receive notifications via QObject signals, see SmartCursorNotifier.
*
* \sa SmartCursor, SmartCursorNotifier
*
* \author Hamish Rodda \<rodda@kde.org\>
*/
class KTEXTEDITOR_EXPORT SmartCursorWatcher
{
public:
/**
* Default constructor.
*/
SmartCursorWatcher();
/**
* Virtual destructor.
*/
virtual ~SmartCursorWatcher();
/**
* Returns whether this watcher wants to be notified of changes that happen
* directly to the cursor, e.g. by calls to SmartCursor::setPosition(), rather
* than just when surrounding text changes.
*/
bool wantsDirectChanges() const;
/**
* Set whether this watcher should be notified of changes that happen
* directly to the cursor, e.g. by calls to SmartCursor::setPosition(), rather
* than just when surrounding text changes.
*
* \param wantsDirectChanges whether this watcher should receive notifications for direct changes.
*/
void setWantsDirectChanges(bool wantsDirectChanges);
/**
* The cursor's position was changed.
*
* \param cursor pointer to the cursor which generated the notification.
*/
virtual void positionChanged(SmartCursor* cursor);
/**
* The cursor's surrounding characters were both deleted simultaneously.
* The cursor is automatically placed at the start of the deleted region.
*
* \param cursor pointer to the cursor which generated the notification.
*/
virtual void positionDeleted(SmartCursor* cursor);
/**
* The character immediately surrounding the cursor was deleted.
* If both characters are simultaneously deleted, positionDeleted() is called instead.
*
* \param cursor pointer to the cursor which generated the notification.
* \param deletedBefore \c true if the character immediately before was deleted,
* \c false if the character immediately after was deleted.
*/
virtual void characterDeleted(SmartCursor* cursor, bool deletedBefore);
/**
* A character was inserted immediately before or after the cursor, as given
* by \p insertedBefore.
*
* \param cursor pointer to the cursor which generated the notification.
* \param insertedBefore \e true if a character was inserted before \p cursor,
* \e false if a character was inserted after
*/
virtual void characterInserted(SmartCursor* cursor, bool insertedBefore);
/**
* The SmartCursor instance specified by \p cursor is being deleted.
*
* \param cursor pointer to the cursor which is about to be deleted. It is
* still safe to access information at this point.
*/
virtual void deleted(SmartCursor* cursor);
private:
bool m_wantDirectChanges;
};
}
#endif
// kate: space-indent on; indent-width 2; replace-tabs on;

View file

@ -1,94 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2001 Christoph Cullmann (cullmann@kde.org)
Copyright (C) 2005-2006 Hamish Rodda <rodda@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.
*/
#include "smartinterface.h"
#include <QtCore/QMutex>
using namespace KTextEditor;
class KTextEditor::SmartInterfacePrivate
{
public:
SmartInterfacePrivate()
: clearOnDocumentReload(true)
{}
QMutex mutex;
bool clearOnDocumentReload;
};
SmartInterface::SmartInterface()
: d(new SmartInterfacePrivate)
{
}
SmartInterface::~ SmartInterface( )
{
delete d;
}
bool SmartInterface::clearOnDocumentReload() const
{
return d->clearOnDocumentReload;
}
void SmartInterface::setClearOnDocumentReload(bool clearOnReload)
{
QMutexLocker lock(&d->mutex);
d->clearOnDocumentReload = clearOnReload;
}
void SmartInterface::clearRevision()
{
useRevision(-1);
}
Cursor SmartInterface::translateFromRevision(const Cursor& cursor, SmartCursor::InsertBehavior insertBehavior) const
{
Q_UNUSED(insertBehavior);
return cursor;
}
SmartCursor* SmartInterface::newSmartCursor(int line, int column, SmartCursor::InsertBehavior insertBehavior)
{
return newSmartCursor(Cursor(line, column), insertBehavior);
}
SmartRange* SmartInterface::newSmartRange(const Cursor& startPosition,
const Cursor& endPosition,
SmartRange* parent,
SmartRange::InsertBehaviors insertBehavior)
{
return newSmartRange(Range(startPosition, endPosition), parent, insertBehavior);
}
SmartRange* SmartInterface::newSmartRange(int startLine, int startColumn, int endLine, int endColumn, SmartRange* parent, SmartRange::InsertBehaviors insertBehavior)
{
return newSmartRange(Range(startLine, startColumn, endLine, endColumn), parent, insertBehavior);
}
Range SmartInterface::translateFromRevision(const Range& range, SmartRange::InsertBehaviors insertBehavior) const
{
Q_UNUSED(insertBehavior);
return range;
}
// kate: space-indent on; indent-width 2; replace-tabs on;

View file

@ -1,489 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2005 Hamish Rodda <rodda@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 KDELIBS_KTEXTEDITOR_SMARTINTERFACE_H
#define KDELIBS_KTEXTEDITOR_SMARTINTERFACE_H
#include <ktexteditor/ktexteditor_export.h>
#include <ktexteditor/smartrange.h>
#include <QMutex>
namespace KTextEditor
{
class Document;
class View;
class SmartCursor;
/**
* \brief A Document extension interface for handling SmartCursor%s and SmartRange%s.
*
* \ingroup kte_group_doc_extensions
*
* Topics:
* - \ref smartiface_intro
* - \ref smartiface_creation
* - \ref smartiface_highlight
* - \ref smartiface_action
* - \ref smartiface_access
*
* \section smartiface_intro Introduction
* Use this interface to:
* \li create new SmartCursor%s and SmartRange%s;
* \li create arbitrary highlighting; and
* \li associate KAction%s with ranges of text
*
* \section smartiface_creation Creation of SmartCursors and SmartRanges
* These functions must be used to create SmartCursor%s and SmartRange%s. This
* means that these objects cannot be derived from by third party applications.
*
* You then own these objects; upon deletion they de-register themselves from
* the Document with which they were associated. Alternatively, they are all
* deleted with the deletion of the owning Document.
*
* \section smartiface_highlight Arbitrary Highlighting
* Arbitrary highlighting of text can be achieved by creating SmartRange%s in a
* tree structure, and assigning appropriate Attributes to these ranges.
*
* To highlight all views, use addHighlightToDocument(); to highlight one or some
* of the views, use addHighlightToView(). You only need to call this function once
* per tree; just supply the top range you want to have highlighted. Calling
* this function more than once with ranges from the same tree may give undefined results.
*
* \section smartiface_action Action Binding
* Action binding can be used to associate KAction%s with specific ranges of text.
* These bound actions are automatically enabled and disabled when the caret enters
* their associated ranges, and context menus are automatically populated with the
* relevant actions.
*
* As with the arbitrary highlighting interface, to enable bound actions to be active,
* call addActionsToDocument() or addActionsToView() on the top SmartRange of a tree.
* If only small branches of a tree contain actions, it may be more efficient to simply add
* each of these branches instead (but this is unlikely unless the tree is complex).
*
* Note that actions can be bound either directly to the range via
* SmartRange::associateAction(), or indirectly via
* Attribute::associateAction(). Using attributes may be more convenient when
* you want all ranges of a specific type to have the same action associated
* with them.
*
* \todo extend this to provide a signal from the action indicating which range was
* used to activate it (if possible)
*
* \section smartiface_access Accessing the Interface
*
* The SmartInterface is supposed to be an extension interface for a Document,
* i.e. the Document inherits the interface \e provided that the
* KTextEditor library in use implements the interface. Use dynamic_cast to access
* the interface:
* \code
* // doc is of type KTextEditor::Document*
* KTextEditor::SmartInterface *iface =
* qobject_cast<KTextEditor::SmartInterface*>( doc );
*
* if( iface ) {
* // the implementation supports the interface
* // do stuff
* }
* \endcode
*
* \author Hamish Rodda \<rodda@kde.org\>
*/
class KTEXTEDITOR_EXPORT SmartInterface
{
friend class Attribute;
public:
SmartInterface();
virtual ~SmartInterface();
/**
* Clears or deletes all instances of smart objects, ie:
* \li deletes all SmartCursor%s
* \li deletes all SmartRange%s
* \li clears all arbitrary highlight ranges
* \li clears all action binding
*
* Deletion occurs without modification to the underlying text.
*/
virtual void clearSmartInterface() = 0;
/**
* Returns whether the smart interface will be cleared on reload of the document.
*
* Defaults to true.
*/
bool clearOnDocumentReload() const;
/**
* Specify whether the smart interface should be cleared on reload of the document.
*
* \param clearOnReload set to true to enable clearing of the smart interface on reload (the default).
*/
void setClearOnDocumentReload(bool clearOnReload);
//BEGIN New cursor methods
/**
* Retrieve a token representing the current version of the document. This can
* be used later to create cursors and ranges as they would have been at this revision.
*
* Once you have finished with the token, release it with releaseRevision().
*/
virtual int currentRevision() const = 0;
/**
* Release a revision token provided by currentRevision(). You will no longer be able to
* create cursors and ranges against this revision.
*/
virtual void releaseRevision(int revision) const = 0;
/**
* Tell the smart interface to work against the given \a revision when creating cursors and
* ranges. This has only an effect for the thread calling this function, as this property
* is stored thread locally. This is not allowed to be called in the main gui thread.
* If you call it in the main gui thread, fatal error will occur.
*
* \param revision the token representing a revision retrieved by currentRevision(), or -1 to
* clear any previous setting and use the current document revision.
*/
virtual void useRevision(int revision) = 0;
/**
* Clear any previous setting to use a specific revision.
* Convenience wrapper for useRevision (-1).
*/
void clearRevision();
/**
* Translate the given \a cursor against the revision specified through useRevision(),
* using the given \a insertBehavior.
*
* If no revision is set, simply returns the cursor.
*/
virtual KTextEditor::Cursor translateFromRevision(const KTextEditor::Cursor& cursor, KTextEditor::SmartCursor::InsertBehavior insertBehavior = KTextEditor::SmartCursor::StayOnInsert) const;
/**
* Translate the given \a range against the revision specified through useRevision(),
* using the given \a insertBehavior.
*
* If no revision is set, simply returns the range.
*/
virtual KTextEditor::Range translateFromRevision(const KTextEditor::Range& range, KTextEditor::SmartRange::InsertBehaviors insertBehavior = KTextEditor::SmartRange::ExpandLeft | KTextEditor::SmartRange::ExpandRight) const;
/**
* \name Smart Cursors
*
* The following functions allow for creation and deletion of SmartCursor%s.
* \{
*/
/**
* Creates a new SmartCursor.
*
* You own this object, and may delete it when you are finished with it.
* Alternatively, you may call the various clear methods, or wait for the Document
* to be destroyed.
*
* \param position The initial cursor position assumed by the new cursor.
* If not specified, it will start at position (0, 0).
* \param insertBehavior Define whether the cursor should move when text is inserted at the cursor position.
*/
virtual SmartCursor* newSmartCursor(const Cursor& position = Cursor::start(), SmartCursor::InsertBehavior insertBehavior = SmartCursor::MoveOnInsert) = 0;
/**
* \overload
* \n \n
* Creates a new SmartCursor.
*
* You own this object, and may delete it when you are finished with it.
* Alternatively, you may call the various clear methods, or wait for the Document
* to be destroyed.
*
* \param line the line number of the cursor's initial position
* \param column the line number of the cursor's initial position
* \param insertBehavior Define whether the cursor should move when text is inserted at the cursor position.
*/
SmartCursor* newSmartCursor(int line, int column, SmartCursor::InsertBehavior insertBehavior = SmartCursor::MoveOnInsert);
/**
* Delete all SmartCursor%s from this document, with the exception of those
* cursors currently bound to ranges.
*/
virtual void deleteCursors() = 0;
//END
//BEGIN New range methods
/**
* \}
*
* \name Smart Ranges
*
* The following functions allow for creation of new SmartRange%s.
* \{
*/
/**
* Creates a new SmartRange.
* \param range The initial text range assumed by the new range.
* \param parent The parent SmartRange, if this is to be the child of an existing range.
* \param insertBehavior Define whether the range should expand when text is inserted adjacent to the range.
*/
virtual SmartRange* newSmartRange(const Range& range = Range(),
SmartRange* parent = 0L,
SmartRange::InsertBehaviors insertBehavior = SmartRange::DoNotExpand) = 0;
/**
* \overload
* \n \n
* Creates a new SmartRange.
* \param startPosition The start position assumed by the new range.
* \param endPosition The end position assumed by the new range.
* \param parent The parent SmartRange, if this is to be the child of an existing range.
* \param insertBehavior Define whether the range should expand when text is inserted adjacent to the range.
*/
SmartRange* newSmartRange(const Cursor& startPosition,
const Cursor& endPosition,
SmartRange* parent = 0L,
SmartRange::InsertBehaviors insertBehavior = SmartRange::DoNotExpand);
/**
* \overload
* \n \n
* Creates a new SmartRange.
* \param startLine The start line assumed by the new range.
* \param startColumn The start column assumed by the new range.
* \param endLine The end line assumed by the new range.
* \param endColumn The end column assumed by the new range.
* \param parent The parent SmartRange, if this is to be the child of an existing range.
* \param insertBehavior Define whether the range should expand when text is inserted adjacent to the range.
*/
SmartRange* newSmartRange(int startLine, int startColumn, int endLine, int endColumn, SmartRange* parent = 0L, SmartRange::InsertBehaviors insertBehavior = SmartRange::DoNotExpand);
/**
* Creates a new SmartRange from pre-existing SmartCursor%s. The cursors must not be part of any other range.
*
* \param start Start SmartCursor
* \param end End SmartCursor
* \param parent The parent SmartRange, if this is to be the child of an existing range.
* \param insertBehavior Define whether the range should expand when text is inserted at ends of the range.
*/
virtual SmartRange* newSmartRange(SmartCursor* start, SmartCursor* end, SmartRange* parent = 0L, SmartRange::InsertBehaviors insertBehavior = SmartRange::DoNotExpand) = 0;
/**
* Delete a SmartRange without deleting the SmartCursor%s which make up its start() and end().
*
* First, extract the cursors yourself using:
* \code
* SmartCursor* start = &range->smartStart();
* SmartCursor* end = &range->smartEnd();
* \endcode
*
* Then, call this function to delete the SmartRange instance. The underlying text will not be affected.
*
* \param range the range to dissociate from its smart cursors, and delete
*/
virtual void unbindSmartRange(SmartRange* range) = 0;
/**
* Delete all SmartRange%s from this document. This will also delete all
* cursors currently bound to ranges.
*
* This will not affect any underlying text.
*/
virtual void deleteRanges() = 0;
//END
//BEGIN Syntax highlighting extension
/**
* \}
*
* \name Arbitrary Highlighting
*
* The following functions enable highlighting processing for SmartRange%s with arbitrary
* highlighting information.
* \{
*/
/**
* Register a SmartRange tree as providing arbitrary highlighting information,
* and that it should be rendered on all of the views of a document.
*
* \param topRange the top range of the tree to add
* \param supportDynamic support dynamic highlighting attributes
*/
virtual void addHighlightToDocument(SmartRange* topRange, bool supportDynamic = false) = 0;
/**
* Remove a SmartRange tree from providing arbitrary highlighting information
* to all of the views of a document.
*
* \param topRange the top range of the tree to remove
*/
virtual void removeHighlightFromDocument(SmartRange* topRange) = 0;
/**
* Return a list of SmartRange%s which are currently registered as
* providing arbitrary highlighting information to all of the views of a
* document.
*/
virtual const QList<SmartRange*> documentHighlights() const = 0;
/**
* Clear the highlight ranges from a Document.
*/
virtual void clearDocumentHighlights() = 0;
/**
* Register a SmartRange tree as providing arbitrary highlighting information,
* and that it should be rendered on the specified \p view.
*
* \param view view on which to render the highlight
* \param topRange the top range of the tree to add
* \param supportDynamic support dynamic highlighting attributes
*/
virtual void addHighlightToView(View* view, SmartRange* topRange, bool supportDynamic = false) = 0;
/**
* Remove a SmartRange tree from providing arbitrary highlighting information
* to a specific view of a document.
*
* \note implementations should not take into account document-bound
* highlighting ranges when calling this function; it is intended solely
* to be the counter of addHighlightToView()
*
* \param view view on which the highlight was previously rendered
* \param topRange the top range of the tree to remove
*/
virtual void removeHighlightFromView(View* view, SmartRange* topRange) = 0;
/**
* Return a list of SmartRange%s which are currently registered as
* providing arbitrary highlighting information to a specific view of a
* document.
*
* \note implementations should not take into account document-bound
* highlighting ranges when returning the list; it is intended solely
* to show highlights added via addHighlightToView()
*
* \param view view to query for the highlight list
*/
virtual const QList<SmartRange*> viewHighlights(View* view) const = 0;
/**
* Clear the highlight ranges from a View.
*
* \param view view to clear highlights from
*/
virtual void clearViewHighlights(View* view) = 0;
//END
//BEGIN Action binding extension - not implemented
/* not implemented
* Register a SmartRange tree as providing bound actions,
* and that they should interact with all of the views of a document.
*
* \param topRange the top range of the tree to add
*/
virtual void addActionsToDocument(SmartRange* topRange) = 0;
/* not implemented
* Remove a SmartRange tree from providing bound actions
* to all of the views of a document.
*
* \param topRange the top range of the tree to remove
*/
virtual void removeActionsFromDocument(SmartRange* topRange) = 0;
/* not implemented
* Return a list of SmartRange%s which are currently registered as
* providing bound actions to all of the views of a document.
*/
virtual const QList<SmartRange*> documentActions() const = 0;
/* not implemented
* Remove all bound SmartRange%s which provide actions to the document.
*/
virtual void clearDocumentActions() = 0;
/* not implemented
* Register a SmartRange tree as providing bound actions,
* and that they should interact with the specified \p view.
*
* \param view view on which to use the actions
* \param topRange the top range of the tree to add
*/
virtual void addActionsToView(View* view, SmartRange* topRange) = 0;
/* not implemented
* Remove a SmartRange tree from providing bound actions
* to the specified \p view.
*
* \note implementations should not take into account document-bound
* action ranges when calling this function; it is intended solely
* to be the counter of addActionsToView()
*
* \param view view on which the actions were previously used
* \param topRange the top range of the tree to remove
*/
virtual void removeActionsFromView(View* view, SmartRange* topRange) = 0;
/* not implemented
* Return a list of SmartRange%s which are currently registered as
* providing bound actions to the specified \p view.
*
* \note implementations should not take into account document-bound
* action ranges when returning the list; it is intended solely
* to show actions added via addActionsToView()
*
* \param view view to query for the action list
*/
virtual const QList<SmartRange*> viewActions(View* view) const = 0;
/* not implemented
* Remove all bound SmartRange%s which provide actions to the specified \p view.
*
* \param view view from which to remove actions
*/
virtual void clearViewActions(View* view) = 0;
//END
protected:
/**
* \internal
* Used to notify implementations that an Attribute has gained
* a dynamic component and needs to be included in mouse and/or cursor
* tracking.
*/
virtual void attributeDynamic(Attribute::Ptr a) = 0;
/**
* \internal
* Used to notify implementations that an Attribute has lost
* all dynamic components and no longer needs to be included in mouse and cursor
* tracking.
*/
virtual void attributeNotDynamic(Attribute::Ptr a) = 0;
private:
class SmartInterfacePrivate* const d;
};
}
Q_DECLARE_INTERFACE(KTextEditor::SmartInterface, "org.kde.KTextEditor.SmartInterface")
#endif
// kate: space-indent on; indent-width 2; replace-tabs on;

View file

@ -1,940 +0,0 @@
/* This file is part of the KDE libraries
Copyright (C) 2003-2005 Hamish Rodda <rodda@kde.org>
Copyright (C) 2008 David Nolden <david.nolden.kdevelop@art-master.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
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.
*/
#include "smartrange.h"
#include <QtCore/QStack>
#include "document.h"
#include "view.h"
#include "attribute.h"
#include "rangefeedback.h"
#include <kaction.h>
#include <kdebug.h>
using namespace KTextEditor;
//Uncomment this to enable debugging of the child-order. If it is enabled, an assertion will
//be triggered when the order is violated.
//This is slow.
// #define SHOULD_DEBUG_CHILD_ORDER
//Uncomment this to debug the m_overlapCount values. When it is enabled,
//extensive tests will be done to verify that the values are true,
//and an assertion is triggered when not.
//This is very slow, especially with many child-ranges.
// #define SHOULD_DEBUG_OVERLAP
#ifdef SHOULD_DEBUG_CHILD_ORDER
#define DEBUG_CHILD_ORDER \
{\
KTextEditor::Cursor lastEnd = KTextEditor::Cursor(-1,-1);\
for(int a = 0; a < m_childRanges.size(); ++a) {\
Q_ASSERT(m_childRanges[a]->end() >= lastEnd);\
Q_ASSERT(m_childRanges[a]->start() >= start());\
Q_ASSERT(m_childRanges[a]->end() <= end());\
lastEnd = m_childRanges[a]->end();\
}\
}\
#else
#define DEBUG_CHILD_ORDER
#endif
#ifdef SHOULD_DEBUG_OVERLAP
#define DEBUG_CHILD_OVERLAP \
{\
QVector<int> counter(m_childRanges.size(), 0);\
\
for(int a = 0; a < m_childRanges.size(); ++a) {\
const SmartRange& overlapper(*m_childRanges[a]);\
for(int b = 0; b < a; ++b) {\
const SmartRange& overlapped(*m_childRanges[b]);\
Q_ASSERT(overlapped.end() <= overlapper.end());\
if(overlapped.end() > overlapper.start()) {\
++counter[b];\
}\
}\
}\
for(int a = 0; a < m_childRanges.size(); ++a) {\
Q_ASSERT(m_childRanges[a]->m_overlapCount == counter[a]);\
}\
}\
#define DEBUG_PARENT_OVERLAP \
if(m_parentRange) {\
QVector<int> counter(m_parentRange->m_childRanges.size(), 0);\
\
for(int a = 0; a < m_parentRange->m_childRanges.size(); ++a) {\
const SmartRange& overlapper(*m_parentRange->m_childRanges[a]);\
for(int b = 0; b < a; ++b) {\
const SmartRange& overlapped(*m_parentRange->m_childRanges[b]);\
Q_ASSERT(overlapped.end() <= overlapper.end());\
if(overlapped.end() > overlapper.start()) {\
++counter[b];\
}\
}\
}\
for(int a = 0; a < m_parentRange->m_childRanges.size(); ++a) {\
Q_ASSERT(m_parentRange->m_childRanges[a]->m_overlapCount == counter[a]);\
}\
}\
#else
#define DEBUG_CHILD_OVERLAP
#define DEBUG_PARENT_OVERLAP
#endif
///Returns the index of the first range that ends behind @p pos
///The list must be sorted by the ranges end-positions.
static int lowerBound(const QList<SmartRange*>& ranges, const Cursor& pos)
{
int begin = 0;
int n = ranges.count();
while (n > 0) {
int half = n >> 1;
int middle = begin + half;
if(ranges[middle]->end() > pos) {
n = half;
}else{
begin = middle + 1;
n -= half + 1;
}
}
return begin;
}
///Searches for the given range, or a lower bound for the given position. Does not work correctly in case of overlaps,
///but for that case we have a fallback. Only for use in findIndex.
static int lowerBoundRange(const QList<SmartRange*>& ranges, const Cursor& pos, const SmartRange* range)
{
int begin = 0;
int n = ranges.count();
while (n > 0) {
int half = n >> 1;
int middle = begin + half;
if(ranges[begin] == range)
return begin;
if(ranges[middle] == range)
return middle;
if(ranges[middle]->end() > pos) {
n = half;
}else{
begin = middle + 1;
n -= half + 1;
}
}
return begin;
}
///Finds the index of the given SmartRange in the sorted list using binary search. Uses @param range For searching, and @param smartRange for equality comparison.
static int findIndex(const QList<SmartRange*>& ranges, const SmartRange* smartRange, const Range* range) {
int index = lowerBoundRange(ranges, range->start(), smartRange);
int childCount = ranges.count();
//In case of degenerated ranges, we may have found the wrong index.
while(index < childCount && ranges[index] != smartRange)
++index;
if(index == childCount) {
//During rangeChanged the order may temporarily be inconsistent, so we use indexOf as fallback
return ranges.indexOf(const_cast<SmartRange*>(smartRange));
/* if(smartRange != range) //Try again finding the range, using the smart-range only
return findIndex(ranges, smartRange, smartRange);*/
// Q_ASSERT(ranges.indexOf(const_cast<SmartRange*>(smartRange)) == -1);
return -1;
}
return index;
}
SmartRange::SmartRange(SmartCursor* start, SmartCursor* end, SmartRange * parent, InsertBehaviors insertBehavior )
: Range(start, end)
, m_attribute(0L)
, m_parentRange(parent)
, m_ownsAttribute(false)
, m_overlapCount(0)
{
setInsertBehavior(insertBehavior);
// Not calling setParentRange here...:
// 1) subclasses are not yet constructed
// 2) it would otherwise give the wrong impression
if (m_parentRange)
m_parentRange->insertChildRange(this);
}
SmartRange::~SmartRange( )
{
deleteChildRanges();
setParentRange(0L);
/*if (!m_deleteCursors)
{
// Save from deletion in the parent
m_start = 0L;
m_end = 0L;
}*/
}
bool SmartRange::confineToRange(const Range& range)
{
if (!Range::confineToRange(range))
// Don't need to check if children should be confined, they already are
return false;
foreach (SmartRange* child, m_childRanges)
child->confineToRange(*this);
return true;
}
bool SmartRange::expandToRange(const Range& range)
{
if (!Range::expandToRange(range))
// Don't need to check if parents should be expanded, they already are
return false;
if (parentRange())
parentRange()->expandToRange(*this);
return true;
}
void SmartRange::setRange(const Range& range)
{
if (range == *this)
return;
Range old = *this;
Range::setRange(range);
DEBUG_CHILD_OVERLAP
}
const QList<SmartRange*>& SmartRange::childRanges() const
{
return m_childRanges;
}
SmartRange * SmartRange::childBefore( const SmartRange * range ) const
{
int index = findIndex(m_childRanges, range, range);
if (--index >= 0)
return m_childRanges[index];
return 0L;
}
SmartRange * SmartRange::childAfter( const SmartRange * range ) const
{
int index = findIndex(m_childRanges, range, range);
if (index != -1 && ++index < m_childRanges.count())
return m_childRanges[index];
return 0L;
}
void SmartRange::insertChildRange( SmartRange * newChild )
{
DEBUG_CHILD_OVERLAP
Q_ASSERT(newChild->parentRange() == this);
// A new child has been added, so expand this range if required.
expandToRange(*newChild);
DEBUG_CHILD_ORDER
int insertAt = lowerBound(m_childRanges, newChild->end());
m_childRanges.insert(insertAt, newChild);
//Increase the overlap of previous ranges
for(int current = insertAt-1; current >= 0; --current) {
SmartRange& range(*m_childRanges[current]);
Q_ASSERT(range.end() <= newChild->end());
if(range.end() > newChild->start()) {
++range.m_overlapCount;
}else{
//range.end() <= start(), The range does not overlap, and the same applies for all earlier ranges
break;
}
}
//Increase this ranges overlap from already existing ranges
for(int current = insertAt+1; current < m_childRanges.size(); ++current) {
SmartRange& range(*m_childRanges[current]);
Q_ASSERT(range.end() >= newChild->end());
if(range.start() < newChild->end())
++newChild->m_overlapCount; //The range overlaps newChild
if(!range.m_overlapCount)
break; //If this follower-range isn't overlapped by any other ranges, we can break here.
}
DEBUG_CHILD_OVERLAP
DEBUG_CHILD_ORDER
QMutableListIterator<SmartRange*> it = m_childRanges;
it.toBack();
foreach (SmartRangeNotifier* n, m_notifiers)
emit n->childRangeInserted(this, newChild);
foreach (SmartRangeWatcher* w, m_watchers)
w->childRangeInserted(this, newChild);
DEBUG_CHILD_OVERLAP
DEBUG_CHILD_ORDER
}
void SmartRange::removeChildRange(SmartRange* child)
{
DEBUG_CHILD_OVERLAP
int index = findIndex(m_childRanges, child, child);
if (index != -1) {
m_childRanges.removeAt(index);
//Reduce the overlap with all previously overlapping ranges(parentChildren is still sorted by the old end-position)
for(int current = index-1; current >= 0; --current) {
SmartRange& range(*m_childRanges[current]);
Q_ASSERT(range.end() <= child->end());
if(range.end() <= child->start()) {
break; //This range did not overlap before, the same applies for all earlier ranges because of the order
}else{
if(range.m_overlapCount) {
--range.m_overlapCount;
} else {
//May happen with more than 64 overlaps
#ifdef SHOULD_DEBUG_OVERLAP
Q_ASSERT(0);
#endif
}
}
}
DEBUG_CHILD_OVERLAP
child->m_overlapCount = 0; //It has no neighbors any more, so no overlap
foreach (SmartRangeNotifier* n, m_notifiers)
emit n->childRangeInserted(this, child);
foreach (SmartRangeWatcher* w, m_watchers)
w->childRangeInserted(this, child);
}
DEBUG_CHILD_OVERLAP
}
SmartRange * SmartRange::mostSpecificRange( const Range & input ) const
{
if (!input.isValid())
return 0L;
if (contains(input)) {
int child = lowerBound(m_childRanges, input.start());
SmartRange* mostSpecific = 0;
while(child != m_childRanges.size()) {
SmartRange* r = m_childRanges[child];
if(r->contains(input)) {
SmartRange* candidate = r->mostSpecificRange(input);
if(mostSpecific == 0 ||
((candidate->end() - candidate->start()) < (mostSpecific->end() - mostSpecific->start())) ||
(candidate->end() < mostSpecific->end()))
mostSpecific = candidate;
}
if(r->m_overlapCount == 0)
break;
++child; //We have to iterate as long as there is overlapping ranges
}
if(mostSpecific)
return mostSpecific;
else
return const_cast<SmartRange*>(this);
} else if (parentRange()) {
return parentRange()->mostSpecificRange(input);
} else {
return 0L;
}
}
SmartRange * SmartRange::firstRangeContaining( const Cursor & pos ) const
{
if (!pos.isValid())
return 0L;
if (contains(pos)) {
if (parentRange() && parentRange()->contains(pos))
return parentRange()->firstRangeContaining(pos);
return const_cast<SmartRange*>(this);
} else {
if (!parentRange())
return 0L;
return parentRange()->firstRangeContaining(pos);
}
}
int SmartRange::overlapCount() const
{
return m_overlapCount;
}
QList<SmartRange*> SmartRange::deepestRangesContaining(const Cursor& pos) const
{
QList<SmartRange*> ret;
if(!contains(pos))
return ret;
int child = lowerBound(m_childRanges, pos);
while(child != m_childRanges.size()) {
SmartRange* r = m_childRanges[child];
//The list will be unchanged if the range doesn't contain the position
ret += r->deepestRangesContaining(pos);
if(r->m_overlapCount == 0)
break;
++child; //We have to iterate as long as there is overlapping ranges
}
if(!ret.isEmpty())
return ret;
else
return ret << const_cast<SmartRange*>(this);
}
SmartRange * SmartRange::deepestRangeContaining( const Cursor & pos, QStack<SmartRange*>* rangesEntered, QStack<SmartRange*>* rangesExited ) const
{
if (!pos.isValid()) {
// Just leave all ranges
if (rangesExited) {
SmartRange* range = const_cast<SmartRange*>(this);
while (range) {
rangesExited->append(range);
range = range->parentRange();
}
}
return 0L;
}
return deepestRangeContainingInternal(pos, rangesEntered, rangesExited, true);
}
SmartRange * SmartRange::deepestRangeContainingInternal( const Cursor & pos, QStack<SmartRange*>* rangesEntered, QStack<SmartRange*>* rangesExited, bool first ) const
{
if (contains(pos)) {
if (!first && rangesEntered)
rangesEntered->push(const_cast<SmartRange*>(this));
int child = lowerBound(m_childRanges, pos);
QStack<SmartRange*> mostSpecificStack;
SmartRange* mostSpecific = 0;
while(child != m_childRanges.size()) {
SmartRange* r = m_childRanges[child];
if(r->contains(pos)) {
QStack<SmartRange*> candidateStack;
SmartRange* candidateRange = r->deepestRangeContainingInternal(pos, rangesEntered ? &candidateStack : 0, 0);
Q_ASSERT(!rangesEntered || !candidateStack.isEmpty());
Q_ASSERT(candidateRange);
if(!mostSpecific ||
((candidateRange->end() - candidateRange->start()) < (mostSpecific->end() - mostSpecific->start())) ||
(candidateRange->end() < mostSpecific->end())) {
mostSpecific = candidateRange;
mostSpecificStack = candidateStack;
}
}
if(r->m_overlapCount == 0)
break;
++child; //We have to iterate as long as there is overlapping ranges
}
if(mostSpecific) {
if(rangesEntered)
*rangesEntered += mostSpecificStack;
return mostSpecific;
}
return const_cast<SmartRange*>(this);
} else {
if (rangesExited)
rangesExited->push(const_cast<SmartRange*>(this));
if (!parentRange())
return 0L;
// first is true, because the parentRange won't be "entered" on first descent
return parentRange()->deepestRangeContainingInternal(pos, rangesEntered, rangesExited, true);
}
}
Document* SmartRange::document( ) const
{
return smartStart().document();
}
void SmartRange::associateAction( KAction * action )
{
m_associatedActions.append(action);
bool enable = false;
if (View* v = document()->activeView())
if (contains(v->cursorPosition()))
enable = true;
action->setEnabled(enable);
if (m_associatedActions.count() == 1)
checkFeedback();
}
void SmartRange::dissociateAction( KAction * action )
{
m_associatedActions.removeAll(action);
if (!m_associatedActions.count())
checkFeedback();
}
void SmartRange::clearAssociatedActions( )
{
m_associatedActions.clear();
checkFeedback();
}
SmartRange::InsertBehaviors SmartRange::insertBehavior( ) const
{
return ((smartStart().insertBehavior() == SmartCursor::MoveOnInsert) ? DoNotExpand : ExpandLeft) | ((smartEnd().insertBehavior() == SmartCursor::MoveOnInsert) ? ExpandRight : DoNotExpand);
}
void SmartRange::setInsertBehavior(SmartRange::InsertBehaviors behavior)
{
static_cast<SmartCursor*>(m_start)->setInsertBehavior((behavior & ExpandLeft) ? SmartCursor::StayOnInsert : SmartCursor::MoveOnInsert);
static_cast<SmartCursor*>(m_end)->setInsertBehavior((behavior & ExpandRight) ? SmartCursor::MoveOnInsert : SmartCursor::StayOnInsert);
}
void SmartRange::clearChildRanges()
{
foreach (SmartRange* r, m_childRanges)
r->removeText();
}
void SmartRange::deleteChildRanges()
{
// FIXME: Probably more efficient to prevent them from unlinking themselves?
qDeleteAll(m_childRanges);
// i.e. this is probably already clear
m_childRanges.clear();
}
void SmartRange::clearAndDeleteChildRanges( )
{
// FIXME: Probably more efficient to prevent them from unlinking themselves?
foreach (SmartRange* r, m_childRanges)
r->removeText();
qDeleteAll(m_childRanges);
// i.e. this is probably already clear
m_childRanges.clear();
}
void SmartRange::setParentRange( SmartRange * r )
{
if (m_parentRange == r)
return;
DEBUG_PARENT_OVERLAP
if (m_parentRange)
m_parentRange->removeChildRange(this);
SmartRange* oldParent = m_parentRange;
m_parentRange = r;
if (m_parentRange)
m_parentRange->insertChildRange(this);
foreach (SmartRangeNotifier* n, m_notifiers)
emit n->parentRangeChanged(this, m_parentRange, oldParent);
foreach (SmartRangeWatcher* w, m_watchers)
w->parentRangeChanged(this, m_parentRange, oldParent);
DEBUG_PARENT_OVERLAP
}
void SmartRange::setAttribute( Attribute::Ptr attribute )
{
if (attribute == m_attribute)
return;
Attribute::Ptr prev = m_attribute;
m_attribute = attribute;
foreach (SmartRangeNotifier* n, m_notifiers)
emit n->rangeAttributeChanged(this, attribute, prev);
foreach (SmartRangeWatcher* w, m_watchers)
w->rangeAttributeChanged(this, attribute, prev);
}
Attribute::Ptr SmartRange::attribute( ) const
{
return m_attribute;
}
QStringList SmartRange::text( bool block ) const
{
return document()->textLines(*this, block);
}
bool SmartRange::replaceText( const QStringList & text, bool block )
{
return document()->replaceText(*this, text, block);
}
bool SmartRange::removeText( bool block )
{
return document()->removeText(*this, block);
}
static bool rangeEndLessThan(const SmartRange* s1, const SmartRange* s2) {
return s1->end() < s2->end();
}
void SmartRange::rebuildChildStructure() {
///Re-order
qStableSort(m_childRanges.begin(), m_childRanges.end(), rangeEndLessThan);
DEBUG_CHILD_ORDER
///Update overlap
for(int a = 0; a < m_childRanges.size(); ++a) {
SmartRange& overlapper(*m_childRanges[a]);
overlapper.m_overlapCount = 0;
//Increase the overlap of overlapped ranegs
for(int current = a-1; current >= 0; --current) {
SmartRange& range(*m_childRanges[current]);
Q_ASSERT(range.end() <= overlapper.end());
if(range.end() > overlapper.start()) {
++range.m_overlapCount;
}else{
//range.end() <= start(), The range does not overlap, and the same applies for all earlier ranges
break;
}
}
}
DEBUG_CHILD_OVERLAP
}
void SmartRange::rangeChanged( Cursor* c, const Range& from )
{
#ifdef SHOULD_DEBUG_CHILD_ORDER
if (parentRange() ) {
//Make sure the child-order is correct, in respect to "from"
QList<SmartRange*>& parentChildren(parentRange()->m_childRanges);
int index = findIndex(parentChildren, this, &from);
Q_ASSERT(index != -1);
Q_ASSERT(parentChildren[index] == this);
const Range* lastRange = 0;
for(int a = 0; a < index; ++a) {
if(lastRange) {
Q_ASSERT(lastRange->end() <= parentChildren[a]->end());
}
lastRange = parentChildren[a];
}
if(lastRange) {
Q_ASSERT(lastRange->end() <= from.end());
}
if(index+1 < parentChildren.size()) {
Q_ASSERT(from.end() <= parentChildren[index+1]->end());
}
lastRange = &from;
for(int a = index+1; a < parentChildren.size(); ++a) {
if(lastRange) {
Q_ASSERT(lastRange->end() <= parentChildren[a]->end());
}
lastRange = parentChildren[a];
}
}
#endif
Range::rangeChanged(c, from);
// Decide whether the parent range has expanded or contracted, if there is one
if (parentRange() ) {
QList<SmartRange*>& parentChildren(parentRange()->m_childRanges);
int index = findIndex(parentChildren, this, &from);
Q_ASSERT(index != -1);
Q_ASSERT(parentChildren[index] == this);
//Reduce the overlap with all previously overlapping ranges(parentChildren is still sorted by the old end-position)
for(int current = index-1; current >= 0; --current) {
SmartRange& range(*parentChildren[current]);
Q_ASSERT(range.end() <= from.end());
if(range.end() <= from.start()) {
// break; //This range did not overlap before, the same applies for all earlier ranges because of the order
}else{
if(range.m_overlapCount) {
--range.m_overlapCount;
}else{
#ifdef SHOULD_DEBUG_OVERLAP
Q_ASSERT(0);
#endif
}
}
}
//Decrease this ranges overlap from existing ranges behind, since it may be moved so it isn't overlapped any more
for(int current = index+1; current < parentChildren.size(); ++current) {
SmartRange& range(*parentChildren[current]);
Q_ASSERT(range.end() >= from.end());
if(range.start() < from.end())
--m_overlapCount; //The range overlaps newChild
if(!range.m_overlapCount)
break; //If this follower-range isn't overlapped by any other ranges, we can break here.
}
if(from.end() != end()) {
//Update the order in the parent, the ranges must be strictly sorted
if(from.end() > end()) {
//Bubble backwards, the position has been reduced
while(index > 0 && parentChildren[index-1]->end() > end()) {
parentChildren[index] = parentChildren[index-1];
parentChildren[index-1] = this;
--index;
}
}else{
//Bubble forwards, the position has moved forwards
while( index+1 < parentChildren.size() && (parentChildren[index+1]->end() < end()) ) {
parentChildren[index] = parentChildren[index+1];
parentChildren[index+1] = this;
++index;
}
}
}
Q_ASSERT(parentChildren[index] == this);
//Increase the overlap
for(int current = index-1; current >= 0; --current) {
SmartRange& range(*parentChildren[current]);
Q_ASSERT(range.end() <= end());
if(range.end() > start()) {
++range.m_overlapCount;
}else{
//range.end() <= start(), The range does not overlap, and the same applies for all earlier ranges
break;
}
}
//Increase this ranges overlap from existing ranges behind, since it may have been moved
for(int current = index+1; current < parentChildren.size(); ++current) {
SmartRange& range(*parentChildren[current]);
Q_ASSERT(range.end() >= end());
if(range.start() < end())
++m_overlapCount; //The range overlaps newChild
if(!range.m_overlapCount)
break; //If this follower-range isn't overlapped by any other ranges, we can break here.
}
DEBUG_CHILD_ORDER
DEBUG_PARENT_OVERLAP
//Expand the parent in the end, so the overlap is consistent when the parent gets control
if ((start() < from.start() || end() > from.end()))
parentRange()->expandToRange(*this);
}
DEBUG_CHILD_OVERLAP
// Contract child ranges if required
if(!m_childRanges.isEmpty()) {
if (start() > from.start()) {
foreach(SmartRange* child, m_childRanges) {
if(child->start() < start())
child->start() = start();
else if(!child->m_overlapCount)
break; //We can safely break here, because the child is not overlapped
}
}
if (end() < from.end()) {
//We have to create a copy of the child-ranges, because their order may change
QList<SmartRange*> oldChildRanges = m_childRanges;
for(int a = oldChildRanges.size()-1; a >= 0; --a) {
if(oldChildRanges[a]->end() <= end())
break; //Child-ranges are sorted by the end-cursor, so we can just break here.
oldChildRanges[a]->end() = end();
}
}
}
DEBUG_CHILD_ORDER
DEBUG_CHILD_OVERLAP
// SmartCursor and its subclasses take care of adjusting ranges if the tree
// structure is being used.
foreach (SmartRangeNotifier* n, m_notifiers)
if (n->wantsDirectChanges()) {
emit n->rangePositionChanged(this);
emit n->rangeContentsChanged(this);
if (start() == end())
emit n->rangeEliminated(this);
}
foreach (SmartRangeWatcher* w, m_watchers)
if (w->wantsDirectChanges()) {
w->rangePositionChanged(this);
w->rangeContentsChanged(this);
if (start() == end())
w->rangeEliminated(this);
}
}
bool SmartRange::isSmartRange( ) const
{
return true;
}
SmartRange* SmartRange::toSmartRange( ) const
{
return const_cast<SmartRange*>(this);
}
bool SmartRange::hasParent( SmartRange * parent ) const
{
if (parentRange() == parent)
return true;
if (parentRange())
return parentRange()->hasParent(parent);
return false;
}
const QList< SmartRangeWatcher * > & SmartRange::watchers( ) const
{
return m_watchers;
}
void SmartRange::addWatcher( SmartRangeWatcher * watcher )
{
if (!m_watchers.contains(watcher))
m_watchers.append(watcher);
checkFeedback();
}
void SmartRange::removeWatcher( SmartRangeWatcher * watcher )
{
m_watchers.removeAll(watcher);
checkFeedback();
}
SmartRangeNotifier * SmartRange::primaryNotifier( )
{
if (m_notifiers.isEmpty())
m_notifiers.append(createNotifier());
return m_notifiers.first();
}
const QList< SmartRangeNotifier * > SmartRange::notifiers( ) const
{
return m_notifiers;
}
void SmartRange::addNotifier( SmartRangeNotifier * notifier )
{
if (!m_notifiers.contains(notifier))
m_notifiers.append(notifier);
checkFeedback();
}
void SmartRange::removeNotifier( SmartRangeNotifier * notifier )
{
m_notifiers.removeAll(notifier);
checkFeedback();
}
void SmartRange::deletePrimaryNotifier( )
{
if (m_notifiers.isEmpty())
return;
SmartRangeNotifier* n = m_notifiers.first();
removeNotifier(n);
delete n;
}
void SmartRange::checkFeedback( )
{
}
// kate: space-indent on; indent-width 2; replace-tabs on;

View file

@ -1,742 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2003-2005 Hamish Rodda <rodda@kde.org>
Copyright (C) 2008 David Nolden <david.nolden.kdevelop@art-master.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
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 KDELIBS_KTEXTEDITOR_SMARTRANGE_H
#define KDELIBS_KTEXTEDITOR_SMARTRANGE_H
#include <ktexteditor/ktexteditor_export.h>
#include <ktexteditor/range.h>
#include <ktexteditor/smartcursor.h>
#include <ktexteditor/attribute.h>
#include <QtCore/QList>
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#include <QStack>
#endif
class KAction;
namespace KTextEditor
{
class SmartRangeNotifier;
class SmartRangeWatcher;
/**
* \short A Range which is bound to a specific Document, and maintains its position.
*
* \ingroup kte_group_smart_classes
*
* A SmartRange is an extension of the basic Range class. It maintains its
* position in the document and provides extra functionality,
* including:
* \li convenience functions for accessing and manipulating the content
* of the associated document,
* \li adjusting behavior in response to text edits,
* \li forming a tree structure out of multiple SmartRange%s,
* \li providing attribute information for the arbitrary highlighting extension,
* \li allowing KAction%s to be bound to the range (note: not currently implemented), and
* \li providing notification of changes to 3rd party software.
*
* As a result of a smart range's close association with a document, and the processing
* that occurrs as a result, smart ranges may not be copied.
*
* For simplicity of code, ranges always maintain their start position to
* be before or equal to their end position. Attempting to set either the
* start or end of the range beyond the respective end or start will result in
* both values being set to the specified position.
*
* Hierarchical range-trees maintain specific relationships:
* - When a child-range is changed, all parent-ranges are resized so the child-range fits in
* - When a parent-range is changed, all child-ranges are resized so they fit in
*
* This means that parent-ranges always completely contain all their child-ranges. However
* it may lead to unexpected range-changes from the perspective of your application, so keep
* this in mind.
*
* The child-ranges of one smart-range are allowed to overlap each other. However overlaps
* should be omitted where possible, for performance-reasons, and because each range can
* be overlapped by max. 63 sibling-ranges while still rendering correctly.
*
* Create a new SmartRange like this:
* \code
* // Retrieve the SmartInterface
* KTextEditor::SmartInterface* smart =
* qobject_cast<KTextEditor::SmartInterface*>( yourDocument );
*
* if ( smart ) {
* KTextEditor::SmartRange* range = smart->newSmartRange();
* }
* \endcode
*
* When finished with a SmartRange, simply delete it.
*
* \sa Range, SmartRangeNotifier, SmartRangeWatcher, and SmartInterface
*
* \author Hamish Rodda \<rodda@kde.org\>
*/
class KTEXTEDITOR_EXPORT SmartRange : public Range
{
friend class SmartCursor;
public:
/// Determine how the range reacts to characters inserted immediately outside the range.
enum InsertBehavior {
/// Don't expand to encapsulate new characters in either direction. This is the default.
DoNotExpand = 0,
/// Expand to encapsulate new characters to the left of the range.
ExpandLeft = 0x1,
/// Expand to encapsulate new characters to the right of the range.
ExpandRight = 0x2
};
Q_DECLARE_FLAGS(InsertBehaviors, InsertBehavior)
virtual ~SmartRange();
/**
* Returns that this range is a SmartRange.
*/
virtual bool isSmartRange() const;
/**
* Returns this range as a SmartRange, if it is one.
*/
virtual SmartRange* toSmartRange() const;
/**
* \name Position
*
* The following functions provide access and manipulation of the range's position.
* \{
*/
/**
* \copydoc Range::setRange(const Range&)
*
* This function also provides any required adjustment of parent and child ranges,
* and notification of the change if required.
*/
virtual void setRange(const Range& range);
/**
* Get the start point of this range. This version returns a casted
* version of start(), as SmartRange%s always use SmartCursor%s as
* the start() and end().
*
* \returns a reference to the start of this range.
*/
inline SmartCursor& smartStart()
{ return *static_cast<SmartCursor*>(m_start); }
/**
* Get the start point of this range. This version returns a casted
* version of start(), as SmartRange%s always use SmartCursor%s as
* the start() and end().
*
* \returns a const reference to the start of this range.
*/
inline const SmartCursor& smartStart() const
{ return *static_cast<const SmartCursor*>(m_start); }
/**
* Get the end point of this range. This version returns a casted
* version of end(), as SmartRange%s always use SmartCursor%s as
* the start() and end().
*
* \returns a reference to the end of this range.
*/
inline SmartCursor& smartEnd()
{ return *static_cast<SmartCursor*>(m_end); }
/**
* Get the end point of this range. This version returns a casted
* version of end(), as SmartRange%s always use SmartCursor%s as
* the start() and end().
*
* \returns a const reference to the end of this range.
*/
inline const SmartCursor& smartEnd() const
{ return *static_cast<const SmartCursor*>(m_end); }
/**
* \overload confineToRange(const Range&)
* Overloaded version which confines child ranges as well.
*/
virtual bool confineToRange(const Range& range);
/**
* \overload expandToRange(const Range&)
* Overloaded version which expands child ranges as well.
*/
virtual bool expandToRange(const Range& range);
//BEGIN Functionality present from having this range associated with a Document
/**
* \}
*
* \name Document-related functions
*
* The following functions are provided for convenient access to the
* associated Document.
* \{
*/
/**
* Retrieve the document associated with this SmartRange.
*
* \return a pointer to the associated document
*/
Document* document() const;
/**
* Retrieve the text which is contained within this range.
*
* \param block specify whether the text should be returned from the range's visual block, rather
* than all the text within the range.
*/
virtual QStringList text(bool block = false) const;
/**
* Replace text in this range with \p text
*
* \param text text to use as a replacement
* \param block insert this text as a visual block of text rather than a linear sequence
* \return \e true on success, otherwise \e false
*/
virtual bool replaceText(const QStringList &text, bool block = false);
/**
* Remove text contained within this range.
* The range itself will not be deleted.
*
* \param block specify whether the text should be deleted from the range's visual block, rather
* than all the text within the range.
*/
virtual bool removeText(bool block = false);
//END
//BEGIN Behavior
/**
* \}
*
* \name Behavior
*
* The following functions relate to the behavior of this SmartRange.
* \{
*/
/**
* Returns how this range reacts to characters inserted immediately outside the range.
*
* \return the current insert behavior.
*/
InsertBehaviors insertBehavior() const;
/**
* Determine how the range should react to characters inserted immediately outside the range.
*
* \todo does this need a custom function to enable determining of the behavior based on the
* text that is inserted / deleted?
*
* \param behavior the insertion behavior to use for future edits
*
* \sa InsertBehavior
*/
void setInsertBehavior(InsertBehaviors behavior);
//END
//BEGIN Relationships to other ranges
/**
* \}
*
* \name Tree structure
*
* The following functions relate to the tree structure functionality.
* \{
*/
/**
* Returns this range's parent range, if one exists.
*
* At all times, this range will be contained within parentRange().
*
* \return a pointer to the current parent range
*/
inline SmartRange* parentRange() const
{ return m_parentRange; }
/**
* Set this range's parent range.
*
* At all times, this range will be contained within parentRange(). So, if it is outside of the
* new parent to begin with, it will be expanded automatically.
*
* When being inserted into the parent range, the parent range will be fit in between any other
* pre-existing child ranges, and may resize them so as not to overlap. However, once insertion
* has occurred, changing this range directly will only resize the others, it will \e not change
* the order of the ranges. To change the order, unset the parent range, change the range, and
* re-set the parent range.
*
* \param r range to become the new parent of this range
*/
virtual void setParentRange(SmartRange* r);
/**
* Determine whether \a parent is a parent of this range.
*
* \param parent range to check to see if it is a parent of this range.
*
* \return \e true if \a parent is in the parent heirachy, otherwise \e false.
*/
bool hasParent(SmartRange* parent) const;
/**
* Calculate the current depth of this range.
*
* \return the depth of this range, where 0 is no parent, 1 is one parent, etc.
*/
inline int depth() const
{ return m_parentRange ? m_parentRange->depth() + 1 : 0; }
/**
* Returns the range's top parent range, or this range if there are no parents.
*
* \return a pointer to the top parent range
*/
inline SmartRange* topParentRange() const
{ return parentRange() ? parentRange()->topParentRange() : const_cast<SmartRange*>(this); }
/**
* Get the ordered list of child ranges.
*
* To insert a child range, simply set its parent to this range using setParentRange().
*
* \returns a list of child ranges.
*/
const QList<SmartRange*>& childRanges() const;
/**
* Clears child ranges - i.e., removes the text that is covered by the ranges.
* The ranges themselves are not deleted.
*
* \sa removeText()
*/
void clearChildRanges();
/**
* Deletes child ranges - i.e., deletes the SmartRange objects only.
* The underlying text is not affected.
*/
void deleteChildRanges();
/**
* Clears child ranges - i.e., clears the text that is covered by the ranges,
* and deletes the SmartRange objects.
*/
void clearAndDeleteChildRanges();
/**
* Find the child before \p range, if any.
* The order is determined by the range end-cursors.
*
* \param range to seach backwards from
*
* \return the range before \p range if one exists, otherwise null.
*/
SmartRange* childBefore( const SmartRange * range ) const;
/**
* Find the child after \p range, if any.
* The order is determined by the range end-cursors.
*
* \param range to seach forwards from
*
* \return the range after \p range if one exists, otherwise null.
*/
SmartRange* childAfter( const SmartRange * range ) const;
/**
* Finds the most specific range in a heirachy for the given input range
* (ie. the smallest range which wholly contains the input range)
*
* In case of overlaps, the smallest containing range is chosen,
* if there are multiple of the same size, then the first one.
*
* \param input the range to use in searching
*
* \return the deepest range which contains \p input
*/
SmartRange* mostSpecificRange(const Range& input) const;
/**
* Finds the first child range which contains position \p pos.
*
* \param pos the cursor position to use in searching
*
* \return the most shallow range (from and including this range) which
* contains \p pos
*/
SmartRange* firstRangeContaining(const Cursor& pos) const;
/**
* Finds the deepest range in the heirachy which contains position \p pos.
* Allows the caller to determine which ranges were entered and exited
* by providing pointers to QStack<SmartRange*>.
*
* If child-ranges overlap in the given position,
* the first smallest one is returned.
*
* \param pos the cursor position to use in searching
* \param rangesEntered provide a QStack<SmartRange*> here to find out
* which ranges were entered during the traversal.
* The top item was the first descended.
* \param rangesExited provide a QStack<SmartRange*> here to find out
* which ranges were exited during the traversal.
* The top item was the first exited.
*
* \return the deepest range (from and including this range) which
* contains \p pos, or null if no ranges contain this position.
*/
SmartRange* deepestRangeContaining(const Cursor& pos,
QStack<SmartRange*>* rangesEntered = 0L,
QStack<SmartRange*>* rangesExited = 0L) const;
QList<SmartRange*> deepestRangesContaining(const Cursor& pos) const;
/**
* Returns the count of ranges within the parent-range
* that end behind this range, and that overlap this range.
*/
int overlapCount() const;
//END
//BEGIN Arbitrary highlighting
/**
* \}
*
* \name Arbitrary highlighting
*
* The following functions relate to arbitrary highlighting capabilities.
* \{
*/
/**
* Gets the active Attribute for this range.
*
* \return a pointer to the active attribute
*/
Attribute::Ptr attribute() const;
/**
* Sets the currently active attribute for this range.
*
* \param attribute Attribute to assign to this range. If null, simply
* removes the previous Attribute.
*
* \note \ref SmartInterface::addHighlightToDocument must be called with the top-range before
* the highlighting can work.
*/
void setAttribute(Attribute::Ptr attribute);
//END
//BEGIN Action binding
/**
* \}
*
* \name Action binding
*
* The following functions relate to action binding capabilities.
*
* \note This feature is currently not implemented (ETA KDE 4.1).
* \{
*/
/**
* Associate an action with this range. The associated action(s) will be
* enabled when the caret enters the range, and disabled them on exit.
* The action is also added to the context menu when the mouse/caret is within
* an associated range.
*
* \param action KAction to associate with this range
*/
void associateAction(KAction* action);
/**
* Remove the association with an action from this range; it will no
* longer be managed.
*
* \param action KAction to dissociate from this range
*/
void dissociateAction(KAction* action);
/**
* Access the list of currently associated KAction%s.
*
* \return the list of associated actions
*/
const QList<KAction*>& associatedActions() const
{ return m_associatedActions; }
/**
* Clears all associations between KAction%s and this range.
*/
void clearAssociatedActions();
//END
//BEGIN Notification methods
/**
* \}
*
* \name Notification
*
* The following functions allow for changes related to this range to be
* notified to 3rd party programs.
* \{
*/
/**
* Connect to a notifier to receive signals indicating change of state of this range.
* This function creates a notifier if none is already bound to this range; if one has
* already been assigned this will return the first notifier.
*
* If you have finished with notifications for a reasonable period of time you can
* save memory by calling deleteNotifier().
*/
SmartRangeNotifier* primaryNotifier();
/**
* Returns a list of notifiers which are receiving signals indicating change of state
* of this range. These notifiers may be receiving signals from other ranges as well.
*/
const QList<SmartRangeNotifier*> notifiers() const;
/**
* Register a notifier to receive signals indicating change of state of this range.
*
* NOTE: Make sure you call @c removeNotifier() when deleting the notifier before the range.
*
* \param notifier notifier to register. Ownership is not transferred.
*/
void addNotifier(SmartRangeNotifier* notifier);
/**
* Deregister a notifier and no longer deliver signals indicating change of state of this range.
*
* \param notifier notifier to deregister.
*/
void removeNotifier(SmartRangeNotifier* notifier);
/**
* When finished with the primaryNotifier(), call this method to save memory by
* having the SmartRangeNotifier deleted.
*
* \note If a notifier was first registered via addNotifier() rather than created inside
* primaryNotifier(), this method will delete that notifier. Text editor implementations
* should not use notifiers for internal purposes, instead use watchers (faster and
* has documentation to this effect)
*/
void deletePrimaryNotifier();
/**
* Returns a list of registered SmartRangeWatchers.
*
* \note this function may return watchers internal to the text editor's implementation,
* eg. in the case of arbitrary highlighting and kate part. Removing these watchers
* with removeWatcher() will result in malfunction.
*/
const QList<SmartRangeWatcher*>& watchers() const;
/**
* Register a SmartRangeWatcher to receive calls indicating change of state
* of this range. To finish receiving notifications, call removeWatcher().
*
* NOTE: Make sure you call @c removeWachter() when deleting the notifier before the range.
*
* \param watcher the instance of a class which is to receive
* notifications about changes to this range.
*/
void addWatcher(SmartRangeWatcher* watcher);
/**
* Stop delivery of notifications to a SmartRangeWatcher.
*
* \param watcher the watcher that no longer wants notifications.
*/
void removeWatcher(SmartRangeWatcher* watcher);
//!\}
//END
/**
* Assignment operator. Assigns the current position of the provided range, \p rhs, only;
* does not assign watchers, notifiers, behavior etc.
*
* \note The assignment will be performed even if the provided range belongs to
* another Document.
*
* \param rhs range to assign to this range.
*
* \return a reference to this range, after assignment has occurred.
*
* \see setRange()
*/
inline SmartRange& operator=(const SmartRange& rhs)
{ setRange(rhs); return *this; }
/**
* Assignment operator. Assigns the current position of the provided range, \p rhs.
*
* \param rhs range to assign to this range.
*
* \return a reference to this range, after assignment has occurred.
*
* \see setRange()
*/
inline SmartRange& operator=(const Range& rhs)
{ setRange(rhs); return *this; }
protected:
/**
* Constructor for subclasses to utilise. Protected to prevent direct
* instantiation.
*
* \note 3rd party developers: you do not (and should not) need to subclass
* the Smart* classes; instead, use the SmartInterface to create instances.
*
* \internal
*
* \param start the start cursor to use - ownership is taken
* \param end the end cursor to use - ownership is taken
* \param parent the parent range if this is a subrange of another range
* \param insertBehavior the behavior of this range when an insert happens
* immediately outside the range.
*/
SmartRange(SmartCursor* start, SmartCursor* end, SmartRange* parent = 0L, InsertBehaviors insertBehavior = DoNotExpand);
/**
* \internal
*
* Notify this range that one or both of the cursors' position has changed directly.
*
* \param cursor the cursor that changed. If null, both cursors have changed.
* \param from the previous position of this range
*/
virtual void rangeChanged(Cursor* cursor, const Range& from);
/**
* \internal
*
* This routine is called when the range changes how much feedback it may need, eg. if it adds an action.
*/
virtual void checkFeedback();
/**
* \internal
*
* Called to request creation of a new SmartRangeNotifier for this object.
*/
virtual SmartRangeNotifier* createNotifier() = 0;
/**
* Is called after child-ranges have changed internally without the rangeChanged() notification, for example
* after translations. It rebuilds the child-structure, so it is consistent again.
*/
void rebuildChildStructure();
private:
/**
* \internal
* Copy constructor: Disable copying of this class.
*/
SmartRange(const SmartRange&);
/**
* \internal
* Implementation of deepestRangeContaining().
*/
SmartRange* deepestRangeContainingInternal(const Cursor& pos,
QStack<SmartRange*>* rangesEntered,
QStack<SmartRange*>* rangesExited,
bool first = false) const;
/**
* \internal
*
* New child classes call this to register themselves.
*/
void insertChildRange(SmartRange* newChild);
/**
* \internal
*
* Disassociating child classes call this to de-register themselves.
*/
void removeChildRange(SmartRange* newChild);
/**
* \internal
*
* This range's current attribute.
*/
Attribute::Ptr m_attribute;
SmartRange* m_parentRange;
/**
* \internal
*
* The list of this range's child ranges, sorted by end-cursor.
*/
QList<SmartRange*> m_childRanges;
/**
* \internal
*
* The list of this range's associated KAction%s.
*/
QList<KAction*> m_associatedActions;
/**
* \internal
*
* The list of registered SmartRangeNotifiers.
*/
QList<SmartRangeNotifier*> m_notifiers;
/**
* \internal
*
* The list of registered SmartRangeWatchers.
*/
QList<SmartRangeWatcher*> m_watchers;
/**
* \internal
*
* Whether this range owns the currently assigned attribute or not.
*/
bool m_ownsAttribute :1;
/**
* \internal
*
* How many ranges that end behind this one at least partially overlap it.
* Currently max. 64 overlaps are allowed.
*/
uchar m_overlapCount:6;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(SmartRange::InsertBehaviors)
}
#endif
// kate: space-indent on; indent-width 2; replace-tabs on;

View file

@ -1,211 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2003-2005 Hamish Rodda <rodda@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 version 2 as published by the Free Software Foundation.
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 KDELIBS_KTEXTEDITOR_SMARTRANGENOTIFIER_H
#define KDELIBS_KTEXTEDITOR_SMARTRANGENOTIFIER_H
#include <ktexteditor/ktexteditor_export.h>
#include <QtCore/QObject>
#include <ktexteditor/attribute.h>
// TODO: Should SmartRangeWatcher become a base class for SmartRangeNotifier?
namespace KTextEditor
{
class SmartRange;
class View;
/**
* \short A class which provides notifications of state changes to a SmartRange via QObject signals.
*
* \ingroup kte_group_smart_classes
*
* This class provides notifications of changes to the position or contents of
* a SmartRange via QObject signals.
*
* If you prefer to receive notifications via virtual inheritance, see SmartRangeWatcher.
*
* \sa SmartRange, SmartRangeWatcher
*
* \author Hamish Rodda \<rodda@kde.org\>
*/
class KTEXTEDITOR_EXPORT SmartRangeNotifier : public QObject
{
Q_OBJECT
friend class SmartRange;
public:
/**
* Default constructor.
*/
SmartRangeNotifier();
/**
* Returns whether this notifier will notify of changes that happen
* directly to the range, e.g. by calls to SmartCursor::setRange(), or by
* direct assignment to either of the start() or end() cursors, rather
* than just when surrounding text changes.
*/
bool wantsDirectChanges() const;
/**
* Set whether this notifier should notify of changes that happen
* directly to the range, e.g. by calls to SmartCursor::setRange(), or by
* direct assignment to either of the start() or end() cursors, rather
* than just when surrounding text changes.
*
* \param wantsDirectChanges whether this watcher should provide notifications for direct changes.
*/
void setWantsDirectChanges(bool wantsDirectChanges);
Q_SIGNALS:
/**
* The range's position changed.
*
* \param range pointer to the range which generated the notification.
*/
void rangePositionChanged(KTextEditor::SmartRange* range);
/**
* The contents of the range changed.
*
* \param range pointer to the range which generated the notification.
*/
void rangeContentsChanged(KTextEditor::SmartRange* range);
/**
* The contents of the range changed.
*
* \warning This notification is special in that it is only emitted by
* the top range of a heirachy, and also gives the furthest descendant child range which still
* encompasses the whole change (see \p contents).
*
* \param range pointer to the range which generated the notification.
* \param mostSpecificChild the child range which both contains the entire change and is
* the furthest descendant of this range.
*/
void rangeContentsChanged(KTextEditor::SmartRange* range, KTextEditor::SmartRange* mostSpecificChild);
/**
* The mouse cursor on \a view entered \p range.
*
* \todo For now, to receive this notification, the range heirachy must be registered with
* the SmartInterface as for arbitrary highlighting with dynamic highlighting.
* Need to add another (and probably simplify existing) method.
*
* \param range pointer to the range which generated the notification.
* \param view view over which the mouse moved to generate the notification
*/
void mouseEnteredRange(KTextEditor::SmartRange* range, KTextEditor::View* view);
/**
* The mouse cursor on \a view exited \p range.
*
* \todo For now, to receive this notification, the range heirachy must be registered with
* the SmartInterface as for arbitrary highlighting with dynamic highlighting.
* Need to add another (and probably simplify existing) method.
*
* \param range pointer to the range which generated the notification.
* \param view view over which the mouse moved to generate the notification
*/
void mouseExitedRange(KTextEditor::SmartRange* range, KTextEditor::View* view);
/**
* The caret on \a view entered \p range.
*
* \todo For now, to receive this notification, the range heirachy must be registered with
* the SmartInterface as for arbitrary highlighting with dynamic highlighting.
* Need to add another (and probably simplify existing) method.
*
* \param range pointer to the range which generated the notification.
* \param view view over which the mouse moved to generate the notification
*/
void caretEnteredRange(KTextEditor::SmartRange* range, KTextEditor::View* view);
/**
* The caret on \a view exited \p range.
*
* \todo For now, to receive this notification, the range heirachy must be registered with
* the SmartInterface as for arbitrary highlighting with dynamic highlighting.
* Need to add another (and probably simplify existing) method.
*
* \param range pointer to the range which generated the notification.
* \param view view over which the mouse moved to generate the notification
*/
void caretExitedRange(KTextEditor::SmartRange* range, KTextEditor::View* view);
/**
* The range now contains no characters (ie. the start and end cursors are the same).
*
* \param range pointer to the range which generated the notification.
*/
void rangeEliminated(KTextEditor::SmartRange* range);
/**
* The SmartRange instance specified by \p range is being deleted.
*
* \param range pointer to the range which is about to be deleted. It is
* still safe to access information at this point.
*/
void rangeDeleted(KTextEditor::SmartRange* range);
/**
* The range's parent was changed.
*
* \param range pointer to the range which generated the notification.
* \param newParent pointer to the range which was is now the parent range.
* \param oldParent pointer to the range which used to be the parent range.
*/
void parentRangeChanged(KTextEditor::SmartRange* range, KTextEditor::SmartRange* newParent, KTextEditor::SmartRange* oldParent);
/**
* The range \a child was inserted as a child range into the current \a range.
*
* \param range pointer to the range which generated the notification.
* \param child pointer to the range which was inserted as a child range.
*/
void childRangeInserted(KTextEditor::SmartRange* range, KTextEditor::SmartRange* child);
/**
* The child range \a child was removed from the current \a range.
*
* \param range pointer to the range which generated the notification.
* \param child pointer to the child range which was removed.
*/
void childRangeRemoved(KTextEditor::SmartRange* range, KTextEditor::SmartRange* child);
/**
* The highlighting attribute of \a range was changed from \a previousAttribute to
* \a currentAttribute.
*
* \param range pointer to the range which generated the notification.
* \param currentAttribute the attribute newly assigned to this range
* \param previousAttribute the attribute previously assigned to this range
*/
void rangeAttributeChanged(KTextEditor::SmartRange* range, KTextEditor::Attribute::Ptr currentAttribute, KTextEditor::Attribute::Ptr previousAttribute);
private:
bool m_wantDirectChanges;
};
}
#endif
// kate: space-indent on; indent-width 2; replace-tabs on;

View file

@ -1,212 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2003-2005 Hamish Rodda <rodda@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 version 2 as published by the Free Software Foundation.
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 KDELIBS_KTEXTEDITOR_SMARTRANGEWATCHER_H
#define KDELIBS_KTEXTEDITOR_SMARTRANGEWATCHER_H
#include <ktexteditor/ktexteditor_export.h>
#include <QtCore/QObject>
#include <ktexteditor/attribute.h>
// TODO: Should SmartRangeWatcher become a base class for SmartRangeNotifier?
namespace KTextEditor
{
class SmartRange;
class View;
/**
* \short A class which provides notifications of state changes to a SmartRange via virtual inheritance.
*
* \ingroup kte_group_smart_classes
*
* This class provides notifications of changes to the position or contents of
* a SmartRange via virtual inheritance.
*
* If you prefer to receive notifications via QObject signals, see SmartRangeNotifier.
*
* Before destruction, you must unregister the watcher from any ranges it is watching.
*
* \sa SmartRange, SmartRangeNotifier
*
* \author Hamish Rodda \<rodda@kde.org\>
*/
class KTEXTEDITOR_EXPORT SmartRangeWatcher
{
public:
/**
* Default constructor
*/
SmartRangeWatcher();
/**
* Virtual destructor
*/
virtual ~SmartRangeWatcher();
/**
* Returns whether this watcher will be notified of changes that happen
* directly to the range, e.g. by calls to SmartCursor::setRange(), or by
* direct assignment to either of the start() or end() cursors, rather
* than just when surrounding text changes.
*/
bool wantsDirectChanges() const;
/**
* Set whether this watcher should be notified of changes that happen
* directly to the range, e.g. by calls to SmartCursor::setRange(), or by
* direct assignment to either of the start() or end() cursors, rather
* than just when surrounding text changes.
*
* \param wantsDirectChanges whether this watcher should receive notifications for direct changes.
*/
void setWantsDirectChanges(bool wantsDirectChanges);
/**
* The range's position changed.
*
* \param range pointer to the range which generated the notification.
*/
virtual void rangePositionChanged(SmartRange* range);
/**
* The contents of the range changed.
*
* \param range pointer to the range which generated the notification.
*/
virtual void rangeContentsChanged(SmartRange* range);
/**
* The contents of the range changed. This notification is special in that it is only emitted by
* the top range of a heirachy, and also gives the furthest descendant child range which still
* encompasses the whole change (see \p contents).
*
* \param range the range which has changed
* \param mostSpecificChild the child range which both contains the entire change and is
* the furthest descendant of this range.
*/
virtual void rangeContentsChanged(SmartRange* range, SmartRange* mostSpecificChild);
/**
* The mouse cursor on \a view entered \p range.
*
* \todo For now, to receive this notification, the range heirachy must be registered with
* the SmartInterface as for arbitrary highlighting with dynamic highlighting.
* Need to add another (and probably simplify existing) method.
*
* \param range pointer to the range which generated the notification.
* \param view view over which the mouse moved to generate the notification
*/
virtual void mouseEnteredRange(SmartRange* range, View* view);
/**
* The mouse cursor on \a view exited \p range.
*
* \todo For now, to receive this notification, the range heirachy must be registered with
* the SmartInterface as for arbitrary highlighting with dynamic highlighting.
* Need to add another (and probably simplify existing) method.
*
* \param range pointer to the range which generated the notification.
* \param view view over which the mouse moved to generate the notification
*/
virtual void mouseExitedRange(SmartRange* range, View* view);
/**
* The caret on \a view entered \p range.
*
* \todo For now, to receive this notification, the range heirachy must be registered with
* the SmartInterface as for arbitrary highlighting with dynamic highlighting.
* Need to add another (and probably simplify existing) method.
*
* \param range pointer to the range which generated the notification.
* \param view view over which the mouse moved to generate the notification
*/
virtual void caretEnteredRange(SmartRange* range, View* view);
/**
* The caret on \a view exited \p range.
*
* \todo For now, to receive this notification, the range heirachy must be registered with
* the SmartInterface as for arbitrary highlighting with dynamic highlighting.
* Need to add another (and probably simplify existing) method.
*
* \param range pointer to the range which generated the notification.
* \param view view over which the mouse moved to generate the notification
*/
virtual void caretExitedRange(SmartRange* range, View* view);
/**
* The range now contains no characters (ie. the start and end cursors are the same).
*
* \param range pointer to the range which generated the notification.
*/
virtual void rangeEliminated(SmartRange* range);
/**
* The SmartRange instance specified by \p range is being deleted.
*
* \param range pointer to the range which is about to be deleted. It is
* still safe to access information at this point.
*/
virtual void rangeDeleted(SmartRange* range);
/**
* The range's parent was changed.
*
* \param range pointer to the range which generated the notification.
* \param newParent pointer to the range which was is now the parent range.
* \param oldParent pointer to the range which used to be the parent range.
*/
virtual void parentRangeChanged(SmartRange* range, SmartRange* newParent, SmartRange* oldParent);
/**
* The range \a child was inserted as a child range into the current \a range.
*
* \param range pointer to the range which generated the notification.
* \param child pointer to the range which was inserted as a child range.
*/
virtual void childRangeInserted(SmartRange* range, SmartRange* child);
/**
* The child range \a child was removed from the current \a range.
*
* \param range pointer to the range which generated the notification.
* \param child pointer to the child range which was removed.
*/
virtual void childRangeRemoved(SmartRange* range, SmartRange* child);
/**
* The highlighting attribute of \a range was changed from \a previousAttribute to
* \a currentAttribute.
*
* \param range pointer to the range which generated the notification.
* \param currentAttribute the attribute newly assigned to this range
* \param previousAttribute the attribute previously assigned to this range
*/
virtual void rangeAttributeChanged(SmartRange* range, Attribute::Ptr currentAttribute, Attribute::Ptr previousAttribute);
private:
bool m_wantDirectChanges;
};
}
#endif
// kate: space-indent on; indent-width 2; replace-tabs on;

View file

@ -28,7 +28,6 @@
// widget
#include <QtGui/QWidget>
#include <QMenu>
namespace KTextEditor
@ -499,7 +498,7 @@ class KTEXTEDITOR_EXPORT View : public QWidget, public KXMLGUIClient
* \see selectionRange(), selection()
*
* \todo rodda - is this really needed? it can now be accomplished with
* SmartCursor::advance()
* Cursor::advance()
*/
virtual bool setSelection ( const Cursor &position,
int length,