• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Kate

ISearchPlugin.cpp

Go to the documentation of this file.
00001  /* This file is part of the KDE libraries
00002     Copyright (C) 2002 by John Firebaugh <jfirebaugh@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License version 2 as published by the Free Software Foundation.
00007 
00008     This library is distributed in the hope that it will be useful,
00009     but WITHOUT ANY WARRANTY; without even the implied warranty of
00010     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011     Library General Public License for more details.
00012 
00013     You should have received a copy of the GNU Library General Public License
00014     along with this library; see the file COPYING.LIB.  If not, write to
00015     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016     Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include <qlabel.h>
00020 #include <qregexp.h>
00021 #include <qstyle.h>
00022 #include <qpopupmenu.h>
00023 #include <kgenericfactory.h>
00024 #include <klocale.h>
00025 #include <kaction.h>
00026 #include <kcombobox.h>
00027 #include <kconfig.h>
00028 #include <kdebug.h>
00029 
00030 #include "ISearchPlugin.h"
00031 #include "ISearchPlugin.moc"
00032 
00033 K_EXPORT_COMPONENT_FACTORY( ktexteditor_isearch, KGenericFactory<ISearchPlugin>( "ktexteditor_isearch" ) )
00034 
00035 ISearchPluginView::ISearchPluginView( KTextEditor::View *view )
00036     : QObject ( view ), KXMLGUIClient (view)
00037     , m_view( 0L )
00038     , m_doc( 0L )
00039     , m_searchIF( 0L )
00040     , m_cursorIF( 0L )
00041     , m_selectIF( 0L )
00042 //  , m_toolBarAction( 0L )
00043     , m_searchForwardAction( 0L )
00044     , m_searchBackwardAction( 0L )
00045     , m_label( 0L )
00046     , m_combo( 0L )
00047     , m_lastString( "" )
00048     , m_searchBackward( false )
00049     , m_caseSensitive( false )
00050     , m_fromBeginning( false )
00051     , m_regExp( false )
00052     , m_autoWrap( false )
00053     , m_wrapped( false )
00054     , m_startLine( 0 )
00055     , m_startCol( 0 )
00056     , m_searchLine( 0 )
00057     , m_searchCol( 0 )
00058     , m_foundLine( 0 )
00059     , m_foundCol( 0 )
00060     , m_matchLen( 0 )
00061     , m_toolBarWasHidden( false )
00062 {
00063     view->insertChildClient (this);
00064 
00065     setInstance( KGenericFactory<ISearchPlugin>::instance() );
00066 
00067     m_searchForwardAction = new KAction(
00068         i18n("Search Incrementally"), CTRL+ALT+Key_F,
00069         this, SLOT(slotSearchForwardAction()),
00070         actionCollection(), "edit_isearch" );
00071     m_searchBackwardAction = new KAction(
00072         i18n("Search Incrementally Backwards"), CTRL+ALT+SHIFT+Key_F,
00073         this, SLOT(slotSearchBackwardAction()),
00074         actionCollection(), "edit_isearch_reverse" );
00075 
00076     m_label = new QLabel( i18n("I-Search:"), 0L, "kde toolbar widget" );
00077     KWidgetAction* labelAction = new KWidgetAction(
00078         m_label,
00079         i18n("I-Search:"), 0, 0, 0,
00080         actionCollection(), "isearch_label" );
00081     labelAction->setShortcutConfigurable( false );
00082 
00083     m_combo = new KHistoryCombo();
00084     m_combo->setDuplicatesEnabled( false );
00085     m_combo->setMaximumWidth( 300 );
00086     m_combo->lineEdit()->installEventFilter( this );
00087     connect( m_combo, SIGNAL(textChanged(const QString&)),
00088              this, SLOT(slotTextChanged(const QString&)) );
00089     connect( m_combo, SIGNAL(returnPressed(const QString&)),
00090              this, SLOT(slotReturnPressed(const QString&)) );
00091     connect( m_combo, SIGNAL(aboutToShowContextMenu(QPopupMenu*)),
00092          this, SLOT(slotAddContextMenuItems(QPopupMenu*)) );
00093     m_comboAction = new KWidgetAction(
00094         m_combo,
00095         i18n("Search"), 0, 0, 0,
00096         actionCollection(), "isearch_combo" );
00097     m_comboAction->setAutoSized( true );
00098     m_comboAction->setShortcutConfigurable( false );
00099 
00100     KActionMenu* optionMenu = new KActionMenu(
00101         i18n("Search Options"), "configure",
00102         actionCollection(), "isearch_options" );
00103     optionMenu->setDelayed( false );
00104 
00105     KToggleAction* action = new KToggleAction(
00106         i18n("Case Sensitive"), KShortcut(),
00107         actionCollection(), "isearch_case_sensitive" );
00108     action->setShortcutConfigurable( false );
00109     connect( action, SIGNAL(toggled(bool)),
00110              this, SLOT(setCaseSensitive(bool)) );
00111     action->setChecked( m_caseSensitive );
00112     optionMenu->insert( action );
00113 
00114     action = new KToggleAction(
00115         i18n("From Beginning"), KShortcut(),
00116         actionCollection(), "isearch_from_beginning" );
00117     action->setShortcutConfigurable( false );
00118     connect( action, SIGNAL(toggled(bool)),
00119              this, SLOT(setFromBeginning(bool)) );
00120     action->setChecked( m_fromBeginning );
00121     optionMenu->insert( action );
00122 
00123     action = new KToggleAction(
00124         i18n("Regular Expression"), KShortcut(),
00125         actionCollection(), "isearch_reg_exp" );
00126     action->setShortcutConfigurable( false );
00127     connect( action, SIGNAL(toggled(bool)),
00128              this, SLOT(setRegExp(bool)) );
00129     action->setChecked( m_regExp );
00130     optionMenu->insert( action );
00131 
00132 //  optionMenu->insert( new KActionSeparator() );
00133 //
00134 //  action = new KToggleAction(
00135 //      i18n("Auto-Wrap Search"), KShortcut(),
00136 //      actionCollection(), "isearch_auto_wrap" );
00137 //  connect( action, SIGNAL(toggled(bool)),
00138 //           this, SLOT(setAutoWrap(bool)) );
00139 //  action->setChecked( m_autoWrap );
00140 //  optionMenu->insert( action );
00141 
00142     setXMLFile( "ktexteditor_isearchui.rc" );
00143 }
00144 
00145 ISearchPluginView::~ISearchPluginView()
00146 {
00147     writeConfig();
00148     m_combo->lineEdit()->removeEventFilter( this );
00149     delete m_combo;
00150     delete m_label;
00151 }
00152 
00153 void ISearchPluginView::setView( KTextEditor::View* view )
00154 {
00155     m_view = view;
00156     m_doc  = m_view->document();
00157     m_searchIF = KTextEditor::searchInterface ( m_doc );
00158     m_cursorIF = KTextEditor::viewCursorInterface ( m_view );
00159     m_selectIF = KTextEditor::selectionInterface ( m_doc );
00160     if( !m_doc || !m_cursorIF || !m_selectIF ) {
00161         m_view = 0L;
00162         m_doc = 0L;
00163         m_searchIF = 0L;
00164         m_cursorIF = 0L;
00165         m_selectIF = 0L;
00166     }
00167 
00168     readConfig();
00169 }
00170 
00171 void ISearchPluginView::readConfig()
00172 {
00173     // KConfig* config = instance()->config();
00174 }
00175 
00176 void ISearchPluginView::writeConfig()
00177 {
00178     // KConfig* config = instance()->config();
00179 }
00180 
00181 void ISearchPluginView::setCaseSensitive( bool caseSensitive )
00182 {
00183     m_caseSensitive = caseSensitive;
00184 }
00185 
00186 void ISearchPluginView::setFromBeginning( bool fromBeginning )
00187 {
00188     m_fromBeginning = fromBeginning;
00189 
00190     if( m_fromBeginning ) {
00191         m_searchLine = m_searchCol = 0;
00192     }
00193 }
00194 
00195 void ISearchPluginView::setRegExp( bool regExp )
00196 {
00197     m_regExp = regExp;
00198 }
00199 
00200 void ISearchPluginView::setAutoWrap( bool autoWrap )
00201 {
00202     m_autoWrap = autoWrap;
00203 }
00204 
00205 bool ISearchPluginView::eventFilter( QObject* o, QEvent* e )
00206 {
00207     if( o != m_combo->lineEdit() )
00208         return false;
00209 
00210     if( e->type() == QEvent::FocusIn ) {
00211         QFocusEvent* focusEvent = (QFocusEvent*)e;
00212         if( focusEvent->reason() == QFocusEvent::ActiveWindow ||
00213             focusEvent->reason() == QFocusEvent::Popup )
00214             return false;
00215         startSearch();
00216     }
00217 
00218     if( e->type() == QEvent::FocusOut ) {
00219         QFocusEvent* focusEvent = (QFocusEvent*)e;
00220         if( focusEvent->reason() == QFocusEvent::ActiveWindow ||
00221             focusEvent->reason() == QFocusEvent::Popup )
00222             return false;
00223         endSearch();
00224     }
00225 
00226     if( e->type() == QEvent::KeyPress ) {
00227         QKeyEvent *keyEvent = (QKeyEvent*)e;
00228         if( keyEvent->key() == Qt::Key_Escape )
00229             quitToView( QString::null );
00230     }
00231 
00232     return false;
00233 }
00234 
00235 // Sigh... i18n hell.
00236 void ISearchPluginView::updateLabelText(
00237     bool failing /* = false */, bool reverse /* = false */,
00238     bool wrapped /* = false */, bool overwrapped /* = false */ )
00239 {
00240     QString text;
00241     // Reverse binary:
00242     // 0000
00243     if( !failing && !reverse && !wrapped && !overwrapped ) {
00244         text = i18n("Incremental Search", "I-Search:");
00245     // 1000
00246     } else if ( failing && !reverse && !wrapped && !overwrapped ) {
00247         text = i18n("Incremental Search found no match", "Failing I-Search:");
00248     // 0100
00249     } else if ( !failing && reverse && !wrapped && !overwrapped ) {
00250         text = i18n("Incremental Search in the reverse direction", "I-Search Backward:");
00251     // 1100
00252     } else if ( failing && reverse && !wrapped && !overwrapped ) {
00253         text = i18n("Failing I-Search Backward:");
00254     // 0010
00255     } else if ( !failing && !reverse && wrapped  && !overwrapped ) {
00256         text = i18n("Incremental Search has passed the end of the document", "Wrapped I-Search:");
00257     // 1010
00258     } else if ( failing && !reverse && wrapped && !overwrapped ) {
00259         text = i18n("Failing Wrapped I-Search:");
00260     // 0110
00261     } else if ( !failing && reverse && wrapped && !overwrapped ) {
00262         text = i18n("Wrapped I-Search Backward:");
00263     // 1110
00264     } else if ( failing && reverse && wrapped && !overwrapped ) {
00265         text = i18n("Failing Wrapped I-Search Backward:");
00266     // 0011
00267     } else if ( !failing && !reverse && overwrapped ) {
00268         text = i18n("Incremental Search has passed both the end of the document "
00269                     "and the original starting position", "Overwrapped I-Search:");
00270     // 1011
00271     } else if ( failing && !reverse && overwrapped ) {
00272         text = i18n("Failing Overwrapped I-Search:");
00273     // 0111
00274     } else if ( !failing && reverse && overwrapped ) {
00275         text = i18n("Overwrapped I-Search Backwards:");
00276     // 1111
00277     } else if ( failing && reverse && overwrapped ) {
00278         text = i18n("Failing Overwrapped I-Search Backward:");
00279     } else {
00280         text = i18n("Error: unknown i-search state!");
00281     }
00282     m_label->setText( text );
00283 }
00284 
00285 void ISearchPluginView::slotSearchForwardAction()
00286 {
00287     slotSearchAction( false );
00288 }
00289 
00290 void ISearchPluginView::slotSearchBackwardAction()
00291 {
00292     slotSearchAction( true );
00293 }
00294 
00295 void ISearchPluginView::slotSearchAction( bool reverse )
00296 {
00297     if( !m_combo->hasFocus() ) {
00298         if( m_comboAction->container(0) && m_comboAction->container(0)->isHidden() ) {
00299             m_toolBarWasHidden = true;
00300             m_comboAction->container(0)->setHidden( false );
00301         } else {
00302             m_toolBarWasHidden = false;
00303         }
00304         m_combo->setFocus(); // Will call startSearch()
00305     } else {
00306         nextMatch( reverse );
00307     }
00308 }
00309 
00310 void ISearchPluginView::nextMatch( bool reverse )
00311 {
00312     QString text = m_combo->currentText();
00313     if( text.isEmpty() )
00314         return;
00315     if( state != MatchSearch ) {
00316         // Last search was performed by typing, start from that match.
00317         if( !reverse ) {
00318             m_searchLine = m_foundLine;
00319             m_searchCol = m_foundCol + m_matchLen;
00320         } else {
00321             m_searchLine = m_foundLine;
00322             m_searchCol = m_foundCol;
00323         }
00324         state = MatchSearch;
00325     }
00326         
00327     bool found = iSearch( m_searchLine, m_searchCol, text, reverse, m_autoWrap );
00328     if( found ) {
00329         m_searchLine = m_foundLine;
00330         m_searchCol = m_foundCol + m_matchLen;
00331     } else {
00332         m_wrapped = true;
00333         m_searchLine = m_searchCol = 0;
00334     }
00335 }
00336 
00337 void ISearchPluginView::startSearch()
00338 {
00339     if( !m_view ) return;
00340 
00341     m_searchForwardAction->setText( i18n("Next Incremental Search Match") );
00342     m_searchBackwardAction->setText( i18n("Previous Incremental Search Match") );
00343 
00344     m_wrapped = false;
00345 
00346     if( m_fromBeginning ) {
00347         m_startLine = m_startCol = 0;
00348     } else {
00349         m_cursorIF->cursorPositionReal( &m_startLine, &m_startCol );
00350     }
00351     m_searchLine = m_startLine;
00352     m_searchCol = m_startCol;
00353 
00354     updateLabelText( false, m_searchBackward );
00355 
00356     m_combo->blockSignals( true );
00357 
00358     QString text = m_selectIF->selection();
00359     if( text.isEmpty() )
00360         text = m_lastString;
00361     m_combo->setCurrentText( text );
00362 
00363     m_combo->blockSignals( false );
00364     m_combo->lineEdit()->selectAll();
00365 
00366 //  kdDebug() << "Starting search at " << m_startLine << ", " << m_startCol << endl;
00367 }
00368 
00369 void ISearchPluginView::endSearch()
00370 {
00371     m_searchForwardAction->setText( i18n("Search Incrementally") );
00372     m_searchBackwardAction->setText( i18n("Search Incrementally Backwards") );
00373 
00374     updateLabelText();
00375 
00376     if( m_toolBarWasHidden && m_comboAction->containerCount() > 0 ) {
00377         m_comboAction->container(0)->setHidden( true );
00378     }
00379 }
00380 
00381 void ISearchPluginView::quitToView( const QString &text )
00382 {
00383     if( !text.isNull() && !text.isEmpty() ) {
00384         m_combo->addToHistory( text );
00385         m_lastString = text;
00386     }
00387 
00388     if( m_view ) {
00389         m_view->setFocus(); // Will call endSearch()
00390     }
00391 }
00392 
00393 void ISearchPluginView::slotTextChanged( const QString& text )
00394 {
00395     state = TextSearch;
00396 
00397     if( text.isEmpty() )
00398         return;
00399 
00400     iSearch( m_searchLine, m_searchCol, text, m_searchBackward, m_autoWrap );
00401 }
00402 
00403 void ISearchPluginView::slotReturnPressed( const QString& text )
00404 {
00405     quitToView( text );
00406 }
00407 
00408 void ISearchPluginView::slotAddContextMenuItems( QPopupMenu *menu )
00409 {
00410     if( menu ) {
00411         menu->insertSeparator();
00412         menu->insertItem( i18n("Case Sensitive"), this,
00413                   SLOT(setCaseSensitive(bool)));
00414         menu->insertItem( i18n("From Beginning"), this,
00415                   SLOT(setFromBeginning(bool)));
00416         menu->insertItem( i18n("Regular Expression"), this,
00417                   SLOT(setRegExp(bool)));
00418         //menu->insertItem( i18n("Auto-Wrap Search"), this,
00419         //        SLOT(setAutoWrap(bool)));
00420     }
00421 }
00422 
00423 bool ISearchPluginView::iSearch(
00424     uint startLine, uint startCol,
00425     const QString& text, bool reverse,
00426     bool autoWrap )
00427 {
00428     if( !m_view ) return false;
00429 
00430 //  kdDebug() << "Searching for " << text << " at " << startLine << ", " << startCol << endl;
00431     bool found = false;
00432     if( !m_regExp ) {
00433         found = m_searchIF->searchText( startLine,
00434                        startCol,
00435                        text,
00436                        &m_foundLine,
00437                        &m_foundCol,
00438                        &m_matchLen,
00439                        m_caseSensitive,
00440                        reverse );
00441     } else {
00442         found = m_searchIF->searchText( startLine,
00443                        startCol,
00444                        QRegExp( text ),
00445                        &m_foundLine,
00446                        &m_foundCol,
00447                        &m_matchLen,
00448                        reverse );
00449     }
00450     if( found ) {
00451 //      kdDebug() << "Found '" << text << "' at " << m_foundLine << ", " << m_foundCol << endl;
00452 //      v->gotoLineNumber( m_foundLine );
00453         m_cursorIF->setCursorPositionReal( m_foundLine, m_foundCol + m_matchLen );
00454         m_selectIF->setSelection( m_foundLine, m_foundCol, m_foundLine, m_foundCol + m_matchLen );
00455     } else if ( autoWrap ) {
00456         m_wrapped = true;
00457         found = iSearch( 0, 0, text, reverse, false );
00458     }
00459     // FIXME
00460     bool overwrapped = ( m_wrapped &&
00461         ((m_foundLine > m_startLine ) ||
00462          (m_foundLine == m_startLine && m_foundCol >= m_startCol)) );
00463 //  kdDebug() << "Overwrap = " << overwrapped << ". Start was " << m_startLine << ", " << m_startCol << endl;
00464     updateLabelText( !found, reverse, m_wrapped, overwrapped );
00465     return found;
00466 }
00467 
00468 ISearchPlugin::ISearchPlugin( QObject *parent, const char* name, const QStringList& )
00469     : KTextEditor::Plugin ( (KTextEditor::Document*) parent, name )
00470 {
00471 }
00472 
00473 ISearchPlugin::~ISearchPlugin()
00474 {
00475 }
00476 
00477 void ISearchPlugin::addView(KTextEditor::View *view)
00478 {
00479     ISearchPluginView *nview = new ISearchPluginView (view);
00480     nview->setView (view);
00481     m_views.append (nview);
00482 }
00483 
00484 void ISearchPlugin::removeView(KTextEditor::View *view)
00485 {
00486     for (uint z=0; z < m_views.count(); z++)
00487         {
00488         if (m_views.at(z)->parentClient() == view)
00489         {
00490             ISearchPluginView *nview = m_views.at(z);
00491             m_views.remove (nview);
00492             delete nview;
00493         }
00494     }
00495 }

Kate

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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal