Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions src/qt/bitcoinaddressvalidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include <key_io.h>

#include <vector>

/* Base58 characters are:
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

Expand All @@ -20,10 +22,8 @@ BitcoinAddressEntryValidator::BitcoinAddressEntryValidator(QObject *parent) :
{
}

QValidator::State BitcoinAddressEntryValidator::validate(QString &input, int &pos) const
QValidator::State BitcoinAddressEntryValidator::validate(QString &input, std::vector<int>&error_locations) const
{
Q_UNUSED(pos);

// Empty address is "intermediate" input
if (input.isEmpty())
return QValidator::Intermediate;
Expand Down Expand Up @@ -73,23 +73,33 @@ QValidator::State BitcoinAddressEntryValidator::validate(QString &input, int &po
}
else
{
error_locations.push_back(idx);
state = QValidator::Invalid;
}
}

return state;
}

QValidator::State BitcoinAddressEntryValidator::validate(QString &input, int &pos) const
{
std::vector<int> error_locations;
const auto ret = validate(input, error_locations);
if (!error_locations.empty()) pos = error_locations.at(0);
return ret;
}

BitcoinAddressCheckValidator::BitcoinAddressCheckValidator(QObject *parent) :
QValidator(parent)
BitcoinAddressEntryValidator(parent)
{
}

QValidator::State BitcoinAddressCheckValidator::validate(QString &input, int &pos) const
QValidator::State BitcoinAddressCheckValidator::validate(QString &input, std::vector<int>&error_locations) const
{
Q_UNUSED(pos);
// Validate the passed Bitcoin address
if (IsValidDestinationString(input.toStdString())) {
std::string error_msg;
CTxDestination dest = DecodeDestination(input.toStdString(), error_msg, &error_locations);
if (IsValidDestination(dest)) {
return QValidator::Acceptable;
}

Expand Down
9 changes: 6 additions & 3 deletions src/qt/bitcoinaddressvalidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include <QValidator>

#include <vector>

/** Base58 entry widget validator, checks for valid characters and
* removes some whitespace.
*/
Expand All @@ -17,19 +19,20 @@ class BitcoinAddressEntryValidator : public QValidator
public:
explicit BitcoinAddressEntryValidator(QObject *parent);

State validate(QString &input, int &pos) const override;
virtual State validate(QString &input, std::vector<int>&error_locations) const;
virtual State validate(QString &input, int &pos) const override;
};

/** Bitcoin address widget validator, checks for a valid bitcoin address.
*/
class BitcoinAddressCheckValidator : public QValidator
class BitcoinAddressCheckValidator : public BitcoinAddressEntryValidator
{
Q_OBJECT

public:
explicit BitcoinAddressCheckValidator(QObject *parent);

State validate(QString &input, int &pos) const override;
State validate(QString &input, std::vector<int>&error_locations) const override;
};

#endif // BITCOIN_QT_BITCOINADDRESSVALIDATOR_H
2 changes: 2 additions & 0 deletions src/qt/guiconstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ static const bool DEFAULT_SPLASHSCREEN = true;

/* Invalid field background style */
#define STYLE_INVALID "background:#FF8080"
/* "Warning" field background style */
#define STYLE_INCORRECT "background:#FFFF80"

/* Transaction list -- unconfirmed transaction */
#define COLOR_UNCONFIRMED QColor(128, 128, 128)
Expand Down
92 changes: 82 additions & 10 deletions src/qt/qvalidatedlineedit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
#include <qt/bitcoinaddressvalidator.h>
#include <qt/guiconstants.h>

#include <QColor>
#include <QCoreApplication>
#include <QFont>
#include <QInputMethodEvent>
#include <QList>
#include <QTextCharFormat>

QValidatedLineEdit::QValidatedLineEdit(QWidget *parent) :
QLineEdit(parent),
valid(true),
Expand All @@ -15,27 +22,56 @@ QValidatedLineEdit::QValidatedLineEdit(QWidget *parent) :
connect(this, &QValidatedLineEdit::textChanged, this, &QValidatedLineEdit::markValid);
}

QValidatedLineEdit::~QValidatedLineEdit()
{
delete m_warning_validator;
}

void QValidatedLineEdit::setText(const QString& text)
{
QLineEdit::setText(text);
checkValidity();
}

