source: trunk/tools/designer/editor/completion.cpp

Last change on this file was 197, checked in by rudi, 14 years ago

Added QtDesigner

File size: 23.6 KB
Line 
1/**********************************************************************
2** Copyright (C) 2005-2007 Trolltech ASA. All rights reserved.
3**
4** This file is part of Qt Designer.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
12** licenses may use this file in accordance with the Qt Commercial License
13** Agreement provided with the Software.
14**
15** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17**
18** See http://www.trolltech.com/gpl/ for GPL licensing information.
19** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
20** information about Qt Commercial License Agreements.
21**
22** Contact info@trolltech.com if any conditions of this licensing are
23** not clear to you.
24**
25**********************************************************************/
26
27#include "completion.h"
28#include "paragdata.h"
29#include "editor.h"
30#include <qlistbox.h>
31#include <qvbox.h>
32#include <qmap.h>
33#include <private/qrichtext_p.h>
34#include <qapplication.h>
35#include <qregexp.h>
36#include "arghintwidget.h"
37#include <qsizegrip.h>
38#include <qtimer.h>
39
40static QColor getColor( const QString &type )
41{
42 if ( type == "function" || type == "slot" || type == "package" )
43 return Qt::blue;
44 else if ( type == "variable" || type == "widget" || type == "dir" )
45 return Qt::darkRed;
46 else if ( type == "object" || type == "class" )
47 return Qt::darkBlue;
48 else if ( type == "property" )
49 return Qt::darkGreen;
50 else if ( type == "enum" )
51 return Qt::darkYellow;
52 return Qt::black;
53}
54
55class CompletionItem : public QListBoxItem
56{
57public:
58 CompletionItem( QListBox *lb, const QString &txt, const QString &t, const QString &p,
59 const QString &pre, const QString &p2 )
60 : QListBoxItem( lb ), type( t ), postfix( p ), prefix( pre ), postfix2( p2 ),
61 parag( 0 ), lastState( FALSE ) { setText( txt ); }
62 ~CompletionItem() { delete parag; }
63 void paint( QPainter *painter ) {
64 if ( lastState != isSelected() ) {
65 delete parag;
66 parag = 0;
67 }
68 lastState = isSelected();
69 if ( !parag )
70 setupParagraph();
71 parag->paint( *painter, listBox()->colorGroup() );
72 }
73
74 int height( const QListBox * ) const {
75 if ( !parag )
76 ( (CompletionItem*)this )->setupParagraph();
77 return parag->rect().height();
78 }
79 int width( const QListBox * ) const {
80 if ( !parag )
81 ( (CompletionItem*)this )->setupParagraph();
82 return parag->rect().width() - 2;
83 }
84 QString text() const { return QListBoxItem::text() + postfix; }
85
86private:
87 void setupParagraph();
88 QString type, postfix, prefix, postfix2;
89 QTextParagraph *parag;
90 bool lastState;
91
92};
93
94void CompletionItem::setupParagraph() {
95 if ( !parag ) {
96 QTextFormatter *formatter;
97 formatter = new QTextFormatterBreakWords;
98 formatter->setWrapEnabled( FALSE );
99 parag = new QTextParagraph( 0 );
100 parag->setTabStops( listBox()->fontMetrics().width( "propertyXXXX" ) );
101 parag->pseudoDocument()->pFormatter = formatter;
102 parag->insert( 0, " " + type + ( type.isEmpty() ? " " : "\t" ) + prefix +
103 QListBoxItem::text() + postfix + postfix2 );
104 bool selCol = isSelected() && listBox()->colorGroup().highlightedText() != listBox()->colorGroup().text();
105 QColor sc = selCol ? listBox()->colorGroup().highlightedText() : getColor( type );
106 QTextFormat *f1 = parag->formatCollection()->format( listBox()->font(), sc );
107 QTextFormat *f3 = parag->formatCollection()->format( listBox()->font(), isSelected() ?
108 listBox()->colorGroup().highlightedText() :
109 listBox()->colorGroup().text() );
110 QFont f( listBox()->font() );
111 f.setBold( TRUE );
112 QTextFormat *f2 =
113 parag->formatCollection()->format( f, isSelected() ? listBox()->colorGroup().highlightedText() :
114 listBox()->colorGroup().text() );
115 parag->setFormat( 1, type.length() + 1, f1 );
116 parag->setFormat( type.length() + 2, prefix.length() + QListBoxItem::text().length(), f2 );
117 if ( !postfix.isEmpty() )
118 parag->setFormat( type.length() + 2 + prefix.length() + QListBoxItem::text().length(),
119 postfix.length(), f3 );
120 parag->setFormat( type.length() + 2 + prefix.length() + QListBoxItem::text().length() + postfix.length(),
121 postfix2.length(), f3 );
122 f1->removeRef();
123 f2->removeRef();
124 f3->removeRef();
125 parag->format();
126 }
127}
128
129
130EditorCompletion::EditorCompletion( Editor *e )
131{
132 enabled = TRUE;
133 lastDoc = 0;
134 completionPopup = new QVBox( e->topLevelWidget(), 0, WType_Popup );
135 completionPopup->setFrameStyle( QFrame::Box | QFrame::Plain );
136 completionPopup->setLineWidth( 1 );
137 functionLabel = new ArgHintWidget( e->topLevelWidget(), "editor_function_lbl" );
138 functionLabel->hide();
139 completionListBox = new QListBox( completionPopup, "editor_completion_lb" );
140 completionListBox->setFrameStyle( QFrame::NoFrame );
141 completionListBox->installEventFilter( this );
142 completionListBox->setHScrollBarMode( QScrollView::AlwaysOn );
143 completionListBox->setVScrollBarMode( QScrollView::AlwaysOn );
144 completionListBox->setCornerWidget( new QSizeGrip( completionListBox, "editor_cornerwidget" ) );
145 completionPopup->installEventFilter( this );
146 functionLabel->installEventFilter( this );
147 completionPopup->setFocusProxy( completionListBox );
148 completionOffset = 0;
149 curEditor = e;
150 curEditor->installEventFilter( this );
151}
152
153EditorCompletion::~EditorCompletion()
154{
155 delete completionPopup;
156 delete functionLabel;
157}
158
159void EditorCompletion::addCompletionEntry( const QString &s, QTextDocument *, bool strict )
160{
161 QChar key( s[ 0 ] );
162 QMap<QChar, QStringList>::Iterator it = completionMap.find( key );
163 if ( it == completionMap.end() ) {
164 completionMap.insert( key, QStringList( s ) );
165 } else {
166 if ( strict ) {
167 QStringList::Iterator sit;
168 for ( sit = (*it).begin(); sit != (*it).end(); ) {
169 QStringList::Iterator it2 = sit;
170 ++sit;
171 if ( (*it2).length() > s.length() && (*it2).left( s.length() ) == s ) {
172 if ( (*it2)[ (int)s.length() ].isLetter() && (*it2)[ (int)s.length() ].upper() != (*it2)[ (int)s.length() ] )
173 return;
174 } else if ( s.length() > (*it2).length() && s.left( (*it2).length() ) == *it2 ) {
175 if ( s[ (int)(*it2).length() ].isLetter() && s[ (int)(*it2).length() ].upper() != s[ (int)(*it2).length() ] )
176 (*it).remove( it2 );
177 }
178 }
179 }
180 (*it).append( s );
181 }
182}
183
184QValueList<CompletionEntry> EditorCompletion::completionList( const QString &s, QTextDocument *doc ) const
185{
186 if ( doc )
187 ( (EditorCompletion*)this )->updateCompletionMap( doc );
188
189 QChar key( s[ 0 ] );
190 QMap<QChar, QStringList>::ConstIterator it = completionMap.find( key );
191 if ( it == completionMap.end() )
192 return QValueList<CompletionEntry>();
193 QStringList::ConstIterator it2 = (*it).begin();
194 QValueList<CompletionEntry> lst;
195 int len = s.length();
196 for ( ; it2 != (*it).end(); ++it2 ) {
197 CompletionEntry c;
198 c.type = "";
199 c.text = *it2;
200 c.postfix = "";
201 c.prefix = "";
202 c.postfix2 = "";
203 if ( (int)(*it2).length() > len && (*it2).left( len ) == s && lst.find( c ) == lst.end() )
204 lst << c;
205 }
206
207 return lst;
208}
209
210void EditorCompletion::updateCompletionMap( QTextDocument *doc )
211{
212 bool strict = TRUE;
213 if ( doc != lastDoc )
214 strict = FALSE;
215 lastDoc = doc;
216 QTextParagraph *s = doc->firstParagraph();
217 if ( !s->extraData() )
218 s->setExtraData( new ParagData );
219 while ( s ) {
220 if ( s->length() == ( (ParagData*)s->extraData() )->lastLengthForCompletion ) {
221 s = s->next();
222 continue;
223 }
224
225 QChar c;
226 QString buffer;
227 for ( int i = 0; i < s->length(); ++i ) {
228 c = s->at( i )->c;
229 if ( c.isLetter() || c.isNumber() || c == '_' || c == '#' ) {
230 buffer += c;
231 } else {
232 addCompletionEntry( buffer, doc, strict );
233 buffer = QString::null;
234 }
235 }
236 if ( !buffer.isEmpty() )
237 addCompletionEntry( buffer, doc, strict );
238
239 ( (ParagData*)s->extraData() )->lastLengthForCompletion = s->length();
240 s = s->next();
241 }
242}
243
244bool EditorCompletion::doCompletion()
245{
246 searchString = "";
247 if ( !curEditor )
248 return FALSE;
249
250 QTextCursor *cursor = curEditor->textCursor();
251 QTextDocument *doc = curEditor->document();
252
253 if ( cursor->index() > 0 && cursor->paragraph()->at( cursor->index() - 1 )->c == '.' &&
254 ( cursor->index() == 1 || cursor->paragraph()->at( cursor->index() - 2 )->c != '.' ) )
255 return doObjectCompletion();
256
257 int idx = cursor->index();
258 if ( idx == 0 )
259 return FALSE;
260 QChar c = cursor->paragraph()->at( idx - 1 )->c;
261 if ( !c.isLetter() && !c.isNumber() && c != '_' && c != '#' )
262 return FALSE;
263
264 QString s;
265 idx--;
266 completionOffset = 1;
267 for (;;) {
268 s.prepend( QString( cursor->paragraph()->at( idx )->c ) );
269 idx--;
270 if ( idx < 0 )
271 break;
272 if ( !cursor->paragraph()->at( idx )->c.isLetter() &&
273 !cursor->paragraph()->at( idx )->c.isNumber() &&
274 cursor->paragraph()->at( idx )->c != '_' &&
275 cursor->paragraph()->at( idx )->c != '#' )
276 break;
277 completionOffset++;
278 }
279
280 searchString = s;
281
282 QValueList<CompletionEntry> lst( completionList( s, doc ) );
283 if ( lst.count() > 1 ) {
284 QTextStringChar *chr = cursor->paragraph()->at( cursor->index() );
285 int h = cursor->paragraph()->lineHeightOfChar( cursor->index() );
286 int x = cursor->paragraph()->rect().x() + chr->x;
287 int y, dummy;
288 cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y );
289 y += cursor->paragraph()->rect().y();
290 completionListBox->clear();
291 for ( QValueList<CompletionEntry>::ConstIterator it = lst.begin(); it != lst.end(); ++it )
292 (void)new CompletionItem( completionListBox, (*it).text, (*it).type, (*it).postfix,
293 (*it).prefix, (*it).postfix2 );
294 cList = lst;
295 completionPopup->resize( completionListBox->sizeHint() +
296 QSize( completionListBox->verticalScrollBar()->width() + 4,
297 completionListBox->horizontalScrollBar()->height() + 4 ) );
298 completionListBox->setCurrentItem( 0 );
299 completionListBox->setFocus();
300 if ( curEditor->mapToGlobal( QPoint( 0, y ) ).y() + h + completionPopup->height() < QApplication::desktop()->height() )
301 completionPopup->move( curEditor->mapToGlobal( curEditor->
302 contentsToViewport( QPoint( x, y + h ) ) ) );
303 else
304 completionPopup->move( curEditor->mapToGlobal( curEditor->
305 contentsToViewport( QPoint( x, y - completionPopup->height() ) ) ) );
306 completionPopup->show();
307 } else if ( lst.count() == 1 ) {
308 curEditor->insert( lst.first().text.mid( completionOffset, 0xFFFFFF ),
309 (uint) ( QTextEdit::RedoIndentation |
310 QTextEdit::CheckNewLines |
311 QTextEdit::RemoveSelected ) );
312 } else {
313 return FALSE;
314 }
315
316 return TRUE;
317}
318
319bool EditorCompletion::eventFilter( QObject *o, QEvent *e )
320{
321 if ( !enabled )
322 return FALSE;
323 if ( e->type() == QEvent::KeyPress && ::qt_cast<Editor*>(o)) {
324 curEditor = (Editor*)o;
325 QKeyEvent *ke = (QKeyEvent*)e;
326 if ( ke->key() == Key_Tab ) {
327 QString s = curEditor->textCursor()->paragraph()->string()->toString().
328 left( curEditor->textCursor()->index() );
329 if ( curEditor->document()->hasSelection( QTextDocument::Standard ) ||
330 s.simplifyWhiteSpace().isEmpty() ) {
331 if ( curEditor->document()->indent() ) {
332 curEditor->indent();
333 int i = 0;
334 for ( ; i < curEditor->textCursor()->paragraph()->length() - 1; ++i ) {
335 if ( curEditor->textCursor()->paragraph()->at( i )->c != ' ' &&
336 curEditor->textCursor()->paragraph()->at( i )->c != '\t' )
337 break;
338 }
339 curEditor->drawCursor( FALSE );
340 curEditor->textCursor()->setIndex( i );
341 curEditor->drawCursor( TRUE );
342 } else {
343 curEditor->insert( "\t" );
344 }
345 return TRUE;
346 }
347 }
348
349 if ( functionLabel->isVisible() ) {
350 if ( ke->key() == Key_Up && ( ke->state() & ControlButton ) == ControlButton ) {
351 functionLabel->gotoPrev();
352 return TRUE;
353 } else if ( ke->key() == Key_Down && ( ke->state() & ControlButton ) == ControlButton ) {
354 functionLabel->gotoNext();
355 return TRUE;
356 }
357 }
358
359 if ( ke->text().length() && !( ke->state() & AltButton ) &&
360 ( !ke->ascii() || ke->ascii() >= 32 ) ||
361 ( ke->text() == "\t" && !( ke->state() & ControlButton ) ) ) {
362 if ( ke->key() == Key_Tab ) {
363 if ( curEditor->textCursor()->index() == 0 &&
364 curEditor->textCursor()->paragraph()->isListItem() )
365 return FALSE;
366 if ( doCompletion() )
367 return TRUE;
368 } else if ( ke->key() == Key_Period &&
369 ( curEditor->textCursor()->index() == 0 ||
370 curEditor->textCursor()->paragraph()->at( curEditor->textCursor()->index() - 1 )->c != '.' )
371 ||
372 ke->key() == Key_Greater &&
373 curEditor->textCursor()->index() > 0 &&
374 curEditor->textCursor()->paragraph()->at( curEditor->textCursor()->index() - 1 )->c == '-' ) {
375 doObjectCompletion();
376 } else {
377 if ( !doArgumentHint( ke->text() == "(" ) )
378 functionLabel->hide();
379 }
380 }
381 } else if ( o == completionPopup || o == completionListBox ||
382 o == completionListBox->viewport() ) {
383 if ( e->type() == QEvent::KeyPress ) {
384 QKeyEvent *ke = (QKeyEvent*)e;
385 if ( ke->key() == Key_Enter || ke->key() == Key_Return || ke->key() == Key_Tab ) {
386 if ( ke->key() == Key_Tab && completionListBox->count() > 1 &&
387 completionListBox->currentItem() < (int)completionListBox->count() - 1 ) {
388 completionListBox->setCurrentItem( completionListBox->currentItem() + 1 );
389 return TRUE;
390 }
391 completeCompletion();
392 return TRUE;
393 } else if ( ke->key() == Key_Left || ke->key() == Key_Right ||
394 ke->key() == Key_Up || ke->key() == Key_Down ||
395 ke->key() == Key_Home || ke->key() == Key_End ||
396 ke->key() == Key_Prior || ke->key() == Key_Next ) {
397 return FALSE;
398 } else if ( ke->key() != Key_Shift && ke->key() != Key_Control &&
399 ke->key() != Key_Alt ) {
400 int l = searchString.length();
401 if ( ke->key() == Key_Backspace ) {
402 searchString.remove( searchString.length() - 1, 1 );
403 } else {
404 searchString += ke->text();
405 l = 1;
406 }
407 if ( !l || !continueComplete() ) {
408 completionPopup->close();
409 curEditor->setFocus();
410 }
411 QApplication::sendEvent( curEditor, e );
412 return TRUE;
413 }
414 } else if ( e->type() == QEvent::MouseButtonDblClick ) {
415 completeCompletion();
416 return TRUE;
417 }
418 }
419 if ( o == functionLabel || ::qt_cast<Editor*>(o) && functionLabel->isVisible() ) {
420 if ( e->type() == QEvent::KeyPress ) {
421 QKeyEvent *ke = (QKeyEvent*)e;
422 if ( ke->key() == Key_Escape ) {
423 functionLabel->hide();
424 } else {
425 if ( !doArgumentHint( ke->text() == "(" ) )
426 functionLabel->hide();
427 if ( o == functionLabel ) {
428 QApplication::sendEvent( curEditor, e );
429 return TRUE;
430 }
431 }
432 }
433 }
434 return FALSE;
435}
436
437void EditorCompletion::completeCompletion()
438{
439 int idx = curEditor->textCursor()->index();
440 QString s = completionListBox->currentText().mid( searchString.length() );
441 curEditor->insert( s, (uint) ( QTextEdit::RedoIndentation |
442 QTextEdit::CheckNewLines |
443 QTextEdit::RemoveSelected ) );
444 int i = s.find( '(' );
445 completionPopup->close();
446 curEditor->setFocus();
447 if ( i != -1 && i < (int)s.length() ) {
448 curEditor->setCursorPosition( curEditor->textCursor()->paragraph()->paragId(), idx + i + 1 );
449 doArgumentHint( FALSE );
450 }
451}
452
453void EditorCompletion::setCurrentEdior( Editor *e )
454{
455 curEditor = e;
456 curEditor->installEventFilter( this );
457}
458
459void EditorCompletion::addEditor( Editor *e )
460{
461 e->installEventFilter( this );
462}
463
464bool EditorCompletion::doObjectCompletion()
465{
466 searchString = "";
467 QString object;
468 int i = curEditor->textCursor()->index();
469 i--;
470 QTextParagraph *p = curEditor->textCursor()->paragraph();
471 for (;;) {
472 if ( i < 0 )
473 break;
474 if ( p->at( i )->c == ' ' || p->at( i )->c == '\t' )
475 break;
476 object.prepend( p->at( i )->c );
477 i--;
478 }
479
480 if ( object[ (int)object.length() - 1 ] == '-' )
481 object.remove( object.length() - 1, 1 );
482
483 if ( object.isEmpty() )
484 return FALSE;
485 return doObjectCompletion( object );
486}
487
488bool EditorCompletion::doObjectCompletion( const QString & )
489{
490 return FALSE;
491}
492
493static void strip( QString &txt )
494{
495 int i = txt.find( "(" );
496 if ( i == -1 )
497 return;
498 txt = txt.left( i );
499}
500
501bool EditorCompletion::continueComplete()
502{
503 if ( searchString.isEmpty() ) {
504 completionListBox->clear();
505 for ( QValueList<CompletionEntry>::ConstIterator it = cList.begin(); it != cList.end(); ++it )
506 (void)new CompletionItem( completionListBox, (*it).text, (*it).type,
507 (*it).postfix, (*it).prefix, (*it).postfix2 );
508 completionListBox->setCurrentItem( 0 );
509 completionListBox->setSelected( completionListBox->currentItem(), TRUE );
510 return TRUE;
511 }
512
513 QListBoxItem *i = completionListBox->findItem( searchString );
514 if ( !i )
515 return FALSE;
516
517 QString txt1 = i->text();
518 QString txt2 = searchString;
519 strip( txt1 );
520 strip( txt2 );
521 if ( txt1 == txt2 && !i->next() )
522 return FALSE;
523
524 QValueList<CompletionEntry> res;
525 for ( QValueList<CompletionEntry>::ConstIterator it = cList.begin(); it != cList.end(); ++it ) {
526 if ( (*it).text.left( searchString.length() ) == searchString )
527 res << *it;
528 }
529 if ( res.isEmpty() )
530 return FALSE;
531 completionListBox->clear();
532 for ( QValueList<CompletionEntry>::ConstIterator it2 = res.begin(); it2 != res.end(); ++it2 )
533 (void)new CompletionItem( completionListBox, (*it2).text, (*it2).type,
534 (*it2).postfix, (*it2).prefix, (*it2).postfix2 );
535 completionListBox->setCurrentItem( 0 );
536 completionListBox->setSelected( completionListBox->currentItem(), TRUE );
537 return TRUE;
538}
539
540bool EditorCompletion::doArgumentHint( bool useIndex )
541{
542 QTextCursor *cursor = curEditor->textCursor();
543 int i = cursor->index() ;
544 if ( !useIndex ) {
545 bool foundParen = FALSE;
546 int closeParens = 0;
547 while ( i >= 0 ) {
548 if ( cursor->paragraph()->at( i )->c == ')' && i != cursor->index() )
549 closeParens++;
550 if ( cursor->paragraph()->at( i )->c == '(' ) {
551 closeParens--;
552 if ( closeParens == -1 ) {
553 foundParen = TRUE;
554 break;
555 }
556 }
557 --i;
558 }
559
560 if ( !foundParen )
561 return FALSE;
562 }
563 int j = i - 1;
564 bool foundSpace = FALSE;
565 bool foundNonSpace = FALSE;
566 while ( j >= 0 ) {
567 if ( foundNonSpace && ( cursor->paragraph()->at( j )->c == ' ' || cursor->paragraph()->at( j )->c == ',' ) ) {
568 foundSpace = TRUE;
569 break;
570 }
571 if ( !foundNonSpace && ( cursor->paragraph()->at( j )->c != ' ' || cursor->paragraph()->at( j )->c != ',' ) )
572 foundNonSpace = TRUE;
573 --j;
574 }
575 if ( foundSpace )
576 ++j;
577 j = QMAX( j, 0 );
578 QString function( cursor->paragraph()->string()->toString().mid( j, i - j + 1 ) );
579 QString part = cursor->paragraph()->string()->toString().mid( j, cursor->index() - j + 1 );
580 function = function.simplifyWhiteSpace();
581 for (;;) {
582 if ( function[ (int)function.length() - 1 ] == '(' ) {
583 function.remove( function.length() - 1, 1 );
584 function = function.simplifyWhiteSpace();
585 } else if ( function[ (int)function.length() - 1 ] == ')' ) {
586 function.remove( function.length() - 1, 1 );
587 function = function.simplifyWhiteSpace();
588 } else {
589 break;
590 }
591 }
592
593 QChar sep;
594 QString pre, post;
595 QValueList<QStringList> argl = functionParameters( function, sep, pre, post );
596 if ( argl.isEmpty() )
597 return FALSE;
598
599 QString label;
600 int w = 0;
601 int num = 0;
602 if ( !functionLabel->isVisible() )
603 functionLabel->setNumFunctions( (int)argl.count() );
604 for ( QValueList<QStringList>::Iterator vit = argl.begin(); vit != argl.end(); ++vit, ++num ) {
605 QStringList args = *vit;
606 int argNum = 0;
607 int inParen = 0;
608 for ( int k = 0; k < (int)part.length(); ++k ) {
609 if ( part[ k ] == sep && inParen < 2 )
610 argNum++;
611 if ( part[ k ] == '(' )
612 inParen++;
613 if ( part[ k ] == ')' )
614 inParen--;
615 }
616
617 QString func = function;
618 int pnt = -1;
619 pnt = func.findRev( '.' );
620 if ( pnt == -1 )
621 func.findRev( '>' );
622 if ( pnt != -1 )
623 func = func.mid( pnt + 1 );
624
625 QString s = func + "( ";
626 if ( s[ 0 ] == '\"' )
627 s.remove( (uint)0, 1 );
628 i = 0;
629 for ( QStringList::Iterator it = args.begin(); it != args.end(); ++it, ++i ) {
630 if ( i == argNum )
631 s += "<b>" + *it + "</b>";
632 else
633 s += *it;
634 if ( i < (int)args.count() - 1 )
635 s += ", ";
636 else
637 s += " ";
638 }
639 s += ")";
640 s.prepend( pre );
641 s.append( post );
642 label += "<p>" + s + "</p>";
643 functionLabel->setFunctionText( num, s );
644 w = QMAX( w, functionLabel->fontMetrics().width( s ) + 10 );
645 }
646 w += 16;
647 if ( label.isEmpty() )
648 return FALSE;
649 if ( functionLabel->isVisible() ) {
650 functionLabel->resize( w + 50, QMAX( functionLabel->fontMetrics().height(), 16 ) );
651 } else {
652 QTextStringChar *chr = cursor->paragraph()->at( cursor->index() );
653 int h = cursor->paragraph()->lineHeightOfChar( cursor->index() );
654 int x = cursor->paragraph()->rect().x() + chr->x;
655 int y, dummy;
656 cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y );
657 y += cursor->paragraph()->rect().y();
658 functionLabel->resize( w + 50, QMAX( functionLabel->fontMetrics().height(), 16 ) );
659 functionLabel->move( curEditor->mapToGlobal( curEditor->contentsToViewport( QPoint( x, y + h ) ) ) );
660 if ( functionLabel->x() + functionLabel->width() > QApplication::desktop()->width() )
661 functionLabel->move( QMAX( 0, QApplication::desktop()->width() - functionLabel->width() ),
662 functionLabel->y() );
663 functionLabel->show();
664 curEditor->setFocus();
665 }
666 QTimer::singleShot( 0, functionLabel, SLOT( relayout() ) );
667
668 return TRUE;
669}
670
671QValueList<QStringList> EditorCompletion::functionParameters( const QString &, QChar &, QString &, QString & )
672{
673 return QValueList<QStringList>();
674}
675
676void EditorCompletion::setContext( QObject * )
677{
678}
679
680void EditorCompletion::showCompletion( const QValueList<CompletionEntry> &lst )
681{
682 QTextCursor *cursor = curEditor->textCursor();
683 QTextStringChar *chr = cursor->paragraph()->at( cursor->index() );
684 int h = cursor->paragraph()->lineHeightOfChar( cursor->index() );
685 int x = cursor->paragraph()->rect().x() + chr->x;
686 int y, dummy;
687 cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y );
688 y += cursor->paragraph()->rect().y();
689 completionListBox->clear();
690 for ( QValueList<CompletionEntry>::ConstIterator it = lst.begin(); it != lst.end(); ++it )
691 (void)new CompletionItem( completionListBox, (*it).text, (*it).type,
692 (*it).postfix, (*it).prefix, (*it).postfix2 );
693 cList = lst;
694 completionPopup->resize( completionListBox->sizeHint() +
695 QSize( completionListBox->verticalScrollBar()->width() + 4,
696 completionListBox->horizontalScrollBar()->height() + 4 ) );
697 completionListBox->setCurrentItem( 0 );
698 completionListBox->setFocus();
699 if ( curEditor->mapToGlobal( QPoint( 0, y ) ).y() + h + completionPopup->height() < QApplication::desktop()->height() )
700 completionPopup->move( curEditor->mapToGlobal( curEditor->
701 contentsToViewport( QPoint( x, y + h ) ) ) );
702 else
703 completionPopup->move( curEditor->mapToGlobal( curEditor->
704 contentsToViewport( QPoint( x, y - completionPopup->height() ) ) ) );
705
706 completionPopup->show();
707}
Note: See TracBrowser for help on using the repository browser.