gui: Refactor OpenWalletActivity #16261

pull promag wants to merge 1 commits into bitcoin:master from promag:2019-06-refactor-open-wallet changing 3 files +101 −59
  1. promag commented at 3:01 PM on June 21, 2019: member

    This PR consists in 3 refactors:

    1. Split from OpenWalletActivity a base class WalletControllerActivity to simplify new activities, like the upcoming CreateWalletActivity;
    2. Move from BitcoinGUI the details of the wallet opening;
    3. Change threading model - WalletControllerActivity instances belong to the GUI thread and some code (the blocking code) is now executed in the worker thread asynchronously, which allows for a responsive GUI.
  2. DrahtBot commented at 3:05 PM on June 21, 2019: member

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    No conflicts as of last run.

  3. in src/qt/walletcontroller.cpp:205 in a962b68ebf outdated
     211 | +{
     212 | +    QString name = path.empty() ? QString("["+tr("default wallet")+"]") : QString::fromStdString(path);
     213 | +
     214 | +    showProgressDialog(tr("Opening Wallet <b>%1</b>...").arg(name.toHtmlEscaped()));
     215 | +
     216 | +    QTimer::singleShot(500, worker(), [this, path] {
    


    promag commented at 3:07 PM on June 21, 2019:

    We can ditch these 500ms but I think it is ok.

    If we decide to have 0ms then we can only replace QTimer::singleShot(0, with QMetaObject::invokeMethod after bumping Qt to 5.10 - see https://doc.qt.io/qt-5/qmetaobject.html#invokeMethod-5.


    hebasto commented at 9:23 AM on July 7, 2019:

    What is the point to pause? If there is no clear and obvious rationale, QTimer::singleShot() should be avoided, IMO.


    promag commented at 2:39 PM on July 13, 2019:

    No point, but not harm, can make it 0. The point is to call the lambda in the worker() thread.


    hebasto commented at 7:58 PM on July 13, 2019:

    The point is to call the lambda in the worker() thread.

    Did you consider some other approaches?


    promag commented at 8:10 PM on July 13, 2019:

    Yes, those require more QObject subclass, signals and slots. IMO this approach is more clear.


    hebasto commented at 8:22 PM on July 13, 2019:

    May I suggest to remove (make 0 ms) or comment 500 ms timeout?


    promag commented at 9:38 PM on July 13, 2019:

    Sure, I can make 0ms and leave a comment.


    jonasschnelli commented at 3:46 PM on July 16, 2019:

    Is there a benefit of using 500ms? Seems racy...


    promag commented at 1:18 PM on August 29, 2019:

    Not really, I'll make 0 then.

  4. DrahtBot added the label GUI on Jun 21, 2019
  5. fanquake added this to the "Blockers" column in a project

  6. fanquake requested review from hebasto on Jul 5, 2019
  7. fanquake requested review from jonasschnelli on Jul 5, 2019
  8. fanquake commented at 6:56 AM on July 5, 2019: member

    @promag Can you rebase this on master; as it contains some bug fixes that would be nice to have when testing this PR, such as #16231.

  9. fanquake added the label Waiting for author on Jul 5, 2019
  10. promag force-pushed on Jul 5, 2019
  11. promag commented at 7:33 AM on July 5, 2019: member

    @fanquake done.

  12. fanquake removed the label Waiting for author on Jul 5, 2019
  13. hebasto commented at 3:02 PM on July 5, 2019: member

    Concept ACK.

  14. fanquake commented at 2:24 AM on July 6, 2019: member

    I had a quick test, and this PR on top of master (4f378ac30cf66178564620b4a8ca9cad7f031cc3) doesn't fix #15453.

  15. in src/qt/walletcontroller.cpp:210 in 5604d30a30 outdated
     216 | +    QTimer::singleShot(500, worker(), [this, path] {
     217 | +        std::unique_ptr<interfaces::Wallet> wallet = node().loadWallet(path, m_error_message, m_warning_message);
     218 | +
     219 | +        if (wallet) m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(wallet));
     220 | +
     221 | +        QTimer::singleShot(500, this, &OpenWalletActivity::finish);
    


    hebasto commented at 9:23 AM on July 7, 2019:

    Same here.


    hebasto commented at 8:08 PM on July 13, 2019:

    OpenWalletActivity::finish() could be inlined here. OpenWalletActivity::open() will remain small enough and readability will be improved, no?


    promag commented at 9:43 PM on July 13, 2019:

    OpenWalletActivity::finish() could be inlined here.

    At the time I had 2 reasons to not do that:

    1. finish could be called from multiple places, also initially it was a virtual method in the super class;
    2. wanted to avoid nesting lambdas.

    hebasto commented at 5:08 AM on July 14, 2019:

    Could it be just

            finish();
    

    ?


    promag commented at 9:11 AM on July 14, 2019:

    No, this finish() is not thread safe - it would be called from the worker thread.


    hebasto commented at 9:39 AM on July 14, 2019:

    ... this finish() is not thread safe - it would be called from the worker thread.

    Right. But thread safety is not required for finish(), IMO.


    promag commented at 1:36 PM on August 29, 2019:

    But it is, see OpenWalletActivity::finish(), it must be called on the GUI thread.


    hebasto commented at 10:24 AM on September 2, 2019:

    Correct.

  16. in src/qt/walletcontroller.cpp:192 in 5604d30a30 outdated
     212 | +    QString name = path.empty() ? QString("["+tr("default wallet")+"]") : QString::fromStdString(path);
     213 | +
     214 | +    showProgressDialog(tr("Opening Wallet <b>%1</b>...").arg(name.toHtmlEscaped()));
     215 | +
     216 | +    QTimer::singleShot(500, worker(), [this, path] {
     217 | +        std::unique_ptr<interfaces::Wallet> wallet = node().loadWallet(path, m_error_message, m_warning_message);
    


    hebasto commented at 10:13 AM on July 7, 2019:
    auto wallet = node().loadWallet(path, m_error_message, m_warning_message);
    

    promag commented at 2:37 PM on July 13, 2019:

    I prefer to have to have the type.

  17. in src/qt/walletcontroller.cpp:46 in 5604d30a30 outdated
      44 |  {
      45 | -    m_activity_thread.quit();
      46 | -    m_activity_thread.wait();
      47 | +    m_activity_thread->quit();
      48 | +    m_activity_thread->wait();
      49 | +    delete m_activity_worker;
    


    hebasto commented at 1:08 PM on July 7, 2019:

    Could naked delete be avoided in the new code? There are some techniques to achieve this. E.g., m_activity_worker could have a parent QObject, like m_activity_thread has.


    promag commented at 9:34 PM on July 13, 2019:

    No object could be m_activity_worker parent because it's the only object on its thread. Could connect WalletController::destroyed to its deleteLater or could use some smart pointer but honestly I think this is better.


    hebasto commented at 5:25 AM on July 14, 2019:

    You could use QThread::finished signal. See: https://github.com/bitcoin/bitcoin/pull/16261/files#r303227866

  18. in src/qt/walletcontroller.cpp:151 in 5604d30a30 outdated
     157 | -    : m_wallet_controller(wallet_controller)
     158 | -    , m_name(name)
     159 | -{}
     160 | +WalletControllerActivity::~WalletControllerActivity()
     161 | +{
     162 | +    delete m_progress_dialog;
    


    hebasto commented at 1:09 PM on July 7, 2019:

    Could naked delete be avoided in the new code?


    promag commented at 9:38 PM on July 13, 2019:

    Ownership is given to m_parent_widget so that it shows up properly. If the activity finishes first then we delete it - note lines L174-L176 below.


    hebasto commented at 5:57 AM on July 14, 2019:
  19. DrahtBot added the label Needs rebase on Jul 8, 2019
  20. promag force-pushed on Jul 8, 2019
  21. DrahtBot removed the label Needs rebase on Jul 9, 2019
  22. in src/qt/walletcontroller.cpp:36 in b71017a295 outdated
      32 | @@ -29,15 +33,17 @@ WalletController::WalletController(interfaces::Node& node, const PlatformStyle*
      33 |          getOrCreateWallet(std::move(wallet));
      34 |      }
      35 |  
      36 | -    m_activity_thread.start();
      37 | +    m_activity_worker->moveToThread(m_activity_thread);
    


    hebasto commented at 5:20 AM on July 14, 2019:

    Could add

        connect(m_activity_thread, &QThread::finished, m_activity_worker, &QObject::deleteLater);
    

    and remove following

       delete m_activity_worker;
    

    ?


    promag commented at 4:57 PM on July 16, 2019:

    Why? The thread is explicitly stopped (actually the event loop is stopped and the thread finishes) in ~WalletController() so what better place to also delete the worker? I think explicit teardown is preferable.


    hebasto commented at 7:11 AM on July 18, 2019:

    Why?

    Your approach binds the life of m_activity_worker to the WalletController instance lifetime. IMO, as m_activity_worker lives in m_activity_thread, connecting to the QThread::finished signal seems more appropriate.

  23. hebasto changes_requested
  24. in src/qt/walletcontroller.cpp:157 in b71017a295 outdated
     176 | -    if (wallet) {
     177 | -        Q_EMIT opened(m_wallet_controller->getOrCreateWallet(std::move(wallet)));
     178 | -    } else {
     179 | -        Q_EMIT message(QMessageBox::Critical, QString::fromStdString(error));
     180 | +    m_progress_dialog = new QProgressDialog(m_parent_widget);
     181 | +
    


    hebasto commented at 5:53 AM on July 14, 2019:

    Could add

        connect(this, &OpenWalletActivity::finished, m_progress_dialog, &QObject::deleteLater);
    

    and remove above:

       delete m_progress_dialog;
    

    ?

  25. in src/qt/walletcontroller.cpp:175 in b71017a295 outdated
     184 | +    m_progress_dialog->setCancelButton(nullptr);
     185 | +    m_progress_dialog->setWindowModality(Qt::ApplicationModal);
     186 | +    GUIUtil::PolishProgressDialog(m_progress_dialog);
     187 | +
     188 | +    connect(m_progress_dialog, &QObject::destroyed, [this] {
     189 | +        m_progress_dialog = nullptr;
    


    hebasto commented at 5:55 AM on July 14, 2019:

    Which cases require this line?


    promag commented at 5:26 PM on July 16, 2019:

    Actually I think it's not required now. Initially I had setAttribute(Qt::WA_DeleteOnClose). Removed.

  26. hebasto changes_requested
  27. jonasschnelli commented at 9:17 AM on July 17, 2019: contributor

    Looks like the wallet encryption test fails...

  28. promag commented at 10:20 AM on July 17, 2019: member

    @jonasschnelli it was failing because of build timeouts.

  29. promag force-pushed on Aug 29, 2019
  30. hebasto approved
  31. hebasto commented at 10:46 AM on September 2, 2019: member

    ACK 7afbd0cb69dae4af4b6a78c442c25832cd7fad42, I have tested the code: no change in behavior is observed (compared to the master 6519be605480fec95dcd814771038efcb1ad2abe).

  32. promag force-pushed on Sep 5, 2019
  33. gui: Refactor OpenWalletActivity bc6d8a3662
  34. promag force-pushed on Sep 5, 2019
  35. promag commented at 12:43 AM on September 6, 2019: member

    @hebasto rebased and removed the unused declaration std::vector<std::string> getWalletsAvailableToOpen() const; - left over from other work.

  36. fanquake merged this on Sep 7, 2019
  37. fanquake closed this on Sep 7, 2019

  38. fanquake removed this from the "Blockers" column in a project

  39. promag deleted the branch on Sep 7, 2019
  40. DrahtBot locked this on Dec 16, 2021


jonasschnelli

Labels

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-05-03 03:14 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me