From 0205e25afb9db1e681e2a44bf44505f3ec6b1733 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 8 Apr 2020 09:50:30 +0200 Subject: [PATCH 01/29] Adding initial GUI code. --- CMakeLists.txt | 1 + gui/CMakeLists.txt | 22 +++++ gui/SearchWindow.cpp | 215 +++++++++++++++++++++++++++++++++++++++++++ gui/SearchWindow.h | 105 +++++++++++++++++++++ gui/main.cpp | 36 ++++++++ 5 files changed, 379 insertions(+) create mode 100644 gui/CMakeLists.txt create mode 100644 gui/SearchWindow.cpp create mode 100644 gui/SearchWindow.h create mode 100644 gui/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d6d36b3..12dedca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,6 +65,7 @@ include_directories(${PROJECT_BINARY_DIR}) add_subdirectory( common ) add_subdirectory( cli ) +add_subdirectory( gui ) # -------------------------------- # Install diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt new file mode 100644 index 0000000..01f46bb --- /dev/null +++ b/gui/CMakeLists.txt @@ -0,0 +1,22 @@ + +# Qt5 needs MOC,RCC and UIC +set( CMAKE_AUTOMOC ON ) +set( CMAKE_AUTORCC ON ) +set( CMAKE_AUTOUIC ON ) + +# -------------------------------- +# Program +# -------------------------------- + +set( PROGRAM_EXE ${CMAKE_PROJECT_NAME}-gui ) + +set( PROGRAM_SRC + main.cpp + SearchWindow.cpp +) + +add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) + +# Libraries +find_package( Qt5 COMPONENTS Core Widgets REQUIRED ) +target_link_libraries( ${PROGRAM_EXE} Qt5::Core Qt5::Widgets common ) diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp new file mode 100644 index 0000000..fae2321 --- /dev/null +++ b/gui/SearchWindow.cpp @@ -0,0 +1,215 @@ +/** + * MIT License + * + * Copyright (c) 2020 EOS Sw/eden + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include "SearchWindow.h" + +SearchWindow::SearchWindow(QWidget *parent, Qt::WindowFlags flags) : +QWidget (parent, flags), +m_worker (NULL), +m_status ("status"), +m_leet_cb ("L33t"), +m_btn_exec ("Search"), +m_btn_clear ("Clear") +{ + setMinimumSize(600, 400); + + // Monospaced font + QFont f_mono("monospace"); + + // Output + m_output.setFont(f_mono); + m_output.setReadOnly(true); + + // Layout + // ------------------------ + setLayout(&m_layout); + m_layout.setColumnStretch(0, 10); + + // First row. + m_layout.addWidget(&m_leet_cb, 0, 1); + + m_num_threads.setValue((int) eoskeygen::KeySearch::max_threads()); + m_num_threads.setRange(1, (int) eoskeygen::KeySearch::max_threads()); + m_num_threads.setSuffix(" Threads"); + m_layout.addWidget(&m_num_threads, 0, 2); + + m_num_results.setValue(10); + m_num_results.setRange(1, 99); + m_num_results.setSuffix(" Results"); + m_layout.addWidget(&m_num_results, 0, 3); + + // Second row. + m_layout.addWidget(&m_status, 1, 0, 1, 2); + m_layout.addWidget(&m_txt_search, 1, 0, 1, 2); + m_layout.addWidget(&m_btn_exec, 1, 2); + m_layout.addWidget(&m_btn_clear, 1, 3); + + + // Third row. + m_layout.addWidget(&m_output, 2, 0, 1, 0); + + // Search + // ------------------------ + + m_ksearch.setCallback(this); + + initSignals(); + + // Focus search field. + m_txt_search.setFocus(); +} + +SearchWindow::~SearchWindow() +{ + // Make sure worker thread exits. + if (m_worker) { + m_worker->quit(); + m_worker->wait(); + } +} + +void SearchWindow::initSignals() +{ + // Buttons + connect(&m_btn_exec, SIGNAL(released()), this, SLOT(search())); + connect(&m_btn_clear, SIGNAL(released()), &m_output, SLOT(clear())); + + connect(this, SIGNAL(addOutput(QString)), this, SLOT(output(QString))); +} + +void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct eoskeygen::KeySearch::result& result) +{ + int pos = (int) result.pos; + int len = (int) result.len; + QString pub = QString::fromStdString(libeosio::wif_pub_encode(key->pub)); + QString mid = pub.mid(pos, len); + QString left = pub.left(pos); + QString right = pub.mid(pos + len, pub.size() - pos); + + QString out = "Public: " + pub.left(3); + for(int i = 3; i < pub.length(); ) { + + if (i == pos) { + out += "" + pub.mid(pos, len) + ""; + i += pos; + continue; + } + + out += pub[i++]; + } + + out += "
Private: " + QString::fromStdString(libeosio::wif_priv_encode(key->secret)); + + // As this function could be called from a non-gui thread. we use signals. + emit addOutput("

" + out + "

