• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kate
 

kate

  • kate
  • part
katecodecompletion.cpp
1 /* This file is part of the KDE libraries
2  Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
3  Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org>
4  Copyright (C) 2001 by Victor Röder <Victor_Roeder@GMX.de>
5  Copyright (C) 2002 by Roberto Raggi <roberto@kdevelop.org>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License version 2 as published by the Free Software Foundation.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Library General Public License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to
18  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  Boston, MA 02110-1301, USA.
20 */
21 
22 /******** Partly based on the ArgHintWidget of Qt3 by Trolltech AS *********/
23 /* Trolltech doesn't mind, if we license that piece of code as LGPL, because there isn't much
24  * left from the desigener code */
25 
26 #include "katecodecompletion.h"
27 #include "katecodecompletion.moc"
28 
29 #include "katedocument.h"
30 #include "kateview.h"
31 #include "katerenderer.h"
32 #include "kateconfig.h"
33 #include "katefont.h"
34 
35 #include <kdebug.h>
36 
37 #include <tqwhatsthis.h>
38 #include <tqvbox.h>
39 #include <tqlistbox.h>
40 #include <tqtimer.h>
41 #include <tqtooltip.h>
42 #include <tqapplication.h>
43 #include <tqsizegrip.h>
44 #include <tqfontmetrics.h>
45 #include <tqlayout.h>
46 #include <tqregexp.h>
47 
54 class KateCCListBox : public TQListBox
55 {
56  public:
60  KateCCListBox (TQWidget* parent = 0, const char* name = 0, WFlags f = 0):TQListBox(parent, name, f)
61  {
62  }
63 
64  TQSize sizeHint() const
65  {
66  int count = this->count();
67  int height = 20;
68  int tmpwidth = 8;
69  //FIXME the height is for some reasons at least 3 items heigh, even if there is only one item in the list
70  if (count > 0)
71  if(count < 11)
72  height = count * itemHeight(0);
73  else {
74  height = 10 * itemHeight(0);
75  tmpwidth += verticalScrollBar()->width();
76  }
77 
78  int maxcount = 0, tmpcount = 0;
79  for (int i = 0; i < count; ++i)
80  if ( (tmpcount = fontMetrics().width(text(i)) ) > maxcount)
81  maxcount = tmpcount;
82 
83  if (maxcount > TQApplication::desktop()->width()){
84  tmpwidth = TQApplication::desktop()->width() - 5;
85  height += horizontalScrollBar()->height();
86  } else
87  tmpwidth += maxcount;
88  return TQSize(tmpwidth,height);
89 
90  }
91 };
92 
93 class KateCompletionItem : public TQListBoxText
94 {
95  public:
96  KateCompletionItem( TQListBox* lb, KTextEditor::CompletionEntry entry )
97  : TQListBoxText( lb )
98  , m_entry( entry )
99  {
100  if( entry.postfix == "()" ) { // should be configurable
101  setText( entry.prefix + " " + entry.text + entry.postfix );
102  } else {
103  setText( entry.prefix + " " + entry.text + " " + entry.postfix);
104  }
105  }
106 
107  KTextEditor::CompletionEntry m_entry;
108 };
109 
110 
111 KateCodeCompletion::KateCodeCompletion( KateView* view )
112  : TQObject( view, "Kate Code Completion" )
113  , m_view( view )
114  , m_commentLabel( 0 )
115 {
116  m_completionPopup = new TQVBox( 0, 0, (WFlags)WType_Popup );
117  m_completionPopup->setFrameStyle( TQFrame::Box | TQFrame::Plain );
118  m_completionPopup->setLineWidth( 1 );
119 
120  m_completionListBox = new KateCCListBox( m_completionPopup );
121  m_completionListBox->setFrameStyle( TQFrame::NoFrame );
122  //m_completionListBox->setCornerWidget( new TQSizeGrip( m_completionListBox) );
123  m_completionListBox->setFocusProxy( m_view->m_viewInternal );
124 
125  m_completionListBox->installEventFilter( this );
126 
127  m_completionPopup->resize(m_completionListBox->sizeHint() + TQSize(2,2));
128  m_completionPopup->installEventFilter( this );
129  m_completionPopup->setFocusProxy( m_view->m_viewInternal );
130 
131  m_pArgHint = new KateArgHint( m_view );
132  connect( m_pArgHint, TQT_SIGNAL(argHintHidden()),
133  this, TQT_SIGNAL(argHintHidden()) );
134 
135  connect( m_view, TQT_SIGNAL(cursorPositionChanged()),
136  this, TQT_SLOT(slotCursorPosChanged()) );
137 }
138 
139 KateCodeCompletion::~KateCodeCompletion()
140 {
141  delete m_completionPopup;
142 }
143 
144 bool KateCodeCompletion::codeCompletionVisible () {
145  return m_completionPopup->isVisible();
146 }
147 
148 void KateCodeCompletion::showCompletionBox(
149  TQValueList<KTextEditor::CompletionEntry> complList, int offset, bool casesensitive )
150 {
151  kdDebug(13035) << "showCompletionBox " << endl;
152 
153  if ( codeCompletionVisible() ) return;
154 
155  m_caseSensitive = casesensitive;
156  m_complList = complList;
157  m_offset = offset;
158  m_view->cursorPositionReal( &m_lineCursor, &m_colCursor );
159  m_colCursor -= offset;
160 
161  updateBox( true );
162 }
163 
164 bool KateCodeCompletion::eventFilter( TQObject *o, TQEvent *e )
165 {
166  if ( TQT_BASE_OBJECT(o) != TQT_BASE_OBJECT(m_completionPopup) &&
167  TQT_BASE_OBJECT(o) != TQT_BASE_OBJECT(m_completionListBox) &&
168  TQT_BASE_OBJECT(o) != TQT_BASE_OBJECT(m_completionListBox->viewport()) )
169  return false;
170 
171  if( e->type() == TQEvent::Hide )
172  {
173  //don't use abortCompletion() as aborting here again will send abort signal
174  //even on successfull completion we will emit completionAborted() twice...
175  m_completionPopup->hide();
176  delete m_commentLabel;
177  m_commentLabel = 0;
178  return false;
179  }
180 
181 
182  if ( e->type() == TQEvent::MouseButtonDblClick ) {
183  doComplete();
184  return false;
185  }
186 
187  if ( e->type() == TQEvent::MouseButtonPress ) {
188  TQTimer::singleShot(0, this, TQT_SLOT(showComment()));
189  return false;
190  }
191 
192  return false;
193 }
194 
195 void KateCodeCompletion::handleKey (TQKeyEvent *e)
196 {
197  // close completion if you move out of range
198  if ((e->key() == Key_Up) && (m_completionListBox->currentItem() == 0))
199  {
200  abortCompletion();
201  m_view->setFocus();
202  return;
203  }
204 
205  // keyboard movement
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 ))
209  {
210  TQTimer::singleShot(0,this,TQT_SLOT(showComment()));
211  TQApplication::sendEvent( m_completionListBox, (TQEvent*)e );
212  return;
213  }
214 
215  // update the box
216  updateBox();
217 }
218 
219 void KateCodeCompletion::doComplete()
220 {
221  KateCompletionItem* item = static_cast<KateCompletionItem*>(
222  m_completionListBox->item(m_completionListBox->currentItem()));
223 
224  if( item == 0 )
225  return;
226 
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 == "()" )
233  add += "(";
234 
235  emit filterInsertString(&(item->m_entry),&add);
236  m_view->insertText(add);
237 
238  complete( item->m_entry );
239  m_view->setFocus();
240 }
241 
242 void KateCodeCompletion::abortCompletion()
243 {
244  m_completionPopup->hide();
245  delete m_commentLabel;
246  m_commentLabel = 0;
247  emit completionAborted();
248 }
249 
250 void KateCodeCompletion::complete( KTextEditor::CompletionEntry entry )
251 {
252  m_completionPopup->hide();
253  delete m_commentLabel;
254  m_commentLabel = 0;
255  emit completionDone( entry );
256  emit completionDone();
257 }
258 
259 void KateCodeCompletion::updateBox( bool )
260 {
261  if( m_colCursor > m_view->cursorColumnReal() ) {
262  // the cursor is too far left
263  kdDebug(13035) << "Aborting Codecompletion after sendEvent" << endl;
264  kdDebug(13035) << m_view->cursorColumnReal() << endl;
265  abortCompletion();
266  m_view->setFocus();
267  return;
268  }
269 
270  m_completionListBox->clear();
271 
272  TQString currentLine = m_view->currentTextLine();
273  int len = m_view->cursorColumnReal() - m_colCursor;
274  TQString currentComplText = currentLine.mid(m_colCursor,len);
275 /* No-one really badly wants those, or?
276  kdDebug(13035) << "Column: " << m_colCursor << endl;
277  kdDebug(13035) << "Line: " << currentLine << endl;
278  kdDebug(13035) << "CurrentColumn: " << m_view->cursorColumnReal() << endl;
279  kdDebug(13035) << "Len: " << len << endl;
280  kdDebug(13035) << "Text: '" << currentComplText << "'" << endl;
281  kdDebug(13035) << "Count: " << m_complList.count() << endl;
282 */
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);
288  }
289  }
290  } else {
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);
295  }
296  }
297  }
298 
299  if( m_completionListBox->count() == 0 ||
300  ( m_completionListBox->count() == 1 && // abort if we equaled the last item
301  currentComplText == m_completionListBox->text(0).stripWhiteSpace() ) ) {
302  abortCompletion();
303  m_view->setFocus();
304  return;
305  }
306 
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() );
310  int x = p.x();
311  int y = p.y() ;
312  if ( y + m_completionPopup->height() + m_view->renderer()->config()->fontMetrics( )->height() > TQApplication::desktop()->height() )
313  y -= (m_completionPopup->height() );
314  else
315  y += m_view->renderer()->config()->fontMetrics( )->height();
316 
317  if (x + m_completionPopup->width() > TQApplication::desktop()->width())
318  x = TQApplication::desktop()->width() - m_completionPopup->width();
319 
320  m_completionPopup->move( TQPoint(x,y) );
321 
322  m_completionListBox->setCurrentItem( 0 );
323  m_completionListBox->setSelected( 0, true );
324  m_completionListBox->setFocus();
325  m_completionPopup->show();
326 
327  TQTimer::singleShot(0,this,TQT_SLOT(showComment()));
328 }
329 
330 void KateCodeCompletion::showArgHint ( TQStringList functionList, const TQString& strWrapping, const TQString& strDelimiter )
331 {
332  unsigned int line, col;
333  m_view->cursorPositionReal( &line, &col );
334  m_pArgHint->reset( line, col );
335  m_pArgHint->setArgMarkInfos( strWrapping, strDelimiter );
336 
337  int nNum = 0;
338  TQStringList::Iterator end(functionList.end());
339  for( TQStringList::Iterator it = functionList.begin(); it != end; ++it )
340  {
341  kdDebug(13035) << "Insert function text: " << *it << endl;
342 
343  m_pArgHint->addFunction( nNum, ( *it ) );
344 
345  nNum++;
346  }
347 
348  m_pArgHint->move(m_view->mapToGlobal(m_view->cursorCoordinates() + TQPoint(0,m_view->renderer()->config()->fontMetrics( )->height())) );
349  m_pArgHint->show();
350 }
351 
352 void KateCodeCompletion::slotCursorPosChanged()
353 {
354  m_pArgHint->cursorPositionChanged ( m_view, m_view->cursorLine(), m_view->cursorColumnReal() );
355 }
356 
357 void KateCodeCompletion::showComment()
358 {
359  if (!m_completionPopup->isVisible())
360  return;
361 
362  KateCompletionItem* item = static_cast<KateCompletionItem*>(m_completionListBox->item(m_completionListBox->currentItem()));
363 
364  if( !item )
365  return;
366 
367  if( item->m_entry.comment.isEmpty() )
368  return;
369 
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());
374 
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 );
378  TQPoint finalPoint;
379  if (rightPoint.x()+m_commentLabel->width() > screen.x() + screen.width())
380  finalPoint.setX(leftPoint.x()-m_commentLabel->width());
381  else
382  finalPoint.setX(rightPoint.x());
383 
384  m_completionListBox->ensureCurrentVisible();
385 
386  finalPoint.setY(
387  m_completionListBox->viewport()->mapToGlobal(m_completionListBox->itemRect(
388  m_completionListBox->item(m_completionListBox->currentItem())).topLeft()).y());
389 
390  m_commentLabel->move(finalPoint);
391  m_commentLabel->show();
392 }
393 
394 KateArgHint::KateArgHint( KateView* parent, const char* name )
395  : TQFrame( parent, name, (WFlags)WType_Popup )
396 {
397  setBackgroundColor( black );
398  setPaletteForegroundColor( Qt::black );
399 
400  labelDict.setAutoDelete( true );
401  layout = new TQVBoxLayout( this, 1, 2 );
402  layout->setAutoAdd( true );
403  editorView = parent;
404 
405  m_markCurrentFunction = true;
406 
407  setFocusPolicy( TQ_StrongFocus );
408  setFocusProxy( parent );
409 
410  reset( -1, -1 );
411 }
412 
413 KateArgHint::~KateArgHint()
414 {
415 }
416 
417 void KateArgHint::setArgMarkInfos( const TQString& wrapping, const TQString& delimiter )
418 {
419  m_wrapping = wrapping;
420  m_delimiter = delimiter;
421  m_markCurrentFunction = true;
422 }
423 
424 void KateArgHint::reset( int line, int col )
425 {
426  m_functionMap.clear();
427  m_currentFunction = -1;
428  labelDict.clear();
429 
430  m_currentLine = line;
431  m_currentCol = col - 1;
432 }
433 
434 void KateArgHint::slotDone(bool completed)
435 {
436  hide();
437 
438  m_currentLine = m_currentCol = -1;
439 
440  emit argHintHidden();
441  if (completed)
442  emit argHintCompleted();
443  else
444  emit argHintAborted();
445 }
446 
447 void KateArgHint::cursorPositionChanged( KateView* view, int line, int col )
448 {
449  if( m_currentCol == -1 || m_currentLine == -1 ){
450  slotDone(false);
451  return;
452  }
453 
454  int nCountDelimiter = 0;
455  int count = 0;
456 
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( "'[^']*'" );
461 
462  text = text
463  .replace( strconst_rx, "\"\"" )
464  .replace( chrconst_rx, "''" );
465 
466  int index = 0;
467  while( index < (int)text.length() ){
468  if( text[index] == m_wrapping[0] ){
469  ++count;
470  } else if( text[index] == m_wrapping[1] ){
471  --count;
472  } else if( count > 0 && text[index] == m_delimiter[0] ){
473  ++nCountDelimiter;
474  }
475  ++index;
476  }
477 
478  if( (m_currentLine > 0 && m_currentLine != line) || (m_currentLine < col) || (count == 0) ){
479  slotDone(count == 0);
480  return;
481  }
482 
483  // setCurArg ( nCountDelimiter + 1 );
484 
485 }
486 
487 void KateArgHint::addFunction( int id, const TQString& prot )
488 {
489  m_functionMap[ id ] = prot;
490  TQLabel* label = new TQLabel( prot.stripWhiteSpace().simplifyWhiteSpace(), this );
491  label->setBackgroundColor( TQColor(255, 255, 238) );
492  label->show();
493  labelDict.insert( id, label );
494 
495  if( m_currentFunction < 0 )
496  setCurrentFunction( id );
497 }
498 
499 void KateArgHint::setCurrentFunction( int currentFunction )
500 {
501  if( m_currentFunction != currentFunction ){
502 
503  if( currentFunction < 0 )
504  currentFunction = (int)m_functionMap.size() - 1;
505 
506  if( currentFunction > (int)m_functionMap.size()-1 )
507  currentFunction = 0;
508 
509  if( m_markCurrentFunction && m_currentFunction >= 0 ){
510  TQLabel* label = labelDict[ m_currentFunction ];
511  label->setFont( font() );
512  }
513 
514  m_currentFunction = currentFunction;
515 
516  if( m_markCurrentFunction ){
517  TQLabel* label = labelDict[ currentFunction ];
518  TQFont fnt( font() );
519  fnt.setBold( true );
520  label->setFont( fnt );
521  }
522 
523  adjustSize();
524  }
525 }
526 
527 void KateArgHint::show()
528 {
529  TQFrame::show();
530  adjustSize();
531 }
532 
533 bool KateArgHint::eventFilter( TQObject*, TQEvent* e )
534 {
535  if( isVisible() && e->type() == TQEvent::KeyPress ){
536  TQKeyEvent* ke = TQT_TQKEYEVENT( e );
537  if( (ke->state() & ControlButton) && ke->key() == Key_Left ){
538  setCurrentFunction( currentFunction() - 1 );
539  ke->accept();
540  return true;
541  } else if( ke->key() == Key_Escape ){
542  slotDone(false);
543  return false;
544  } else if( (ke->state() & ControlButton) && ke->key() == Key_Right ){
545  setCurrentFunction( currentFunction() + 1 );
546  ke->accept();
547  return true;
548  }
549  }
550 
551  return false;
552 }
553 
554 void KateArgHint::adjustSize( )
555 {
556  TQRect screen = TQApplication::desktop()->screenGeometry( pos() );
557 
558  TQFrame::adjustSize();
559  if( width() > screen.width() )
560  resize( screen.width(), height() );
561 
562  if( x() + width() > screen.x() + screen.width() )
563  move( screen.x() + screen.width() - width(), y() );
564 }
kdDebug
kdbgstream kdDebug(int area=0)
TDEStdAccel::end
const TDEShortcut & end()
endl
kndbgstream & endl(kndbgstream &s)
TDEStdAccel::name
TQString name(StdAccel id)
TDEStdAccel::label
TQString label(StdAccel id)

kate

Skip menu "kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kate

Skip menu "kate"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kate by doxygen 1.8.8
This website is maintained by Timothy Pearson.