kio Library API Documentation

kbookmark.cc

00001 // -*- c-basic-offset:4; indent-tabs-mode:nil -*-
00002 // vim: set ts=4 sts=4 sw=4 et:
00003 /* This file is part of the KDE libraries
00004    Copyright (C) 2000 David Faure <faure@kde.org>
00005    Copyright (C) 2003 Alexander Kellett <lypanov@kde.org>
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Library General Public
00009    License version 2 as published by the Free Software Foundation.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019    Boston, MA 02111-1307, USA.
00020 */
00021 
00022 #include "kbookmark.h"
00023 #include <qvaluestack.h>
00024 #include <kdebug.h>
00025 #include <kmimetype.h>
00026 #include <kstringhandler.h>
00027 #include <kinputdialog.h>
00028 #include <kglobal.h>
00029 #include <klocale.h>
00030 #include <assert.h>
00031 #include <kapplication.h>
00032 #include <dcopclient.h>
00033 #include <kbookmarkmanager.h>
00034 
00035 KBookmarkGroup::KBookmarkGroup()
00036  : KBookmark( QDomElement() )
00037 {
00038 }
00039 
00040 KBookmarkGroup::KBookmarkGroup( QDomElement elem )
00041  : KBookmark(elem)
00042 {
00043 }
00044 
00045 QString KBookmarkGroup::groupAddress() const
00046 {
00047     if (m_address.isEmpty())
00048         m_address = address();
00049     return m_address;
00050 }
00051 
00052 bool KBookmarkGroup::isOpen() const
00053 {
00054     return element.attribute("folded") == "no"; // default is: folded
00055 }
00056 
00057 KBookmark KBookmarkGroup::first() const
00058 {
00059     return KBookmark( nextKnownTag( element.firstChild().toElement(), true ) );
00060 }
00061 
00062 KBookmark KBookmarkGroup::previous( const KBookmark & current ) const
00063 {
00064     return KBookmark( nextKnownTag( current.element.previousSibling().toElement(), false ) );
00065 }
00066 
00067 KBookmark KBookmarkGroup::next( const KBookmark & current ) const
00068 {
00069     return KBookmark( nextKnownTag( current.element.nextSibling().toElement(), true ) );
00070 }
00071 
00072 QDomElement KBookmarkGroup::nextKnownTag( QDomElement start, bool goNext ) const
00073 {
00074     static const QString & bookmark = KGlobal::staticQString("bookmark");
00075     static const QString & folder = KGlobal::staticQString("folder");
00076     static const QString & separator = KGlobal::staticQString("separator");
00077     QDomElement elem = start;
00078     while ( !elem.isNull() )
00079     {
00080         QString tag = elem.tagName();
00081         if (tag == folder || tag == bookmark || tag == separator)
00082             break;
00083         if (goNext)
00084             elem = elem.nextSibling().toElement();
00085         else
00086             elem = elem.previousSibling().toElement();
00087     }
00088     return elem;
00089 }
00090 
00091 KBookmarkGroup KBookmarkGroup::createNewFolder( KBookmarkManager* mgr, const QString & text, bool emitSignal )
00092 {
00093     QString txt( text );
00094     if ( text.isEmpty() )
00095     {
00096         bool ok;
00097         QString caption = parentGroup().fullText().isEmpty() ?
00098                       i18n( "Create New Bookmark Folder" ) :
00099                       i18n( "Create New Bookmark Folder in %1" )
00100                       .arg( parentGroup().text() );
00101         txt = KInputDialog::getText( caption, i18n( "New folder:" ),
00102                       QString::null, &ok );
00103         if ( !ok )
00104             return KBookmarkGroup();
00105     }
00106 
00107     Q_ASSERT(!element.isNull());
00108     QDomDocument doc = element.ownerDocument();
00109     QDomElement groupElem = doc.createElement( "folder" );
00110     element.appendChild( groupElem );
00111     QDomElement textElem = doc.createElement( "title" );
00112     groupElem.appendChild( textElem );
00113     textElem.appendChild( doc.createTextNode( txt ) );
00114 
00115     KBookmarkGroup grp(groupElem);
00116 
00117     if (emitSignal) 
00118         emit mgr->notifier().createdNewFolder(
00119                                 mgr->path(), grp.fullText(), 
00120                                 grp.address() );
00121 
00122     return grp;
00123 
00124 }
00125 
00126 KBookmark KBookmarkGroup::createNewSeparator()
00127 {
00128     Q_ASSERT(!element.isNull());
00129     QDomDocument doc = element.ownerDocument();
00130     Q_ASSERT(!doc.isNull());
00131     QDomElement sepElem = doc.createElement( "separator" );
00132     element.appendChild( sepElem );
00133     return KBookmark(sepElem);
00134 }
00135 
00136 bool KBookmarkGroup::moveItem( const KBookmark & item, const KBookmark & after )
00137 {
00138     QDomNode n;
00139     if ( !after.isNull() )
00140         n = element.insertAfter( item.element, after.element );
00141     else // first child
00142     {
00143         if ( element.firstChild().isNull() ) // Empty element -> set as real first child
00144             n = element.insertBefore( item.element, QDomElement() );
00145 
00146         // we have to skip everything up to the first valid child
00147         QDomElement firstChild = nextKnownTag(element.firstChild().toElement(), true);
00148         if ( !firstChild.isNull() )
00149             n = element.insertBefore( item.element, firstChild );
00150         else
00151         {
00152             // No real first child -> append after the <title> etc.
00153             n = element.appendChild( item.element );
00154         }
00155     }
00156     return (!n.isNull());
00157 }
00158 
00159 KBookmark KBookmarkGroup::addBookmark( KBookmarkManager* mgr, const QString & text, const KURL & url, const QString & icon, bool emitSignal )
00160 {
00161     //kdDebug(7043) << "KBookmarkGroup::addBookmark " << text << " into " << m_address << endl;
00162     QDomDocument doc = element.ownerDocument();
00163     QDomElement elem = doc.createElement( "bookmark" );
00164     element.appendChild( elem );
00165     elem.setAttribute( "href", url.url( 0, 106 ) ); // write utf8 URL (106 is mib enum for utf8)
00166     QString _icon = icon;
00167     if ( _icon.isEmpty() )
00168         _icon = KMimeType::iconForURL( url );
00169     elem.setAttribute( "icon", _icon );
00170 
00171     QDomElement textElem = doc.createElement( "title" );
00172     elem.appendChild( textElem );
00173     textElem.appendChild( doc.createTextNode( text ) );
00174 
00175     KBookmark bk(elem);
00176 
00177     if (emitSignal)
00178         emit mgr->notifier().addedBookmark(
00179                                  mgr->path(), url.url(),
00180                                  text, bk.address(), icon );
00181 
00182     return bk;
00183 }
00184 
00185 void KBookmarkGroup::deleteBookmark( KBookmark bk )
00186 {
00187     element.removeChild( bk.element );
00188 }
00189 
00190 bool KBookmarkGroup::isToolbarGroup() const
00191 {
00192     return ( element.attribute("toolbar") == "yes" );
00193 }
00194 
00195 QDomElement KBookmarkGroup::findToolbar() const
00196 {
00197     if ( element.attribute("toolbar") == "yes" )
00198         return element;
00199     QDomElement e = element.firstChild().toElement();
00200     for ( ; !e.isNull() ; e = e.nextSibling().toElement() )
00201     {
00202         // Search among the "folder" children only
00203         if ( e.tagName() == "folder" )
00204         {
00205             if ( e.attribute("toolbar") == "yes" )
00206                 return e;
00207             else
00208             {
00209                 QDomElement result = KBookmarkGroup(e).findToolbar();
00210                 if (!result.isNull())
00211                     return result;
00212             }
00213         }
00214     }
00215     return QDomElement();
00216 }
00217 
00218 QValueList<KURL> KBookmarkGroup::groupUrlList() const
00219 {
00220     QValueList<KURL> urlList;
00221     for ( KBookmark bm = first(); !bm.isNull(); bm = next(bm) )
00222     {
00223         if ( bm.isSeparator() || bm.isGroup() )
00224            continue;
00225         urlList << bm.url();
00226     }
00227     return urlList;
00228 }
00229 
00231 
00232 bool KBookmark::isGroup() const
00233 {
00234     QString tag = element.tagName();
00235     return ( tag == "folder"
00236              || tag == "xbel" ); // don't forget the toplevel group
00237 }
00238 
00239 bool KBookmark::isSeparator() const
00240 {
00241     return (element.tagName() == "separator");
00242 }
00243 
00244 bool KBookmark::hasParent() const
00245 {
00246     QDomElement parent = element.parentNode().toElement();
00247     return !parent.isNull();
00248 }
00249 
00250 QString KBookmark::text() const
00251 {
00252     return KStringHandler::csqueeze( fullText() );
00253 }
00254 
00255 QString KBookmark::fullText() const
00256 {
00257     if (isSeparator())
00258         return i18n("--- separator ---");
00259 
00260     return element.namedItem("title").toElement().text();
00261 }
00262 
00263 KURL KBookmark::url() const
00264 {
00265     return KURL(element.attribute("href"), 106); // Decode it from utf8 (106 is mib enum for utf8)
00266 }
00267 
00268 QString KBookmark::icon() const
00269 {
00270     QString icon = element.attribute("icon");
00271     if ( icon.isEmpty() )
00272         // Default icon depends on URL for bookmarks, and is default directory
00273         // icon for groups.
00274         if ( isGroup() )
00275             icon = "bookmark_folder";
00276         else
00277             if ( isSeparator() )
00278                 icon = "eraser"; // whatever
00279             else
00280                 icon = KMimeType::iconForURL( url() );
00281     return icon;
00282 }
00283 
00284 KBookmarkGroup KBookmark::parentGroup() const
00285 {
00286     return KBookmarkGroup( element.parentNode().toElement() );
00287 }
00288 
00289 KBookmarkGroup KBookmark::toGroup() const
00290 {
00291     Q_ASSERT( isGroup() );
00292     return KBookmarkGroup(element);
00293 }
00294 
00295 QString KBookmark::address() const
00296 {
00297     if ( element.tagName() == "xbel" )
00298         return ""; // not QString::null !
00299     else
00300     {
00301         // Use keditbookmarks's DEBUG_ADDRESSES flag to debug this code :)
00302         if (!hasParent())
00303         {
00304             Q_ASSERT(hasParent());
00305             return "ERROR"; // Avoid an infinite loop
00306         }
00307         KBookmarkGroup group = parentGroup();
00308         QString parentAddress = group.address();
00309         uint counter = 0;
00310         // Implementation note: we don't use QDomNode's childNode list because we
00311         // would have to skip "TEXT", which KBookmarkGroup already does for us.
00312         for ( KBookmark bk = group.first() ; !bk.isNull() ; bk = group.next(bk), ++counter )
00313         {
00314             if ( bk.element == element )
00315                 return parentAddress + "/" + QString::number(counter);
00316         }
00317         kdWarning() << "KBookmark::address : this can't happen!  " << parentAddress << endl;
00318         return "ERROR";
00319     }
00320 }
00321 
00322 KBookmark KBookmark::standaloneBookmark( const QString & text, const KURL & url, const QString & icon )
00323 {
00324     QDomDocument doc("xbel");
00325     QDomElement elem = doc.createElement("xbel");
00326     doc.appendChild( elem );
00327     KBookmarkGroup grp( elem );
00328     grp.addBookmark( 0L, text, url, icon, false );
00329     return grp.first();
00330 }
00331 
00332 static QDomNode cd_or_create(QDomNode node, QString name)
00333 {
00334     QDomNode subnode = node.namedItem(name);
00335     if (subnode.isNull()) 
00336     {
00337         subnode = node.ownerDocument().createElement(name);
00338         node.appendChild(subnode);
00339     }
00340     return subnode;
00341 }
00342 
00343 static QDomText get_or_create_text(QDomNode node)
00344 {
00345     QDomNode subnode = node.firstChild();
00346     if (subnode.isNull()) 
00347     {
00348         subnode = node.ownerDocument().createTextNode("");
00349         node.appendChild(subnode);
00350     }
00351     return subnode.toText();
00352 }
00353 
00354 void KBookmark::updateAccessMetadata()
00355 {
00356     kdDebug(7043) << "KBookmark::updateAccessMetadata " << address() << " " << url().prettyURL() << endl;
00357 
00358     QDomNode subnode = cd_or_create(internalElement(), "info");
00359     subnode = cd_or_create(subnode, "metadata");
00360 
00361     uint timet = QDateTime::currentDateTime().toTime_t();
00362 
00363     QDomNode item = cd_or_create(subnode, "time_added");
00364     QDomText domtext = get_or_create_text(item);
00365     if (domtext.data().isEmpty()) 
00366         domtext.setData(QString::number(timet));
00367 
00368     item = cd_or_create(subnode, "time_visited");
00369     domtext = get_or_create_text(item);
00370     domtext.setData(QString::number(timet));
00371 
00372     item = cd_or_create(subnode, "visit_count"); // TODO use spec'ed name
00373     domtext = get_or_create_text(item);
00374     QString countStr = domtext.data();
00375     bool ok;
00376     int currentCount = countStr.toInt(&ok);
00377     if (!ok)
00378         currentCount = 0;
00379     currentCount++;
00380     domtext.setData(QString::number(currentCount));
00381 
00382     // TODO - for 3.3 - time_modified
00383 }
00384 
00385 void KBookmarkGroupTraverser::traverse(const KBookmarkGroup &root)
00386 {
00387     // non-recursive bookmark iterator
00388     QValueStack<KBookmarkGroup> stack;
00389     stack.push(root);
00390     KBookmark bk = stack.top().first();
00391     for (;;) {
00392         if (bk.isNull())
00393         {
00394             if (stack.isEmpty()) 
00395                 return;
00396             if (stack.count() > 1)
00397                 visitLeave(stack.top());
00398             bk = stack.pop();
00399             bk = stack.top().next(bk);
00400             if (bk.isNull())
00401                 continue;
00402         } 
00403 
00404         if (bk.isGroup()) 
00405         {
00406             KBookmarkGroup gp = bk.toGroup();
00407             visitEnter(gp);
00408             if (!gp.first().isNull()) 
00409             {
00410                 stack.push(gp);
00411                 bk = gp.first();
00412                 continue;
00413             }
00414             // empty group
00415             visitLeave(gp);
00416         } 
00417         else 
00418             visit(bk);
00419 
00420         bk = stack.top().next(bk);
00421     }
00422 
00423     // never reached
00424 }
00425 
KDE Logo
This file is part of the documentation for kio Library Version 3.2.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Feb 4 12:35:02 2004 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2003