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();
258 if ( e.tagName() ==
"TEXT" )
260 e.setTagName(
"title");
262 else if ( e.tagName() ==
"SEPARATOR" )
264 e.setTagName(
"separator");
266 else if ( e.tagName() ==
"GROUP" )
268 e.setTagName(
"folder");
269 convertAttribute(e,
"ICON",
"icon");
270 if ( e.hasAttribute(
"TOOLBAR" ) )
272 e.setAttribute(
"toolbar", e.attribute(
"TOOLBAR" ) ==
"1" ?
"yes" :
"no" );
273 e.removeAttribute(
"TOOLBAR" );
276 convertAttribute(e,
"NETSCAPEINFO",
"netscapeinfo");
277 bool open = (e.attribute(
"OPEN") ==
"1");
278 e.removeAttribute(
"OPEN");
279 e.setAttribute(
"folded", open ?
"no" :
"yes");
283 if ( e.tagName() ==
"BOOKMARK" )
285 e.setTagName(
"bookmark");
286 convertAttribute(e,
"ICON",
"icon");
287 convertAttribute(e,
"NETSCAPEINFO",
"netscapeinfo");
288 convertAttribute(e,
"URL",
"href");
289 TQString text = e.text();
290 while ( !e.firstChild().isNull() )
291 e.removeChild(e.firstChild());
292 TQDomElement titleElem = e.ownerDocument().createElement(
"title");
293 e.appendChild( titleElem );
294 titleElem.appendChild( e.ownerDocument().createTextNode( text ) );
297 kdWarning(7043) <<
"Unknown tag " << e.tagName() << endl;
302 void KBookmarkManager::convertAttribute( TQDomElement elem,
const TQString & oldName,
const TQString & newName )
304 if ( elem.hasAttribute( oldName ) )
306 elem.setAttribute( newName, elem.attribute( oldName ) );
307 elem.removeAttribute( oldName );
311 void KBookmarkManager::importDesktopFiles()
314 TQString
path(KGlobal::dirs()->saveLocation(
"data",
"kfm/bookmarks",
true));
315 importer.import(
path );
323 return saveAs( m_bookmarksFile, toolbarCache );
328 kdDebug(7043) <<
"KBookmarkManager::save " << filename << endl;
332 const TQString cacheFilename = filename + TQString::fromLatin1(
".tbcache");
333 if(toolbarCache && !
root().isToolbarGroup())
335 KSaveFile cacheFile( cacheFilename );
336 if ( cacheFile.status() == 0 )
339 TQTextStream stream(&str, IO_WriteOnly);
340 stream <<
root().findToolbar();
341 TQCString cstr = str.utf8();
342 cacheFile.file()->writeBlock( cstr.data(), cstr.length() );
348 TQFile::remove( cacheFilename );
351 KSaveFile file( filename );
352 if ( file.status() == 0 )
354 file.backupFile( file.name(), TQString::null,
".bak" );
356 cstr = internalDocument().toCString();
357 file.file()->writeBlock( cstr.data(), cstr.length() );
362 static int hadSaveError =
false;
364 if ( !hadSaveError ) {
365 TQString error = i18n(
"Unable to save bookmarks in %1. Reported error was: %2. "
366 "This error message will only be shown once. The cause "
367 "of the error needs to be fixed as quickly as possible, "
368 "which is most likely a full hard drive.")
369 .arg(filename).arg(TQString::fromLocal8Bit(strerror(file.status())));
370 if (tqApp->type() != TQApplication::Tty)
371 KMessageBox::error( 0L, error );
373 kdError() << error << endl;
386 kdDebug(7043) <<
"KBookmarkManager::toolbar begin" << endl;
390 kdDebug(7043) <<
"KBookmarkManager::toolbar trying cache" << endl;
391 const TQString cacheFilename = m_bookmarksFile + TQString::fromLatin1(
".tbcache");
392 TQFileInfo bmInfo(m_bookmarksFile);
393 TQFileInfo cacheInfo(cacheFilename);
394 if (m_toolbarDoc.isNull() &&
395 TQFile::exists(cacheFilename) &&
396 bmInfo.lastModified() < cacheInfo.lastModified())
398 kdDebug(7043) <<
"KBookmarkManager::toolbar reading file" << endl;
399 TQFile file( cacheFilename );
401 if ( file.open( IO_ReadOnly ) )
403 m_toolbarDoc = TQDomDocument(
"cache");
404 m_toolbarDoc.setContent( &file );
405 kdDebug(7043) <<
"KBookmarkManager::toolbar opened" << endl;
408 if (!m_toolbarDoc.isNull())
410 kdDebug(7043) <<
"KBookmarkManager::toolbar returning element" << endl;
411 TQDomElement elem = m_toolbarDoc.firstChild().toElement();
418 TQDomElement elem =
root().findToolbar();
428 KBookmark result =
root();
430 TQStringList addresses = TQStringList::split(TQRegExp(
"[/+]"),address);
432 for ( TQStringList::Iterator it = addresses.begin() ; it != addresses.end() ; )
434 bool append = ((*it) ==
"+");
435 uint number = (*it).toUInt();
436 Q_ASSERT(result.isGroup());
438 KBookmark bk = group.
first(), lbk = bk;
439 for ( uint i = 0 ; ( (i<number) || append ) && !bk.isNull() ; ++i ) {
445 int shouldBeGroup = !bk.isGroup() && (it != addresses.end());
446 if ( tolerant && ( bk.isNull() || shouldBeGroup ) ) {
447 if (!lbk.isNull()) result = lbk;
454 if (result.isNull()) {
455 kdWarning() <<
"KBookmarkManager::findByAddress: couldn't find item " << address << endl;
463 const TQString &title,
const TQString &url
466 KBookmark ch = parentBookmark.
first();
468 TQString uniqueTitle = title;
471 while ( !ch.isNull() )
473 if ( uniqueTitle == ch.text() )
476 if ( url != ch.url().url() )
478 uniqueTitle = title + TQString(
" (%1)").arg(++count);
480 ch = parentBookmark.
first();
486 return TQString::null;
489 ch = parentBookmark.
next( ch );
491 }
while ( !ch.isNull() );
497 const TQString & _url,
const TQString & _title,
498 const TQString & _parentBookmarkAddress
501 TQString title = _title;
502 TQString parentBookmarkAddress = _parentBookmarkAddress;
506 KMessageBox::error( 0L, i18n(
"Cannot add bookmark with empty URL."));
510 if ( title.isEmpty() )
513 if ( KBookmarkSettings::self()->m_advancedaddbookmark)
515 KBookmarkEditDialog dlg( title, url,
this, KBookmarkEditDialog::InsertionMode, parentBookmarkAddress );
516 if ( dlg.exec() != KDialogBase::Accepted )
518 title = dlg.finalTitle();
519 url = dlg.finalUrl();
520 parentBookmarkAddress = dlg.finalAddress();
524 parentBookmark =
findByAddress( parentBookmarkAddress ).toGroup();
525 Q_ASSERT( !parentBookmark.isNull() );
527 TQString uniqueTitle = pickUnusedTitle( parentBookmark, title, url );
528 if ( !uniqueTitle.isNull() )
529 parentBookmark.
addBookmark(
this, uniqueTitle, KURL( url ));
531 return parentBookmark;
543 TQDataStream ds( data, IO_WriteOnly );
544 ds << group.address();
546 emitDCOPSignal(
"bookmarksChanged(TQString)", data);
552 void KBookmarkManager::emitConfigChanged()
554 emitDCOPSignal(
"bookmarkConfigChanged()", TQByteArray());
559 if (!m_update)
return;
570 void KBookmarkManager::notifyConfigChanged()
572 kdDebug() <<
"reloaded bookmark config!" << endl;
573 KBookmarkSettings::self()->readSettings();
579 if (!m_update)
return;
583 if (callingDcopClient()->senderId() != DCOPClient::mainClient()->appId())
589 emit
changed( groupAddress, TQString::null );
599 m_showNSBookmarks = show;
610 dptr()->m_editorCaption = caption;
611 dptr()->m_browserEditor = browser;
614 void KBookmarkManager::slotEditBookmarks()
617 proc << TQString::fromLatin1(
"keditbookmarks");
618 if (!dptr()->m_editorCaption.isNull())
619 proc << TQString::fromLatin1(
"--customcaption") << dptr()->m_editorCaption;
620 if (!dptr()->m_browserEditor)
621 proc << TQString::fromLatin1(
"--nobrowser");
622 proc << m_bookmarksFile;
623 proc.start(KProcess::DontCare);
626 void KBookmarkManager::slotEditBookmarksAtAddress(
const TQString& address )
629 proc << TQString::fromLatin1(
"keditbookmarks")
630 << TQString::fromLatin1(
"--address") << address
632 proc.start(KProcess::DontCare);
639 (void)
new KRun(KURL( url ));
642 void KBookmarkOwner::virtual_hook(
int,
void* )
648 s_bk_map =
new KBookmarkMap(
this);
652 TQValueList<KBookmark> list = s_bk_map->find(url);
653 if ( list.count() == 0 )
656 for ( TQValueList<KBookmark>::iterator it = list.begin();
657 it != list.end(); ++it )
658 (*it).updateAccessMetadata();
666 void KBookmarkManager::updateFavicon(
const TQString &url,
const TQString &faviconurl,
bool emitSignal )
668 Q_UNUSED(faviconurl);
671 s_bk_map =
new KBookmarkMap(
this);
675 TQValueList<KBookmark> list = s_bk_map->find(url);
676 for ( TQValueList<KBookmark>::iterator it = list.begin();
677 it != list.end(); ++it )
693 return locateLocal(
"data", TQString::fromLatin1(
"konqueror/bookmarks.xml"));
701 KBookmarkSettings* KBookmarkSettings::s_self = 0;
703 void KBookmarkSettings::readSettings()
705 KConfig config(
"kbookmarkrc",
false,
false);
706 config.setGroup(
"Bookmarks");
709 s_self->m_advancedaddbookmark = config.readBoolEntry(
"AdvancedAddBookmarkDialog",
false);
712 s_self->m_contextmenu = config.readBoolEntry(
"ContextMenuActions",
true);
713 s_self->m_quickactions = config.readBoolEntry(
"QuickActionSubmenu",
false);
714 s_self->m_filteredtoolbar = config.readBoolEntry(
"FilteredToolbar",
false);
717 KBookmarkSettings *KBookmarkSettings::self()
721 s_self =
new KBookmarkSettings;
727 #include "kbookmarkmanager.moc"