• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/bookmarks
 

tdeio/bookmarks

  • tdeio
  • bookmarks
kbookmark.cpp
1/* This file is part of the KDE libraries
2 Copyright (C) 2000 David Faure <faure@kde.org>
3 Copyright (C) 2003 Alexander Kellett <lypanov@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#include "kbookmark.h"
21#include <tqvaluestack.h>
22#include <kdebug.h>
23#include <kmimetype.h>
24#include <kstringhandler.h>
25#include <kinputdialog.h>
26#include <tdeglobal.h>
27#include <tdelocale.h>
28#include <assert.h>
29#include <tdeapplication.h>
30#include <dcopclient.h>
31#include <kbookmarkmanager.h>
32
33KBookmarkGroup::KBookmarkGroup()
34 : KBookmark( TQDomElement() )
35{
36}
37
38KBookmarkGroup::KBookmarkGroup( TQDomElement elem )
39 : KBookmark(elem)
40{
41}
42
43TQString KBookmarkGroup::groupAddress() const
44{
45 if (m_address.isEmpty())
46 m_address = address();
47 return m_address;
48}
49
50bool KBookmarkGroup::isOpen() const
51{
52 return element.attribute("folded") == "no"; // default is: folded
53}
54
55// Returns first element node equal to or after node n
56static TQDomElement firstElement(TQDomNode n)
57{
58 while(!n.isNull() && !n.isElement())
59 n = n.nextSibling();
60 return n.toElement();
61}
62
63// Returns first element node equal to or before node n
64static TQDomElement lastElement(TQDomNode n)
65{
66 while(!n.isNull() && !n.isElement())
67 n = n.previousSibling();
68 return n.toElement();
69}
70
71KBookmark KBookmarkGroup::first() const
72{
73 return KBookmark( nextKnownTag( firstElement(element.firstChild()), true ) );
74}
75
76KBookmark KBookmarkGroup::previous( const KBookmark & current ) const
77{
78 return KBookmark( nextKnownTag( lastElement(current.element.previousSibling()), false ) );
79}
80
81KBookmark KBookmarkGroup::next( const KBookmark & current ) const
82{
83 return KBookmark( nextKnownTag( firstElement(current.element.nextSibling()), true ) );
84}
85
86// KDE4: Change TQDomElement to TQDomNode so that we can get rid of
87// firstElement() and lastElement()
88TQDomElement KBookmarkGroup::nextKnownTag( TQDomElement start, bool goNext ) const
89{
90 static const TQString & bookmark = TDEGlobal::staticQString("bookmark");
91 static const TQString & folder = TDEGlobal::staticQString("folder");
92 static const TQString & separator = TDEGlobal::staticQString("separator");
93
94 for( TQDomNode n = start; !n.isNull(); )
95 {
96 TQDomElement elem = n.toElement();
97 TQString tag = elem.tagName();
98 if (tag == folder || tag == bookmark || tag == separator)
99 return elem;
100 if (goNext)
101 n = n.nextSibling();
102 else
103 n = n.previousSibling();
104 }
105 return TQDomElement();
106}
107
108KBookmarkGroup KBookmarkGroup::createNewFolder( KBookmarkManager* mgr, const TQString & text, bool emitSignal )
109{
110 TQString txt( text );
111 if ( text.isEmpty() )
112 {
113 bool ok;
114 TQString caption = parentGroup().fullText().isEmpty() ?
115 i18n( "Create New Bookmark Folder" ) :
116 i18n( "Create New Bookmark Folder in %1" )
117 .arg( parentGroup().text() );
118 txt = KInputDialog::getText( caption, i18n( "New folder:" ),
119 TQString::null, &ok );
120 if ( !ok )
121 return KBookmarkGroup();
122 }
123
124 Q_ASSERT(!element.isNull());
125 TQDomDocument doc = element.ownerDocument();
126 TQDomElement groupElem = doc.createElement( "folder" );
127 element.appendChild( groupElem );
128 TQDomElement textElem = doc.createElement( "title" );
129 groupElem.appendChild( textElem );
130 textElem.appendChild( doc.createTextNode( txt ) );
131
132 KBookmarkGroup grp(groupElem);
133
134 if (emitSignal)
135 emit mgr->notifier().createdNewFolder(
136 mgr->path(), grp.fullText(),
137 grp.address() );
138
139 return grp;
140
141}
142
143KBookmark KBookmarkGroup::createNewSeparator()
144{
145 Q_ASSERT(!element.isNull());
146 TQDomDocument doc = element.ownerDocument();
147 Q_ASSERT(!doc.isNull());
148 TQDomElement sepElem = doc.createElement( "separator" );
149 element.appendChild( sepElem );
150 return KBookmark(sepElem);
151}
152
153bool KBookmarkGroup::moveItem( const KBookmark & item, const KBookmark & after )
154{
155 TQDomNode n;
156 if ( !after.isNull() )
157 n = element.insertAfter( item.element, after.element );
158 else // first child
159 {
160 if ( element.firstChild().isNull() ) // Empty element -> set as real first child
161 n = element.insertBefore( item.element, TQDomElement() );
162
163 // we have to skip everything up to the first valid child
164 TQDomElement firstChild = nextKnownTag(element.firstChild().toElement(), true);
165 if ( !firstChild.isNull() )
166 n = element.insertBefore( item.element, firstChild );
167 else
168 {
169 // No real first child -> append after the <title> etc.
170 n = element.appendChild( item.element );
171 }
172 }
173 return (!n.isNull());
174}
175
176KBookmark KBookmarkGroup::addBookmark( KBookmarkManager* mgr, const KBookmark &bm, bool emitSignal )
177{
178 element.appendChild( bm.internalElement() );
179
180 if (emitSignal) {
181 if ( bm.hasMetaData() ) {
182 mgr->notifyCompleteChange( "" );
183 } else {
184 emit mgr->notifier().addedBookmark(
185 mgr->path(), bm.url().url(),
186 bm.fullText(), bm.address(), bm.icon() );
187 }
188 }
189
190 return bm;
191}
192
193KBookmark KBookmarkGroup::addBookmark( KBookmarkManager* mgr, const TQString & text, const KURL & url, const TQString & icon, bool emitSignal )
194{
195 //kdDebug(7043) << "KBookmarkGroup::addBookmark " << text << " into " << m_address << endl;
196 TQDomDocument doc = element.ownerDocument();
197 TQDomElement elem = doc.createElement( "bookmark" );
198 elem.setAttribute( "href", url.url( 0, 106 ) ); // write utf8 URL (106 is mib enum for utf8)
199 TQString _icon = icon;
200 if ( _icon.isEmpty() )
201 _icon = KMimeType::iconForURL( url );
202 elem.setAttribute( "icon", _icon );
203
204 TQDomElement textElem = doc.createElement( "title" );
205 elem.appendChild( textElem );
206 textElem.appendChild( doc.createTextNode( text ) );
207
208 return addBookmark( mgr, KBookmark( elem ), emitSignal );
209}
210
211void KBookmarkGroup::deleteBookmark( KBookmark bk )
212{
213 element.removeChild( bk.element );
214}
215
216bool KBookmarkGroup::isToolbarGroup() const
217{
218 return ( element.attribute("toolbar") == "yes" );
219}
220
221TQDomElement KBookmarkGroup::findToolbar() const
222{
223 if ( element.attribute("toolbar") == "yes" )
224 return element;
225 for (TQDomNode n = element.firstChild(); !n.isNull() ; n = n.nextSibling() )
226 {
227 TQDomElement e = n.toElement();
228 // Search among the "folder" children only
229 if ( e.tagName() == "folder" )
230 {
231 if ( e.attribute("toolbar") == "yes" )
232 return e;
233 else
234 {
235 TQDomElement result = KBookmarkGroup(e).findToolbar();
236 if (!result.isNull())
237 return result;
238 }
239 }
240 }
241 return TQDomElement();
242}
243
244TQValueList<KURL> KBookmarkGroup::groupUrlList() const
245{
246 TQValueList<KURL> urlList;
247 for ( KBookmark bm = first(); !bm.isNull(); bm = next(bm) )
248 {
249 if ( bm.isSeparator() || bm.isGroup() )
250 continue;
251 urlList << bm.url();
252 }
253 return urlList;
254}
255
257
258bool KBookmark::isGroup() const
259{
260 TQString tag = element.tagName();
261 return ( tag == "folder"
262 || tag == "xbel" ); // don't forget the toplevel group
263}
264
265bool KBookmark::isSeparator() const
266{
267 return (element.tagName() == "separator");
268}
269
270bool KBookmark::hasParent() const
271{
272 TQDomElement parent = element.parentNode().toElement();
273 return !parent.isNull();
274}
275
276TQString KBookmark::text() const
277{
278 return KStringHandler::csqueeze( fullText() );
279}
280
281TQString KBookmark::fullText() const
282{
283 if (isSeparator())
284 return i18n("--- separator ---");
285
286 return element.namedItem("title").toElement().text();
287}
288
289KURL KBookmark::url() const
290{
291 return KURL(element.attribute("href"), 106); // Decode it from utf8 (106 is mib enum for utf8)
292}
293
294TQString KBookmark::icon() const
295{
296 TQString icon = element.attribute("icon");
297 if ( icon.isEmpty() ) {
298 // Default icon depends on URL for bookmarks, and is default directory
299 // icon for groups.
300 if ( isGroup() ) {
301 icon = "bookmark_folder";
302 }
303 else {
304 if ( isSeparator() ) {
305 icon = "eraser"; // whatever
306 }
307 else {
308 icon = KMimeType::iconForURL( url() );
309 }
310 }
311 }
312 return icon;
313}
314
315KBookmarkGroup KBookmark::parentGroup() const
316{
317 return KBookmarkGroup( element.parentNode().toElement() );
318}
319
320KBookmarkGroup KBookmark::toGroup() const
321{
322 Q_ASSERT( isGroup() );
323 return KBookmarkGroup(element);
324}
325
326TQString KBookmark::address() const
327{
328 if ( element.tagName() == "xbel" )
329 return ""; // not TQString::null !
330 else
331 {
332 // Use keditbookmarks's DEBUG_ADDRESSES flag to debug this code :)
333 if (!hasParent())
334 {
335 Q_ASSERT(hasParent());
336 return "ERROR"; // Avoid an infinite loop
337 }
338 KBookmarkGroup group = parentGroup();
339 TQString parentAddress = group.address();
340 uint counter = 0;
341 // Implementation note: we don't use QDomNode's childNode list because we
342 // would have to skip "TEXT", which KBookmarkGroup already does for us.
343 for ( KBookmark bk = group.first() ; !bk.isNull() ; bk = group.next(bk), ++counter )
344 {
345 if ( bk.element == element )
346 return parentAddress + "/" + TQString::number(counter);
347 }
348 kdWarning() << "KBookmark::address : this can't happen! " << parentAddress << endl;
349 return "ERROR";
350 }
351}
352
353KBookmark KBookmark::standaloneBookmark( const TQString & text, const KURL & url, const TQString & icon )
354{
355 TQDomDocument doc("xbel");
356 TQDomElement elem = doc.createElement("xbel");
357 doc.appendChild( elem );
358 KBookmarkGroup grp( elem );
359 grp.addBookmark( 0L, text, url, icon, false );
360 return grp.first();
361}
362
363// For some strange reason TQString("").left(0) returns TQString::null;
364// That breaks commonParent()
365TQString KBookmark::left(const TQString & str, uint len)
366{
367 //kdDebug()<<"********"<<TQString("").left(0).isNull()<<endl;
368 if(len == 0)
369 return TQString("");
370 else
371 return str.left(len);
372}
373
374TQString KBookmark::commonParent(TQString A, TQString B)
375{
376 TQString error("ERROR");
377 if(A == error || B == error)
378 return error;
379
380 A += "/";
381 B += "/";
382
383 uint lastCommonSlash = 0;
384 uint lastPos = A.length() < B.length() ? A.length() : B.length();
385 for(uint i=0; i < lastPos; ++i)
386 {
387 if(A[i] != B[i])
388 return left(A, lastCommonSlash);
389 if(A[i] == '/')
390 lastCommonSlash = i;
391 }
392 return left(A, lastCommonSlash);
393}
394
395static TQDomNode cd_or_create(TQDomNode node, TQString name)
396{
397 TQDomNode subnode = node.namedItem(name);
398 if (subnode.isNull())
399 {
400 subnode = node.ownerDocument().createElement(name);
401 node.appendChild(subnode);
402 }
403 return subnode;
404}
405
406static TQDomText get_or_create_text(TQDomNode node)
407{
408 TQDomNode subnode = node.firstChild();
409 if (subnode.isNull())
410 {
411 subnode = node.ownerDocument().createTextNode("");
412 node.appendChild(subnode);
413 }
414 return subnode.toText();
415}
416
417// Look for a metadata with owner="http://www.kde.org" or without any owner (for compatibility)
418static TQDomNode findOrCreateMetadata( TQDomNode& parent )
419{
420 static const char kdeOwner[] = "http://www.kde.org";
421 TQDomElement metadataElement;
422 for ( TQDomNode _node = parent.firstChild(); !_node.isNull(); _node = _node.nextSibling() ) {
423 TQDomElement elem = _node.toElement();
424 if ( !elem.isNull() && elem.tagName() == "metadata" ) {
425 const TQString owner = elem.attribute( "owner" );
426 if ( owner == kdeOwner )
427 return elem;
428 if ( owner.isEmpty() )
429 metadataElement = elem;
430 }
431 }
432 if ( metadataElement.isNull() ) {
433 metadataElement = parent.ownerDocument().createElement( "metadata" );
434 parent.appendChild(metadataElement);
435 }
436 metadataElement.setAttribute( "owner", kdeOwner );
437 return metadataElement;
438}
439
440bool KBookmark::hasMetaData() const
441{
442 // ### NOTE: this code creates <info> and <metadata>, despite its name and the const.
443 // It doesn't matter much in practice since it's only called for newly-created bookmarks,
444 // which will get metadata soon after anyway.
445 TQDomNode n = cd_or_create( internalElement(), "info" );
446 return findOrCreateMetadata( n ).hasChildNodes();
447}
448
449void KBookmark::updateAccessMetadata()
450{
451 kdDebug(7043) << "KBookmark::updateAccessMetadata " << address() << " " << url().prettyURL() << endl;
452
453 const uint timet = TQDateTime::currentDateTime().toTime_t();
454 setMetaDataItem( "time_added", TQString::number( timet ), DontOverwriteMetaData );
455 setMetaDataItem( "time_visited", TQString::number( timet ) );
456
457 TQString countStr = metaDataItem( "visit_count" ); // TODO use spec'ed name
458 bool ok;
459 int currentCount = countStr.toInt(&ok);
460 if (!ok)
461 currentCount = 0;
462 currentCount++;
463 setMetaDataItem( "visit_count", TQString::number( currentCount ) );
464
465 // TODO - for 4.0 - time_modified
466}
467
468TQString KBookmark::metaDataItem( const TQString &key ) const
469{
470 TQDomNode infoNode = cd_or_create( internalElement(), "info" );
471 infoNode = findOrCreateMetadata( infoNode );
472 for ( TQDomNode n = infoNode.firstChild(); !n.isNull(); n = n.nextSibling() ) {
473 if ( !n.isElement() ) {
474 continue;
475 }
476 const TQDomElement e = n.toElement();
477 if ( e.tagName() == key ) {
478 return e.text();
479 }
480 }
481 return TQString::null;
482}
483
484void KBookmark::setMetaDataItem( const TQString &key, const TQString &value, MetaDataOverwriteMode mode )
485{
486 TQDomNode infoNode = cd_or_create( internalElement(), "info" );
487 infoNode = findOrCreateMetadata( infoNode );
488
489 TQDomNode item = cd_or_create( infoNode, key );
490 TQDomText text = get_or_create_text( item );
491 if ( mode == DontOverwriteMetaData && !text.data().isEmpty() ) {
492 return;
493 }
494
495 text.setData( value );
496}
497
498void KBookmarkGroupTraverser::traverse(const KBookmarkGroup &root)
499{
500 // non-recursive bookmark iterator
501 TQValueStack<KBookmarkGroup> stack;
502 stack.push(root);
503 KBookmark bk = stack.top().first();
504 for (;;) {
505 if (bk.isNull())
506 {
507 if (stack.isEmpty())
508 return;
509 if (stack.count() > 1)
510 visitLeave(stack.top());
511 bk = stack.pop();
512 bk = stack.top().next(bk);
513 if (bk.isNull())
514 continue;
515 }
516
517 if (bk.isGroup())
518 {
519 KBookmarkGroup gp = bk.toGroup();
520 visitEnter(gp);
521 if (!gp.first().isNull())
522 {
523 stack.push(gp);
524 bk = gp.first();
525 continue;
526 }
527 // empty group
528 visitLeave(gp);
529 }
530 else
531 visit(bk);
532
533 bk = stack.top().next(bk);
534 }
535
536 // never reached
537}
538
KBookmarkGroup
A group of bookmarks.
Definition: kbookmark.h:198
KBookmarkGroup::isToolbarGroup
bool isToolbarGroup() const
Definition: kbookmark.cpp:216
KBookmarkGroup::next
KBookmark next(const KBookmark &current) const
Return the next sibling of a child bookmark of this group.
Definition: kbookmark.cpp:81
KBookmarkGroup::groupAddress
TQString groupAddress() const
Much like KBookmark::address, but caches the address into m_address.
Definition: kbookmark.cpp:43
KBookmarkGroup::first
KBookmark first() const
Return the first child bookmark of this group.
Definition: kbookmark.cpp:71
KBookmarkGroup::isOpen
bool isOpen() const
Definition: kbookmark.cpp:50
KBookmarkGroup::KBookmarkGroup
KBookmarkGroup()
Create an invalid group.
Definition: kbookmark.cpp:33
KBookmarkGroup::addBookmark
KBookmark addBookmark(KBookmarkManager *mgr, const KBookmark &bm, bool emitSignal=true)
Create a new bookmark, as the last child of this group Don't forget to use KBookmarkManager::self()->...
Definition: kbookmark.cpp:176
KBookmarkGroup::deleteBookmark
void deleteBookmark(KBookmark bk)
Delete a bookmark - it has to be one of our children ! Don't forget to use KBookmarkManager::self()->...
Definition: kbookmark.cpp:211
KBookmarkGroup::previous
KBookmark previous(const KBookmark &current) const
Return the prevous sibling of a child bookmark of this group.
Definition: kbookmark.cpp:76
KBookmarkGroup::createNewFolder
KBookmarkGroup createNewFolder(KBookmarkManager *mgr, const TQString &text=TQString::null, bool emitSignal=true)
Create a new bookmark folder, as the last child of this group.
Definition: kbookmark.cpp:108
KBookmarkGroup::createNewSeparator
KBookmark createNewSeparator()
Create a new bookmark separator Don't forget to use KBookmarkManager::self()->emitChanged( parentBook...
Definition: kbookmark.cpp:143
KBookmarkGroup::moveItem
bool moveItem(const KBookmark &item, const KBookmark &after)
Moves item after after (which should be a child of ours).
Definition: kbookmark.cpp:153
KBookmarkGroup::groupUrlList
TQValueList< KURL > groupUrlList() const
Definition: kbookmark.cpp:244
KBookmarkManager
This class implements the reading/writing of bookmarks in XML.
Definition: kbookmarkmanager.h:52
KBookmarkManager::path
TQString path()
This will return the path that this manager is using to read the bookmarks.
Definition: kbookmarkmanager.h:132
KBookmarkManager::notifier
KBookmarkNotifier & notifier()
Access to bookmark notifier, for emitting signals.
Definition: kbookmarkmanager.h:235
KBookmarkManager::notifyCompleteChange
ASYNC notifyCompleteChange(TQString caller)
Reparse the whole bookmarks file and notify about the change (Called by the bookmark editor)
Definition: kbookmarkmanager.cpp:561

tdeio/bookmarks

Skip menu "tdeio/bookmarks"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

tdeio/bookmarks

Skip menu "tdeio/bookmarks"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/bookmarks by doxygen 1.9.4
This website is maintained by Timothy Pearson.