From eea675e1f33d29550c9f3e90eb6b6b2402e5ef37 Mon Sep 17 00:00:00 2001
From: Aqua-sama <aqua@iserlohn-fortress.net>
Date: Tue, 28 Jan 2020 14:59:23 +0200
Subject: Add bookmarks toolbar

Bookmarks Toolbar displays the contents of the top-level "Bookmarks
Toolbar" folder.
---
 src/bookmarks/bookmarkstoolbar.cpp | 62 ++++++++++++++++++++++++++++++++++++++
 src/bookmarks/bookmarkstoolbar.h   | 29 ++++++++++++++++++
 src/bookmarks/bookmarkswidget.cpp  | 58 +++++++++++++++++------------------
 src/bookmarks/bookmarkswidget.h    |  3 +-
 src/bookmarks/builtins.cpp         |  5 ++-
 src/mainwindow/mainwindow.cpp      |  6 ++++
 src/meson.build                    |  2 +-
 7 files changed, 131 insertions(+), 34 deletions(-)
 create mode 100644 src/bookmarks/bookmarkstoolbar.cpp
 create mode 100644 src/bookmarks/bookmarkstoolbar.h

(limited to 'src')

diff --git a/src/bookmarks/bookmarkstoolbar.cpp b/src/bookmarks/bookmarkstoolbar.cpp
new file mode 100644
index 0000000..11dd712
--- /dev/null
+++ b/src/bookmarks/bookmarkstoolbar.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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 "bookmarkstoolbar.h"
+#include "bookmarkmodel.h"
+#include "mainwindow/mainwindow.h"
+#include <QMenu>
+
+BookmarksToolbar::BookmarksToolbar(const BookmarkModel *model, MainWindow *parent)
+    : QToolBar(parent)
+{
+    m_window = parent;
+
+    const auto *root = model->root();
+    for(int i = 0; i < root->childCount(); ++i) {
+        const auto *child = root->child(i);
+        if(child->type() == BookmarkItem::Folder && child->data(BookmarkItem::Title).toString() == "Bookmarks Toolbar") {
+            addFolder(child);
+            break;
+        }
+    }
+}
+
+void BookmarksToolbar::addBookmark(const BookmarkItem *item, QMenu *where)
+{
+    QAction *action = nullptr;
+    if(where)
+        action = where->addAction(item->data(BookmarkItem::Title).toString());
+    else
+        action = addAction(item->data(BookmarkItem::Title).toString());
+
+    action->setIcon(item->icon());
+
+    const auto url = item->data(BookmarkItem::Href).toUrl();
+    connect(action, &QAction::triggered, m_window, [this, url]() {
+        m_window->createTab(url);
+    });
+}
+
+void BookmarksToolbar::addFolder(const BookmarkItem *item, QMenu *where)
+{
+    for(int i = 0; i < item->childCount(); ++i) {
+        auto *child = item->child(i);
+
+        if(child->type() == BookmarkItem::Bookmark)
+            addBookmark(child, where);
+
+        else if(child->type() == BookmarkItem::Folder) {
+            auto *action = addAction(child->data(BookmarkItem::Title).toString());
+            //action->setIcon(child->icon());
+
+            auto *menu = new QMenu(this);
+            addFolder(child, menu);
+            action->setMenu(menu);
+        }
+    }
+}
diff --git a/src/bookmarks/bookmarkstoolbar.h b/src/bookmarks/bookmarkstoolbar.h
new file mode 100644
index 0000000..b3cb19d
--- /dev/null
+++ b/src/bookmarks/bookmarkstoolbar.h
@@ -0,0 +1,29 @@
+/*
+ * 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 BOOKMARKSTOOLBAR
+#define BOOKMARKSTOOLBAR
+
+#include <QToolBar>
+
+class BookmarkModel;
+class BookmarkItem;
+class MainWindow;
+class BookmarksToolbar : public QToolBar
+{
+public:
+    explicit BookmarksToolbar(const BookmarkModel *model, MainWindow *parent = nullptr);
+
+private:
+    void addBookmark(const BookmarkItem *item, QMenu *where = nullptr);
+    void addFolder(const BookmarkItem *item, QMenu *where = nullptr);
+
+    MainWindow *m_window = nullptr;
+};
+
+#endif // BOOKMARKSTOOLBAR
diff --git a/src/bookmarks/bookmarkswidget.cpp b/src/bookmarks/bookmarkswidget.cpp
index bd2d607..21739e7 100644
--- a/src/bookmarks/bookmarkswidget.cpp
+++ b/src/bookmarks/bookmarkswidget.cpp
@@ -7,47 +7,47 @@
  */
 
 #include "bookmarkswidget.h"
