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 // Returns first element node equal to or after node n 00058 static QDomElement firstElement(QDomNode n) 00059 { 00060 while(!n.isNull() && !n.isElement()) 00061 n = n.nextSibling(); 00062 return n.toElement(); 00063 } 00064 00065 // Returns first element node equal to or before node n 00066 static QDomElement lastElement(QDomNode n) 00067 { 00068 while(!n.isNull() && !n.isElement()) 00069 n = n.previousSibling(); 00070 return n.toElement(); 00071 } 00072 00073 KBookmark KBookmarkGroup::first() const 00074 { 00075 return KBookmark( nextKnownTag( firstElement(element.firstChild()), true ) ); 00076 } 00077 00078 KBookmark KBookmarkGroup::previous( const KBookmark & current ) const 00079 { 00080 return KBookmark( nextKnownTag( lastElement(current.element.previousSibling()), false ) ); 00081 } 00082 00083 KBookmark KBookmarkGroup::next( const KBookmark & current ) const 00084 { 00085 return KBookmark( nextKnownTag( firstElement(current.element.nextSibling()), true ) ); 00086 } 00087 00088 // KDE4: Change QDomElement to QDomNode so that we can get rid of 00089 // firstElement() and lastElement() 00090 QDomElement KBookmarkGroup::nextKnownTag( QDomElement start, bool goNext ) const 00091 { 00092 static const QString & bookmark = KGlobal::staticQString("bookmark"); 00093 static const QString & folder = KGlobal::staticQString("folder"); 00094 static const QString & separator = KGlobal::staticQString("separator"); 00095 00096 for( QDomNode n = start; !n.isNull(); ) 00097 { 00098 QDomElement elem = n.toElement(); 00099 QString tag = elem.tagName(); 00100 if (tag == folder || tag == bookmark || tag == separator) 00101 return elem; 00102 if (goNext) 00103 n = n.nextSibling(); 00104 else 00105 n = n.previousSibling(); 00106 } 00107 return QDomElement(); 00108 } 00109 00110 KBookmarkGroup KBookmarkGroup::createNewFolder( KBookmarkManager* mgr, const QString & text, bool emitSignal ) 00111 { 00112 QString txt( text ); 00113 if ( text.isEmpty() ) 00114 { 00115 bool ok; 00116 QString caption = parentGroup().fullText().isEmpty() ? 00117 i18n( "Create New Bookmark Folder" ) : 00118 i18n( "Create New Bookmark Folder in %1" ) 00119 .arg( parentGroup().text() ); 00120 txt = KInputDialog::getText( caption, i18n( "New folder:" ), 00121 QString::null, &ok ); 00122 if ( !ok ) 00123 return KBookmarkGroup(); 00124 } 00125 00126 Q_ASSERT(!element.isNull()); 00127 QDomDocument doc = element.ownerDocument(); 00128 QDomElement groupElem = doc.createElement( "folder" ); 00129 element.appendChild( groupElem ); 00130 QDomElement textElem = doc.createElement( "title" ); 00131 groupElem.appendChild( textElem ); 00132 textElem.appendChild( doc.createTextNode( txt ) ); 00133 00134 KBookmarkGroup grp(groupElem); 00135 00136 if (emitSignal) 00137 emit mgr->notifier().createdNewFolder( 00138 mgr->path(), grp.fullText(), 00139 grp.address() ); 00140 00141 return grp; 00142 00143 } 00144 00145 KBookmark KBookmarkGroup::createNewSeparator() 00146 { 00147 Q_ASSERT(!element.isNull()); 00148 QDomDocument doc = element.ownerDocument(); 00149 Q_ASSERT(!doc.isNull()); 00150 QDomElement sepElem = doc.createElement( "separator" ); 00151 element.appendChild( sepElem ); 00152 return KBookmark(sepElem); 00153 } 00154 00155 bool KBookmarkGroup::moveItem( const KBookmark & item, const KBookmark & after ) 00156 { 00157 QDomNode n; 00158 if ( !after.isNull() ) 00159 n = element.insertAfter( item.element, after.element ); 00160 else // first child 00161 { 00162 if ( element.firstChild().isNull() ) // Empty element -> set as real first child 00163 n = element.insertBefore( item.element, QDomElement() ); 00164 00165 // we have to skip everything up to the first valid child 00166 QDomElement firstChild = nextKnownTag(element.firstChild().toElement(), true); 00167 if ( !firstChild.isNull() ) 00168 n = element.insertBefore( item.element, firstChild ); 00169 else 00170 { 00171 // No real first child -> append after the <title> etc. 00172 n = element.appendChild( item.element ); 00173 } 00174 } 00175 return (!n.isNull()); 00176 } 00177 00178 KBookmark KBookmarkGroup::addBookmark( KBookmarkManager* mgr, const QString & text, const KURL & url, const QString & icon, bool emitSignal ) 00179 { 00180 //kdDebug(7043) << "KBookmarkGroup::addBookmark " << text << " into " << m_address << endl; 00181 QDomDocument doc = element.ownerDocument(); 00182 QDomElement elem = doc.createElement( "bookmark" ); 00183 element.appendChild( elem ); 00184 elem.setAttribute( "href", url.url( 0, 106 ) ); // write utf8 URL (106 is mib enum for utf8) 00185 QString _icon = icon; 00186 if ( _icon.isEmpty() ) 00187 _icon = KMimeType::iconForURL( url ); 00188 elem.setAttribute( "icon", _icon ); 00189 00190 QDomElement textElem = doc.createElement( "title" ); 00191 elem.appendChild( textElem ); 00192 textElem.appendChild( doc.createTextNode( text ) ); 00193 00194 KBookmark bk(elem); 00195 00196 if (emitSignal) 00197 emit mgr->notifier().addedBookmark( 00198 mgr->path(), url.url(), 00199 text, bk.address(), icon ); 00200 00201 return bk; 00202 } 00203 00204 void KBookmarkGroup::deleteBookmark( KBookmark bk ) 00205 { 00206 element.removeChild( bk.element ); 00207 } 00208 00209 bool KBookmarkGroup::isToolbarGroup() const 00210 { 00211 return ( element.attribute("toolbar") == "yes" ); 00212 } 00213 00214 QDomElement KBookmarkGroup::findToolbar() const 00215 { 00216 if ( element.attribute("toolbar") == "yes" ) 00217 return element; 00218 for (QDomNode n = element.firstChild(); !n.isNull() ; n = n.nextSibling() ) 00219 { 00220 QDomElement e = n.toElement(); 00221 // Search among the "folder" children only 00222 if ( e.tagName() == "folder" ) 00223 { 00224 if ( e.attribute("toolbar") == "yes" ) 00225 return e; 00226 else 00227 { 00228 QDomElement result = KBookmarkGroup(e).findToolbar(); 00229 if (!result.isNull()) 00230 return result; 00231 } 00232 } 00233 } 00234 return QDomElement(); 00235 } 00236 00237 QValueList<KURL> KBookmarkGroup::groupUrlList() const 00238 { 00239 QValueList<KURL> urlList; 00240 for ( KBookmark bm = first(); !bm.isNull(); bm = next(bm) ) 00241 { 00242 if ( bm.isSeparator() || bm.isGroup() ) 00243 continue; 00244 urlList << bm.url(); 00245 } 00246 return urlList; 00247 } 00248 00250 00251 bool KBookmark::isGroup() const 00252 { 00253 QString tag = element.tagName(); 00254 return ( tag == "folder" 00255 || tag == "xbel" ); // don't forget the toplevel group 00256 } 00257 00258 bool KBookmark::isSeparator() const 00259 { 00260 return (element.tagName() == "separator"); 00261 } 00262 00263 bool KBookmark::hasParent() const 00264 { 00265 QDomElement parent = element.parentNode().toElement(); 00266 return !parent.isNull(); 00267 } 00268 00269 QString KBookmark::text() const 00270 { 00271 return KStringHandler::csqueeze( fullText() ); 00272 } 00273 00274 QString KBookmark::fullText() const 00275 { 00276 if (isSeparator()) 00277 return i18n("--- separator ---"); 00278 00279 return element.namedItem("title").toElement().text(); 00280 } 00281 00282 KURL KBookmark::url() const 00283 { 00284 return KURL(element.attribute("href"), 106); // Decode it from utf8 (106 is mib enum for utf8) 00285 } 00286 00287 QString KBookmark::icon() const 00288 { 00289 QString icon = element.attribute("icon"); 00290 if ( icon.isEmpty() ) 00291 // Default icon depends on URL for bookmarks, and is default directory 00292 // icon for groups. 00293 if ( isGroup() ) 00294 icon = "bookmark_folder"; 00295 else 00296 if ( isSeparator() ) 00297 icon = "eraser"; // whatever 00298 else 00299 icon = KMimeType::iconForURL( url() ); 00300 return icon; 00301 } 00302 00303 KBookmarkGroup KBookmark::parentGroup() const 00304 { 00305 return KBookmarkGroup( element.parentNode().toElement() ); 00306 } 00307 00308 KBookmarkGroup KBookmark::toGroup() const 00309 { 00310 Q_ASSERT( isGroup() ); 00311 return KBookmarkGroup(element); 00312 } 00313 00314 QString KBookmark::address() const 00315 { 00316 if ( element.tagName() == "xbel" ) 00317 return ""; // not QString::null ! 00318 else 00319 { 00320 // Use keditbookmarks's DEBUG_ADDRESSES flag to debug this code :) 00321 if (!hasParent()) 00322 { 00323 Q_ASSERT(hasParent()); 00324 return "ERROR"; // Avoid an infinite loop 00325 } 00326 KBookmarkGroup group = parentGroup(); 00327 QString parentAddress = group.address(); 00328 uint counter = 0; 00329 // Implementation note: we don't use QDomNode's childNode list because we 00330 // would have to skip "TEXT", which KBookmarkGroup already does for us. 00331 for ( KBookmark bk = group.first() ; !bk.isNull() ; bk = group.next(bk), ++counter ) 00332 { 00333 if ( bk.element == element ) 00334 return parentAddress + "/" + QString::number(counter); 00335 } 00336 kdWarning() << "KBookmark::address : this can't happen! " << parentAddress << endl; 00337 return "ERROR"; 00338 } 00339 } 00340 00341 KBookmark KBookmark::standaloneBookmark( const QString & text, const KURL & url, const QString & icon ) 00342 { 00343 QDomDocument doc("xbel"); 00344 QDomElement elem = doc.createElement("xbel"); 00345 doc.appendChild( elem ); 00346 KBookmarkGroup grp( elem ); 00347 grp.addBookmark( 0L, text, url, icon, false ); 00348 return grp.first(); 00349 } 00350 00351 static QDomNode cd_or_create(QDomNode node, QString name) 00352 { 00353 QDomNode subnode = node.namedItem(name); 00354 if (subnode.isNull()) 00355 { 00356 subnode = node.ownerDocument().createElement(name); 00357 node.appendChild(subnode); 00358 } 00359 return subnode; 00360 } 00361 00362 static QDomText get_or_create_text(QDomNode node) 00363 { 00364 QDomNode subnode = node.firstChild(); 00365 if (subnode.isNull()) 00366 { 00367 subnode = node.ownerDocument().createTextNode(""); 00368 node.appendChild(subnode); 00369 } 00370 return subnode.toText(); 00371 } 00372 00373 void KBookmark::updateAccessMetadata() 00374 { 00375 kdDebug(7043) << "KBookmark::updateAccessMetadata " << address() << " " << url().prettyURL() << endl; 00376 00377 QDomNode subnode = cd_or_create(internalElement(), "info"); 00378 subnode = cd_or_create(subnode, "metadata"); 00379 00380 uint timet = QDateTime::currentDateTime().toTime_t(); 00381 00382 QDomNode item = cd_or_create(subnode, "time_added"); 00383 QDomText domtext = get_or_create_text(item); 00384 if (domtext.data().isEmpty()) 00385 domtext.setData(QString::number(timet)); 00386 00387 item = cd_or_create(subnode, "time_visited"); 00388 domtext = get_or_create_text(item); 00389 domtext.setData(QString::number(timet)); 00390 00391 item = cd_or_create(subnode, "visit_count"); // TODO use spec'ed name 00392 domtext = get_or_create_text(item); 00393 QString countStr = domtext.data(); 00394 bool ok; 00395 int currentCount = countStr.toInt(&ok); 00396 if (!ok) 00397 currentCount = 0; 00398 currentCount++; 00399 domtext.setData(QString::number(currentCount)); 00400 00401 // TODO - for 3.3 - time_modified 00402 } 00403 00404 void KBookmarkGroupTraverser::traverse(const KBookmarkGroup &root) 00405 { 00406 // non-recursive bookmark iterator 00407 QValueStack<KBookmarkGroup> stack; 00408 stack.push(root); 00409 KBookmark bk = stack.top().first(); 00410 for (;;) { 00411 if (bk.isNull()) 00412 { 00413 if (stack.isEmpty()) 00414 return; 00415 if (stack.count() > 1) 00416 visitLeave(stack.top()); 00417 bk = stack.pop(); 00418 bk = stack.top().next(bk); 00419 if (bk.isNull()) 00420 continue; 00421 } 00422 00423 if (bk.isGroup()) 00424 { 00425 KBookmarkGroup gp = bk.toGroup(); 00426 visitEnter(gp); 00427 if (!gp.first().isNull()) 00428 { 00429 stack.push(gp); 00430 bk = gp.first(); 00431 continue; 00432 } 00433 // empty group 00434 visitLeave(gp); 00435 } 00436 else 00437 visit(bk); 00438 00439 bk = stack.top().next(bk); 00440 } 00441 00442 // never reached 00443 } 00444
KDE Logo
This file is part of the documentation for kio Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:41:02 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003