"); +} + +// -------------------- +// Slots +// -------------------- + +void SearchWindow::search() +{ + if (m_worker && m_worker->isRunning()) { + return; + } + + const std::string& input = m_txt_search.text().toLocal8Bit().constData(); + eoskeygen::strlist_t list; + + if (m_leet_cb.isChecked()) { + list = eoskeygen::l33twords(input); + } else { + list = eoskeygen::strlist::splitw(input); + } + + // Validate that we atleast got something to search for. + if (list.size() < 1 || (list.size() == 1 && list[0] == "")) { + QMessageBox::warning( this, + "Empty search field.", + "You must specify atleast one search string" ); + return; + } + + m_ksearch.clear(); + m_ksearch.addList(list); + m_ksearch.setThreadCount(m_num_threads.value()); + + // Create search thread + m_worker = QThread::create([this] { + m_ksearch.find(m_num_results.value()); + }); + + connect(m_worker, SIGNAL(started()), this, SLOT(searchStarted())); + connect(m_worker, SIGNAL(finished()), this, SLOT(searchFinished())); + + m_status.setText("Searching for: " + QString::fromStdString(eoskeygen::strlist::join(list, ", "))); + m_worker->start(); +} + +void SearchWindow::output(const std::string& html) +{ + output(QString::fromStdString(html)); +} + +void SearchWindow::output(const QString& html) +{ + if (m_output.toPlainText().size()) { + m_output.setHtml(m_output.toHtml() + html); + } else { + m_output.setHtml(html); + } +} + +void SearchWindow::searchStarted() +{ + m_txt_search.setEnabled(false); + m_txt_search.setHidden(true); + m_btn_exec.setEnabled(false); + m_btn_clear.setEnabled(false); + m_num_threads.setEnabled(false); + m_num_results.setEnabled(false); +} + +void SearchWindow::searchFinished() +{ + m_txt_search.setEnabled(true); + m_txt_search.setHidden(false); + m_btn_exec.setEnabled(true); + m_btn_clear.setEnabled(true); + m_num_threads.setEnabled(true); + m_num_results.setEnabled(true); + + // We are done with the worker pointer. + if (m_worker) { + delete m_worker; + m_worker = NULL; + } +} diff --git a/gui/SearchWindow.h b/gui/SearchWindow.h new file mode 100644 index 0000000..2959c02 --- /dev/null +++ b/gui/SearchWindow.h @@ -0,0 +1,105 @@ +/** + * MIT License + * + * Copyright (c) 2020 EOS Sw/eden + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef SEARCH_WINDOW_H +#define SEARCH_WINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class QThread; + +class SearchWindow : public QWidget, public eoskeygen::IKeySearchResult +{ + Q_OBJECT +public: + explicit SearchWindow(QWidget *parent = 0, Qt::WindowFlags flags = Qt::WindowFlags()); + virtual ~SearchWindow(); + + void onResult(const struct libeosio::ec_keypair* key, const struct eoskeygen::KeySearch::result& result); + +private : + void initSignals(); + +private slots: + + // Start a search + void search(); + + // Output html to screen. + void output(const std::string& html); + void output(const QString& html); + + // Called when a search is started. + void searchStarted(); + + // Called when a search is done. + void searchFinished(); + +signals: + void addOutput(const QString& line); + +private: + + // Search worker thread. + QThread* m_worker; + + eoskeygen::KeySearch m_ksearch; + + // Widgets + // ---------------- + + // Status text. + QLabel m_status; + + // Search input. + QLineEdit m_txt_search; + + // Number of Threads. + QSpinBox m_num_threads; + + // Number of Results + QSpinBox m_num_results; + + QCheckBox m_leet_cb; + + // Buttons + QPushButton m_btn_exec; + QPushButton m_btn_clear; + + // Text output. + QTextEdit m_output; + + // Gui Layout. + QGridLayout m_layout; +}; + +#endif /* SEARCH_WINDOW_H */ diff --git a/gui/main.cpp b/gui/main.cpp new file mode 100644 index 0000000..73fe05f --- /dev/null +++ b/gui/main.cpp @@ -0,0 +1,36 @@ +/** + * MIT License + * + * Copyright (c) 2020 EOS Sw/eden + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include "SearchWindow.h" + +int main(int argc, char **argv) { + + QApplication app(argc, argv); + + SearchWindow search_win; + + search_win.show(); + + return app.exec(); +} From 69017c7a213790cb3cb77300a3b57b65c6b05596 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 9 Apr 2020 12:39:55 +0200 Subject: [PATCH 02/29] CMake: Adding BUILD_COMPONENT_GUI and BUILD_COMPONENT_CLI (so user's can build either one or both). --- CMakeLists.txt | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 12dedca..b752918 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,17 @@ project(eosio-keygen set( PROJECT_MAINTAINER "Henrik Hautakoski ") +# -------------------------------- +# Options +# -------------------------------- + +option(BUILD_COMPONENT_CLI "Build CLI Component" ON) +option(BUILD_COMPONENT_GUI "Build GUI Component (Qt5)" OFF) + +if (NOT BUILD_COMPONENT_CLI AND NOT BUILD_COMPONENT_GUI) + message(FATAL_ERROR "Atleast one of BUILD_COMPONENT_GUI,BUILD_COMPONENT_CLI must be set to ON") +endif() + # -------------------------------- # CMake settings # -------------------------------- @@ -60,12 +71,18 @@ configure_file(config.h.in "${PROJECT_BINARY_DIR}/config.h" @ONLY) include_directories(${PROJECT_BINARY_DIR}) # -------------------------------- -# Subdirectories +# Components # -------------------------------- add_subdirectory( common ) -add_subdirectory( cli ) -add_subdirectory( gui ) + +if (BUILD_COMPONENT_CLI) + add_subdirectory( cli ) +endif() + +if (BUILD_COMPONENT_GUI) + add_subdirectory( gui ) +endif() # -------------------------------- # Install From a2ec5eaaec7164b7ac65db2bb5368fb52934217a Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 9 Apr 2020 14:03:01 +0200 Subject: [PATCH 03/29] gui/CMakeLists.txt: Force Qt 5.11 or later. --- gui/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 01f46bb..fc02215 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -18,5 +18,5 @@ set( PROGRAM_SRC add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) # Libraries -find_package( Qt5 COMPONENTS Core Widgets REQUIRED ) +find_package( Qt5 5.11 COMPONENTS Core Widgets REQUIRED ) target_link_libraries( ${PROGRAM_EXE} Qt5::Core Qt5::Widgets common ) From 8cb3fad9b1b20818c4c95c3b74c828d3ec41c350 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 9 Apr 2020 14:05:03 +0200 Subject: [PATCH 04/29] gui/CMakeLists.txt: Adding install target --- gui/CMakeLists.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index fc02215..94b0226 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -8,7 +8,9 @@ set( CMAKE_AUTOUIC ON ) # Program # -------------------------------- -set( PROGRAM_EXE ${CMAKE_PROJECT_NAME}-gui ) +set( COMPONENT_NAME ${CMAKE_PROJECT_NAME}-gui) + +set( PROGRAM_EXE ${COMPONENT_NAME} ) set( PROGRAM_SRC main.cpp @@ -20,3 +22,11 @@ add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) # Libraries find_package( Qt5 5.11 COMPONENTS Core Widgets REQUIRED ) target_link_libraries( ${PROGRAM_EXE} Qt5::Core Qt5::Widgets common ) + +# -------------------------------- +# Install +# -------------------------------- + +install(TARGETS ${PROGRAM_EXE} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT ${COMPONENT_NAME}) From 3c21e27f450a1446751fa26ef84d4019a0b4b8ff Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 10 Apr 2020 10:45:19 +0200 Subject: [PATCH 05/29] gui/SearchWindow: Use QFutureWatcher instead of QThread. By removing the call to QThread::create() that requires version >= 5.11 we can have a lower version as requirement. This is useful because a lot of systems don't ship with 5.11 as default. --- gui/CMakeLists.txt | 4 ++-- gui/SearchWindow.cpp | 35 +++++++++-------------------------- gui/SearchWindow.h | 6 ++---- 3 files changed, 13 insertions(+), 32 deletions(-) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 94b0226..8c330ed 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -20,8 +20,8 @@ set( PROGRAM_SRC add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) # Libraries -find_package( Qt5 5.11 COMPONENTS Core Widgets REQUIRED ) -target_link_libraries( ${PROGRAM_EXE} Qt5::Core Qt5::Widgets common ) +find_package( Qt5 5.11 COMPONENTS Concurrent Core Widgets REQUIRED ) +target_link_libraries( ${PROGRAM_EXE} Qt5::Concurrent Qt5::Core Qt5::Widgets common ) # -------------------------------- # Install diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index fae2321..e34f556 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -24,7 +24,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -32,7 +33,6 @@ SearchWindow::SearchWindow(QWidget *parent, Qt::WindowFlags flags) : QWidget (parent, flags), -m_worker (NULL), m_status ("status"), m_leet_cb ("L33t"), m_btn_exec ("Search"), @@ -86,21 +86,16 @@ m_btn_clear ("Clear") m_txt_search.setFocus(); } -SearchWindow::~SearchWindow() -{ - // Make sure worker thread exits. - if (m_worker) { - m_worker->quit(); - m_worker->wait(); - } -} - void SearchWindow::initSignals() { // Buttons connect(&m_btn_exec, SIGNAL(released()), this, SLOT(search())); connect(&m_btn_clear, SIGNAL(released()), &m_output, SLOT(clear())); + // Worker Thread + connect(&m_worker, SIGNAL(started()), this, SLOT(searchStarted())); + connect(&m_worker, SIGNAL(finished()), this, SLOT(searchFinished())); + connect(this, SIGNAL(addOutput(QString)), this, SLOT(output(QString))); } @@ -137,7 +132,7 @@ void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct void SearchWindow::search() { - if (m_worker && m_worker->isRunning()) { + if (m_worker.isRunning()) { return; } @@ -162,16 +157,10 @@ void SearchWindow::search() m_ksearch.addList(list); m_ksearch.setThreadCount(m_num_threads.value()); - // Create search thread - m_worker = QThread::create([this] { - m_ksearch.find(m_num_results.value()); - }); - - connect(m_worker, SIGNAL(started()), this, SLOT(searchStarted())); - connect(m_worker, SIGNAL(finished()), this, SLOT(searchFinished())); + QFuture future = QtConcurrent::run(m_ksearch, &eoskeygen::KeySearch::find, m_num_results.value()); + m_worker.setFuture(future); m_status.setText("Searching for: " + QString::fromStdString(eoskeygen::strlist::join(list, ", "))); - m_worker->start(); } void SearchWindow::output(const std::string& html) @@ -206,10 +195,4 @@ void SearchWindow::searchFinished() m_btn_clear.setEnabled(true); m_num_threads.setEnabled(true); m_num_results.setEnabled(true); - - // We are done with the worker pointer. - if (m_worker) { - delete m_worker; - m_worker = NULL; - } } diff --git a/gui/SearchWindow.h b/gui/SearchWindow.h index 2959c02..0bc6a65 100644 --- a/gui/SearchWindow.h +++ b/gui/SearchWindow.h @@ -31,18 +31,16 @@ #include #include #include +#include #include #include #include -class QThread; - class SearchWindow : public QWidget, public eoskeygen::IKeySearchResult { Q_OBJECT public: explicit SearchWindow(QWidget *parent = 0, Qt::WindowFlags flags = Qt::WindowFlags()); - virtual ~SearchWindow(); void onResult(const struct libeosio::ec_keypair* key, const struct eoskeygen::KeySearch::result& result); @@ -70,7 +68,7 @@ signals: private: // Search worker thread. - QThread* m_worker; + QFutureWatcher m_worker; eoskeygen::KeySearch m_ksearch; From 40ddff41dbaee9043804e0985296c6237aadedb1 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 10 Apr 2020 10:48:26 +0200 Subject: [PATCH 06/29] gui/CMakeLists.txt: Drop the requirement for QT 5.11 --- gui/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 8c330ed..cb65710 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -20,7 +20,7 @@ set( PROGRAM_SRC add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) # Libraries -find_package( Qt5 5.11 COMPONENTS Concurrent Core Widgets REQUIRED ) +find_package( Qt5 COMPONENTS Concurrent Core Widgets REQUIRED ) target_link_libraries( ${PROGRAM_EXE} Qt5::Concurrent Qt5::Core Qt5::Widgets common ) # -------------------------------- From 0d44bbc8f65a8cae78ae505a2fd4424ec8039942 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 10 Apr 2020 10:49:26 +0200 Subject: [PATCH 07/29] .github/workflows/ci.yml: Build GUI --- .github/workflows/ci.yml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef1fafb..6f4e4a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,12 @@ jobs: strategy: matrix: os: [ ubuntu-16.04, ubuntu-18.04, macos-latest, windows-latest ] - build-opts: [ "-DFORCE_ANSI=ON", "-DFORCE_ANSI=OFF" ] + build-opts: [ + -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=ON, + -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=OFF, + -DBUILD_COMPONENT_CLI=OFF -DBUILD_COMPONENT_GUI=ON + ] + name: ${{matrix.os}} (${{matrix.build-opts}}) runs-on: ${{matrix.os}} @@ -20,13 +25,24 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Dependancies + - name: OpenSSL shell: bash run: | if [ "$RUNNER_OS" == "macOS" ]; then brew install openssl fi + - name: Qt - Ubuntu + if: contains(matrix.build-opts, '-DBUILD_COMPONENT_GUI=ON') && runner.os == 'Linux' + shell: bash + run: sudo apt-get install qt5-default + + - name: Qt - Windows/Mac + if: contains(matrix.build-opts, '-DBUILD_COMPONENT_GUI=ON') && runner.os != 'Linux' + uses: jurplel/install-qt-action@v2 + with: + version: '5.9' + - name: Configure shell: bash run: | From 48eb7161654f01bc4d94faa1bfcfa4d187a1a390 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 10 Apr 2020 17:44:19 +0200 Subject: [PATCH 08/29] .github/workflows/ci.yml: add abit more human friendly names than matrix.build-opts. and have the actual cmake flags as matrix includes. --- .github/workflows/ci.yml | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f4e4a2..1f9186e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,14 +12,17 @@ jobs: strategy: matrix: os: [ ubuntu-16.04, ubuntu-18.04, macos-latest, windows-latest ] - build-opts: [ - -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=ON, - -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=OFF, - -DBUILD_COMPONENT_CLI=OFF -DBUILD_COMPONENT_GUI=ON - ] + build: [ cli-force-ansi-on, cli-force-ansi-off, gui ] + include: + - build: cli-force-ansi-on + cmake-opts: -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=ON + - build: cli-force-ansi-off + cmake-opts: -DBUILD_COMPONENT_CLI=ON -DBUILD_COMPONENT_GUI=OFF -DFORCE_ANSI=ON + - build: gui + cmake-opts: -DBUILD_COMPONENT_CLI=OFF -DBUILD_COMPONENT_GUI=ON - name: ${{matrix.os}} (${{matrix.build-opts}}) + name: ${{matrix.os}} (${{matrix.build}}) runs-on: ${{matrix.os}} steps: @@ -33,12 +36,12 @@ jobs: fi - name: Qt - Ubuntu - if: contains(matrix.build-opts, '-DBUILD_COMPONENT_GUI=ON') && runner.os == 'Linux' + if: matrix.build == 'gui' && runner.os == 'Linux' shell: bash run: sudo apt-get install qt5-default - name: Qt - Windows/Mac - if: contains(matrix.build-opts, '-DBUILD_COMPONENT_GUI=ON') && runner.os != 'Linux' + if: matrix.build == 'gui' && runner.os != 'Linux' uses: jurplel/install-qt-action@v2 with: version: '5.9' @@ -49,7 +52,7 @@ jobs: if [ "$RUNNER_OS" == "macOS" ]; then SSL_OPTS="-D OPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1" fi - cmake ${SSL_OPTS} ${{matrix.build-opts}} -B build + cmake ${SSL_OPTS} ${{matrix.cmake-opts}} -B build - name: Build shell: bash @@ -58,5 +61,5 @@ jobs: - name: Upload artifact uses: actions/upload-artifact@v1 with: - name: ${{matrix.os}}_${{matrix.build-opts}}-build + name: ${{matrix.os}}_${{matrix.build}}-build path: build From c206ec764f4c138f3a6ae1897e3dacd4f85a3ece Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 10 Apr 2020 17:47:45 +0200 Subject: [PATCH 09/29] .github/workflows/ci.yml: some minor cleanup. --- .github/workflows/ci.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f9186e..af10bb7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,12 +28,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: OpenSSL + - name: OpenSSL OSX + if: runner.os == 'macOS' shell: bash - run: | - if [ "$RUNNER_OS" == "macOS" ]; then - brew install openssl - fi + run: brew install openssl - name: Qt - Ubuntu if: matrix.build == 'gui' && runner.os == 'Linux' @@ -49,10 +47,11 @@ jobs: - name: Configure shell: bash run: | + OPTS="${{matrix.cmake-opts}}" if [ "$RUNNER_OS" == "macOS" ]; then - SSL_OPTS="-D OPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1" + OPTS="-D OPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1 ${OPTS}" fi - cmake ${SSL_OPTS} ${{matrix.cmake-opts}} -B build + cmake ${OPTS} -B build - name: Build shell: bash From bfc40bd3e70ccfaba6ed2908e53b41ac7275f49b Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sat, 11 Apr 2020 16:29:42 +0200 Subject: [PATCH 10/29] gui/SearchWindow.cpp: Force scrollbar to the bottom when adding text to m_output. --- gui/SearchWindow.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index e34f556..ba3a757 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -23,6 +23,7 @@ */ #include #include +#include #include #include #include @@ -175,6 +176,9 @@ void SearchWindow::output(const QString& html) } else { m_output.setHtml(html); } + + // Force scrollbar to the bottom. + m_output.verticalScrollBar()->setValue(m_output.verticalScrollBar()->maximum()); } void SearchWindow::searchStarted() From 6a53999c14196b30dda0a1f3972bfcbbb1dc927c Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 14:24:56 +0200 Subject: [PATCH 11/29] Adding gui/MultiSelect module --- gui/CMakeLists.txt | 1 + gui/MultiSelect.cpp | 137 ++++++++++++++++++++++++++++++++++++++++++++ gui/MultiSelect.h | 89 ++++++++++++++++++++++++++++ 3 files changed, 227 insertions(+) create mode 100644 gui/MultiSelect.cpp create mode 100644 gui/MultiSelect.h diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index cb65710..f681677 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -15,6 +15,7 @@ set( PROGRAM_EXE ${COMPONENT_NAME} ) set( PROGRAM_SRC main.cpp SearchWindow.cpp + MultiSelect.cpp ) add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) diff --git a/gui/MultiSelect.cpp b/gui/MultiSelect.cpp new file mode 100644 index 0000000..6288b89 --- /dev/null +++ b/gui/MultiSelect.cpp @@ -0,0 +1,137 @@ +/** + * MIT License + * + * Copyright (c) 2020 EOS Sw/eden + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include +#include +#include +#include "MultiSelect.h" + +MultiSelect::MultiSelect(const QString& text, QWidget *parent) : +QPushButton (text + ": none", parent) +{ + QPushButton* btn; + QVBoxLayout* layout; + + m_prefix = text; + + // Dialog + m_dialog = new QDialog(this); + + // Dialog Widgets + m_list = new QListWidget(); + btn = new QPushButton("Select"); + + // Dialog layout + layout = new QVBoxLayout(m_dialog); + layout->addWidget(m_list); + layout->addWidget(btn); + + // Connections + QObject::connect(btn, SIGNAL(clicked()), m_dialog, SLOT(accept())); + QObject::connect(m_dialog, SIGNAL(accepted()), this, SLOT(selectionConfirmed())); + QObject::connect(m_list, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(listItemClicked(QListWidgetItem*))); +} + +void MultiSelect::addItem(const QString& text) +{ + QListWidgetItem* item = new QListWidgetItem(text, m_list); + item->setFlags(Qt::ItemIsEnabled); + item->setCheckState(Qt::Unchecked); +} + +void MultiSelect::addItems(const QStringList& list) +{ + QStringList::const_iterator it; + + for(it = list.cbegin(); it != list.cend(); it++) { + addItem(*it); + } +} + +void MultiSelect::clearItems() +{ + m_list->clear(); +} + +QStringList MultiSelect::getSelectedItems() const +{ + QListWidgetItem* item; + QStringList ret; + + // Cannot use m_list->selectedItems() as that function only fetches + // _selected_ and not _checked_ items (there is a difference). + for(int i = 0; i < m_list->count(); i++) { + item = m_list->item(i); + // Include in list if checked. + if (item->checkState() == Qt::Checked) { + ret << item->text(); + } + } + return ret; +} + +void MultiSelect::selectionConfirmed() +{ + QStringList selected = getSelectedItems(); + + // Update the text for this widget to + // reflect the selected objects. + QString txt = m_prefix + ": "; + + // Have more than one item. show number of items. + if (selected.count() > 1) { + txt += QString::number(selected.count()) + " selected"; + } + // Just one, we can show the text. + else if (selected.count() == 1) { + txt += selected.at(0); + } + else { + txt += "none"; + } + + setText(txt); + + // Emit the selectionChanged signal with the updated list + emit selectionChanged(selected); +} + +void MultiSelect::listItemClicked(QListWidgetItem *item) +{ + // toggle state when user clicks. + bool checked = item->checkState() == Qt::Checked; + item->setCheckState(checked ? Qt::Unchecked : Qt::Checked); +} + +void MultiSelect::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + // Show select dialog. + m_dialog->show(); + } else { + // pass on other buttons to base class + QPushButton::mousePressEvent(event); + } +} diff --git a/gui/MultiSelect.h b/gui/MultiSelect.h new file mode 100644 index 0000000..fc40731 --- /dev/null +++ b/gui/MultiSelect.h @@ -0,0 +1,89 @@ +/** + * MIT License + * + * Copyright (c) 2020 EOS Sw/eden + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef MULTI_SELECT_H +#define MULTI_SELECT_H + +#include +#include +#include + +class QMouseEvent; +class QPushButton; +class QListWidget; +class QListWidgetItem; +class QDialog; +class MultiSelectDialog; + +// +// MultiSelect implements multi selection of items using +// a push button and a dialog with a list of checkbox items. +// +class MultiSelect : public QPushButton +{ + Q_OBJECT +public: + MultiSelect(const QString& text, QWidget *parent = 0); + + // Items. + + void addItem(const QString& text); + + void addItems(const QStringList& list); + + void clearItems(); + + // Get a list of currently selected items. + QStringList getSelectedItems() const; + +signals: + + // This signal is emitted whenever the user has made a new selection. + void selectionChanged(QStringList selected); + +private slots : + + // Called when the dialog is accepted. + void selectionConfirmed(); + + // Called when a list item is clicked on. + void listItemClicked(QListWidgetItem *item); + +protected : + + // Event handlers + void mousePressEvent(QMouseEvent *e) override; + +private : + + // Prefix to show on the button before value. + QString m_prefix; + + // List of items + QListWidget* m_list; + + // Dialog to show if this widget are clicked on. + QDialog* m_dialog; +}; + +#endif /* MULTI_SELECT_H */ From 45005c995073d17330ba36eb22dd12523d795f78 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 14:37:25 +0200 Subject: [PATCH 12/29] adding gui/helpers module --- gui/CMakeLists.txt | 1 + gui/helpers.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ gui/helpers.h | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 gui/helpers.cpp create mode 100644 gui/helpers.h diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index f681677..7dba68c 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -16,6 +16,7 @@ set( PROGRAM_SRC main.cpp SearchWindow.cpp MultiSelect.cpp + helpers.cpp ) add_executable( ${PROGRAM_EXE} ${PROGRAM_SRC} ) diff --git a/gui/helpers.cpp b/gui/helpers.cpp new file mode 100644 index 0000000..3b492b4 --- /dev/null +++ b/gui/helpers.cpp @@ -0,0 +1,42 @@ +/** + * MIT License + * + * Copyright (c) 2020 EOS Sw/eden + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "helpers.h" + +QStringList get_files(const QDir& directory) { + + QFileInfoList list; + QStringList ret; + + list = directory.entryInfoList(QDir::Files); + for (int i = 0; i < list.size(); ++i) { + QFileInfo info = list.at(i); + ret << info.fileName(); + } + return ret; +} + +QStringList get_files(const QString& directory) +{ + return get_files(QDir(directory)); +} diff --git a/gui/helpers.h b/gui/helpers.h new file mode 100644 index 0000000..ccb5218 --- /dev/null +++ b/gui/helpers.h @@ -0,0 +1,38 @@ +/** + * MIT License + * + * Copyright (c) 2020 EOS Sw/eden + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef HELPERS_H +#define HELPERS_H + +#include +#include +#include + +// +// Get a list of files for a given directory. +// NOTE: only filenames are returned. relative to directory. +// +QStringList get_files(const QDir& directory); +QStringList get_files(const QString& directory); + +#endif /* HELPERS_H */ From 35706c9ba3712629cf03d641135239b5d12413e0 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 14:39:46 +0200 Subject: [PATCH 13/29] config.h.in: add CONFIG_DICT_PATH and CONFIG_DICT_FULL_PATH --- config.h.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config.h.in b/config.h.in index ff5de16..a1b4356 100644 --- a/config.h.in +++ b/config.h.in @@ -31,4 +31,7 @@ #define CONFIG_SHARE_PATH "@CMAKE_INSTALL_DATADIR@/@CMAKE_PROJECT_NAME@" #define CONFIG_SHARE_FULL_PATH "@CMAKE_INSTALL_FULL_DATADIR@/@CMAKE_PROJECT_NAME@" +#define CONFIG_DICT_PATH "@CMAKE_INSTALL_DATADIR@/@CMAKE_PROJECT_NAME@/dict" +#define CONFIG_DICT_FULL_PATH "@CMAKE_INSTALL_FULL_DATADIR@/@CMAKE_PROJECT_NAME@/dict" + #endif /* EOSIOKEYGEN_CONFIG_H */ From 3b1ada9cb771e93ac4242e39d7b44d6aa84b48c8 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 16:19:39 +0200 Subject: [PATCH 14/29] gui/SearchWindow.cpp: in onResult() should advance index by word length and not position. --- gui/SearchWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index ba3a757..9543467 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -114,7 +114,7 @@ void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct if (i == pos) { out += "" + pub.mid(pos, len) + ""; - i += pos; + i += len; continue; } From 1f8fbfc8caa843908d37e37c521905f1288922e6 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 16:33:07 +0200 Subject: [PATCH 15/29] gui/SearchWindow: implement dictionary language --- gui/SearchWindow.cpp | 39 +++++++++++++++++++++++++++++++++++++++ gui/SearchWindow.h | 8 ++++++++ 2 files changed, 47 insertions(+) diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index 9543467..bc5d9b7 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -30,12 +30,15 @@ #include #include #include +#include "config.h" +#include "helpers.h" #include "SearchWindow.h" SearchWindow::SearchWindow(QWidget *parent, Qt::WindowFlags flags) : QWidget (parent, flags), m_status ("status"), m_leet_cb ("L33t"), +m_dict_lang ("Dictionary Language"), m_btn_exec ("Search"), m_btn_clear ("Clear") { @@ -54,6 +57,9 @@ m_btn_clear ("Clear") m_layout.setColumnStretch(0, 10); // First row. + m_dict_lang.addItems(get_files(CONFIG_DICT_FULL_PATH)); + m_layout.addWidget(&m_dict_lang, 0, 0); + m_layout.addWidget(&m_leet_cb, 0, 1); m_num_threads.setValue((int) eoskeygen::KeySearch::max_threads()); @@ -98,6 +104,8 @@ void SearchWindow::initSignals() connect(&m_worker, SIGNAL(finished()), this, SLOT(searchFinished())); connect(this, SIGNAL(addOutput(QString)), this, SLOT(output(QString))); + + connect(&m_dict_lang, SIGNAL(selectionChanged(QStringList)), this, SLOT(langSelected(QStringList))); } void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct eoskeygen::KeySearch::result& result) @@ -108,6 +116,7 @@ void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct QString mid = pub.mid(pos, len); QString left = pub.left(pos); QString right = pub.mid(pos + len, pub.size() - pos); + eoskeygen::Dictionary::search_result_t dict_res = m_dict.search(pub.toStdString()); QString out = "Public: " + pub.left(3); for(int i = 3; i < pub.length(); ) { @@ -118,6 +127,16 @@ void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct continue; } + // Look in the dictionary. + auto dp = dict_res.find(i); + if (dp != dict_res.end()) { + int p = (int) dp->first; + int l = (int) dp->second; + out += "" + pub.mid(p, l) + ""; + i += l; + continue; + } + out += pub[i++]; } @@ -181,10 +200,29 @@ void SearchWindow::output(const QString& html) m_output.verticalScrollBar()->setValue(m_output.verticalScrollBar()->maximum()); } +void SearchWindow::langSelected(QStringList selected) +{ + std::string base_path(CONFIG_DICT_FULL_PATH); + + // Clear dictionary first. + m_dict.clear(); + + // Go through all selected languages. + for(QStringList::const_iterator it = selected.cbegin(); it != selected.cend(); it++) { + + // Load and add them to dictionary. + eoskeygen::Dictionary dict; + dict.loadFromFile(base_path + "/" + it->toStdString()); + + m_dict.add(dict); + } +} + void SearchWindow::searchStarted() { m_txt_search.setEnabled(false); m_txt_search.setHidden(true); + m_dict_lang.setEnabled(false); m_btn_exec.setEnabled(false); m_btn_clear.setEnabled(false); m_num_threads.setEnabled(false); @@ -195,6 +233,7 @@ void SearchWindow::searchFinished() { m_txt_search.setEnabled(true); m_txt_search.setHidden(false); + m_dict_lang.setEnabled(true); m_btn_exec.setEnabled(true); m_btn_clear.setEnabled(true); m_num_threads.setEnabled(true); diff --git a/gui/SearchWindow.h b/gui/SearchWindow.h index 0bc6a65..1aff8b1 100644 --- a/gui/SearchWindow.h +++ b/gui/SearchWindow.h @@ -35,6 +35,7 @@ #include #include #include +#include "MultiSelect.h" class SearchWindow : public QWidget, public eoskeygen::IKeySearchResult { @@ -62,6 +63,9 @@ private slots: // Called when a search is done. void searchFinished(); + // Called when dictionary language(s) are selected. + void langSelected(QStringList selected); + signals: void addOutput(const QString& line); @@ -72,6 +76,8 @@ private: eoskeygen::KeySearch m_ksearch; + eoskeygen::Dictionary m_dict; + // Widgets // ---------------- @@ -89,6 +95,8 @@ private: QCheckBox m_leet_cb; + MultiSelect m_dict_lang; + // Buttons QPushButton m_btn_exec; QPushButton m_btn_clear; From c14a453f01f45f31bda229cd0ba2c699f8a082c8 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 16:38:17 +0200 Subject: [PATCH 16/29] gui/SearchWindow.cpp: disable m_leet_cb during search. --- gui/SearchWindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index bc5d9b7..0ae0d5e 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -223,6 +223,7 @@ void SearchWindow::searchStarted() m_txt_search.setEnabled(false); m_txt_search.setHidden(true); m_dict_lang.setEnabled(false); + m_leet_cb.setEnabled(false); m_btn_exec.setEnabled(false); m_btn_clear.setEnabled(false); m_num_threads.setEnabled(false); @@ -234,6 +235,7 @@ void SearchWindow::searchFinished() m_txt_search.setEnabled(true); m_txt_search.setHidden(false); m_dict_lang.setEnabled(true); + m_leet_cb.setEnabled(true); m_btn_exec.setEnabled(true); m_btn_clear.setEnabled(true); m_num_threads.setEnabled(true); From 925ef7e8ad285071dafc2f7caaa6feded71980cf Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 21:49:40 +0200 Subject: [PATCH 17/29] gui/MultiSelect: add variable for default state for addItem() and addItems() --- gui/MultiSelect.cpp | 8 ++++---- gui/MultiSelect.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gui/MultiSelect.cpp b/gui/MultiSelect.cpp index 6288b89..2578eba 100644 --- a/gui/MultiSelect.cpp +++ b/gui/MultiSelect.cpp @@ -54,19 +54,19 @@ QPushButton (text + ": none", parent) QObject::connect(m_list, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(listItemClicked(QListWidgetItem*))); } -void MultiSelect::addItem(const QString& text) +void MultiSelect::addItem(const QString& text, bool checked) { QListWidgetItem* item = new QListWidgetItem(text, m_list); item->setFlags(Qt::ItemIsEnabled); - item->setCheckState(Qt::Unchecked); + item->setCheckState(checked ? Qt::Checked : Qt::Unchecked); } -void MultiSelect::addItems(const QStringList& list) +void MultiSelect::addItems(const QStringList& list, bool checked) { QStringList::const_iterator it; for(it = list.cbegin(); it != list.cend(); it++) { - addItem(*it); + addItem(*it, checked); } } diff --git a/gui/MultiSelect.h b/gui/MultiSelect.h index fc40731..830c4d0 100644 --- a/gui/MultiSelect.h +++ b/gui/MultiSelect.h @@ -47,9 +47,9 @@ public: // Items. - void addItem(const QString& text); + void addItem(const QString& text, bool checked = false); - void addItems(const QStringList& list); + void addItems(const QStringList& list, bool checked = false); void clearItems(); From 50a2805c3fe1db9739d11090bda0cb3a3fa8ffdb Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 21:56:04 +0200 Subject: [PATCH 18/29] gui/MultiSelect: Add user_add_item parameter to constructor adds a button and signal to the MultiSelect, allowing client code to implement adding items from user input. --- gui/MultiSelect.cpp | 17 +++++++++++++++-- gui/MultiSelect.h | 9 ++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/gui/MultiSelect.cpp b/gui/MultiSelect.cpp index 2578eba..98c6dac 100644 --- a/gui/MultiSelect.cpp +++ b/gui/MultiSelect.cpp @@ -28,8 +28,8 @@ #include #include "MultiSelect.h" -MultiSelect::MultiSelect(const QString& text, QWidget *parent) : -QPushButton (text + ": none", parent) +MultiSelect::MultiSelect(const QString& text, bool user_can_add, QWidget *parent) : +QPushButton (text + ": none", parent) { QPushButton* btn; QVBoxLayout* layout; @@ -52,6 +52,13 @@ QPushButton (text + ": none", parent) QObject::connect(btn, SIGNAL(clicked()), m_dialog, SLOT(accept())); QObject::connect(m_dialog, SIGNAL(accepted()), this, SLOT(selectionConfirmed())); QObject::connect(m_list, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(listItemClicked(QListWidgetItem*))); + + // Configured to let users add items. provide button and signal. + if (user_can_add) { + btn = new QPushButton("Add"); + layout->addWidget(btn); + QObject::connect(btn, SIGNAL(clicked()), this, SLOT(addBtnClicked())); + } } void MultiSelect::addItem(const QString& text, bool checked) @@ -125,6 +132,12 @@ void MultiSelect::listItemClicked(QListWidgetItem *item) item->setCheckState(checked ? Qt::Unchecked : Qt::Checked); } +void MultiSelect::addBtnClicked() +{ + // Just emit addNewItem event. + emit addNewItem(); +} + void MultiSelect::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { diff --git a/gui/MultiSelect.h b/gui/MultiSelect.h index 830c4d0..84ed207 100644 --- a/gui/MultiSelect.h +++ b/gui/MultiSelect.h @@ -43,7 +43,7 @@ class MultiSelect : public QPushButton { Q_OBJECT public: - MultiSelect(const QString& text, QWidget *parent = 0); + MultiSelect(const QString& text, bool user_add_item = false, QWidget *parent = 0); // Items. @@ -61,6 +61,10 @@ signals: // This signal is emitted whenever the user has made a new selection. void selectionChanged(QStringList selected); + // This signal is emitted whenever the user clicks the "Add" button. + // NOTE: Will only be emitted if `user_add_item` has been set to `true` in the constructor. + void addNewItem(); + private slots : // Called when the dialog is accepted. @@ -69,6 +73,9 @@ private slots : // Called when a list item is clicked on. void listItemClicked(QListWidgetItem *item); + // Called when the add button is clicked on. + void addBtnClicked(); + protected : // Event handlers From 769e56af2f3d4275fbcf70d9047886d2b947fdd3 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Tue, 14 Apr 2020 21:56:41 +0200 Subject: [PATCH 19/29] gui/SearchWindow: adding "Dictionary file" widget. --- gui/SearchWindow.cpp | 71 ++++++++++++++++++++++++++++++-------------- gui/SearchWindow.h | 8 +++-- 2 files changed, 54 insertions(+), 25 deletions(-) diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index 0ae0d5e..cbfa290 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -22,6 +22,7 @@ * SOFTWARE. */ #include +#include #include #include #include @@ -39,6 +40,7 @@ QWidget (parent, flags), m_status ("status"), m_leet_cb ("L33t"), m_dict_lang ("Dictionary Language"), +m_dict_file ("Dictionary File", true), m_btn_exec ("Search"), m_btn_clear ("Clear") { @@ -55,29 +57,30 @@ m_btn_clear ("Clear") // ------------------------ setLayout(&m_layout); m_layout.setColumnStretch(0, 10); + m_layout.setColumnStretch(1, 10); // First row. m_dict_lang.addItems(get_files(CONFIG_DICT_FULL_PATH)); m_layout.addWidget(&m_dict_lang, 0, 0); + m_layout.addWidget(&m_dict_file, 0, 1); - m_layout.addWidget(&m_leet_cb, 0, 1); + m_layout.addWidget(&m_leet_cb, 0, 2); m_num_threads.setValue((int) eoskeygen::KeySearch::max_threads()); m_num_threads.setRange(1, (int) eoskeygen::KeySearch::max_threads()); m_num_threads.setSuffix(" Threads"); - m_layout.addWidget(&m_num_threads, 0, 2); + m_layout.addWidget(&m_num_threads, 0, 3); m_num_results.setValue(10); m_num_results.setRange(1, 99); m_num_results.setSuffix(" Results"); - m_layout.addWidget(&m_num_results, 0, 3); + m_layout.addWidget(&m_num_results, 0, 4); // Second row. - m_layout.addWidget(&m_status, 1, 0, 1, 2); - m_layout.addWidget(&m_txt_search, 1, 0, 1, 2); - m_layout.addWidget(&m_btn_exec, 1, 2); - m_layout.addWidget(&m_btn_clear, 1, 3); - + m_layout.addWidget(&m_status, 1, 0, 1, 3); + m_layout.addWidget(&m_txt_search, 1, 0, 1, 3); + m_layout.addWidget(&m_btn_exec, 1, 3); + m_layout.addWidget(&m_btn_clear, 1, 4); // Third row. m_layout.addWidget(&m_output, 2, 0, 1, 0); @@ -105,7 +108,35 @@ void SearchWindow::initSignals() connect(this, SIGNAL(addOutput(QString)), this, SLOT(output(QString))); - connect(&m_dict_lang, SIGNAL(selectionChanged(QStringList)), this, SLOT(langSelected(QStringList))); + connect(&m_dict_file, SIGNAL(addNewItem()), this, SLOT(langFileAdd())); +} + +void SearchWindow::loadDictionaries() +{ + QStringList list; + eoskeygen::Dictionary tmpDict; + std::string base_path(CONFIG_DICT_FULL_PATH); + + // Clear dictionary first. + m_dict.clear(); + + // Go through all selected languages. + list = m_dict_lang.getSelectedItems(); + for(QStringList::const_iterator it = list.cbegin(); it != list.cend(); it++) { + + // Load and add them to dictionary. + tmpDict.loadFromFile(base_path + "/" + it->toStdString()); + m_dict.add(tmpDict); + } + + // Go through all selected files. + list = m_dict_file.getSelectedItems(); + for(QStringList::const_iterator it = list.cbegin(); it != list.cend(); it++) { + + // Load and add them to dictionary. + tmpDict.loadFromFile(it->toStdString()); + m_dict.add(tmpDict); + } } void SearchWindow::onResult(const struct libeosio::ec_keypair* key, const struct eoskeygen::KeySearch::result& result) @@ -173,6 +204,8 @@ void SearchWindow::search() return; } + loadDictionaries(); + m_ksearch.clear(); m_ksearch.addList(list); m_ksearch.setThreadCount(m_num_threads.value()); @@ -200,22 +233,12 @@ void SearchWindow::output(const QString& html) m_output.verticalScrollBar()->setValue(m_output.verticalScrollBar()->maximum()); } -void SearchWindow::langSelected(QStringList selected) +void SearchWindow::langFileAdd() { - std::string base_path(CONFIG_DICT_FULL_PATH); + QStringList files = QFileDialog::getOpenFileNames(this, + "Select one or more language files"); - // Clear dictionary first. - m_dict.clear(); - - // Go through all selected languages. - for(QStringList::const_iterator it = selected.cbegin(); it != selected.cend(); it++) { - - // Load and add them to dictionary. - eoskeygen::Dictionary dict; - dict.loadFromFile(base_path + "/" + it->toStdString()); - - m_dict.add(dict); - } + m_dict_file.addItems(files, true); } void SearchWindow::searchStarted() @@ -223,6 +246,7 @@ void SearchWindow::searchStarted() m_txt_search.setEnabled(false); m_txt_search.setHidden(true); m_dict_lang.setEnabled(false); + m_dict_file.setEnabled(false); m_leet_cb.setEnabled(false); m_btn_exec.setEnabled(false); m_btn_clear.setEnabled(false); @@ -235,6 +259,7 @@ void SearchWindow::searchFinished() m_txt_search.setEnabled(true); m_txt_search.setHidden(false); m_dict_lang.setEnabled(true); + m_dict_file.setEnabled(true); m_leet_cb.setEnabled(true); m_btn_exec.setEnabled(true); m_btn_clear.setEnabled(true); diff --git a/gui/SearchWindow.h b/gui/SearchWindow.h index 1aff8b1..c57f17f 100644 --- a/gui/SearchWindow.h +++ b/gui/SearchWindow.h @@ -48,6 +48,8 @@ public: private : void initSignals(); + void loadDictionaries(); + private slots: // Start a search @@ -63,8 +65,8 @@ private slots: // Called when a search is done. void searchFinished(); - // Called when dictionary language(s) are selected. - void langSelected(QStringList selected); + // Called when a new language file should be added + void langFileAdd(); signals: void addOutput(const QString& line); @@ -97,6 +99,8 @@ private: MultiSelect m_dict_lang; + MultiSelect m_dict_file; + // Buttons QPushButton m_btn_exec; QPushButton m_btn_clear; From 3bd9e9856b1b3c5875db0db90258f45107e03977 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 16:15:39 +0200 Subject: [PATCH 20/29] GUI: Adding GenerateWindow class --- gui/CMakeLists.txt | 1 + gui/GenerateWindow.cpp | 116 +++++++++++++++++++++++++++++++++++++++++ gui/GenerateWindow.hpp | 62 ++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 gui/GenerateWindow.cpp create mode 100644 gui/GenerateWindow.hpp diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 7dba68c..7e37389 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -14,6 +14,7 @@ set( PROGRAM_EXE ${COMPONENT_NAME} ) set( PROGRAM_SRC main.cpp + GenerateWindow.cpp SearchWindow.cpp MultiSelect.cpp helpers.cpp diff --git a/gui/GenerateWindow.cpp b/gui/GenerateWindow.cpp new file mode 100644 index 0000000..8ab00bb --- /dev/null +++ b/gui/GenerateWindow.cpp @@ -0,0 +1,116 @@ +/** + * MIT License + * + * Copyright (c) 2020 EOS Sw/eden + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include "GenerateWindow.hpp" + +void _initKeyWidget(QLineEdit& w) { + w.setFixedWidth(450); + w.setReadOnly(true); +} + +void _initKeyCopyButton(QPushButton& btn, const QIcon& icon) { + btn.setFixedWidth(32); + btn.setIcon(icon); +} + +GenerateWindow::GenerateWindow(QWidget *parent) : +QWidget (parent), +m_btn_gen ("Generate"), +m_btn_copy_both ("Copy keys") +{ + QIcon copy_icon = QIcon::fromTheme("edit-copy"); + QGridLayout* layout; + + _initKeyWidget(m_pub); + _initKeyWidget(m_priv); + + _initKeyCopyButton(m_btn_copy_pub, copy_icon); + _initKeyCopyButton(m_btn_copy_priv, copy_icon); + + // Layout + layout = new QGridLayout(); + layout->setAlignment(Qt::AlignCenter); + + // Public key row + + layout->addWidget(new QLabel("Public:"), 0, 0); + layout->addWidget(&m_pub, 0, 1); + layout->addWidget(&m_btn_copy_pub, 0, 2); + + // Private key row + + layout->addWidget(new QLabel("Private:"), 1, 0); + layout->addWidget(&m_priv, 1, 1); + layout->addWidget(&m_btn_copy_priv, 1, 2); + + // Bottom row + + m_btn_copy_both.setFixedWidth(80); + + layout->addWidget(&m_btn_gen, 2, 1); + layout->addWidget(&m_btn_copy_both, 2, 2); + + setLayout(layout); + + // Connections + connect(&m_btn_gen, SIGNAL(released()), this, SLOT(generate_key())); + connect(&m_btn_copy_both, SIGNAL(released()), this, SLOT(copy_both_keys())); + connect(&m_btn_copy_pub, SIGNAL(released()), this, SLOT(copy_pub_key())); + connect(&m_btn_copy_priv, SIGNAL(released()), this, SLOT(copy_priv_key())); +} + +void GenerateWindow::generate_key() +{ + std::string pubstr, privstr; + struct libeosio::ec_keypair pair; + + libeosio::ec_generate_key(&pair); + + m_pub.setText(QString::fromStdString(libeosio::wif_pub_encode(pair.pub))); + m_priv.setText(QString::fromStdString(libeosio::wif_priv_encode(pair.secret))); +} + +void GenerateWindow::copy_both_keys() +{ + QClipboard *clipboard = QGuiApplication::clipboard(); + clipboard->setText(m_pub.text() + "\n" + m_priv.text()); +} + +void GenerateWindow::copy_pub_key() +{ + QClipboard *clipboard = QGuiApplication::clipboard(); + clipboard->setText(m_pub.text()); +} + +void GenerateWindow::copy_priv_key() +{ + QClipboard *clipboard = QGuiApplication::clipboard(); + clipboard->setText(m_priv.text()); +} diff --git a/gui/GenerateWindow.hpp b/gui/GenerateWindow.hpp new file mode 100644 index 0000000..da2a110 --- /dev/null +++ b/gui/GenerateWindow.hpp @@ -0,0 +1,62 @@ +/** + * MIT License + * + * Copyright (c) 2020 EOS Sw/eden + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef GENERATE_WINDOW_H +#define GENERATE_WINDOW_H + +#include +#include +#include + +class GenerateWindow : public QWidget +{ + Q_OBJECT +public: + GenerateWindow(QWidget *parent = 0); + +public slots: + + // Genereate a new key. + void generate_key(); + + // Copy both keys to clipboard + void copy_both_keys(); + + // copy public key to clipboard + void copy_pub_key(); + + // copy private key to clipboard + void copy_priv_key(); + +protected: + + QLineEdit m_pub; + QLineEdit m_priv; + + QPushButton m_btn_gen; + QPushButton m_btn_copy_both; + QPushButton m_btn_copy_priv; + QPushButton m_btn_copy_pub; +}; + +#endif /* GENERATE_WINDOW_H */ From 8f45d3707a9436348356cd55649220747c59e263 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 16:17:24 +0200 Subject: [PATCH 21/29] GUI: Adding MainWindow class --- gui/CMakeLists.txt | 1 + gui/MainWindow.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++ gui/MainWindow.hpp | 50 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 gui/MainWindow.cpp create mode 100644 gui/MainWindow.hpp diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 7e37389..a9f1f6a 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -14,6 +14,7 @@ set( PROGRAM_EXE ${COMPONENT_NAME} ) set( PROGRAM_SRC main.cpp + MainWindow.cpp GenerateWindow.cpp SearchWindow.cpp MultiSelect.cpp diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp new file mode 100644 index 0000000..414ea0e --- /dev/null +++ b/gui/MainWindow.cpp @@ -0,0 +1,55 @@ +/** + * MIT License + * + * Copyright (c) 2020 EOS Sw/eden + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include +#include "GenerateWindow.hpp" +#include "SearchWindow.h" +#include "MainWindow.hpp" + +MainWindow::MainWindow(QWidget *parent) : +QMainWindow (parent) +{ + // Create sub windows and stacked widget. + m_stacked = new QStackedWidget(); + m_stacked->addWidget(new GenerateWindow()); + m_stacked->addWidget(new SearchWindow()); + + setCentralWidget(m_stacked); + + // Menu bar. + + menuBar()->addAction("Generate", this, SLOT(switchToGenerate())); + menuBar()->addAction("Search", this, SLOT(switchToSearch())); +} + +void MainWindow::switchToGenerate() +{ + m_stacked->setCurrentIndex(0); +} + +void MainWindow::switchToSearch() +{ + m_stacked->setCurrentIndex(1); +} diff --git a/gui/MainWindow.hpp b/gui/MainWindow.hpp new file mode 100644 index 0000000..1d5d695 --- /dev/null +++ b/gui/MainWindow.hpp @@ -0,0 +1,50 @@ +/** + * MIT License + * + * Copyright (c) 2020 EOS Sw/eden + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef MAIN_WINDOW_H +#define MAIN_WINDOW_H + +#include + +class QStackedWidget; + +class MainWindow : public QMainWindow +{ + Q_OBJECT +public: + MainWindow(QWidget *parent = 0); + +private slots : + + // Switch to generate window. + void switchToGenerate(); + + // Switch to search window. + void switchToSearch(); + +private : + + QStackedWidget* m_stacked; +}; + +#endif /* MAIN_WINDOW_H */ From f6dc9cd0b1bd74be0f72eb71b06a1384d2eb5e6a Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 16:19:14 +0200 Subject: [PATCH 22/29] gui/main.cpp: use MainWindow class. --- gui/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gui/main.cpp b/gui/main.cpp index 73fe05f..ecd14e6 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -22,15 +22,15 @@ * SOFTWARE. */ #include -#include "SearchWindow.h" +#include "MainWindow.hpp" int main(int argc, char **argv) { QApplication app(argc, argv); - SearchWindow search_win; + MainWindow window; - search_win.show(); + window.show(); return app.exec(); } From 4a3e5a5f62f5809adff12ec39d5bf6a19d6b1fcd Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 16:24:39 +0200 Subject: [PATCH 23/29] GUI: rename all header files from .h to .hpp --- gui/MainWindow.cpp | 2 +- gui/MultiSelect.cpp | 2 +- gui/{MultiSelect.h => MultiSelect.hpp} | 0 gui/SearchWindow.cpp | 4 ++-- gui/{SearchWindow.h => SearchWindow.hpp} | 2 +- gui/helpers.cpp | 2 +- gui/{helpers.h => helpers.hpp} | 0 7 files changed, 6 insertions(+), 6 deletions(-) rename gui/{MultiSelect.h => MultiSelect.hpp} (100%) rename gui/{SearchWindow.h => SearchWindow.hpp} (99%) rename gui/{helpers.h => helpers.hpp} (100%) diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index 414ea0e..e4f42a4 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -25,7 +25,7 @@ #include #include #include "GenerateWindow.hpp" -#include "SearchWindow.h" +#include "SearchWindow.hpp" #include "MainWindow.hpp" MainWindow::MainWindow(QWidget *parent) : diff --git a/gui/MultiSelect.cpp b/gui/MultiSelect.cpp index 98c6dac..bccf803 100644 --- a/gui/MultiSelect.cpp +++ b/gui/MultiSelect.cpp @@ -26,7 +26,7 @@ #include #include #include -#include "MultiSelect.h" +#include "MultiSelect.hpp" MultiSelect::MultiSelect(const QString& text, bool user_can_add, QWidget *parent) : QPushButton (text + ": none", parent) diff --git a/gui/MultiSelect.h b/gui/MultiSelect.hpp similarity index 100% rename from gui/MultiSelect.h rename to gui/MultiSelect.hpp diff --git a/gui/SearchWindow.cpp b/gui/SearchWindow.cpp index cbfa290..3b962d5 100644 --- a/gui/SearchWindow.cpp +++ b/gui/SearchWindow.cpp @@ -32,8 +32,8 @@ #include #include #include "config.h" -#include "helpers.h" -#include "SearchWindow.h" +#include "helpers.hpp" +#include "SearchWindow.hpp" SearchWindow::SearchWindow(QWidget *parent, Qt::WindowFlags flags) : QWidget (parent, flags), diff --git a/gui/SearchWindow.h b/gui/SearchWindow.hpp similarity index 99% rename from gui/SearchWindow.h rename to gui/SearchWindow.hpp index c57f17f..49bc41b 100644 --- a/gui/SearchWindow.h +++ b/gui/SearchWindow.hpp @@ -35,7 +35,7 @@ #include #include #include -#include "MultiSelect.h" +#include "MultiSelect.hpp" class SearchWindow : public QWidget, public eoskeygen::IKeySearchResult { diff --git a/gui/helpers.cpp b/gui/helpers.cpp index 3b492b4..d1574d4 100644 --- a/gui/helpers.cpp +++ b/gui/helpers.cpp @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "helpers.h" +#include "helpers.hpp" QStringList get_files(const QDir& directory) { diff --git a/gui/helpers.h b/gui/helpers.hpp similarity index 100% rename from gui/helpers.h rename to gui/helpers.hpp From 0503aa0f049639ea4c1d2acfb11d11041cc0b50d Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 19:31:49 +0200 Subject: [PATCH 24/29] CMakeLists.txt: Add PROJECT_LICENSE_FILE variable. --- CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b752918..77ad630 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ project(eosio-keygen HOMEPAGE_URL "https://github.com/eosswedenorg/eosio-keygen" ) set( PROJECT_MAINTAINER "Henrik Hautakoski ") +set( PROJECT_LICENSE_FILE ${CMAKE_CURRENT_LIST_DIR}/LICENSE ) # -------------------------------- # Options @@ -89,7 +90,7 @@ endif() # -------------------------------- # Readme and license -install(FILES README.md LICENSE +install(FILES README.md ${PROJECT_LICENSE_FILE} DESTINATION ${CMAKE_INSTALL_SHAREDIR}) # -------------------------------- @@ -97,7 +98,7 @@ install(FILES README.md LICENSE # -------------------------------- if (CPACK_GENERATOR MATCHES "^[Nn][Ss][Ii][Ss]$") - set( CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_LIST_DIR}/LICENSE ) + set( CPACK_RESOURCE_FILE_LICENSE ${PROJECT_LICENSE_FILE} ) endif() set( CPACK_DEBIAN_PACKAGE_PRIORITY "optional" ) From 2f16accbba7d40a7b8d9ed17ce6f927e420ef429 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 19:32:39 +0200 Subject: [PATCH 25/29] Adding gui/gui_about.h.in --- gui/gui_about.h.in | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 gui/gui_about.h.in diff --git a/gui/gui_about.h.in b/gui/gui_about.h.in new file mode 100644 index 0000000..1f6ab9f --- /dev/null +++ b/gui/gui_about.h.in @@ -0,0 +1,37 @@ +/** + * MIT License + * + * Copyright (c) 2020 EOS Sw/eden + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef EOSIOKEYGEN_GUI_ABOUT_H +#define EOSIOKEYGEN_GUI_ABOUT_H + +#define EOSIOKEYGEN_GUI_ABOUT_TITLE "@PROJECT_NAME@ - About" + +#define EOSIOKEYGEN_GUI_ABOUT_TEXT \ + "