void QValidatedLineEdit::setValid(bool _valid)
void QValidatedLineEdit::setValid(bool _valid, bool with_warning, const std::vector<int>&error_locations)
{
if(_valid == this->valid)
if(_valid && this->valid)
{
return;
if (with_warning == m_has_warning) {
return;
}
}

QList<QInputMethodEvent::Attribute> attributes;

if(_valid)
{
setStyleSheet("");
m_has_warning = with_warning;
if (with_warning) {
setStyleSheet("QValidatedLineEdit { " STYLE_INCORRECT "}");
} else {
setStyleSheet("");
}
}
else
{
setStyleSheet("QValidatedLineEdit { " STYLE_INVALID "}");
if (!error_locations.empty()) {
QTextCharFormat format;
format.setFontUnderline(true);
format.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline);
format.setUnderlineColor(Qt::yellow);
format.setForeground(Qt::yellow);
format.setFontWeight(QFont::Bold);
for (auto error_pos : error_locations) {
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, error_pos - cursorPosition(), /*length=*/ 1, format));
}
}
}

QInputMethodEvent event(QString(), attributes);
QCoreApplication::sendEvent(this, &event);

this->valid = _valid;
}

Expand Down Expand Up @@ -84,23 +120,34 @@ void QValidatedLineEdit::setEnabled(bool enabled)

void QValidatedLineEdit::checkValidity()
{
const bool has_warning = checkWarning();
if (text().isEmpty())
{
setValid(true);
}
else if (hasAcceptableInput())
{
setValid(true);
setValid(/* valid= */ true, has_warning);

// Check contents on focus out
if (checkValidator)
{
QString address = text();
int pos = 0;
if (checkValidator->validate(address, pos) == QValidator::Acceptable)
setValid(true);
else
setValid(false);
QValidator::State validation_result;
std::vector<int> error_locations;
const BitcoinAddressEntryValidator * const address_validator = dynamic_cast<const BitcoinAddressEntryValidator*>(checkValidator);
if (address_validator) {
validation_result = address_validator->validate(address, error_locations);
} else {
int pos = 0;
validation_result = checkValidator->validate(address, pos);
error_locations.push_back(pos);
}
if (validation_result == QValidator::Acceptable) {
setValid(/* valid= */ true, has_warning);
} else {
setValid(/* valid= */ false, /* with_warning= */ false, error_locations);
}
}
}
else
Expand Down Expand Up @@ -128,3 +175,28 @@ bool QValidatedLineEdit::isValid()

return valid;
}

void QValidatedLineEdit::setWarningValidator(const QValidator *v)
{
delete m_warning_validator;
m_warning_validator = v;
checkValidity();
}

bool QValidatedLineEdit::checkWarning() const
{
if (m_warning_validator && !text().isEmpty()) {
QString address = text();
int pos = 0;
if (m_warning_validator->validate(address, pos) != QValidator::Acceptable) {
return true;
}
}

return false;
}

bool QValidatedLineEdit::hasWarning() const
{
return m_has_warning;
}
8 changes: 7 additions & 1 deletion src/qt/qvalidatedlineedit.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ class QValidatedLineEdit : public QLineEdit

public:
explicit QValidatedLineEdit(QWidget *parent);
~QValidatedLineEdit();
void clear();
void setCheckValidator(const QValidator *v);
bool isValid();
void setWarningValidator(const QValidator *);
bool hasWarning() const;

protected:
void focusInEvent(QFocusEvent *evt) override;
Expand All @@ -27,10 +30,12 @@ class QValidatedLineEdit : public QLineEdit
private:
bool valid;
const QValidator *checkValidator;
bool m_has_warning{false};
const QValidator *m_warning_validator{nullptr};

public Q_SLOTS:
void setText(const QString&);
void setValid(bool valid);
void setValid(bool valid, bool with_warning=false, const std::vector<int>&error_locations=std::vector<int>());
void setEnabled(bool enabled);

Q_SIGNALS:
Expand All @@ -39,6 +44,7 @@ public Q_SLOTS:
private Q_SLOTS:
void markValid();
void checkValidity();
bool checkWarning() const;
};

#endif // BITCOIN_QT_QVALIDATEDLINEEDIT_H