Kate
katebookmarks.cpp
Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, 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 <kactioncollection.h> 00029 #include <kguiitem.h> 00030 #include <kicon.h> 00031 #include <kmenu.h> 00032 #include <kstringhandler.h> 00033 #include <kxmlguiclient.h> 00034 #include <kxmlguifactory.h> 00035 #include <ktoggleaction.h> 00036 #include <kactionmenu.h> 00037 00038 #include <QtCore/QRegExp> 00039 #include <QtCore/QEvent> 00040 #include <QtCore/QVector> 00041 00042 namespace KTextEditor{ class Document; } 00043 00051 static void ssort( QVector<uint> &a, int max ) 00052 { 00053 uint tmp, j, maxpos; 00054 for ( uint h = max; h >= 1; h-- ) 00055 { 00056 maxpos = 0; 00057 for ( j = 0; j <= h; j++ ) 00058 maxpos = a[j] > a[maxpos] ? j : maxpos; 00059 tmp = a[maxpos]; 00060 a[maxpos] = a[h]; 00061 a[h] = tmp; 00062 } 00063 } 00064 00065 // TODO add a insort() or bubble_sort - more efficient for aboutToShow() ? 00066 00067 KateBookmarks::KateBookmarks( KateView* view, Sorting sort ) 00068 : QObject( view ) 00069 , m_view( view ) 00070 , m_bookmarkClear (0) 00071 , m_sorting( sort ) 00072 { 00073 setObjectName( "kate bookmarks" ); 00074 connect (view->doc(), SIGNAL( marksChanged( KTextEditor::Document* ) ), this, SLOT( marksChanged() )); 00075 _tries=0; 00076 m_bookmarksMenu = 0L; 00077 } 00078 00079 KateBookmarks::~KateBookmarks() 00080 { 00081 } 00082 00083 void KateBookmarks::createActions( KActionCollection* ac ) 00084 { 00085 m_bookmarkToggle = new KToggleAction( i18n("Set &Bookmark"), this ); 00086 ac->addAction( "bookmarks_toggle", m_bookmarkToggle ); 00087 m_bookmarkToggle->setIcon( KIcon( "bookmark-new" ) ); 00088 m_bookmarkToggle->setShortcut( Qt::CTRL+Qt::Key_B ); 00089 m_bookmarkToggle->setWhatsThis(i18n("If a line has no bookmark then add one, otherwise remove it.")); 00090 connect( m_bookmarkToggle, SIGNAL( triggered() ), this, SLOT(toggleBookmark()) ); 00091 00092 m_bookmarkClear = new KAction( i18n("Clear &All Bookmarks"), this ); 00093 ac->addAction("bookmarks_clear", m_bookmarkClear); 00094 m_bookmarkClear->setWhatsThis(i18n("Remove all bookmarks of the current document.")); 00095 connect( m_bookmarkClear, SIGNAL( triggered() ), this, SLOT(clearBookmarks()) ); 00096 00097 m_goNext = new KAction( i18n("Next Bookmark"), this); 00098 ac->addAction("bookmarks_next", m_goNext); 00099 m_goNext->setIcon( KIcon( "go-down-search" ) ); 00100 m_goNext->setShortcut( Qt::ALT + Qt::Key_PageDown ); 00101 m_goNext->setWhatsThis(i18n("Go to the next bookmark.")); 00102 connect( m_goNext, SIGNAL( triggered() ), this, SLOT(goNext()) ); 00103 00104 m_goPrevious = new KAction( i18n("Previous Bookmark"), this); 00105 ac->addAction("bookmarks_previous", m_goPrevious); 00106 m_goPrevious->setIcon( KIcon( "go-up-search" ) ); 00107 m_goPrevious->setShortcut( Qt::ALT + Qt::Key_PageUp ); 00108 m_goPrevious->setWhatsThis(i18n("Go to the previous bookmark.")); 00109 connect( m_goPrevious, SIGNAL( triggered() ), this, SLOT(goPrevious()) ); 00110 00111 KActionMenu *actionMenu = new KActionMenu(i18n("&Bookmarks"), this); 00112 ac->addAction("bookmarks", actionMenu); 00113 m_bookmarksMenu = actionMenu->menu(); 00114 00115 connect( m_bookmarksMenu, SIGNAL(aboutToShow()), this, SLOT(bookmarkMenuAboutToShow())); 00116 00117 marksChanged (); 00118 00119 // Always want the actions with shortcuts plugged into something so their shortcuts can work 00120 m_view->addAction(m_bookmarkToggle); 00121 m_view->addAction(m_bookmarkClear); 00122 m_view->addAction(m_goNext); 00123 m_view->addAction(m_goPrevious); 00124 } 00125 00126 void KateBookmarks::toggleBookmark () 00127 { 00128 uint mark = m_view->doc()->mark( m_view->cursorPosition().line() ); 00129 if( mark & KTextEditor::MarkInterface::markType01 ) 00130 m_view->doc()->removeMark( m_view->cursorPosition().line(), 00131 KTextEditor::MarkInterface::markType01 ); 00132 else 00133 m_view->doc()->addMark( m_view->cursorPosition().line(), 00134 KTextEditor::MarkInterface::markType01 ); 00135 } 00136 00137 void KateBookmarks::clearBookmarks () 00138 { 00139 QHash<int, KTextEditor::Mark*> m = m_view->doc()->marks(); 00140 for (QHash<int, KTextEditor::Mark*>::const_iterator i = m.constBegin(); i != m.constEnd(); ++i) 00141 m_view->doc()->removeMark( i.value()->line, KTextEditor::MarkInterface::markType01 ); 00142 00143 // just to be sure ;) 00144 // dominik: the following line can be deleted afaics, as Document::removeMark emits this signal. 00145 marksChanged (); 00146 } 00147 00148 void KateBookmarks::insertBookmarks( QMenu& menu ) 00149 { 00150 int line = m_view->cursorPosition().line(); 00151 const QRegExp re("&(?!&)"); 00152 int idx( -1 ); 00153 KTextEditor::Mark *next = 0; 00154 KTextEditor::Mark *prev = 0; 00155 00156 const QHash<int, KTextEditor::Mark*> &m = m_view->doc()->marks(); 00157 QVector<uint> sortArray( m.size() ); 00158 00159 if ( m.isEmpty() ) 00160 return; 00161 00162 int i = 0; 00163 QAction* firstNewAction = menu.addSeparator(); 00164 for (QHash<int, KTextEditor::Mark*>::const_iterator it = m.constBegin(); it != m.constEnd(); ++it, ++i) 00165 { 00166 if( it.value()->type & KTextEditor::MarkInterface::markType01 ) 00167 { 00168 QString bText = menu.fontMetrics().elidedText 00169 ( m_view->doc()->line( it.value()->line ), 00170 Qt::ElideRight, 00171 menu.fontMetrics().maxWidth() * 32 ); 00172 bText.replace(re, "&&"); // kill undesired accellerators! 00173 bText.replace('\t', ' '); // kill tabs, as they are interpreted as shortcuts 00174 00175 QAction *before=0; 00176 if ( m_sorting == Position ) 00177 { 00178 sortArray[i] = it.value()->line; 00179 ssort( sortArray, i ); 00180 00181 for (int i=0; i < sortArray.size(); ++i) 00182 { 00183 if ((int)sortArray[i] == it.value()->line) 00184 { 00185 idx = i + 3; 00186 if (idx>=menu.actions().size()) before=0; 00187 else before=menu.actions()[idx]; 00188 break; 00189 } 00190 } 00191 } 00192 00193 if (before) { 00194 QAction *a=new QAction(QString("%1 - \"%2\"").arg( it.value()->line+1 ).arg( bText ),&menu); 00195 menu.insertAction(before,a); 00196 connect(a,SIGNAL(activated()),this,SLOT(gotoLine())); 00197 a->setData(it.value()->line); 00198 if (!firstNewAction) firstNewAction = a; 00199 00200 } else { 00201 QAction* a = menu.addAction(QString("%1 - \"%2\"").arg( it.value()->line+1 ).arg( bText ), this, SLOT(gotoLine())); 00202 a->setData(it.value()->line); 00203 } 00204 00205 if ( it.value()->line < line ) 00206 { 00207 if ( ! prev || prev->line < it.value()->line ) 00208 prev = (*it); 00209 } 00210 00211 else if ( it.value()->line > line ) 00212 { 00213 if ( ! next || next->line > it.value()->line ) 00214 next = it.value(); 00215 } 00216 } 00217 } 00218 00219 if ( next ) 00220 { 00221 m_goNext->setText( i18n("&Next: %1 - \"%2\"", next->line + 1 , 00222 KStringHandler::rsqueeze( m_view->doc()->line( next->line ), 24 ) ) ); 00223 menu.insertAction(firstNewAction, m_goNext); 00224 firstNewAction = m_goNext; 00225 } 00226 if ( prev ) 00227 { 00228 m_goPrevious->setText( i18n("&Previous: %1 - \"%2\"", prev->line + 1 , 00229 KStringHandler::rsqueeze( m_view->doc()->line( prev->line ), 24 ) ) ); 00230 menu.insertAction(firstNewAction, m_goPrevious); 00231 firstNewAction = m_goPrevious; 00232 } 00233 00234 if ( next || prev ) 00235 menu.insertSeparator(firstNewAction); 00236 } 00237 00238 void KateBookmarks::gotoLine() 00239 { 00240 if (!sender()) return; 00241 gotoLine(((QAction*)(sender()))->data().toInt()); 00242 } 00243 00244 void KateBookmarks::gotoLine (int line) 00245 { 00246 m_view->setCursorPosition(KTextEditor::Cursor(line, 0)); 00247 } 00248 00249 void KateBookmarks::bookmarkMenuAboutToShow() 00250 { 00251 m_bookmarksMenu->clear(); 00252 m_bookmarkToggle->setChecked( m_view->doc()->mark( m_view->cursorPosition().line() ) 00253 & KTextEditor::MarkInterface::markType01 ); 00254 m_bookmarksMenu->addAction(m_bookmarkToggle); 00255 m_bookmarksMenu->addAction(m_bookmarkClear); 00256 00257 m_goNext->setText( i18n("Next Bookmark") ); 00258 m_goPrevious->setText( i18n("Previous Bookmark") ); 00259 00260 insertBookmarks(*m_bookmarksMenu); 00261 } 00262 00263 void KateBookmarks::goNext() 00264 { 00265 const QHash<int, KTextEditor::Mark*> &m = m_view->doc()->marks(); 00266 if (m.isEmpty()) 00267 return; 00268 00269 int line = m_view->cursorPosition().line(); 00270 int found = -1; 00271 00272 for (QHash<int, KTextEditor::Mark*>::const_iterator it = m.constBegin(); it != m.constEnd(); ++it) 00273 { 00274 if ( (it.value()->line > line) && ((found == -1) || (found > it.value()->line)) ) 00275 found = it.value()->line; 00276 } 00277 00278 if (found != -1) 00279 gotoLine ( found ); 00280 } 00281 00282 void KateBookmarks::goPrevious() 00283 { 00284 const QHash<int, KTextEditor::Mark*> &m = m_view->doc()->marks(); 00285 if (m.isEmpty()) 00286 return; 00287 00288 int line = m_view->cursorPosition().line(); 00289 int found = -1; 00290 00291 for (QHash<int, KTextEditor::Mark*>::const_iterator it = m.constBegin(); it != m.constEnd(); ++it) 00292 { 00293 if ((it.value()->line < line) && ((found == -1) || (found < it.value()->line))) 00294 found = it.value()->line; 00295 } 00296 00297 if (found != -1) 00298 gotoLine ( found ); 00299 } 00300 00301 void KateBookmarks::marksChanged () 00302 { 00303 if (m_bookmarkClear) 00304 m_bookmarkClear->setEnabled( !m_view->doc()->marks().isEmpty() ); 00305 } 00306 00307 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE 4.6 API Reference