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"