kbookmarkmanager.cc Source File (kio Library)

| # kio Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# kbookmarkmanager.cc

    00001 /* This file is part of the KDE libraries
    00002    Copyright (C) 2000 David Faure <faure@kde.org>
    00003
    00004    This library is free software; you can redistribute it and/or
    00005    modify it under the terms of the GNU Library General Public
    00006    License version 2 as published by the Free Software Foundation.
    00007
    00008    This library is distributed in the hope that it will be useful,
    00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
    00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00011    Library General Public License for more details.
    00012
    00013    You should have received a copy of the GNU Library General Public License
    00014    along with this library; see the file COPYING.LIB.  If not, write to
    00015    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00016    Boston, MA 02111-1307, USA.
    00017 */
    00018
    00019 #include "kbookmarkmanager.h"
    00020 #include "kbookmarkimporter.h"
    00021 #include <kdebug.h>
    00022 #include <krun.h>
    00023 #include <kstandarddirs.h>
    00024 #include <ksavefile.h>
    00025 #include <qtextstream.h>
    00026 #include <qregexp.h>
    00027 #include <kmessagebox.h>
    00028 #include <kprocess.h>
    00029 #include <klocale.h>
    00030 #include <kapplication.h>
    00031 #include <dcopclient.h>
    00032 #include <qfile.h>
    00033 #include <qfileinfo.h>
    00034 #include <qtextstream.h>
    00035 #include <kstaticdeleter.h>
    00036
    00037 QPtrList<KBookmarkManager>* KBookmarkManager::s_pSelf = 0L;
    00038 KStaticDeleter<QPtrList<KBookmarkManager> > sdbm;
    00039
    00040 KBookmarkManager* KBookmarkManager::managerForFile( const QString& bookmarksFile, bool bImportDesktopFiles )
    00041 {
    00042     if ( !s_pSelf ) {
    00043         sdbm.setObject( s_pSelf, new QPtrList<KBookmarkManager> );
    00044         s_pSelf->setAutoDelete( true );
    00045     }
    00046     QPtrListIterator<KBookmarkManager> it ( *s_pSelf );
    00047     for ( ; it.current() ; ++it )
    00048         if ( it.current()->path() == bookmarksFile )
    00049             return it.current();
    00050
    00051     KBookmarkManager* mgr = new KBookmarkManager( bookmarksFile, bImportDesktopFiles );
    00052     s_pSelf->append( mgr );
    00053     return mgr;
    00054 }
    00055
    00056 KBookmarkManager::KBookmarkManager( const QString & bookmarksFile, bool bImportDesktopFiles )
    00057     : DCOPObject(QCString("KBookmarkManager-")+bookmarksFile.utf8()), m_doc("xbel"), m_docIsLoaded(false)
    00058 {
    00059     m_toolbarDoc.clear();
    00060
    00061     m_update = true;
    00062     m_showNSBookmarks = true;
    00063
    00064     Q_ASSERT( !bookmarksFile.isEmpty() );
    00065     m_bookmarksFile = bookmarksFile;
    00066
    00067     if ( !QFile::exists(m_bookmarksFile) )
    00068     {
    00069         // First time we use this class
    00070         QDomElement topLevel = m_doc.createElement("xbel");
    00071         m_doc.appendChild( topLevel );
    00072         if ( bImportDesktopFiles )
    00073             importDesktopFiles();
    00074         m_docIsLoaded = true;
    00075     }
    00076 }
    00077
    00078 KBookmarkManager::~KBookmarkManager()
    00079 {
    00080     if ( s_pSelf )
    00081         s_pSelf->removeRef( this );
    00082 }
    00083
    00084 void KBookmarkManager::setUpdate(bool update)
    00085 {
    00086     m_update = update;
    00087 }
    00088
    00089 const QDomDocument &KBookmarkManager::internalDocument() const
    00090 {
    00091     if(!m_docIsLoaded)
    00092     {
    00093         parse();
    00094         m_toolbarDoc.clear();
    00095     }
    00096     return m_doc;
    00097 }
    00098
    00099 void KBookmarkManager::parse() const
    00100 {
    00101     m_docIsLoaded = true;
    00102     //kdDebug(1203) << "KBookmarkManager::parse " << m_bookmarksFile << endl;
    00103     QFile file( m_bookmarksFile );
    00104     if ( !file.open( IO_ReadOnly ) )
    00105     {
    00106         kdWarning() << "Can't open " << m_bookmarksFile << endl;
    00107         return;
    00108     }
    00109     m_doc = QDomDocument("xbel");
    00110     m_doc.setContent( &file );
    00111
    00112     QDomElement docElem = m_doc.documentElement();
    00113     if ( docElem.isNull() )
    00114         kdWarning() << "KBookmarkManager::parse : can't parse " << m_bookmarksFile << endl;
    00115     else
    00116     {
    00117         QString mainTag = docElem.tagName();
    00118         if ( mainTag == "BOOKMARKS" )
    00119         {
    00120             kdWarning() << "Old style bookmarks found. Calling convertToXBEL." << endl;
    00121             docElem.setTagName("xbel");
    00122             if ( docElem.hasAttribute( "HIDE_NSBK" ) && m_showNSBookmarks ) // non standard either, but we need it
    00123             {
    00124                 docElem.setAttribute( "hide_nsbk", docElem.attribute( "HIDE_NSBK" ) == "1" ? "yes" : "no" );
    00125                 docElem.removeAttribute( "HIDE_NSBK" );
    00126             }
    00127
    00128             convertToXBEL( docElem );
    00129             save();
    00130         }
    00131         else if ( mainTag != "xbel" )
    00132             kdWarning() << "KBookmarkManager::parse : unknown main tag " << mainTag << endl;
    00133     }
    00134
    00135     file.close();
    00136 }
    00137
    00138 void KBookmarkManager::convertToXBEL( QDomElement & group )
    00139 {
    00140     QDomNode n = group.firstChild();
    00141     while( !n.isNull() )
    00142     {
    00143         QDomElement e = n.toElement();
    00144         if ( !e.isNull() )
    00145             if ( e.tagName() == "TEXT" )
    00146             {
    00147                 e.setTagName("title");
    00148             }
    00149             else if ( e.tagName() == "SEPARATOR" )
    00150             {
    00151                 e.setTagName("separator"); // so close...
    00152             }
    00153             else if ( e.tagName() == "GROUP" )
    00154             {
    00155                 e.setTagName("folder");
    00156                 convertAttribute(e, "ICON","icon"); // non standard, but we need it
    00157                 if ( e.hasAttribute( "TOOLBAR" ) ) // non standard either, but we need it
    00158                 {
    00159                     e.setAttribute( "toolbar", e.attribute( "TOOLBAR" ) == "1" ? "yes" : "no" );
    00160                     e.removeAttribute( "TOOLBAR" );
    00161                 }
    00162
    00163                 convertAttribute(e, "NETSCAPEINFO","netscapeinfo"); // idem
    00164                 bool open = (e.attribute("OPEN") == "1");
    00165                 e.removeAttribute("OPEN");
    00166                 e.setAttribute("folded", open ? "no" : "yes");
    00167                 convertToXBEL( e );
    00168             }
    00169             else
    00170                 if ( e.tagName() == "BOOKMARK" )
    00171                 {
    00172                     e.setTagName("bookmark"); // so much difference :-)
    00173                     convertAttribute(e, "ICON","icon"); // non standard, but we need it
    00174                     convertAttribute(e, "NETSCAPEINFO","netscapeinfo"); // idem
    00175                     convertAttribute(e, "URL","href");
    00176                     QString text = e.text();
    00177                     while ( !e.firstChild().isNull() ) // clean up the old contained text
    00178                         e.removeChild(e.firstChild());
    00179                     QDomElement titleElem = e.ownerDocument().createElement("title");
    00180                     e.appendChild( titleElem ); // should be the only child anyway
    00181                     titleElem.appendChild( e.ownerDocument().createTextNode( text ) );
    00182                 }
    00183                 else
    00184                     kdWarning(1203) << "Unknown tag " << e.tagName() << endl;
    00185         n = n.nextSibling();
    00186     }
    00187 }
    00188
    00189 void KBookmarkManager::convertAttribute( QDomElement elem, const QString & oldName, const QString & newName )
    00190 {
    00191     if ( elem.hasAttribute( oldName ) )
    00192     {
    00193         elem.setAttribute( newName, elem.attribute( oldName ) );
    00194         elem.removeAttribute( oldName );
    00195     }
    00196 }
    00197
    00198 void KBookmarkManager::importDesktopFiles()
    00199 {
    00200     KBookmarkImporter importer( const_cast<QDomDocument *>(&internalDocument()) );
    00201     QString path(KGlobal::dirs()->saveLocation("data", "kfm/bookmarks", true));
    00202     importer.import( path );
    00203     //kdDebug(1203) << internalDocument().toCString() << endl;
    00204
    00205     save();
    00206 }
    00207
    00208 bool KBookmarkManager::save( bool toolbarCache ) const
    00209 {
    00210     return saveAs( m_bookmarksFile, toolbarCache );
    00211 }
    00212
    00213 bool KBookmarkManager::saveAs( const QString & filename, bool toolbarCache ) const
    00214 {
    00215     //kdDebug(1203) << "KBookmarkManager::save " << filename << endl;
    00216
    00217     // Save the bookmark toolbar folder for quick loading
    00218     // but only when it will actually make things quicker
    00219     const QString cacheFilename = filename + QString::fromLatin1(".tbcache");
    00220     if(toolbarCache && !root().isToolbarGroup())
    00221     {
    00222         KSaveFile cacheFile( cacheFilename );
    00223         if ( cacheFile.status() == 0 )
    00224         {
    00225             QString str;
    00226             QTextStream stream(&str, IO_WriteOnly);
    00227             stream << root().findToolbar();
    00228             QCString cstr = str.utf8();
    00229             cacheFile.file()->writeBlock( cstr.data(), cstr.length() );
    00230             cacheFile.close();
    00231         }
    00232     }
    00233     else // remove any (now) stale cache
    00234     {
    00235         QFile::remove( cacheFilename );
    00236     }
    00237
    00238     KSaveFile file( filename );
    00239
    00240     if ( file.status() != 0 )
    00241     {
    00242         KMessageBox::error( 0L, i18n("Couldn't save bookmarks in %1. %2").arg(filename).arg(strerror(file.status())) );
    00243         return false;
    00244     }
    00245     QCString cstr = internalDocument().toCString(); // is in UTF8
    00246     file.file()->writeBlock( cstr.data(), cstr.length() );
    00247     if (!file.close())
    00248     {
    00249         KMessageBox::error( 0L, i18n("Couldn't save bookmarks in %1. %2").arg(filename).arg(strerror(file.status())) );
    00250         return false;
    00251     }
    00252     return true;
    00253 }
    00254
    00255 KBookmarkGroup KBookmarkManager::root() const
    00256 {
    00257     return KBookmarkGroup(internalDocument().documentElement());
    00258 }
    00259
    00260 KBookmarkGroup KBookmarkManager::toolbar()
    00261 {
    00262     kdDebug(1203) << "KBookmarkManager::toolbar begin" << endl;
    00263     // Only try to read from a toolbar cache if the full document isn't loaded
    00264     if(!m_docIsLoaded)
    00265     {
    00266         kdDebug(1203) << "KBookmarkManager::toolbar trying cache" << endl;
    00267         const QString cacheFilename = m_bookmarksFile + QString::fromLatin1(".tbcache");
    00268         QFileInfo bmInfo(m_bookmarksFile);
    00269         QFileInfo cacheInfo(cacheFilename);
    00270         if (m_toolbarDoc.isNull() &&
    00271             QFile::exists(cacheFilename) &&
    00272             bmInfo.lastModified() < cacheInfo.lastModified())
    00273         {
    00274             kdDebug(1203) << "KBookmarkManager::toolbar reading file" << endl;
    00275             QFile file( cacheFilename );
    00276
    00277             if ( file.open( IO_ReadOnly ) )
    00278             {
    00279                 m_toolbarDoc = QDomDocument("cache");
    00280                 m_toolbarDoc.setContent( &file );
    00281                 kdDebug(1203) << "KBookmarkManager::toolbar opened" << endl;
    00282             }
    00283         }
    00284         if (!m_toolbarDoc.isNull())
    00285         {
    00286             kdDebug(1203) << "KBookmarkManager::toolbar returning element" << endl;
    00287             QDomElement elem = m_toolbarDoc.firstChild().toElement();
    00288             return KBookmarkGroup(elem);
    00289         }
    00290     }
    00291
    00292     // Fallback to the normal way if there is no cache or if the bookmark file
    00293     // is already loaded
    00294     QDomElement elem = root().findToolbar();
    00295     if (elem.isNull())
    00296         return root(); // Root is the bookmark toolbar if none has been set.
    00297     else
    00298         return KBookmarkGroup(root().findToolbar());
    00299 }
    00300
    00301 KBookmark KBookmarkManager::findByAddress( const QString & address, bool tolerant )
    00302 {
    00303     //kdDebug(1203) << "KBookmarkManager::findByAddress " << address << endl;
    00304     KBookmark result = root();
    00305     // The address is something like /5/10/2+
    00306     QStringList addresses = QStringList::split(QRegExp("[/+]"),address);
    00307     // kdWarning() << addresses.join(",") << endl;
    00308     for ( QStringList::Iterator it = addresses.begin() ; it != addresses.end() ; )
    00309     {
    00310        bool append = ((*it) == "+");
    00311        uint number = (*it).toUInt();
    00312        Q_ASSERT(result.isGroup());
    00313        KBookmarkGroup group = result.toGroup();
    00314        KBookmark bk = group.first(), lbk = bk; // last non-null bookmark
    00315        for ( uint i = 0 ; ( (i<number) || append ) && !bk.isNull() ; ++i ) {
    00316            lbk = bk;
    00317            bk = group.next(bk);
    00318          //kdWarning() << i << endl;
    00319        }
    00320        it++;
    00321        int shouldBeGroup = !bk.isGroup() && (it != addresses.end());
    00322        if ( tolerant && ( bk.isNull() || shouldBeGroup ) ) {
    00323           if (!lbk.isNull()) result = lbk;
    00324           //kdWarning() << "break" << endl;
    00325           break;
    00326        }
    00327        //kdWarning() << "found section" << endl;
    00328        result = bk;
    00329     }
    00330     if (result.isNull()) {
    00331        kdWarning() << "KBookmarkManager::findByAddress: couldn't find item " << address << endl;
    00332        Q_ASSERT(!tolerant);
    00333     }
    00334     //kdWarning() << "found " << result.address() << endl;
    00335     return result;
    00336  }
    00337
    00338 void KBookmarkManager::emitChanged( KBookmarkGroup & group )
    00339 {
    00340     save();
    00341
    00342     // Tell the other processes too
    00343     //kdDebug(1203) << "KBookmarkManager::emitChanged : broadcasting change " << group.address() << endl;
    00344     QByteArray data;
    00345     QDataStream stream( data, IO_WriteOnly );
    00346     stream << group.address();
    00347     QCString objId( "KBookmarkManager-" );
    00348     objId += m_bookmarksFile.utf8();
    00349     kapp->dcopClient()->send( "*", objId, "notifyChanged(QString)", data );
    00350
    00351     // We do get our own broadcast, so no need for this anymore
    00352     //emit changed( group );
    00353 }
    00354
    00355 void KBookmarkManager::notifyCompleteChange( QString caller ) // DCOP call
    00356 {
    00357     if (!m_update) return;
    00358
    00359     //kdDebug(1203) << "KBookmarkManager::notifyCompleteChange" << endl;
    00360     // The bk editor tells us we should reload everything
    00361     // Reparse
    00362     parse();
    00363     // Tell our GUI
    00364     // (emit with group == "" to directly mark the root menu as dirty)
    00365     emit changed( "", caller );
    00366     // Also tell specifically about the toolbar - unless it's the root as well
    00367     KBookmarkGroup tbGroup = toolbar();
    00368     if (!tbGroup.isNull() && !tbGroup.groupAddress().isEmpty())
    00369         emit changed( tbGroup.groupAddress(), caller );
    00370 }
    00371
    00372 void KBookmarkManager::notifyChanged( QString groupAddress ) // DCOP call
    00373 {
    00374     if (!m_update) return;
    00375
    00376     // Reparse (the whole file, no other choice)
    00377     // Of course, if we are the emitter this is a bit stupid....
    00378     parse();
    00379
    00380     //kdDebug(1203) << "KBookmarkManager::notifyChanged " << groupAddress << endl;
    00381     //KBookmarkGroup group = findByAddress( groupAddress ).toGroup();
    00382     //Q_ASSERT(!group.isNull());
    00383     emit changed( groupAddress, QString::null );
    00384 }
    00385
    00386 bool KBookmarkManager::showNSBookmarks() const
    00387 {
    00388     // The attr name is HIDE, so that the default is to show them
    00389     return root().internalElement().attribute("hide_nsbk") != "yes";
    00390 }
    00391
    00392 void KBookmarkManager::setShowNSBookmarks( bool show )
    00393 {
    00394     m_showNSBookmarks = show;
    00395     root().internalElement().setAttribute("hide_nsbk", show ? "no" : "yes");
    00396 }
    00397
    00398 void KBookmarkManager::slotEditBookmarks()
    00399 {
    00400     KProcess proc;
    00401     proc << QString::fromLatin1("keditbookmarks") << m_bookmarksFile;
    00402     proc.start(KProcess::DontCare);
    00403 }
    00404
    00406
    00407 void KBookmarkOwner::openBookmarkURL(const QString& url)
    00408 {
    00409   (void) new KRun(url);
    00410 }
    00411
    00412 void KBookmarkOwner::virtual_hook( int, void* )
    00413 { /*BASE::virtual_hook( id, data );*/ }
    00414
    00415 #include "kbookmarkmanager.moc"

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:13:11 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001