kate Library API Documentation

katebookmarks.cpp

00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2002, 2003, 2004 Anders Lund <anders.lund@lund.tdcadsl.dk>
00003    Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License version 2 as published by the Free Software Foundation.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #include "katebookmarks.h"
00021 #include "katebookmarks.moc"
00022 
00023 #include "katedocument.h"
00024 #include "kateview.h"
00025 
00026 #include <klocale.h>
00027 #include <kaction.h>
00028 #include <kpopupmenu.h>
00029 #include <kstringhandler.h>
00030 #include <kxmlguiclient.h>
00031 #include <kxmlguifactory.h>
00032 #include <kdebug.h>
00033 
00034 #include <qregexp.h>
00035 #include <qmemarray.h>
00036 #include <qevent.h>
00037 
00045 static void ssort( QMemArray<uint> &a, int max )
00046 {
00047   uint tmp, j, maxpos;
00048   for ( uint h = max; h >= 1; h-- )
00049   {
00050     maxpos = 0;
00051     for ( j = 0; j <= h; j++ )
00052       maxpos = a[j] > a[maxpos] ? j : maxpos;
00053     tmp = a[maxpos];
00054     a[maxpos] = a[h];
00055     a[h] = tmp;
00056   }
00057 }
00058 
00059 // TODO add a insort() or bubble_sort - more efficient for aboutToShow() ?
00060 
00061 KateBookmarks::KateBookmarks( KateView* view, Sorting sort )
00062   : QObject( view, "kate bookmarks" )
00063   , m_view( view )
00064   , m_sorting( sort )
00065 {
00066   connect (view->getDoc(), SIGNAL(marksChanged()), this, SLOT(marksChanged()));
00067   m_view->installEventFilter( this );
00068   _tries=0;
00069   m_bookmarksMenu = 0L;
00070 }
00071 
00072 KateBookmarks::~KateBookmarks()
00073 {
00074 }
00075 
00076 void KateBookmarks::createActions( KActionCollection* ac )
00077 {
00078   m_bookmarkToggle = new KAction(
00079     i18n("Toggle &Bookmark"), "bookmark", CTRL+Key_B,
00080     this, SLOT(toggleBookmark()),
00081     ac, "bookmarks_toggle" );
00082   m_bookmarkToggle->setWhatsThis(i18n("If a line has no bookmark then add one, otherwise remove it."));
00083 
00084   m_bookmarkClear = new KAction(
00085     i18n("Clear Bookmarks"), 0,
00086     this, SLOT(clearBookmarks()),
00087     ac, "bookmarks_clear");
00088   m_bookmarkClear->setWhatsThis(i18n("Remove all bookmarks of the current document."));
00089 
00090   m_goNext = new KAction(
00091     i18n("Next Bookmark"), "next", ALT + Key_PageDown,
00092     this, SLOT(goNext()),
00093     ac, "bookmarks_next");
00094   m_goNext->setWhatsThis(i18n("Go to the next bookmark."));
00095 
00096   m_goPrevious = new KAction(
00097     i18n("Previous Bookmark"), "previous", ALT + Key_PageUp,
00098     this, SLOT(goPrevious()),
00099     ac, "bookmarks_previous");
00100   m_goPrevious->setWhatsThis(i18n("Go to the previous bookmark."));
00101 
00102   marksChanged ();
00103 }
00104 
00105 bool KateBookmarks::eventFilter( QObject *o, QEvent *e )
00106 {
00107   if ( o == m_view && e->type() == QEvent::Show )
00108     connectMenuAndDisConnectAgain();
00109   return false;
00110 }
00111 
00112 
00113 void KateBookmarks::connectMenuAndDisConnectAgain()
00114 {
00115   kdDebug()<<"KateBookmarks::connectMenuAndDisConnectAgain()"<<endl;
00116 
00117   if (m_view->factory())
00118     {
00119         QPtrList<KXMLGUIClient> clients = m_view->factory()->clients();
00120         QPtrListIterator<KXMLGUIClient> it(clients);
00121         KXMLGUIClient *client;
00122         while ((client = it.current()) != 0)
00123         {
00124             m_bookmarksMenu = static_cast<QPopupMenu*>(client->factory()->container("bookmarks", client));
00125 
00126             if (m_bookmarksMenu)
00127             {
00128                 // connect bookmarks menu aboutToshow
00129                 disconnect( m_bookmarksMenu, SIGNAL(aboutToShow()),
00130                         0, 0);
00131                 connect( m_bookmarksMenu, SIGNAL(aboutToShow()),
00132                         this, SLOT(bookmarkMenuAboutToShow()));
00133 
00134                 // anders: I ensure the next/prev actions are available
00135                 // and reset their texts (for edit shortcuts dialog, call me picky!).
00136                 // TODO - come up with a better solution, please anyone?
00137                 disconnect( m_bookmarksMenu, SIGNAL(aboutToHide()),
00138                         0, 0);
00139                 connect( m_bookmarksMenu, SIGNAL(aboutToHide()),
00140                         this, SLOT(bookmarkMenuAboutToHide()) );
00141 
00142                 // ### don't remove the event filter, since in kate we will otherwise loose
00143                 // the document menu :(
00144           //      m_view->removeEventFilter( this );
00145                 return;
00146             }
00147             ++it;
00148          }
00149     }
00150 
00151     // FUCKY-SUCKY -- try later
00152     if ( _tries > 3 ) // give up
00153     {
00154       m_view->removeEventFilter( this );
00155       return;
00156     }
00157 
00158     if ( m_view->isVisible() )
00159       QTimer::singleShot( 0, this, SLOT(connectMenuAndDisConnectAgain()));
00160 
00161     _tries++;
00162 }
00163 
00164 void KateBookmarks::toggleBookmark ()
00165 {
00166   uint mark = m_view->getDoc()->mark( m_view->cursorLine() );
00167   if( mark & KTextEditor::MarkInterface::markType01 )
00168     m_view->getDoc()->removeMark( m_view->cursorLine(),
00169         KTextEditor::MarkInterface::markType01 );
00170   else
00171     m_view->getDoc()->addMark( m_view->cursorLine(),
00172         KTextEditor::MarkInterface::markType01 );
00173 }
00174 
00175 void KateBookmarks::clearBookmarks ()
00176 {
00177   QPtrList<KTextEditor::Mark> m = m_view->getDoc()->marks();
00178   for (uint i=0; i < m.count(); i++)
00179     m_view->getDoc()->removeMark( m.at(i)->line, KTextEditor::MarkInterface::markType01 );
00180 
00181   // just to be sure ;)
00182   marksChanged ();
00183 }
00184 
00185 void KateBookmarks::bookmarkMenuAboutToShow()
00186 {
00187   QPtrList<KTextEditor::Mark> m = m_view->getDoc()->marks();
00188 
00189   m_bookmarksMenu->clear();
00190   m_bookmarkToggle->plug( m_bookmarksMenu );
00191   m_bookmarkClear->plug( m_bookmarksMenu );
00192   KTextEditor::Mark *next = 0;
00193   KTextEditor::Mark *prev = 0;
00194   uint line = m_view->cursorLine();
00195 
00196   const QRegExp re("&(?!&)");
00197 
00198   int idx( -1 );
00199   QMemArray<uint> sortArray( m.count() );
00200   QPtrListIterator<KTextEditor::Mark> it( m );
00201 
00202   if ( it.count() > 0 )
00203     m_bookmarksMenu->insertSeparator();
00204 
00205   for( int i = 0; *it; ++it, ++i )
00206   {
00207     if( (*it)->type & KTextEditor::MarkInterface::markType01 )
00208     {
00209       QString bText = KStringHandler::rEmSqueeze
00210                       ( m_view->getDoc()->textLine( (*it)->line ),
00211                         m_bookmarksMenu->fontMetrics(), 32 );
00212       bText.replace(re, "&&"); // kill undesired accellerators!
00213 
00214       if ( m_sorting == Position )
00215       {
00216         sortArray[i] = (*it)->line;
00217         ssort( sortArray, i );
00218         idx = sortArray.find( (*it)->line ) + 3;
00219       }
00220 
00221       m_bookmarksMenu->insertItem(
00222           QString("%1 - \"%2\"").arg( (*it)->line+1 ).arg( bText ),
00223           m_view, SLOT(gotoLineNumber(int)), 0, (*it)->line, idx );
00224 
00225       if ( (*it)->line < line )
00226       {
00227         if ( ! prev || prev->line < (*it)->line )
00228           prev = (*it);
00229       }
00230 
00231       else if ( (*it)->line > line )
00232       {
00233         if ( ! next || next->line > (*it)->line )
00234           next = (*it);
00235       }
00236     }
00237   }
00238 
00239   idx = 3;
00240   if ( next )
00241   {
00242     m_goNext->setText( i18n("&Next: %1 - \"%2\"").arg( next->line + 1 )
00243         .arg( KStringHandler::rsqueeze( m_view->getDoc()->textLine( next->line ), 24 ) ) );
00244     m_goNext->plug( m_bookmarksMenu, idx );
00245     idx++;
00246   }
00247   if ( prev )
00248   {
00249     m_goPrevious->setText( i18n("&Previous: %1 - \"%2\"").arg(prev->line + 1 )
00250         .arg( KStringHandler::rsqueeze( m_view->getDoc()->textLine( prev->line ), 24 ) ) );
00251     m_goPrevious->plug( m_bookmarksMenu, idx );
00252     idx++;
00253   }
00254   if ( next || prev )
00255     m_bookmarksMenu->insertSeparator( idx );
00256 }
00257 
00258 /*
00259    Make sure next/prev actions are plugged, and have a clean text
00260 */
00261 void KateBookmarks::bookmarkMenuAboutToHide()
00262 {
00263   //menu->clear();
00264 
00265   m_bookmarkToggle->plug( m_bookmarksMenu );
00266   m_bookmarkClear->plug( m_bookmarksMenu );
00267   m_goNext->setText( i18n("Next Bookmark") );
00268   m_goNext->plug( m_bookmarksMenu );
00269   m_goPrevious->setText( i18n("Previous Bookmark") );
00270   m_goPrevious->plug( m_bookmarksMenu );
00271 }
00272 
00273 void KateBookmarks::goNext()
00274 {
00275   QPtrList<KTextEditor::Mark> m = m_view->getDoc()->marks();
00276   if (m.isEmpty())
00277     return;
00278 
00279   uint line = m_view->cursorLine();
00280   int found = -1;
00281 
00282   for (uint z=0; z < m.count(); z++)
00283     if ( (m.at(z)->line > line) && ((found == -1) || (uint(found) > m.at(z)->line)) )
00284       found = m.at(z)->line;
00285 
00286   if (found != -1)
00287     m_view->gotoLineNumber ( found );
00288 }
00289 
00290 void KateBookmarks::goPrevious()
00291 {
00292   QPtrList<KTextEditor::Mark> m = m_view->getDoc()->marks();
00293   if (m.isEmpty())
00294     return;
00295 
00296   uint line = m_view->cursorLine();
00297   int found = -1;
00298 
00299   for (uint z=0; z < m.count(); z++)
00300     if ((m.at(z)->line < line) && ((found == -1) || (uint(found) < m.at(z)->line)))
00301       found = m.at(z)->line;
00302 
00303   if (found != -1)
00304     m_view->gotoLineNumber ( found );
00305 }
00306 
00307 void KateBookmarks::marksChanged ()
00308 {
00309   m_bookmarkClear->setEnabled( !m_view->getDoc()->marks().isEmpty() );
00310 }
00311 
00312 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE Logo
This file is part of the documentation for kate Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Aug 4 05:29:47 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2003