Source Code (Use browser search to find items of interest.)
Class Index
kdelibs'KCompletion (./kdelibs/kdecore/kcompletion.h:119)
class KCompletion : public QObject
{
Q_OBJECT
public:
/**
* Constructor, nothing special here :)
*/
KCompletion();
// FIXME: copy constructor, assignment constructor...
/**
* Destructor, nothing special here, either.
*/
virtual ~KCompletion();
/**
* Attempts to find an item in the list of available completions,
* that begins with string. Will either return the first (if more than one
* match) matching item or QString::null, if no match was found. In the
* latter case, a beep will be issued, depending on @ref isSoundsEnabled().
* If a match was found, it will also be emitted via the signal
* @ref match().
*
* If this is called twice or more often with the same string while no
* items were added or removed in the meantime, all available completions
* will be emitted via the signal @ref matches().
* This happens only in shell-completion-mode.
*
* @returns the matching item, or QString::null if there is no matching
* item.
* @see #slotMakeCompletion
*/
virtual QString makeCompletion( const QString& string );
/**
* @returns the next item from the matching-items-list
* When reaching the beginning, the list is rotated, so it will return
* the last match. When there is no match, QString::null is returned and
* a beep will be issued, depending on @ref isSoundsEnabled().
* @see #slotPreviousMatch
*/
QString previousMatch();
/**
* @returns the previous item from the matching-items-list
* When reaching the last item, the list is rotated, so it will return
* the first match. When there is no match, QString::null is returned and
* a beep will be issued, depending on @ref isSoundsEnabled().
* @see #slotNextMatch
*/
QString nextMatch();
/**
* @returns the last match. Might be useful if you need to check whether
* a completion is different from the last one.
* QString::null is returned when there is no last match.
*/
virtual const QString& lastMatch() const { return myLastMatch; }
/**
* @returns a list of all items inserted into KCompletion. This is useful
* if you need to save the state of a KCompletion object and restore it
* later.
* @see #setItems
*/
QStringList items() const;
/**
* Sets the completion mode to Auto/Manual (see @ref KCompletion
* documentation), Shell or None.
* If you don't set the mode explicitly, the global default value
* KGlobalSettings::completionMode() is used.
* @ref KGlobalSettings::CompletionNone disables completion.
* @see #completionMode
* @see #KGlobalSettings::completionMode
*/
void setCompletionMode( KGlobalSettings::Completion mode );
/**
* @returns the current completion mode.
* May be different from @ref KGlobalSettings::completionMode(), if you
* explicitly called @ref setCompletionMode().
* @see #setCompletionMode
*/
KGlobalSettings::Completion completionMode() const { return myCompletionMode; }
/**
* Setting this to true makes us go into sorted mode (doh).
* Completion will then always return the alphabetically first match.
* If set to false, the order is the same as the items were inserted.
* Note: this only affects new inserted items, already existing items will
* stay in the current order. So you probably want to call setSorted( true )
* before inserting items, when you want everything sorted.
* Default is false, not sorted.
* @see #isSorted
*/
void setSorted( bool enable ) { mySorting = enable; }
/**
* Setting this to true makes KCompletion behave case insensitively.
* E.g. makeCompletion( "CA" ); might return "carp@cs.tu-berlin.de".
* Default is false (case sensitive).
* @see #ignoreCase
*/
// void setIgnoreCase( bool ignoreCase ) { myIgnoreCase = ignoreCase; }
/**
* @returns whether KCompletion acts case insensitively or not.
* Default is false (case sensitive).
* @see #setIgnoreCase
*/
// bool ignoreCase() const { return myIgnoreCase; }
/**
* @returns true if the completion-items are alphabetically sorted and
* false if the order of insertion is used.
* @see #setSorted
*/
bool isSorted() const { return mySorting; }
/**
* @returns a list of all matching items. Might take some time, when you
* have LOTS of items.
*/
QStringList allMatches() { return findAllCompletions( myLastString ); }
/**
* Enables playing a sound when
* @li @ref makeCompletion() can't find a match
* @li there is a partial completion
* @li @ref nextMatch() or @ref previousMatch() hit the last possible
* match -> rotation
*
* @see #disableSounds
* @see #isSoundEnabled
*/
void enableSounds() { myBeep = true; }
/**
* Disables playing a sound when
* @li @ref makeCompletion() can't find a match
* @li there is a partial completion
*
* Sounds are only played in shell-completion mode. Default is enabled
* @see #enableSounds
* @see #isSoundEnabled
*/
void disableSounds() { myBeep = false; }
/**
* Tells you whether KCompletion will issue beeps (@ref KApplication::beep())
* Beeps only in manual-completion mode
* Default is enabled
* @see #enableSounds
* @see #disableSounds
*/
bool isSoundsEnabled() const { return myBeep; }
public slots:
/**
* Attempts to complete "string" and emits the completion via @ref match().
* Same as @ref makeCompletion() (just as a slot).
* @see #makeCompletion
*/
void slotMakeCompletion( const QString& string ) {
(void) makeCompletion( string );
}
/**
* Searches the previous matching item and emits it via @ref match()
* Same as @ref previousMatch() (just as a slot).
* @see #previousMatch
*/
void slotPreviousMatch() {
(void) previousMatch();
}
/**
* Searches the next matching item and emits it via @ref match()
* Same as @ref nextMatch() (just as a slot).
* @see #nextMatch
*/
void slotNextMatch() {
(void) nextMatch();
}
/**
* @returns true when more than one match is found
* @see #multipleMatches
*/
bool hasMultipleMatches() const { return myHasMultipleMatches; }
/**
* Sets the list of items available for completion. Removes all previous
* items.
* @see #items
*/
void setItems( const QStringList& );
/**
* Adds an item to the list of available completions.
* Resets the current item-state (@ref previousMatch() and @ref nextMatch()
* won't work anymore).
*/
void addItem( const QString& );
/**
* Removes an item from the list of available completions.
* Resets the current item-state (@ref previousMatch() and @ref nextMatch()
* won't work anymore).
*/
void removeItem( const QString& );
/**
* Clears the list of inserted items.
*/
void clear();
signals:
/**
* The matching item. Will be emitted by @ref makeCompletion(),
* @ref previousMatch() or @ref nextMatch(). May be QString::null if there is
* no matching item.
*/
void match( const QString& );
/**
* All matching items. Will be emitted by @ref makeCompletion() in shell-
* completion-mode, when the same string is passed to makeCompletion twice
* or more often.
*/
void matches( const QStringList& );
/**
* This signal is emitted, when calling @ref makeCompletion() and more than
* one matching item is found.
* @see #hasMultipleMatches
*/
void multipleMatches();
protected:
/**
* This method is called after a completion is found and before the
* matching string is emitted. You can override this method to modify the
* string that will be emitted.
* This is necessary e.g. in @ref KURLCompletion, where files with spaces
* in their names are shown escaped ("filename\ with\ spaces"), but stored
* unescaped inside KCompletion.
* Never delete that pointer!
*
* Default implementation does nothing.
* @see #postProcessMatches
*/
virtual void postProcessMatch( QString * /*match*/ ) {}
/**
* This method is called before a list of all available completions is
* emitted via @ref matches. You can override this method to modify the
* list which that will be emitted.
* Never delete that pointer!
*
* Default implementation does nothing.
* @see #postProcessMatch
*/
virtual void postProcessMatches( QStringList * /*matches*/ ) {}
private:
void addItemInternal( const QString& );
QString findCompletion( const QString& string );
const QStringList& findAllCompletions( const QString& );
void extractStringsFromNode( const KCompTreeNode *,
const QString& beginning,
QStringList *matches ) const;
enum BeepMode { NoMatch, PartialMatch, Rotation };
void doBeep( BeepMode );
QStringList myMatches;
KGlobalSettings::Completion myCompletionMode;
QString myLastString;
QString myLastMatch;
QString myCurrentMatch;
KCompTreeNode * myTreeRoot;
QStringList myRotations;
bool mySorting;
bool myBeep;
bool myBackwards;
bool myIgnoreCase;
bool myHasMultipleMatches;
int myItemIndex; // FIXME
uint myRotationIndex;
KCompletionPrivate *d;
};
/**
* An abstract base class for adding completion feature
* into widgets.
*
* This is a convienence class that tries to provide
* the common functions needed to add support for
* completion into widgets. Refer to @ref KLineEdit
* or @ref KComboBox to see how to such support can be
* added using this base class.
*
* NOTE: Do not forget to provide an implementation for
* the protected pure virtual method @ref connectSignals()
* if you do not want the class to be abstract.
*
* @short An abstract class for using KCompletion in widgets
* @author Dawit Alemayehu <adawit@earthlink.net>
*/
kdelibs'KCompletion::KCompletion() (./kdelibs/kdecore/kcompletion.cpp:29)
KCompletion::KCompletion()
{
myCompletionMode = KGlobalSettings::completionMode();
myTreeRoot = new KCompTreeNode;
mySorting = false;
myBeep = true;
myIgnoreCase = false;
myRotationIndex = 0;
}
kdelibs'KCompletion::~KCompletion() (./kdelibs/kdecore/kcompletion.cpp:39)
KCompletion::~KCompletion()
{
delete myTreeRoot;
}
kdelibs'KCompletion::setItems() (./kdelibs/kdecore/kcompletion.cpp:45)
void KCompletion::setItems( const QStringList& items )
{
myMatches.clear();
myRotationIndex = 0;
myLastString = QString::null;
QStringList::ConstIterator it;
for ( it = items.begin(); it != items.end(); ++it )
addItemInternal( *it );
}
kdelibs'KCompletion::items() (./kdelibs/kdecore/kcompletion.cpp:57)
QStringList KCompletion::items() const
{
QStringList list;
extractStringsFromNode( myTreeRoot, QString::null, &list );
return list;
}
kdelibs'KCompletion::addItem() (./kdelibs/kdecore/kcompletion.cpp:66)
void KCompletion::addItem( const QString& item )
{
myMatches.clear();
myRotationIndex = 0;
myLastString = QString::null;
addItemInternal( item );
}
kdelibs'KCompletion::addItemInternal() (./kdelibs/kdecore/kcompletion.cpp:76)
void KCompletion::addItemInternal( const QString& item )
{
QChar ch;
KCompTreeNode *node = myTreeRoot;
for ( uint i = 0; i < item.length(); i++ ) {
ch = item.at( i );
node = node->insert( ch, mySorting );
}
node->insert( 0x0, true ); // add 0x0-item as delimiter
}
kdelibs'KCompletion::removeItem() (./kdelibs/kdecore/kcompletion.cpp:90)
void KCompletion::removeItem( const QString& item )
{
myMatches.clear();
myRotationIndex = 0;
myLastString = QString::null;
myTreeRoot->remove( item );
}
kdelibs'KCompletion::clear() (./kdelibs/kdecore/kcompletion.cpp:100)
void KCompletion::clear()
{
myMatches.clear();
myRotationIndex = 0;
myLastString = QString::null;
delete myTreeRoot;
myTreeRoot = new KCompTreeNode;
}
kdelibs'KCompletion::makeCompletion() (./kdelibs/kdecore/kcompletion.cpp:111)
QString KCompletion::makeCompletion( const QString& string )
{
if ( myCompletionMode == KGlobalSettings::CompletionNone )
return QString::null;
kdDebug(0) << "KCompletion: completing: " << debugString( string ) << endl;
myMatches.clear();
myRotationIndex = 0;
myHasMultipleMatches = false;
myLastMatch = myCurrentMatch;
// in Shell-completion-mode, emit all matches when we get the same
// complete-string twice
if ( myCompletionMode == KGlobalSettings::CompletionShell &&
string == myLastString ) {
myMatches = findAllCompletions( string );
postProcessMatches( &myMatches );
emit matches( myMatches );
}
QString completion = findCompletion( string );
if ( myHasMultipleMatches )
emit multipleMatches();
myLastString = string;
myCurrentMatch = completion;
if ( !string.isEmpty() ) { // only emit match when string != ""
kdDebug(0) << "KCompletion: Match: " << completion;
postProcessMatch( &completion );
emit match( completion );
}
else
postProcessMatch( &completion );
if ( completion.isNull() )
doBeep( NoMatch );
return completion;
}
kdelibs'KCompletion::setCompletionMode() (./kdelibs/kdecore/kcompletion.cpp:155)
void KCompletion::setCompletionMode( KGlobalSettings::Completion mode )
{
myCompletionMode = mode;
}
/////////////////////////////////////////////////////
///////////////// tree operations ///////////////////
kdelibs'KCompletion::nextMatch() (./kdelibs/kdecore/kcompletion.cpp:166)
QString KCompletion::nextMatch()
{
QString completion;
myLastMatch = myCurrentMatch;
if ( myMatches.isEmpty() ) {
myMatches = findAllCompletions( myLastString );
completion = myMatches.first();
myCurrentMatch = completion;
postProcessMatch( &completion );
emit match( completion );
return completion;
}
myLastMatch = myMatches[ myRotationIndex++ ];
if ( myRotationIndex == myMatches.count() -1 )
doBeep( Rotation ); // indicate last matching item -> rotating
else if ( myRotationIndex == myMatches.count() )
myRotationIndex = 0;
completion = myMatches[ myRotationIndex ];
myCurrentMatch = completion;
postProcessMatch( &completion );
emit match( completion );
return completion;
}
kdelibs'KCompletion::previousMatch() (./kdelibs/kdecore/kcompletion.cpp:197)
QString KCompletion::previousMatch()
{
QString completion;
myLastMatch = myCurrentMatch;
if ( myMatches.isEmpty() ) {
myMatches = findAllCompletions( myLastString );
completion = myMatches.last();
myCurrentMatch = completion;
postProcessMatch( &completion );
emit match( completion );
return completion;
}
myLastMatch = myMatches[ myRotationIndex ];
if ( myRotationIndex == 1 )
doBeep( Rotation ); // indicate first item -> rotating
else if ( myRotationIndex == 0 )
myRotationIndex = myMatches.count();
myRotationIndex--;
completion = myMatches[ myRotationIndex ];
myCurrentMatch = completion;
postProcessMatch( &completion );
emit match( completion );
return completion;
}
// tries to complete "string" from the tree-root
kdelibs'KCompletion::findCompletion() (./kdelibs/kdecore/kcompletion.cpp:230)
QString KCompletion::findCompletion( const QString& string )
{
QChar ch;
QString completion;
const KCompTreeNode *node = myTreeRoot;
// start at the tree-root and try to find the search-string
for( uint i = 0; i < string.length(); i++ ) {
ch = string.at( i );
node = node->find( ch, myIgnoreCase );
if ( node )
completion += ch;
else
return QString::null; // no completion
}
// Now we have the last node of the to be completed string.
// Follow it as long as it has exactly one child (= longest possible
// completion)
while ( node->childrenCount() == 1 ) {
node = node->firstChild();
if ( !node->isNull() )
completion += *node;
}
// if multiple matches and auto-completion mode
// -> find the first complete match
if ( node && node->childrenCount() > 1 ) {
myHasMultipleMatches = true;
if ( myCompletionMode == KGlobalSettings::CompletionAuto ||
myCompletionMode == KGlobalSettings::CompletionMan ) {
myRotationIndex = 1;
while ( (node = node->firstChild()) ) {
if ( !node->isNull() )
completion += *node;
else
break;
}
}
else
doBeep( PartialMatch ); // partial match -> beep
}
return completion;
}
kdelibs'KCompletion::findAllCompletions() (./kdelibs/kdecore/kcompletion.cpp:282)
const QStringList& KCompletion::findAllCompletions( const QString& string )
{
kdDebug(0) << "*** finding all completions for " << string << endl;
myMatches.clear();
myRotationIndex = 0;
if ( string.isEmpty() )
return myMatches;
QChar ch;
QString completion;
const KCompTreeNode *node = myTreeRoot;
// start at the tree-root and try to find the search-string
for( uint i = 0; i < string.length(); i++ ) {
ch = string.at( i );
node = node->find( ch, myIgnoreCase );
if ( node )
completion += ch;
else
return myMatches; // no completion -> return empty list
}
// Now we have the last node of the to be completed string.
// Follow it as long as it has exactly one child (= longest possible
// completion)
while ( node->childrenCount() == 1 ) {
node = node->firstChild();
if ( !node->isNull() )
completion += *node;
// debug("-> %s, %c", completion.ascii(), node->latin1());
}
// there is just one single match)
if ( node->childrenCount() == 0 )
myMatches.append( completion );
else {
// node has more than one child
// -> recursively find all remaining completions
myHasMultipleMatches = true;
extractStringsFromNode( node, completion, &myMatches );
}
return myMatches;
}
kdelibs'KCompletion::extractStringsFromNode() (./kdelibs/kdecore/kcompletion.cpp:333)
void KCompletion::extractStringsFromNode( const KCompTreeNode *node,
const QString& beginning,
QStringList *matches ) const
{
if ( !node || !matches )
return;
// debug("Beginning: %s", beginning.ascii());
KCompTreeChildren::ConstIterator it;
const KCompTreeChildren *list = node->children();
QString string;
// loop thru all children
for ( it = list->begin(); it != list->end(); ++it ) {
string = beginning;
node = *it;
string += *node;
while ( node && node->childrenCount() == 1 ) {
node = node->firstChild();
if ( !node->isNull() )
string += *node;
else { // we found a leaf
matches->append( string );
// debug( " -> found match: %s", debugString( string ));
}
}
// recursively find all other strings.
if ( node && node->childrenCount() > 1 )
extractStringsFromNode( node, string, matches );
}
}
kdelibs'KCompletion::doBeep() (./kdelibs/kdecore/kcompletion.cpp:370)
void KCompletion::doBeep( BeepMode mode )
{
if ( !myBeep )
return;
QString text, event;
switch ( mode ) {
case Rotation:
event = QString::fromLatin1("KCompletion: rotation");
text = i18n("You reached the end of the list\nof matching items.\n");
break;
case PartialMatch:
if ( myCompletionMode == KGlobalSettings::CompletionShell ) {
event = QString::fromLatin1("KCompletion: partial match");
text = i18n("The completion is ambiguous, more than one\nmatch is available.\n");
}
break;
case NoMatch:
if ( myCompletionMode == KGlobalSettings::CompletionShell ||
myCompletionMode == KGlobalSettings::CompletionMan ) {
event = QString::fromLatin1("KCompletion: no match");
text = i18n("There is no matching item available.\n");
}
break;
}
if ( !text.isEmpty() )
KNotifyClient::event( event, text );
}
/////////////////////////////////
/////////
// Implements the tree. Every node is a QChar and has a list of children, which
// are Nodes as well.
// QChar( 0x0 ) is used as the delimiter of a string; the last child of each
// inserted string is 0x0.