kde-workspace/kate/part/utils/katebookmarks.cpp

296 lines
9.8 KiB
C++
Raw Normal View History

/* This file is part of the KDE libraries
Copyright (C) 2002, 2003, 2004 Anders Lund <anders.lund@lund.tdcadsl.dk>
Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "katebookmarks.h"
#include "moc_katebookmarks.cpp"
#include "katedocument.h"
#include "kateview.h"
#include <klocale.h>
#include <kaction.h>
#include <kactioncollection.h>
#include <kguiitem.h>
#include <kicon.h>
#include <kmenu.h>
#include <kstringhandler.h>
#include <kxmlguiclient.h>
#include <kxmlguifactory.h>
#include <ktoggleaction.h>
#include <kactionmenu.h>
#include <QtCore/QRegExp>
#include <QtCore/QEvent>
#include <QtCore/QVector>
namespace KTextEditor{ class Document; }
KateBookmarks::KateBookmarks( KateView* view, Sorting sort )
: QObject( view )
, m_view( view )
, m_bookmarkClear (0)
, m_sorting( sort )
{
setObjectName( "kate bookmarks" );
connect (view->doc(), SIGNAL(marksChanged(KTextEditor::Document*)), this, SLOT(marksChanged()));
_tries=0;
m_bookmarksMenu = 0L;
}
KateBookmarks::~KateBookmarks()
{
}
void KateBookmarks::createActions( KActionCollection* ac )
{
m_bookmarkToggle = new KToggleAction( i18n("Set &Bookmark"), this );
ac->addAction( "bookmarks_toggle", m_bookmarkToggle );
m_bookmarkToggle->setIcon( KIcon( "bookmark-new" ) );
m_bookmarkToggle->setShortcut( Qt::CTRL+Qt::Key_B );
m_bookmarkToggle->setWhatsThis(i18n("If a line has no bookmark then add one, otherwise remove it."));
connect( m_bookmarkToggle, SIGNAL(triggered()), this, SLOT(toggleBookmark()) );
m_bookmarkClear = new KAction( i18n("Clear &All Bookmarks"), this );
ac->addAction("bookmarks_clear", m_bookmarkClear);
m_bookmarkClear->setWhatsThis(i18n("Remove all bookmarks of the current document."));
connect( m_bookmarkClear, SIGNAL(triggered()), this, SLOT(clearBookmarks()) );
m_goNext = new KAction( i18n("Next Bookmark"), this);
ac->addAction("bookmarks_next", m_goNext);
m_goNext->setIcon( KIcon( "go-down-search" ) );
m_goNext->setShortcut( Qt::ALT + Qt::Key_PageDown );
m_goNext->setWhatsThis(i18n("Go to the next bookmark."));
connect( m_goNext, SIGNAL(triggered()), this, SLOT(goNext()) );
m_goPrevious = new KAction( i18n("Previous Bookmark"), this);
ac->addAction("bookmarks_previous", m_goPrevious);
m_goPrevious->setIcon( KIcon( "go-up-search" ) );
m_goPrevious->setShortcut( Qt::ALT + Qt::Key_PageUp );
m_goPrevious->setWhatsThis(i18n("Go to the previous bookmark."));
connect( m_goPrevious, SIGNAL(triggered()), this, SLOT(goPrevious()) );
KActionMenu *actionMenu = new KActionMenu(i18n("&Bookmarks"), this);
ac->addAction("bookmarks", actionMenu);
m_bookmarksMenu = actionMenu->menu();
connect( m_bookmarksMenu, SIGNAL(aboutToShow()), this, SLOT(bookmarkMenuAboutToShow()));
marksChanged ();
// Always want the actions with shortcuts plugged into something so their shortcuts can work
m_view->addAction(m_bookmarkToggle);
m_view->addAction(m_bookmarkClear);
m_view->addAction(m_goNext);
m_view->addAction(m_goPrevious);
}
void KateBookmarks::toggleBookmark ()
{
uint mark = m_view->doc()->mark( m_view->cursorPosition().line() );
if( mark & KTextEditor::MarkInterface::markType01 )
m_view->doc()->removeMark( m_view->cursorPosition().line(),
KTextEditor::MarkInterface::markType01 );
else
m_view->doc()->addMark( m_view->cursorPosition().line(),
KTextEditor::MarkInterface::markType01 );
}
void KateBookmarks::clearBookmarks ()
{
QHash<int, KTextEditor::Mark*> m = m_view->doc()->marks();
for (QHash<int, KTextEditor::Mark*>::const_iterator i = m.constBegin(); i != m.constEnd(); ++i)
m_view->doc()->removeMark( i.value()->line, KTextEditor::MarkInterface::markType01 );
// just to be sure ;)
// dominik: the following line can be deleted afaics, as Document::removeMark emits this signal.
marksChanged ();
}
void KateBookmarks::insertBookmarks( QMenu& menu )
{
int line = m_view->cursorPosition().line();
const QRegExp re("&(?!&)");
int next = -1; // -1 means next bookmark doesn't exist
int prev = -1; // -1 means previous bookmark doesn't exist
const QHash<int, KTextEditor::Mark*> &m = m_view->doc()->marks();
QVector<int> bookmarkLineArray; // Array of line numbers which have bookmarks
if ( m.isEmpty() )
return;
// Find line numbers where bookmarks are set & store those line numbers in bookmarkLineArray
for (QHash<int, KTextEditor::Mark*>::const_iterator it = m.constBegin(); it != m.constEnd(); ++it)
{
if( it.value()->type & KTextEditor::MarkInterface::markType01 )
{
bookmarkLineArray.append(it.value()->line);
}
}
if ( m_sorting == Position )
{
qSort(bookmarkLineArray.begin(), bookmarkLineArray.end());
}
QAction* firstNewAction = menu.addSeparator();
// Consider each line with a bookmark one at a time
for (int i = 0; i < bookmarkLineArray.size(); ++i)
{
// Get text in this particular line in a QString
QString bText = menu.fontMetrics().elidedText
( m_view->doc()->line( bookmarkLineArray.at(i) ),
Qt::ElideRight,
menu.fontMetrics().maxWidth() * 32 );
bText.replace(re, "&&"); // kill undesired accellerators!
bText.replace('\t', ' '); // kill tabs, as they are interpreted as shortcuts
QAction *before=0;
if ( m_sorting == Position )
{
// 3 actions already present
if (menu.actions().size() <= i+3)
before=0;
else
before=menu.actions()[i+3];
}
// Adding action for this bookmark in menu
if (before) {
QAction *a=new QAction(QString("%1 %3 - \"%2\"")
.arg( bookmarkLineArray.at(i) + 1 ).arg( bText )
.arg(false),&menu);
menu.insertAction(before,a);
connect(a,SIGNAL(activated()),this,SLOT(gotoLine()));
a->setData(bookmarkLineArray.at(i));
if (!firstNewAction) firstNewAction = a;
} else {
QAction* a = menu.addAction(QString("%1 %3 - \"%2\"")
.arg( bookmarkLineArray.at(i) + 1 ).arg( bText )
.arg(false),
this, SLOT(gotoLine()));
a->setData(bookmarkLineArray.at(i));
}
// Find the line number of previous & next bookmark (if present) in relation to the cursor
if ( bookmarkLineArray.at(i) < line )
{
if ( (prev == -1) || prev < (bookmarkLineArray.at(i)) )
prev = bookmarkLineArray.at(i);
}
else if ( bookmarkLineArray.at(i) > line )
{
if ( (next == -1) || next > (bookmarkLineArray.at(i)) )
next = bookmarkLineArray.at(i);
}
}
if ( next != -1 )
{
// Insert action for next bookmark
m_goNext->setText( i18n("&Next: %1 - \"%2\"", next + 1 ,
KStringHandler::rsqueeze( m_view->doc()->line( next ), 24 ) ) );
menu.insertAction(firstNewAction, m_goNext);
firstNewAction = m_goNext;
}
if ( prev != -1 )
{
// Insert action for previous bookmark
m_goPrevious->setText( i18n("&Previous: %1 - \"%2\"", prev + 1 ,
KStringHandler::rsqueeze( m_view->doc()->line( prev ), 24 ) ) );
menu.insertAction(firstNewAction, m_goPrevious);
firstNewAction = m_goPrevious;
}
if ( next != -1 || prev != -1 )
menu.insertSeparator(firstNewAction);
}
void KateBookmarks::gotoLine()
{
if (!sender()) return;
gotoLine(((QAction*)(sender()))->data().toInt());
}
void KateBookmarks::gotoLine (int line)
{
m_view->setCursorPosition(KTextEditor::Cursor(line, 0));
}
void KateBookmarks::bookmarkMenuAboutToShow()
{
m_bookmarksMenu->clear();
m_bookmarkToggle->setChecked( m_view->doc()->mark( m_view->cursorPosition().line() )
& KTextEditor::MarkInterface::markType01 );
m_bookmarksMenu->addAction(m_bookmarkToggle);
m_bookmarksMenu->addAction(m_bookmarkClear);
m_goNext->setText( i18n("Next Bookmark") );
m_goPrevious->setText( i18n("Previous Bookmark") );
insertBookmarks(*m_bookmarksMenu);
}
void KateBookmarks::goNext()
{
const QHash<int, KTextEditor::Mark*> &m = m_view->doc()->marks();
if (m.isEmpty())
return;
int line = m_view->cursorPosition().line();
int found = -1;
for (QHash<int, KTextEditor::Mark*>::const_iterator it = m.constBegin(); it != m.constEnd(); ++it)
{
if ( (it.value()->line > line) && ((found == -1) || (found > it.value()->line)) )
found = it.value()->line;
}
if (found != -1)
gotoLine ( found );
}
void KateBookmarks::goPrevious()
{
const QHash<int, KTextEditor::Mark*> &m = m_view->doc()->marks();
if (m.isEmpty())
return;
int line = m_view->cursorPosition().line();
int found = -1;
for (QHash<int, KTextEditor::Mark*>::const_iterator it = m.constBegin(); it != m.constEnd(); ++it)
{
if ((it.value()->line < line) && ((found == -1) || (found < it.value()->line)))
found = it.value()->line;
}
if (found != -1)
gotoLine ( found );
}
void KateBookmarks::marksChanged ()
{
if (m_bookmarkClear)
m_bookmarkClear->setEnabled( !m_view->doc()->marks().isEmpty() );
}
// kate: space-indent on; indent-width 2; replace-tabs on;