summaryrefslogtreecommitdiffstats
path: root/tools/designer/editor/completion.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/designer/editor/completion.cpp')
-rw-r--r--tools/designer/editor/completion.cpp714
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();
+}