You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
qt3/tools/designer/editor/completion.cpp

715 lines
23 KiB

/**********************************************************************
** 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();
}