From 09c4508aee96ca20d084b8a60b4c6603de8bff8b Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Sun, 25 Nov 2018 13:01:17 +0100 Subject: Add Session Dialog --- doc/Development.asciidoc | 9 ++++ doc/Development/Fuzzing.asciidoc | 49 +++++++++++++++++++ lib/configuration/configuration.cpp | 2 + meson.build | 2 +- src/mainwindow/mainwindow.cpp | 11 ++--- src/meson.build | 12 +++-- src/session/sessiondialog.cpp | 87 +++++++++++++++++++++++++++++++++ src/session/sessiondialog.h | 34 +++++++++++++ src/session/sessiondialog.ui | 96 +++++++++++++++++++++++++++++++++++++ src/session/sessionform.cpp | 36 ++++++++++++++ src/session/sessionform.h | 37 ++++++++++++++ src/session/sessionform.ui | 41 ++++++++++++++++ tools/format-code.sh | 4 ++ 13 files changed, 407 insertions(+), 13 deletions(-) create mode 100644 doc/Development/Fuzzing.asciidoc create mode 100644 src/session/sessiondialog.cpp create mode 100644 src/session/sessiondialog.h create mode 100644 src/session/sessiondialog.ui create mode 100644 src/session/sessionform.cpp create mode 100644 src/session/sessionform.h create mode 100644 src/session/sessionform.ui create mode 100755 tools/format-code.sh diff --git a/doc/Development.asciidoc b/doc/Development.asciidoc index c849d67..1ef2ded 100644 --- a/doc/Development.asciidoc +++ b/doc/Development.asciidoc @@ -15,6 +15,15 @@ extensions. Source code should be kept as platform-agnostic as possible. syntax (SIGNAL/SLOT). This enables compile-time connect checks. * Prefer QVector over QList: http://lists.qt-project.org/pipermail/development/2017-March/029040.html +=== Setting linker +Meson has no environment variable to set the linker (link:https://github.com/mesonbuild/meson/issues/3597[issue]). + +Instead, this can be done using the cpp_link_args: +[source, sh] +---- +build% meson configure -Dcpp_link_args='-fuse-ld=gold' +---- + === clazy You can use https://github.com/KDE/clazy[clazy] to check Qt semantics. diff --git a/doc/Development/Fuzzing.asciidoc b/doc/Development/Fuzzing.asciidoc new file mode 100644 index 0000000..0981f1a --- /dev/null +++ b/doc/Development/Fuzzing.asciidoc @@ -0,0 +1,49 @@ +=== Setup +Required packages: afl + +==== Compiling Qt +This will build an instrumented Qt: + +[source, sh] +---- +export CC=$(which afl-gcc) +export CXX=$(which afl-g++) +./configure ... +make +---- + +=== Running the fuzzer +[source, sh] +---- +cd /sys/devices/system/cpu +su +echo performance | tee cpu*/cpufreq/scaling_governor +exit + +cd $testdir +afl-fuzz -m 512 -t 40 -i $input -o $output -- $testexe @@ + +# see for available scaling_governor values: +cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors + +cd /sys/devices/system/cpu +su +echo powersave | tee cpu*/cpufreq/scaling_governor +exit +---- + +The $input directory contains your reference input files, while the findings of the fuzzers will be written in $output. + +@@ gets replaced by the name of a file generated by AFL, containing the mutated input. + +=== Using ramdisk for tests +[source, sh] +---- +$ mkdir afl +# mount -t tmpfs -o size=1024M tmpfs afl/ +$ cd afl/ +$ afl-fuzz -i inputs -o findings ... +---- + +=== Sources +1. https://www.kdab.com/fuzzing-qt-fun-profit/ diff --git a/lib/configuration/configuration.cpp b/lib/configuration/configuration.cpp index 388c7bd..398044b 100644 --- a/lib/configuration/configuration.cpp +++ b/lib/configuration/configuration.cpp @@ -55,6 +55,8 @@ Configuration::Configuration(QObject *parent) ("browser.locale", po::value(), "Set Qt localization.") ("browser.translation", po::value(), "Set application localization.") + ("browser.session.path", po::value()->default_value("~/.config/smolbote/session.d")) + #ifdef CONFIG_USEBREAKPAD ("browser.crash.path", po::value()->default_value(CONFIG_PATH_CRASHDUMP)) ("browser.crash.handler", po::value()->default_value(CONFIG_PATH_CRASHHANDLER)) diff --git a/meson.build b/meson.build index 25fced3..06d52b6 100644 --- a/meson.build +++ b/meson.build @@ -26,7 +26,7 @@ dep_plasma = declare_dependency( ) # add -DQT_NO_DEBUG to non-debug builds -if not get_option('buildtype').startswith('debug') +if not get_option('debug') add_global_arguments('-DQT_NO_DEBUG', language: 'cpp') endif diff --git a/src/mainwindow/mainwindow.cpp b/src/mainwindow/mainwindow.cpp index 8f635c9..80e4faa 100644 --- a/src/mainwindow/mainwindow.cpp +++ b/src/mainwindow/mainwindow.cpp @@ -13,6 +13,7 @@ #include "configuration.h" #include "profilemanager.h" #include "session.h" +#include "session/sessiondialog.h" #include "subwindow/subwindow.h" #include "ui_mainwindow.h" #include "webengine/webview.h" @@ -126,14 +127,8 @@ MainWindow::MainWindow(const std::unique_ptr &config, QWidget *pa } }); connect(ui->actionLoadSession, &QAction::triggered, this, [this]() { - const QString filename = QFileDialog::getOpenFileName(this, tr("Load Session"), QDir::homePath(), tr("JSON (*.json)")); - QFile json(filename); - if(json.open(QIODevice::ReadOnly | QIODevice::Text)) { - auto *browser = qobject_cast(qApp); - auto doc = QJsonDocument::fromJson(json.readAll()); - browser->createSession(doc.object()); - json.close(); - } + auto *sessionDialog = new SessionDialog(this); + sessionDialog->exec(); }); } diff --git a/src/meson.build b/src/meson.build index f99d0c7..5df5a36 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,10 +1,11 @@ # poi poi_moc = qt5.preprocess( moc_headers: ['browser.h', - 'mainwindow/mainwindow.h', 'mainwindow/widgets/dockwidget.h', 'mainwindow/widgets/navigationbar.h', 'mainwindow/widgets/searchform.h', - 'subwindow/subwindow.h', 'subwindow/tabwidget.h', + 'mainwindow/mainwindow.h', 'mainwindow/widgets/dockwidget.h', 'mainwindow/widgets/navigationbar.h', 'mainwindow/widgets/searchform.h', + 'session/sessiondialog.h', 'session/sessionform.h', + 'subwindow/subwindow.h', 'subwindow/tabwidget.h', 'webengine/filter.h', 'webengine/urlinterceptor.h', 'webengine/webpage.h', 'webengine/webview.h'], - ui_files: ['mainwindow/mainwindow.ui', 'mainwindow/widgets/searchform.ui'], + ui_files: ['mainwindow/mainwindow.ui', 'mainwindow/widgets/searchform.ui', 'session/sessiondialog.ui', 'session/sessionform.ui'], qresources: '../data/resources.qrc', rcc_extra_arguments: ['--format-version=1'], dependencies: dep_qt5 @@ -32,7 +33,10 @@ poi = executable(get_option('poiName'), install: true, 'mainwindow/mainwindow.cpp', 'mainwindow/widgets/dockwidget.cpp', 'mainwindow/widgets/navigationbar.cpp', - 'mainwindow/widgets/searchform.cpp', + 'mainwindow/widgets/searchform.cpp', + + 'session/sessiondialog.cpp', + 'session/sessionform.cpp', 'subwindow/subwindow.cpp', 'subwindow/tabwidget.cpp', diff --git a/src/session/sessiondialog.cpp b/src/session/sessiondialog.cpp new file mode 100644 index 0000000..e31a42f --- /dev/null +++ b/src/session/sessiondialog.cpp @@ -0,0 +1,87 @@ +/* + * 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 "sessiondialog.h" +#include "../browser.h" +#include "../util.h" +#include "sessionform.h" +#include "ui_sessiondialog.h" +#include "ui_sessionform.h" +#include +#include +#include +#include + +SessionDialog::SessionDialog(QWidget *parent) + : QDialog(parent) + , ui(new Ui::SessionDialog) +{ + ui->setupUi(this); + ui->open->setIcon(style()->standardIcon(QStyle::SP_DirOpenIcon)); + + auto *browser = qobject_cast(qApp); + Q_CHECK_PTR(browser); + + for(const QString &path : Util::files(browser->configuration("browser.session.path"), { "*.json" })) { + auto *item = new QListWidgetItem(ui->listWidget); + auto *widget = new SessionForm(path, this); + connect(widget->ui->delete_toolButton, &QToolButton::clicked, this, [item, widget]() { + delete item; + delete widget; + }); + ui->listWidget->setItemWidget(item, widget); + } + +#ifdef QT_DEBUG + ui->listWidget->addItem(tr("Start new session")); +#endif + + connect(ui->listWidget, &QListWidget::currentItemChanged, this, [this](QListWidgetItem *currentItem, QListWidgetItem *previousItem) { + auto *currentWidget = qobject_cast(ui->listWidget->itemWidget(currentItem)); + if(currentWidget) + currentWidget->ui->delete_toolButton->show(); + + auto *previousWidget = qobject_cast(ui->listWidget->itemWidget(previousItem)); + if(previousWidget) + previousWidget->ui->delete_toolButton->hide(); + }); + + connect(ui->open, &QPushButton::clicked, this, [this]() { + const QString filename = QFileDialog::getOpenFileName(this, tr("Select Session file"), QDir::homePath(), tr("JSON (*.json)")); + if(!filename.isEmpty()) { + this->openSession(filename); + // close the dialog window; reject so it doesn't open another session + this->reject(); + } + }); + + connect(this, &SessionDialog::accepted, this, [this]() { + auto *currentWidget = qobject_cast(ui->listWidget->itemWidget(ui->listWidget->currentItem())); + if(currentWidget) + this->openSession(currentWidget->ui->label->text()); + }); +} + +SessionDialog::~SessionDialog() +{ + delete ui; +} + +void SessionDialog::openSession(const QString &filename) +{ + auto *browser = qobject_cast(qApp); + Q_CHECK_PTR(browser); + + QFile json(filename); + if(json.open(QIODevice::ReadOnly | QIODevice::Text)) { + auto *browser = qobject_cast(qApp); + auto doc = QJsonDocument::fromJson(json.readAll()); + browser->createSession(doc.object()); + json.close(); + } +} diff --git a/src/session/sessiondialog.h b/src/session/sessiondialog.h new file mode 100644 index 0000000..7fea3c2 --- /dev/null +++ b/src/session/sessiondialog.h @@ -0,0 +1,34 @@ +/* + * 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 SMOLBOTE_SESSIONDIALOG_H +#define SMOLBOTE_SESSIONDIALOG_H + +#include + +namespace Ui +{ +class SessionDialog; +} + +class SessionDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SessionDialog(QWidget *parent = nullptr); + ~SessionDialog() override; + +private: + void openSession(const QString &filename); + +private: + Ui::SessionDialog *ui; +}; + +#endif // SMOLBOTE_SESSIONDIALOG_H diff --git a/src/session/sessiondialog.ui b/src/session/sessiondialog.ui new file mode 100644 index 0000000..3a61dc1 --- /dev/null +++ b/src/session/sessiondialog.ui @@ -0,0 +1,96 @@ + + + SessionDialog + + + + 0 + 0 + 1000 + 600 + + + + Select Session + + + + + + + + Filter + + + + + + + Search + + + + + + + + + + + + + + Open from File + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close|QDialogButtonBox::Open + + + + + + + + + + + buttonBox + accepted() + SessionDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + SessionDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/session/sessionform.cpp b/src/session/sessionform.cpp new file mode 100644 index 0000000..761cb42 --- /dev/null +++ b/src/session/sessionform.cpp @@ -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://neueland.iserlohn-fortress.net/gitea/aqua/smolbote + * + * SPDX-License-Identifier: GPL-3.0 + */ + +#include "sessionform.h" +#include "ui_sessionform.h" +#include + +SessionForm::SessionForm(const QString &path, QWidget *parent) + : QWidget(parent) + , ui(new Ui::SessionForm) +{ + ui->setupUi(this); + ui->label->setText(path); + ui->delete_toolButton->setIcon(style()->standardIcon(QStyle::SP_TrashIcon)); + ui->delete_toolButton->hide(); +} + +SessionForm::~SessionForm() +{ + delete ui; +} + +void SessionForm::showDetails() +{ + ui->delete_toolButton->show(); +} + +void SessionForm::hideDetails() +{ + ui->delete_toolButton->hide(); +} diff --git a/src/session/sessionform.h b/src/session/sessionform.h new file mode 100644 index 0000000..5e5f52e --- /dev/null +++ b/src/session/sessionform.h @@ -0,0 +1,37 @@ +/* + * 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 SMOLBOTE_SESSIONFORM_H +#define SMOLBOTE_SESSIONFORM_H + +#include + +namespace Ui +{ +class SessionForm; +} + +class SessionForm : public QWidget +{ + Q_OBJECT + + friend class SessionDialog; + +public: + explicit SessionForm(const QString &path, QWidget *parent = nullptr); + ~SessionForm() override; + +public slots: + void showDetails(); + void hideDetails(); + +private: + Ui::SessionForm *ui; +}; + +#endif // SMOLBOTE_SESSIONFORM_H diff --git a/src/session/sessionform.ui b/src/session/sessionform.ui new file mode 100644 index 0000000..dbf0237 --- /dev/null +++ b/src/session/sessionform.ui @@ -0,0 +1,41 @@ + + + SessionForm + + + + 0 + 0 + 711 + 34 + + + + Form + + + + 0 + + + 0 + + + + + TextLabel + + + + + + + ... + + + + + + + + diff --git a/tools/format-code.sh b/tools/format-code.sh new file mode 100755 index 0000000..68be1d8 --- /dev/null +++ b/tools/format-code.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +# get names of staged files | filter out the header and cpp files | clang-format them +git diff --staged --name-only | grep --regex="\.h\|\.cpp" | xargs clang-format -i -- cgit v1.2.1