22 #include "kbookmarkmanager.h"
23 #include "kbookmarkmenu.h"
24 #include "kbookmarkmenu_p.h"
25 #include "kbookmarkimporter.h"
28 #include <kstandarddirs.h>
29 #include <ksavefile.h>
32 #include <kmessagebox.h>
35 #include <kapplication.h>
36 #include <dcopclient.h>
38 #include <tqfileinfo.h>
39 #include <tqtextstream.h>
40 #include <kstaticdeleter.h>
41 #include <tqptrstack.h>
43 #include "dptrtemplate.h"
45 class KBookmarkManagerPrivate :
public dPtrTemplate<KBookmarkManager, KBookmarkManagerPrivate> {
47 KBookmarkManagerPrivate()
48 { m_browserEditor =
true; }
49 TQString m_editorCaption;
52 template<> TQPtrDict<KBookmarkManagerPrivate>* dPtrTemplate<KBookmarkManager, KBookmarkManagerPrivate>::d_ptr = 0;
54 KBookmarkManagerPrivate* KBookmarkManager::dptr()
const {
55 return KBookmarkManagerPrivate::d(
this );
59 TQPtrList<KBookmarkManager>* KBookmarkManager::s_pSelf;
60 static KStaticDeleter<TQPtrList<KBookmarkManager> > sdbm;
66 TQValueList<KBookmark> find(
const TQString &url )
const
67 {
return m_bk_map[url]; }
69 virtual void visit(
const KBookmark &);
73 typedef TQValueList<KBookmark> KBookmarkList;
74 TQMap<TQString, KBookmarkList> m_bk_map;
78 static KBookmarkMap *s_bk_map = 0;
84 void KBookmarkMap::update()
91 void KBookmarkMap::visit(
const KBookmark &bk)
93 if (!bk.isSeparator()) {
95 m_bk_map[bk.internalElement().attribute(
"href")].append(bk);
103 sdbm.setObject( s_pSelf,
new TQPtrList<KBookmarkManager> );
104 s_pSelf->setAutoDelete(
true );
106 TQPtrListIterator<KBookmarkManager> it ( *s_pSelf );
107 for ( ; it.current() ; ++it )
108 if ( it.current()->path() == bookmarksFile )
112 s_pSelf->append( mgr );
120 sdbm.setObject( s_pSelf,
new TQPtrList<KBookmarkManager> );
121 s_pSelf->setAutoDelete(
true );
124 s_pSelf->append( mgr );
128 #define PI_DATA "version=\"1.0\" encoding=\"UTF-8\""
131 : DCOPObject(TQCString(
"KBookmarkManager-")+bookmarksFile.utf8()), m_doc(
"xbel"), m_docIsLoaded(false)
133 m_toolbarDoc.clear();
136 m_showNSBookmarks =
true;
138 Q_ASSERT( !bookmarksFile.isEmpty() );
139 m_bookmarksFile = bookmarksFile;
141 if ( !TQFile::exists(m_bookmarksFile) )
143 TQDomElement topLevel = m_doc.createElement(
"xbel");
144 m_doc.appendChild( topLevel );
145 m_doc.insertBefore( m_doc.createProcessingInstruction(
"xml", PI_DATA), topLevel );
146 if ( bImportDesktopFiles )
147 importDesktopFiles();
148 m_docIsLoaded =
true;
151 connectDCOPSignal(0, objId(),
"bookmarksChanged(TQString)",
"notifyChanged(TQString)",
false);
152 connectDCOPSignal(0, objId(),
"bookmarkConfigChanged()",
"notifyConfigChanged()",
false);
156 : DCOPObject(TQCString(
"KBookmarkManager-generated")), m_doc(
"xbel"), m_docIsLoaded(true)
158 m_toolbarDoc.clear();
161 m_showNSBookmarks =
true;
163 m_bookmarksFile = TQString::null;
165 TQDomElement topLevel = m_doc.createElement(
"xbel");
166 m_doc.appendChild( topLevel );
167 m_doc.insertBefore( m_doc.createProcessingInstruction(
"xml", PI_DATA), topLevel );
171 connectDCOPSignal(0, objId(),
"bookmarksChanged(TQString)",
"notifyChanged(TQString)",
false);
172 connectDCOPSignal(0, objId(),
"bookmarkConfigChanged()",
"notifyConfigChanged()",
false);
179 s_pSelf->removeRef(
this );
187 const TQDomDocument &KBookmarkManager::internalDocument()
const
192 m_toolbarDoc.clear();
198 void KBookmarkManager::parse()
const
200 m_docIsLoaded =
true;
202 TQFile file( m_bookmarksFile );
203 if ( !file.open( IO_ReadOnly ) )
205 kdWarning() <<
"Can't open " << m_bookmarksFile << endl;
208 m_doc = TQDomDocument(
"xbel");
209 m_doc.setContent( &file );
211 TQDomElement docElem = m_doc.documentElement();
212 if ( docElem.isNull() )
213 kdWarning() <<
"KBookmarkManager::parse : can't parse " << m_bookmarksFile << endl;
216 TQString mainTag = docElem.tagName();
217 if ( mainTag ==
"BOOKMARKS" )
219 kdWarning() <<
"Old style bookmarks found. Calling convertToXBEL." << endl;
220 docElem.setTagName(
"xbel");
221 if ( docElem.hasAttribute(
"HIDE_NSBK" ) && m_showNSBookmarks )
223 docElem.setAttribute(
"hide_nsbk", docElem.attribute(
"HIDE_NSBK" ) ==
"1" ?
"yes" :
"no" );
224 docElem.removeAttribute(
"HIDE_NSBK" );
227 convertToXBEL( docElem );
230 else if ( mainTag !=
"xbel" )
231 kdWarning() <<
"KBookmarkManager::parse : unknown main tag " << mainTag << endl;
233 TQDomNode n = m_doc.documentElement().previousSibling();
234 if ( n.isProcessingInstruction() )
236 TQDomProcessingInstruction pi = n.toProcessingInstruction();
237 pi.parentNode().removeChild(pi);
240 TQDomProcessingInstruction pi;
241 pi = m_doc.createProcessingInstruction(
"xml", PI_DATA );
242 m_doc.insertBefore( pi, docElem );
247 s_bk_map =
new KBookmarkMap( const_cast<KBookmarkManager*>(
this ) );
251 void KBookmarkManager::convertToXBEL( TQDomElement & group )
253 TQDomNode n = group.firstChild();
256 TQDomElement e = n.toElement();
259 if ( e.tagName() ==
"TEXT" )
261 e.setTagName(
"title");
263 else if ( e.tagName() ==
"SEPARATOR" )
265 e.setTagName(
"separator");
267 else if ( e.tagName() ==
"GROUP" )
269 e.setTagName(
"folder");
270 convertAttribute(e,
"ICON",
"icon");
271 if ( e.hasAttribute(
"TOOLBAR" ) )
273 e.setAttribute(
"toolbar", e.attribute(
"TOOLBAR" ) ==
"1" ?
"yes" :
"no" );
274 e.removeAttribute(
"TOOLBAR" );
277 convertAttribute(e,
"NETSCAPEINFO",
"netscapeinfo");
278 bool open = (e.attribute(
"OPEN") ==
"1");
279 e.removeAttribute(
"OPEN");
280 e.setAttribute(
"folded", open ?
"no" :
"yes");
285 if ( e.tagName() ==
"BOOKMARK" )
287 e.setTagName(
"bookmark");
288 convertAttribute(e,
"ICON",
"icon");
289 convertAttribute(e,
"NETSCAPEINFO",
"netscapeinfo");
290 convertAttribute(e,
"URL",
"href");
291 TQString text = e.text();
292 while ( !e.firstChild().isNull() )
293 e.removeChild(e.firstChild());
294 TQDomElement titleElem = e.ownerDocument().createElement(
"title");
295 e.appendChild( titleElem );
296 titleElem.appendChild( e.ownerDocument().createTextNode( text ) );
300 kdWarning(7043) <<
"Unknown tag " << e.tagName() << endl;
308 void KBookmarkManager::convertAttribute( TQDomElement elem,
const TQString & oldName,
const TQString & newName )
310 if ( elem.hasAttribute( oldName ) )
312 elem.setAttribute( newName, elem.attribute( oldName ) );
313 elem.removeAttribute( oldName );
317 void KBookmarkManager::importDesktopFiles()
320 TQString
path(KGlobal::dirs()->saveLocation(
"data",
"kfm/bookmarks",
true));
321 importer.import(
path );
329 return saveAs( m_bookmarksFile, toolbarCache );
334 kdDebug(7043) <<
"KBookmarkManager::save " << filename << endl;
338 const TQString cacheFilename = filename + TQString::fromLatin1(
".tbcache");
339 if(toolbarCache && !
root().isToolbarGroup())
341 KSaveFile cacheFile( cacheFilename );
342 if ( cacheFile.status() == 0 )
345 TQTextStream stream(&str, IO_WriteOnly);
346 stream <<
root().findToolbar();
347 TQCString cstr = str.utf8();
348 cacheFile.file()->writeBlock( cstr.data(), cstr.length() );
354 TQFile::remove( cacheFilename );
357 KSaveFile file( filename );
358 if ( file.status() == 0 )
360 file.backupFile( file.name(), TQString::null,
".bak" );
362 cstr = internalDocument().toCString();
363 file.file()->writeBlock( cstr.data(), cstr.length() );
368 static int hadSaveError =
false;
370 if ( !hadSaveError ) {
371 TQString error = i18n(
"Unable to save bookmarks in %1. Reported error was: %2. "
372 "This error message will only be shown once. The cause "
373 "of the error needs to be fixed as quickly as possible, "
374 "which is most likely a full hard drive.")
375 .arg(filename).arg(TQString::fromLocal8Bit(strerror(file.status())));
376 if (tqApp->type() != TQApplication::Tty)
377 KMessageBox::error( 0L, error );
379 kdError() << error << endl;
392 kdDebug(7043) <<
"KBookmarkManager::toolbar begin" << endl;
396 kdDebug(7043) <<
"KBookmarkManager::toolbar trying cache" << endl;
397 const TQString cacheFilename = m_bookmarksFile + TQString::fromLatin1(
".tbcache");
398 TQFileInfo bmInfo(m_bookmarksFile);
399 TQFileInfo cacheInfo(cacheFilename);
400 if (m_toolbarDoc.isNull() &&
401 TQFile::exists(cacheFilename) &&
402 bmInfo.lastModified() < cacheInfo.lastModified())
404 kdDebug(7043) <<
"KBookmarkManager::toolbar reading file" << endl;
405 TQFile file( cacheFilename );
407 if ( file.open( IO_ReadOnly ) )
409 m_toolbarDoc = TQDomDocument(
"cache");
410 m_toolbarDoc.setContent( &file );
411 kdDebug(7043) <<
"KBookmarkManager::toolbar opened" << endl;
414 if (!m_toolbarDoc.isNull())
416 kdDebug(7043) <<
"KBookmarkManager::toolbar returning element" << endl;
417 TQDomElement elem = m_toolbarDoc.firstChild().toElement();
424 TQDomElement elem =
root().findToolbar();
434 KBookmark result =
root();
436 TQStringList addresses = TQStringList::split(TQRegExp(
"[/+]"),address);
438 for ( TQStringList::Iterator it = addresses.begin() ; it != addresses.end() ; )
440 bool append = ((*it) ==
"+");
441 uint number = (*it).toUInt();
442 Q_ASSERT(result.isGroup());
444 KBookmark bk = group.
first(), lbk = bk;
445 for ( uint i = 0 ; ( (i<number) || append ) && !bk.isNull() ; ++i ) {
451 int shouldBeGroup = !bk.isGroup() && (it != addresses.end());
452 if ( tolerant && ( bk.isNull() || shouldBeGroup ) ) {
453 if (!lbk.isNull()) result = lbk;
460 if (result.isNull()) {
461 kdWarning() <<
"KBookmarkManager::findByAddress: couldn't find item " << address << endl;
469 const TQString &title,
const TQString &url
472 KBookmark ch = parentBookmark.
first();
474 TQString uniqueTitle = title;
477 while ( !ch.isNull() )
479 if ( uniqueTitle == ch.text() )
482 if ( url != ch.url().url() )
484 uniqueTitle = title + TQString(
" (%1)").arg(++count);
486 ch = parentBookmark.
first();
492 return TQString::null;
495 ch = parentBookmark.
next( ch );
497 }
while ( !ch.isNull() );
503 const TQString & _url,
const TQString & _title,
504 const TQString & _parentBookmarkAddress
507 TQString title = _title;
508 TQString parentBookmarkAddress = _parentBookmarkAddress;
512 KMessageBox::error( 0L, i18n(
"Cannot add bookmark with empty URL."));
516 if ( title.isEmpty() )
519 if ( KBookmarkSettings::self()->m_advancedaddbookmark)
521 KBookmarkEditDialog dlg( title, url,
this, KBookmarkEditDialog::InsertionMode, parentBookmarkAddress );
522 if ( dlg.exec() != KDialogBase::Accepted )
524 title = dlg.finalTitle();
525 url = dlg.finalUrl();
526 parentBookmarkAddress = dlg.finalAddress();
530 parentBookmark =
findByAddress( parentBookmarkAddress ).toGroup();
531 Q_ASSERT( !parentBookmark.isNull() );
533 TQString uniqueTitle = pickUnusedTitle( parentBookmark, title, url );
534 if ( !uniqueTitle.isNull() )
535 parentBookmark.
addBookmark(
this, uniqueTitle, KURL( url ));
537 return parentBookmark;
549 TQDataStream ds( data, IO_WriteOnly );
550 ds << group.address();
552 emitDCOPSignal(
"bookmarksChanged(TQString)", data);
558 void KBookmarkManager::emitConfigChanged()
560 emitDCOPSignal(
"bookmarkConfigChanged()", TQByteArray());
565 if (!m_update)
return;
576 void KBookmarkManager::notifyConfigChanged()
578 kdDebug() <<
"reloaded bookmark config!" << endl;
579 KBookmarkSettings::self()->readSettings();
585 if (!m_update)
return;
589 if (callingDcopClient()->senderId() != DCOPClient::mainClient()->appId())
595 emit
changed( groupAddress, TQString::null );
605 m_showNSBookmarks = show;
616 dptr()->m_editorCaption = caption;
617 dptr()->m_browserEditor = browser;
620 void KBookmarkManager::slotEditBookmarks()
623 proc << TQString::fromLatin1(
"keditbookmarks");
624 if (!dptr()->m_editorCaption.isNull())
625 proc << TQString::fromLatin1(
"--customcaption") << dptr()->m_editorCaption;
626 if (!dptr()->m_browserEditor)
627 proc << TQString::fromLatin1(
"--nobrowser");
628 proc << m_bookmarksFile;
629 proc.start(KProcess::DontCare);
632 void KBookmarkManager::slotEditBookmarksAtAddress(
const TQString& address )
635 proc << TQString::fromLatin1(
"keditbookmarks")
636 << TQString::fromLatin1(
"--address") << address
638 proc.start(KProcess::DontCare);
645 (void)
new KRun(KURL( url ));
648 void KBookmarkOwner::virtual_hook(
int,
void* )
654 s_bk_map =
new KBookmarkMap(
this);
658 TQValueList<KBookmark> list = s_bk_map->find(url);
659 if ( list.count() == 0 )
662 for ( TQValueList<KBookmark>::iterator it = list.begin();
663 it != list.end(); ++it )
664 (*it).updateAccessMetadata();
672 void KBookmarkManager::updateFavicon(
const TQString &url,
const TQString &faviconurl,
bool emitSignal )
674 Q_UNUSED(faviconurl);
677 s_bk_map =
new KBookmarkMap(
this);
681 TQValueList<KBookmark> list = s_bk_map->find(url);
682 for ( TQValueList<KBookmark>::iterator it = list.begin();
683 it != list.end(); ++it )
699 return locateLocal(
"data", TQString::fromLatin1(
"konqueror/bookmarks.xml"));
707 KBookmarkSettings* KBookmarkSettings::s_self = 0;
709 void KBookmarkSettings::readSettings()
711 KConfig config(
"kbookmarkrc",
false,
false);
712 config.setGroup(
"Bookmarks");
715 s_self->m_advancedaddbookmark = config.readBoolEntry(
"AdvancedAddBookmarkDialog",
false);
718 s_self->m_contextmenu = config.readBoolEntry(
"ContextMenuActions",
true);
719 s_self->m_quickactions = config.readBoolEntry(
"QuickActionSubmenu",
false);
720 s_self->m_filteredtoolbar = config.readBoolEntry(
"FilteredToolbar",
false);
723 KBookmarkSettings *KBookmarkSettings::self()
727 s_self =
new KBookmarkSettings;
733 #include "kbookmarkmanager.moc"
A class for importing the previous bookmarks (desktop files) Separated from KBookmarkManager to save ...
bool updateAccessMetadata(const TQString &url, bool emitSignal=true)
Update access time stamps for a given url.
KBookmarkNotifier & notifier()
Access to bookmark notifier, for emitting signals.
KBookmark addBookmark(KBookmarkManager *mgr, const KBookmark &bm, bool emitSignal=true)
Create a new bookmark, as the last child of this group Don't forget to use KBookmarkManager::self()->...
This class implements the reading/writing of bookmarks in XML.
static KBookmarkManager * managerForFile(const TQString &bookmarksFile, bool bImportDesktopFiles=true)
This static function will return an instance of the KBookmarkManager, responsible for the given bookm...
void setShowNSBookmarks(bool show)
Shows an extra menu for NS bookmarks.
void setUpdate(bool update)
Set the update flag.
ASYNC notifyCompleteChange(TQString caller)
Reparse the whole bookmarks file and notify about the change (Called by the bookmark editor) ...
void emitChanged(KBookmarkGroup &group)
Saves the bookmark file and notifies everyone.
bool save(bool toolbarCache=true) const
Save the bookmarks to the default konqueror XML file on disk.
virtual void openBookmarkURL(const TQString &_url)
This function is called if the user selects a bookmark.
KBookmarkGroup toolbar()
This returns the root of the toolbar menu.
static KBookmarkManager * userBookmarksManager()
Returns a pointer to the users main bookmark collection.
bool saveAs(const TQString &filename, bool toolbarCache=true) const
Save the bookmarks to the given XML file on disk.
TQString path()
This will return the path that this manager is using to read the bookmarks.
static TQString userBookmarksFile()
Returns the path to the user's main bookmark collection file.
void setEditorOptions(const TQString &caption, bool browser)
Set options with which slotEditBookmarks called keditbookmarks this can be used to change the appeara...
KBookmark findByAddress(const TQString &address, bool tolerate=false)
KBookmarkGroup addBookmarkDialog(const TQString &_url, const TQString &_title, const TQString &_parentBookmarkAddress=TQString::null)
KBookmarkGroup root() const
This will return the root bookmark.
void changed(const TQString &groupAddress, const TQString &caller)
Signals that the group (or any of its children) with the address groupAddress (e.g.
~KBookmarkManager()
Destructor.
ASYNC notifyChanged(TQString groupAddress)
Emit the changed signal for the group whose address is given.
bool showNSBookmarks() const
KBookmark next(const KBookmark ¤t) const
Return the next sibling of a child bookmark of this group.
KBookmark first() const
Return the first child bookmark of this group.