From 114a878c64ce6f8223cfd22d76a20eb16d177e5e Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdevelop@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- parts/bookmarks/Makefile.am | 14 + parts/bookmarks/README | 1 + parts/bookmarks/README.dox | 20 + parts/bookmarks/bookmarks_config.cpp | 138 +++++++ parts/bookmarks/bookmarks_config.h | 53 +++ parts/bookmarks/bookmarks_part.cpp | 568 +++++++++++++++++++++++++++++ parts/bookmarks/bookmarks_part.h | 109 ++++++ parts/bookmarks/bookmarks_settings.cpp | 66 ++++ parts/bookmarks/bookmarks_settings.h | 41 +++ parts/bookmarks/bookmarks_settings_base.ui | 240 ++++++++++++ parts/bookmarks/bookmarks_widget.cpp | 336 +++++++++++++++++ parts/bookmarks/bookmarks_widget.h | 72 ++++ parts/bookmarks/kdevbookmarks.desktop | 85 +++++ 13 files changed, 1743 insertions(+) create mode 100644 parts/bookmarks/Makefile.am create mode 100644 parts/bookmarks/README create mode 100644 parts/bookmarks/README.dox create mode 100644 parts/bookmarks/bookmarks_config.cpp create mode 100644 parts/bookmarks/bookmarks_config.h create mode 100644 parts/bookmarks/bookmarks_part.cpp create mode 100644 parts/bookmarks/bookmarks_part.h create mode 100644 parts/bookmarks/bookmarks_settings.cpp create mode 100644 parts/bookmarks/bookmarks_settings.h create mode 100644 parts/bookmarks/bookmarks_settings_base.ui create mode 100644 parts/bookmarks/bookmarks_widget.cpp create mode 100644 parts/bookmarks/bookmarks_widget.h create mode 100644 parts/bookmarks/kdevbookmarks.desktop (limited to 'parts/bookmarks') diff --git a/parts/bookmarks/Makefile.am b/parts/bookmarks/Makefile.am new file mode 100644 index 00000000..87589dfe --- /dev/null +++ b/parts/bookmarks/Makefile.am @@ -0,0 +1,14 @@ +INCLUDES = -I$(top_srcdir)/lib/interfaces -I$(top_srcdir)/lib/util $(all_includes) + +kde_module_LTLIBRARIES = libkdevbookmarks.la +libkdevbookmarks_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) +libkdevbookmarks_la_LIBADD = $(top_builddir)/lib/libkdevelop.la + +libkdevbookmarks_la_SOURCES = bookmarks_part.cpp bookmarks_widget.cpp bookmarks_settings_base.ui bookmarks_settings.cpp bookmarks_config.cpp + +METASOURCES = AUTO + +servicedir = $(kde_servicesdir) +service_DATA = kdevbookmarks.desktop + +noinst_HEADERS = bookmarks_settings.h bookmarks_config.h diff --git a/parts/bookmarks/README b/parts/bookmarks/README new file mode 100644 index 00000000..335789a8 --- /dev/null +++ b/parts/bookmarks/README @@ -0,0 +1 @@ +Please read the README.dox file diff --git a/parts/bookmarks/README.dox b/parts/bookmarks/README.dox new file mode 100644 index 00000000..10d86bd3 --- /dev/null +++ b/parts/bookmarks/README.dox @@ -0,0 +1,20 @@ +/** \class BookmarksPart +This plugin provides a navigation view for bookmarks and persistance to editor bookmarks +so that it is possible to have bookmarks in files that are not open and that these +bookmarks are saved with the project. + +\feature Provides a navigation view for bookmarks + +\feature Persists bookmarks between sessions + +\authors Jens Dagerbo aka teatime + +\maintainer Jens Dagerbo aka teatime + +\bug Pre KDE-3.2 / KDE-3.1.3, using source reformatting, or +the ReplacePart will result in katepart messing up bookmarks +(and breakpoints). There is no current workaround. + +\requirement KDE >= 3.1.3 + +*/ diff --git a/parts/bookmarks/bookmarks_config.cpp b/parts/bookmarks/bookmarks_config.cpp new file mode 100644 index 00000000..095c3f83 --- /dev/null +++ b/parts/bookmarks/bookmarks_config.cpp @@ -0,0 +1,138 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include +#include + +#include "bookmarks_config.h" + +BookmarksConfig::BookmarksConfig() +{ + _context = 5; + _codeline = Never; // 0 - Never, 1 - Only if Comment, 2 - Always + _tooltip = true; +} + + +BookmarksConfig::~BookmarksConfig() +{ +} + + +/*! + \fn BookmarksConfig::writeConfig() + */ +void BookmarksConfig::writeConfig() +{ + KConfig *config = kapp->config(); + config->setGroup("Bookmarks"); + + config->writeEntry("Context", _context ); + config->writeEntry("Codeline", _codeline ); + config->writeEntry("ToolTip", _tooltip ); + config->writeEntry("Token", _token ); + + config->sync(); +} + + +/*! + \fn BookmarksConfig::readConfig() + */ +void BookmarksConfig::readConfig() +{ + KConfig *config = kapp->config(); + config->setGroup("Bookmarks"); + + _context = config->readPropertyEntry( "Context", 5 ).toInt(); + _tooltip = config->readBoolEntry( "ToolTip", true ); + _token = config->readEntry( "Token", "//" ); + unsigned int cl = config->readPropertyEntry( "Codeline", 0 ).toInt(); + + switch( cl ) + { + case 1: + _codeline = Token; + break; + case 2: + _codeline = Always; + break; + default: + _codeline = Never; + } + + if ( _context > 15 ) _context = 15; +} + + +/*! + \fn BookmarksConfig::toolTip + */ +bool BookmarksConfig::toolTip() +{ + return _tooltip; +} + + +/*! + \fn BookmarksConfig::codeline + */ +BookmarksConfig::CodeLineType BookmarksConfig::codeline() +{ + return _codeline; +} + + +/*! + \fn BookmarksConfig::context() + */ +unsigned int BookmarksConfig::context() +{ + return _context; +} + + +/*! + \fn BookmarksConfig::setCodeline( CodeLineType ) + */ +void BookmarksConfig::setCodeline( CodeLineType codeline ) +{ + _codeline = codeline; +} + +/*! + \fn BookmarksConfig::setContext( unsigned int ) + */ +void BookmarksConfig::setContext( unsigned int context ) +{ + _context = context; +} + + +/*! + \fn BookmarksConfig::setToolTip( bool ) + */ +void BookmarksConfig::setToolTip( bool tooltip ) +{ + _tooltip = tooltip; +} + +QString BookmarksConfig::token( ) +{ + return _token; +} + +void BookmarksConfig::setToken( QString const & token ) +{ + _token = token; +} + +// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off; diff --git a/parts/bookmarks/bookmarks_config.h b/parts/bookmarks/bookmarks_config.h new file mode 100644 index 00000000..c372eb51 --- /dev/null +++ b/parts/bookmarks/bookmarks_config.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef BOOKMARKS_CONFIG_H +#define BOOKMARKS_CONFIG_H + +/** +@author KDevelop Authors +*/ +class BookmarksConfig +{ + +public: + + enum CodeLineType { Never = 0, Token, Always }; + + BookmarksConfig(); + ~BookmarksConfig(); + + bool toolTip(); + void setToolTip( bool ); + + CodeLineType codeline(); + void setCodeline( CodeLineType ); + + unsigned int context(); + void setContext( unsigned int ); + + QString token(); + void setToken( QString const & ); + + void readConfig(); + void writeConfig(); + +private: + bool _tooltip; + CodeLineType _codeline; + unsigned int _context; + QString _token; + +}; + +#endif + +// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off; diff --git a/parts/bookmarks/bookmarks_part.cpp b/parts/bookmarks/bookmarks_part.cpp new file mode 100644 index 00000000..f23863af --- /dev/null +++ b/parts/bookmarks/bookmarks_part.cpp @@ -0,0 +1,568 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "domutil.h" + +#include "bookmarks_widget.h" +#include "bookmarks_part.h" +#include "bookmarks_settings.h" +#include "bookmarks_config.h" + +#include +#include + +#define BOOKMARKSETTINGSPAGE 1 + +typedef KDevGenericFactory BookmarksFactory; +static const KDevPluginInfo data("kdevbookmarks"); +K_EXPORT_COMPONENT_FACTORY( libkdevbookmarks, BookmarksFactory( data ) ) + +BookmarksPart::BookmarksPart(QObject *parent, const char *name, const QStringList& ) + : KDevPlugin(&data, parent, name ? name : "BookmarksPart" ) +{ + setInstance(BookmarksFactory::instance()); + + _widget = new BookmarksWidget(this); + + _widget->setCaption(i18n("Bookmarks")); + _widget->setIcon(SmallIcon( info()->icon() )); + + _marksChangeTimer = new QTimer( this ); + + QWhatsThis::add(_widget, i18n("Bookmarks

