File indexing completed on 2024-12-08 12:16:05
0001 // -*- c-basic-offset:4; indent-tabs-mode:nil -*- 0002 /* 0003 This file is part of the KDE libraries 0004 SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org> 0005 SPDX-FileCopyrightText: 2003 Alexander Kellett <lypanov@kde.org> 0006 SPDX-FileCopyrightText: 2008 Norbert Frese <nf2@scheinwelt.at> 0007 0008 SPDX-License-Identifier: LGPL-2.0-only 0009 */ 0010 0011 #include "kbookmark.h" 0012 #include "kbookmarks_debug.h" 0013 #include <kbookmarkmanager.h> 0014 0015 #include <KStringHandler> 0016 #include <kurlmimedata.h> 0017 0018 #include <QCoreApplication> 0019 #include <QMimeDatabase> 0020 #include <QStack> 0021 #include <QDateTime> 0022 #include <QMimeData> 0023 0024 namespace 0025 { 0026 namespace Strings 0027 { 0028 QString metaDataKDEOwner() 0029 { 0030 return QStringLiteral("http://www.kde.org"); 0031 } 0032 QString metaDataFreedesktopOwner() 0033 { 0034 return QStringLiteral("http://freedesktop.org"); 0035 } 0036 QString metaDataMimeOwner() 0037 { 0038 return QStringLiteral("http://www.freedesktop.org/standards/shared-mime-info"); 0039 } 0040 0041 QString xbelMimeType() 0042 { 0043 return QStringLiteral("application/x-xbel"); 0044 } 0045 } 0046 } 0047 0048 ////// utility functions 0049 0050 static QDomNode cd(QDomNode node, const QString &name, bool create) 0051 { 0052 QDomNode subnode = node.namedItem(name); 0053 if (create && subnode.isNull()) { 0054 subnode = node.ownerDocument().createElement(name); 0055 node.appendChild(subnode); 0056 } 0057 return subnode; 0058 } 0059 0060 static QDomNode cd_or_create(const QDomNode &node, const QString &name) 0061 { 0062 return cd(node, name, true); 0063 } 0064 0065 static QDomText get_or_create_text(QDomNode node) 0066 { 0067 QDomNode subnode = node.firstChild(); 0068 if (subnode.isNull()) { 0069 subnode = node.ownerDocument().createTextNode(QLatin1String("")); 0070 node.appendChild(subnode); 0071 } 0072 return subnode.toText(); 0073 } 0074 0075 static QDomNode findMetadata(const QString &forOwner, QDomNode &parent, bool create) 0076 { 0077 const bool forOwnerIsKDE = (forOwner == Strings::metaDataKDEOwner()); 0078 0079 QDomElement metadataElement; 0080 for (QDomNode _node = parent.firstChild(); !_node.isNull(); _node = _node.nextSibling()) { 0081 QDomElement elem = _node.toElement(); 0082 if (!elem.isNull() && elem.tagName() == QLatin1String("metadata")) { 0083 const QString owner = elem.attribute(QStringLiteral("owner")); 0084 if (owner == forOwner) { 0085 return elem; 0086 } 0087 if (owner.isEmpty() && forOwnerIsKDE) { 0088 metadataElement = elem; 0089 } 0090 } 0091 } 0092 if (create && metadataElement.isNull()) { 0093 metadataElement = parent.ownerDocument().createElement(QStringLiteral("metadata")); 0094 parent.appendChild(metadataElement); 0095 metadataElement.setAttribute(QStringLiteral("owner"), forOwner); 0096 0097 } else if (!metadataElement.isNull() && forOwnerIsKDE) { 0098 // i'm not sure if this is good, we shouldn't take over foreign metadata 0099 metadataElement.setAttribute(QStringLiteral("owner"), Strings::metaDataKDEOwner()); 0100 } 0101 return metadataElement; 0102 } 0103 0104 ////// 0105 0106 KBookmarkGroup::KBookmarkGroup() 0107 : KBookmark(QDomElement()) 0108 { 0109 } 0110 0111 KBookmarkGroup::KBookmarkGroup(const QDomElement &elem) 0112 : KBookmark(elem) 0113 { 0114 } 0115 0116 bool KBookmarkGroup::isOpen() const 0117 { 0118 return element.attribute(QStringLiteral("folded")) == QLatin1String("no"); // default is: folded 0119 } 0120 0121 KBookmark KBookmarkGroup::first() const 0122 { 0123 return KBookmark(nextKnownTag(element.firstChildElement(), true)); 0124 } 0125 0126 KBookmark KBookmarkGroup::previous(const KBookmark ¤t) const 0127 { 0128 return KBookmark(nextKnownTag(current.element.previousSiblingElement(), false)); 0129 } 0130 0131 KBookmark KBookmarkGroup::next(const KBookmark ¤t) const 0132 { 0133 return KBookmark(nextKnownTag(current.element.nextSiblingElement(), true)); 0134 } 0135 0136 int KBookmarkGroup::indexOf(const KBookmark &child) const 0137 { 0138 int counter = 0; 0139 for (KBookmark bk = first(); !bk.isNull(); bk = next(bk), ++counter) { 0140 if (bk.element == child.element) { 0141 return counter; 0142 } 0143 } 0144 return -1; 0145 } 0146 0147 QDomElement KBookmarkGroup::nextKnownTag(const QDomElement &start, bool goNext) const 0148 { 0149 for (QDomElement elem = start; !elem.isNull();) { 0150 QString tag = elem.tagName(); 0151 if (tag == QLatin1String("folder") || tag == QLatin1String("bookmark") || tag == QLatin1String("separator")) { 0152 return elem; 0153 } 0154 if (goNext) { 0155 elem = elem.nextSiblingElement(); 0156 } else { 0157 elem = elem.previousSiblingElement(); 0158 } 0159 } 0160 return QDomElement(); 0161 } 0162 0163 KBookmarkGroup KBookmarkGroup::createNewFolder(const QString &text) 0164 { 0165 if (isNull()) { 0166 return KBookmarkGroup(); 0167 } 0168 QDomDocument doc = element.ownerDocument(); 0169 QDomElement groupElem = doc.createElement(QStringLiteral("folder")); 0170 element.appendChild(groupElem); 0171 QDomElement textElem = doc.createElement(QStringLiteral("title")); 0172 groupElem.appendChild(textElem); 0173 textElem.appendChild(doc.createTextNode(text)); 0174 return KBookmarkGroup(groupElem); 0175 } 0176 0177 KBookmark KBookmarkGroup::createNewSeparator() 0178 { 0179 if (isNull()) { 0180 return KBookmark(); 0181 } 0182 QDomDocument doc = element.ownerDocument(); 0183 Q_ASSERT(!doc.isNull()); 0184 QDomElement sepElem = doc.createElement(QStringLiteral("separator")); 0185 element.appendChild(sepElem); 0186 return KBookmark(sepElem); 0187 } 0188 0189 bool KBookmarkGroup::moveBookmark(const KBookmark &item, const KBookmark &after) 0190 { 0191 QDomNode n; 0192 if (!after.isNull()) { 0193 n = element.insertAfter(item.element, after.element); 0194 } else { // first child 0195 if (element.firstChild().isNull()) { // Empty element -> set as real first child 0196 n = element.insertBefore(item.element, QDomElement()); 0197 } 0198 0199 // we have to skip everything up to the first valid child 0200 QDomElement firstChild = nextKnownTag(element.firstChild().toElement(), true); 0201 if (!firstChild.isNull()) { 0202 if (firstChild == item.element) { // item is already the first child, done 0203 return true; 0204 } 0205 n = element.insertBefore(item.element, firstChild); 0206 } else { 0207 // No real first child -> append after the <title> etc. 0208 n = element.appendChild(item.element); 0209 } 0210 } 0211 return (!n.isNull()); 0212 } 0213 0214 KBookmark KBookmarkGroup::addBookmark(const KBookmark &bm) 0215 { 0216 element.appendChild(bm.internalElement()); 0217 return bm; 0218 } 0219 0220 KBookmark KBookmarkGroup::addBookmark(const QString &text, const QUrl &url, const QString &icon) 0221 { 0222 if (isNull()) { 0223 return KBookmark(); 0224 } 0225 QDomDocument doc = element.ownerDocument(); 0226 QDomElement elem = doc.createElement(QStringLiteral("bookmark")); 0227 elem.setAttribute(QStringLiteral("href"), url.toString(QUrl::FullyEncoded)); 0228 0229 QDomElement textElem = doc.createElement(QStringLiteral("title")); 0230 elem.appendChild(textElem); 0231 textElem.appendChild(doc.createTextNode(text)); 0232 0233 KBookmark newBookmark = addBookmark(KBookmark(elem)); 0234 0235 // as icons are moved to metadata, we have to use the KBookmark API for this 0236 newBookmark.setIcon(icon); 0237 return newBookmark; 0238 } 0239 0240 void KBookmarkGroup::deleteBookmark(const KBookmark &bk) 0241 { 0242 element.removeChild(bk.element); 0243 } 0244 0245 bool KBookmarkGroup::isToolbarGroup() const 0246 { 0247 return (element.attribute(QStringLiteral("toolbar")) == QLatin1String("yes")); 0248 } 0249 0250 QDomElement KBookmarkGroup::findToolbar() const 0251 { 0252 if (element.attribute(QStringLiteral("toolbar")) == QLatin1String("yes")) { 0253 return element; 0254 } 0255 for (QDomElement e = element.firstChildElement(QStringLiteral("folder")); !e.isNull(); e = e.nextSiblingElement(QStringLiteral("folder"))) { 0256 QDomElement result = KBookmarkGroup(e).findToolbar(); 0257 if (!result.isNull()) { 0258 return result; 0259 } 0260 } 0261 return QDomElement(); 0262 } 0263 0264 QList<QUrl> KBookmarkGroup::groupUrlList() const 0265 { 0266 QList<QUrl> urlList; 0267 for (KBookmark bm = first(); !bm.isNull(); bm = next(bm)) { 0268 if (bm.isSeparator() || bm.isGroup()) { 0269 continue; 0270 } 0271 urlList << bm.url(); 0272 } 0273 return urlList; 0274 } 0275 0276 ////// 0277 0278 KBookmark::KBookmark() 0279 { 0280 } 0281 0282 KBookmark::KBookmark(const QDomElement &elem) 0283 : element(elem) 0284 { 0285 } 0286 0287 bool KBookmark::isGroup() const 0288 { 0289 QString tag = element.tagName(); 0290 return tag == QLatin1String("folder") // 0291 || tag == QLatin1String("xbel"); // don't forget the toplevel group 0292 } 0293 0294 bool KBookmark::isSeparator() const 0295 { 0296 return (element.tagName() == QLatin1String("separator")); 0297 } 0298 0299 bool KBookmark::isNull() const 0300 { 0301 return element.isNull(); 0302 } 0303 0304 bool KBookmark::hasParent() const 0305 { 0306 QDomElement parent = element.parentNode().toElement(); 0307 return !parent.isNull(); 0308 } 0309 0310 QString KBookmark::text() const 0311 { 0312 return KStringHandler::csqueeze(fullText()); 0313 } 0314 0315 QString KBookmark::fullText() const 0316 { 0317 if (isSeparator()) { 0318 return QCoreApplication::translate("KBookmark", "--- separator ---", "Bookmark separator"); 0319 } 0320 0321 QString text = element.namedItem(QStringLiteral("title")).toElement().text(); 0322 text.replace(QLatin1Char('\n'), QLatin1Char(' ')); // #140673 0323 return text; 0324 } 0325 0326 void KBookmark::setFullText(const QString &fullText) 0327 { 0328 QDomNode titleNode = element.namedItem(QStringLiteral("title")); 0329 if (titleNode.isNull()) { 0330 titleNode = element.ownerDocument().createElement(QStringLiteral("title")); 0331 element.appendChild(titleNode); 0332 } 0333 0334 if (titleNode.firstChild().isNull()) { 0335 QDomText domtext = titleNode.ownerDocument().createTextNode(QLatin1String("")); 0336 titleNode.appendChild(domtext); 0337 } 0338 0339 QDomText domtext = titleNode.firstChild().toText(); 0340 domtext.setData(fullText); 0341 } 0342 0343 QUrl KBookmark::url() const 0344 { 0345 return QUrl(element.attribute(QStringLiteral("href"))); 0346 } 0347 0348 void KBookmark::setUrl(const QUrl &url) 0349 { 0350 element.setAttribute(QStringLiteral("href"), url.toString()); 0351 } 0352 0353 QString KBookmark::icon() const 0354 { 0355 QDomNode metaDataNode = metaData(Strings::metaDataFreedesktopOwner(), false); 0356 QDomElement iconElement = cd(metaDataNode, QStringLiteral("bookmark:icon"), false).toElement(); 0357 0358 QString icon = iconElement.attribute(QStringLiteral("name")); 0359 0360 // migration code 0361 if (icon.isEmpty()) { 0362 icon = element.attribute(QStringLiteral("icon")); 0363 } 0364 if (icon == QLatin1String("www")) { // common icon for kde3 bookmarks 0365 return QStringLiteral("internet-web-browser"); 0366 } 0367 // end migration code 0368 0369 if (icon == QLatin1String("bookmark_folder")) { 0370 return QStringLiteral("folder-bookmarks"); 0371 } 0372 if (icon.isEmpty()) { 0373 // Default icon depends on URL for bookmarks, and is default directory 0374 // icon for groups. 0375 if (isGroup()) { 0376 icon = QStringLiteral("folder-bookmarks"); 0377 } else { 0378 if (isSeparator()) { 0379 icon = QStringLiteral("edit-clear"); // whatever 0380 } else { 0381 // get icon from mimeType 0382 QMimeDatabase db; 0383 QMimeType mime; 0384 QString _mimeType = mimeType(); 0385 if (!_mimeType.isEmpty()) { 0386 mime = db.mimeTypeForName(_mimeType); 0387 } else { 0388 mime = db.mimeTypeForUrl(url()); 0389 } 0390 if (mime.isValid()) { 0391 icon = mime.iconName(); 0392 } 0393 } 0394 } 0395 } 0396 return icon; 0397 } 0398 0399 void KBookmark::setIcon(const QString &icon) 0400 { 0401 QDomNode metaDataNode = metaData(Strings::metaDataFreedesktopOwner(), true); 0402 QDomElement iconElement = cd_or_create(metaDataNode, QStringLiteral("bookmark:icon")).toElement(); 0403 iconElement.setAttribute(QStringLiteral("name"), icon); 0404 0405 // migration code 0406 if (!element.attribute(QStringLiteral("icon")).isEmpty()) { 0407 element.removeAttribute(QStringLiteral("icon")); 0408 } 0409 } 0410 0411 QString KBookmark::description() const 0412 { 0413 if (isSeparator()) { 0414 return QString(); 0415 } 0416 0417 QString description = element.namedItem(QStringLiteral("desc")).toElement().text(); 0418 description.replace(QLatin1Char('\n'), QLatin1Char(' ')); // #140673 0419 return description; 0420 } 0421 0422 void KBookmark::setDescription(const QString &description) 0423 { 0424 QDomNode descNode = element.namedItem(QStringLiteral("desc")); 0425 if (descNode.isNull()) { 0426 descNode = element.ownerDocument().createElement(QStringLiteral("desc")); 0427 element.appendChild(descNode); 0428 } 0429 0430 if (descNode.firstChild().isNull()) { 0431 QDomText domtext = descNode.ownerDocument().createTextNode(QString()); 0432 descNode.appendChild(domtext); 0433 } 0434 0435 QDomText domtext = descNode.firstChild().toText(); 0436 domtext.setData(description); 0437 } 0438 0439 QString KBookmark::mimeType() const 0440 { 0441 QDomNode metaDataNode = metaData(Strings::metaDataMimeOwner(), false); 0442 QDomElement mimeTypeElement = cd(metaDataNode, QStringLiteral("mime:mime-type"), false).toElement(); 0443 return mimeTypeElement.attribute(QStringLiteral("type")); 0444 } 0445 0446 void KBookmark::setMimeType(const QString &mimeType) 0447 { 0448 QDomNode metaDataNode = metaData(Strings::metaDataMimeOwner(), true); 0449 QDomElement iconElement = cd_or_create(metaDataNode, QStringLiteral("mime:mime-type")).toElement(); 0450 iconElement.setAttribute(QStringLiteral("type"), mimeType); 0451 } 0452 0453 bool KBookmark::showInToolbar() const 0454 { 0455 if (element.hasAttribute(QStringLiteral("showintoolbar"))) { 0456 bool show = element.attribute(QStringLiteral("showintoolbar")) == QLatin1String("yes"); 0457 const_cast<QDomElement *>(&element)->removeAttribute(QStringLiteral("showintoolbar")); 0458 const_cast<KBookmark *>(this)->setShowInToolbar(show); 0459 } 0460 return metaDataItem(QStringLiteral("showintoolbar")) == QLatin1String("yes"); 0461 } 0462 0463 void KBookmark::setShowInToolbar(bool show) 0464 { 0465 setMetaDataItem(QStringLiteral("showintoolbar"), show ? QStringLiteral("yes") : QStringLiteral("no")); 0466 } 0467 0468 KBookmarkGroup KBookmark::parentGroup() const 0469 { 0470 return KBookmarkGroup(element.parentNode().toElement()); 0471 } 0472 0473 KBookmarkGroup KBookmark::toGroup() const 0474 { 0475 Q_ASSERT(isGroup()); 0476 return KBookmarkGroup(element); 0477 } 0478 0479 QString KBookmark::address() const 0480 { 0481 if (element.tagName() == QLatin1String("xbel")) { 0482 return QLatin1String(""); // not QString() ! 0483 } else { 0484 // Use keditbookmarks's DEBUG_ADDRESSES flag to debug this code :) 0485 if (element.parentNode().isNull()) { 0486 Q_ASSERT(false); 0487 return QStringLiteral("ERROR"); // Avoid an infinite loop 0488 } 0489 KBookmarkGroup group = parentGroup(); 0490 QString parentAddress = group.address(); 0491 int pos = group.indexOf(*this); 0492 Q_ASSERT(pos != -1); 0493 return parentAddress + QLatin1Char('/') + QString::number(pos); 0494 } 0495 } 0496 0497 int KBookmark::positionInParent() const 0498 { 0499 return parentGroup().indexOf(*this); 0500 } 0501 0502 QDomElement KBookmark::internalElement() const 0503 { 0504 return element; 0505 } 0506 0507 KBookmark KBookmark::standaloneBookmark(const QString &text, const QUrl &url, const QString &icon) 0508 { 0509 QDomDocument doc(QStringLiteral("xbel")); 0510 QDomElement elem = doc.createElement(QStringLiteral("xbel")); 0511 doc.appendChild(elem); 0512 KBookmarkGroup grp(elem); 0513 grp.addBookmark(text, url, icon); 0514 return grp.first(); 0515 } 0516 0517 QString KBookmark::commonParent(const QString &first, const QString &second) 0518 { 0519 QString A = first; 0520 QString B = second; 0521 QString error(QStringLiteral("ERROR")); 0522 if (A == error || B == error) { 0523 return error; 0524 } 0525 0526 A += QLatin1Char('/'); 0527 B += QLatin1Char('/'); 0528 0529 int lastCommonSlash = 0; 0530 int lastPos = A.length() < B.length() ? A.length() : B.length(); 0531 for (int i = 0; i < lastPos; ++i) { 0532 if (A[i] != B[i]) { 0533 return A.left(lastCommonSlash); 0534 } 0535 if (A[i] == QLatin1Char('/')) { 0536 lastCommonSlash = i; 0537 } 0538 } 0539 return A.left(lastCommonSlash); 0540 } 0541 0542 void KBookmark::updateAccessMetadata() 0543 { 0544 // qCDebug(KBOOKMARKS_LOG) << "KBookmark::updateAccessMetadata " << address() << " " << url(); 0545 0546 const uint timet = QDateTime::currentDateTimeUtc().toSecsSinceEpoch(); 0547 setMetaDataItem(QStringLiteral("time_added"), QString::number(timet), DontOverwriteMetaData); 0548 setMetaDataItem(QStringLiteral("time_visited"), QString::number(timet)); 0549 0550 QString countStr = metaDataItem(QStringLiteral("visit_count")); // TODO use spec'ed name 0551 bool ok; 0552 int currentCount = countStr.toInt(&ok); 0553 if (!ok) { 0554 currentCount = 0; 0555 } 0556 currentCount++; 0557 setMetaDataItem(QStringLiteral("visit_count"), QString::number(currentCount)); 0558 0559 // TODO - time_modified 0560 } 0561 0562 QString KBookmark::parentAddress(const QString &address) 0563 { 0564 return address.left(address.lastIndexOf(QLatin1Char('/'))); 0565 } 0566 0567 uint KBookmark::positionInParent(const QString &address) 0568 { 0569 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 0570 return QStringView(address).mid(address.lastIndexOf(QLatin1Char('/')) + 1).toInt(); 0571 #else 0572 return address.midRef(address.lastIndexOf(QLatin1Char('/')) + 1).toInt(); 0573 #endif 0574 } 0575 0576 QString KBookmark::previousAddress(const QString &address) 0577 { 0578 uint pp = positionInParent(address); 0579 return pp > 0 ? parentAddress(address) + QLatin1Char('/') + QString::number(pp - 1) : QString(); 0580 } 0581 0582 QString KBookmark::nextAddress(const QString &address) 0583 { 0584 return parentAddress(address) + QLatin1Char('/') + QString::number(positionInParent(address) + 1); 0585 } 0586 0587 QDomNode KBookmark::metaData(const QString &owner, bool create) const 0588 { 0589 QDomNode infoNode = cd(internalElement(), QStringLiteral("info"), create); 0590 if (infoNode.isNull()) { 0591 return QDomNode(); 0592 } 0593 return findMetadata(owner, infoNode, create); 0594 } 0595 0596 QString KBookmark::metaDataItem(const QString &key) const 0597 { 0598 QDomNode metaDataNode = metaData(Strings::metaDataKDEOwner(), false); 0599 for (QDomElement e = metaDataNode.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) { 0600 if (e.tagName() == key) { 0601 return e.text(); 0602 } 0603 } 0604 return QString(); 0605 } 0606 0607 void KBookmark::setMetaDataItem(const QString &key, const QString &value, MetaDataOverwriteMode mode) 0608 { 0609 QDomNode metaDataNode = metaData(Strings::metaDataKDEOwner(), true); 0610 QDomNode item = cd_or_create(metaDataNode, key); 0611 QDomText text = get_or_create_text(item); 0612 if (mode == DontOverwriteMetaData && !text.data().isEmpty()) { 0613 return; 0614 } 0615 0616 text.setData(value); 0617 } 0618 0619 bool KBookmark::operator==(const KBookmark &rhs) const 0620 { 0621 return element == rhs.element; 0622 } 0623 0624 //// 0625 0626 KBookmarkGroupTraverser::~KBookmarkGroupTraverser() 0627 { 0628 } 0629 0630 void KBookmarkGroupTraverser::traverse(const KBookmarkGroup &root) 0631 { 0632 QStack<KBookmarkGroup> stack; 0633 stack.push(root); 0634 KBookmark bk = root.first(); 0635 for (;;) { 0636 if (bk.isNull()) { 0637 if (stack.count() == 1) { // only root is on the stack 0638 return; 0639 } 0640 if (!stack.isEmpty()) { 0641 visitLeave(stack.top()); 0642 bk = stack.pop(); 0643 } 0644 bk = stack.top().next(bk); 0645 } else if (bk.isGroup()) { 0646 KBookmarkGroup gp = bk.toGroup(); 0647 visitEnter(gp); 0648 bk = gp.first(); 0649 stack.push(gp); 0650 } else { 0651 visit(bk); 0652 bk = stack.top().next(bk); 0653 } 0654 } 0655 } 0656 0657 void KBookmarkGroupTraverser::visit(const KBookmark &) 0658 { 0659 } 0660 0661 void KBookmarkGroupTraverser::visitEnter(const KBookmarkGroup &) 0662 { 0663 } 0664 0665 void KBookmarkGroupTraverser::visitLeave(const KBookmarkGroup &) 0666 { 0667 } 0668 0669 void KBookmark::populateMimeData(QMimeData *mimeData) const 0670 { 0671 KBookmark::List bookmarkList; 0672 bookmarkList.append(*this); 0673 bookmarkList.populateMimeData(mimeData); 0674 } 0675 0676 KBookmark::List::List() 0677 : QList<KBookmark>() 0678 { 0679 } 0680 0681 void KBookmark::List::populateMimeData(QMimeData *mimeData) const 0682 { 0683 QList<QUrl> urls; 0684 0685 QDomDocument doc(QStringLiteral("xbel")); 0686 QDomElement elem = doc.createElement(QStringLiteral("xbel")); 0687 doc.appendChild(elem); 0688 0689 for (const_iterator it = begin(), end = this->end(); it != end; ++it) { 0690 urls.append((*it).url()); 0691 elem.appendChild((*it).internalElement().cloneNode(true /* deep */)); 0692 } 0693 0694 // This sets text/uri-list and text/plain into the mimedata 0695 mimeData->setUrls(urls); 0696 0697 mimeData->setData(Strings::xbelMimeType(), doc.toByteArray()); 0698 } 0699 0700 bool KBookmark::List::canDecode(const QMimeData *mimeData) 0701 { 0702 return mimeData->hasFormat(Strings::xbelMimeType()) || mimeData->hasUrls(); 0703 } 0704 0705 QStringList KBookmark::List::mimeDataTypes() 0706 { 0707 return QStringList() << Strings::xbelMimeType() << KUrlMimeData::mimeDataTypes(); 0708 } 0709 0710 KBookmark::List KBookmark::List::fromMimeData(const QMimeData *mimeData, QDomDocument &doc) 0711 { 0712 KBookmark::List bookmarks; 0713 const QByteArray payload = mimeData->data(Strings::xbelMimeType()); 0714 if (!payload.isEmpty()) { 0715 doc.setContent(payload); 0716 QDomElement elem = doc.documentElement(); 0717 const QDomNodeList children = elem.childNodes(); 0718 bookmarks.reserve(children.count()); 0719 for (int childno = 0; childno < children.count(); childno++) { 0720 bookmarks.append(KBookmark(children.item(childno).toElement())); 0721 } 0722 return bookmarks; 0723 } 0724 const QList<QUrl> urls = KUrlMimeData::urlsFromMimeData(mimeData); 0725 bookmarks.reserve(urls.size()); 0726 for (int i = 0; i < urls.size(); ++i) { 0727 const QUrl url = urls.at(i); 0728 bookmarks.append(KBookmark::standaloneBookmark(url.toDisplayString(), url, QString() /*TODO icon*/)); 0729 } 0730 return bookmarks; 0731 }