/* * 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 "browser.h" #include "addressbar/addressbar.h" #include "mainwindow/mainwindow.h" #include "subwindow/subwindow.h" #include "util.h" #include "webengine/urlinterceptor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "webengine/filter.h" #include #include #include "config.h" Browser::Browser(int &argc, char *argv[], bool allowSecondary) : SingleApplication(argc, argv, allowSecondary, SingleApplication::User | SingleApplication::SecondaryNotification | SingleApplication::ExcludeAppVersion) { setApplicationName(CONFIG_POI_NAME); setWindowIcon(QIcon(CONFIG_POI_ICON)); setApplicationVersion(poi_Version); } Browser::~Browser() { if(m_bookmarks) m_bookmarks->save(); qDeleteAll(m_windows); m_windows.clear(); } void Browser::about() { auto *dlg = new AboutDialog; for(const QPluginLoader *loader : qAsConst(m_plugins)) { const auto meta = loader->metaData().value("MetaData").toObject(); dlg->addPlugin(meta.value("name").toString(), meta.value("author").toString(), meta.value("shortcut").toString()); } dlg->exec(); } const QStringList Browser::configurationOptions() const { QStringList options; for(const auto &option : m_config->options()) { options.append(QString::fromStdString(option->long_name())); } return options; } const QString Browser::configuration(const QString& key) const { return m_config->value(qUtf8Printable(key)).value_or(QString()); } void Browser::setConfiguration(const QString& key, const QString& value) { m_config->setValue(qUtf8Printable(key), value); } const QList> Browser::profileList() const { QList> profiles; for(const QString &id : m_profileManager->idList()) { profiles.append(qMakePair(id, m_profileManager->profile(id))); } return profiles; } QPair Browser::loadProfile(const QString &id, bool isOffTheRecord) { WebProfile *profile = nullptr; if(QFile::exists(id)) { profile = m_profileManager->loadProfile(id); } else { profile = m_profileManager->createProfile(id, isOffTheRecord); } connect(profile, &WebProfile::downloadRequested, m_downloads.get(), &DownloadsWidget::addDownload); auto *interceptor = new UrlRequestInterceptor(m_urlFilter.get(), profile, profile); profile->setRequestInterceptor(interceptor); return QPair(m_profileManager->id(profile), profile); } void Browser::removeProfile(const QString &id) { m_profileManager->deleteProfile(id); } void Browser::setConfiguration(std::unique_ptr &config) { Q_ASSERT(config); m_config = std::move(config); } Configuration *Browser::getConfiguration() const { Q_ASSERT(m_config); return m_config.get(); } ProfileManager *Browser::getProfileManager() { return m_profileManager; } void Browser::setup(QVector plugins) { Q_ASSERT(m_config); m_plugins = plugins; auto stylesheet = m_config->value("browser.stylesheet"); if(stylesheet) { QFile f(stylesheet.value()); if(f.open(QIODevice::ReadOnly)) { setStyleSheet(f.readAll()); f.close(); } } // downloads m_downloads = std::make_unique(m_config->value("downloads.path").value()); // url request filter m_urlFilter = std::make_unique(m_config); // cookie request filter // load profiles m_profileManager = new ProfileManager(m_config->section("profile"), this); for(const QString &profilePath : Util::files(m_config->value("profile.path").value(), { "*.profile" })) { this->loadProfile(profilePath); } // set default profile { const QString id = m_config->value("profile.default").value(); auto *profile = m_profileManager->profile(id); if(profile == nullptr) { profile = qobject_cast(loadProfile(id).second); } WebProfile::setDefaultProfile(profile); } // bookmarks m_bookmarks = std::make_shared(QString::fromStdString(m_config->value("bookmarks.path").value())); connect(m_bookmarks.get(), &BookmarksWidget::openUrl, this, [this](const QUrl &url) { m_windows.last()->createTab(url); }); auto *timer = new QTimer(this); connect(timer, &QTimer::timeout, m_bookmarks.get(), &BookmarksWidget::save); // 5min * 60sec * 1000ms timer->start(5 * 60 * 1000); } void Browser::createSession(const QJsonObject &object) { MainWindow *mainwindow = nullptr; if(m_windows.isEmpty()) mainwindow = createWindow(); else mainwindow = m_windows.last(); const QJsonArray subwindows = object.value("subwindows").toArray(); for(const QJsonValue &s : subwindows) { const QJsonObject subwindow = s.toObject(); const QString profileId = subwindow.value("profile").toString(); WebProfile *profile = m_profileManager->profile(profileId); if(profile == nullptr) profile = WebProfile::defaultProfile(); Q_CHECK_PTR(profile); SubWindow *window = nullptr; for(SubWindow *w : mainwindow->subWindows()) { if(w->profile() == profile) { window = w; break; } } if(window == nullptr) window = mainwindow->createSubWindow(m_config, profile); const QJsonArray tabs = subwindow.value("tabs").toArray(); if(tabs.isEmpty()) window->addTab(profile->newtab()); else { for(const auto &t : tabs) { const QJsonObject tab = t.toObject(); const QUrl url = QUrl::fromUserInput(tab.value("url").toString()); WebProfile *p = m_profileManager->profile(tab.value("profile").toString()); window->addTab(url, p); } } } } MainWindow *Browser::createWindow() { // the window will delete itself when it closes, so we don't need to delete it auto *window = new MainWindow(m_config); connect(window->addressBar, &AddressBar::complete, m_bookmarks.get(), &BookmarksWidget::search); connect(window, &MainWindow::createBookmark, m_bookmarks.get(), &BookmarksWidget::addBookmark); auto *bookmarksAction = new QAction(tr("Bookmarks"), window); m_config->setShortcut(bookmarksAction, "bookmarks.shortcut"); connect(bookmarksAction, &QAction::triggered, window, [this, window]() { bool wasVisible = m_bookmarks->isVisible(); for(MainWindow *w : qAsConst(m_windows)) { w->removeDockWidget(m_bookmarks.get()); } if(!wasVisible) { window->addDockWidget(Qt::RightDockWidgetArea, m_bookmarks.get()); } }); window->addAction(MainWindow::ToolsMenu, bookmarksAction); auto *downloadsAction = new QAction(tr("Downloads"), window); m_config->setShortcut(downloadsAction, "downloads.shortcut"); connect(downloadsAction, &QAction::triggered, window, [this, window]() { bool wasVisible = m_downloads->isVisible(); for(MainWindow *w : qAsConst(m_windows)) { w->removeDockWidget(m_downloads.get()); } if(!wasVisible) { window->addDockWidget(Qt::RightDockWidgetArea, m_downloads.get()); } }); window->addAction(MainWindow::ToolsMenu, downloadsAction); for(QPluginLoader *loader : qAsConst(m_plugins)) { const auto *plugin = qobject_cast(loader->instance()); Q_CHECK_PTR(plugin); auto *pluginAction = new QAction(loader->metaData().value("MetaData").toObject().value("name").toString(), window); pluginAction->setShortcut(QKeySequence::fromString(loader->metaData().value("MetaData").toObject().value("shortcut").toString())); connect(pluginAction, &QAction::triggered, window, [=]() { plugin->createWidget(window)->exec(); }); window->addAction(MainWindow::ToolsMenu, pluginAction); } m_windows.append(window); connect(window, &MainWindow::destroyed, this, [this, window]() { m_windows.removeOne(window); }); return window; }