kbookmarkmanager.cc
00001 // -*- c-basic-offset:4; indent-tabs-mode:nil -*- 00002 // vim: set ts=4 sts=4 sw=4 et: 00003 /* This file is part of the KDE libraries 00004 Copyright (C) 2000 David Faure <faure@kde.org> 00005 Copyright (C) 2003 Alexander Kellett <lypanov@kde.org> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License version 2 as published by the Free Software Foundation. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 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 // TODO - clean this stuff up by just using the above dptrtemplate? 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 // add bookmark to url map 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 // principally used for filtered toolbars 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(); // strange ;-) 00159 00160 m_update = false; // TODO - make it read/write 00161 m_showNSBookmarks = true; 00162 00163 m_bookmarksFile = QString::null; // AK - check all codepaths for this one 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 // TODO - enable this via some sort of api and fix the above DCOPObject script somehow 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 //kdDebug(7043) << "KBookmarkManager::parse " << m_bookmarksFile << endl; 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 ) // non standard either, but we need it 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"); // so close... 00265 } 00266 else if ( e.tagName() == "GROUP" ) 00267 { 00268 e.setTagName("folder"); 00269 convertAttribute(e, "ICON","icon"); // non standard, but we need it 00270 if ( e.hasAttribute( "TOOLBAR" ) ) // non standard either, but we need it 00271 { 00272 e.setAttribute( "toolbar", e.attribute( "TOOLBAR" ) == "1" ? "yes" : "no" ); 00273 e.removeAttribute( "TOOLBAR" ); 00274 } 00275 00276 convertAttribute(e, "NETSCAPEINFO","netscapeinfo"); // idem 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"); // so much difference :-) 00286 convertAttribute(e, "ICON","icon"); // non standard, but we need it 00287 convertAttribute(e, "NETSCAPEINFO","netscapeinfo"); // idem 00288 convertAttribute(e, "URL","href"); 00289 QString text = e.text(); 00290 while ( !e.firstChild().isNull() ) // clean up the old contained text 00291 e.removeChild(e.firstChild()); 00292 QDomElement titleElem = e.ownerDocument().createElement("title"); 00293 e.appendChild( titleElem ); // should be the only child anyway 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 //kdDebug(7043) << internalDocument().toCString() << endl; 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 // Save the bookmark toolbar folder for quick loading 00331 // but only when it will actually make things quicker 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 // remove any (now) stale cache 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(); // is in UTF8 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 // Only try to read from a toolbar cache if the full document isn't loaded 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 // Fallback to the normal way if there is no cache or if the bookmark file 00417 // is already loaded 00418 QDomElement elem = root().findToolbar(); 00419 if (elem.isNull()) 00420 return root(); // Root is the bookmark toolbar if none has been set. 00421 else 00422 return KBookmarkGroup(root().findToolbar()); 00423 } 00424 00425 KBookmark KBookmarkManager::findByAddress( const QString & address, bool tolerant ) 00426 { 00427 //kdDebug(7043) << "KBookmarkManager::findByAddress " << address << endl; 00428 KBookmark result = root(); 00429 // The address is something like /5/10/2+ 00430 QStringList addresses = QStringList::split(QRegExp("[/+]"),address); 00431 // kdWarning() << addresses.join(",") << endl; 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; // last non-null bookmark 00439 for ( uint i = 0 ; ( (i<number) || append ) && !bk.isNull() ; ++i ) { 00440 lbk = bk; 00441 bk = group.next(bk); 00442 //kdWarning() << i << endl; 00443 } 00444 it++; 00445 int shouldBeGroup = !bk.isGroup() && (it != addresses.end()); 00446 if ( tolerant && ( bk.isNull() || shouldBeGroup ) ) { 00447 if (!lbk.isNull()) result = lbk; 00448 //kdWarning() << "break" << endl; 00449 break; 00450 } 00451 //kdWarning() << "found section" << endl; 00452 result = bk; 00453 } 00454 if (result.isNull()) { 00455 kdWarning() << "KBookmarkManager::findByAddress: couldn't find item " << address << endl; 00456 Q_ASSERT(!tolerant); 00457 } 00458 //kdWarning() << "found " << result.address() << endl; 00459 return result; 00460 } 00461 00462 static QString pickUnusedTitle( KBookmarkGroup parentBookmark, 00463 const QString &title, const QString &url 00464 ) { 00465 // If this title is already used, we'll try to find something unused. 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 // Title already used ! 00476 if ( url != ch.url().url() ) 00477 { 00478 uniqueTitle = title + QString(" (%1)").arg(++count); 00479 // New title -> restart search from the beginning 00480 ch = parentBookmark.first(); 00481 break; 00482 } 00483 else 00484 { 00485 // this exact URL already exists 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( /*KDE4 const*/ KBookmarkGroup & group ) 00536 { 00537 save(); 00538 00539 // Tell the other processes too 00540 // kdDebug(7043) << "KBookmarkManager::emitChanged : broadcasting change " << group.address() << endl; 00541 00542 QByteArray data; 00543 QDataStream ds( data, IO_WriteOnly ); 00544 ds << group.address(); 00545 00546 emitDCOPSignal("bookmarksChanged(QString)", data); 00547 00548 // We do get our own broadcast, so no need for this anymore 00549 //emit changed( group ); 00550 } 00551 00552 void KBookmarkManager::emitConfigChanged() 00553 { 00554 emitDCOPSignal("bookmarkConfigChanged()", QByteArray()); 00555 } 00556 00557 void KBookmarkManager::notifyCompleteChange( QString caller ) // DCOP call 00558 { 00559 if (!m_update) return; 00560 00561 //kdDebug(7043) << "KBookmarkManager::notifyCompleteChange" << endl; 00562 // The bk editor tells us we should reload everything 00563 // Reparse 00564 parse(); 00565 // Tell our GUI 00566 // (emit where group is "" to directly mark the root menu as dirty) 00567 emit changed( "", caller ); 00568 } 00569 00570 void KBookmarkManager::notifyConfigChanged() // DCOP call 00571 { 00572 kdDebug() << "reloaded bookmark config!" << endl; 00573 KBookmarkSettings::self()->readSettings(); 00574 parse(); // reload, and thusly recreate the menus 00575 } 00576 00577 void KBookmarkManager::notifyChanged( QString groupAddress ) // DCOP call 00578 { 00579 if (!m_update) return; 00580 00581 // Reparse (the whole file, no other choice) 00582 // if someone else notified us 00583 if (callingDcopClient()->senderId() != DCOPClient::mainClient()->appId()) 00584 parse(); 00585 00586 //kdDebug(7043) << "KBookmarkManager::notifyChanged " << groupAddress << endl; 00587 //KBookmarkGroup group = findByAddress( groupAddress ).toGroup(); 00588 //Q_ASSERT(!group.isNull()); 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 { /*BASE::virtual_hook( id, data );*/ } 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 // TODO - update favicon data based on faviconurl 00680 // but only when the previously used icon 00681 // isn't a manually set one. 00682 } 00683 00684 if (emitSignal) 00685 { 00686 // TODO 00687 // emit notifier().updatedFavicon( path(), url, faviconurl ); 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 // add bookmark dialog usage - no reparse 00709 s_self->m_advancedaddbookmark = config.readBoolEntry("AdvancedAddBookmarkDialog", false); 00710 00711 // these three alter the menu, therefore all need a reparse 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"