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

Kate

katetemplatehandler.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002   Copyright (C) 2004 Joseph Wenninger <jowenn@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 #include "katetemplatehandler.h"
00019 #include "katetemplatehandler.moc"
00020 #include "katedocument.h"
00021 #include "katesupercursor.h"
00022 #include "katearbitraryhighlight.h"
00023 #include "kateview.h"
00024 #include <qregexp.h>
00025 #include <kdebug.h>
00026 #include <qvaluelist.h>
00027 
00028 KateTemplateHandler::KateTemplateHandler(
00029   KateDocument *doc,
00030   uint line, uint column,
00031   const QString &templateString,
00032   const QMap<QString, QString> &initialValues )
00033     : QObject( doc )
00034     , KateKeyInterceptorFunctor()
00035     , m_doc( doc )
00036     , m_currentTabStop( -1 )
00037     , m_currentRange( 0 )
00038     , m_initOk( false )
00039     , m_recursion( false )
00040 {
00041   connect( m_doc, SIGNAL( destroyed() ), this, SLOT( slotDocumentDestroyed() ) );
00042   m_ranges = new KateSuperRangeList( false, this ); //false/*,this*/);
00043 
00044   if ( !m_doc->setTabInterceptor( this ) )
00045   {
00046     deleteLater();
00047     return ;
00048   }
00049 
00050   KateArbitraryHighlight *kah = doc->arbitraryHL();
00051   /*KateArbitraryHighlightRange *hlr=new KateArbitraryHighlightRange(doc,KateTextCursor(line,column),
00052    KateTextCursor(line,column+3));
00053   hlr->setUnderline(true);
00054   hlr->setOverline(true);
00055   l->append(hlr);*/
00056   QValueList<KateTemplateHandlerPlaceHolderInfo> buildList;
00057   QRegExp rx( "([$%])\\{([^}\\s]+)\\}" );
00058   rx.setMinimal( true );
00059   int pos = 0;
00060   int opos = 0;
00061   QString insertString = templateString;
00062 
00063   while ( pos >= 0 )
00064   {
00065     pos = rx.search( insertString, pos );
00066 
00067     if ( pos > -1 )
00068     {
00069       if ( ( pos - opos ) > 0 )
00070       {
00071         if ( insertString[ pos - 1 ] == '\\' )
00072         {
00073           insertString.remove( pos - 1, 1 );
00074           opos = pos;
00075           continue;
00076         }
00077       }
00078 
00079       QString placeholder = rx.cap( 2 );
00080       QString value = initialValues[ placeholder ];
00081 
00082       // don't add %{MACRO} to the tab navigation, unless there was not value
00083       if ( rx.cap( 1 ) != "%" || placeholder == value )
00084         buildList.append( KateTemplateHandlerPlaceHolderInfo( pos, value.length(), placeholder ) );
00085 
00086       insertString.replace( pos, rx.matchedLength(), value );
00087       pos += value.length();
00088       opos = pos;
00089     }
00090   }
00091 
00092   doc->editStart();
00093 
00094   if ( !doc->insertText( line, column, insertString ) )
00095   {
00096     deleteLater();
00097     doc->editEnd();
00098     return ;
00099   }
00100 
00101   if ( buildList.isEmpty() )
00102   {
00103     m_initOk = true;
00104     deleteLater();
00105     doc->editEnd();
00106     return ;
00107   }
00108 
00109   doc->undoSafePoint();
00110   doc->editEnd();
00111   generateRangeTable( line, column, insertString, buildList );
00112   kah->addHighlightToDocument( m_ranges );
00113 
00114   for ( KateSuperRangeList::const_iterator it = m_ranges->begin();it != m_ranges->end();++it )
00115   {
00116     m_doc->tagLines( ( *it ) ->start().line(), ( *it ) ->end().line() );
00117   }
00118 
00119   /* connect(doc,SIGNAL(charactersInteractivelyInserted(int ,int ,const QString&)),this,
00120    SLOT(slotCharactersInteractivlyInserted(int,int,const QString&)));
00121    connect(doc,SIGNAL(charactersSemiInteractivelyInserted(int ,int ,const QString&)),this,
00122    SLOT(slotCharactersInteractivlyInserted(int,int,const QString&)));*/
00123   connect( doc, SIGNAL( textInserted( int, int ) ), this, SLOT( slotTextInserted( int, int ) ) );
00124   connect( doc, SIGNAL( aboutToRemoveText( const KateTextRange& ) ), this, SLOT( slotAboutToRemoveText( const KateTextRange& ) ) );
00125   connect( doc, SIGNAL( textRemoved() ), this, SLOT( slotTextRemoved() ) );
00126 
00127   ( *this ) ( Qt::Key_Tab );
00128 }
00129 
00130 KateTemplateHandler::~KateTemplateHandler()
00131 {
00132   m_ranges->setAutoManage( true );
00133 
00134   if ( m_doc )
00135   {
00136     m_doc->removeTabInterceptor( this );
00137 
00138     for ( KateSuperRangeList::const_iterator it = m_ranges->begin();it != m_ranges->end();++it )
00139     {
00140       m_doc->tagLines( ( *it ) ->start().line(), ( *it ) ->end().line() );
00141     }
00142   }
00143 
00144   m_ranges->clear();
00145 }
00146 
00147 void KateTemplateHandler::slotDocumentDestroyed() {m_doc = 0;}
00148 
00149 void KateTemplateHandler::generateRangeTable( uint insertLine, uint insertCol, const QString& insertString, const QValueList<KateTemplateHandlerPlaceHolderInfo> &buildList )
00150 {
00151   uint line = insertLine;
00152   uint col = insertCol;
00153   uint colInText = 0;
00154 
00155   for ( QValueList<KateTemplateHandlerPlaceHolderInfo>::const_iterator it = buildList.begin();it != buildList.end();++it )
00156   {
00157     KateTemplatePlaceHolder *ph = m_dict[ ( *it ).placeholder ];
00158 
00159     if ( !ph )
00160     {
00161       ph = new KateTemplatePlaceHolder;
00162       ph->isInitialValue = true;
00163       ph->isCursor = ( ( *it ).placeholder == "cursor" );
00164       m_dict.insert( ( *it ).placeholder, ph );
00165 
00166       if ( !ph->isCursor ) m_tabOrder.append( ph );
00167 
00168       ph->ranges.setAutoManage( false );
00169     }
00170 
00171     // FIXME handle space/tab replacement correctly make it use of the indenter
00172     while ( colInText < ( *it ).begin )
00173     {
00174       ++col;
00175 
00176       if ( insertString.at( colInText ) == '\n' )
00177       {
00178         col = 0;
00179         line++;
00180       }
00181 
00182       ++colInText;
00183     }
00184 
00185     KateArbitraryHighlightRange *hlr = new KateArbitraryHighlightRange( m_doc, KateTextCursor( line, col ),
00186                                        KateTextCursor( line, ( *it ).len + col ) );
00187     colInText += ( *it ).len;
00188     col += ( *it ).len;
00189     hlr->allowZeroLength();
00190     hlr->setUnderline( true );
00191     hlr->setOverline( true );
00192     //hlr->setBehaviour(KateSuperRange::ExpandRight);
00193     ph->ranges.append( hlr );
00194     m_ranges->append( hlr );
00195   }
00196 
00197   KateTemplatePlaceHolder *cursor = m_dict[ "cursor" ];
00198 
00199   if ( cursor ) m_tabOrder.append( cursor );
00200 }
00201 
00202 void KateTemplateHandler::slotTextInserted( int line, int col )
00203 {
00204 #ifdef __GNUC__
00205 #warning FIXME undo/redo detection
00206 #endif
00207 
00208   if ( m_recursion ) return ;
00209 
00210   //if (m_editSessionNumber!=0) return; // assume that this is due an udno/redo operation right now
00211   KateTextCursor cur( line, col );
00212 
00213   if ( ( !m_currentRange ) ||
00214        ( ( !m_currentRange->includes( cur ) ) && ( ! ( ( m_currentRange->start() == m_currentRange->end() ) && m_currentRange->end() == cur ) )
00215        ) ) locateRange( cur );
00216 
00217   if ( !m_currentRange ) return ;
00218 
00219   KateTemplatePlaceHolder *ph = m_tabOrder.at( m_currentTabStop );
00220 
00221   QString sourceText = m_doc->text ( m_currentRange->start().line(), m_currentRange->start().col(),
00222                                      m_currentRange->end().line(), m_currentRange->end().col(), false );
00223 
00224   ph->isInitialValue = false;
00225   bool undoDontMerge = m_doc->m_undoDontMerge;
00226   Q_ASSERT( m_doc->editSessionNumber == 0 );
00227   m_recursion = true;
00228 
00229   m_doc->editStart( /*false*/ );
00230 
00231   for ( KateSuperRangeList::const_iterator it = ph->ranges.begin();it != ph->ranges.end();++it )
00232   {
00233     if ( ( *it ) == m_currentRange ) continue;
00234 
00235     KateTextCursor start = ( *it ) ->start();
00236     KateTextCursor end = ( *it ) ->end();
00237     m_doc->removeText( start.line(), start.col(), end.line(), end.col(), false );
00238     m_doc->insertText( start.line(), start.col(), sourceText );
00239   }
00240 
00241   m_doc->m_undoDontMerge = false;
00242   m_doc->m_undoComplexMerge = true;
00243   m_doc->undoSafePoint();
00244   m_doc->editEnd();
00245   m_doc->m_undoDontMerge = undoDontMerge;
00246   m_recursion = false;
00247 
00248   if ( ph->isCursor ) deleteLater();
00249 }
00250 
00251 void KateTemplateHandler::locateRange( const KateTextCursor& cursor )
00252 {
00253   /* if (m_currentRange) {
00254     m_doc->tagLines(m_currentRange->start().line(),m_currentRange->end().line());
00255 
00256    }*/
00257 
00258   for ( uint i = 0;i < m_tabOrder.count();i++ )
00259   {
00260     KateTemplatePlaceHolder *ph = m_tabOrder.at( i );
00261 
00262     for ( KateSuperRangeList::const_iterator it = ph->ranges.begin();it != ph->ranges.end();++it )
00263     {
00264       if ( ( *it ) ->includes( cursor ) )
00265       {
00266         m_currentTabStop = i;
00267         m_currentRange = ( *it );
00268         //m_doc->tagLines(m_currentRange->start().line(),m_currentRange->end().line());
00269         return ;
00270       }
00271     }
00272 
00273   }
00274 
00275   m_currentRange = 0;
00276   /*while (m_ranges->count()>0)
00277    delete (m_ranges->take(0));
00278   disconnect(m_ranges,0,0,0);
00279   delete m_ranges;*/
00280   deleteLater();
00281 }
00282 
00283 
00284 bool KateTemplateHandler::operator() ( KKey key )
00285 {
00286   if ( key==Qt::Key_Tab )
00287   {
00288     m_currentTabStop++;
00289 
00290     if ( m_currentTabStop >= ( int ) m_tabOrder.count() )
00291       m_currentTabStop = 0;
00292   }
00293   else
00294   {
00295     m_currentTabStop--;
00296 
00297     if ( m_currentTabStop < 0 ) m_currentTabStop = m_tabOrder.count() - 1;
00298   }
00299 
00300   m_currentRange = m_tabOrder.at( m_currentTabStop ) ->ranges.at( 0 );
00301 
00302   if ( m_tabOrder.at( m_currentTabStop ) ->isInitialValue )
00303   {
00304     m_doc->activeView()->setSelection( m_currentRange->start(), m_currentRange->end() );
00305   }
00306   else m_doc->activeView()->setSelection( m_currentRange->end(), m_currentRange->end() );
00307 
00308   m_doc->activeView() ->setCursorPositionReal( m_currentRange->end().line(), m_currentRange->end().col() );
00309   m_doc->activeView() ->tagLine( m_currentRange->end() );
00310 
00311   return true;
00312 }
00313 
00314 void KateTemplateHandler::slotAboutToRemoveText( const KateTextRange &range )
00315 {
00316   if ( m_recursion ) return ;
00317 
00318   if ( m_currentRange && ( !m_currentRange->includes( range.start() ) ) ) locateRange( range.start() );
00319 
00320   if ( m_currentRange != 0 )
00321   {
00322     if ( m_currentRange->end() <= range.end() ) return ;
00323   }
00324 
00325   if ( m_doc )
00326   {
00327     disconnect( m_doc, SIGNAL( textInserted( int, int ) ), this, SLOT( slotTextInserted( int, int ) ) );
00328     disconnect( m_doc, SIGNAL( aboutToRemoveText( const KateTextRange& ) ), this, SLOT( slotAboutToRemoveText( const KateTextRange& ) ) );
00329     disconnect( m_doc, SIGNAL( textRemoved() ), this, SLOT( slotTextRemoved() ) );
00330   }
00331 
00332   deleteLater();
00333 }
00334 
00335 void KateTemplateHandler::slotTextRemoved()
00336 {
00337   if ( m_recursion ) return ;
00338   if ( !m_currentRange ) return ;
00339 
00340   slotTextInserted( m_currentRange->start().line(), m_currentRange->start().col() );
00341 }
00342 

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