diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5172ea0ba..1908cea09 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -38,6 +38,7 @@ configure_file(version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/version.h @ONLY) set(keepassx_SOURCES core/AutoTypeAssociations.cpp + core/AsyncTask.h core/Config.cpp core/CsvParser.cpp core/Database.cpp diff --git a/src/core/AsyncTask.h b/src/core/AsyncTask.h new file mode 100644 index 000000000..67cab1609 --- /dev/null +++ b/src/core/AsyncTask.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +#ifndef KEEPASSXC_ASYNCTASK_HPP +#define KEEPASSXC_ASYNCTASK_HPP + +#include +#include +#include + + +/** + * Asynchronously run computations outside the GUI thread. + */ +namespace AsyncTask +{ + +/** + * Wait for the given future without blocking the event loop. + * + * @param future future to wait for + * @return async task result + */ +template +typename std::result_of::type waitForFuture(QFuture::type> future) +{ + QEventLoop loop; + QFutureWatcher::type> watcher; + QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit())); + watcher.setFuture(future); + loop.exec(); + return future.result(); +} + +/** + * Run a given task and wait for it to finish without blocking the event loop. + * + * @param task std::function object to run + * @return async task result + */ +template +typename std::result_of::type runAndWaitForFuture(FunctionObject task) +{ + return waitForFuture(QtConcurrent::run(task)); +} + +}; // namespace AsyncTask + +#endif //KEEPASSXC_ASYNCTASK_HPP diff --git a/src/gui/DatabaseSettingsWidget.cpp b/src/gui/DatabaseSettingsWidget.cpp index 5f1dfeedf..ce1fb8dbb 100644 --- a/src/gui/DatabaseSettingsWidget.cpp +++ b/src/gui/DatabaseSettingsWidget.cpp @@ -18,28 +18,18 @@ #include "DatabaseSettingsWidget.h" #include "ui_DatabaseSettingsWidget.h" -#include -#include -#include -#include -#include #include -#include +#include "core/AsyncTask.h" #include "core/Database.h" #include "core/Group.h" #include "core/Metadata.h" #include "crypto/SymmetricCipher.h" -#include "format/KeePass2.h" -#include "keys/CompositeKey.h" -#include "format/KeePass2.h" -#include "crypto/kdf/Kdf.h" #include "MessageBox.h" DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent) : DialogyWidget(parent) , m_ui(new Ui::DatabaseSettingsWidget()) - , m_benchmarkField(nullptr) , m_db(nullptr) { m_ui->setupUi(this); @@ -51,6 +41,7 @@ DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent) connect(m_ui->historyMaxSizeCheckBox, SIGNAL(toggled(bool)), m_ui->historyMaxSizeSpinBox, SLOT(setEnabled(bool))); connect(m_ui->kdfComboBox, SIGNAL(currentIndexChanged(int)), SLOT(changeKdf(int))); + connect(m_ui->transformBenchmarkButton, SIGNAL(clicked()), SLOT(transformRoundsBenchmark())); } DatabaseSettingsWidget::~DatabaseSettingsWidget() @@ -111,6 +102,7 @@ void DatabaseSettingsWidget::load(Database* db) } displayKdf(*m_kdf); m_ui->kdfComboBox->blockSignals(blockSignals); + m_ui->transformRoundsSpinBox->setValue(static_cast(m_kdf->rounds())); m_ui->dbNameEdit->setFocus(); } @@ -191,13 +183,12 @@ void DatabaseSettingsWidget::reject() void DatabaseSettingsWidget::transformRoundsBenchmark() { - if (m_benchmarkField == nullptr) { - Q_ASSERT(false); - return; - } QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - m_benchmarkField->setValue(m_kdf->benchmark(1000)); - QApplication::restoreOverrideCursor(); + m_ui->transformRoundsSpinBox->setValue(AsyncTask::runAndWaitForFuture([this]() { + int rounds = m_kdf->benchmark(1000); + QApplication::restoreOverrideCursor(); + return rounds; + })); } void DatabaseSettingsWidget::truncateHistories() diff --git a/src/gui/DatabaseSettingsWidget.h b/src/gui/DatabaseSettingsWidget.h index a6001b892..fe8e25c6b 100644 --- a/src/gui/DatabaseSettingsWidget.h +++ b/src/gui/DatabaseSettingsWidget.h @@ -28,13 +28,14 @@ class Database; -namespace Ui { - class DatabaseSettingsWidget; +namespace Ui +{ +class DatabaseSettingsWidget; } -class DatabaseSettingsWidget : public DialogyWidget +class DatabaseSettingsWidget: public DialogyWidget { - Q_OBJECT +Q_OBJECT public: explicit DatabaseSettingsWidget(QWidget* parent = nullptr); @@ -58,8 +59,6 @@ private: const QScopedPointer m_ui; QList m_kdfWidgets; - QList> m_kdfFields; - QSpinBox* m_benchmarkField; QScopedPointer m_kdf; Database* m_db;