summaryrefslogtreecommitdiff
path: root/src/bookmarks/bookmarkstreeformat_xbel_read.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bookmarks/bookmarkstreeformat_xbel_read.cpp')
-rw-r--r--src/bookmarks/bookmarkstreeformat_xbel_read.cpp184
1 files changed, 184 insertions, 0 deletions
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 <aqua@iserlohn-fortress.net>
+ * ============================================================
+ * Description: rekonq bookmarks model
+ * ============================================================ */
+
+#include "bookmarkstreeformat_xbel.h"
+#include "bookmarkstreeitem.hpp"
+#include <QDateTime>
+#include <QXmlStreamReader>
+
+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);
+}