diff options
36 files changed, 757 insertions, 993 deletions
diff --git a/include/smolbote/plugininterface.hpp b/include/smolbote/plugininterface.hpp index 5fa4530..328cba5 100644 --- a/include/smolbote/plugininterface.hpp +++ b/include/smolbote/plugininterface.hpp @@ -9,14 +9,28 @@ #ifndef SMOLBOTE_PLUGIN_INTERFACE_HPP #define SMOLBOTE_PLUGIN_INTERFACE_HPP +#include <QDialog> #include <QtPlugin> +#include <QSettings> + +class QWebEngineProfile; +class ProfileDialog : public QDialog +{ +public: + ProfileDialog(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()) + : QDialog(parent, f) + { + } + virtual ~ProfileDialog() = default; + virtual int addProfile(const QString &id, const QString name, QWebEngineProfile *profile, QSettings *settings) = 0; + virtual void showProfile(int index) = 0; +}; -class QDialog; class PluginInterface { public: virtual ~PluginInterface() = default; - virtual QDialog *createWidget(QWidget *parent = nullptr) const = 0; + virtual QDialog *createWidget(QWidget *parent) const = 0; }; #define PluginInterfaceIid "net.iserlohn-fortress.smolbote.PluginInterface" diff --git a/meson.build b/meson.build index 3cf7105..c180449 100644 --- a/meson.build +++ b/meson.build @@ -91,8 +91,7 @@ subdir('lang') subdir('doc') subdir('tools') -#subdir('plugins/ConfigurationEditor') -#subdir('plugins/ProfileEditor') +subdir('plugins/ProfileEditor') subdir('test/firefox-bookmarks-json-parser') diff --git a/plugins/ProfileEditor/ProfileEditor.json b/plugins/ProfileEditor/ProfileEditor.json index 8381e9a..afa0a1f 100644 --- a/plugins/ProfileEditor/ProfileEditor.json +++ b/plugins/ProfileEditor/ProfileEditor.json @@ -1,5 +1,6 @@ { "name": "Profile Editor", - "author": "Aqua-sama", - "shortcut": "Ctrl+Shift+E" + "author": "aqua@", + "shortcut": "Ctrl+Shift+E", + "license": "GPL3" } diff --git a/plugins/ProfileEditor/forms/newhttpheaderdialog.cpp b/plugins/ProfileEditor/forms/newhttpheaderdialog.cpp deleted file mode 100644 index 3978c4e..0000000 --- a/plugins/ProfileEditor/forms/newhttpheaderdialog.cpp +++ /dev/null @@ -1,32 +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 - */ - -#include "newhttpheaderdialog.h" -#include "ui_newhttpheaderdialog.h" - -NewHttpHeaderDialog::NewHttpHeaderDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::NewHttpHeaderDialog) -{ - ui->setupUi(this); -} - -NewHttpHeaderDialog::~NewHttpHeaderDialog() -{ - delete ui; -} - -QString NewHttpHeaderDialog::header() const -{ - return ui->header->text(); -} - -QString NewHttpHeaderDialog::value() const -{ - return ui->value->text(); -} diff --git a/plugins/ProfileEditor/forms/newhttpheaderdialog.h b/plugins/ProfileEditor/forms/newhttpheaderdialog.h deleted file mode 100644 index 53a2a80..0000000 --- a/plugins/ProfileEditor/forms/newhttpheaderdialog.h +++ /dev/null @@ -1,33 +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 NEWHTTPHEADERDIALOG_H -#define NEWHTTPHEADERDIALOG_H - -#include <QDialog> - -namespace Ui { -class NewHttpHeaderDialog; -} - -class NewHttpHeaderDialog : public QDialog -{ - Q_OBJECT - -public: - explicit NewHttpHeaderDialog(QWidget *parent = nullptr); - ~NewHttpHeaderDialog(); - - QString header() const; - QString value() const; - -private: - Ui::NewHttpHeaderDialog *ui; -}; - -#endif // NEWHTTPHEADERDIALOG_H diff --git a/plugins/ProfileEditor/forms/newhttpheaderdialog.ui b/plugins/ProfileEditor/forms/newhttpheaderdialog.ui deleted file mode 100644 index a457ba6..0000000 --- a/plugins/ProfileEditor/forms/newhttpheaderdialog.ui +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>NewHttpHeaderDialog</class> - <widget class="QDialog" name="NewHttpHeaderDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>320</width> - <height>108</height> - </rect> - </property> - <property name="windowTitle"> - <string>Dialog</string> - </property> - <layout class="QFormLayout" name="formLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="header_label"> - <property name="text"> - <string>Header</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="header"/> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="value_label"> - <property name="text"> - <string>Value</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="value"/> - </item> - <item row="2" column="0" colspan="2"> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>NewHttpHeaderDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>NewHttpHeaderDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/plugins/ProfileEditor/forms/newprofiledialog.cpp b/plugins/ProfileEditor/forms/newprofiledialog.cpp deleted file mode 100644 index 3ed61d8..0000000 --- a/plugins/ProfileEditor/forms/newprofiledialog.cpp +++ /dev/null @@ -1,32 +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 - */ - -#include "newprofiledialog.h" -#include "ui_newprofiledialog.h" - -NewProfileDialog::NewProfileDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::NewProfileDialog) -{ - ui->setupUi(this); -} - -NewProfileDialog::~NewProfileDialog() -{ - delete ui; -} - -const QString NewProfileDialog::getId() const -{ - return ui->id_lineEdit->text(); -} - -bool NewProfileDialog::getOtr() const -{ - return ui->offTheRecord->isChecked(); -} diff --git a/plugins/ProfileEditor/forms/newprofiledialog.h b/plugins/ProfileEditor/forms/newprofiledialog.h deleted file mode 100644 index dd9aa4e..0000000 --- a/plugins/ProfileEditor/forms/newprofiledialog.h +++ /dev/null @@ -1,33 +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 NEWPROFILEDIALOG_H -#define NEWPROFILEDIALOG_H - -#include <QDialog> - -namespace Ui { -class NewProfileDialog; -} - -class NewProfileDialog : public QDialog -{ - Q_OBJECT - -public: - explicit NewProfileDialog(QWidget *parent = nullptr); - ~NewProfileDialog(); - - const QString getId() const; - bool getOtr() const; - -private: - Ui::NewProfileDialog *ui; -}; - -#endif // NEWPROFILEDIALOG_H diff --git a/plugins/ProfileEditor/forms/newprofiledialog.ui b/plugins/ProfileEditor/forms/newprofiledialog.ui deleted file mode 100644 index 8b4888d..0000000 --- a/plugins/ProfileEditor/forms/newprofiledialog.ui +++ /dev/null @@ -1,81 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>NewProfileDialog</class> - <widget class="QDialog" name="NewProfileDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>320</width> - <height>112</height> - </rect> - </property> - <property name="windowTitle"> - <string>New Profile</string> - </property> - <layout class="QFormLayout" name="formLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="id_label"> - <property name="text"> - <string>ID</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="id_lineEdit"/> - </item> - <item row="2" column="0" colspan="2"> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QCheckBox" name="offTheRecord"> - <property name="text"> - <string>Off the record</string> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>NewProfileDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>NewProfileDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/plugins/ProfileEditor/forms/profilemanagerdialog.cpp b/plugins/ProfileEditor/forms/profilemanagerdialog.cpp index f5a17b1..6cbc806 100644 --- a/plugins/ProfileEditor/forms/profilemanagerdialog.cpp +++ b/plugins/ProfileEditor/forms/profilemanagerdialog.cpp @@ -10,15 +10,14 @@ #include "profileview.h" #include <QDir> #include <QPointer> +#include "ui_profilemanagerdialog.h" ProfileManagerDialog::ProfileManagerDialog(QWidget *parent) - : QDialog(parent) + : ProfileDialog(parent) , ui(new Ui::ProfileManagerDialog) { ui->setupUi(this); - - connect(ui->listWidget, &QListWidget::itemPressed, this, &ProfileManagerDialog::showProfile); - showProfile(nullptr); + connect(ui->listWidget, &QListWidget::itemPressed, this, &ProfileManagerDialog::showItem); } ProfileManagerDialog::~ProfileManagerDialog() @@ -26,17 +25,26 @@ ProfileManagerDialog::~ProfileManagerDialog() delete ui; } -void ProfileManagerDialog::addProfile(const QString &id, Profile *profile) +int ProfileManagerDialog::addProfile(const QString &id, const QString name, QWebEngineProfile *profile, QSettings *settings) { Q_CHECK_PTR(profile); auto *item = new QListWidgetItem(id, ui->listWidget); - auto pointer = QPointer<Profile>(profile); - item->setData(Qt::UserRole, QVariant::fromValue(pointer)); + item->setData(Qt::UserRole, name); + item->setData(Qt::UserRole+1, QVariant::fromValue(QPointer<QWebEngineProfile>(profile))); + item->setData(Qt::UserRole+2, QVariant::fromValue(QPointer<QSettings>(settings))); + + return ui->listWidget->count() - 1; +} + +void ProfileManagerDialog::showProfile(int index) +{ + auto *item = ui->listWidget->item(index); + showItem(item); } -void ProfileManagerDialog::showProfile(QListWidgetItem *item) +void ProfileManagerDialog::showItem(QListWidgetItem *item) { // clear out groupbox layout QLayoutItem *i; @@ -51,8 +59,10 @@ void ProfileManagerDialog::showProfile(QListWidgetItem *item) } ui->groupBox->setVisible(true); - auto profile = item->data(Qt::UserRole).value<QPointer<Profile>>(); - auto *v = new ProfileView(profile.data(), this); + const auto name = item->data(Qt::UserRole).value<QString>(); + auto profile = item->data(Qt::UserRole+1).value<QPointer<QWebEngineProfile>>(); + auto settings = item->data(Qt::UserRole+2).value<QPointer<QSettings>>(); + auto *v = new ProfileView(name, profile.data(), settings.data(), this); ui->groupBox->layout()->addWidget(v); v->adjustSize(); } diff --git a/plugins/ProfileEditor/forms/profilemanagerdialog.h b/plugins/ProfileEditor/forms/profilemanagerdialog.h index fe91948..8dd307e 100644 --- a/plugins/ProfileEditor/forms/profilemanagerdialog.h +++ b/plugins/ProfileEditor/forms/profilemanagerdialog.h @@ -11,12 +11,15 @@ #include <QDialog> #include <QVector> -#include <profileinterface.h> -#include "ui_profilemanagerdialog.h" +#include <QWebEngineProfile> +#include <smolbote/plugininterface.hpp> + +namespace Ui { + class ProfileManagerDialog; +} -class WebProfile; class QListWidgetItem; -class ProfileManagerDialog : public QDialog +class ProfileManagerDialog : public ProfileDialog { Q_OBJECT @@ -27,10 +30,9 @@ public: ~ProfileManagerDialog() override; public slots: - void addProfile(const QString &id, Profile *profile); - -private slots: - void showProfile(QListWidgetItem *item); + int addProfile(const QString &id, const QString name, QWebEngineProfile *profile, QSettings *settings) override; + void showProfile(int index) override; + void showItem(QListWidgetItem *item); private: Ui::ProfileManagerDialog *ui; diff --git a/plugins/ProfileEditor/forms/profilemanagerdialog.ui b/plugins/ProfileEditor/forms/profilemanagerdialog.ui index f41b1b0..b715b86 100644 --- a/plugins/ProfileEditor/forms/profilemanagerdialog.ui +++ b/plugins/ProfileEditor/forms/profilemanagerdialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>400</width> - <height>300</height> + <width>918</width> + <height>600</height> </rect> </property> <property name="windowTitle"> @@ -34,6 +34,12 @@ <verstretch>0</verstretch> </sizepolicy> </property> + <property name="minimumSize"> + <size> + <width>640</width> + <height>0</height> + </size> + </property> <layout class="QVBoxLayout" name="verticalLayout_2"/> </widget> </item> @@ -42,20 +48,6 @@ <item> <layout class="QHBoxLayout" name="buttons_horizontalLayout"> <item> - <widget class="QPushButton" name="new_pushButton"> - <property name="text"> - <string>New</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="delete_pushButton"> - <property name="text"> - <string>Delete</string> - </property> - </widget> - </item> - <item> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> diff --git a/plugins/ProfileEditor/forms/profileview.cpp b/plugins/ProfileEditor/forms/profileview.cpp index 9a19cfc..992364c 100644 --- a/plugins/ProfileEditor/forms/profileview.cpp +++ b/plugins/ProfileEditor/forms/profileview.cpp @@ -1,29 +1,26 @@ /* * 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 + * location: https://neueland.iserlohn-fortress.net/cgit/smolbote * * SPDX-License-Identifier: GPL-3.0 */ #include "profileview.h" #include "ui_profileview.h" -#include <profileinterface.h> -#include <QWebEngineSettings> -#include <QWebEngineCookieStore> #include <QDateTime> -#include "newhttpheaderdialog.h" +#include <QWebEngineCookieStore> +#include <QWebEngineSettings> -inline void connectSetting(QCheckBox *checkBox, Profile *profile, QWebEngineSettings::WebAttribute attr) +inline void connectSetting(QCheckBox *checkBox, QWebEngineProfile *profile, QWebEngineSettings::WebAttribute attr) { checkBox->setChecked(profile->settings()->testAttribute(attr)); QObject::connect(checkBox, &QCheckBox::clicked, [profile, attr](bool checked) { profile->settings()->setAttribute(attr, checked); - emit profile->attributeChanged(attr, checked); }); } -ProfileView::ProfileView(Profile *profile, QWidget *parent) +ProfileView::ProfileView(const QString &name, QWebEngineProfile *profile, QSettings *settings, QWidget *parent) : QWidget(parent) , ui(new Ui::ProfileView) { @@ -32,52 +29,37 @@ ProfileView::ProfileView(Profile *profile, QWidget *parent) ui->setupUi(this); // general tab - ui->name->setText(profile->name()); - connect(ui->name, &QLineEdit::editingFinished, profile, [=]() { - profile->setName(ui->name->text()); - }); - + ui->name->setText(name); ui->offTheRecord->setChecked(profile->isOffTheRecord()); - ui->homepage->setText(profile->homepage().toString()); - connect(ui->homepage, &QLineEdit::editingFinished, profile, [=]() { - profile->setHomepage(QUrl::fromUserInput(ui->homepage->text())); - }); - - ui->newtab->setText(profile->newtab().toString()); - connect(ui->newtab, &QLineEdit::editingFinished, profile, [=]() { - profile->setNewtab(QUrl::fromUserInput(ui->newtab->text())); - }); - - ui->search->setText(profile->search()); - connect(ui->search, &QLineEdit::editingFinished, profile, [=]() { - profile->setSearch(ui->search->text()); - }); + ui->settings_table->connect(settings); // http tab ui->userAgent->setPlainText(m_profile->httpUserAgent()); - connect(ui->userAgent, &QPlainTextEdit::textChanged, profile, [=]() { + connect(ui->userAgent, &QPlainTextEdit::textChanged, profile, [this, profile]() { profile->setHttpUserAgent(ui->userAgent->toPlainText()); }); ui->acceptLanguage->setPlainText(m_profile->httpAcceptLanguage()); - connect(ui->acceptLanguage, &QPlainTextEdit::textChanged, profile, [=]() { + connect(ui->acceptLanguage, &QPlainTextEdit::textChanged, profile, [this, profile]() { profile->setHttpAcceptLanguage(ui->acceptLanguage->toPlainText()); }); + ui->headers_table->connect(settings, "headers"); + ui->cacheType->setCurrentIndex(m_profile->httpCacheType()); - connect(ui->cacheType, QOverload<int>::of(&QComboBox::currentIndexChanged), profile, [=](int index) { - profile->setHttpCacheType(index); + connect(ui->cacheType, QOverload<int>::of(&QComboBox::currentIndexChanged), profile, [profile](int index) { + profile->setHttpCacheType(static_cast<QWebEngineProfile::HttpCacheType>(index)); }); ui->cacheSize->setText(QString::number(m_profile->httpCacheMaximumSize())); - connect(ui->cacheSize, &QLineEdit::textChanged, profile, [=](const QString &text) { + connect(ui->cacheSize, &QLineEdit::textChanged, profile, [profile](const QString &text) { profile->setHttpCacheMaximumSize(text.toInt()); }); ui->cookiePolicy->setCurrentIndex(m_profile->persistentCookiesPolicy()); - connect(ui->cookiePolicy, QOverload<int>::of(&QComboBox::currentIndexChanged), profile, [=](int index) { - profile->setPersistentCookiesPolicy(index); + connect(ui->cookiePolicy, QOverload<int>::of(&QComboBox::currentIndexChanged), profile, [profile](int index) { + profile->setPersistentCookiesPolicy(static_cast<QWebEngineProfile::PersistentCookiesPolicy>(index)); }); connect(ui->clearCache_pushButton, &QPushButton::clicked, profile, &QWebEngineProfile::clearHttpCache); @@ -86,28 +68,13 @@ ProfileView::ProfileView(Profile *profile, QWidget *parent) ui->storagePath_lineEdit->setText(m_profile->persistentStoragePath()); ui->cachePath_lineEdit->setText(m_profile->cachePath()); - // headers tab - for(auto i = m_profile->headers().constBegin(); i != m_profile->headers().constEnd(); ++i) { - //ui->httpHeaders->addItem(); - headerChanged(i.key(), i.value()); + if(profile->isOffTheRecord()) { + ui->cacheType->setEnabled(false); + ui->cacheSize->setEnabled(false); + ui->storagePath_lineEdit->setEnabled(false); + ui->cachePath_lineEdit->setEnabled(false); + ui->cookiePolicy->setEnabled(false); } - connect(m_profile, &Profile::headerChanged, this, &ProfileView::headerChanged); - connect(m_profile, &Profile::headerRemoved, this, &ProfileView::headerRemoved); - connect(ui->headers_insert, &QPushButton::clicked, m_profile, [this]() { - auto *dlg = new NewHttpHeaderDialog(this); - if(dlg->exec() == QDialog::Accepted) { - m_profile->setHttpHeader(dlg->header(), dlg->value()); - } - delete dlg; - }); - connect(ui->headers_delete, &QPushButton::clicked, m_profile, [this]() { - for(auto &list : ui->httpHeaders->selectedRanges()) { - for(int i = list.bottomRow(); i >= list.topRow(); --i) { - m_profile->removeHttpHeader(ui->httpHeaders->item(i, 0)->text()); - } - } - }); - // settings tab connectSetting(ui->autoloadImages, m_profile, QWebEngineSettings::AutoLoadImages); connectSetting(ui->autoloadIcons, m_profile, QWebEngineSettings::AutoLoadIconsForPage); @@ -144,62 +111,39 @@ ProfileView::ProfileView(Profile *profile, QWidget *parent) connectSetting(ui->printElementBackgrounds, m_profile, QWebEngineSettings::PrintElementBackgrounds); // cookies tab - loadCookies(profile->cookieStore()); - for(const auto &c : profile->cookies()) { - cookieAdded(c); + for(const auto &data : profile->property("cookies").toList()) { + for(const auto &cookie : QNetworkCookie::parseCookies(data.toByteArray())) { + cookieAdded(cookie); + } } -} -ProfileView::~ProfileView() -{ - delete ui; -} + connect(profile->cookieStore(), &QWebEngineCookieStore::cookieAdded, this, &ProfileView::cookieAdded); + connect(profile->cookieStore(), &QWebEngineCookieStore::cookieRemoved, this, &ProfileView::cookieRemoved); -void ProfileView::loadCookies(QWebEngineCookieStore *store) -{ - // - connect(store, &QWebEngineCookieStore::cookieAdded, this, &ProfileView::cookieAdded); - connect(store, &QWebEngineCookieStore::cookieRemoved, this, &ProfileView::cookieRemoved); + connect(ui->cookies_deleteSession, &QPushButton::clicked, profile->cookieStore(), &QWebEngineCookieStore::deleteSessionCookies); + connect(ui->cookies_deleteAll, &QPushButton::clicked, profile->cookieStore(), &QWebEngineCookieStore::deleteAllCookies); - connect(ui->cookies_reload, &QPushButton::clicked, store, [=]() { - ui->cookies->clearContents(); - ui->cookies->setRowCount(0); - store->loadAllCookies(); - }); - - connect(ui->cookies_delete, &QPushButton::clicked, store, [=]() { + connect(ui->cookies_delete, &QPushButton::clicked, [this, profile]() { for(auto &list : ui->cookies->selectedRanges()) { for(int i = list.bottomRow(); i >= list.topRow(); --i) { auto cookie = ui->cookies->item(i, 0)->data(Qt::UserRole).value<QNetworkCookie>(); - store->deleteCookie(cookie); + profile->cookieStore()->deleteCookie(cookie); } } }); - connect(ui->cookies_deleteSession, &QPushButton::clicked, store, &QWebEngineCookieStore::deleteSessionCookies); - connect(ui->cookies_deleteAll, &QPushButton::clicked, store, &QWebEngineCookieStore::deleteAllCookies); -} -void ProfileView::headerChanged(const QString &name, const QString &value) -{ - const auto items = ui->httpHeaders->findItems(name, Qt::MatchExactly); - if(!items.isEmpty()) { - QTableWidgetItem *valueItem = ui->httpHeaders->item(items.constFirst()->row(), 1); - valueItem->setText(value); - } else { - // new header - const int index = ui->httpHeaders->rowCount(); - ui->httpHeaders->setRowCount(index + 1); - ui->httpHeaders->setItem(index, 0, new QTableWidgetItem(name)); - ui->httpHeaders->setItem(index, 1, new QTableWidgetItem(value)); - } + connect(ui->cookies_reload, &QPushButton::clicked, [this, profile]() { + ui->cookies->clearContents(); + ui->cookies->setRowCount(0); + qDebug("loadAllCookies called!"); + profile->cookieStore()->loadAllCookies(); + }); + } -void ProfileView::headerRemoved(const QString& name) +ProfileView::~ProfileView() { - const auto items = ui->httpHeaders->findItems(name, Qt::MatchExactly); - if(!items.isEmpty()) { - ui->httpHeaders->removeRow(items.constFirst()->row()); - } + delete ui; } void ProfileView::cookieAdded(const QNetworkCookie &cookie) @@ -212,21 +156,24 @@ void ProfileView::cookieAdded(const QNetworkCookie &cookie) ui->cookies->setItem(index, 0, item); ui->cookies->setItem(index, 1, new QTableWidgetItem(cookie.domain())); ui->cookies->setItem(index, 2, new QTableWidgetItem(cookie.path())); - if(cookie.isSessionCookie()) + if(cookie.isSessionCookie()) { ui->cookies->setItem(index, 3, new QTableWidgetItem(tr("session"))); - else + } else { ui->cookies->setItem(index, 3, new QTableWidgetItem(cookie.expirationDate().toString(Qt::RFC2822Date))); + } } void ProfileView::cookieRemoved(const QNetworkCookie &cookie) { + qDebug("cookieRemoved called"); + for(int i = 0; i < ui->cookies->rowCount(); ++i) { auto *item = ui->cookies->item(i, 0); - if(item->data(Qt::UserRole).value<QNetworkCookie>() == cookie) { - //qDebug("removing cookie on row %i", i); + if(item->data(Qt::UserRole).value<QNetworkCookie>().hasSameIdentifier(cookie)) { + qDebug("removing cookie on row %i", i); ui->cookies->removeRow(i); - break; + return; } + qDebug("cookie on row %i doesn't have the same identifier", i); } } - diff --git a/plugins/ProfileEditor/forms/profileview.h b/plugins/ProfileEditor/forms/profileview.h index 7f3e738..9b4506a 100644 --- a/plugins/ProfileEditor/forms/profileview.h +++ b/plugins/ProfileEditor/forms/profileview.h @@ -12,13 +12,14 @@ #include <QWidget> #include <QNetworkCookie> #include <QWebEngineSettings> +#include <QWebEngineProfile> +#include <QSettings> namespace Ui { class ProfileView; } -class Profile; class QWebEngineCookieStore; class QCheckBox; @@ -27,21 +28,16 @@ class ProfileView : public QWidget Q_OBJECT public: - explicit ProfileView(Profile *profile, QWidget *parent = nullptr); + explicit ProfileView(const QString &name, QWebEngineProfile *profile, QSettings *settings, QWidget *parent = nullptr); ~ProfileView() override; private slots: - void loadCookies(QWebEngineCookieStore *store); - - void headerChanged(const QString &name, const QString &value); - void headerRemoved(const QString &name); - void cookieAdded(const QNetworkCookie &cookie); void cookieRemoved(const QNetworkCookie &cookie); private: Ui::ProfileView *ui; - Profile *m_profile; + QWebEngineProfile *m_profile; }; #endif // PROFILEDIALOG_H diff --git a/plugins/ProfileEditor/forms/profileview.ui b/plugins/ProfileEditor/forms/profileview.ui index 630e53d..46e0a68 100644 --- a/plugins/ProfileEditor/forms/profileview.ui +++ b/plugins/ProfileEditor/forms/profileview.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>640</width> - <height>504</height> + <height>510</height> </rect> </property> <property name="minimumSize"> @@ -19,7 +19,7 @@ <property name="windowTitle"> <string>Profile</string> </property> - <layout class="QVBoxLayout" name="verticalLayout"> + <layout class="QVBoxLayout" name="verticalLayout_7"> <item> <widget class="QTabWidget" name="tabWidget"> <property name="currentIndex"> @@ -29,76 +29,58 @@ <attribute name="title"> <string>General</string> </attribute> - <layout class="QFormLayout" name="formLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="name_label"> - <property name="text"> - <string>Name</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="name"/> - </item> - <item row="1" column="1"> - <widget class="QCheckBox" name="offTheRecord"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Off-the-record</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QLineEdit" name="configurationPath"> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="name"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="offTheRecord"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Off-the-record</string> + </property> + </widget> + </item> + </layout> </item> - <item row="2" column="0"> - <widget class="QLabel" name="configurationPath_label"> - <property name="text"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> <string>Configuration</string> </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="homepage_label"> - <property name="text"> - <string>Homepage</string> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QLabel" name="newtab_label"> - <property name="text"> - <string>New tab page</string> - </property> - </widget> - </item> - <item row="6" column="0"> - <widget class="QLabel" name="search_label"> - <property name="text"> - <string>Search</string> - </property> - </widget> - </item> - <item row="5" column="1"> - <widget class="QLineEdit" name="newtab"/> - </item> - <item row="6" column="1"> - <widget class="QLineEdit" name="search"/> - </item> - <item row="4" column="1"> - <widget class="QLineEdit" name="homepage"/> - </item> - <item row="3" column="1"> - <widget class="Line" name="line_8"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> + <property name="flat"> + <bool>true</bool> </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="SettingsTable" name="settings_table"> + <attribute name="horizontalHeaderStretchLastSection"> + <bool>true</bool> + </attribute> + <attribute name="verticalHeaderVisible"> + <bool>false</bool> + </attribute> + <column> + <property name="text"> + <string>Key</string> + </property> + </column> + <column> + <property name="text"> + <string>Value</string> + </property> + </column> + </widget> + </item> + </layout> </widget> </item> </layout> @@ -125,176 +107,150 @@ </property> </widget> </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_5"> - <property name="text"> - <string>Cache Type</string> - </property> + <item row="1" column="1"> + <widget class="QPlainTextEdit" name="acceptLanguage"/> + </item> + <item row="3" column="1"> + <widget class="SettingsTable" name="headers_table"> + <attribute name="horizontalHeaderStretchLastSection"> + <bool>true</bool> + </attribute> + <attribute name="verticalHeaderVisible"> + <bool>false</bool> + </attribute> + <column> + <property name="text"> + <string>Key</string> + </property> + </column> + <column> + <property name="text"> + <string>Value</string> + </property> + </column> </widget> </item> <item row="3" column="0"> - <widget class="QLabel" name="label_6"> + <widget class="QLabel" name="label_2"> <property name="text"> - <string>Cache Size</string> + <string>Headers</string> </property> </widget> </item> - <item row="1" column="1"> - <widget class="QPlainTextEdit" name="acceptLanguage"/> + </layout> + </widget> + <widget class="QWidget" name="storageTab"> + <attribute name="title"> + <string>Storage</string> + </attribute> + <layout class="QFormLayout" name="formLayout_3"> + <item row="0" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Cache Type</string> + </property> + </widget> </item> - <item row="2" column="1"> - <widget class="QComboBox" name="cacheType"> + <item row="0" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> - <property name="text"> - <string>Memory Cache</string> - </property> + <widget class="QComboBox" name="cacheType"> + <item> + <property name="text"> + <string>Memory Cache</string> + </property> + </item> + <item> + <property name="text"> + <string>Disk Cache</string> + </property> + </item> + <item> + <property name="text"> + <string>Disabled</string> + </property> + </item> + </widget> </item> <item> - <property name="text"> - <string>Disk Cache</string> - </property> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> </item> <item> - <property name="text"> - <string>Disabled</string> - </property> + <widget class="QPushButton" name="clearCache_pushButton"> + <property name="text"> + <string>Clear Cache</string> + </property> + </widget> </item> - </widget> - </item> - <item row="3" column="1"> - <widget class="QLineEdit" name="cacheSize"/> + </layout> </item> - <item row="6" column="0"> - <widget class="QLabel" name="storagePath_label"> + <item row="1" column="0"> + <widget class="QLabel" name="label_6"> <property name="text"> - <string>Storage Path</string> + <string>Cache Size</string> </property> </widget> </item> - <item row="6" column="1"> - <widget class="QLineEdit" name="storagePath_lineEdit"> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> + <item row="1" column="1"> + <widget class="QLineEdit" name="cacheSize"/> </item> - <item row="4" column="0"> + <item row="2" column="0"> <widget class="QLabel" name="cachePath_label"> <property name="text"> <string>Cache Path</string> </property> </widget> </item> - <item row="4" column="1"> + <item row="2" column="1"> <widget class="QLineEdit" name="cachePath_lineEdit"> <property name="enabled"> <bool>false</bool> </property> </widget> </item> - <item row="5" column="1"> - <widget class="QPushButton" name="clearCache_pushButton"> + <item row="3" column="0"> + <widget class="QLabel" name="storagePath_label"> <property name="text"> - <string>Clear Cache</string> + <string>Storage Path</string> </property> </widget> </item> - <item row="7" column="0"> - <widget class="QLabel" name="cookiePolicy_label"> - <property name="text"> - <string>Cookies</string> + <item row="3" column="1"> + <widget class="QLineEdit" name="storagePath_lineEdit"> + <property name="enabled"> + <bool>false</bool> </property> </widget> </item> - <item row="7" column="1"> - <widget class="QComboBox" name="cookiePolicy"> - <item> - <property name="text"> - <string>No Persistent Cookies</string> - </property> - </item> - <item> - <property name="text"> - <string>Allow Persistent Cookies</string> - </property> - </item> - <item> - <property name="text"> - <string>Force Persistent Cookies</string> - </property> - </item> - </widget> - </item> - <item row="8" column="1"> + <item row="4" column="1"> <widget class="QPushButton" name="clearHistory_pushButton"> <property name="text"> <string>Clear History</string> </property> </widget> </item> - </layout> - </widget> - <widget class="QWidget" name="httpHeadersTab"> - <attribute name="title"> - <string>Headers</string> - </attribute> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QTableWidget" name="httpHeaders"> - <attribute name="horizontalHeaderDefaultSectionSize"> - <number>200</number> - </attribute> - <attribute name="horizontalHeaderMinimumSectionSize"> - <number>100</number> - </attribute> - <attribute name="horizontalHeaderStretchLastSection"> - <bool>true</bool> - </attribute> - <attribute name="verticalHeaderVisible"> - <bool>false</bool> - </attribute> - <column> - <property name="text"> - <string>Name</string> - </property> - </column> - <column> - <property name="text"> - <string>Value</string> - </property> - </column> - </widget> - </item> - <item> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <widget class="QPushButton" name="headers_insert"> - <property name="text"> - <string>Insert</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="headers_delete"> - <property name="text"> - <string>Delete</string> - </property> - </widget> - </item> - <item> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> + <item row="5" column="1"> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> </item> </layout> </widget> @@ -313,7 +269,7 @@ <rect> <x>0</x> <y>0</y> - <width>584</width> + <width>273</width> <height>797</height> </rect> </property> @@ -559,94 +515,128 @@ <attribute name="title"> <string>Cookies</string> </attribute> - <layout class="QHBoxLayout" name="horizontalLayout"> + <layout class="QVBoxLayout" name="verticalLayout_6"> <item> - <widget class="QTableWidget" name="cookies"> - <property name="sizeAdjustPolicy"> - <enum>QAbstractScrollArea::AdjustToContents</enum> - </property> - <property name="editTriggers"> - <set>QAbstractItemView::NoEditTriggers</set> - </property> - <property name="selectionBehavior"> - <enum>QAbstractItemView::SelectRows</enum> - </property> - <property name="cornerButtonEnabled"> - <bool>false</bool> - </property> - <attribute name="horizontalHeaderHighlightSections"> - <bool>false</bool> - </attribute> - <attribute name="horizontalHeaderStretchLastSection"> - <bool>true</bool> - </attribute> - <attribute name="verticalHeaderVisible"> - <bool>false</bool> - </attribute> - <column> - <property name="text"> - <string>Name</string> - </property> - </column> - <column> - <property name="text"> - <string>Domain</string> - </property> - </column> - <column> - <property name="text"> - <string>Path</string> - </property> - </column> - <column> - <property name="text"> - <string>Expires</string> - </property> - </column> - </widget> - </item> - <item> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QPushButton" name="cookies_reload"> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="cookiePolicy_label"> <property name="text"> - <string>Reload</string> + <string>Cookies</string> </property> </widget> </item> - <item> - <widget class="QPushButton" name="cookies_delete"> - <property name="text"> - <string>Delete</string> - </property> + <item row="0" column="1"> + <widget class="QComboBox" name="cookiePolicy"> + <item> + <property name="text"> + <string>No Persistent Cookies</string> + </property> + </item> + <item> + <property name="text"> + <string>Allow Persistent Cookies</string> + </property> + </item> + <item> + <property name="text"> + <string>Force Persistent Cookies</string> + </property> + </item> </widget> </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> <item> - <widget class="QPushButton" name="cookies_deleteSession"> - <property name="text"> - <string>Delete Session</string> + <widget class="QTableWidget" name="cookies"> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="cookies_deleteAll"> - <property name="text"> - <string>Delete All</string> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> </property> + <property name="cornerButtonEnabled"> + <bool>false</bool> + </property> + <attribute name="horizontalHeaderHighlightSections"> + <bool>false</bool> + </attribute> + <attribute name="horizontalHeaderStretchLastSection"> + <bool>true</bool> + </attribute> + <attribute name="verticalHeaderVisible"> + <bool>false</bool> + </attribute> + <column> + <property name="text"> + <string>Name</string> + </property> + </column> + <column> + <property name="text"> + <string>Domain</string> + </property> + </column> + <column> + <property name="text"> + <string>Path</string> + </property> + </column> + <column> + <property name="text"> + <string>Expires</string> + </property> + </column> </widget> </item> <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QPushButton" name="cookies_reload"> + <property name="text"> + <string>Reload</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="cookies_delete"> + <property name="text"> + <string>Delete</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="cookies_deleteSession"> + <property name="text"> + <string>Delete Session</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="cookies_deleteAll"> + <property name="text"> + <string>Delete All</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> </item> </layout> </item> @@ -656,6 +646,13 @@ </item> </layout> </widget> + <customwidgets> + <customwidget> + <class>SettingsTable</class> + <extends>QTableWidget</extends> + <header>forms/settingstable.h</header> + </customwidget> + </customwidgets> <resources/> <connections/> </ui> diff --git a/plugins/ProfileEditor/forms/settingstable.cpp b/plugins/ProfileEditor/forms/settingstable.cpp new file mode 100644 index 0000000..6cfe144 --- /dev/null +++ b/plugins/ProfileEditor/forms/settingstable.cpp @@ -0,0 +1,90 @@ +/* + * 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/cgit/smolbote + * + * SPDX-License-Identifier: GPL-3.0 + */ + +#include "settingstable.h" +#include <QResizeEvent> +#include <QSettings> +#include <QToolButton> + +SettingsTable::SettingsTable(QWidget *parent) + : QTableWidget(parent) +{ + QObject::connect(this, &QTableWidget::currentCellChanged, [this](int currentRow, int currentColumn, int /*previousRow*/, int /*previousColumn*/) { + if(currentColumn == 0) { + const auto key = item(currentRow, currentColumn)->text(); + m_selectedKey = key; + } + }); + + addBtn = new QToolButton(this); + addBtn->setText("Add"); + removeBtn = new QToolButton(this); + removeBtn->setText("Remove"); +} + +void SettingsTable::connect(QSettings *settings, const QString §ion) +{ + settings->beginGroup(section); + if(settings != nullptr) { + const auto keys = settings->childKeys(); + setRowCount(keys.count()); + for(int i = 0; i < keys.count(); ++i) { + setItem(i, 0, new QTableWidgetItem(keys[i])); + setItem(i, 1, new QTableWidgetItem(settings->value(keys[i]).toString())); + } + } + settings->endGroup(); + + QObject::connect(addBtn, &QToolButton::clicked, [this]() { + const auto row = rowCount(); + setRowCount(row + 1); + setItem(row, 0, new QTableWidgetItem("key")); + setItem(row, 1, new QTableWidgetItem("value")); + }); + + QObject::connect(removeBtn, &QToolButton::clicked, [this, settings, section]() { + settings->beginGroup(section); + + const int row = currentRow(); + const auto key = item(row, 0)->text(); + + removeRow(row); + qDebug("remove key: %s", qUtf8Printable(key)); + settings->remove(key); + + settings->endGroup(); + }); + + QObject::connect(this, &QTableWidget::cellChanged, [this, settings, section](int row, int column) { + // no value has been created yet + if(item(row, 1) == nullptr) { + return; + } + + settings->beginGroup(section); + + if(column == 0) { + qDebug("remove old key: %s", qUtf8Printable(m_selectedKey)); + settings->remove(m_selectedKey); + } + + const auto key = item(row, 0)->text(); + const auto val = item(row, 1)->text(); + qDebug("set: [%s]=[%s]", qUtf8Printable(key), qUtf8Printable(val)); + settings->setValue(key, val); + + settings->endGroup(); + }); +} + +void SettingsTable::resizeEvent(QResizeEvent *event) +{ + QTableWidget::resizeEvent(event); + addBtn->move(width() - addBtn->width() - removeBtn->width(), 0); + removeBtn->move(width() - removeBtn->width(), 0); +} diff --git a/plugins/ProfileEditor/forms/settingstable.h b/plugins/ProfileEditor/forms/settingstable.h new file mode 100644 index 0000000..80e76f0 --- /dev/null +++ b/plugins/ProfileEditor/forms/settingstable.h @@ -0,0 +1,31 @@ +/* + * 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/cgit/smolbote + * + * SPDX-License-Identifier: GPL-3.0 + */ + +#ifndef SETTINGS_TREE +#define SETTINGS_TREE + +#include <QTableWidget> + +class QSettings; +class QToolButton; +class SettingsTable : public QTableWidget +{ +public: + SettingsTable(QWidget *parent = nullptr); + + void connect(QSettings *settings, const QString §ion = QString()); + +protected: + void resizeEvent(QResizeEvent *event); + +private: + QString m_selectedKey; + QToolButton *addBtn = nullptr, *removeBtn = nullptr; +}; + +#endif // SETTINGS_TREE diff --git a/plugins/ProfileEditor/meson.build b/plugins/ProfileEditor/meson.build index caa3a75..47a1c17 100644 --- a/plugins/ProfileEditor/meson.build +++ b/plugins/ProfileEditor/meson.build @@ -1,15 +1,14 @@ ProfileEditorPlugin_moc = mod_qt5.preprocess( - include_directories: include, - moc_headers: ['profileeditorplugin.h', 'forms/profilemanagerdialog.h', 'forms/profileview.h', 'forms/newprofiledialog.h', 'forms/newhttpheaderdialog.h'], - ui_files: ['forms/profilemanagerdialog.ui', 'forms/profileview.ui', 'forms/newprofiledialog.ui', 'forms/newhttpheaderdialog.ui'], - dependencies: dep_qt5 + include_directories: plugininterfaces_include, + moc_headers: [ 'profileeditorplugin.h', 'forms/profilemanagerdialog.h', 'forms/profileview.h' ], + ui_files: [ 'forms/profilemanagerdialog.ui', 'forms/profileview.ui' ], ) -ProfileEditorPlugin_lib = shared_library('ProfileEditorPlugin', - [interfaces_moc, ProfileEditorPlugin_moc, 'profileeditorplugin.cpp', 'forms/profilemanagerdialog.cpp', 'forms/profileview.cpp', 'forms/newprofiledialog.cpp', 'forms/newhttpheaderdialog.cpp'], - dependencies: dep_qt5, - include_directories: include, - install: true, install_dir: join_paths(get_option('libdir'), 'smolbote/plugins') +ProfileEditorPlugin = shared_library('ProfileEditorPlugin', + [ ProfileEditorPlugin_moc, 'profileeditorplugin.cpp', 'forms/profilemanagerdialog.cpp', 'forms/profileview.cpp', 'forms/settingstable.cpp' ], + include_directories: plugininterfaces_include, + dependencies: [ dep_qt5 ], + install: true, install_dir: join_paths(get_option('libdir'), 'smolbote/plugins') ) test('run', executable('ProfileEditor', 'test/main.cpp', diff --git a/plugins/ProfileEditor/profileeditorplugin.cpp b/plugins/ProfileEditor/profileeditorplugin.cpp index d480392..6d1fc6a 100644 --- a/plugins/ProfileEditor/profileeditorplugin.cpp +++ b/plugins/ProfileEditor/profileeditorplugin.cpp @@ -8,48 +8,12 @@ #include "profileeditorplugin.h" #include "forms/profilemanagerdialog.h" -#include "forms/newprofiledialog.h" - -QHash<QString, std::function<int()>> ProfileEditorPlugin::commands() -{ - QHash<QString, std::function<int()>> hash; - - hash.insert("edit-profiles-ui", [this]() -> int { - auto *dialog = createWidget(nullptr); - return dialog->exec(); - }); - return hash; -} QDialog *ProfileEditorPlugin::createWidget(QWidget *parent) const { - auto *app = browser(); - Q_CHECK_PTR(app); auto *widget = new ProfileManagerDialog(parent); widget->setAttribute(Qt::WA_DeleteOnClose, true); - for(const auto &pair : app->profileList()) { - widget->addProfile(pair.first, pair.second); - } - - connect(widget->ui->new_pushButton, &QPushButton::clicked, widget, [=]() { - auto *newProfileDlg = new NewProfileDialog(widget); - if(newProfileDlg->exec() == QDialog::Accepted) { - const auto pair = app->loadProfile(newProfileDlg->getId(), newProfileDlg->getOtr()); - widget->addProfile(pair.first, pair.second); - } - delete newProfileDlg; - }); - - connect(widget->ui->delete_pushButton, &QPushButton::clicked, widget, [=]() { - auto *item = widget->ui->listWidget->currentItem(); - if(item != nullptr) { - // there is a selected widget - const QString id = item->text(); - widget->showProfile(nullptr); - app->removeProfile(id); - } - }); return widget; } diff --git a/plugins/ProfileEditor/profileeditorplugin.h b/plugins/ProfileEditor/profileeditorplugin.h index a673436..13f6d90 100644 --- a/plugins/ProfileEditor/profileeditorplugin.h +++ b/plugins/ProfileEditor/profileeditorplugin.h @@ -9,7 +9,7 @@ #ifndef PROFILEEDITOR_PLUGIN_H #define PROFILEEDITOR_PLUGIN_H -#include <plugininterface.h> +#include <smolbote/plugininterface.hpp> class QDialog; class ProfileEditorPlugin : public QObject, public PluginInterface @@ -19,10 +19,7 @@ class ProfileEditorPlugin : public QObject, public PluginInterface Q_INTERFACES(PluginInterface) public: - // PluginInterface - QHash<QString, std::function<int()>> commands() override; - - // ProfileInterface + ~ProfileEditorPlugin() override = default; QDialog *createWidget(QWidget *parent) const override; }; diff --git a/plugins/ProfileEditor/test/main.cpp b/plugins/ProfileEditor/test/main.cpp new file mode 100644 index 0000000..40b563c --- /dev/null +++ b/plugins/ProfileEditor/test/main.cpp @@ -0,0 +1,22 @@ +#include <QApplication> +#include "profileeditorplugin.h" +#include <QDialog> +#include <QTimer> +#include <QWebEngineProfile> + +int main(int argc, char** argv) +{ + QApplication app(argc, argv); + ProfileEditorPlugin plugin; + + auto *dlg = dynamic_cast<ProfileDialog*>(plugin.createWidget(nullptr)); + const auto i = dlg->addProfile("id", "testing", new QWebEngineProfile, new QSettings(QString(), QSettings::IniFormat, &app)); + dlg->show(); + + if(qEnvironmentVariableIsSet("autoclose")) { + dlg->showProfile(i); + QTimer::singleShot(200, dlg, &QDialog::accept); + } + + return app.exec(); +} diff --git a/src/about/aboutdialog.ui b/src/about/aboutdialog.ui index 5b1c12a..036474c 100644 --- a/src/about/aboutdialog.ui +++ b/src/about/aboutdialog.ui @@ -134,11 +134,6 @@ </item> </layout> </widget> - <widget class="QWidget" name="tab"> - <attribute name="title"> - <string>Plugins</string> - </attribute> - </widget> </widget> </item> <item> diff --git a/src/about/aboutplugin.cpp b/src/about/aboutplugin.cpp index 92e55bb..a011b47 100644 --- a/src/about/aboutplugin.cpp +++ b/src/about/aboutplugin.cpp @@ -12,57 +12,12 @@ #include <QPluginLoader> #include <QToolButton> -QTreeWidgetItem *createItem(const QString &key, const QJsonValue &json, QTreeWidgetItem *parent) -{ - auto *item = new QTreeWidgetItem(parent, { key, QLatin1String("---") }); - - switch(json.type()) { - case QJsonValue::Bool: - item->setText(1, json.toBool() ? QLatin1String("true") : QLatin1String("false")); - break; - - case QJsonValue::Double: - item->setText(1, QString::number(json.toDouble())); - break; - - case QJsonValue::String: - item->setText(1, json.toString()); - break; - - case QJsonValue::Array: - item->setText(1, QString()); - for(const auto &v : json.toArray()) { - createItem(QString(), v, item); - } - break; - - case QJsonValue::Object: - item->setText(1, QString()); - for(const QString &k : json.toObject().keys()) { - createItem(k, json.toObject()[k], item); - } - break; - - case QJsonValue::Null: - item->setText(1, QLatin1String("null")); - break; - - case QJsonValue::Undefined: - item->setText(1, QLatin1String("undefined")); - break; - } - - return item; -} - AboutPluginDialog::AboutPluginDialog(QWidget *parent) : QDialog(parent) , ui(new Ui::AboutPluginDialog) { setAttribute(Qt::WA_DeleteOnClose, true); ui->setupUi(this); - - } AboutPluginDialog::~AboutPluginDialog() @@ -85,20 +40,17 @@ void AboutPluginDialog::add(QPluginLoader *loader) auto *enable_btn = new QToolButton(this); enable_btn->setCheckable(true); enable_btn->setChecked(loader->isLoaded()); + enable_btn->setText(loader->isLoaded() ? "loaded" : "unloaded"); ui->tableWidget->setCellWidget(index, 4, enable_btn); - connect(enable_btn, &QToolButton::clicked, this, [ loader, enable_btn ](bool checked) { + connect(enable_btn, &QToolButton::clicked, this, [this, loader, enable_btn](bool checked) { const bool success = checked ? loader->load() : loader->unload(); if(!success) { enable_btn->setChecked(!checked); - //ui->error->setText(loader->errorString()); + ui->msg->setText(loader->errorString()); + } else { + ui->msg->setText(checked ? "Plugin successfully loaded" : "Plugin successfully unloaded"); + enable_btn->setText(checked ? "loaded" : "unloaded"); } }); - - for(const QString &key : metadata.keys()) { - auto *i = createItem(key, metadata.value(key), nullptr); - if(i != nullptr) { - ui->details_treeWidget->insertTopLevelItem(0, i); - } - } } diff --git a/src/about/aboutplugin.h b/src/about/aboutplugin.h index b01cc78..f9cd3d4 100644 --- a/src/about/aboutplugin.h +++ b/src/about/aboutplugin.h @@ -24,6 +24,9 @@ public: explicit AboutPluginDialog(QWidget *parent = nullptr); ~AboutPluginDialog() override; +signals: + void loadPlugin(const QString &path); + public slots: void add(QPluginLoader *loader); diff --git a/src/about/aboutplugin.ui b/src/about/aboutplugin.ui index d4291e5..5f44886 100644 --- a/src/about/aboutplugin.ui +++ b/src/about/aboutplugin.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>600</width> + <width>900</width> <height>420</height> </rect> </property> @@ -19,6 +19,9 @@ <attribute name="horizontalHeaderStretchLastSection"> <bool>true</bool> </attribute> + <attribute name="verticalHeaderVisible"> + <bool>false</bool> + </attribute> <column> <property name="text"> <string>Name</string> @@ -52,28 +55,32 @@ </widget> </item> <item> - <widget class="QTreeWidget" name="details_treeWidget"> - <column> - <property name="text"> - <string>Key</string> - </property> - </column> - <column> - <property name="text"> - <string>Value</string> - </property> - </column> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Close</set> - </property> - </widget> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QToolButton" name="add_toolButton"> + <property name="text"> + <string>Add</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="msg"> + <property name="text"> + <string>text</string> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + </item> + </layout> </item> </layout> </widget> diff --git a/src/applicationmenu.cpp b/src/applicationmenu.cpp index b7acd57..dc888e7 100644 --- a/src/applicationmenu.cpp +++ b/src/applicationmenu.cpp @@ -13,10 +13,12 @@ #include "session/sessiondialog.h" #include "smolbote/plugininterface.hpp" #include <QPluginLoader> +#include <spdlog/spdlog.h> ApplicationMenu::ApplicationMenu(Browser *app, QWidget *parent) : QMenu(parent) { + m_app = app; setTitle(qApp->applicationName()); Configuration conf; @@ -57,11 +59,21 @@ void ApplicationMenu::addPlugin(QPluginLoader *plugin) auto *action = addAction(metadata.value("name").toString()); action->setShortcut(QKeySequence::fromString(metadata.value("shortcut").toString())); - connect(action, &QAction::triggered, this, [this, plugin]() { + connect(action, &QAction::triggered, [this, plugin]() { if(plugin->isLoaded()) { - if(const auto *interface = qobject_cast<PluginInterface *>(plugin->instance())) { - interface->createWidget(this->parentWidget())->exec(); + const auto *interface = qobject_cast<PluginInterface *>(plugin->instance()); + auto *dlg = interface->createWidget(this->parentWidget()); + + if(auto *profileDlg = dynamic_cast<ProfileDialog*>(dlg)) { + WebProfileManager mgr; + mgr.walk([profileDlg](const QString &id, WebProfile *profile, QSettings *settings) { + profileDlg->addProfile(id, profile->name(), profile, settings); + }); } + + dlg->exec(); + } else { + spdlog::warn("Trying to run unloaded plugin!"); } }); insertAction(bottom_pluginSeparator, action); diff --git a/src/applicationmenu.h b/src/applicationmenu.h index 7e1fe47..8b558e0 100644 --- a/src/applicationmenu.h +++ b/src/applicationmenu.h @@ -25,6 +25,7 @@ public slots: void addPlugin(QPluginLoader *plugin); private: + Browser *m_app = nullptr; QAction *top_pluginSeparator = nullptr, *bottom_pluginSeparator = nullptr; }; diff --git a/src/browser.cpp b/src/browser.cpp index 2277e54..4f1e02e 100644 --- a/src/browser.cpp +++ b/src/browser.cpp @@ -92,10 +92,11 @@ void Browser::aboutPlugins() dlg->exec(); } -void Browser::loadPlugins(const QStringList &paths, const std::function<void(const QPluginLoader *)> &callback) +bool Browser::loadPlugin(const QString &path) { - if(paths.isEmpty()) - return; + if(path.isEmpty()) { + return false; + } Configuration conf; const auto state = PluginLoader::signature_state( @@ -103,23 +104,18 @@ void Browser::loadPlugins(const QStringList &paths, const std::function<void(con conf.value<bool>("plugins.signature.checked").value(), conf.value<bool>("plugins.signature.enforced").value()); - for(const auto &path : paths) { - auto *loader = new PluginLoader(path, state, this); - const bool loaded = loader->load(); - - callback(loader); - - if(!loaded) { - delete loader; - } else { - auto *info = new PluginInfo(loader); - m_plugins.append(info); + auto *loader = new PluginLoader(path, state, this); + const bool loaded = loader->load(); - for(MainWindow *window : qAsConst(m_windows)) { - addPluginTo(info, window); - } - } + if(!loaded) { + delete loader; + return false; } + auto *info = new PluginInfo(loader); + m_plugins.append(info); + + emit pluginAdded(loader); + return true; } void Browser::setup() @@ -205,6 +201,7 @@ void Browser::open(const QVector<Session::MainWindow> &data, bool merge) for(const auto &windowData : data) { auto *menu = new ApplicationMenu(this); + connect(this, &Browser::pluginAdded, menu, &ApplicationMenu::addPlugin); for(auto *info : qAsConst(m_plugins)) { menu->addPlugin(info->loader); } @@ -219,28 +216,3 @@ void Browser::open(const QVector<Session::MainWindow> &data, bool merge) }); } } - -void Browser::addPluginTo(PluginInfo *info, MainWindow *window) -{ - QPluginLoader *loader = info->loader; - auto *pluginMenu = new QMenu(loader->metaData().value("MetaData").toObject().value("name").toString()); - //window->m_menuBar->insertPlugin(pluginMenu); - info->menus.append(pluginMenu); - - auto *runAction = pluginMenu->addAction(tr("Run")); - runAction->setShortcut(QKeySequence::fromString(loader->metaData().value("MetaData").toObject().value("shortcut").toString())); - - connect(runAction, &QAction::triggered, window, [loader, window]() { - if(loader->isLoaded()) { - const auto *interface = qobject_cast<PluginInterface *>(loader->instance()); - Q_CHECK_PTR(interface); - interface->createWidget(window)->exec(); - } - }); - - auto *removeAction = pluginMenu->addAction(tr("Remove")); - connect(removeAction, &QAction::triggered, this, [this, info]() { - m_plugins.removeOne(info); - delete info; - }); -} diff --git a/src/browser.h b/src/browser.h index 74136f1..1964267 100644 --- a/src/browser.h +++ b/src/browser.h @@ -31,8 +31,6 @@ public: explicit Browser(int &argc, char *argv[], bool allowSecondary = true); ~Browser() final; - void loadPlugins( - const QStringList &paths, const std::function<void(const QPluginLoader *)> &callback = [](const auto) {}); void setup(); const QVector<MainWindow *> windows() const @@ -49,12 +47,18 @@ public: return m_downloads.get(); } +signals: + void pluginAdded(QPluginLoader *); + public slots: void about(); void aboutPlugins(); + void showWidget(QWidget *widget, MainWindow *where) const; void open(const QVector<Session::MainWindow> &data, bool merge = true); + bool loadPlugin(const QString &path); + private: struct PluginInfo { explicit PluginInfo(QPluginLoader *l) @@ -71,7 +75,6 @@ private: QPluginLoader *loader; QVector<QMenu *> menus; }; - void addPluginTo(PluginInfo *info, MainWindow *window); Q_DISABLE_COPY(Browser) diff --git a/src/main.cpp b/src/main.cpp index ca85b65..f0c1591 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -118,13 +118,13 @@ int main(int argc, char **argv) } // load plugins - app.loadPlugins(Util::files(conf.value<QString>("plugins.path").value(), { "*.so", "*.dll" }), - [](const auto *loader) { - if(loader->isLoaded()) - spdlog::info("Loaded plugin [{}]", qUtf8Printable(loader->fileName())); - else - spdlog::warn("Loading plugin [{}] failed: {}", qUtf8Printable(loader->fileName()), qUtf8Printable(loader->errorString())); - }); + for(const QString &path : Util::files(conf.value<QString>("plugins.path").value(), { "*.so", "*.dll" })) { + if(app.loadPlugin(path)) { + spdlog::debug("Loaded plugin [{}]", qUtf8Printable(path)); + } else { + spdlog::warn("Failed loading plugin [{}]", qUtf8Printable(path)); + } + } } const auto profile = []() { diff --git a/src/webengine/meson.build b/src/webengine/meson.build index db7bdc5..47e4adf 100644 --- a/src/webengine/meson.build +++ b/src/webengine/meson.build @@ -5,7 +5,7 @@ webengine_moc = mod_qt5.preprocess( dep_webengine = declare_dependency( include_directories: [ '.', smolbote_include ], - link_with: static_library('webengine', dependencies: dep_qt5, + link_with: static_library('webengine', dependencies: [ dep_qt5, dep_spdlog ], include_directories: smolbote_include, sources: [ 'webprofile.cpp', 'urlinterceptor.cpp', 'webprofilemanager.cpp', 'webpage.cpp', 'webview.cpp', 'webviewcontextmenu.cpp', webengine_moc ]) ) diff --git a/src/webengine/test/profile.cpp b/src/webengine/test/profile.cpp index 7351f66..ae3a4e3 100644 --- a/src/webengine/test/profile.cpp +++ b/src/webengine/test/profile.cpp @@ -22,98 +22,99 @@ TEST_CASE("loading profile settings") delete settings; } -SCENARIO("loading individual profiles") +SCENARIO("profile properties") { - GIVEN("no profile preset") - { - const QString search = GENERATE(as<QString>{}, "https://search.url/t=%1", "https://duckduckgo.com/?q=%1&ia=web", "aaabbbccc"); - const QUrl homepage = GENERATE(as<QUrl>{}, "https://homepage.net", "about:blank", "aaabbbccc"); - const QUrl newtab = GENERATE(as<QUrl>{}, "https://newtab.net", "about:blank", "aaabbbccc"); + const QString search{ "about:blank" }; + const QUrl homepage{ "about:blank" }; + const QUrl newtab{ "about:blank" }; + const QString id{ "id" }; + + REQUIRE(qEnvironmentVariableIsSet("PROFILE")); - const QString id{ "id" }; - auto *settings = WebProfile::load(QString(), search, homepage, newtab); - auto *profile = WebProfile::load(id, settings, true); + // create an empty settings object + const QString settings_path = GENERATE(as<QString>{}, QString(), qgetenv("PROFILE")); + auto *settings = WebProfile::load(settings_path, search, homepage, newtab); + // create the actual profile + auto *profile = WebProfile::load(id, settings, true); - REQUIRE(profile != nullptr); + REQUIRE(profile != nullptr); + REQUIRE(profile->isOffTheRecord()); + + WHEN("id constant") + { REQUIRE(profile->getId() == id); REQUIRE(profile->property("id").toString() == id); - REQUIRE(profile->name() == id); - REQUIRE(profile->search() == search); - REQUIRE(profile->homepage() == homepage); - REQUIRE(profile->newtab() == newtab); - - REQUIRE(profile->isOffTheRecord()); - delete settings; - delete profile; } - GIVEN("an off-the-record profile preset") + WHEN("changing profile name") { - REQUIRE(qEnvironmentVariableIsSet("PROFILE")); - - const QString id{ "id" }; - auto *settings = WebProfile::load(qgetenv("PROFILE"), QString(), QUrl(), QUrl()); - auto *profile = WebProfile::load(id, settings, true); - - REQUIRE(profile != nullptr); - REQUIRE(profile->getId() == id); - REQUIRE(profile->isOffTheRecord()); - - WHEN("created") + const QString name = GENERATE(as<QString>{}, "a", "bb", "ccc"); + profile->setName(name); + THEN("the name changes") { - THEN("uses default values") - { - REQUIRE(profile->name() == "Test Profile"); - REQUIRE(profile->search() == "https://duckduckgo.com/?q=%1&ia=web"); - REQUIRE(profile->homepage() == QUrl("about:blank")); - REQUIRE(profile->newtab() == QUrl("about:blank")); - } + REQUIRE(profile->name() == name); + REQUIRE(settings->value("name").toString() == name); } - - WHEN("changing profile name") + } + WHEN("changing search") + { + const QString search = GENERATE(as<QString>{}, "a", "bb", "ccc"); + profile->setSearch(search); + THEN("the search url changes") { - const QString name = GENERATE(as<QString>{}, "a", "bb", "ccc"); - profile->setName(name); - THEN("the name changes") - { - REQUIRE(profile->name() == name); - REQUIRE(settings->value("name").toString() == name); - } + REQUIRE(profile->search() == search); + REQUIRE(settings->value("search").toString() == search); } - WHEN("changing search url") + } + WHEN("changing homepage url") + { + const QUrl url = GENERATE(as<QUrl>{}, "a", "bb", "ccc"); + profile->setHomepage(url); + THEN("homepage changes") { - const QString search = GENERATE(as<QString>{}, "a", "bb", "ccc"); - profile->setSearch(search); - THEN("the search url changes") - { - REQUIRE(profile->search() == search); - REQUIRE(settings->value("search").toString() == search); - } + REQUIRE(profile->homepage() == url); + REQUIRE(settings->value("homepage").toUrl() == url); } - WHEN("changing homepage") + } + WHEN("changing newtab url") + { + const QUrl url = GENERATE(as<QUrl>{}, "a", "bb", "ccc"); + profile->setNewtab(url); + THEN("newtab changes") { - const QUrl url = GENERATE(as<QUrl>{}, "a", "bb", "ccc"); - profile->setHomepage(url); - THEN("homepage changes") - { - REQUIRE(profile->homepage() == url); - REQUIRE(settings->value("homepage").toUrl() == url); - } + REQUIRE(profile->newtab() == url); + REQUIRE(settings->value("newtab").toUrl() == url); } - WHEN("changing newtab") + } + + WHEN("changing cookies") + { + auto list = profile->cookies(); + REQUIRE(list.isEmpty()); + list.append(QNetworkCookie("name", "value").toRawForm()); + profile->setCookies(list); + THEN("new cookie list gets applied") { - const QUrl url = GENERATE(as<QUrl>{}, "a", "bb", "ccc"); - profile->setNewtab(url); - THEN("newtab changes") - { - REQUIRE(profile->newtab() == url); - REQUIRE(settings->value("newtab").toUrl() == url); - } + // There is no event loop, so the signals cannot fire and update the cookie list + //REQUIRE(list == profile->cookies()); } + } - delete settings; - delete profile; + WHEN("changing headers") + { + QMap<QString, QVariant> headers; + headers.insert("Dnt", "1"); + headers.insert("unknown", "pair"); + + profile->setHeaders(headers); + THEN("headers change") + { + REQUIRE(profile->headers() == headers); + } } + + delete settings; + delete profile; } int main(int argc, char **argv) diff --git a/src/webengine/webprofile.cpp b/src/webengine/webprofile.cpp index f0368c9..719ab34 100644 --- a/src/webengine/webprofile.cpp +++ b/src/webengine/webprofile.cpp @@ -7,11 +7,12 @@ */ #include "webprofile.h" +#include "urlinterceptor.h" #include <QFileInfo> #include <QSettings> #include <QWebEngineCookieStore> #include <QWebEngineSettings> -#include "urlinterceptor.h" +#include <spdlog/spdlog.h> static WebProfile *s_profile = nullptr; @@ -47,7 +48,7 @@ WebProfile *WebProfile::load(const QString &id, QSettings *settings, bool isOffT { WebProfile *profile = nullptr; - if(isOffTheRecord || settings->value("otr", isOffTheRecord).toBool()) { + if(settings->value("otr", isOffTheRecord).toBool()) { profile = new WebProfile(id, nullptr); } else { profile = new WebProfile(id, id, nullptr); @@ -89,7 +90,8 @@ WebProfile *WebProfile::load(const QString &id, QSettings *settings, bool isOffT { // headers settings->beginGroup("headers"); - for(const QString &key : settings->childKeys()) { + const auto keys = settings->childKeys(); + for(const QString &key : keys) { profile->setHttpHeader(key.toLatin1(), settings->value(key).toString().toLatin1()); } settings->endGroup(); @@ -110,11 +112,14 @@ WebProfile::WebProfile(const QString &id, QObject *parent) { QWebEngineProfile::setUrlRequestInterceptor(new UrlRequestInterceptor(this)); connect(this->cookieStore(), &QWebEngineCookieStore::cookieAdded, this, [this](const QNetworkCookie &cookie) { + spdlog::debug("[{}]: +cookie {}", qUtf8Printable(m_name), qUtf8Printable(cookie.name())); m_cookies.append(cookie); }); connect(this->cookieStore(), &QWebEngineCookieStore::cookieRemoved, this, [this](const QNetworkCookie &cookie) { - m_cookies.removeAll(cookie); + spdlog::debug("[{}]: -cookie {}", qUtf8Printable(m_name), qUtf8Printable(cookie.name())); + m_cookies.removeOne(cookie); }); + cookieStore()->loadAllCookies(); } // default constructor @@ -124,9 +129,12 @@ WebProfile::WebProfile(const QString &id, const QString &storageName, QObject *p { QWebEngineProfile::setUrlRequestInterceptor(new UrlRequestInterceptor(this)); connect(this->cookieStore(), &QWebEngineCookieStore::cookieAdded, this, [this](const QNetworkCookie &cookie) { + spdlog::debug("[{}]: +cookie {}", qUtf8Printable(m_name), qUtf8Printable(cookie.name())); m_cookies.append(cookie); }); connect(this->cookieStore(), &QWebEngineCookieStore::cookieRemoved, this, [this](const QNetworkCookie &cookie) { - m_cookies.removeAll(cookie); + spdlog::debug("[{}]: -cookie {}", qUtf8Printable(m_name), qUtf8Printable(cookie.name())); + m_cookies.removeOne(cookie); }); + cookieStore()->loadAllCookies(); } diff --git a/src/webengine/webprofile.h b/src/webengine/webprofile.h index 180cc9d..0747638 100644 --- a/src/webengine/webprofile.h +++ b/src/webengine/webprofile.h @@ -11,13 +11,14 @@ #include <QMap> #include <QNetworkCookie> +#include <QSettings> #include <QString> #include <QUrl> +#include <QVariant> #include <QVector> +#include <QWebEngineCookieStore> #include <QWebEngineProfile> #include <QWebEngineSettings> -#include <QVariant> -#include <QSettings> class UrlRequestInterceptor; class WebProfile : public QWebEngineProfile @@ -44,6 +45,10 @@ class WebProfile : public QWebEngineProfile Q_PROPERTY(bool spellCheckEnabled READ isSpellCheckEnabled WRITE setSpellCheckEnabled NOTIFY propertyChanged) + // more custom properties + Q_PROPERTY(QList<QVariant> cookies READ cookies WRITE setCookies NOTIFY cookiesChanged) + Q_PROPERTY(QMap<QString, QVariant> headers READ headers WRITE setHeaders NOTIFY headersChanged) + signals: void nameChanged(const QString &name); void searchChanged(const QString &url); @@ -52,6 +57,9 @@ signals: void propertyChanged(const QString &name, const QVariant &value); void attributeChanged(QWebEngineSettings::WebAttribute attribute, bool value); + + void cookiesChanged(); + void headersChanged(); void headerChanged(const QString &name, const QString &value); void headerRemoved(const QString &name); @@ -60,9 +68,9 @@ public: [[nodiscard]] static WebProfile *load(const QString &id, QSettings *settings, bool isOffTheRecord = true); WebProfile(const WebProfile &) = delete; - WebProfile& operator=(const WebProfile &) = delete; + WebProfile &operator=(const WebProfile &) = delete; WebProfile(WebProfile &&) = delete; - WebProfile& operator=(WebProfile &&) = delete; + WebProfile &operator=(WebProfile &&) = delete; static WebProfile *defaultProfile(); static void setDefaultProfile(WebProfile *profile); @@ -83,9 +91,13 @@ public: emit nameChanged(name); } - [[nodiscard]] QVector<QNetworkCookie> cookies() const + [[nodiscard]] QList<QVariant> cookies() const { - return qAsConst(m_cookies); + QList<QVariant> r; + for(const auto &cookie : m_cookies) { + r.append(cookie.toRawForm()); + } + return r; } [[nodiscard]] QString search() const @@ -166,7 +178,16 @@ public: emit headerRemoved(name); } } - + [[nodiscard]] QMap<QString, QVariant> headers() const + { + QMap<QString, QVariant> r; + auto it = m_headers.constBegin(); + while(it != m_headers.constEnd()) { + r.insert(QString(it.key()), QVariant(it.value())); + ++it; + } + return r; + } void setSpellCheckEnabled(bool enable) { QWebEngineProfile::setSpellCheckEnabled(enable); @@ -178,6 +199,29 @@ public: m_filters.append(interceptor); } +public slots: + void setCookies(const QList<QVariant> &cookies) + { + auto *store = cookieStore(); + store->deleteAllCookies(); + for(const auto &data : cookies) { + for(const auto &cookie : QNetworkCookie::parseCookies(data.toByteArray())) { + store->setCookie(cookie); + } + } + emit cookiesChanged(); + } + void setHeaders(const QMap<QString, QVariant> &headers) + { + m_headers.clear(); + auto it = headers.constBegin(); + while(it != headers.constEnd()) { + m_headers.insert(it.key().toLatin1(), it.value().toByteArray()); + ++it; + } + emit headersChanged(); + } + protected: // off-the-record constructor explicit WebProfile(const QString &id, QObject *parent = nullptr); @@ -190,8 +234,8 @@ protected: QUrl m_homepage = QUrl("about:blank"); QUrl m_newtab = QUrl("about:blank"); - QVector<QWebEngineUrlRequestInterceptor*> m_filters; - QVector<QNetworkCookie> m_cookies; + QVector<QWebEngineUrlRequestInterceptor *> m_filters; + QList<QNetworkCookie> m_cookies; QMap<QByteArray, QByteArray> m_headers; }; diff --git a/src/webengine/webprofilemanager.cpp b/src/webengine/webprofilemanager.cpp index 785251b..5cc83f8 100644 --- a/src/webengine/webprofilemanager.cpp +++ b/src/webengine/webprofilemanager.cpp @@ -56,7 +56,7 @@ QStringList WebProfileManager<true>::idList() const } template <> -void WebProfileManager<false>::walk(std::function<void(const QString &id, WebProfile *profile, const QSettings *settings)> f) const +void WebProfileManager<false>::walk(std::function<void(const QString &id, WebProfile *profile, QSettings *settings)> f) const { for(auto iter = profiles.begin(); iter != profiles.end(); ++iter) { f(iter.key(), iter.value().ptr, iter.value().settings); @@ -64,7 +64,7 @@ void WebProfileManager<false>::walk(std::function<void(const QString &id, WebPro } template <> -void WebProfileManager<true>::walk(std::function<void(const QString &id, WebProfile *profile, const QSettings *settings)> f) const +void WebProfileManager<true>::walk(std::function<void(const QString &id, WebProfile *profile, QSettings *settings)> f) const { s_instance->walk(f); } diff --git a/src/webengine/webprofilemanager.h b/src/webengine/webprofilemanager.h index 22fb31c..91dcaf8 100644 --- a/src/webengine/webprofilemanager.h +++ b/src/webengine/webprofilemanager.h @@ -93,7 +93,7 @@ public: return profiles.keys(); } - callable_when(unconsumed) void walk(std::function<void(const QString &id, WebProfile *profile, const QSettings *settings)>) const; + callable_when(unconsumed) void walk(std::function<void(const QString &id, WebProfile *profile, QSettings *settings)>) const; callable_when(unconsumed) void make_global(); |