00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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
00144
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, "&&");
00173 bText.replace('\t', ' ');
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