aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2020-01-17 13:39:59 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2020-01-17 13:39:59 +0200
commit4c73f86fc6cbdaaee90f9f8e40af36c1ab84c374 (patch)
tree63b42986ffccb3c0fdb3b978f3c78b56ca5a03a8
parentCreate default profile when the one set doesn't exist (diff)
parentParse Tags and Descriptions in FFJson (diff)
downloadsmolbote-4c73f86fc6cbdaaee90f9f8e40af36c1ab84c374.tar.xz
Merge branch 'firefox-bookmarks-json-importer'
-rw-r--r--lib/bookmarks/bookmarkformat.cpp (renamed from lib/bookmarks/formats/format.cpp)17
-rw-r--r--lib/bookmarks/bookmarkformat.h65
-rw-r--r--lib/bookmarks/bookmarkitem.cpp (renamed from lib/bookmarks/model/bookmarkitem.cpp)0
-rw-r--r--lib/bookmarks/bookmarkitem.h (renamed from lib/bookmarks/model/bookmarkitem.h)2
-rw-r--r--lib/bookmarks/bookmarkmodel.cpp (renamed from lib/bookmarks/model/bookmarkmodel.cpp)3
-rw-r--r--lib/bookmarks/bookmarkmodel.h (renamed from lib/bookmarks/model/bookmarkmodel.h)0
-rw-r--r--lib/bookmarks/formats/ffjson.cpp72
-rw-r--r--lib/bookmarks/formats/ffjson.h19
-rw-r--r--lib/bookmarks/formats/format.h36
-rw-r--r--lib/bookmarks/formats/xbel.cpp26
-rw-r--r--lib/bookmarks/meson.build13
-rw-r--r--meson.build1
-rw-r--r--src/bookmarks/bookmarksform.ui (renamed from lib/bookmarks/bookmarksform.ui)13
-rw-r--r--src/bookmarks/bookmarkswidget.cpp (renamed from lib/bookmarks/bookmarkswidget.cpp)55
-rw-r--r--src/bookmarks/bookmarkswidget.h (renamed from lib/bookmarks/bookmarkswidget.h)0
-rw-r--r--src/bookmarks/editbookmarkdialog.cpp (renamed from lib/bookmarks/forms/editbookmarkdialog.cpp)8
-rw-r--r--src/bookmarks/editbookmarkdialog.h (renamed from lib/bookmarks/forms/editbookmarkdialog.h)0
-rw-r--r--src/bookmarks/editbookmarkdialog.ui (renamed from lib/bookmarks/forms/editbookmarkdialog.ui)0
-rw-r--r--src/browser.cpp2
-rw-r--r--src/mainwindow/menubar.cpp2
-rw-r--r--src/meson.build8
-rw-r--r--test/firefox-bookmarks-json-parser/main.cpp35
-rw-r--r--test/firefox-bookmarks-json-parser/meson.build13
23 files changed, 311 insertions, 79 deletions
diff --git a/lib/bookmarks/formats/format.cpp b/lib/bookmarks/bookmarkformat.cpp
index 551151c..87b816c 100644
--- a/lib/bookmarks/formats/format.cpp
+++ b/lib/bookmarks/bookmarkformat.cpp
@@ -6,21 +6,26 @@
* SPDX-License-Identifier: GPL-3.0
*/
-#include "format.h"
-#include "xbel.h"
+#include "bookmarkformat.h"
+#include "formats/xbel.h"
+#include "formats/ffjson.h"
#include <QIODevice>
template<>
-void BookmarksFormat<BookmarksFormats::XbelFormat>::read(BookmarkItem *root)
+void BookmarkFormat<BookmarkFormats::XbelFormat>::read(BookmarkItem *root) const
{
- Q_CHECK_PTR(m_device);
Xbel::read(m_device, root);
}
template<>
-void BookmarksFormat<BookmarksFormats::XbelFormat>::write(BookmarkItem *root)
+void BookmarkFormat<BookmarkFormats::XbelFormat>::write(BookmarkItem *root)
{
- Q_CHECK_PTR(m_device);
Xbel::write(m_device, root);
}
+template<>
+void BookmarkFormat<BookmarkFormats::FirefoxJsonFormat>::read(BookmarkItem *root) const
+{
+ FFJson::read(m_device, root);
+}
+
diff --git a/lib/bookmarks/bookmarkformat.h b/lib/bookmarks/bookmarkformat.h
new file mode 100644
index 0000000..c886546
--- /dev/null
+++ b/lib/bookmarks/bookmarkformat.h
@@ -0,0 +1,65 @@
+/*
+ * This file is part of smolbote. It's copyrighted by the contributors recorded
+ * in the version control history of the file, available from its original
+ * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#ifndef BOOKMARKFORMAT_H
+#define BOOKMARKFORMAT_H
+
+#include "bookmarkmodel.h"
+
+class QIODevice;
+
+enum BookmarkFormats {
+ XbelFormat,
+ FirefoxJsonFormat
+};
+
+template<BookmarkFormats format>
+class BookmarkFormat
+{
+public:
+ explicit BookmarkFormat(QIODevice *device)
+ {
+ Q_CHECK_PTR(device);
+ m_device = device;
+ }
+
+ void read(BookmarkItem *root) const;
+ void write(BookmarkItem *root);
+
+protected:
+ QIODevice *m_device;
+};
+
+template<BookmarkFormats T>
+void operator<<(BookmarkModel *model, const BookmarkFormat<T> &format)
+{
+ format.read(model->root());
+}
+
+template<BookmarkFormats T>
+void operator>>(const BookmarkFormat<T> &format, BookmarkModel *model)
+{
+ format.read(model->root());
+}
+
+template<BookmarkFormats T>
+void operator<<(BookmarkFormat<T> &format, BookmarkModel *model)
+{
+ format.write(model->root());
+ model->resetModified();
+}
+
+template<BookmarkFormats T>
+void operator>>(BookmarkModel *model, BookmarkFormat<T> &format)
+{
+ format.write(model->root());
+ model->resetModified();
+}
+
+#endif // BOOKMARKSFORMAT_H
+
diff --git a/lib/bookmarks/model/bookmarkitem.cpp b/lib/bookmarks/bookmarkitem.cpp
index 21d034f..21d034f 100644
--- a/lib/bookmarks/model/bookmarkitem.cpp
+++ b/lib/bookmarks/bookmarkitem.cpp
diff --git a/lib/bookmarks/model/bookmarkitem.h b/lib/bookmarks/bookmarkitem.h
index 8c9463f..6751526 100644
--- a/lib/bookmarks/model/bookmarkitem.h
+++ b/lib/bookmarks/bookmarkitem.h
@@ -27,6 +27,8 @@ public:
Href,
Tags,
Description,
+ DateAdded,
+ LastModified,
FieldCount
};
diff --git a/lib/bookmarks/model/bookmarkmodel.cpp b/lib/bookmarks/bookmarkmodel.cpp
index 895b178..05df3d7 100644
--- a/lib/bookmarks/model/bookmarkmodel.cpp
+++ b/lib/bookmarks/bookmarkmodel.cpp
@@ -12,6 +12,7 @@
#include <QBuffer>
#include <QMimeData>
#include <QRegularExpression>
+#include <QDateTime>
BookmarkModel::BookmarkModel(QObject *parent)
: QAbstractItemModel(parent)
@@ -132,6 +133,7 @@ QModelIndex BookmarkModel::appendBookmark(const QString &title, const QString &u
int row = parentItem->childCount();
beginInsertRows(parent, row, row);
auto *childItem = new BookmarkItem({ title, url }, BookmarkItem::Bookmark, parentItem);
+ childItem->setData(BookmarkItem::DateAdded, QDateTime::currentDateTime());
parentItem->appendChild(childItem);
endInsertRows();
@@ -146,6 +148,7 @@ QModelIndex BookmarkModel::appendFolder(const QString &title, const QModelIndex
beginInsertRows(parent, row, row);
auto *childItem = new BookmarkItem({ title }, BookmarkItem::Folder, parentItem);
+ childItem->setData(BookmarkItem::DateAdded, QDateTime::currentDateTime());
parentItem->appendChild(childItem);
endInsertRows();
diff --git a/lib/bookmarks/model/bookmarkmodel.h b/lib/bookmarks/bookmarkmodel.h
index 300b724..300b724 100644
--- a/lib/bookmarks/model/bookmarkmodel.h
+++ b/lib/bookmarks/bookmarkmodel.h
diff --git a/lib/bookmarks/formats/ffjson.cpp b/lib/bookmarks/formats/ffjson.cpp
new file mode 100644
index 0000000..1fe6a96
--- /dev/null
+++ b/lib/bookmarks/formats/ffjson.cpp
@@ -0,0 +1,72 @@
+/*
+ * This file is part of smolbote. It's copyrighted by the contributors recorded
+ * in the version control history of the file, available from its original
+ * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#include "ffjson.h"
+#include "bookmarkitem.h"
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QDebug>
+#include <QDateTime>
+
+inline auto asDate(const QJsonValue &v)
+{
+ // timestamps in bookmarks.json are, for some reason, in *micro*seconds
+ return QDateTime::fromMSecsSinceEpoch(v.toVariant().toLongLong() / 1000);
+}
+
+inline void readElementData(const QJsonObject &object, BookmarkItem *item)
+{
+ item->setData(BookmarkItem::Title, object["title"].toString());
+ item->setData(BookmarkItem::DateAdded, asDate(object["dateAdded"]));
+ item->setData(BookmarkItem::LastModified, asDate(object["lastModified"]));
+
+ // tags
+ const auto tags = object["tags"].toString().split(",");
+ if(!tags.isEmpty())
+ item->setData(BookmarkItem::Tags, tags);
+
+ // descriptions
+ for(const auto &a : object["annos"].toArray()) {
+ const auto anno = a.toObject();
+ if(anno["name"] == "bookmarkProperties/description") {
+ item->setData(BookmarkItem::Description, anno["value"].toString());
+ }
+ }
+}
+
+void readChildElements(const QJsonObject &object, BookmarkItem *item)
+{
+ for(const auto c : object["children"].toArray()) {
+ const auto child = c.toObject();
+ const auto type = child["type"].toString();
+
+ if(type == "text/x-moz-place-container") {
+ auto *childItem = new BookmarkItem({}, BookmarkItem::Folder, item);
+ childItem->setExpanded(true);
+ readElementData(child, childItem);
+ item->appendChild(childItem);
+ readChildElements(child, childItem);
+
+ } else if(type == "text/x-moz-place") {
+ auto *childItem = new BookmarkItem({}, BookmarkItem::Bookmark, item);
+ readElementData(child, childItem);
+ childItem->setData(BookmarkItem::Href, child["uri"].toString());
+ item->appendChild(childItem);
+
+ } else {
+ qDebug() << "!!! unknown type " << qUtf8Printable(type);
+ }
+ }
+}
+
+void FFJson::read(QIODevice *device, BookmarkItem *item)
+{
+ const auto doc = QJsonDocument::fromJson(device->readAll());
+ readChildElements(doc.object(), item);
+}
diff --git a/lib/bookmarks/formats/ffjson.h b/lib/bookmarks/formats/ffjson.h
new file mode 100644
index 0000000..cc6ac24
--- /dev/null
+++ b/lib/bookmarks/formats/ffjson.h
@@ -0,0 +1,19 @@
+/*
+ * This file is part of smolbote. It's copyrighted by the contributors recorded
+ * in the version control history of the file, available from its original
+ * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#ifndef FFJSON_H
+#define FFJSON_H
+
+class QIODevice;
+class BookmarkItem;
+namespace FFJson
+{
+void read(QIODevice *device, BookmarkItem *item);
+}
+
+#endif // FFJSON_H
diff --git a/lib/bookmarks/formats/format.h b/lib/bookmarks/formats/format.h
deleted file mode 100644
index e96dfcc..0000000
--- a/lib/bookmarks/formats/format.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * This file is part of smolbote. It's copyrighted by the contributors recorded
- * in the version control history of the file, available from its original
- * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote
- *
- * SPDX-License-Identifier: GPL-3.0
- */
-
-#ifndef BOOKMARKSFORMAT_H
-#define BOOKMARKSFORMAT_H
-
-class QIODevice;
-class BookmarkItem;
-
-enum BookmarksFormats {
- XbelFormat
-};
-
-template<BookmarksFormats format>
-class BookmarksFormat
-{
-public:
- explicit BookmarksFormat(QIODevice *device)
- {
- m_device = device;
- }
-
- void read(BookmarkItem *root);
- void write(BookmarkItem *root);
-
-protected:
- QIODevice *m_device;
-};
-
-#endif // BOOKMARKSFORMAT_H
-
diff --git a/lib/bookmarks/formats/xbel.cpp b/lib/bookmarks/formats/xbel.cpp
index 1cb5756..bac2bc8 100644
--- a/lib/bookmarks/formats/xbel.cpp
+++ b/lib/bookmarks/formats/xbel.cpp
@@ -7,9 +7,10 @@
*/
#include "xbel.h"
-#include "model/bookmarkitem.h"
+#include "bookmarkitem.h"
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
+#include <QDateTime>
inline void readChildElements(QXmlStreamReader &reader, BookmarkItem *parent)
{
@@ -17,6 +18,12 @@ inline void readChildElements(QXmlStreamReader &reader, BookmarkItem *parent)
if(reader.name() == "title") {
parent->setData(BookmarkItem::Title, reader.readElementText());
+ } else if(reader.name() == "dateAdded") {
+ parent->setData(BookmarkItem::DateAdded, QDateTime::fromString(reader.readElementText(), Qt::RFC2822Date));
+
+ } else if(reader.name() == "lastModified") {
+ parent->setData(BookmarkItem::LastModified, QDateTime::fromString(reader.readElementText(), Qt::RFC2822Date));
+
} else if(reader.name() == "tags") {
parent->setData(BookmarkItem::Tags, reader.readElementText().split(";"));
@@ -54,6 +61,19 @@ void Xbel::read(QIODevice *device, BookmarkItem *item)
}
}
+inline void writeCommon(QXmlStreamWriter &writer, const BookmarkItem *item)
+{
+ writer.writeTextElement("title", item->data(BookmarkItem::Title).toString());
+
+ const auto dateAdded = item->data(BookmarkItem::DateAdded);
+ if(!dateAdded.isNull())
+ writer.writeTextElement("dateAdded", dateAdded.toDateTime().toString(Qt::RFC2822Date));
+
+ const auto lastModified = item->data(BookmarkItem::LastModified);
+ if(!lastModified.isNull())
+ writer.writeTextElement("lastModified", lastModified.toDateTime().toString(Qt::RFC2822Date));
+}
+
inline void writeChildElements(QXmlStreamWriter &writer, const BookmarkItem *item)
{
switch(item->type()) {
@@ -66,7 +86,7 @@ inline void writeChildElements(QXmlStreamWriter &writer, const BookmarkItem *ite
case BookmarkItem::Folder:
writer.writeStartElement("folder");
writer.writeAttribute("folded", !item->isExpanded() ? "yes" : "no");
- writer.writeTextElement("title", item->data(BookmarkItem::Title).toString());
+ writeCommon(writer, item);
if(!item->data(BookmarkItem::Tags).isNull())
writer.writeTextElement("tags", item->data(BookmarkItem::Tags).toStringList().join(";"));
if(!item->data(BookmarkItem::Description).isNull())
@@ -82,7 +102,7 @@ inline void writeChildElements(QXmlStreamWriter &writer, const BookmarkItem *ite
case BookmarkItem::Bookmark:
writer.writeStartElement("bookmark");
writer.writeAttribute("href", item->data(BookmarkItem::Href).toString());
- writer.writeTextElement("title", item->data(BookmarkItem::Title).toString());
+ writeCommon(writer, item);
if(!item->data(BookmarkItem::Tags).isNull())
writer.writeTextElement("tags", item->data(BookmarkItem::Tags).toStringList().join(";"));
if(!item->data(BookmarkItem::Description).isNull())
diff --git a/lib/bookmarks/meson.build b/lib/bookmarks/meson.build
index 3049e3c..81c1ece 100644
--- a/lib/bookmarks/meson.build
+++ b/lib/bookmarks/meson.build
@@ -1,19 +1,16 @@
-bookmarks_inc = include_directories('.')
bookmarks_moc = mod_qt5.preprocess(
- moc_headers: ['bookmarkswidget.h', 'model/bookmarkmodel.h', 'forms/editbookmarkdialog.h'],
- ui_files: ['bookmarksform.ui', 'forms/editbookmarkdialog.ui'],
+ moc_headers: [ 'bookmarkmodel.h' ],
dependencies: dep_qt5
)
bookmarks_lib = static_library('bookmarks',
- ['bookmarkswidget.cpp', bookmarks_moc,
- 'formats/format.cpp', 'formats/xbel.cpp',
- 'model/bookmarkitem.cpp', 'model/bookmarkmodel.cpp',
- 'forms/editbookmarkdialog.cpp'],
+ [ bookmarks_moc,
+ 'bookmarkformat.cpp', 'formats/xbel.cpp', 'formats/ffjson.cpp',
+ 'bookmarkitem.cpp', 'bookmarkmodel.cpp' ],
dependencies: dep_qt5
)
dep_bookmarks = declare_dependency(
- include_directories: bookmarks_inc,
+ include_directories: include_directories('.'),
link_with: bookmarks_lib
)
diff --git a/meson.build b/meson.build
index 32984ea..5e50801 100644
--- a/meson.build
+++ b/meson.build
@@ -88,6 +88,7 @@ subdir('tools')
#subdir('plugins/ProfileEditor')
subdir('test/conf')
+subdir('test/firefox-bookmarks-json-parser')
ssconfig = poi_sourceset.apply(cdata)
diff --git a/lib/bookmarks/bookmarksform.ui b/src/bookmarks/bookmarksform.ui
index a003e53..2dfebf4 100644
--- a/lib/bookmarks/bookmarksform.ui
+++ b/src/bookmarks/bookmarksform.ui
@@ -17,6 +17,13 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
+ <widget class="QToolButton" name="import_toolButton">
+ <property name="text">
+ <string>Import</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -66,12 +73,12 @@
<property name="defaultDropAction">
<enum>Qt::MoveAction</enum>
</property>
- <attribute name="headerDefaultSectionSize">
- <number>200</number>
- </attribute>
<attribute name="headerMinimumSectionSize">
<number>50</number>
</attribute>
+ <attribute name="headerDefaultSectionSize">
+ <number>200</number>
+ </attribute>
</widget>
</item>
<item>
diff --git a/lib/bookmarks/bookmarkswidget.cpp b/src/bookmarks/bookmarkswidget.cpp
index aed7e97..bd2d607 100644
--- a/lib/bookmarks/bookmarkswidget.cpp
+++ b/src/bookmarks/bookmarkswidget.cpp
@@ -7,13 +7,12 @@
*/
#include "bookmarkswidget.h"
-#include "forms/editbookmarkdialog.h"
-#include "model/bookmarkitem.h"
-#include "model/bookmarkmodel.h"
+#include "editbookmarkdialog.h"
#include "ui_bookmarksform.h"
-#include "formats/format.h"
+#include "bookmarkformat.h"
#include <QTreeView>
#include <QUrl>
+#include <QFileDialog>
inline void expandChildren(QTreeView *view, BookmarkModel *model, const QModelIndex &rootIndex)
{
@@ -28,6 +27,29 @@ inline void expandChildren(QTreeView *view, BookmarkModel *model, const QModelIn
}
}
+inline void loadModel(const QString &path, BookmarkModel *model, QTreeView *view)
+{
+ view->setModel(nullptr);
+
+ if(path.endsWith(".xbel")) {
+ QFile f(path);
+ if(f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ BookmarkFormat<XbelFormat>(&f) >> model;
+ f.close();
+ }
+
+ } else if(path.endsWith(".json")) {
+ QFile f(path);
+ if(f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ BookmarkFormat<FirefoxJsonFormat>(&f) >> model;
+ f.close();
+ }
+ }
+
+ view->setModel(model);
+ expandChildren(view, model, QModelIndex());
+}
+
BookmarksWidget::BookmarksWidget(const QString &path, QWidget *parent)
: QWidget(parent)
, ui(new Ui::BookmarksDialog)
@@ -46,16 +68,7 @@ BookmarksWidget::BookmarksWidget(const QString &path, QWidget *parent)
model = new BookmarkModel(this);
m_bookmarksPath = path;
- QFile bookmarksFile(m_bookmarksPath);
- if(bookmarksFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
- BookmarksFormat<XbelFormat> format(&bookmarksFile);
- format.read(model->root());
- bookmarksFile.close();
- }
- model->resetModified();
-
- ui->treeView->setModel(model);
- expandChildren(ui->treeView, model, QModelIndex());
+ loadModel(path, model, ui->treeView);
// item activated
connect(ui->treeView, &QTreeView::activated, this, [this](const QModelIndex &index) {
@@ -104,6 +117,14 @@ BookmarksWidget::BookmarksWidget(const QString &path, QWidget *parent)
const QModelIndex idx = ui->treeView->currentIndex();
model->removeRow(idx.row(), idx.parent());
});
+
+ // import button
+ connect(ui->import_toolButton, &QToolButton::clicked, this, [this]() {
+ const auto path = QFileDialog::getOpenFileName(this, tr("Open bookmarks file"), QDir::homePath(), tr("Firefox bookmarks backup (*.json)"));
+ if(!path.isEmpty()) {
+ loadModel(path, model, ui->treeView);
+ }
+ });
}
BookmarksWidget::~BookmarksWidget()
@@ -124,11 +145,9 @@ void BookmarksWidget::save()
QFile bookmarksFile(m_bookmarksPath);
if(bookmarksFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
- BookmarksFormat<XbelFormat> format(&bookmarksFile);
- format.write(model->root());
+ BookmarkFormat<XbelFormat> f(&bookmarksFile);
+ model >> f;
bookmarksFile.flush();
- bookmarksFile.close();
- model->resetModified();
}
}
diff --git a/lib/bookmarks/bookmarkswidget.h b/src/bookmarks/bookmarkswidget.h
index 149d2a6..149d2a6 100644
--- a/lib/bookmarks/bookmarkswidget.h
+++ b/src/bookmarks/bookmarkswidget.h
diff --git a/lib/bookmarks/forms/editbookmarkdialog.cpp b/src/bookmarks/editbookmarkdialog.cpp
index 9c6efa0..4461840 100644
--- a/lib/bookmarks/forms/editbookmarkdialog.cpp
+++ b/src/bookmarks/editbookmarkdialog.cpp
@@ -7,9 +7,10 @@
*/
#include "editbookmarkdialog.h"
-#include "model/bookmarkitem.h"
-#include "model/bookmarkmodel.h"
+#include "bookmarkitem.h"
+#include "bookmarkmodel.h"
#include "ui_editbookmarkdialog.h"
+#include <QDateTime>
EditBookmarkDialog::EditBookmarkDialog(BookmarkModel *model, const QModelIndex &index, QWidget *parent)
: QDialog(parent)
@@ -67,4 +68,7 @@ void EditBookmarkDialog::saveChanges()
if(descriptionChanged) {
m_model->setData(m_index, ui->description->toPlainText(), BookmarkItem::Description, Qt::DisplayRole);
}
+
+ if(titleChanged || hrefChanged || tagsChanged || descriptionChanged)
+ m_model->setData(m_index, QDateTime::currentDateTime(), BookmarkItem::LastModified, Qt::DisplayRole);
}
diff --git a/lib/bookmarks/forms/editbookmarkdialog.h b/src/bookmarks/editbookmarkdialog.h
index fb53239..fb53239 100644
--- a/lib/bookmarks/forms/editbookmarkdialog.h
+++ b/src/bookmarks/editbookmarkdialog.h
diff --git a/lib/bookmarks/forms/editbookmarkdialog.ui b/src/bookmarks/editbookmarkdialog.ui
index b988394..b988394 100644
--- a/lib/bookmarks/forms/editbookmarkdialog.ui
+++ b/src/bookmarks/editbookmarkdialog.ui
diff --git a/src/browser.cpp b/src/browser.cpp
index 42cde5e..488131e 100644
--- a/src/browser.cpp
+++ b/src/browser.cpp
@@ -10,7 +10,7 @@
#include "aboutdialog.h"
#include "aboutplugin.h"
#include "adblock/adblocklist.h"
-#include "bookmarkswidget.h"
+#include "bookmarks/bookmarkswidget.h"
#include "configuration.h"
#include "downloadswidget.h"
#include "hostlist/hostlist.h"
diff --git a/src/mainwindow/menubar.cpp b/src/mainwindow/menubar.cpp
index 7fdad24..a8d0590 100644
--- a/src/mainwindow/menubar.cpp
+++ b/src/mainwindow/menubar.cpp
@@ -7,7 +7,7 @@
*/
#include "menubar.h"
-#include "bookmarkswidget.h"
+#include "bookmarks/bookmarkswidget.h"
#include "browser.h"
#include "configuration.h"
#include "downloadswidget.h"
diff --git a/src/meson.build b/src/meson.build
index 6d6a1aa..1783455 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -10,10 +10,14 @@ poi_settings_h = custom_target('default_config_value',
poi_sourceset.add(mod_qt5.preprocess(
moc_headers: ['browser.h',
'mainwindow/mainwindow.h', 'mainwindow/addressbar.h', 'mainwindow/menubar.h', 'mainwindow/widgets/completer.h', 'mainwindow/widgets/urllineedit.h', 'mainwindow/widgets/dockwidget.h', 'mainwindow/widgets/menusearch.h', 'mainwindow/widgets/navigationbar.h', 'mainwindow/widgets/searchform.h',
+ 'bookmarks/bookmarkswidget.h', 'bookmarks/editbookmarkdialog.h',
'session/savesessiondialog.h', 'session/sessiondialog.h', 'session/sessionform.h',
'subwindow/subwindow.h', 'subwindow/tabwidget.h',
'webengine/urlinterceptor.h', 'webengine/webpage.h', 'webengine/webview.h', 'webengine/webprofilemanager.h', 'webengine/webprofile.h'],
- ui_files: ['mainwindow/addressbar.ui', 'mainwindow/widgets/searchform.ui', 'session/savesessiondialog.ui', 'session/sessiondialog.ui', 'session/sessionform.ui'],
+ ui_files: [
+ 'mainwindow/addressbar.ui', 'mainwindow/widgets/searchform.ui',
+ 'bookmarks/bookmarksform.ui', 'bookmarks/editbookmarkdialog.ui',
+ 'session/savesessiondialog.ui', 'session/sessiondialog.ui', 'session/sessionform.ui'],
qresources: '../data/resources.qrc',
rcc_extra_arguments: ['--format-version=1'],
dependencies: dep_qt5
@@ -34,6 +38,8 @@ poi_sourceset.add(files(
'mainwindow/widgets/navigationbar.cpp',
'mainwindow/widgets/searchform.cpp',
+ 'bookmarks/bookmarkswidget.cpp', 'bookmarks/editbookmarkdialog.cpp',
+
'session/session.cpp',
'session/savesessiondialog.cpp',
'session/sessiondialog.cpp',
diff --git a/test/firefox-bookmarks-json-parser/main.cpp b/test/firefox-bookmarks-json-parser/main.cpp
new file mode 100644
index 0000000..54819a2
--- /dev/null
+++ b/test/firefox-bookmarks-json-parser/main.cpp
@@ -0,0 +1,35 @@
+#include <QFile>
+#include "bookmarkformat.h"
+#include <QTreeView>
+#include <QApplication>
+#include <QDebug>
+
+int main(int argc, char** argv)
+{
+ QApplication app(argc, argv);
+
+ QFile f(qgetenv("FILE"));
+
+ auto *model = new BookmarkModel;
+
+ if(f.open(QIODevice::ReadOnly)) {
+ BookmarkFormat<FirefoxJsonFormat>(&f) >> model;
+ f.close();
+ } else
+ return -1;
+
+ auto *view = new QTreeView;
+ view->setModel(model);
+
+ if(qgetenv("NOGUI") == "1")
+ return 0;
+
+ QObject::connect(view, &QTreeView::activated, [model](const QModelIndex &index) {
+ const auto tags = model->data(index, BookmarkItem::Tags, Qt::DisplayRole).toStringList();
+ qDebug() << tags.join(" || ");
+ });
+
+
+ view->show();
+ return app.exec();
+}
diff --git a/test/firefox-bookmarks-json-parser/meson.build b/test/firefox-bookmarks-json-parser/meson.build
new file mode 100644
index 0000000..1432e68
--- /dev/null
+++ b/test/firefox-bookmarks-json-parser/meson.build
@@ -0,0 +1,13 @@
+e = executable('bookmarks-json-parser',
+ sources: [ 'main.cpp' ],
+ dependencies: [ dep_qt5, dep_bookmarks ]
+)
+
+env = environment({
+ 'NOGUI' : '1',
+ 'FILE' : 'bookmarks.json'
+})
+test('Firefox bookmarks.json parser', e,
+ env: env,
+ workdir: meson.build_root()
+)