25 #include <QtCore/QFile>
26 #include <QtCore/QFileInfo>
27 #include <QtCore/QProcess>
28 #include <QtCore/QRegExp>
29 #include <QtCore/QTextStream>
30 #include <QtDBus/QtDBus>
31 #include <QtGui/QApplication>
47 #define BOOKMARK_CHANGE_NOTIFY_INTERFACE "org.kde.KIO.KBookmarkManager"
49 class KBookmarkManagerList :
public QList<KBookmarkManager *>
52 ~KBookmarkManagerList() {
63 KBookmarkMap() : m_mapNeedsUpdate(true) {}
64 void setNeedsUpdate() { m_mapNeedsUpdate =
true; }
67 {
return m_bk_map.value(url); }
73 typedef QList<KBookmark> KBookmarkList;
75 bool m_mapNeedsUpdate;
80 if (m_mapNeedsUpdate) {
81 m_mapNeedsUpdate =
false;
89 void KBookmarkMap::visit(
const KBookmark &bk)
99 class KBookmarkManager::Private
102 Private(
bool bDocIsloaded,
const QString &dbusObjectName =
QString())
104 , m_dbusObjectName(dbusObjectName)
105 , m_docIsLoaded(bDocIsloaded)
107 , m_dialogAllowed(true)
109 , m_browserEditor(false)
110 , m_typeExternal(false)
118 mutable QDomDocument m_doc;
119 mutable QDomDocument m_toolbarDoc;
122 mutable bool m_docIsLoaded;
124 bool m_dialogAllowed;
127 bool m_browserEditor;
141 for ( KBookmarkManagerList::ConstIterator bmit = s_pSelf->constBegin(), bmend = s_pSelf->constEnd();
142 bmit != bmend; ++bmit ) {
143 if ( (*bmit)->path() == bookmarksFile )
154 QReadLocker readLock(&s_pSelf->lock);
161 QWriteLocker writeLock(&s_pSelf->lock);
168 s_pSelf->append( mgr );
176 QReadLocker readLock(&s_pSelf->lock);
183 QWriteLocker writeLock(&s_pSelf->lock);
190 s_pSelf->append( mgr );
199 s_pSelf->append( mgr );
203 #define PI_DATA "version=\"1.0\" encoding=\"UTF-8\""
207 QDomElement topLevel = doc.createElement(
"xbel");
208 topLevel.setAttribute(
"xmlns:mime",
"http://www.freedesktop.org/standards/shared-mime-info");
209 topLevel.setAttribute(
"xmlns:bookmark",
"http://www.freedesktop.org/standards/desktop-bookmarks");
210 topLevel.setAttribute(
"xmlns:kdepriv",
"http://www.kde.org/kdepriv");
211 doc.appendChild( topLevel );
212 doc.insertBefore( doc.createProcessingInstruction(
"xml",
PI_DATA), topLevel );
216 KBookmarkManager::KBookmarkManager(
const QString & bookmarksFile,
const QString & dbusObjectName)
217 : d(new Private(false, dbusObjectName))
219 if(dbusObjectName.isNull())
220 if ( QFile::exists(d->m_bookmarksFile) )
223 init(
"/KBookmarkManager/"+d->m_dbusObjectName );
227 Q_ASSERT( !bookmarksFile.isEmpty() );
228 d->m_bookmarksFile = bookmarksFile;
230 if ( !QFile::exists(d->m_bookmarksFile) )
233 topLevel.setAttribute(
"dbusName", dbusObjectName);
234 d->m_docIsLoaded =
true;
238 KBookmarkManager::KBookmarkManager(
const QString & bookmarksFile)
239 : d(new Private(false))
242 d->m_typeExternal =
true;
245 Q_ASSERT( !bookmarksFile.isEmpty() );
246 d->m_bookmarksFile = bookmarksFile;
248 if ( !QFile::exists(d->m_bookmarksFile) )
256 d->m_docIsLoaded =
true;
260 d->m_kDirWatch->
addFile(d->m_bookmarksFile);
261 QObject::connect( d->m_kDirWatch, SIGNAL(dirty(
const QString&)),
262 this, SLOT(slotFileChanged(
const QString&)));
263 QObject::connect( d->m_kDirWatch, SIGNAL(created(
const QString&)),
264 this, SLOT(slotFileChanged(
const QString&)));
265 QObject::connect( d->m_kDirWatch, SIGNAL(deleted(
const QString&)),
266 this, SLOT(slotFileChanged(
const QString&)));
267 kDebug(7043) <<
"starting KDirWatch for " << d->m_bookmarksFile;
270 KBookmarkManager::KBookmarkManager( )
271 : d(new Private(true))
273 init(
"/KBookmarkManager/generated" );
279 void KBookmarkManager::init(
const QString& dbusPath )
283 if ( dbusPath !=
"/KBookmarkManager/" && dbusPath !=
"/KBookmarkManager/generated")
286 QDBusConnection::sessionBus().registerObject( dbusPath,
this );
295 void KBookmarkManager::slotFileChanged(
const QString& path)
297 if (path == d->m_bookmarksFile)
299 kDebug(7043) <<
"file changed (KDirWatch) " <<
path ;
310 if (!s_pSelf.isDestroyed()) {
311 s_pSelf->removeAll(
this);
319 return d->m_dialogAllowed;
324 d->m_dialogAllowed = enable;
325 d->m_dialogParent = parent;
330 d->m_update = update;
335 if(!d->m_docIsLoaded)
338 d->m_toolbarDoc.clear();
344 void KBookmarkManager::parse()
const
346 d->m_docIsLoaded =
true;
348 QFile file( d->m_bookmarksFile );
349 if ( !file.open( QIODevice::ReadOnly ) )
351 kWarning() <<
"Can't open " << d->m_bookmarksFile;
354 d->m_doc = QDomDocument(
"xbel");
355 d->m_doc.setContent( &file );
357 if ( d->m_doc.documentElement().isNull() )
359 kWarning() <<
"KBookmarkManager::parse : main tag is missing, creating default " << d->m_bookmarksFile;
360 QDomElement element = d->m_doc.createElement(
"xbel");
361 d->m_doc.appendChild(element);
364 QDomElement docElem = d->m_doc.documentElement();
366 QString mainTag = docElem.tagName();
367 if ( mainTag !=
"xbel" )
368 kWarning() <<
"KBookmarkManager::parse : unknown main tag " << mainTag;
370 if(d->m_dbusObjectName.isNull())
372 d->m_dbusObjectName = docElem.attribute(
"dbusName");
374 else if(docElem.attribute(
"dbusName") != d->m_dbusObjectName)
376 docElem.setAttribute(
"dbusName", d->m_dbusObjectName);
380 QDomNode n = d->m_doc.documentElement().previousSibling();
381 if ( n.isProcessingInstruction() )
383 QDomProcessingInstruction pi = n.toProcessingInstruction();
384 pi.parentNode().removeChild(pi);
387 QDomProcessingInstruction pi;
388 pi = d->m_doc.createProcessingInstruction(
"xml",
PI_DATA );
389 d->m_doc.insertBefore( pi, docElem );
393 d->m_map.setNeedsUpdate();
398 return saveAs( d->m_bookmarksFile, toolbarCache );
403 kDebug(7043) <<
"KBookmarkManager::save " << filename;
407 const QString cacheFilename = filename + QLatin1String(
".tbcache");
408 if(toolbarCache && !
root().isToolbarGroup())
411 if ( cacheFile.
open() )
414 QTextStream stream(&str, QIODevice::WriteOnly);
416 const QByteArray cstr = str.toUtf8();
417 cacheFile.write( cstr.data(), cstr.length() );
423 QFile::remove( cacheFilename );
430 QTextStream stream(&file);
431 stream.setCodec( QTextCodec::codecForName(
"UTF-8" ) );
440 static int hadSaveError =
false;
442 if ( !hadSaveError ) {
443 QString err =
i18n(
"Unable to save bookmarks in %1. Reported error was: %2. "
444 "This error message will only be shown once. The cause "
445 "of the error needs to be fixed as quickly as possible, "
446 "which is most likely a full hard drive.",
449 if (d->m_dialogAllowed && qApp->type() != QApplication::Tty && QThread::currentThread() == qApp->thread())
452 kError() <<
QString(
"Unable to save bookmarks in %1. File reported the following error-code: %2.").arg(filename).arg(file.
error());
461 return d->m_bookmarksFile;
471 kDebug(7043) <<
"KBookmarkManager::toolbar begin";
473 if(!d->m_docIsLoaded)
475 kDebug(7043) <<
"KBookmarkManager::toolbar trying cache";
476 const QString cacheFilename = d->m_bookmarksFile + QLatin1String(
".tbcache");
477 QFileInfo bmInfo(d->m_bookmarksFile);
478 QFileInfo cacheInfo(cacheFilename);
479 if (d->m_toolbarDoc.isNull() &&
480 QFile::exists(cacheFilename) &&
481 bmInfo.lastModified() < cacheInfo.lastModified())
483 kDebug(7043) <<
"KBookmarkManager::toolbar reading file";
484 QFile file( cacheFilename );
486 if ( file.open( QIODevice::ReadOnly ) )
488 d->m_toolbarDoc = QDomDocument(
"cache");
489 d->m_toolbarDoc.setContent( &file );
490 kDebug(7043) <<
"KBookmarkManager::toolbar opened";
493 if (!d->m_toolbarDoc.isNull())
495 kDebug(7043) <<
"KBookmarkManager::toolbar returning element";
496 QDomElement elem = d->m_toolbarDoc.firstChild().toElement();
520 const QStringList addresses = address.split(QRegExp(
"[/+]"),QString::SkipEmptyParts);
522 for ( QStringList::const_iterator it = addresses.begin() ; it != addresses.end() ; )
524 bool append = ((*it) ==
"+");
525 uint
number = (*it).toUInt();
529 for ( uint i = 0 ; ( (i<
number) || append ) && !bk.
isNull() ; ++i ) {
539 kWarning() <<
"KBookmarkManager::findByAddress: couldn't find item " << address;
574 kDebug(7043) <<
"KBookmarkManager::notifyCompleteChange";
585 kDebug() <<
"reloaded bookmark config!";
593 kDebug() <<
"KBookmarkManager::notifyChanged ( "<<groupAddress<<
")";
599 if (msg.service() != QDBusConnection::sessionBus().baseService())
610 d->m_editorCaption = caption;
611 d->m_browserEditor = browser;
617 if ( !d->m_editorCaption.isEmpty() )
618 args << QLatin1String(
"--customcaption") << d->m_editorCaption;
619 if ( !d->m_browserEditor )
620 args << QLatin1String(
"--nobrowser");
621 if( !d->m_dbusObjectName.isEmpty() )
622 args << QLatin1String(
"--dbusObjectName") << d->m_dbusObjectName;
623 args << d->m_bookmarksFile;
624 QProcess::startDetached(
"keditbookmarks", args);
630 if ( !d->m_editorCaption.isEmpty() )
631 args << QLatin1String(
"--customcaption") << d->m_editorCaption;
632 if ( !d->m_browserEditor )
633 args << QLatin1String(
"--nobrowser");
634 if( !d->m_dbusObjectName.isEmpty() )
635 args << QLatin1String(
"--dbusObjectName") << d->m_dbusObjectName;
636 args << QLatin1String(
"--address") << address
637 << d->m_bookmarksFile;
638 QProcess::startDetached(
"keditbookmarks", args);
644 d->m_map.update(
this);
645 QList<KBookmark>
list = d->m_map.find(url);
646 if ( list.count() == 0 )
649 for ( QList<KBookmark>::iterator it = list.begin();
650 it != list.end(); ++it )
651 (*it).updateAccessMetadata();
658 d->m_map.update(
this);
659 QList<KBookmark>
list = d->m_map.find(url);
660 for ( QList<KBookmark>::iterator it = list.begin();
661 it != list.end(); ++it )
674 return bookmarkManager;
722 #include "kbookmarkmanager.moc"