diff options
Diffstat (limited to 'tools/designer/editor/completion.cpp')
-rw-r--r-- | tools/designer/editor/completion.cpp | 714 |
1 files changed, 714 insertions, 0 deletions
diff --git a/tools/designer/editor/completion.cpp b/tools/designer/editor/completion.cpp new file mode 100644 index 0000000..9ab09fa --- /dev/null +++ b/tools/designer/editor/completion.cpp @@ -0,0 +1,714 @@ +/********************************************************************** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of Qt Designer. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free Qt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with +** the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "completion.h" +#include "paragdata.h" +#include "editor.h" +#include <qlistbox.h> +#include <qvbox.h> +#include <qmap.h> +#include <private/qrichtext_p.h> +#include <qapplication.h> +#include <qregexp.h> +#include "arghintwidget.h" +#include <qsizegrip.h> +#include <qtimer.h> + +static QColor getColor( const QString &type ) +{ + if ( type == "function" || type == "slot" || type == "package" ) + return Qt::blue; + else if ( type == "variable" || type == "widget" || type == "dir" ) + return Qt::darkRed; + else if ( type == "object" || type == "class" ) + return Qt::darkBlue; + else if ( type == "property" ) + return Qt::darkGreen; + else if ( type == "enum" ) + return Qt::darkYellow; + return Qt::black; +} + +class CompletionItem : public QListBoxItem +{ +public: + CompletionItem( QListBox *lb, const QString &txt, const QString &t, const QString &p, + const QString &pre, const QString &p2 ) + : QListBoxItem( lb ), type( t ), postfix( p ), prefix( pre ), postfix2( p2 ), + parag( 0 ), lastState( FALSE ) { setText( txt ); } + ~CompletionItem() { delete parag; } + void paint( QPainter *painter ) { + if ( lastState != isSelected() ) { + delete parag; + parag = 0; + } + lastState = isSelected(); + if ( !parag ) + setupParagraph(); + parag->paint( *painter, listBox()->colorGroup() ); + } + + int height( const QListBox * ) const { + if ( !parag ) + ( (CompletionItem*)this )->setupParagraph(); + return parag->rect().height(); + } + int width( const QListBox * ) const { + if ( !parag ) + ( (CompletionItem*)this )->setupParagraph(); + return parag->rect().width() - 2; + } + QString text() const { return QListBoxItem::text() + postfix; } + +private: + void setupParagraph(); + QString type, postfix, prefix, postfix2; + QTextParagraph *parag; + bool lastState; + +}; + +void CompletionItem::setupParagraph() { + if ( !parag ) { + QTextFormatter *formatter; + formatter = new QTextFormatterBreakWords; + formatter->setWrapEnabled( FALSE ); + parag = new QTextParagraph( 0 ); + parag->setTabStops( listBox()->fontMetrics().width( "propertyXXXX" ) ); + parag->pseudoDocument()->pFormatter = formatter; + parag->insert( 0, " " + type + ( type.isEmpty() ? " " : "\t" ) + prefix + + QListBoxItem::text() + postfix + postfix2 ); + bool selCol = isSelected() && listBox()->colorGroup().highlightedText() != listBox()->colorGroup().text(); + QColor sc = selCol ? listBox()->colorGroup().highlightedText() : getColor( type ); + QTextFormat *f1 = parag->formatCollection()->format( listBox()->font(), sc ); + QTextFormat *f3 = parag->formatCollection()->format( listBox()->font(), isSelected() ? + listBox()->colorGroup().highlightedText() : + listBox()->colorGroup().text() ); + QFont f( listBox()->font() ); + f.setBold( TRUE ); + QTextFormat *f2 = + parag->formatCollection()->format( f, isSelected() ? listBox()->colorGroup().highlightedText() : + listBox()->colorGroup().text() ); + parag->setFormat( 1, type.length() + 1, f1 ); + parag->setFormat( type.length() + 2, prefix.length() + QListBoxItem::text().length(), f2 ); + if ( !postfix.isEmpty() ) + parag->setFormat( type.length() + 2 + prefix.length() + QListBoxItem::text().length(), + postfix.length(), f3 ); + parag->setFormat( type.length() + 2 + prefix.length() + QListBoxItem::text().length() + postfix.length(), + postfix2.length(), f3 ); + f1->removeRef(); + f2->removeRef(); + f3->removeRef(); + parag->format(); + } +} + + +EditorCompletion::EditorCompletion( Editor *e ) +{ + enabled = TRUE; + lastDoc = 0; + completionPopup = new QVBox( e->topLevelWidget(), 0, WType_Popup ); + completionPopup->setFrameStyle( QFrame::Box | QFrame::Plain ); + completionPopup->setLineWidth( 1 ); + functionLabel = new ArgHintWidget( e->topLevelWidget(), "editor_function_lbl" ); + functionLabel->hide(); + completionListBox = new QListBox( completionPopup, "editor_completion_lb" ); + completionListBox->setFrameStyle( QFrame::NoFrame ); + completionListBox->installEventFilter( this ); + completionListBox->setHScrollBarMode( QScrollView::AlwaysOn ); + completionListBox->setVScrollBarMode( QScrollView::AlwaysOn ); + completionListBox->setCornerWidget( new QSizeGrip( completionListBox, "editor_cornerwidget" ) ); + completionPopup->installEventFilter( this ); + functionLabel->installEventFilter( this ); + completionPopup->setFocusProxy( completionListBox ); + completionOffset = 0; + curEditor = e; + curEditor->installEventFilter( this ); +} + +EditorCompletion::~EditorCompletion() +{ + delete completionPopup; + delete functionLabel; +} + +void EditorCompletion::addCompletionEntry( const QString &s, QTextDocument *, bool strict ) +{ + QChar key( s[ 0 ] ); + QMap<QChar, QStringList>::Iterator it = completionMap.find( key ); + if ( it == completionMap.end() ) { + completionMap.insert( key, QStringList( s ) ); + } else { + if ( strict ) { + QStringList::Iterator sit; + for ( sit = (*it).begin(); sit != (*it).end(); ) { + QStringList::Iterator it2 = sit; + ++sit; + if ( (*it2).length() > s.length() && (*it2).left( s.length() ) == s ) { + if ( (*it2)[ (int)s.length() ].isLetter() && (*it2)[ (int)s.length() ].upper() != (*it2)[ (int)s.length() ] ) + return; + } else if ( s.length() > (*it2).length() && s.left( (*it2).length() ) == *it2 ) { + if ( s[ (int)(*it2).length() ].isLetter() && s[ (int)(*it2).length() ].upper() != s[ (int)(*it2).length() ] ) + (*it).remove( it2 ); + } + } + } + (*it).append( s ); + } +} + +QValueList<CompletionEntry> EditorCompletion::completionList( const QString &s, QTextDocument *doc ) const +{ + if ( doc ) + ( (EditorCompletion*)this )->updateCompletionMap( doc ); + + QChar key( s[ 0 ] ); + QMap<QChar, QStringList>::ConstIterator it = completionMap.find( key ); + if ( it == completionMap.end() ) + return QValueList<CompletionEntry>(); + QStringList::ConstIterator it2 = (*it).begin(); + QValueList<CompletionEntry> lst; + int len = s.length(); + for ( ; it2 != (*it).end(); ++it2 ) { + CompletionEntry c; + c.type = ""; + c.text = *it2; + c.postfix = ""; + c.prefix = ""; + c.postfix2 = ""; + if ( (int)(*it2).length() > len && (*it2).left( len ) == s && lst.find( c ) == lst.end() ) + lst << c; + } + + return lst; +} + +void EditorCompletion::updateCompletionMap( QTextDocument *doc ) +{ + bool strict = TRUE; + if ( doc != lastDoc ) + strict = FALSE; + lastDoc = doc; + QTextParagraph *s = doc->firstParagraph(); + if ( !s->extraData() ) + s->setExtraData( new ParagData ); + while ( s ) { + if ( s->length() == ( (ParagData*)s->extraData() )->lastLengthForCompletion ) { + s = s->next(); + continue; + } + + QChar c; + QString buffer; + for ( int i = 0; i < s->length(); ++i ) { + c = s->at( i )->c; + if ( c.isLetter() || c.isNumber() || c == '_' || c == '#' ) { + buffer += c; + } else { + addCompletionEntry( buffer, doc, strict ); + buffer = QString::null; + } + } + if ( !buffer.isEmpty() ) + addCompletionEntry( buffer, doc, strict ); + + ( (ParagData*)s->extraData() )->lastLengthForCompletion = s->length(); + s = s->next(); + } +} + +bool EditorCompletion::doCompletion() +{ + searchString = ""; + if ( !curEditor ) + return FALSE; + + QTextCursor *cursor = curEditor->textCursor(); + QTextDocument *doc = curEditor->document(); + + if ( cursor->index() > 0 && cursor->paragraph()->at( cursor->index() - 1 )->c == '.' && + ( cursor->index() == 1 || cursor->paragraph()->at( cursor->index() - 2 )->c != '.' ) ) + return doObjectCompletion(); + + int idx = cursor->index(); + if ( idx == 0 ) + return FALSE; + QChar c = cursor->paragraph()->at( idx - 1 )->c; + if ( !c.isLetter() && !c.isNumber() && c != '_' && c != '#' ) + return FALSE; + + QString s; + idx--; + completionOffset = 1; + for (;;) { + s.prepend( QString( cursor->paragraph()->at( idx )->c ) ); + idx--; + if ( idx < 0 ) + break; + if ( !cursor->paragraph()->at( idx )->c.isLetter() && + !cursor->paragraph()->at( idx )->c.isNumber() && + cursor->paragraph()->at( idx )->c != '_' && + cursor->paragraph()->at( idx )->c != '#' ) + break; + completionOffset++; + } + + searchString = s; + + QValueList<CompletionEntry> lst( completionList( s, doc ) ); + if ( lst.count() > 1 ) { + QTextStringChar *chr = cursor->paragraph()->at( cursor->index() ); + int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); + int x = cursor->paragraph()->rect().x() + chr->x; + int y, dummy; + cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y ); + y += cursor->paragraph()->rect().y(); + completionListBox->clear(); + for ( QValueList<CompletionEntry>::ConstIterator it = lst.begin(); it != lst.end(); ++it ) + (void)new CompletionItem( completionListBox, (*it).text, (*it).type, (*it).postfix, + (*it).prefix, (*it).postfix2 ); + cList = lst; + completionPopup->resize( completionListBox->sizeHint() + + QSize( completionListBox->verticalScrollBar()->width() + 4, + completionListBox->horizontalScrollBar()->height() + 4 ) ); + completionListBox->setCurrentItem( 0 ); + completionListBox->setFocus(); + if ( curEditor->mapToGlobal( QPoint( 0, y ) ).y() + h + completionPopup->height() < QApplication::desktop()->height() ) + completionPopup->move( curEditor->mapToGlobal( curEditor-> + contentsToViewport( QPoint( x, y + h ) ) ) ); + else + completionPopup->move( curEditor->mapToGlobal( curEditor-> + contentsToViewport( QPoint( x, y - completionPopup->height() ) ) ) ); + completionPopup->show(); + } else if ( lst.count() == 1 ) { + curEditor->insert( lst.first().text.mid( completionOffset, 0xFFFFFF ), + (uint) ( QTextEdit::RedoIndentation | + QTextEdit::CheckNewLines | + QTextEdit::RemoveSelected ) ); + } else { + return FALSE; + } + + return TRUE; +} + +bool EditorCompletion::eventFilter( QObject *o, QEvent *e ) +{ + if ( !enabled ) + return FALSE; + if ( e->type() == QEvent::KeyPress && ::qt_cast<Editor*>(o)) { + curEditor = (Editor*)o; + QKeyEvent *ke = (QKeyEvent*)e; + if ( ke->key() == Key_Tab ) { + QString s = curEditor->textCursor()->paragraph()->string()->toString(). + left( curEditor->textCursor()->index() ); + if ( curEditor->document()->hasSelection( QTextDocument::Standard ) || + s.simplifyWhiteSpace().isEmpty() ) { + if ( curEditor->document()->indent() ) { + curEditor->indent(); + int i = 0; + for ( ; i < curEditor->textCursor()->paragraph()->length() - 1; ++i ) { + if ( curEditor->textCursor()->paragraph()->at( i )->c != ' ' && + curEditor->textCursor()->paragraph()->at( i )->c != '\t' ) + break; + } + curEditor->drawCursor( FALSE ); + curEditor->textCursor()->setIndex( i ); + curEditor->drawCursor( TRUE ); + } else { + curEditor->insert( "\t" ); + } + return TRUE; + } + } + + if ( functionLabel->isVisible() ) { + if ( ke->key() == Key_Up && ( ke->state() & ControlButton ) == ControlButton ) { + functionLabel->gotoPrev(); + return TRUE; + } else if ( ke->key() == Key_Down && ( ke->state() & ControlButton ) == ControlButton ) { + functionLabel->gotoNext(); + return TRUE; + } + } + + if ( ke->text().length() && !( ke->state() & AltButton ) && + ( !ke->ascii() || ke->ascii() >= 32 ) || + ( ke->text() == "\t" && !( ke->state() & ControlButton ) ) ) { + if ( ke->key() == Key_Tab ) { + if ( curEditor->textCursor()->index() == 0 && + curEditor->textCursor()->paragraph()->isListItem() ) + return FALSE; + if ( doCompletion() ) + return TRUE; + } else if ( ke->key() == Key_Period && + ( curEditor->textCursor()->index() == 0 || + curEditor->textCursor()->paragraph()->at( curEditor->textCursor()->index() - 1 )->c != '.' ) + || + ke->key() == Key_Greater && + curEditor->textCursor()->index() > 0 && + curEditor->textCursor()->paragraph()->at( curEditor->textCursor()->index() - 1 )->c == '-' ) { + doObjectCompletion(); + } else { + if ( !doArgumentHint( ke->text() == "(" ) ) + functionLabel->hide(); + } + } + } else if ( o == completionPopup || o == completionListBox || + o == completionListBox->viewport() ) { + if ( e->type() == QEvent::KeyPress ) { + QKeyEvent *ke = (QKeyEvent*)e; + if ( ke->key() == Key_Enter || ke->key() == Key_Return || ke->key() == Key_Tab ) { + if ( ke->key() == Key_Tab && completionListBox->count() > 1 && + completionListBox->currentItem() < (int)completionListBox->count() - 1 ) { + completionListBox->setCurrentItem( completionListBox->currentItem() + 1 ); + return TRUE; + } + completeCompletion(); + return TRUE; + } else if ( ke->key() == Key_Left || ke->key() == Key_Right || + ke->key() == Key_Up || ke->key() == Key_Down || + ke->key() == Key_Home || ke->key() == Key_End || + ke->key() == Key_Prior || ke->key() == Key_Next ) { + return FALSE; + } else if ( ke->key() != Key_Shift && ke->key() != Key_Control && + ke->key() != Key_Alt ) { + int l = searchString.length(); + if ( ke->key() == Key_Backspace ) { + searchString.remove( searchString.length() - 1, 1 ); + } else { + searchString += ke->text(); + l = 1; + } + if ( !l || !continueComplete() ) { + completionPopup->close(); + curEditor->setFocus(); + } + QApplication::sendEvent( curEditor, e ); + return TRUE; + } + } else if ( e->type() == QEvent::MouseButtonDblClick ) { + completeCompletion(); + return TRUE; + } + } + if ( o == functionLabel || ::qt_cast<Editor*>(o) && functionLabel->isVisible() ) { + if ( e->type() == QEvent::KeyPress ) { + QKeyEvent *ke = (QKeyEvent*)e; + if ( ke->key() == Key_Escape ) { + functionLabel->hide(); + } else { + if ( !doArgumentHint( ke->text() == "(" ) ) + functionLabel->hide(); + if ( o == functionLabel ) { + QApplication::sendEvent( curEditor, e ); + return TRUE; + } + } + } + } + return FALSE; +} + +void EditorCompletion::completeCompletion() +{ + int idx = curEditor->textCursor()->index(); + QString s = completionListBox->currentText().mid( searchString.length() ); + curEditor->insert( s, (uint) ( QTextEdit::RedoIndentation | + QTextEdit::CheckNewLines | + QTextEdit::RemoveSelected ) ); + int i = s.find( '(' ); + completionPopup->close(); + curEditor->setFocus(); + if ( i != -1 && i < (int)s.length() ) { + curEditor->setCursorPosition( curEditor->textCursor()->paragraph()->paragId(), idx + i + 1 ); + doArgumentHint( FALSE ); + } +} + +void EditorCompletion::setCurrentEdior( Editor *e ) +{ + curEditor = e; + curEditor->installEventFilter( this ); +} + +void EditorCompletion::addEditor( Editor *e ) +{ + e->installEventFilter( this ); +} + +bool EditorCompletion::doObjectCompletion() +{ + searchString = ""; + QString object; + int i = curEditor->textCursor()->index(); + i--; + QTextParagraph *p = curEditor->textCursor()->paragraph(); + for (;;) { + if ( i < 0 ) + break; + if ( p->at( i )->c == ' ' || p->at( i )->c == '\t' ) + break; + object.prepend( p->at( i )->c ); + i--; + } + + if ( object[ (int)object.length() - 1 ] == '-' ) + object.remove( object.length() - 1, 1 ); + + if ( object.isEmpty() ) + return FALSE; + return doObjectCompletion( object ); +} + +bool EditorCompletion::doObjectCompletion( const QString & ) +{ + return FALSE; +} + +static void strip( QString &txt ) +{ + int i = txt.find( "(" ); + if ( i == -1 ) + return; + txt = txt.left( i ); +} + +bool EditorCompletion::continueComplete() +{ + if ( searchString.isEmpty() ) { + completionListBox->clear(); + for ( QValueList<CompletionEntry>::ConstIterator it = cList.begin(); it != cList.end(); ++it ) + (void)new CompletionItem( completionListBox, (*it).text, (*it).type, + (*it).postfix, (*it).prefix, (*it).postfix2 ); + completionListBox->setCurrentItem( 0 ); + completionListBox->setSelected( completionListBox->currentItem(), TRUE ); + return TRUE; + } + + QListBoxItem *i = completionListBox->findItem( searchString ); + if ( !i ) + return FALSE; + + QString txt1 = i->text(); + QString txt2 = searchString; + strip( txt1 ); + strip( txt2 ); + if ( txt1 == txt2 && !i->next() ) + return FALSE; + + QValueList<CompletionEntry> res; + for ( QValueList<CompletionEntry>::ConstIterator it = cList.begin(); it != cList.end(); ++it ) { + if ( (*it).text.left( searchString.length() ) == searchString ) + res << *it; + } + if ( res.isEmpty() ) + return FALSE; + completionListBox->clear(); + for ( QValueList<CompletionEntry>::ConstIterator it2 = res.begin(); it2 != res.end(); ++it2 ) + (void)new CompletionItem( completionListBox, (*it2).text, (*it2).type, + (*it2).postfix, (*it2).prefix, (*it2).postfix2 ); + completionListBox->setCurrentItem( 0 ); + completionListBox->setSelected( completionListBox->currentItem(), TRUE ); + return TRUE; +} + +bool EditorCompletion::doArgumentHint( bool useIndex ) +{ + QTextCursor *cursor = curEditor->textCursor(); + int i = cursor->index() ; + if ( !useIndex ) { + bool foundParen = FALSE; + int closeParens = 0; + while ( i >= 0 ) { + if ( cursor->paragraph()->at( i )->c == ')' && i != cursor->index() ) + closeParens++; + if ( cursor->paragraph()->at( i )->c == '(' ) { + closeParens--; + if ( closeParens == -1 ) { + foundParen = TRUE; + break; + } + } + --i; + } + + if ( !foundParen ) + return FALSE; + } + int j = i - 1; + bool foundSpace = FALSE; + bool foundNonSpace = FALSE; + while ( j >= 0 ) { + if ( foundNonSpace && ( cursor->paragraph()->at( j )->c == ' ' || cursor->paragraph()->at( j )->c == ',' ) ) { + foundSpace = TRUE; + break; + } + if ( !foundNonSpace && ( cursor->paragraph()->at( j )->c != ' ' || cursor->paragraph()->at( j )->c != ',' ) ) + foundNonSpace = TRUE; + --j; + } + if ( foundSpace ) + ++j; + j = QMAX( j, 0 ); + QString function( cursor->paragraph()->string()->toString().mid( j, i - j + 1 ) ); + QString part = cursor->paragraph()->string()->toString().mid( j, cursor->index() - j + 1 ); + function = function.simplifyWhiteSpace(); + for (;;) { + if ( function[ (int)function.length() - 1 ] == '(' ) { + function.remove( function.length() - 1, 1 ); + function = function.simplifyWhiteSpace(); + } else if ( function[ (int)function.length() - 1 ] == ')' ) { + function.remove( function.length() - 1, 1 ); + function = function.simplifyWhiteSpace(); + } else { + break; + } + } + + QChar sep; + QString pre, post; + QValueList<QStringList> argl = functionParameters( function, sep, pre, post ); + if ( argl.isEmpty() ) + return FALSE; + + QString label; + int w = 0; + int num = 0; + if ( !functionLabel->isVisible() ) + functionLabel->setNumFunctions( (int)argl.count() ); + for ( QValueList<QStringList>::Iterator vit = argl.begin(); vit != argl.end(); ++vit, ++num ) { + QStringList args = *vit; + int argNum = 0; + int inParen = 0; + for ( int k = 0; k < (int)part.length(); ++k ) { + if ( part[ k ] == sep && inParen < 2 ) + argNum++; + if ( part[ k ] == '(' ) + inParen++; + if ( part[ k ] == ')' ) + inParen--; + } + + QString func = function; + int pnt = -1; + pnt = func.findRev( '.' ); + if ( pnt == -1 ) + func.findRev( '>' ); + if ( pnt != -1 ) + func = func.mid( pnt + 1 ); + + QString s = func + "( "; + if ( s[ 0 ] == '\"' ) + s.remove( (uint)0, 1 ); + i = 0; + for ( QStringList::Iterator it = args.begin(); it != args.end(); ++it, ++i ) { + if ( i == argNum ) + s += "<b>" + *it + "</b>"; + else + s += *it; + if ( i < (int)args.count() - 1 ) + s += ", "; + else + s += " "; + } + s += ")"; + s.prepend( pre ); + s.append( post ); + label += "<p>" + s + "</p>"; + functionLabel->setFunctionText( num, s ); + w = QMAX( w, functionLabel->fontMetrics().width( s ) + 10 ); + } + w += 16; + if ( label.isEmpty() ) + return FALSE; + if ( functionLabel->isVisible() ) { + functionLabel->resize( w + 50, QMAX( functionLabel->fontMetrics().height(), 16 ) ); + } else { + QTextStringChar *chr = cursor->paragraph()->at( cursor->index() ); + int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); + int x = cursor->paragraph()->rect().x() + chr->x; + int y, dummy; + cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y ); + y += cursor->paragraph()->rect().y(); + functionLabel->resize( w + 50, QMAX( functionLabel->fontMetrics().height(), 16 ) ); + functionLabel->move( curEditor->mapToGlobal( curEditor->contentsToViewport( QPoint( x, y + h ) ) ) ); + if ( functionLabel->x() + functionLabel->width() > QApplication::desktop()->width() ) + functionLabel->move( QMAX( 0, QApplication::desktop()->width() - functionLabel->width() ), + functionLabel->y() ); + functionLabel->show(); + curEditor->setFocus(); + } + QTimer::singleShot( 0, functionLabel, SLOT( relayout() ) ); + + return TRUE; +} + +QValueList<QStringList> EditorCompletion::functionParameters( const QString &, QChar &, QString &, QString & ) +{ + return QValueList<QStringList>(); +} + +void EditorCompletion::setContext( QObject * ) +{ +} + +void EditorCompletion::showCompletion( const QValueList<CompletionEntry> &lst ) +{ + QTextCursor *cursor = curEditor->textCursor(); + QTextStringChar *chr = cursor->paragraph()->at( cursor->index() ); + int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); + int x = cursor->paragraph()->rect().x() + chr->x; + int y, dummy; + cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y ); + y += cursor->paragraph()->rect().y(); + completionListBox->clear(); + for ( QValueList<CompletionEntry>::ConstIterator it = lst.begin(); it != lst.end(); ++it ) + (void)new CompletionItem( completionListBox, (*it).text, (*it).type, + (*it).postfix, (*it).prefix, (*it).postfix2 ); + cList = lst; + completionPopup->resize( completionListBox->sizeHint() + + QSize( completionListBox->verticalScrollBar()->width() + 4, + completionListBox->horizontalScrollBar()->height() + 4 ) ); + completionListBox->setCurrentItem( 0 ); + completionListBox->setFocus(); + if ( curEditor->mapToGlobal( QPoint( 0, y ) ).y() + h + completionPopup->height() < QApplication::desktop()->height() ) + completionPopup->move( curEditor->mapToGlobal( curEditor-> + contentsToViewport( QPoint( x, y + h ) ) ) ); + else + completionPopup->move( curEditor->mapToGlobal( curEditor-> + contentsToViewport( QPoint( x, y - completionPopup->height() ) ) ) ); + + completionPopup->show(); +} |