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