From c2d18d73b0e1a74525ec0cda36a2e2e7e5b4ff4c Mon Sep 17 00:00:00 2001 From: aqua Date: Sun, 14 Aug 2022 18:47:37 +0300 Subject: Import BookmarkModel from poi --- src/bookmarks/bookmarkstreeformat_xbel_read.cpp | 184 ++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 src/bookmarks/bookmarkstreeformat_xbel_read.cpp (limited to 'src/bookmarks/bookmarkstreeformat_xbel_read.cpp') diff --git a/src/bookmarks/bookmarkstreeformat_xbel_read.cpp b/src/bookmarks/bookmarkstreeformat_xbel_read.cpp new file mode 100644 index 00000000..e16eda27 --- /dev/null +++ b/src/bookmarks/bookmarkstreeformat_xbel_read.cpp @@ -0,0 +1,184 @@ +/* ============================================================ + * rekonq + * ============================================================ + * SPDX-License-Identifier: GPL-3.0-only + * Copyright (C) 2022 aqua + * ============================================================ + * Description: rekonq bookmarks model + * ============================================================ */ + +#include "bookmarkstreeformat_xbel.h" +#include "bookmarkstreeitem.hpp" +#include +#include + +inline void readNodeAttributes(BookmarksTreeItem *item, const QXmlStreamAttributes &attributes) +{ + // id + if (attributes.hasAttribute(xbel::attr_id)) + item->setData(BookmarksTreeItem::Id, attributes.value(xbel::attr_id).toString()); + + // added + if (attributes.hasAttribute(xbel::attr_added)) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + auto dateTime = QDateTime::fromString(attributes.value(xbel::attr_added), Qt::ISODate); +#else + auto dateTime = QDateTime::fromString(attributes.value(xbel::attr_added).toString(), Qt::ISODate); +#endif + if (!dateTime.isNull() && dateTime.isValid()) item->setData(BookmarksTreeItem::Added, dateTime); + } +} + +inline void readUrlAttributes(BookmarksTreeItem *item, const QXmlStreamAttributes &attributes) +{ + // href (required) + if (attributes.hasAttribute(xbel::attr_href)) + item->setData(BookmarksTreeItem::Href, attributes.value(xbel::attr_href).toString()); + + // visited + if (attributes.hasAttribute(xbel::attr_visited)) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + auto dateTime = QDateTime::fromString(attributes.value(xbel::attr_visited), Qt::ISODate); +#else + auto dateTime = QDateTime::fromString(attributes.value(xbel::attr_visited).toString(), Qt::ISODate); +#endif + if (!dateTime.isNull() && dateTime.isValid()) item->setData(BookmarksTreeItem::Visited, dateTime); + } + + // modified + if (attributes.hasAttribute(xbel::attr_modified)) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + auto dateTime = QDateTime::fromString(attributes.value(xbel::attr_modified), Qt::ISODate); +#else + auto dateTime = QDateTime::fromString(attributes.value(xbel::attr_modified).toString(), Qt::ISODate); +#endif + if (!dateTime.isNull() && dateTime.isValid()) item->setData(BookmarksTreeItem::Modified, dateTime); + } +} + +[[nodiscard]] inline bool readItemAttributes(BookmarksTreeItem *item, const QXmlStreamAttributes &attr) +{ + bool has_errors = false; + + switch (item->type()) { + + case BookmarksTreeItem::Root: + if (!attr.hasAttribute(xbel::attr_version)) { + has_errors = true; + // spdlog::error("xbel::read: xbel has no version"); + } + else if (attr.value(xbel::attr_version).compare(QLatin1String{xbel::attr_version_value}) != 0) { + has_errors = true; + // spdlog::error("xbel::read: unknown xbel version"); + } + readNodeAttributes(item, attr); + break; + + case BookmarksTreeItem::Folder: + readNodeAttributes(item, attr); + if (attr.hasAttribute(xbel::attr_folded)) + item->setExpanded(attr.value(xbel::attr_folded).compare(QLatin1String{xbel::attr_folded_yes}) != 0); + break; + + case BookmarksTreeItem::Separator: + break; + + case BookmarksTreeItem::Bookmark: + readNodeAttributes(item, attr); + readUrlAttributes(item, attr); + break; + + case BookmarksTreeItem::Alias: + if (!attr.hasAttribute(xbel::attr_ref)) { + has_errors = true; + // spdlog::error("xbel::read: Alias has no ref"); + } + else + item->setData(BookmarksTreeItem::Id, attr.value(xbel::attr_ref).toString()); + break; + + default: + return false; + } + + return has_errors; +} + +/** + * Recursively parse XBEL + * @param reader + * @param parent + * @return true if there were errors during parsing + */ +[[nodiscard]] inline bool readChildElements(QXmlStreamReader &reader, BookmarksTreeItem *parent) +{ + bool has_errors = false; + + while (reader.readNextStartElement()) { + if (reader.hasError()) { + has_errors = true; + // spdlog::warn("xbel::read: error during parsing: {}", qUtf8Printable(reader.errorString())); + } + + const auto name = reader.name(); + if (name == xbel::elem_title) { parent->setData(BookmarksTreeItem::Title, reader.readElementText()); } + else if (name == xbel::elem_desc) { + parent->setData(BookmarksTreeItem::Description, reader.readElementText()); + } + else if (name == xbel::elem_info) { + has_errors += readChildElements(reader, parent); + } + else if (name == xbel::elem_metadata) { + if (reader.attributes().value(xbel::elem_metadata_owner) == QLatin1String{xbel::elem_metadata_owner_value}) + parent->metadata.append(reader.readElementText()); + else + reader.skipCurrentElement(); + } + else if (name == xbel::elem_bookmark) { + + auto *item = new BookmarksTreeItem(BookmarksTreeItem::Bookmark, {}, parent); + has_errors += readItemAttributes(item, reader.attributes()); + if (!parent->appendChild(item)) has_errors = true; + has_errors += readChildElements(reader, item); + } + else if (name == xbel::elem_folder) { + auto *item = new BookmarksTreeItem(BookmarksTreeItem::Folder, {}, parent); + has_errors += readItemAttributes(item, reader.attributes()); + if (!parent->appendChild(item)) has_errors = true; + has_errors += readChildElements(reader, item); + } + else if (name == xbel::elem_separator) { + auto *item = new BookmarksTreeItem(BookmarksTreeItem::Separator, {}, parent); + if (!parent->appendChild(item)) has_errors = true; + reader.skipCurrentElement(); + } + else if (name == xbel::elem_alias) { + auto *item = new BookmarksTreeItem(BookmarksTreeItem::Alias, {}, parent); + item->setData(BookmarksTreeItem::Id, reader.attributes().value(xbel::attr_ref).toString()); + if (!parent->appendChild(item)) has_errors = true; + reader.skipCurrentElement(); + } + else { + // spdlog::error("xbel::read: skipping unknown element {} on line {}", qUtf8Printable(name.toString()), + // reader.lineNumber()); + has_errors = true; + reader.skipCurrentElement(); + } + } + + return has_errors; +} + +bool xbel::read(QIODevice *device, BookmarksTreeItem *root) +{ + if (!device->isOpen()) return false; + + QXmlStreamReader reader(device); + if (!reader.readNextStartElement()) return false; + + // parse the top-level item attributes + if (reader.name().compare(QLatin1String{elem_xbel}) != 0) return false; + if (readItemAttributes(root, reader.attributes())) return false; + + return !readChildElements(reader, root); +} -- cgit v1.2.1