+#include "bookmarkmodel.h"
 #include "editbookmarkdialog.h"
 #include "ui_bookmarksform.h"
-#include "bookmarkformat.h"
+#include <QFileDialog>
 #include <QTreeView>
 #include <QUrl>
-#include <QFileDialog>
 
-inline void expandChildren(QTreeView *view, BookmarkModel *model, const QModelIndex &rootIndex)
+inline void expandChildren(QTreeView *view, BookmarkModel *m_model, const QModelIndex &rootIndex)
 {
-    for(int i = 0; i < model->rowCount(rootIndex); ++i) {
-        QModelIndex idx = model->index(i, 0, rootIndex);
-        if(model->isItemExpanded(idx))
+    for(int i = 0; i < m_model->rowCount(rootIndex); ++i) {
+        QModelIndex idx = m_model->index(i, 0, rootIndex);
+        if(m_model->isItemExpanded(idx))
             view->expand(idx);
 
         // check if index has children
-        if(model->rowCount(idx) > 0)
-            expandChildren(view, model, idx);
+        if(m_model->rowCount(idx) > 0)
+            expandChildren(view, m_model, idx);
     }
 }
 
-inline void loadModel(const QString &path, BookmarkModel *model, QTreeView *view)
+inline void loadModel(const QString &path, BookmarkModel *m_model, QTreeView *view)
 {
     view->setModel(nullptr);
 
     if(path.endsWith(".xbel")) {
         QFile f(path);
         if(f.open(QIODevice::ReadOnly | QIODevice::Text)) {
-            BookmarkFormat<XbelFormat>(&f) >> model;
+            BookmarkFormat<XbelFormat>(&f) >> m_model;
             f.close();
         }
 
     } else if(path.endsWith(".json")) {
         QFile f(path);
         if(f.open(QIODevice::ReadOnly | QIODevice::Text)) {
-            BookmarkFormat<FirefoxJsonFormat>(&f) >> model;
+            BookmarkFormat<FirefoxJsonFormat>(&f) >> m_model;
             f.close();
         }
     }
 
-    view->setModel(model);
-    expandChildren(view, model, QModelIndex());
+    view->setModel(m_model);
+    expandChildren(view, m_model, QModelIndex());
 }
 
 BookmarksWidget::BookmarksWidget(const QString &path, QWidget *parent)
@@ -66,9 +66,9 @@ BookmarksWidget::BookmarksWidget(const QString &path, QWidget *parent)
     ui->deleteItem_toolButton->setIcon(style()->standardPixmap(QStyle::SP_TrashIcon));
     ui->deleteItem_toolButton->setShortcut(QKeySequence::Delete);
 
-    model = new BookmarkModel(this);
+    m_model = new BookmarkModel(this);
     m_bookmarksPath = path;
-    loadModel(path, model, ui->treeView);
+    loadModel(path, m_model, ui->treeView);
 
     // item activated
     connect(ui->treeView, &QTreeView::activated, this, [this](const QModelIndex &index) {
@@ -79,17 +79,17 @@ BookmarksWidget::BookmarksWidget(const QString &path, QWidget *parent)
     });
 
     connect(ui->treeView, &QTreeView::expanded, this, [this](const QModelIndex &index) {
-        model->setItemExpanded(index, true);
+        m_model->setItemExpanded(index, true);
     });
     connect(ui->treeView, &QTreeView::collapsed, this, [this](const QModelIndex &index) {
-        model->setItemExpanded(index, false);
+        m_model->setItemExpanded(index, false);
     });
 
     ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
     connect(ui->treeView, &QTreeView::customContextMenuRequested, this, [this](const QPoint &pos) {
         const QModelIndex idx = ui->treeView->indexAt(pos);
         if(idx.isValid()) {
-            const QUrl url = model->data(idx, 1, Qt::DisplayRole).toUrl();
+            const QUrl url = m_model->data(idx, 1, Qt::DisplayRole).toUrl();
             const QPoint _pos = ui->treeView->viewport()->mapToGlobal(pos);
 
             emit showContextMenu(url, _pos);
@@ -98,16 +98,16 @@ BookmarksWidget::BookmarksWidget(const QString &path, QWidget *parent)
 
     // addBookmark
     connect(ui->addBookmark_toolButton, &QToolButton::clicked, this, [this]() {
-        const QModelIndex idx = model->parentFolder(ui->treeView->currentIndex());
-        const QModelIndex childIdx = model->appendBookmark(tr("Title"), QString(), idx);
+        const QModelIndex idx = m_model->parentFolder(ui->treeView->currentIndex());
+        const QModelIndex childIdx = m_model->appendBookmark(tr("Title"), QString(), idx);
         ui->treeView->setCurrentIndex(childIdx);
         editBookmark(childIdx);
     });
 
     // addFolder
     connect(ui->addFolder_toolButton, &QToolButton::clicked, this, [this]() {
-        const QModelIndex idx = model->parentFolder(ui->treeView->currentIndex());
-        const QModelIndex childIdx = model->appendFolder(tr("Title"), idx);
+        const QModelIndex idx = m_model->parentFolder(ui->treeView->currentIndex());
+        const QModelIndex childIdx = m_model->appendFolder(tr("Title"), idx);
         ui->treeView->setCurrentIndex(childIdx);
         editBookmark(childIdx);
     });
@@ -115,14 +115,14 @@ BookmarksWidget::BookmarksWidget(const QString &path, QWidget *parent)
     // deleteItem
     connect(ui->deleteItem_toolButton, &QToolButton::clicked, this, [this]() {
         const QModelIndex idx = ui->treeView->currentIndex();
-        model->removeRow(idx.row(), idx.parent());
+        m_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);
+            loadModel(path, m_model, ui->treeView);
         }
     });
 }
@@ -134,30 +134,30 @@ BookmarksWidget::~BookmarksWidget()
 
 void BookmarksWidget::editBookmark(const QModelIndex &index)
 {
-    auto *dlg = new EditBookmarkDialog(model, index, this);
+    auto *dlg = new EditBookmarkDialog(m_model, index, this);
     dlg->exec();
 }
 
 void BookmarksWidget::save()
 {
-    if(!model->isModified())
+    if(!m_model->isModified())
         return;
 
     QFile bookmarksFile(m_bookmarksPath);
     if(bookmarksFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
         BookmarkFormat<XbelFormat> f(&bookmarksFile);
-        model >> f;
+        m_model >> f;
         bookmarksFile.flush();
     }
 }
 
 void BookmarksWidget::addBookmark(const QString &title, const QString &url)
 {
-    model->appendBookmark(title, url, QModelIndex());
+    m_model->appendBookmark(title, url, QModelIndex());
 }
 
 void BookmarksWidget::search(const QString &term, const std::function<void(QStringList &)> &callback) const
 {
-    QStringList ret = model->search(term);
+    QStringList ret = m_model->search(term);
     callback(ret);
 }
diff --git a/src/bookmarks/bookmarkswidget.h b/src/bookmarks/bookmarkswidget.h
index 149d2a6..432d936 100644
--- a/src/bookmarks/bookmarkswidget.h
+++ b/src/bookmarks/bookmarkswidget.h
@@ -28,6 +28,7 @@ class BookmarksWidget : public QWidget
 public:
     explicit BookmarksWidget(const QString &path, QWidget *parent = nullptr);
     ~BookmarksWidget() override;
+    const BookmarkModel *model() const { return m_model; };
 
 protected:
     void editBookmark(const QModelIndex &index);
@@ -44,7 +45,7 @@ public slots:
 private:
     Ui::BookmarksDialog *ui;
     QString m_bookmarksPath;
-    BookmarkModel *model;
+    BookmarkModel *m_model;
 };
 
 #endif // BOOKMARKSDIALOG_H