@PROJECT_NAME@ - v@PROJECT_VERSION@

" \ + "

@PROJECT_DESCRIPTION@

" \ + "

@PROJECT_HOMEPAGE_URL@

" \ + "@GUI_ABOUT_LICENSE@" \ + "

Author

" \ + "

@GUI_ABOUT_AUTHOR@

" + +#endif /* EOSIOKEYGEN_CONFIG_ABOUT_H */ From 099d6b30083d61e2ce77ff0c2f2bb02f8141308c Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 19:33:02 +0200 Subject: [PATCH 26/29] gui/CMakeLists.txt: Autogenerate gui_config.h from gui_config.h.in --- gui/CMakeLists.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index a9f1f6a..3a32d08 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -4,6 +4,18 @@ set( CMAKE_AUTOMOC ON ) set( CMAKE_AUTORCC ON ) set( CMAKE_AUTOUIC ON ) +# Autogenerate about config file + +file( READ ${PROJECT_LICENSE_FILE} GUI_ABOUT_LICENSE ) + +string(REGEX REPLACE "^([^\n]+)" "

\\1

" GUI_ABOUT_LICENSE ${GUI_ABOUT_LICENSE}) +string(REGEX REPLACE "\n\n([^\n]+)" "

\\1

" GUI_ABOUT_LICENSE ${GUI_ABOUT_LICENSE}) +string(REGEX REPLACE "\n" "" GUI_ABOUT_LICENSE ${GUI_ABOUT_LICENSE}) +string(REGEX REPLACE "\<(.+)\>" "- \\1" GUI_ABOUT_AUTHOR ${PROJECT_MAINTAINER}) + +configure_file(gui_about.h.in "${CMAKE_CURRENT_BINARY_DIR}/gui_about.h" @ONLY ESCAPE_QUOTES) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + # -------------------------------- # Program # -------------------------------- From c98ed34e6e7e75dd99a6889b09cde432a33ca77f Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 15 Apr 2020 19:33:59 +0200 Subject: [PATCH 27/29] GUI: Implement about dialog in MainWindow. --- gui/MainWindow.cpp | 8 ++++++++ gui/MainWindow.hpp | 2 ++ 2 files changed, 10 insertions(+) diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index e4f42a4..ce2d579 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -21,9 +21,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ +#include #include #include #include +#include "gui_about.h" #include "GenerateWindow.hpp" #include "SearchWindow.hpp" #include "MainWindow.hpp" @@ -42,6 +44,7 @@ QMainWindow (parent) menuBar()->addAction("Generate", this, SLOT(switchToGenerate())); menuBar()->addAction("Search", this, SLOT(switchToSearch())); + menuBar()->addAction("About", this, SLOT(showAbout())); } void MainWindow::switchToGenerate() @@ -53,3 +56,8 @@ void MainWindow::switchToSearch() { m_stacked->setCurrentIndex(1); } + +void MainWindow::showAbout() +{ + QMessageBox::about(this, EOSIOKEYGEN_GUI_ABOUT_TITLE, EOSIOKEYGEN_GUI_ABOUT_TEXT); +} diff --git a/gui/MainWindow.hpp b/gui/MainWindow.hpp index 1d5d695..704fa1f 100644 --- a/gui/MainWindow.hpp +++ b/gui/MainWindow.hpp @@ -42,6 +42,8 @@ private slots : // Switch to search window. void switchToSearch(); + void showAbout(); + private : QStackedWidget* m_stacked; From d3e8cc2814007af60ae9f894bf256ba85ecebaac Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 16 Apr 2020 13:51:34 +0200 Subject: [PATCH 28/29] gui/GenerateWindow.cpp: Align labels to the right. --- gui/GenerateWindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gui/GenerateWindow.cpp b/gui/GenerateWindow.cpp index 8ab00bb..6d6c8e9 100644 --- a/gui/GenerateWindow.cpp +++ b/gui/GenerateWindow.cpp @@ -60,13 +60,13 @@ m_btn_copy_both ("Copy keys") // Public key row - layout->addWidget(new QLabel("Public:"), 0, 0); + layout->addWidget(new QLabel("Public:"), 0, 0, Qt::AlignRight); layout->addWidget(&m_pub, 0, 1); layout->addWidget(&m_btn_copy_pub, 0, 2); // Private key row - layout->addWidget(new QLabel("Private:"), 1, 0); + layout->addWidget(new QLabel("Private:"), 1, 0, Qt::AlignRight); layout->addWidget(&m_priv, 1, 1); layout->addWidget(&m_btn_copy_priv, 1, 2); From 460e8149fd074a5380bdfffb421db5bb6180f6f3 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 16 Apr 2020 13:58:49 +0200 Subject: [PATCH 29/29] gui/GenerateWindow.cpp: Fix horizontal centering of widget's using QGridLayout::setColumnStretch() --- gui/GenerateWindow.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/gui/GenerateWindow.cpp b/gui/GenerateWindow.cpp index 6d6c8e9..898281c 100644 --- a/gui/GenerateWindow.cpp +++ b/gui/GenerateWindow.cpp @@ -58,24 +58,27 @@ m_btn_copy_both ("Copy keys") layout = new QGridLayout(); layout->setAlignment(Qt::AlignCenter); - // Public key row + // Stretch first and last column to make the widgets horizontally centered. + layout->setColumnStretch(0, 1); + layout->setColumnStretch(4, 1); - layout->addWidget(new QLabel("Public:"), 0, 0, Qt::AlignRight); - layout->addWidget(&m_pub, 0, 1); - layout->addWidget(&m_btn_copy_pub, 0, 2); + // Public key row + layout->addWidget(new QLabel("Public:"), 0, 1, Qt::AlignRight); + layout->addWidget(&m_pub, 0, 2); + layout->addWidget(&m_btn_copy_pub, 0, 3); // Private key row - layout->addWidget(new QLabel("Private:"), 1, 0, Qt::AlignRight); - layout->addWidget(&m_priv, 1, 1); - layout->addWidget(&m_btn_copy_priv, 1, 2); + layout->addWidget(new QLabel("Private:"), 1, 1, Qt::AlignRight); + layout->addWidget(&m_priv, 1, 2); + layout->addWidget(&m_btn_copy_priv, 1, 3); // Bottom row m_btn_copy_both.setFixedWidth(80); - layout->addWidget(&m_btn_gen, 2, 1); - layout->addWidget(&m_btn_copy_both, 2, 2); + layout->addWidget(&m_btn_gen, 2, 2); + layout->addWidget(&m_btn_copy_both, 2, 3); setLayout(layout);