From 396bc0c1721af8d3ee970228e7df457f6b2c73d5 Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Mon, 13 Apr 2020 15:44:09 +0300 Subject: Rewrite Session backend Add session.hpp, containing structs that describe session data MainWindow, SubWindow and WebView can be created from Session::structs Opening new window will automatically open a default subwindow and tab if none were specified Add lib/session_formats Add JsonSession, to serialize/deserialize Session structs into JSON - add some tests clang-tidy: - fix various warnings - disable modernize-use-trailing-return-type check --- lib/session_formats/meson.build | 13 +++++ lib/session_formats/session_json.cpp | 97 +++++++++++++++++++++++++++++++++ lib/session_formats/session_json.hpp | 36 ++++++++++++ lib/session_formats/test/json.cpp | 103 +++++++++++++++++++++++++++++++++++ 4 files changed, 249 insertions(+) create mode 100644 lib/session_formats/meson.build create mode 100644 lib/session_formats/session_json.cpp create mode 100644 lib/session_formats/session_json.hpp create mode 100644 lib/session_formats/test/json.cpp (limited to 'lib') diff --git a/lib/session_formats/meson.build b/lib/session_formats/meson.build new file mode 100644 index 0000000..9abf5a2 --- /dev/null +++ b/lib/session_formats/meson.build @@ -0,0 +1,13 @@ +lib_session_formats = declare_dependency( + include_directories: [ '.', include ], + link_with: library('sessionformats', + [ 'session_json.cpp' ], + include_directories: include, + dependencies: dep_qt5 + ) +) + +test('session: json format', executable('session_json', + sources: 'test/json.cpp', + dependencies: [ dep_qt5, dep_catch, lib_session_formats ] +)) diff --git a/lib/session_formats/session_json.cpp b/lib/session_formats/session_json.cpp new file mode 100644 index 0000000..eca96f2 --- /dev/null +++ b/lib/session_formats/session_json.cpp @@ -0,0 +1,97 @@ +/* + * 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://library.iserlohn-fortress.net/aqua/smolbote + * + * SPDX-License-Identifier: GPL-3.0 + */ + +#include "session_json.hpp" +#include +#include + +[[nodiscard]] QVector toWindowList(const QString &profile, const QStringList &urls) +{ + Session::SubWindow main_; + main_.profile = profile; + for(const auto &url : urls) { + main_.tabs.append({ profile, url, QByteArray() }); + } + Session::MainWindow main; + main.subwindows.append(main_); + return { main }; +} + +[[nodiscard]] QJsonObject toJson(const QVector &windows) +{ + QJsonObject root; + QJsonArray windows_; + { + for(const auto &window : windows) { + QJsonObject window_; + QJsonArray subwindows; + for(const auto &subwindow : window.subwindows) { + QJsonObject subwindow_json; + subwindow_json.insert("profile", subwindow.profile); + QJsonArray tabs; + for(const auto &tab : subwindow.tabs) { + QJsonObject tab_; + tab_.insert("profile", tab.profile); + tab_.insert("url", tab.url); + tab_.insert("history", QString::fromLatin1(tab.history.toBase64())); + tabs.append(tab_); + } + subwindow_json.insert("tabs", tabs); + subwindows.append(subwindow_json); + } + window_.insert("subwindows", subwindows); + windows_.append(window_); + } + } + root.insert("windows", windows_); + return root; +} + +JsonSession::JsonSession(const QByteArray &data) + : root(QJsonDocument::fromJson(data).object()) +{ +} + +JsonSession::JsonSession(const QVector &windows) + : root(toJson(windows)) +{ +} + +JsonSession::JsonSession(const QString &profile, const QStringList &urls) + : root(toJson(toWindowList(profile, urls))) +{ +} + +QByteArray JsonSession::serialize() const +{ + QJsonDocument doc(root); + return doc.toJson(QJsonDocument::Compact); +} + +QVector JsonSession::get() const +{ + QVector windows; + for(const auto &windowData : root["windows"].toArray()) { + Session::MainWindow window; + for(const auto &subwindowData : windowData.toObject()["subwindows"].toArray()) { + Session::SubWindow subwindow; + subwindow.profile = subwindowData.toObject()["profile"].toString(); + for(const auto &tabData : subwindowData.toObject()["tabs"].toArray()) { + Session::WebView tab{ + tabData.toObject()["profile"].toString(), + tabData.toObject()["url"].toString(), + QByteArray::fromBase64(tabData.toObject()["history"].toString().toLatin1()) + }; + subwindow.tabs.append(tab); + } + window.subwindows.append(subwindow); + } + windows.append(window); + } + return windows; +} diff --git a/lib/session_formats/session_json.hpp b/lib/session_formats/session_json.hpp new file mode 100644 index 0000000..3332229 --- /dev/null +++ b/lib/session_formats/session_json.hpp @@ -0,0 +1,36 @@ +/* + * 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://library.iserlohn-fortress.net/aqua/smolbote + * + * SPDX-License-Identifier: GPL-3.0 + */ + +#ifndef SESSION_JSON_HPP +#define SESSION_JSON_HPP + +#include +#include + +class JsonSession : public Session +{ +public: + explicit JsonSession() = default; + JsonSession(const JsonSession &) = default; + JsonSession(JsonSession &&) = default; + JsonSession &operator=(const JsonSession &) = delete; + JsonSession &operator=(JsonSession &&) = delete; + + explicit JsonSession(const QByteArray &data); + explicit JsonSession(const QVector &windows); + JsonSession(const QString &profile, const QStringList &urls); + ~JsonSession() override = default; + + [[nodiscard]] QByteArray serialize() const override; + [[nodiscard]] QVector get() const override; + +private: + const QJsonObject root; +}; + +#endif // SESSION_JSON_HPP diff --git a/lib/session_formats/test/json.cpp b/lib/session_formats/test/json.cpp new file mode 100644 index 0000000..4c6b683 --- /dev/null +++ b/lib/session_formats/test/json.cpp @@ -0,0 +1,103 @@ +#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file +#include +#include + +TEST_CASE("JsonSession default constructor") +{ + JsonSession session; + REQUIRE(session.serialize() == "{}"); + const auto tree = session.get(); + REQUIRE(tree.count() == 0); +} + +TEST_CASE("JsonSession command line constructor, single URL") +{ + const QString profile = ""; + const QString url = "https://some.url"; + JsonSession session(profile, QStringList(url)); + + const auto tree = session.get(); + REQUIRE(tree.count() == 1); + + const auto window = tree.at(0); + REQUIRE(window.subwindows.count() == 1); + + const auto subwindow = window.subwindows.at(0); + REQUIRE(subwindow.profile == profile); + REQUIRE(subwindow.tabs.count() == 1); + + const auto tab = subwindow.tabs.at(0); + REQUIRE(tab.profile == profile); + REQUIRE(tab.url == url); + REQUIRE(tab.history.isEmpty()); +} + +TEST_CASE("JsonSession command line constructor, multiple URLs") +{ + const QString profile = "default"; + const QStringList urls{ "https://some.url", "http://other.url", "a random string" }; + JsonSession session(profile, urls); + + const auto tree = session.get(); + REQUIRE(tree.count() == 1); + + const auto window = tree.at(0); + REQUIRE(window.subwindows.count() == 1); + + const auto subwindow = window.subwindows.at(0); + REQUIRE(subwindow.profile == profile); + REQUIRE(subwindow.tabs.count() == 3); + + for(int i = 0; i < urls.size(); ++i) { + const auto tab = subwindow.tabs.at(i); + REQUIRE(tab.profile == profile); + REQUIRE(tab.url == urls.at(i)); + REQUIRE(tab.history.isEmpty()); + } +} + +TEST_CASE("JsonSession QByteArray constuctor") +{ + const QString profile = ""; + const QString url = "about:blank"; + JsonSession donor(profile, { url }); + JsonSession session(donor.serialize()); + + const auto tree = session.get(); + REQUIRE(tree.count() == 1); + + const auto window = tree.at(0); + REQUIRE(window.subwindows.count() == 1); + + const auto subwindow = window.subwindows.at(0); + REQUIRE(subwindow.profile == profile); + REQUIRE(subwindow.tabs.count() == 1); + + const auto tab = subwindow.tabs.at(0); + REQUIRE(tab.profile == profile); + REQUIRE(tab.url == url); + REQUIRE(tab.history.isEmpty()); +} + +TEST_CASE("JsonSession MainWindowVector constructor") +{ + const Session::WebView cview{ "profile", "url", "history" }; + const Session::SubWindow csubwindow{ "profile", { cview } }; + const Session::MainWindow cwindow{ { csubwindow } }; + + const JsonSession session{ { cwindow } }; + const auto tree = session.get(); + REQUIRE(tree.count() == 1); + + const auto window = tree.at(0); + REQUIRE(window.subwindows.count() == 1); + + const auto subwindow = window.subwindows.at(0); + REQUIRE(subwindow.profile == csubwindow.profile); + REQUIRE(subwindow.tabs.count() == 1); + + const auto tab = subwindow.tabs.at(0); + REQUIRE(tab.profile == cview.profile); + REQUIRE(tab.url == cview.url); + REQUIRE(tab.history == cview.history); +} -- cgit v1.2.1