diff --git a/src/bookmarks/builtins.cpp b/src/bookmarks/builtins.cpp
index 259bfa6..2e97e1a 100644
--- a/src/bookmarks/builtins.cpp
+++ b/src/bookmarks/builtins.cpp
@@ -7,7 +7,7 @@
  */
 
 #include "builtins.h"
-#include "bookmarkformat.h"
+#include "bookmarkmodel.h"
 #include "configuration.h"
 #include <QBuffer>
 #include <QFile>
@@ -18,8 +18,7 @@ int builtins::bookmarks(const std::string &progname, std::vector<std::string>::c
 {
     args::ArgumentParser parser("bookmarks",
         "If an output location is not specified, this command will append imported bookmarks to the browser's bookmarks.\n"
-        "If an output location is specified, this command will load all XBEL-format bookmarks, then all JSON-format bookmarks, and write them to the output location."
-    );
+        "If an output location is specified, this command will load all XBEL-format bookmarks, then all JSON-format bookmarks, and write them to the output location.");
     parser.Prog(progname);
 
     args::HelpFlag help(parser, "help", "Display this help message and exit.", { 'h', "help" });
diff --git a/src/mainwindow/mainwindow.cpp b/src/mainwindow/mainwindow.cpp
index 558fe49..5386aab 100644
--- a/src/mainwindow/mainwindow.cpp
+++ b/src/mainwindow/mainwindow.cpp
@@ -8,6 +8,8 @@
 
 #include "mainwindow.h"
 #include "addressbar.h"
+#include "bookmarks/bookmarkstoolbar.h"
+#include "bookmarks/bookmarkswidget.h"
 #include "browser.h"
 #include "configuration.h"
 #include "menubar.h"
@@ -76,6 +78,10 @@ MainWindow::MainWindow(QWidget *parent)
     addressBar = new AddressBar(this);
     navigationToolBar->addWidget(addressBar);
 
+    Browser *app = qobject_cast<Browser *>(qApp);
+    this->addToolBarBreak();
+    this->addToolBar(new BookmarksToolbar(app->bookmarks()->model(), this));
+
     mdiArea->setBackground(Qt::NoBrush);
     setCentralWidget(mdiArea);
     mdiArea->setFocus();
diff --git a/src/meson.build b/src/meson.build
index 95f81f7..12c41c8 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -38,7 +38,7 @@ poi_sourceset.add(files(
     'mainwindow/widgets/navigationbar.cpp',
     'mainwindow/widgets/searchform.cpp',
 
-    'bookmarks/builtins.cpp', 'bookmarks/bookmarkswidget.cpp', 'bookmarks/editbookmarkdialog.cpp',
+    'bookmarks/builtins.cpp', 'bookmarks/bookmarkswidget.cpp', 'bookmarks/editbookmarkdialog.cpp', 'bookmarks/bookmarkstoolbar.cpp',
 
     'session/session.cpp',
     'session/savesessiondialog.cpp',
-- 
cgit v1.2.1