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

kate

  • kate
  • plugins
  • wordcompletion
docwordcompletion.cpp
1 /*
2  This library is free software; you can redistribute it and/or
3  modify it under the terms of the GNU Library General Public
4  License version 2 as published by the Free Software Foundation.
5 
6  This library is distributed in the hope that it will be useful,
7  but WITHOUT ANY WARRANTY; without even the implied warranty of
8  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9  Library General Public License for more details.
10 
11  You should have received a copy of the GNU Library General Public License
12  along with this library; see the file COPYING.LIB. If not, write to
13  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
14  Boston, MA 02110-1301, USA.
15 
16  ---
17  file: docwordcompletion.cpp
18 
19  KTextEditor plugin to autocompletion with document words.
20  Copyright Anders Lund <anders.lund@lund.tdcadsl.dk>, 2003
21 
22  The following completion methods are supported:
23  * Completion with bigger matching words in
24  either direction (backward/forward).
25  * NOT YET Pop up a list of all bigger matching words in document
26 
27 */
28 //BEGIN includes
29 #include "docwordcompletion.h"
30 
31 #include <tdetexteditor/document.h>
32 #include <tdetexteditor/viewcursorinterface.h>
33 #include <tdetexteditor/editinterface.h>
34 #include <tdetexteditor/variableinterface.h>
35 
36 #include <tdeapplication.h>
37 #include <tdeconfig.h>
38 #include <kdialog.h>
39 #include <kgenericfactory.h>
40 #include <tdelocale.h>
41 #include <tdeaction.h>
42 #include <knotifyclient.h>
43 #include <tdeparts/part.h>
44 #include <kiconloader.h>
45 
46 #include <tqregexp.h>
47 #include <tqstring.h>
48 #include <tqdict.h>
49 #include <tqspinbox.h>
50 #include <tqlabel.h>
51 #include <tqlayout.h>
52 #include <tqhbox.h>
53 #include <tqwhatsthis.h>
54 #include <tqcheckbox.h>
55 
56 // #include <kdebug.h>
57 //END
58 
59 //BEGIN DocWordCompletionPlugin
60 K_EXPORT_COMPONENT_FACTORY( tdetexteditor_docwordcompletion, KGenericFactory<DocWordCompletionPlugin>( "tdetexteditor_docwordcompletion" ) )
61 DocWordCompletionPlugin::DocWordCompletionPlugin( TQObject *parent,
62  const char* name,
63  const TQStringList& /*args*/ )
64  : KTextEditor::Plugin ( (KTextEditor::Document*) parent, name )
65 {
66  readConfig();
67 }
68 
69 void DocWordCompletionPlugin::readConfig()
70 {
71  TDEConfig *config = kapp->config();
72  config->setGroup( "DocWordCompletion Plugin" );
73  m_treshold = config->readNumEntry( "treshold", 3 );
74  m_autopopup = config->readBoolEntry( "autopopup", true );
75 }
76 
77 void DocWordCompletionPlugin::writeConfig()
78 {
79  TDEConfig *config = kapp->config();
80  config->setGroup("DocWordCompletion Plugin");
81  config->writeEntry("autopopup", m_autopopup );
82  config->writeEntry("treshold", m_treshold );
83 }
84 
85 void DocWordCompletionPlugin::addView(KTextEditor::View *view)
86 {
87  DocWordCompletionPluginView *nview = new DocWordCompletionPluginView (m_treshold, m_autopopup, view, "Document word completion");
88  m_views.append (nview);
89 }
90 
91 void DocWordCompletionPlugin::removeView(KTextEditor::View *view)
92 {
93  for (uint z=0; z < m_views.count(); z++)
94  if (m_views.at(z)->parentClient() == view)
95  {
96  DocWordCompletionPluginView *nview = m_views.at(z);
97  m_views.remove (nview);
98  delete nview;
99  }
100 }
101 
102 KTextEditor::ConfigPage* DocWordCompletionPlugin::configPage( uint, TQWidget *parent, const char *name )
103 {
104  return new DocWordCompletionConfigPage( this, parent, name );
105 }
106 
107 TQString DocWordCompletionPlugin::configPageName( uint ) const
108 {
109  return i18n("Word Completion Plugin");
110 }
111 
112 TQString DocWordCompletionPlugin::configPageFullName( uint ) const
113 {
114  return i18n("Configure the Word Completion Plugin");
115 }
116 
117 // FIXME provide sucn a icon
118  TQPixmap DocWordCompletionPlugin::configPagePixmap( uint, int size ) const
119 {
120  return UserIcon( "kte_wordcompletion", size );
121 }
122 //END
123 
124 //BEGIN DocWordCompletionPluginView
125 struct DocWordCompletionPluginViewPrivate
126 {
127  uint line, col; // start position of last match (where to search from)
128  uint cline, ccol; // cursor position
129  uint lilen; // length of last insertion
130  TQString last; // last word we were trying to match
131  TQString lastIns; // latest applied completion
132  TQRegExp re; // hrm
133  TDEToggleAction *autopopup; // for accessing state
134  uint treshold; // the required length of a word before popping up the completion list automatically
135  int directionalPos; // be able to insert "" at the correct time
136 };
137 
138 DocWordCompletionPluginView::DocWordCompletionPluginView( uint treshold, bool autopopup, KTextEditor::View *view, const char *name )
139  : TQObject( view, name ),
140  KXMLGUIClient( view ),
141  m_view( view ),
142  d( new DocWordCompletionPluginViewPrivate )
143 {
144  d->treshold = treshold;
145  view->insertChildClient( this );
146  setInstance( KGenericFactory<DocWordCompletionPlugin>::instance() );
147 
148  (void) new TDEAction( i18n("Reuse Word Above"), CTRL+Key_8, this,
149  TQT_SLOT(completeBackwards()), actionCollection(), "doccomplete_bw" );
150  (void) new TDEAction( i18n("Reuse Word Below"), CTRL+Key_9, this,
151  TQT_SLOT(completeForwards()), actionCollection(), "doccomplete_fw" );
152  (void) new TDEAction( i18n("Pop Up Completion List"), 0, this,
153  TQT_SLOT(popupCompletionList()), actionCollection(), "doccomplete_pu" );
154  (void) new TDEAction( i18n("Shell Completion"), 0, this,
155  TQT_SLOT(shellComplete()), actionCollection(), "doccomplete_sh" );
156  d->autopopup = new TDEToggleAction( i18n("Automatic Completion Popup"), 0, this,
157  TQT_SLOT(toggleAutoPopup()), actionCollection(), "enable_autopopup" );
158 
159  d->autopopup->setChecked( autopopup );
160  toggleAutoPopup();
161 
162  setXMLFile("docwordcompletionui.rc");
163 
164  KTextEditor::VariableInterface *vi = KTextEditor::variableInterface( view->document() );
165  if ( vi )
166  {
167  TQString e = vi->variable("wordcompletion-autopopup");
168  if ( ! e.isEmpty() )
169  d->autopopup->setEnabled( e == "true" );
170 
171  connect( view->document(), TQT_SIGNAL(variableChanged(const TQString &, const TQString &)),
172  this, TQT_SLOT(slotVariableChanged(const TQString &, const TQString &)) );
173  }
174 }
175 
176 void DocWordCompletionPluginView::settreshold( uint t )
177 {
178  d->treshold = t;
179 }
180 
181 void DocWordCompletionPluginView::completeBackwards()
182 {
183  complete( false );
184 }
185 
186 void DocWordCompletionPluginView::completeForwards()
187 {
188  complete();
189 }
190 
191 // Pop up the editors completion list if applicable
192 void DocWordCompletionPluginView::popupCompletionList( TQString w )
193 {
194  if ( w.isEmpty() )
195  w = word();
196  if ( w.isEmpty() )
197  return;
198 
199  KTextEditor::CodeCompletionInterface *cci = codeCompletionInterface( m_view );
200  cci->showCompletionBox( allMatches( w ), w.length() );
201 }
202 
203 void DocWordCompletionPluginView::toggleAutoPopup()
204 {
205  if ( d->autopopup->isChecked() ) {
206  if ( ! connect( m_view->document(), TQT_SIGNAL(charactersInteractivelyInserted(int ,int ,const TQString&)),
207  this, TQT_SLOT(autoPopupCompletionList()) ))
208  {
209  connect( m_view->document(), TQT_SIGNAL(textChanged()), this, TQT_SLOT(autoPopupCompletionList()) );
210  }
211  } else {
212  disconnect( m_view->document(), TQT_SIGNAL(textChanged()), this, TQT_SLOT(autoPopupCompletionList()) );
213  disconnect( m_view->document(), TQT_SIGNAL(charactersInteractivelyInserted(int ,int ,const TQString&)),
214  this, TQT_SLOT(autoPopupCompletionList()) );
215 
216  }
217 }
218 
219 // for autopopup FIXME - don't pop up if reuse word is inserting
220 void DocWordCompletionPluginView::autoPopupCompletionList()
221 {
222  if ( ! m_view->hasFocus() ) return;
223  TQString w = word();
224  if ( w.length() >= d->treshold )
225  {
226  popupCompletionList( w );
227  }
228 }
229 
230 // Contributed by <brain@hdsnet.hu>
231 void DocWordCompletionPluginView::shellComplete()
232 {
233  // setup
234  KTextEditor::EditInterface * ei = KTextEditor::editInterface(m_view->document());
235  // find the word we are typing
236  uint cline, ccol;
237  viewCursorInterface(m_view)->cursorPositionReal(&cline, &ccol);
238  TQString wrd = word();
239  if (wrd.isEmpty())
240  return;
241 
242  TQValueList < KTextEditor::CompletionEntry > matches = allMatches(wrd);
243  if (matches.size() == 0)
244  return;
245  TQString partial = findLongestUnique(matches);
246  if (partial.length() == wrd.length())
247  {
248  KTextEditor::CodeCompletionInterface * cci = codeCompletionInterface(m_view);
249  cci->showCompletionBox(matches, wrd.length());
250  }
251  else
252  {
253  partial.remove(0, wrd.length());
254  ei->insertText(cline, ccol, partial);
255  }
256 }
257 
258 // Do one completion, searching in the desired direction,
259 // if possible
260 void DocWordCompletionPluginView::complete( bool fw )
261 {
262  // setup
263  KTextEditor::EditInterface *ei = KTextEditor::editInterface( m_view->document() );
264  // find the word we are typing
265  uint cline, ccol;
266  viewCursorInterface( m_view )->cursorPositionReal( &cline, &ccol );
267  TQString wrd = word();
268  if ( wrd.isEmpty() )
269  return;
270 
271  int inc = fw ? 1 : -1;
272 
273  /* IF the current line is equal to the previous line
274  AND the position - the length of the last inserted string
275  is equal to the old position
276  AND the lastinsertedlength last characters of the word is
277  equal to the last inserted string
278  */
279  if ( cline == d-> cline &&
280  ccol - d->lilen == d->ccol &&
281  wrd.endsWith( d->lastIns ) )
282  {
283  // this is a repeted activation
284 
285  // if we are back to where we started, reset.
286  if ( ( fw && d->directionalPos == -1 ) ||
287  ( !fw && d->directionalPos == 1 ) )
288  {
289  if ( d->lilen )
290  ei->removeText( d->cline, d->ccol, d->cline, d->ccol + d->lilen );
291 
292  d->lastIns = "";
293  d->lilen = 0;
294  d->line = d->cline;
295  d->col = d->ccol;
296  d->directionalPos = 0;
297 
298  return;
299  }
300 
301  if ( fw )
302  d->col += d->lilen;
303 
304  ccol = d->ccol;
305  wrd = d->last;
306 
307  d->directionalPos += inc;
308  }
309  else
310  {
311  d->cline = cline;
312  d->ccol = ccol;
313  d->last = wrd;
314  d->lastIns = "";
315  d->line = cline;
316  d->col = ccol - wrd.length();
317  d->lilen = 0;
318  d->directionalPos = inc;
319  }
320 
321  d->re.setPattern( "\\b" + wrd + "(\\w+)" );
322  int pos ( 0 );
323  TQString ln = ei->textLine( d->line );
324 
325  while ( true )
326  {
327  pos = fw ?
328  d->re.search( ln, d->col ) :
329  d->re.searchRev( ln, d->col );
330 
331  if ( pos > -1 ) // we matched a word
332  {
333  TQString m = d->re.cap( 1 );
334  if ( m != d->lastIns )
335  {
336  // we got good a match! replace text and return.
337  if ( d->lilen )
338  ei->removeText( d->cline, d->ccol, d->cline, d->ccol + d->lilen );
339  ei->insertText( d->cline, d->ccol, m );
340 
341  d->lastIns = m;
342  d->lilen = m.length();
343  d->col = pos; // for next try
344 
345  return;
346  }
347 
348  // equal to last one, continue
349  else
350  {
351  d->col = pos; // for next try
352 
353  if ( fw )
354  d->col += d->re.matchedLength();
355 
356  else
357  {
358  if ( pos == 0 )
359  {
360  if ( d->line > 0 )
361  {
362  d->line += inc;
363  ln = ei->textLine( d->line );
364  d->col = ln.length();
365  }
366  else
367  {
368  KNotifyClient::beep();
369  return;
370  }
371  }
372 
373  else
374  d->col--;
375  }
376  }
377  }
378 
379  else // no match
380  {
381  if ( (! fw && d->line == 0 ) || ( fw && d->line >= (uint)ei->numLines() ) )
382  {
383  KNotifyClient::beep();
384  return;
385  }
386 
387  d->line += inc;
388 
389  ln = ei->textLine( d->line );
390  d->col = fw ? 0 : ln.length();
391  }
392  } // while true
393 }
394 
395 // Contributed by <brain@hdsnet.hu>
396 TQString DocWordCompletionPluginView::findLongestUnique(const TQValueList < KTextEditor::CompletionEntry > &matches)
397 {
398  TQString partial = matches.front().text;
399  TQValueList < KTextEditor::CompletionEntry >::const_iterator i = matches.begin();
400  for (++i; i != matches.end(); ++i)
401  {
402  if (!(*i).text.startsWith(partial))
403  {
404  while(partial.length() > 0)
405  {
406  partial.remove(partial.length() - 1, 1);
407  if ((*i).text.startsWith(partial))
408  {
409  break;
410  }
411  }
412  if (partial.length() == 0)
413  return TQString();
414  }
415  }
416 
417  return partial;
418 }
419 
420 // Return the string to complete (the letters behind the cursor)
421 TQString DocWordCompletionPluginView::word()
422 {
423  uint cline, ccol;
424  viewCursorInterface( m_view )->cursorPositionReal( &cline, &ccol );
425  if ( ! ccol ) return TQString::null; // no word
426  KTextEditor::EditInterface *ei = KTextEditor::editInterface( m_view->document() );
427  d->re.setPattern( "\\b(\\w+)$" );
428  if ( d->re.searchRev(
429  ei->text( cline, 0, cline, ccol )
430  ) < 0 )
431  return TQString::null; // no word
432  return d->re.cap( 1 );
433 }
434 
435 // Scan throught the entire document for possible completions,
436 // ignoring any dublets
437 TQValueList<KTextEditor::CompletionEntry> DocWordCompletionPluginView::allMatches( const TQString &word )
438 {
439  TQValueList<KTextEditor::CompletionEntry> l;
440  uint i( 0 );
441  int pos( 0 );
442  d->re.setPattern( "\\b("+word+"\\w+)" );
443  TQString s, m;
444  KTextEditor::EditInterface *ei = KTextEditor::editInterface( m_view->document() );
445  TQDict<int> seen; // maybe slow with > 17 matches
446  int sawit(1); // to ref for the dict
447  uint cline, ccol;// needed to avoid constructing a word at cursor position
448  viewCursorInterface( m_view )->cursorPositionReal( &cline, &ccol );
449 
450  while( i < ei->numLines() )
451  {
452  s = ei->textLine( i );
453  pos = 0;
454  while ( pos >= 0 )
455  {
456  pos = d->re.search( s, pos );
457  if ( pos >= 0 )
458  {
459  // do not construct a new word!
460  if ( i == cline && pos + word.length() == ccol )
461  {
462  pos += word.length();
463  continue;
464  }
465 
466  m = d->re.cap( 1 );
467  if ( ! seen[ m ] ) {
468  seen.insert( m, &sawit );
469  KTextEditor::CompletionEntry e;
470  e.text = m;
471  l.append( e );
472  }
473  pos += d->re.matchedLength();
474  }
475  }
476  i++;
477  }
478  return l;
479 }
480 
481 void DocWordCompletionPluginView::slotVariableChanged( const TQString &var, const TQString &val )
482 {
483  if ( var == "wordcompletion-autopopup" )
484  d->autopopup->setEnabled( val == "true" );
485  else if ( var == "wordcompletion-treshold" )
486  d->treshold = val.toInt();
487 }
488 //END
489 
490 //BEGIN DocWordCompletionConfigPage
491 DocWordCompletionConfigPage::DocWordCompletionConfigPage( DocWordCompletionPlugin *completion, TQWidget *parent, const char *name )
492  : KTextEditor::ConfigPage( parent, name )
493  , m_completion( completion )
494 {
495  TQVBoxLayout *lo = new TQVBoxLayout( this );
496  lo->setSpacing( KDialog::spacingHint() );
497 
498  cbAutoPopup = new TQCheckBox( i18n("Automatically &show completion list"), this );
499  lo->addWidget( cbAutoPopup );
500 
501  TQHBox *hb = new TQHBox( this );
502  hb->setSpacing( KDialog::spacingHint() );
503  lo->addWidget( hb );
504  TQLabel *l = new TQLabel( i18n(
505  "Translators: This is the first part of two strings wich will comprise the "
506  "sentence 'Show completions when a word is at least N characters'. The first "
507  "part is on the right side of the N, which is represented by a spinbox "
508  "widget, followed by the second part: 'characters long'. Characters is a "
509  "ingeger number between and including 1 and 30. Feel free to leave the "
510  "second part of the sentence blank if it suits your language better. ",
511  "Show completions &when a word is at least"), hb );
512  sbAutoPopup = new TQSpinBox( 1, 30, 1, hb );
513  l->setBuddy( sbAutoPopup );
514  lSbRight = new TQLabel( i18n(
515  "This is the second part of two strings that will comprise teh sentence "
516  "'Show completions when a word is at least N characters'",
517  "characters long."), hb );
518 
519  TQWhatsThis::add( cbAutoPopup, i18n(
520  "Enable the automatic completion list popup as default. The popup can "
521  "be disabled on a view basis from the 'Tools' menu.") );
522  TQWhatsThis::add( sbAutoPopup, i18n(
523  "Define the length a word should have before the completion list "
524  "is displayed.") );
525 
526  cbAutoPopup->setChecked( m_completion->autoPopupEnabled() );
527  sbAutoPopup->setValue( m_completion->treshold() );
528 
529  lo->addStretch();
530 }
531 
532 void DocWordCompletionConfigPage::apply()
533 {
534  m_completion->setAutoPopupEnabled( cbAutoPopup->isChecked() );
535  m_completion->setTreshold( sbAutoPopup->value() );
536  m_completion->writeConfig();
537 }
538 
539 void DocWordCompletionConfigPage::reset()
540 {
541  cbAutoPopup->setChecked( m_completion->autoPopupEnabled() );
542  sbAutoPopup->setValue( m_completion->treshold() );
543 }
544 
545 void DocWordCompletionConfigPage::defaults()
546 {
547  cbAutoPopup->setChecked( true );
548  sbAutoPopup->setValue( 3 );
549 }
550 
551 //END DocWordCompletionConfigPage
552 
553 #include "docwordcompletion.moc"
TDEConfig
KXMLGUIClient
KNotifyClient::beep
void beep(const TQString &reason=TQString::null)
KGenericFactory
TDEAction
tdelocale.h
TDEToggleAction
KTextEditor
Definition: katebookmarks.h:28

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.