" + "The bookmark viewer shows all the source bookmarks in the project.")); + + mainWindow()->embedSelectView(_widget, i18n("Bookmarks"), i18n("Source bookmarks")); + + _editorMap.setAutoDelete( true ); + _settingMarks = false; + + connect( partController(), SIGNAL( partAdded( KParts::Part * ) ), this, SLOT( partAdded( KParts::Part * ) ) ); + + _configProxy = new ConfigWidgetProxy( core() ); + _configProxy->createProjectConfigPage( i18n("Bookmarks"), BOOKMARKSETTINGSPAGE, info()->icon() ); + connect( _configProxy, SIGNAL(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )), + this, SLOT(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )) ); + + connect( _widget, SIGNAL( removeAllBookmarksForURL( const KURL & ) ), + this, SLOT( removeAllBookmarksForURL( const KURL & ) ) ); + connect( _widget, SIGNAL( removeBookmarkForURL( const KURL &, int ) ), + this, SLOT( removeBookmarkForURL( const KURL &, int ) ) ); + + connect( _marksChangeTimer, SIGNAL( timeout() ), this, SLOT( marksChanged() ) ); + + _config = new BookmarksConfig; + _config->readConfig(); + + storeBookmarksForAllURLs(); + updateContextStringForAll(); + _widget->update( _editorMap ); +} + +BookmarksPart::~BookmarksPart() +{ + if( _widget ) { + mainWindow()->removeView( _widget ); + delete _widget; + } + delete _config; + delete _configProxy; +} + +void BookmarksPart::partAdded( KParts::Part * part ) +{ + //kdDebug(0) << "BookmarksPart::partAdded()" << endl; + + if ( KParts::ReadOnlyPart * ro_part = dynamic_cast( part ) ) + { + if ( setBookmarksForURL( ro_part ) ) + { + updateContextStringForURL( ro_part ); + if ( EditorData * data = _editorMap.find( ro_part->url().path() ) ) + { + _widget->updateURL( data ); + } + + // connect to this editor + KTextEditor::Document * doc = static_cast( ro_part ); + connect( doc, SIGNAL( marksChanged() ), this, SLOT( marksEvent() ) ); + + // workaround for a katepart oddity where it drops all bookmarks on 'reload' + connect( doc, SIGNAL( completed() ), this, SLOT( reload() ) ); + } + } +} + +void BookmarksPart::reload() +{ + //kdDebug(0) << "BookmarksPart::reload()" << endl; + + QObject * senderobj = const_cast( sender() ); + if ( KParts::ReadOnlyPart * ro_part = dynamic_cast( senderobj ) ) + { + if ( partIsSane( ro_part ) ) + { + setBookmarksForURL( ro_part ); + } + } +} + +void BookmarksPart::marksEvent() +{ + //kdDebug(0) << "BookmarksPart::marksEvent()" << endl; + + if ( ! _settingMarks ) + { + QObject * senderobj = const_cast( sender() ); + KParts::ReadOnlyPart * ro_part = dynamic_cast( senderobj ); + + if ( partIsSane( ro_part ) && !_dirtyParts.contains( ro_part ) ) + { + _dirtyParts.push_back( ro_part ); + _marksChangeTimer->start( 1000, true ); + } + } +} + +void BookmarksPart::marksChanged() +{ + //kdDebug(0) << "BookmarksPart::marksChanged()" << endl; + + QValueListIterator it = _dirtyParts.begin(); + while ( it != _dirtyParts.end() ) + { + KParts::ReadOnlyPart * ro_part = *it; + if ( partIsSane( ro_part ) ) + { + if ( dynamic_cast( ro_part ) ) + { + if ( EditorData * data = storeBookmarksForURL( ro_part ) ) + { + updateContextStringForURL( ro_part ); + _widget->updateURL( data ); + } + else + { + _widget->removeURL( ro_part->url() ); + } + } + } + ++it; + } + _dirtyParts.clear(); +} + +void BookmarksPart::restorePartialProjectSession( const QDomElement * el ) +{ + //kdDebug(0) << "BookmarksPart::restorePartialProjectSession()" << endl; + + if ( ! el ) return; + + QDomElement bookmarksList = el->namedItem( "bookmarks" ).toElement(); + if ( bookmarksList.isNull() ) return; + + QDomElement bookmark = bookmarksList.firstChild().toElement(); + while ( ! bookmark.isNull() ) + { + QString path = bookmark.attribute( "url" ); + if ( path != QString::null ) + { + EditorData * data = new EditorData; + data->url.setPath( path ); + + QDomElement mark = bookmark.firstChild().toElement(); + while ( ! mark.isNull() ) + { + QString line = mark.attribute( "line" ); + if ( line != QString::null ) + { + data->marks.append( qMakePair( line.toInt(), QString() ) ); + } + mark = mark.nextSibling().toElement(); + } + + if ( ! data->marks.isEmpty() ) + { + _editorMap.insert( data->url.path(), data ); + } + else + { + delete data; + } + } + bookmark = bookmark.nextSibling().toElement(); + } + setBookmarksForAllURLs(); + updateContextStringForAll(); + _widget->update( _editorMap ); +} + +void BookmarksPart::savePartialProjectSession( QDomElement * el ) +{ + //kdDebug(0) << "BookmarksPart::savePartialProjectSession()" << endl; + + if ( ! el ) return; + + QDomDocument domDoc = el->ownerDocument(); + if ( domDoc.isNull() ) return; + + QDomElement bookmarksList = domDoc.createElement( "bookmarks" ); + + QDictIterator it( _editorMap ); + while ( it.current() ) + { + QDomElement bookmark = domDoc.createElement( "bookmark" ); + bookmark.setAttribute( "url", it.current()->url.path() ); + bookmarksList.appendChild( bookmark ); + + QValueListIterator< QPair > it2 = it.current()->marks.begin(); + while ( it2 != it.current()->marks.end() ) + { + QDomElement line = domDoc.createElement( "mark" ); + line.setAttribute( "line", (*it2).first ); + bookmark.appendChild( line ); + ++it2; + } + ++it; + } + + if ( ! bookmarksList.isNull() ) + { + el->appendChild( bookmarksList ); + } +} + +void BookmarksPart::removeAllBookmarksForURL( KURL const & url ) +{ + //kdDebug(0) << "BookmarksPart::removeAllBookmarksForURL()" << endl; + + _editorMap.remove( url.path() ); + + setBookmarksForURL( partForURL( url ) ); + _widget->removeURL( url ); +} + +void BookmarksPart::removeBookmarkForURL( KURL const & url, int line ) +{ + //kdDebug(0) << "BookmarksPart::removeBookmarkForURL()" << endl; + + if ( EditorData * data = _editorMap.find( url.path() ) ) + { + QValueListIterator< QPair > it = data->marks.begin(); + while ( it != data->marks.end() ) + { + if ( (*it).first == line ) + { + data->marks.remove( it ); + break; + } + ++it; + } + + if ( data->marks.isEmpty() ) + { + removeAllBookmarksForURL( url ); + } + else + { + setBookmarksForURL( partForURL( url ) ); + _widget->updateURL( data ); + } + } +} + +void BookmarksPart::updateContextStringForURL( KParts::ReadOnlyPart * ro_part ) +{ + if ( ! ro_part ) return; + + KTextEditor::EditInterface * ed = + dynamic_cast( ro_part ); + + EditorData * data = _editorMap.find( ro_part->url().path() ); + + if ( ! ( data && ed ) ) return; + + QValueListIterator< QPair > it = data->marks.begin(); + while ( it != data->marks.end() ) + { + (*it).second = ed->textLine( (*it).first ); + ++it; + } +} + +void BookmarksPart::updateContextStringForURL( KURL const & url ) +{ + updateContextStringForURL( partForURL( url ) ); +} + +void BookmarksPart::updateContextStringForAll() +{ + QDictIterator it( _editorMap ); + while ( it.current() ) + { + if ( ! it.current()->marks.isEmpty() ) + { + updateContextStringForURL( it.current()->url ); + } + ++it; + } +} + +bool BookmarksPart::setBookmarksForURL( KParts::ReadOnlyPart * ro_part ) +{ + if ( KTextEditor::MarkInterface * mi = dynamic_cast(ro_part) ) + { + clearBookmarksForURL( ro_part ); + + _settingMarks = true; + + if ( EditorData * data = _editorMap.find( ro_part->url().path() ) ) + { + // we've seen this one before, apply stored bookmarks + + QValueListIterator< QPair > it = data->marks.begin(); + while ( it != data->marks.end() ) + { + mi->addMark( (*it).first, KTextEditor::MarkInterface::markType01 ); + ++it; + } + } + _settingMarks = false; + + // true == this is a MarkInterface + return true; + } + return false; +} + +// Note: This method is only a convenience method to clear the bookmark marks, +// the way a hypothetical KTextEditor::MarkInterface::clearMarks( uint markType ) +// would work. +bool BookmarksPart::clearBookmarksForURL( KParts::ReadOnlyPart * ro_part ) +{ + if ( KTextEditor::MarkInterface * mi = dynamic_cast(ro_part) ) + { + _settingMarks = true; + + QPtrList marks = mi->marks(); + QPtrListIterator it( marks ); + while ( it.current() ) + { + if ( it.current()->type & KTextEditor::MarkInterface::markType01 ) + { + mi->removeMark( it.current()->line, KTextEditor::MarkInterface::markType01 ); + } + ++it; + } + + _settingMarks = false; + + // true == this is a MarkInterface + return true; + } + return false; +} + +EditorData * BookmarksPart::storeBookmarksForURL( KParts::ReadOnlyPart * ro_part ) +{ + //kdDebug(0) << "BookmarksPart::storeBookmarksForURL()" << endl; + + if ( KTextEditor::MarkInterface * mi = dynamic_cast( ro_part ) ) + { + EditorData * data = new EditorData; + data->url = ro_part->url(); + + // removing previous data for this url, if any + _editorMap.remove( data->url.path() ); + + QPtrList marks = mi->marks(); + QPtrListIterator it( marks ); + while ( it.current() ) + { + if ( it.current()->type & KTextEditor::MarkInterface::markType01 ) + { + int line = it.current()->line; + data->marks.append( qMakePair( line, QString() ) ); + } + ++it; + } + + if ( ! data->marks.isEmpty() ) + { + _editorMap.insert( data->url.path(), data ); + } + else + { + delete data; + data = 0; + } + return data; + } + return 0; +} + +void BookmarksPart::setBookmarksForAllURLs() +{ + if( const QPtrList * partlist = partController()->parts() ) + { + QPtrListIterator it( *partlist ); + while ( KParts::Part* part = it.current() ) + { + if ( KParts::ReadOnlyPart * ro_part = dynamic_cast( part ) ) + { + setBookmarksForURL( ro_part ); + } + ++it; + } + } +} + +void BookmarksPart::storeBookmarksForAllURLs() +{ + if( const QPtrList * partlist = partController()->parts() ) + { + QPtrListIterator it( *partlist ); + while ( KParts::Part* part = it.current() ) + { + if ( KParts::ReadOnlyPart * ro_part = dynamic_cast( part ) ) + { + storeBookmarksForURL( ro_part ); + } + ++it; + } + } +} + +// reimplemented from PartController::partForURL to avoid linking +KParts::ReadOnlyPart * BookmarksPart::partForURL( KURL const & url ) +{ + QPtrListIterator it( *partController()->parts() ); + while( it.current() ) + { + KParts::ReadOnlyPart *ro_part = dynamic_cast(it.current()); + if (ro_part && url == ro_part->url()) + { + return ro_part; + } + ++it; + } + return 0; +} + +bool BookmarksPart::partIsSane( KParts::ReadOnlyPart * ro_part ) +{ + return ( ro_part != 0 ) && + partController()->parts()->contains( ro_part) && + !ro_part->url().path().isEmpty(); +} + +void BookmarksPart::insertConfigWidget( const KDialogBase * dlg, QWidget * page, unsigned int pagenumber ) +{ + kdDebug() << k_funcinfo << endl; + + if ( pagenumber == BOOKMARKSETTINGSPAGE ) + { + BookmarkSettings * w = new BookmarkSettings( this, page ); + connect( dlg, SIGNAL(okClicked()), w, SLOT(slotAccept()) ); + } +} + +//////////////////////////////////////////// + +QStringList BookmarksPart::getContextFromStream( QTextStream & istream, unsigned int line, unsigned int context ) +{ + kdDebug() << k_funcinfo << endl; + + int startline = context > line ? 0 : line - context; + int endline = line + context; + + int n = 0; + QStringList list; + while ( !istream.atEnd() ) + { + QString templine = istream.readLine(); + if ( (n >= startline) && ( n <= endline ) ) + { + list << templine; + } + n++; + } + + // maybe pad empty lines to the tail + while( n < endline ) + { + list.append( " " ); + n++; + } + + // maybe pad empty lines to the head + while( list.count() < ( context * 2 + 1) ) + { + list.prepend( " " ); + } + + return list; +} + +QStringList BookmarksPart::getContext( KURL const & url, unsigned int line, unsigned int context ) +{ + // if the file is open - get the line from the editor buffer + if ( KTextEditor::EditInterface * ei = dynamic_cast( partForURL( url ) ) ) + { + kdDebug() << "the file is open - get the line from the editor buffer" << endl; + + QString ibuffer = ei->text(); + QTextStream istream( &ibuffer, IO_ReadOnly ); + return getContextFromStream( istream, line, context ); + } + else if ( url.isLocalFile() ) // else the file is not open - get the line from the file on disk + { + kdDebug() << "the file is not open - get the line from the file on disk" << endl; + + QFile file( url.path() ); + QString buffer; + + if ( file.open( IO_ReadOnly ) ) + { + QTextStream istream( &file ); + return getContextFromStream( istream, line, context ); + } + } + return QStringList( i18n("Could not find file") ); +} + +BookmarksConfig * BookmarksPart::config( ) +{ + return _config; +} + +#include "bookmarks_part.moc" + +// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off; diff --git a/parts/bookmarks/bookmarks_part.h b/parts/bookmarks/bookmarks_part.h new file mode 100644 index 00000000..32a105ad --- /dev/null +++ b/parts/bookmarks/bookmarks_part.h @@ -0,0 +1,109 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#ifndef __KDEVPART_BOOKMARKS_H__ +#define __KDEVPART_BOOKMARKS_H__ + + +#include +#include +#include +#include + +#include +#include + +#include + +class QTimer; +class KDialogBase; +class BookmarksConfig; +class ConfigWidgetProxy; + +struct EditorData +{ + KURL url; + QValueList< QPair > marks; +}; + +class BookmarksWidget; +class QDomElement; + +class BookmarksPart : public KDevPlugin +{ + Q_OBJECT + +public: + + BookmarksPart(QObject *parent, const char *name, const QStringList &); + ~BookmarksPart(); + + // reimplemented from KDevPlugin + void restorePartialProjectSession( const QDomElement * el ); + void savePartialProjectSession( QDomElement * el ); + + BookmarksConfig * config(); + + QStringList getContext( KURL const & url, unsigned int line, unsigned int context ); + +private slots: + // connected to partcontroller + void partAdded( KParts::Part * part ); + + // connected to KTextEditor::MarkInterface + void marksEvent(); + + // connected to _marksChangeTimer + void marksChanged(); + + // connected to KParts::ReadOnlyPart + void reload(); + + // connected to BookmarksWidget + void removeAllBookmarksForURL( const KURL & ); + void removeBookmarkForURL( const KURL &, int ); + + void insertConfigWidget( const KDialogBase * dlg, QWidget * page, unsigned int ); + +private: + bool setBookmarksForURL( KParts::ReadOnlyPart * ); + bool clearBookmarksForURL( KParts::ReadOnlyPart * ); + void setBookmarksForAllURLs(); + + EditorData * storeBookmarksForURL( KParts::ReadOnlyPart * ); + void storeBookmarksForAllURLs(); + + void updateContextStringForURL( KParts::ReadOnlyPart * ); + void updateContextStringForURL( KURL const & url ); + void updateContextStringForAll(); + + QStringList getContextFromStream( QTextStream & istream, unsigned int line, unsigned int context ); + + KParts::ReadOnlyPart * partForURL( KURL const & url ); + bool partIsSane( KParts::ReadOnlyPart * ); + + QGuardedPtr _widget; + QDict _editorMap; + bool _settingMarks; // are we currently in the process of setting bookmarks? + + BookmarksConfig * _config; + + ConfigWidgetProxy * _configProxy; + + QTimer * _marksChangeTimer; + QValueList _dirtyParts; +}; + + +#endif + +// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off; diff --git a/parts/bookmarks/bookmarks_settings.cpp b/parts/bookmarks/bookmarks_settings.cpp new file mode 100644 index 00000000..235ec261 --- /dev/null +++ b/parts/bookmarks/bookmarks_settings.cpp @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "bookmarks_part.h" +#include "bookmarks_config.h" +#include "bookmarks_settings.h" + + +BookmarkSettings::BookmarkSettings( BookmarksPart * part, QWidget* parent, const char* name, WFlags fl ) +: BookmarkSettingsBase( parent, name, fl ), m_part( part ) +{ + m_part->config()->readConfig(); + + if ( m_part->config()->codeline() == BookmarksConfig::Never ) + { + radioButton1->setChecked( true ); + } + else if ( m_part->config()->codeline() == BookmarksConfig::Token ) + { + radioButton2->setChecked( true ); + } + else + { + radioButton3->setChecked( true ); + } + + checkBox1->setChecked( m_part->config()->toolTip() ); + spinBox1->setValue( m_part->config()->context() ); + lineEdit1->setText( m_part->config()->token() ); +} + +BookmarkSettings::~BookmarkSettings() +{ +} + +void BookmarkSettings::slotAccept() +{ + BookmarksConfig::CodeLineType codeline = BookmarksConfig::Never; + codeline = radioButton1->isChecked() ? BookmarksConfig::Never : codeline; + codeline = radioButton2->isChecked() ? BookmarksConfig::Token : codeline; + codeline = radioButton3->isChecked() ? BookmarksConfig::Always : codeline; + m_part->config()->setCodeline( codeline ); + m_part->config()->setToolTip( checkBox1->isChecked() ); + m_part->config()->setContext( spinBox1->value() ); + m_part->config()->setToken( lineEdit1->text() ); + + m_part->config()->writeConfig(); +} + + +#include "bookmarks_settings.moc" + +// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off; diff --git a/parts/bookmarks/bookmarks_settings.h b/parts/bookmarks/bookmarks_settings.h new file mode 100644 index 00000000..3fa6c5e9 --- /dev/null +++ b/parts/bookmarks/bookmarks_settings.h @@ -0,0 +1,41 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef BOOKMARKS_SETTINGS_H +#define BOOKMARKS_SETTINGS_H + +#include "bookmarks_settings_base.h" + +class BookmarksPart; + +class BookmarkSettings : public BookmarkSettingsBase +{ + Q_OBJECT + +public: + BookmarkSettings( BookmarksPart * part, QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~BookmarkSettings(); + +public slots: + void slotAccept(); + +protected: + +protected slots: + +private: + + BookmarksPart * m_part; + +}; + +#endif + diff --git a/parts/bookmarks/bookmarks_settings_base.ui b/parts/bookmarks/bookmarks_settings_base.ui new file mode 100644 index 00000000..2d7ab1a2 --- /dev/null +++ b/parts/bookmarks/bookmarks_settings_base.ui @@ -0,0 +1,240 @@ + +BookmarkSettingsBase + + + BookmarkSettingsBase + + + + 0 + 0 + 622 + 490 + + + + + unnamed + + + + groupBox1 + + + Code Tooltip + + + If checked, a tooltip will be shown when the mouse is over the bookmark, containing the text in the area surrounding it. <p> How many surrounding lines to include is decided by the value in the context box. + + + + unnamed + + + + checkBox1 + + + Show code &tooltip + + + true + + + + + + + + + + + layout2 + + + + unnamed + + + + textLabel1 + + + &Lines of context: + + + spinBox1 + + + + + + + + spinBox1 + + + 15 + + + 3 + + + + + + + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 121 + 20 + + + + + + + + + + buttonGroup1 + + + Show Bookmarked Codeline in Bookmark Panel + + + This decides if the bookmark panel should show the content of the bookmarked line in addition to the line number.<p>This can be made optional depending on the start of the line, typically used for only showing lines containing a comment. + + + + unnamed + + + + radioButton1 + + + &Never + + + + + + + + + + + layout3 + + + + unnamed + + + + radioButton2 + + + &Only lines beginning with the following string: + + + true + + + + + + + + lineEdit1 + + + + + spacer3 + + + Horizontal + + + Expanding + + + + 71 + 20 + + + + + + + + radioButton3 + + + &Always + + + Always show the bookmarked line in addition to the line number + + + + + + + spacer2 + + + Vertical + + + Expanding + + + + 20 + 240 + + + + + + + + checkBox1 + toggled(bool) + spinBox1 + setEnabled(bool) + + + checkBox1 + toggled(bool) + textLabel1 + setEnabled(bool) + + + radioButton2 + toggled(bool) + lineEdit1 + setEnabled(bool) + + + + + klineedit.h + + diff --git a/parts/bookmarks/bookmarks_widget.cpp b/parts/bookmarks/bookmarks_widget.cpp new file mode 100644 index 00000000..683c32e1 --- /dev/null +++ b/parts/bookmarks/bookmarks_widget.cpp @@ -0,0 +1,336 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +#include "bookmarks_part.h" +#include "bookmarks_widget.h" +#include "bookmarks_config.h" + +namespace +{ + +// shamelessly lifted from kdelibs/kate/part/kateviewhelpers.cpp +static const char* const bookmark_xpm[]={ +"12 12 4 1", +"b c #808080", +"a c #000080", +"# c #0000ff", +". c None", +"........###.", +".......#...a", +"......#.##.a", +".....#.#..aa", +"....#.#...a.", +"...#.#.a.a..", +"..#.#.a.a...", +".#.#.a.a....", +"#.#.a.a.....", +"#.#a.a......", +"#...a.......", +".aaa........"}; + +} + +class BookmarkItem : public QListViewItem +{ +public: + BookmarkItem( QListView * parent, KURL const & url ) + : QListViewItem( parent, url.fileName() ), + _url( url ), _line( -1 ), _isBookmark( false ) + {} + + BookmarkItem( QListViewItem * parent, KURL const & url, QPair mark ) + : QListViewItem( parent, QString::number( mark.first +1 ).rightJustify( 5 ) ), + _url( url ), _line( mark.first ), _isBookmark( true ) + { + BookmarksWidget * lv = static_cast( listView() ); + BookmarksConfig::CodeLineType codeline = lv->config()->codeline(); + + if ( codeline == BookmarksConfig::Never ) + { + return; + } + + if ( codeline == BookmarksConfig::Token ) + { + if ( mark.second.startsWith( lv->config()->token() ) ) + { + setText( 0, text( 0 ) + " " + mark.second ); + } + return; + } + + setText( 0, text( 0 ) + " " + mark.second ); + } + + KURL url() + { + return _url; + } + int line() + { + return _line; + } + + QString tipText() + { + if ( _isBookmark ) + { + BookmarksWidget * w = static_cast ( listView() ); + QStringList list = w->getContext( _url, _line ); + + QString code = "
";
+			for ( uint i = 0; i < list.count(); i++)
+			{
+				QString temp = QStyleSheet::escape( list[i] );
+				
+				if ( i == (list.count() / 2) )	// count() is always odd
+				{
+					temp = "" + temp + "";
+				}
+				code += temp + "\n";
+			}
+			code += "
"; + + return code; + } + else + { + return _url.prettyURL(); + } + } + + bool isBookmark() + { + return _isBookmark; + } + +private: + KURL _url; + int _line; + bool _isBookmark; + QString _code; + +}; + +BookmarksWidget::BookmarksWidget(BookmarksPart *part) + : KListView(0, "bookmarks widget"), QToolTip( viewport() ), + _part( part ) + +{ + addColumn( QString::null ); + header()->hide(); + setRootIsDecorated( true ); + setResizeMode( QListView::LastColumn ); + setAllColumnsShowFocus( true ); +// setSortColumn( -1 ); + + connect( this, SIGNAL( executed( QListViewItem * ) ), this, SLOT( itemClicked( QListViewItem * ) ) ); + connect( this, SIGNAL( returnPressed( QListViewItem * ) ), this, SLOT( itemClicked( QListViewItem * ) ) ); + connect( this, SIGNAL( contextMenuRequested ( QListViewItem *, const QPoint & , int ) ), + this, SLOT( popupMenu(QListViewItem *, const QPoint & , int ) ) ); +} + + +BookmarksWidget::~BookmarksWidget() +{} + +void BookmarksWidget::maybeTip(const QPoint &p) +{ +// kdDebug(0) << "ToolTip::maybeTip()" << endl; + + if ( ! _part->config()->toolTip() ) return; + + BookmarkItem * item = dynamic_cast( itemAt( p ) ); + QRect r = itemRect( item ); + + if ( item && r.isValid() ) + { + tip( r, item->tipText() ); + } +} + +void BookmarksWidget::update( QDict const & map ) +{ +// kdDebug(0) << "BookmarksWidget::update()" << endl; + + QListView::clear(); + + QDictIterator it( map ); + while ( it.current() ) + { + if ( ! it.current()->marks.isEmpty() ) + { + createURL( it.current() ); + } + ++it; + } +} + +void BookmarksWidget::updateURL( EditorData * data ) +{ +// kdDebug(0) << "BookmarksWidget::updateURL()" << endl; + + // remove the node that contains 'data' + removeURL( data->url ); + + // create it again with new data + createURL( data ); +} + +void BookmarksWidget::createURL( EditorData * data ) +{ +// kdDebug(0) << "BookmarksWidget::createURL()" << endl; + + if ( data ) + { + QListViewItem * file = new BookmarkItem( this, data->url ); + file->setOpen( true ); + file->setPixmap( 0, SmallIcon( "document" ) ); + + QValueListIterator< QPair > it = data->marks.begin(); + while ( it != data->marks.end() ) + { + QListViewItem * item = new BookmarkItem( file, data->url, *it ); + item->setPixmap( 0, QPixmap((const char**)bookmark_xpm) ); + ++it; + } + } +} + +bool BookmarksWidget::removeURL( KURL const & url ) +{ +// kdDebug(0) << "BookmarksWidget::removeURL()" << endl; + + QListViewItem * item = firstChild(); + while ( item ) + { + BookmarkItem * bm = static_cast(item); + if ( bm->url() == url ) + { + delete item; + return true; + } + item = item->nextSibling(); + } + return false; +} + +void BookmarksWidget::doEmitRemoveBookMark() +{ +// kdDebug(0) << "BookmarksWidget::doEmitRemoveBookMark()" << endl; + + if ( _selectedItem->isBookmark() ) + { + emit removeBookmarkForURL( _selectedItem->url(), _selectedItem->line() ); + } + else + { + emit removeAllBookmarksForURL( _selectedItem->url() ); + } +} + +void BookmarksWidget::popupMenu( QListViewItem * item, const QPoint & p, int ) +{ +// kdDebug(0) << "BookmarksWidget::contextMenuRequested()" << endl; + + if ( item ) + { + _selectedItem = static_cast(item); + + KPopupMenu popup; + + if ( _selectedItem->isBookmark() ) + { + popup.insertTitle( _selectedItem->url().fileName() + i18n(", line ") + + QString::number( _selectedItem->line() +1 ) ); + + popup.insertItem( i18n("Remove This Bookmark"), this, SLOT( doEmitRemoveBookMark() ) ); + } + else + { + popup.insertTitle( _selectedItem->url().fileName() + i18n( ", All" ) ); + popup.insertItem( i18n("Remove These Bookmarks"), this, SLOT( doEmitRemoveBookMark() ) ); + } + + popup.insertSeparator(); + + popup.insertItem( i18n( "Collapse All" ), this, SLOT(collapseAll()) ); + popup.insertItem( i18n( "Expand All" ), this, SLOT(expandAll()) ); + + popup.exec(p); + } + +} + +void BookmarksWidget::itemClicked( QListViewItem * clickedItem ) +{ +// kdDebug(0) << "BookmarksWidget::itemClicked()" << endl; + + if ( ! clickedItem ) + return; + + BookmarkItem * item = static_cast( clickedItem ); + _part->partController()->editDocument( item->url(), item->line() ); + +} + +BookmarksConfig * BookmarksWidget::config( ) +{ + return _part->config(); +} + +QStringList BookmarksWidget::getContext( KURL const & url, unsigned int line ) +{ + return _part->getContext( url, line, config()->context() ); +} + +void BookmarksWidget::collapseAll( ) +{ + QListViewItem * it = firstChild(); + while( it ) + { + it->setOpen( false ); + it = it->nextSibling(); + } +} + +void BookmarksWidget::expandAll( ) +{ + QListViewItem * it = firstChild(); + while( it ) + { + it->setOpen( true ); + it = it->nextSibling(); + } +} + + +#include "bookmarks_widget.moc" + +// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off; diff --git a/parts/bookmarks/bookmarks_widget.h b/parts/bookmarks/bookmarks_widget.h new file mode 100644 index 00000000..96bfe046 --- /dev/null +++ b/parts/bookmarks/bookmarks_widget.h @@ -0,0 +1,72 @@ +/*************************************************************************** + * Copyright (C) 2003 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef __BOOKMARKS_WIDGET_H__ +#define __BOOKMARKS_WIDGET_H__ + + +#include +#include +//#include +#include + +#include + +#include "bookmarks_part.h" + +class BookmarksPart; +class BookmarkItem; +class BookmarksConfig; + +class BookmarksWidget : public KListView, public QToolTip +{ + Q_OBJECT + +public: + BookmarksWidget( BookmarksPart * ); + ~BookmarksWidget(); + + void update( QDict const & ); + void updateURL( EditorData * ); + bool removeURL( KURL const & ); + + BookmarksConfig * config(); + QStringList getContext( KURL const &, unsigned int ); + +signals: + void removeAllBookmarksForURL( const KURL & ); + void removeBookmarkForURL( const KURL &, int ); + +protected: + void maybeTip( QPoint const & ); + +private slots: + void itemClicked( QListViewItem * ); + void popupMenu( QListViewItem * , const QPoint & , int ); + void collapseAll(); + void expandAll(); + void doEmitRemoveBookMark(); + +private: + void createURL( EditorData * ); + + BookmarksPart * _part; + BookmarkItem * _selectedItem; + +// static CodeLineType _s_codeline; + + friend class BookmarkItem; +}; + + +#endif + +// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off; diff --git a/parts/bookmarks/kdevbookmarks.desktop b/parts/bookmarks/kdevbookmarks.desktop new file mode 100644 index 00000000..bd5151bd --- /dev/null +++ b/parts/bookmarks/kdevbookmarks.desktop @@ -0,0 +1,85 @@ +[Desktop Entry] +Type=Service +Exec=blubb +Comment=Plugin that provides navigation and overview of active source bookmarks and persists them between sessions. +Comment[ca]=Connector que proporciona navegació i visió de conjunt dels marcadors actius en el codi font i els manté entre sessions. +Comment[da]=Plugin der sørger for navigation og overblik for aktive kilde-bogmærker og lader dem overleve mellem sessioner. +Comment[de]=Ein Modul, das die Navigation in und die Übersicht über Quelltext-Lesezeichen ermöglicht und diese zwischen den Arbeitssitzungen speichert. +Comment[el]=Πρόσθετο που προσφέρει πλοήγηση και περίληψη των ενεργών σελιδοδεικτών στον κώδικα καθώς και τη διατήρηση αυτών μεταξύ των συνεδριών. +Comment[es]=Complemento que proporciona navegación de marcadores del código activos y los mantiene entre sesiones. +Comment[et]=Plugin, mis võimaldab näha ja liikuda aktiivse koodi järjehoidjate vahel ning peab need seansside vahel meeles. +Comment[eu]=Iturburu laster-marka aktiboen arakatze eta ikuspegi orokorra eskeintzen duen plugina da eta hauek sesioen artean mantentzen ditu. +Comment[fa]=وصله‌ای که ناوش و خلاصۀ چوب الفهای فعال منبع را فراهم می‌کند و آنها را در بین نشستها می‌گذارد +Comment[fr]=Module externe qui fournit une navigation et une vue d'ensemble des signets du source actif, et les maintient persistants entre les sessions. +Comment[gl]=Extensión que proporciona navegación e vista xeral de marcadores activos no código e que se encarga de mantelos entre sesións. +Comment[hu]=Bővítőmodul a forrásfájlok könyvjelzőinek áttekintéséhez, eltárolásához +Comment[it]=Plugin che offre la navigazione e l'anteprima dei segnalibri nel codice attivo e rimane nelle varie sessioni. +Comment[ja]=セッション間でアクティブなソースのブックマークや主張の外観やナビゲーションを提供するプラグイン。 +Comment[ms]=Plugin yang menyediakan pengemudian dan pandangan umum bagi tandalaman sumber aktif dan mengekalkan mereka antara sesi. +Comment[nds]=En Moduul, wat dat Stüern twischen un de Översicht över Borntext-Leestekens praatstellt, un disse över Törns wohrt. +Comment[ne]=प्लगइनले सक्रिय स्रोत पुस्तकचिनोको नेभिगेसन र समिक्षा प्रदान गर्दछ र सत्रहरू बिच तिनीहरूलाई राख्दछ । +Comment[nl]=Plugin die bladwijzers biedt die ook blijven bestaan tussen opeenvolgende sessies. +Comment[pl]=Wtyczka umożliwiająca nawigację i uzyskiwanie informacji na temat aktywnych zakładek w kodzie oraz przenoszenie ich między sesjami. +Comment[pt]=Um 'plugin' que oferece uma navegação e uma vista geral sobre os favoritos de código activos, mantendo-os persistentes entre sessões. +Comment[pt_BR]=Plug-in que fornece navegação e uma visão geral dos marcadores de código ativos e persiste entre sessões. +Comment[ru]=Модуль, который обеспечивает навигацию и просмотр активных закладок в коде, а также их сохранение в проекте. +Comment[sk]=Modul proskytuje navigáciu a prehľad aktívnych zdrojových záložiek a ich pretrvanie medzi sedeniami. +Comment[sr]=Прикључак који обезбеђује навигацију и преглед активних маркера изворног кôда и одржава их између сесија. +Comment[sr@Latn]=Priključak koji obezbeđuje navigaciju i pregled aktivnih markera izvornog kôda i održava ih između sesija. +Comment[sv]=Insticksprogram som tillhandahåller navigering och översikt över aktiva källkodsbokmärken och gör dem bestående mellan sessioner. +Comment[ta]=நடப்பில் உள்ள புத்தக குறியீடு மூலத்திற்கு மேற்பார்வை மற்றும் வழிசெலுத்தும் வசதிகளை சொருகி உங்களுக்கு தரும் மற்றும் அமர்வுக்கு இடையே இதனை பரிசோதிக்கும். +Comment[tg]=Модуле, ки навигатсия ва намоиши поягузории фаъолро дар код таъмин месозад, ва боз барои нигоҳ доштан дар лоиҳа ҳам. +Comment[tr]=Etkin kaynak yerimlerinin dolaşımını, gözden geçirilmesini ve oturumlar arasında devamlılığını sağlayan bir eklenti. +Comment[zh_CN]=提供当前源文件书签的浏览、预览和保存的插件。 +Comment[zh_TW]=提供目前程式碼書籤的導覽與概觀,並保持在工作階段間。 +Name=KDevBookmarks +Name[da]=KDevelop bogmærker +Name[de]=Lesezeichen-Unterstützung (KDevelop) +Name[hi]=के-डेव-बुकमार्क्स +Name[nds]=Leestekens-Ünnerstütten (KDevelop) +Name[pl]=KDevZakładki +Name[sk]=KDev záložky +Name[sv]=KDevelop bokmärken +Name[zh_TW]=KDevelop 書籤 +GenericName=Bookmarks +GenericName[br]=Sinedoù +GenericName[ca]=Marcadors +GenericName[cy]=Tudnodau +GenericName[da]=Bogmærker +GenericName[de]=Unterstützung für Lesezeichen +GenericName[el]=Σελιδοδείκτες +GenericName[es]=Marcadores +GenericName[et]=Järjehoidjad +GenericName[eu]=Laster-markak +GenericName[fa]=چوب‌ الفها +GenericName[fr]=Signets +GenericName[ga]=Leabharmharcanna +GenericName[gl]=Marcadores +GenericName[hi]= पसंदीदा +GenericName[hu]=Könyvjelzők +GenericName[it]=Segnalibri +GenericName[ja]=ブックマーク +GenericName[ms]=Tandabuku +GenericName[nds]=Leestekens-Ünnerstütten +GenericName[ne]=पुस्तकचिनो +GenericName[nl]=Bladwijzers +GenericName[pl]=Zakładki +GenericName[pt]=Favoritos +GenericName[pt_BR]=Marcadores +GenericName[ru]=Закладки +GenericName[sk]=Záložky +GenericName[sl]=Zaznamki +GenericName[sr]=Маркери +GenericName[sr@Latn]=Markeri +GenericName[sv]=Bokmärken +GenericName[ta]=புத்தகக்குறியின் +GenericName[tg]=Поягузор +GenericName[tr]=Yerimleri +GenericName[zh_CN]=书签 +GenericName[zh_TW]=書籤 +Icon=bookmark +ServiceTypes=KDevelop/Plugin +X-KDevelop-Scope=Project +X-KDE-Library=libkdevbookmarks +X-KDevelop-Version=5 +X-KDevelop-Properties=CodeEditing -- cgit v1.2.1