1
/* This file is part of the KDE libraries
2
Copyright (C) 2002, 2003, 2004 Anders Lund <anders.lund@lund.tdcadsl.dk>
3
Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org>
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Library General Public
7
License version 2 as published by the Free Software Foundation.
9
This library is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
Library General Public License for more details.
14
You should have received a copy of the GNU Library General Public License
15
along with this library; see the file COPYING.LIB. If not, write to
16
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
Boston, MA 02110-1301, USA.
20
#include "katebookmarks.h"
21
#include "katebookmarks.moc"
23
#include "katedocument.h"
28
#include <kactioncollection.h>
32
#include <kstringhandler.h>
33
#include <kxmlguiclient.h>
34
#include <kxmlguifactory.h>
35
#include <ktoggleaction.h>
36
#include <kactionmenu.h>
38
#include <QtCore/QRegExp>
39
#include <QtCore/QEvent>
40
#include <QtCore/QVector>
42
namespace KTextEditor{ class Document; }
44
KateBookmarks::KateBookmarks( KateView* view, Sorting sort )
50
setObjectName( "kate bookmarks" );
51
connect (view->doc(), SIGNAL(marksChanged(KTextEditor::Document*)), this, SLOT(marksChanged()));
56
KateBookmarks::~KateBookmarks()
60
void KateBookmarks::createActions( KActionCollection* ac )
62
m_bookmarkToggle = new KToggleAction( i18n("Set &Bookmark"), this );
63
ac->addAction( "bookmarks_toggle", m_bookmarkToggle );
64
m_bookmarkToggle->setIcon( KIcon( "bookmark-new" ) );
65
m_bookmarkToggle->setShortcut( Qt::CTRL+Qt::Key_B );
66
m_bookmarkToggle->setWhatsThis(i18n("If a line has no bookmark then add one, otherwise remove it."));
67
connect( m_bookmarkToggle, SIGNAL(triggered()), this, SLOT(toggleBookmark()) );
69
m_bookmarkClear = new KAction( i18n("Clear &All Bookmarks"), this );
70
ac->addAction("bookmarks_clear", m_bookmarkClear);
71
m_bookmarkClear->setWhatsThis(i18n("Remove all bookmarks of the current document."));
72
connect( m_bookmarkClear, SIGNAL(triggered()), this, SLOT(clearBookmarks()) );
74
m_goNext = new KAction( i18n("Next Bookmark"), this);
75
ac->addAction("bookmarks_next", m_goNext);
76
m_goNext->setIcon( KIcon( "go-down-search" ) );
77
m_goNext->setShortcut( Qt::ALT + Qt::Key_PageDown );
78
m_goNext->setWhatsThis(i18n("Go to the next bookmark."));
79
connect( m_goNext, SIGNAL(triggered()), this, SLOT(goNext()) );
81
m_goPrevious = new KAction( i18n("Previous Bookmark"), this);
82
ac->addAction("bookmarks_previous", m_goPrevious);
83
m_goPrevious->setIcon( KIcon( "go-up-search" ) );
84
m_goPrevious->setShortcut( Qt::ALT + Qt::Key_PageUp );
85
m_goPrevious->setWhatsThis(i18n("Go to the previous bookmark."));
86
connect( m_goPrevious, SIGNAL(triggered()), this, SLOT(goPrevious()) );
88
KActionMenu *actionMenu = new KActionMenu(i18n("&Bookmarks"), this);
89
ac->addAction("bookmarks", actionMenu);
90
m_bookmarksMenu = actionMenu->menu();
92
connect( m_bookmarksMenu, SIGNAL(aboutToShow()), this, SLOT(bookmarkMenuAboutToShow()));
96
// Always want the actions with shortcuts plugged into something so their shortcuts can work
97
m_view->addAction(m_bookmarkToggle);
98
m_view->addAction(m_bookmarkClear);
99
m_view->addAction(m_goNext);
100
m_view->addAction(m_goPrevious);
103
void KateBookmarks::toggleBookmark ()
105
uint mark = m_view->doc()->mark( m_view->cursorPosition().line() );
106
if( mark & KTextEditor::MarkInterface::markType01 )
107
m_view->doc()->removeMark( m_view->cursorPosition().line(),
108
KTextEditor::MarkInterface::markType01 );
110
m_view->doc()->addMark( m_view->cursorPosition().line(),
111
KTextEditor::MarkInterface::markType01 );
114
void KateBookmarks::clearBookmarks ()
116
QHash<int, KTextEditor::Mark*> m = m_view->doc()->marks();
117
for (QHash<int, KTextEditor::Mark*>::const_iterator i = m.constBegin(); i != m.constEnd(); ++i)
118
m_view->doc()->removeMark( i.value()->line, KTextEditor::MarkInterface::markType01 );
120
// just to be sure ;)
121
// dominik: the following line can be deleted afaics, as Document::removeMark emits this signal.
125
void KateBookmarks::insertBookmarks( QMenu& menu )
127
int line = m_view->cursorPosition().line();
128
const QRegExp re("&(?!&)");
129
int next = -1; // -1 means next bookmark doesn't exist
130
int prev = -1; // -1 means previous bookmark doesn't exist
132
const QHash<int, KTextEditor::Mark*> &m = m_view->doc()->marks();
133
QVector<int> bookmarkLineArray; // Array of line numbers which have bookmarks
138
// Find line numbers where bookmarks are set & store those line numbers in bookmarkLineArray
139
for (QHash<int, KTextEditor::Mark*>::const_iterator it = m.constBegin(); it != m.constEnd(); ++it)
141
if( it.value()->type & KTextEditor::MarkInterface::markType01 )
143
bookmarkLineArray.append(it.value()->line);
147
if ( m_sorting == Position )
149
qSort(bookmarkLineArray.begin(), bookmarkLineArray.end());
152
QAction* firstNewAction = menu.addSeparator();
153
// Consider each line with a bookmark one at a time
154
for (int i = 0; i < bookmarkLineArray.size(); ++i)
156
// Get text in this particular line in a QString
157
QString bText = menu.fontMetrics().elidedText
158
( m_view->doc()->line( bookmarkLineArray.at(i) ),
160
menu.fontMetrics().maxWidth() * 32 );
161
bText.replace(re, "&&"); // kill undesired accellerators!
162
bText.replace('\t', ' '); // kill tabs, as they are interpreted as shortcuts
165
if ( m_sorting == Position )
167
// 3 actions already present
168
if (menu.actions().size() <= i+3)
171
before=menu.actions()[i+3];
174
// Adding action for this bookmark in menu
176
QAction *a=new QAction(QString("%1 %3 - \"%2\"")
177
.arg( bookmarkLineArray.at(i) + 1 ).arg( bText )
178
.arg(m_view->getViInputModeManager()->getMarksOnTheLine(bookmarkLineArray.at(i))),&menu);
179
menu.insertAction(before,a);
180
connect(a,SIGNAL(activated()),this,SLOT(gotoLine()));
181
a->setData(bookmarkLineArray.at(i));
182
if (!firstNewAction) firstNewAction = a;
185
QAction* a = menu.addAction(QString("%1 %3 - \"%2\"")
186
.arg( bookmarkLineArray.at(i) + 1 ).arg( bText )
187
.arg(m_view->getViInputModeManager()->getMarksOnTheLine(bookmarkLineArray.at(i))),
188
this, SLOT(gotoLine()));
189
a->setData(bookmarkLineArray.at(i));
192
// Find the line number of previous & next bookmark (if present) in relation to the cursor
193
if ( bookmarkLineArray.at(i) < line )
195
if ( (prev == -1) || prev < (bookmarkLineArray.at(i)) )
196
prev = bookmarkLineArray.at(i);
198
else if ( bookmarkLineArray.at(i) > line )
200
if ( (next == -1) || next > (bookmarkLineArray.at(i)) )
201
next = bookmarkLineArray.at(i);
207
// Insert action for next bookmark
208
m_goNext->setText( i18n("&Next: %1 - \"%2\"", next + 1 ,
209
KStringHandler::rsqueeze( m_view->doc()->line( next ), 24 ) ) );
210
menu.insertAction(firstNewAction, m_goNext);
211
firstNewAction = m_goNext;
215
// Insert action for previous bookmark
216
m_goPrevious->setText( i18n("&Previous: %1 - \"%2\"", prev + 1 ,
217
KStringHandler::rsqueeze( m_view->doc()->line( prev ), 24 ) ) );
218
menu.insertAction(firstNewAction, m_goPrevious);
219
firstNewAction = m_goPrevious;
222
if ( next != -1 || prev != -1 )
223
menu.insertSeparator(firstNewAction);
226
void KateBookmarks::gotoLine()
228
if (!sender()) return;
229
gotoLine(((QAction*)(sender()))->data().toInt());
232
void KateBookmarks::gotoLine (int line)
234
m_view->setCursorPosition(KTextEditor::Cursor(line, 0));
237
void KateBookmarks::bookmarkMenuAboutToShow()
239
m_bookmarksMenu->clear();
240
m_bookmarkToggle->setChecked( m_view->doc()->mark( m_view->cursorPosition().line() )
241
& KTextEditor::MarkInterface::markType01 );
242
m_bookmarksMenu->addAction(m_bookmarkToggle);
243
m_bookmarksMenu->addAction(m_bookmarkClear);
245
m_goNext->setText( i18n("Next Bookmark") );
246
m_goPrevious->setText( i18n("Previous Bookmark") );
248
insertBookmarks(*m_bookmarksMenu);
251
void KateBookmarks::goNext()
253
const QHash<int, KTextEditor::Mark*> &m = m_view->doc()->marks();
257
int line = m_view->cursorPosition().line();
260
for (QHash<int, KTextEditor::Mark*>::const_iterator it = m.constBegin(); it != m.constEnd(); ++it)
262
if ( (it.value()->line > line) && ((found == -1) || (found > it.value()->line)) )
263
found = it.value()->line;
270
void KateBookmarks::goPrevious()
272
const QHash<int, KTextEditor::Mark*> &m = m_view->doc()->marks();
276
int line = m_view->cursorPosition().line();
279
for (QHash<int, KTextEditor::Mark*>::const_iterator it = m.constBegin(); it != m.constEnd(); ++it)
281
if ((it.value()->line < line) && ((found == -1) || (found < it.value()->line)))
282
found = it.value()->line;
289
void KateBookmarks::marksChanged ()
292
m_bookmarkClear->setEnabled( !m_view->doc()->marks().isEmpty() );
295
// kate: space-indent on; indent-width 2; replace-tabs on;