26 #include "katecodecompletion.h"
27 #include "katecodecompletion.moc"
29 #include "katedocument.h"
31 #include "katerenderer.h"
32 #include "kateconfig.h"
37 #include <tqwhatsthis.h>
39 #include <tqlistbox.h>
41 #include <tqtooltip.h>
42 #include <tqapplication.h>
43 #include <tqsizegrip.h>
44 #include <tqfontmetrics.h>
54 class KateCCListBox :
public TQListBox
60 KateCCListBox (TQWidget* parent = 0,
const char* name = 0, WFlags f = 0):TQListBox(parent,
name, f)
64 TQSize sizeHint()
const
66 int count = this->count();
72 height = count * itemHeight(0);
74 height = 10 * itemHeight(0);
75 tmpwidth += verticalScrollBar()->width();
78 int maxcount = 0, tmpcount = 0;
79 for (
int i = 0; i < count; ++i)
80 if ( (tmpcount = fontMetrics().width(text(i)) ) > maxcount)
83 if (maxcount > TQApplication::desktop()->width()){
84 tmpwidth = TQApplication::desktop()->width() - 5;
85 height += horizontalScrollBar()->height();
88 return TQSize(tmpwidth,height);
93 class KateCompletionItem :
public TQListBoxText
96 KateCompletionItem( TQListBox* lb, KTextEditor::CompletionEntry entry )
100 if( entry.postfix ==
"()" ) {
101 setText( entry.prefix +
" " + entry.text + entry.postfix );
103 setText( entry.prefix +
" " + entry.text +
" " + entry.postfix);
107 KTextEditor::CompletionEntry m_entry;
111 KateCodeCompletion::KateCodeCompletion( KateView* view )
112 : TQObject( view,
"Kate Code Completion" )
114 , m_commentLabel( 0 )
116 m_completionPopup =
new TQVBox( 0, 0, (WFlags)WType_Popup );
117 m_completionPopup->setFrameStyle( TQFrame::Box | TQFrame::Plain );
118 m_completionPopup->setLineWidth( 1 );
120 m_completionListBox =
new KateCCListBox( m_completionPopup );
121 m_completionListBox->setFrameStyle( TQFrame::NoFrame );
123 m_completionListBox->setFocusProxy( m_view->m_viewInternal );
125 m_completionListBox->installEventFilter(
this );
127 m_completionPopup->resize(m_completionListBox->sizeHint() + TQSize(2,2));
128 m_completionPopup->installEventFilter(
this );
129 m_completionPopup->setFocusProxy( m_view->m_viewInternal );
131 m_pArgHint =
new KateArgHint( m_view );
132 connect( m_pArgHint, TQ_SIGNAL(argHintHidden()),
133 this, TQ_SIGNAL(argHintHidden()) );
135 connect( m_view, TQ_SIGNAL(cursorPositionChanged()),
136 this, TQ_SLOT(slotCursorPosChanged()) );
139 KateCodeCompletion::~KateCodeCompletion()
141 delete m_completionPopup;
144 bool KateCodeCompletion::codeCompletionVisible () {
145 return m_completionPopup->isVisible();
148 void KateCodeCompletion::showCompletionBox(
149 TQValueList<KTextEditor::CompletionEntry> complList,
int offset,
bool casesensitive )
153 if ( codeCompletionVisible() )
return;
155 m_caseSensitive = casesensitive;
156 m_complList = complList;
158 m_view->cursorPositionReal( &m_lineCursor, &m_colCursor );
159 m_colCursor -= offset;
164 bool KateCodeCompletion::eventFilter( TQObject *o, TQEvent *e )
166 if ( o != m_completionPopup &&
167 o != m_completionListBox &&
168 o != m_completionListBox->viewport() )
171 if( e->type() == TQEvent::Hide )
175 m_completionPopup->hide();
176 delete m_commentLabel;
182 if ( e->type() == TQEvent::MouseButtonDblClick ) {
187 if ( e->type() == TQEvent::MouseButtonPress ) {
188 TQTimer::singleShot(0,
this, TQ_SLOT(showComment()));
195 void KateCodeCompletion::handleKey (TQKeyEvent *e)
198 if ((e->key() == Key_Up) && (m_completionListBox->currentItem() == 0))
206 if( (e->key() == Key_Up) || (e->key() == Key_Down ) ||
207 (e->key() == Key_Home ) || (e->key() == Key_End) ||
208 (e->key() == Key_Prior) || (e->key() == Key_Next ))
210 TQTimer::singleShot(0,
this,TQ_SLOT(showComment()));
211 TQApplication::sendEvent( m_completionListBox, (TQEvent*)e );
219 void KateCodeCompletion::doComplete()
221 KateCompletionItem* item =
static_cast<KateCompletionItem*
>(
222 m_completionListBox->item(m_completionListBox->currentItem()));
227 TQString text = item->m_entry.text;
228 TQString currentLine = m_view->currentTextLine();
229 int len = m_view->cursorColumnReal() - m_colCursor;
230 TQString currentComplText = currentLine.mid(m_colCursor,len);
231 TQString add = text.mid(currentComplText.length());
232 if( item->m_entry.postfix ==
"()" )
235 emit filterInsertString(&(item->m_entry),&add);
236 m_view->insertText(add);
238 complete( item->m_entry );
242 void KateCodeCompletion::abortCompletion()
244 m_completionPopup->hide();
245 delete m_commentLabel;
247 emit completionAborted();
250 void KateCodeCompletion::complete( KTextEditor::CompletionEntry entry )
252 m_completionPopup->hide();
253 delete m_commentLabel;
255 emit completionDone( entry );
256 emit completionDone();
259 void KateCodeCompletion::updateBox(
bool )
261 if( m_colCursor > m_view->cursorColumnReal() ) {
263 kdDebug(13035) <<
"Aborting Codecompletion after sendEvent" <<
endl;
264 kdDebug(13035) << m_view->cursorColumnReal() <<
endl;
270 m_completionListBox->clear();
272 TQString currentLine = m_view->currentTextLine();
273 int len = m_view->cursorColumnReal() - m_colCursor;
274 TQString currentComplText = currentLine.mid(m_colCursor,len);
283 TQValueList<KTextEditor::CompletionEntry>::Iterator it;
284 if( m_caseSensitive ) {
285 for( it = m_complList.begin(); it != m_complList.end(); ++it ) {
286 if( (*it).text.startsWith(currentComplText) ) {
287 new KateCompletionItem(m_completionListBox,*it);
291 currentComplText = currentComplText.upper();
292 for( it = m_complList.begin(); it != m_complList.end(); ++it ) {
293 if( (*it).text.upper().startsWith(currentComplText) ) {
294 new KateCompletionItem(m_completionListBox,*it);
299 if( m_completionListBox->count() == 0 ||
300 ( m_completionListBox->count() == 1 &&
301 currentComplText == m_completionListBox->text(0).stripWhiteSpace() ) ) {
307 kdDebug(13035)<<
"KateCodeCompletion::updateBox: Resizing widget"<<
endl;
308 m_completionPopup->resize(m_completionListBox->sizeHint() + TQSize(2,2));
309 TQPoint p = m_view->mapToGlobal( m_view->cursorCoordinates() );
312 if ( y + m_completionPopup->height() + m_view->renderer()->config()->fontMetrics( )->height() > TQApplication::desktop()->height() )
313 y -= (m_completionPopup->height() );
315 y += m_view->renderer()->config()->fontMetrics( )->height();
317 if (x + m_completionPopup->width() > TQApplication::desktop()->width())
318 x = TQApplication::desktop()->width() - m_completionPopup->width();
320 m_completionPopup->move( TQPoint(x,y) );
322 m_completionListBox->setCurrentItem( 0 );
323 m_completionListBox->setSelected( 0,
true );
324 m_completionListBox->setFocus();
325 m_completionPopup->show();
327 TQTimer::singleShot(0,
this,TQ_SLOT(showComment()));
330 void KateCodeCompletion::showArgHint ( TQStringList functionList,
const TQString& strWrapping,
const TQString& strDelimiter )
332 unsigned int line, col;
333 m_view->cursorPositionReal( &line, &col );
334 m_pArgHint->reset( line, col );
335 m_pArgHint->setArgMarkInfos( strWrapping, strDelimiter );
338 TQStringList::Iterator
end(functionList.end());
339 for( TQStringList::Iterator it = functionList.begin(); it != end; ++it )
341 kdDebug(13035) <<
"Insert function text: " << *it <<
endl;
343 m_pArgHint->addFunction( nNum, ( *it ) );
348 m_pArgHint->move(m_view->mapToGlobal(m_view->cursorCoordinates() + TQPoint(0,m_view->renderer()->config()->fontMetrics( )->height())) );
352 void KateCodeCompletion::slotCursorPosChanged()
354 m_pArgHint->cursorPositionChanged ( m_view, m_view->cursorLine(), m_view->cursorColumnReal() );
357 void KateCodeCompletion::showComment()
359 if (!m_completionPopup->isVisible())
362 KateCompletionItem* item =
static_cast<KateCompletionItem*
>(m_completionListBox->item(m_completionListBox->currentItem()));
367 if( item->m_entry.comment.isEmpty() )
370 delete m_commentLabel;
371 m_commentLabel =
new KateCodeCompletionCommentLabel( 0, item->m_entry.comment );
372 m_commentLabel->setFont(TQToolTip::font());
373 m_commentLabel->setPalette(TQToolTip::palette());
375 TQPoint rightPoint = m_completionPopup->mapToGlobal(TQPoint(m_completionPopup->width(),0));
376 TQPoint leftPoint = m_completionPopup->mapToGlobal(TQPoint(0,0));
377 TQRect screen = TQApplication::desktop()->screenGeometry ( m_commentLabel );
379 if (rightPoint.x()+m_commentLabel->width() > screen.x() + screen.width())
380 finalPoint.setX(leftPoint.x()-m_commentLabel->width());
382 finalPoint.setX(rightPoint.x());
384 m_completionListBox->ensureCurrentVisible();
387 m_completionListBox->viewport()->mapToGlobal(m_completionListBox->itemRect(
388 m_completionListBox->item(m_completionListBox->currentItem())).topLeft()).y());
390 m_commentLabel->move(finalPoint);
391 m_commentLabel->show();
394 KateArgHint::KateArgHint( KateView* parent,
const char* name )
395 : TQFrame( parent,
name, (WFlags)WType_Popup )
397 setBackgroundColor( black );
398 setPaletteForegroundColor( TQt::black );
400 labelDict.setAutoDelete(
true );
401 layout =
new TQVBoxLayout(
this, 1, 2 );
402 layout->setAutoAdd(
true );
405 m_markCurrentFunction =
true;
407 setFocusPolicy( TQWidget::StrongFocus );
408 setFocusProxy( parent );
413 KateArgHint::~KateArgHint()
417 void KateArgHint::setArgMarkInfos(
const TQString& wrapping,
const TQString& delimiter )
419 m_wrapping = wrapping;
420 m_delimiter = delimiter;
421 m_markCurrentFunction =
true;
424 void KateArgHint::reset(
int line,
int col )
426 m_functionMap.clear();
427 m_currentFunction = -1;
430 m_currentLine = line;
431 m_currentCol = col - 1;
434 void KateArgHint::slotDone(
bool completed)
438 m_currentLine = m_currentCol = -1;
440 emit argHintHidden();
442 emit argHintCompleted();
444 emit argHintAborted();
447 void KateArgHint::cursorPositionChanged( KateView* view,
int line,
int col )
449 if( m_currentCol == -1 || m_currentLine == -1 ){
454 int nCountDelimiter = 0;
457 TQString currentTextLine = view->doc()->textLine( line );
458 TQString text = currentTextLine.mid( m_currentCol, col - m_currentCol );
459 TQRegExp strconst_rx(
"\"[^\"]*\"" );
460 TQRegExp chrconst_rx(
"'[^']*'" );
463 .replace( strconst_rx,
"\"\"" )
464 .replace( chrconst_rx,
"''" );
467 while( index < (
int)text.length() ){
468 if( text[index] == m_wrapping[0] ){
470 }
else if( text[index] == m_wrapping[1] ){
472 }
else if( count > 0 && text[index] == m_delimiter[0] ){
478 if( (m_currentLine > 0 && m_currentLine != line) || (m_currentLine < col) || (count == 0) ){
479 slotDone(count == 0);
487 void KateArgHint::addFunction(
int id,
const TQString& prot )
489 m_functionMap[ id ] = prot;
490 TQLabel*
label =
new TQLabel( prot.stripWhiteSpace().simplifyWhiteSpace(),
this );
491 label->setBackgroundColor( TQColor(255, 255, 238) );
493 labelDict.insert(
id, label );
495 if( m_currentFunction < 0 )
496 setCurrentFunction(
id );
499 void KateArgHint::setCurrentFunction(
int currentFunction )
501 if( m_currentFunction != currentFunction ){
503 if( currentFunction < 0 )
504 currentFunction = (int)m_functionMap.size() - 1;
506 if( currentFunction > (
int)m_functionMap.size()-1 )
509 if( m_markCurrentFunction && m_currentFunction >= 0 ){
510 TQLabel*
label = labelDict[ m_currentFunction ];
511 label->setFont( font() );
514 m_currentFunction = currentFunction;
516 if( m_markCurrentFunction ){
517 TQLabel*
label = labelDict[ currentFunction ];
518 TQFont fnt( font() );
520 label->setFont( fnt );
527 void KateArgHint::show()
533 bool KateArgHint::eventFilter( TQObject*, TQEvent* e )
535 if( isVisible() && e->type() == TQEvent::KeyPress ){
536 TQKeyEvent* ke =
static_cast<TQKeyEvent*
>( e );
537 if( (ke->state() & ControlButton) && ke->key() == Key_Left ){
538 setCurrentFunction( currentFunction() - 1 );
541 }
else if( ke->key() == Key_Escape ){
544 }
else if( (ke->state() & ControlButton) && ke->key() == Key_Right ){
545 setCurrentFunction( currentFunction() + 1 );
554 void KateArgHint::adjustSize( )
556 TQRect screen = TQApplication::desktop()->screenGeometry( pos() );
558 TQFrame::adjustSize();
559 if( width() > screen.width() )
560 resize( screen.width(), height() );
562 if( x() + width() > screen.x() + screen.width() )
563 move( screen.x() + screen.width() - width(), y() );
kndbgstream & endl(kndbgstream &s)
kdbgstream kdDebug(int area=0)
TQString name(StdAccel id)
const TDEShortcut & end()
TQString label(StdAccel id)