00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "kbookmarkmanager.h"
00023 #include "kbookmarkmenu.h"
00024 #include "kbookmarkmenu_p.h"
00025 #include "kbookmarkimporter.h"
00026 #include <kdebug.h>
00027 #include <krun.h>
00028 #include <kstandarddirs.h>
00029 #include <ksavefile.h>
00030 #include <dcopref.h>
00031 #include <qregexp.h>
00032 #include <kmessagebox.h>
00033 #include <kprocess.h>
00034 #include <klocale.h>
00035 #include <kapplication.h>
00036 #include <dcopclient.h>
00037 #include <qfile.h>
00038 #include <qfileinfo.h>
00039 #include <qtextstream.h>
00040 #include <kstaticdeleter.h>
00041 #include <qptrstack.h>
00042
00043 #include "dptrtemplate.h"
00044
00045 class KBookmarkManagerPrivate : public dPtrTemplate<KBookmarkManager, KBookmarkManagerPrivate> {
00046 public:
00047 KBookmarkManagerPrivate()
00048 { m_browserEditor = true; }
00049 QString m_editorCaption;
00050 bool m_browserEditor;
00051 };
00052 template<> QPtrDict<KBookmarkManagerPrivate>* dPtrTemplate<KBookmarkManager, KBookmarkManagerPrivate>::d_ptr = 0;
00053
00054 KBookmarkManagerPrivate* KBookmarkManager::dptr() const {
00055 return KBookmarkManagerPrivate::d( this );
00056 }
00057
00058
00059 QPtrList<KBookmarkManager>* KBookmarkManager::s_pSelf;
00060 static KStaticDeleter<QPtrList<KBookmarkManager> > sdbm;
00061
00062 class KBookmarkMap : private KBookmarkGroupTraverser {
00063 public:
00064 KBookmarkMap( KBookmarkManager * );
00065 void update();
00066 QValueList<KBookmark> find( const QString &url ) const
00067 { return m_bk_map[url]; }
00068 private:
00069 virtual void visit(const KBookmark &);
00070 virtual void visitEnter(const KBookmarkGroup &) { ; }
00071 virtual void visitLeave(const KBookmarkGroup &) { ; }
00072 private:
00073 typedef QValueList<KBookmark> KBookmarkList;
00074 QMap<QString, KBookmarkList> m_bk_map;
00075 KBookmarkManager *m_manager;
00076 };
00077
00078 static KBookmarkMap *s_bk_map = 0;
00079
00080 KBookmarkMap::KBookmarkMap( KBookmarkManager *manager ) {
00081 m_manager = manager;
00082 }
00083
00084 void KBookmarkMap::update()
00085 {
00086 m_bk_map.clear();
00087 KBookmarkGroup root = m_manager->root();
00088 traverse(root);
00089 }
00090
00091 void KBookmarkMap::visit(const KBookmark &bk)
00092 {
00093 if (!bk.isSeparator()) {
00094
00095 m_bk_map[bk.internalElement().attribute("href")].append(bk);
00096 }
00097 }
00098
00099
00100 KBookmarkManager* KBookmarkManager::managerForFile( const QString& bookmarksFile, bool bImportDesktopFiles )
00101 {
00102 if ( !s_pSelf ) {
00103 sdbm.setObject( s_pSelf, new QPtrList<KBookmarkManager> );
00104 s_pSelf->setAutoDelete( true );
00105 }
00106 QPtrListIterator<KBookmarkManager> it ( *s_pSelf );
00107 for ( ; it.current() ; ++it )
00108 if ( it.current()->path() == bookmarksFile )
00109 return it.current();
00110
00111 KBookmarkManager* mgr = new KBookmarkManager( bookmarksFile, bImportDesktopFiles );
00112 s_pSelf->append( mgr );
00113 return mgr;
00114 }
00115
00116
00117 KBookmarkManager* KBookmarkManager::createTempManager()
00118 {
00119 if ( !s_pSelf ) {
00120 sdbm.setObject( s_pSelf, new QPtrList<KBookmarkManager> );
00121 s_pSelf->setAutoDelete( true );
00122 }
00123 KBookmarkManager* mgr = new KBookmarkManager();
00124 s_pSelf->append( mgr );
00125 return mgr;
00126 }
00127
00128 #define PI_DATA "version=\"1.0\" encoding=\"UTF-8\""
00129
00130 KBookmarkManager::KBookmarkManager( const QString & bookmarksFile, bool bImportDesktopFiles )
00131 : DCOPObject(QCString("KBookmarkManager-")+bookmarksFile.utf8()), m_doc("xbel"), m_docIsLoaded(false)
00132 {
00133 m_toolbarDoc.clear();
00134
00135 m_update = true;
00136 m_showNSBookmarks = true;
00137
00138 Q_ASSERT( !bookmarksFile.isEmpty() );
00139 m_bookmarksFile = bookmarksFile;
00140
00141 if ( !QFile::exists(m_bookmarksFile) )
00142 {
00143 QDomElement topLevel = m_doc.createElement("xbel");
00144 m_doc.appendChild( topLevel );
00145 m_doc.insertBefore( m_doc.createProcessingInstruction( "xml", PI_DATA), topLevel );
00146 if ( bImportDesktopFiles )
00147 importDesktopFiles();
00148 m_docIsLoaded = true;
00149 }
00150
00151 connectDCOPSignal(0, objId(), "bookmarksChanged(QString)", "notifyChanged(QString)", false);
00152 connectDCOPSignal(0, objId(), "bookmarkConfigChanged()", "notifyConfigChanged()", false);
00153 }
00154
00155 KBookmarkManager::KBookmarkManager( )
00156 : DCOPObject(QCString("KBookmarkManager-generated")), m_doc("xbel"), m_docIsLoaded(true)
00157 {
00158 m_toolbarDoc.clear();
00159
00160 m_update = false;
00161 m_showNSBookmarks = true;
00162
00163 m_bookmarksFile = QString::null;
00164
00165 QDomElement topLevel = m_doc.createElement("xbel");
00166 m_doc.appendChild( topLevel );
00167 m_doc.insertBefore( m_doc.createProcessingInstruction( "xml", PI_DATA), topLevel );
00168
00169
00170 #if 0
00171 connectDCOPSignal(0, objId(), "bookmarksChanged(QString)", "notifyChanged(QString)", false);
00172 connectDCOPSignal(0, objId(), "bookmarkConfigChanged()", "notifyConfigChanged()", false);
00173 #endif
00174 }
00175
00176 KBookmarkManager::~KBookmarkManager()
00177 {
00178 if ( s_pSelf )
00179 s_pSelf->removeRef( this );
00180 }
00181
00182 void KBookmarkManager::setUpdate( bool update )
00183 {
00184 m_update = update;
00185 }
00186
00187 const QDomDocument &KBookmarkManager::internalDocument() const
00188 {
00189 if(!m_docIsLoaded)
00190 {
00191 parse();
00192 m_toolbarDoc.clear();
00193 }
00194 return m_doc;
00195 }
00196
00197
00198 void KBookmarkManager::parse() const
00199 {
00200 m_docIsLoaded = true;
00201
00202 QFile file( m_bookmarksFile );
00203 if ( !file.open( IO_ReadOnly ) )
00204 {
00205 kdWarning() << "Can't open " << m_bookmarksFile << endl;
00206 return;
00207 }
00208 m_doc = QDomDocument("xbel");
00209 m_doc.setContent( &file );
00210
00211 QDomElement docElem = m_doc.documentElement();
00212 if ( docElem.isNull() )
00213 kdWarning() << "KBookmarkManager::parse : can't parse " << m_bookmarksFile << endl;
00214 else
00215 {
00216 QString mainTag = docElem.tagName();
00217 if ( mainTag == "BOOKMARKS" )
00218 {
00219 kdWarning() << "Old style bookmarks found. Calling convertToXBEL." << endl;
00220 docElem.setTagName("xbel");
00221 if ( docElem.hasAttribute( "HIDE_NSBK" ) && m_showNSBookmarks )
00222 {
00223 docElem.setAttribute( "hide_nsbk", docElem.attribute( "HIDE_NSBK" ) == "1" ? "yes" : "no" );
00224 docElem.removeAttribute( "HIDE_NSBK" );
00225 }
00226
00227 convertToXBEL( docElem );
00228 save();
00229 }
00230 else if ( mainTag != "xbel" )
00231 kdWarning() << "KBookmarkManager::parse : unknown main tag " << mainTag << endl;
00232
00233 QDomNode n = m_doc.documentElement().previousSibling();
00234 if ( n.isProcessingInstruction() )
00235 {
00236 QDomProcessingInstruction pi = n.toProcessingInstruction();
00237 pi.parentNode().removeChild(pi);
00238 }
00239
00240 QDomProcessingInstruction pi;
00241 pi = m_doc.createProcessingInstruction( "xml", PI_DATA );
00242 m_doc.insertBefore( pi, docElem );
00243 }
00244
00245 file.close();
00246 if ( !s_bk_map )
00247 s_bk_map = new KBookmarkMap( const_cast<KBookmarkManager*>( this ) );
00248 s_bk_map->update();
00249 }
00250
00251 void KBookmarkManager::convertToXBEL( QDomElement & group )
00252 {
00253 QDomNode n = group.firstChild();
00254 while( !n.isNull() )
00255 {
00256 QDomElement e = n.toElement();
00257 if ( !e.isNull() )
00258 if ( e.tagName() == "TEXT" )
00259 {
00260 e.setTagName("title");
00261 }
00262 else if ( e.tagName() == "SEPARATOR" )
00263 {
00264 e.setTagName("separator");
00265 }
00266 else if ( e.tagName() == "GROUP" )
00267 {
00268 e.setTagName("folder");
00269 convertAttribute(e, "ICON","icon");
00270 if ( e.hasAttribute( "TOOLBAR" ) )
00271 {
00272 e.setAttribute( "toolbar", e.attribute( "TOOLBAR" ) == "1" ? "yes" : "no" );
00273 e.removeAttribute( "TOOLBAR" );
00274 }
00275
00276 convertAttribute(e, "NETSCAPEINFO","netscapeinfo");
00277 bool open = (e.attribute("OPEN") == "1");
00278 e.removeAttribute("OPEN");
00279 e.setAttribute("folded", open ? "no" : "yes");
00280 convertToXBEL( e );
00281 }
00282 else
00283 if ( e.tagName() == "BOOKMARK" )
00284 {
00285 e.setTagName("bookmark");
00286 convertAttribute(e, "ICON","icon");
00287 convertAttribute(e, "NETSCAPEINFO","netscapeinfo");
00288 convertAttribute(e, "URL","href");
00289 QString text = e.text();
00290 while ( !e.firstChild().isNull() )
00291 e.removeChild(e.firstChild());
00292 QDomElement titleElem = e.ownerDocument().createElement("title");
00293 e.appendChild( titleElem );
00294 titleElem.appendChild( e.ownerDocument().createTextNode( text ) );
00295 }
00296 else
00297 kdWarning(7043) << "Unknown tag " << e.tagName() << endl;
00298 n = n.nextSibling();
00299 }
00300 }
00301
00302 void KBookmarkManager::convertAttribute( QDomElement elem, const QString & oldName, const QString & newName )
00303 {
00304 if ( elem.hasAttribute( oldName ) )
00305 {
00306 elem.setAttribute( newName, elem.attribute( oldName ) );
00307 elem.removeAttribute( oldName );
00308 }
00309 }
00310
00311 void KBookmarkManager::importDesktopFiles()
00312 {
00313 KBookmarkImporter importer( const_cast<QDomDocument *>(&internalDocument()) );
00314 QString path(KGlobal::dirs()->saveLocation("data", "kfm/bookmarks", true));
00315 importer.import( path );
00316
00317
00318 save();
00319 }
00320
00321 bool KBookmarkManager::save( bool toolbarCache ) const
00322 {
00323 return saveAs( m_bookmarksFile, toolbarCache );
00324 }
00325
00326 bool KBookmarkManager::saveAs( const QString & filename, bool toolbarCache ) const
00327 {
00328 kdDebug(7043) << "KBookmarkManager::save " << filename << endl;
00329
00330
00331
00332 const QString cacheFilename = filename + QString::fromLatin1(".tbcache");
00333 if(toolbarCache && !root().isToolbarGroup())
00334 {
00335 KSaveFile cacheFile( cacheFilename );
00336 if ( cacheFile.status() == 0 )
00337 {
00338 QString str;
00339 QTextStream stream(&str, IO_WriteOnly);
00340 stream << root().findToolbar();
00341 QCString cstr = str.utf8();
00342 cacheFile.file()->writeBlock( cstr.data(), cstr.length() );
00343 cacheFile.close();
00344 }
00345 }
00346 else
00347 {
00348 QFile::remove( cacheFilename );
00349 }
00350
00351 KSaveFile file( filename );
00352 if ( file.status() == 0 )
00353 {
00354 file.backupFile( file.name(), QString::null, ".bak" );
00355 QCString cstr;
00356 cstr = internalDocument().toCString();
00357 file.file()->writeBlock( cstr.data(), cstr.length() );
00358 if ( file.close() )
00359 return true;
00360 }
00361
00362 static int hadSaveError = false;
00363 file.abort();
00364 if ( !hadSaveError ) {
00365 QString error = i18n("Unable to save bookmarks in %1. Reported error was: %2. "
00366 "This error message will only be shown once. The cause "
00367 "of the error needs to be fixed as quickly as possible, "
00368 "which is most likely a full hard drive.")
00369 .arg(filename).arg(QString::fromLocal8Bit(strerror(file.status())));
00370 if (qApp->type() != QApplication::Tty)
00371 KMessageBox::error( 0L, error );
00372 else
00373 kdError() << error << endl;
00374 }
00375 hadSaveError = true;
00376 return false;
00377 }
00378
00379 KBookmarkGroup KBookmarkManager::root() const
00380 {
00381 return KBookmarkGroup(internalDocument().documentElement());
00382 }
00383
00384 KBookmarkGroup KBookmarkManager::toolbar()
00385 {
00386 kdDebug(7043) << "KBookmarkManager::toolbar begin" << endl;
00387
00388 if(!m_docIsLoaded)
00389 {
00390 kdDebug(7043) << "KBookmarkManager::toolbar trying cache" << endl;
00391 const QString cacheFilename = m_bookmarksFile + QString::fromLatin1(".tbcache");
00392 QFileInfo bmInfo(m_bookmarksFile);
00393 QFileInfo cacheInfo(cacheFilename);
00394 if (m_toolbarDoc.isNull() &&
00395 QFile::exists(cacheFilename) &&
00396 bmInfo.lastModified() < cacheInfo.lastModified())
00397 {
00398 kdDebug(7043) << "KBookmarkManager::toolbar reading file" << endl;
00399 QFile file( cacheFilename );
00400
00401 if ( file.open( IO_ReadOnly ) )
00402 {
00403 m_toolbarDoc = QDomDocument("cache");
00404 m_toolbarDoc.setContent( &file );
00405 kdDebug(7043) << "KBookmarkManager::toolbar opened" << endl;
00406 }
00407 }
00408 if (!m_toolbarDoc.isNull())
00409 {
00410 kdDebug(7043) << "KBookmarkManager::toolbar returning element" << endl;
00411 QDomElement elem = m_toolbarDoc.firstChild().toElement();
00412 return KBookmarkGroup(elem);
00413 }
00414 }
00415
00416
00417
00418 QDomElement elem = root().findToolbar();
00419 if (elem.isNull())
00420 return root();
00421 else
00422 return KBookmarkGroup(root().findToolbar());
00423 }
00424
00425 KBookmark KBookmarkManager::findByAddress( const QString & address, bool tolerant )
00426 {
00427
00428 KBookmark result = root();
00429
00430 QStringList addresses = QStringList::split(QRegExp("[/+]"),address);
00431
00432 for ( QStringList::Iterator it = addresses.begin() ; it != addresses.end() ; )
00433 {
00434 bool append = ((*it) == "+");
00435 uint number = (*it).toUInt();
00436 Q_ASSERT(result.isGroup());
00437 KBookmarkGroup group = result.toGroup();
00438 KBookmark bk = group.first(), lbk = bk;
00439 for ( uint i = 0 ; ( (i<number) || append ) && !bk.isNull() ; ++i ) {
00440 lbk = bk;
00441 bk = group.next(bk);
00442
00443 }
00444 it++;
00445 int shouldBeGroup = !bk.isGroup() && (it != addresses.end());
00446 if ( tolerant && ( bk.isNull() || shouldBeGroup ) ) {
00447 if (!lbk.isNull()) result = lbk;
00448
00449 break;
00450 }
00451
00452 result = bk;
00453 }
00454 if (result.isNull()) {
00455 kdWarning() << "KBookmarkManager::findByAddress: couldn't find item " << address << endl;
00456 Q_ASSERT(!tolerant);
00457 }
00458
00459 return result;
00460 }
00461
00462 static QString pickUnusedTitle( KBookmarkGroup parentBookmark,
00463 const QString &title, const QString &url
00464 ) {
00465
00466 KBookmark ch = parentBookmark.first();
00467 int count = 1;
00468 QString uniqueTitle = title;
00469 do
00470 {
00471 while ( !ch.isNull() )
00472 {
00473 if ( uniqueTitle == ch.text() )
00474 {
00475
00476 if ( url != ch.url().url() )
00477 {
00478 uniqueTitle = title + QString(" (%1)").arg(++count);
00479
00480 ch = parentBookmark.first();
00481 break;
00482 }
00483 else
00484 {
00485
00486 return QString::null;
00487 }
00488 }
00489 ch = parentBookmark.next( ch );
00490 }
00491 } while ( !ch.isNull() );
00492
00493 return uniqueTitle;
00494 }
00495
00496 KBookmarkGroup KBookmarkManager::addBookmarkDialog(
00497 const QString & _url, const QString & _title,
00498 const QString & _parentBookmarkAddress
00499 ) {
00500 QString url = _url;
00501 QString title = _title;
00502 QString parentBookmarkAddress = _parentBookmarkAddress;
00503
00504 if ( url.isEmpty() )
00505 {
00506 KMessageBox::error( 0L, i18n("Cannot add bookmark with empty URL."));
00507 return KBookmarkGroup();
00508 }
00509
00510 if ( title.isEmpty() )
00511 title = url;
00512
00513 if ( KBookmarkSettings::self()->m_advancedaddbookmark)
00514 {
00515 KBookmarkEditDialog dlg( title, url, this, KBookmarkEditDialog::InsertionMode, parentBookmarkAddress );
00516 if ( dlg.exec() != KDialogBase::Accepted )
00517 return KBookmarkGroup();
00518 title = dlg.finalTitle();
00519 url = dlg.finalUrl();
00520 parentBookmarkAddress = dlg.finalAddress();
00521 }
00522
00523 KBookmarkGroup parentBookmark;
00524 parentBookmark = findByAddress( parentBookmarkAddress ).toGroup();
00525 Q_ASSERT( !parentBookmark.isNull() );
00526
00527 QString uniqueTitle = pickUnusedTitle( parentBookmark, title, url );
00528 if ( !uniqueTitle.isNull() )
00529 parentBookmark.addBookmark( this, uniqueTitle, KURL( url ));
00530
00531 return parentBookmark;
00532 }
00533
00534
00535 void KBookmarkManager::emitChanged( KBookmarkGroup & group )
00536 {
00537 save();
00538
00539
00540
00541
00542 QByteArray data;
00543 QDataStream ds( data, IO_WriteOnly );
00544 ds << group.address();
00545
00546 emitDCOPSignal("bookmarksChanged(QString)", data);
00547
00548
00549
00550 }
00551
00552 void KBookmarkManager::emitConfigChanged()
00553 {
00554 emitDCOPSignal("bookmarkConfigChanged()", QByteArray());
00555 }
00556
00557 void KBookmarkManager::notifyCompleteChange( QString caller )
00558 {
00559 if (!m_update) return;
00560
00561
00562
00563
00564 parse();
00565
00566
00567 emit changed( "", caller );
00568 }
00569
00570 void KBookmarkManager::notifyConfigChanged()
00571 {
00572 kdDebug() << "reloaded bookmark config!" << endl;
00573 KBookmarkSettings::self()->readSettings();
00574 parse();
00575 }
00576
00577 void KBookmarkManager::notifyChanged( QString groupAddress )
00578 {
00579 if (!m_update) return;
00580
00581
00582
00583 if (callingDcopClient()->senderId() != DCOPClient::mainClient()->appId())
00584 parse();
00585
00586
00587
00588
00589 emit changed( groupAddress, QString::null );
00590 }
00591
00592 bool KBookmarkManager::showNSBookmarks() const
00593 {
00594 return KBookmarkMenu::showDynamicBookmarks("netscape").show;
00595 }
00596
00597 void KBookmarkManager::setShowNSBookmarks( bool show )
00598 {
00599 m_showNSBookmarks = show;
00600 if (this->path() != userBookmarksFile())
00601 return;
00602 KBookmarkMenu::DynMenuInfo info
00603 = KBookmarkMenu::showDynamicBookmarks("netscape");
00604 info.show = show;
00605 KBookmarkMenu::setDynamicBookmarks("netscape", info);
00606 }
00607
00608 void KBookmarkManager::setEditorOptions( const QString& caption, bool browser )
00609 {
00610 dptr()->m_editorCaption = caption;
00611 dptr()->m_browserEditor = browser;
00612 }
00613
00614 void KBookmarkManager::slotEditBookmarks()
00615 {
00616 KProcess proc;
00617 proc << QString::fromLatin1("keditbookmarks");
00618 if (!dptr()->m_editorCaption.isNull())
00619 proc << QString::fromLatin1("--customcaption") << dptr()->m_editorCaption;
00620 if (!dptr()->m_browserEditor)
00621 proc << QString::fromLatin1("--nobrowser");
00622 proc << m_bookmarksFile;
00623 proc.start(KProcess::DontCare);
00624 }
00625
00626 void KBookmarkManager::slotEditBookmarksAtAddress( const QString& address )
00627 {
00628 KProcess proc;
00629 proc << QString::fromLatin1("keditbookmarks")
00630 << QString::fromLatin1("--address") << address
00631 << m_bookmarksFile;
00632 proc.start(KProcess::DontCare);
00633 }
00634
00636
00637 void KBookmarkOwner::openBookmarkURL( const QString& url )
00638 {
00639 (void) new KRun(KURL( url ));
00640 }
00641
00642 void KBookmarkOwner::virtual_hook( int, void* )
00643 { }
00644
00645 bool KBookmarkManager::updateAccessMetadata( const QString & url, bool emitSignal )
00646 {
00647 if (!s_bk_map) {
00648 s_bk_map = new KBookmarkMap(this);
00649 s_bk_map->update();
00650 }
00651
00652 QValueList<KBookmark> list = s_bk_map->find(url);
00653 if ( list.count() == 0 )
00654 return false;
00655
00656 for ( QValueList<KBookmark>::iterator it = list.begin();
00657 it != list.end(); ++it )
00658 (*it).updateAccessMetadata();
00659
00660 if (emitSignal)
00661 emit notifier().updatedAccessMetadata( path(), url );
00662
00663 return true;
00664 }
00665
00666 void KBookmarkManager::updateFavicon( const QString &url, const QString &faviconurl, bool emitSignal )
00667 {
00668 Q_UNUSED(faviconurl);
00669
00670 if (!s_bk_map) {
00671 s_bk_map = new KBookmarkMap(this);
00672 s_bk_map->update();
00673 }
00674
00675 QValueList<KBookmark> list = s_bk_map->find(url);
00676 for ( QValueList<KBookmark>::iterator it = list.begin();
00677 it != list.end(); ++it )
00678 {
00679
00680
00681
00682 }
00683
00684 if (emitSignal)
00685 {
00686
00687
00688 }
00689 }
00690
00691 QString KBookmarkManager::userBookmarksFile()
00692 {
00693 return locateLocal("data", QString::fromLatin1("konqueror/bookmarks.xml"));
00694 }
00695
00696 KBookmarkManager* KBookmarkManager::userBookmarksManager()
00697 {
00698 return KBookmarkManager::managerForFile( userBookmarksFile() );
00699 }
00700
00701 KBookmarkSettings* KBookmarkSettings::s_self = 0;
00702
00703 void KBookmarkSettings::readSettings()
00704 {
00705 KConfig config("kbookmarkrc", false, false);
00706 config.setGroup("Bookmarks");
00707
00708
00709 s_self->m_advancedaddbookmark = config.readBoolEntry("AdvancedAddBookmarkDialog", false);
00710
00711
00712 s_self->m_contextmenu = config.readBoolEntry("ContextMenuActions", true);
00713 s_self->m_quickactions = config.readBoolEntry("QuickActionSubmenu", false);
00714 s_self->m_filteredtoolbar = config.readBoolEntry("FilteredToolbar", false);
00715 }
00716
00717 KBookmarkSettings *KBookmarkSettings::self()
00718 {
00719 if (!s_self)
00720 {
00721 s_self = new KBookmarkSettings;
00722 readSettings();
00723 }
00724 return s_self;
00725 }
00726
00727 #include "kbookmarkmanager.moc"