From 4e1a204bc07b9df18a8c00faf5f00160e78592c9 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Fri, 5 Dec 2014 18:18:43 -0600 Subject: [PATCH] Fix threading issue with startup pw popup The GUI is slow to update after accepting a password, but a cursory ten minute investigation didn't yield why I inserted a processEvents() call before ready = true; at the end of Core::start, but that didn't help. Define the total time between the password dialog disappearing and the UI updating with your own status is T: Then my debug statement indicated that this processEvents call happened around 1/3T, raising two questions: 1) What the hell is happening between 0 and 1/3 T? Decryption doesn't take that long... Note that bad passwords are immediately rejected with a new dialog, so I highly doubt it's the decryption cpu time 2) The remaining 2/3rds: processEvents has been called after the avatar and username signals, yet they don't update in the UI till time T when everything updates after bootstrapping... Oh well, like I said, only a cursory investigation --- src/coreencryption.cpp | 45 ++++++++++-------------------------------- src/widget/widget.cpp | 28 ++++++++++++++++++++++++++ src/widget/widget.h | 2 ++ 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/coreencryption.cpp b/src/coreencryption.cpp index b9de04ca6..07d0a80c5 100644 --- a/src/coreencryption.cpp +++ b/src/coreencryption.cpp @@ -133,7 +133,7 @@ bool Core::loadEncryptedSave(QByteArray& data) Widget::getInstance()->showWarningMsgBox(tr("Encryption error"), tr("The .tox file is encrypted, but encryption was not checked, continuing regardless.")); int error = -1; - QString a(tr("Please enter the password for this profile:", "used in load() when no pw is already set")); + QString a(tr("Please enter the password for this profile.", "used in load() when no pw is already set")); QString b(tr("The previous password is incorrect; please try again:", "used on retries in load()")); QString dialogtxt; @@ -152,30 +152,18 @@ bool Core::loadEncryptedSave(QByteArray& data) uint8_t salt[tox_pass_salt_length()]; tox_get_salt(reinterpret_cast(data.data()), salt); - QInputDialog dialog; - dialog.moveToThread(qApp->thread()); - dialog.setOkButtonText(tr("Set password")); - dialog.setCancelButtonText(tr("Change profile")); - dialog.setWindowTitle(tr("Enter your password")); - dialog.setInputMode(QInputDialog::TextInput); - dialog.setTextEchoMode(QLineEdit::Password); + do { - dialog.setTextValue(QString()); - dialog.setLabelText(dialogtxt); + QString pw = Widget::getInstance()->passwordDialog(tr("Change profile"), dialogtxt); - int val = dialog.exec(); - - if (val == QDialog::Accepted) - { - QString pw = dialog.textValue(); - setPassword(pw, ptMain, salt); - } - else + if (pw.isEmpty()) { clearPassword(ptMain); return false; } + else + setPassword(pw, ptMain, salt); error = tox_encrypted_key_load(tox, reinterpret_cast(data.data()), data.size(), pwsaltedkeys[ptMain]); dialogtxt = a + " " + b; @@ -210,33 +198,20 @@ void Core::checkEncryptedHistory() else dialogtxt = a; - QInputDialog dialog; - dialog.moveToThread(qApp->thread()); - dialog.setOkButtonText(tr("Set password")); - dialog.setCancelButtonText(tr("Disable history")); - dialog.setWindowTitle(tr("Enter your password")); - dialog.setInputMode(QInputDialog::TextInput); - dialog.setTextEchoMode(QLineEdit::Password); bool error = true; do { - dialog.setLabelText(dialogtxt); - dialog.setTextValue(QString()); + QString pw = Widget::getInstance()->passwordDialog(tr("Disable history"), dialogtxt); - int val = dialog.exec(); - - if (val == QDialog::Accepted) - { - QString pw = dialog.textValue(); - setPassword(pw, ptHistory, reinterpret_cast(salt.data())); - } - else + if (pw.isEmpty()) { clearPassword(ptHistory); Settings::getInstance().setEncryptLogs(false); Settings::getInstance().setEnableLogging(false); return; } + else + setPassword(pw, ptHistory, reinterpret_cast(salt.data())); error = !HistoryKeeper::checkPassword(); dialogtxt = a + " " + b; diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index b89ef096f..77f20f6a2 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -1236,6 +1236,34 @@ bool Widget::askMsgboxQuestion(const QString& title, const QString& msg) } } +QString Widget::passwordDialog(const QString& cancel, const QString& body) +{ + // We can only display widgets from the GUI thread + if (QThread::currentThread() != qApp->thread()) + { + QString ret; + QMetaObject::invokeMethod(this, "passwordDialog", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QString, ret), + Q_ARG(const QString&, cancel), Q_ARG(const QString&, body)); + return ret; + } + else + { + QString ret; + QInputDialog dialog; + dialog.setWindowTitle(tr("Enter your password")); + dialog.setOkButtonText(tr("Set password")); + dialog.setCancelButtonText(cancel); + dialog.setInputMode(QInputDialog::TextInput); + dialog.setTextEchoMode(QLineEdit::Password); + dialog.setLabelText(body); + int val = dialog.exec(); + if (val == QDialog::Accepted) + ret = dialog.textValue(); + return ret; + } +} + void Widget::clearAllReceipts() { QList frnds = FriendList::getAllFriends(); diff --git a/src/widget/widget.h b/src/widget/widget.h index 366c5eb60..272ff2f79 100644 --- a/src/widget/widget.h +++ b/src/widget/widget.h @@ -68,6 +68,8 @@ public: QMessageBox::StandardButtons buttonss = QMessageBox::Ok); Q_INVOKABLE void setEnabledThreadsafe(bool enabled); Q_INVOKABLE bool askMsgboxQuestion(const QString& title, const QString& msg); + Q_INVOKABLE QString passwordDialog(const QString& cancel, const QString& body); + // hooray for threading hacks ~Widget(); virtual void closeEvent(QCloseEvent *event);