diff --git a/src/gridcoin/voting/builders.cpp b/src/gridcoin/voting/builders.cpp index 676316d3f1..529a883028 100644 --- a/src/gridcoin/voting/builders.cpp +++ b/src/gridcoin/voting/builders.cpp @@ -1158,19 +1158,19 @@ PollBuilder PollBuilder::AddAdditionalField(Poll::AdditionalField field) ToString(POLL_MAX_ADDITIONAL_FIELDS_SIZE))); } - if (field.m_name.size() > Poll::AdditionalField::MAX_N_OR_V_SIZE) { + if (field.m_name.size() > Poll::AdditionalField::MAX_NAME_SIZE) { throw VotingError(strprintf( _("Poll additional field name \"%s\" exceeds %s characters."), field.m_name, - ToString(Poll::AdditionalField::MAX_N_OR_V_SIZE))); + ToString(Poll::AdditionalField::MAX_NAME_SIZE))); } - if (field.m_value.size() > Poll::AdditionalField::MAX_N_OR_V_SIZE) { + if (field.m_value.size() > Poll::AdditionalField::MAX_VALUE_SIZE) { throw VotingError(strprintf( _("Poll additional field value \"%s\" for field name \"%s\" exceeds %s characters."), field.m_value, field.m_name, - ToString(Poll::AdditionalField::MAX_N_OR_V_SIZE))); + ToString(Poll::AdditionalField::MAX_VALUE_SIZE))); } if (m_poll->m_additional_fields.FieldExists(field.m_name)) { diff --git a/src/gridcoin/voting/poll.h b/src/gridcoin/voting/poll.h index d05cea18a6..1decaae541 100644 --- a/src/gridcoin/voting/poll.h +++ b/src/gridcoin/voting/poll.h @@ -203,9 +203,15 @@ class Poll { public: //! - //! \brief The maximum length for a poll additional field name or value. + //! \brief The maximum length for a poll additional field name. //! - static constexpr size_t MAX_N_OR_V_SIZE = 100; + static constexpr size_t MAX_NAME_SIZE = 100; + + //! + //! \brief The maximum length for a poll additional field value. This is currently set to align with the + //! maximum Project URL length. + //! + static constexpr size_t MAX_VALUE_SIZE = 500; std::string m_name; std::string m_value; @@ -244,8 +250,8 @@ class Poll template inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(LIMITED_STRING(m_name, MAX_N_OR_V_SIZE)); - READWRITE(LIMITED_STRING(m_value, MAX_N_OR_V_SIZE)); + READWRITE(LIMITED_STRING(m_name, MAX_NAME_SIZE)); + READWRITE(LIMITED_STRING(m_value, MAX_VALUE_SIZE)); READWRITE(m_required); } }; // AdditionalField diff --git a/src/qt/voting/pollwizarddetailspage.cpp b/src/qt/voting/pollwizarddetailspage.cpp index c282ffecaa..1e75926e76 100644 --- a/src/qt/voting/pollwizarddetailspage.cpp +++ b/src/qt/voting/pollwizarddetailspage.cpp @@ -3,6 +3,7 @@ // file COPYING or https://opensource.org/licenses/mit-license.php. #include "main.h" +#include "qitemdelegate.h" #include "qt/bitcoinunits.h" #include "qt/decoration.h" #include "qt/forms/voting/ui_pollwizarddetailspage.h" @@ -54,6 +55,37 @@ class ChoicesListDelegate : public QStyledItemDelegate } }; // ChoicesListDelegate +//! +//! \brief Applies custom behavior to additional field items in the poll editor. +//! +class AdditionalFieldDelegate : public QItemDelegate +{ + Q_OBJECT + +public: + AdditionalFieldDelegate(QObject* parent = nullptr) : QItemDelegate(parent) + { + } + + QWidget* createEditor( + QWidget* parent, + const QStyleOptionViewItem& option, + const QModelIndex& index) const override + { + QWidget* editor = QItemDelegate::createEditor(parent, option, index); + + if (QLineEdit* line_edit = qobject_cast(editor)) { + if (index.column() == AdditionalFieldsTableModel::Name) { + line_edit->setMaxLength(VotingModel::maxPollAdditionalFieldNameLength()); + } else if (index.column() == AdditionalFieldsTableModel::Value) { + line_edit->setMaxLength(VotingModel::maxPollAdditionalFieldValueLength()); + } + } + + return editor; + } +}; // AdditionalFieldDelegate + //! //! \brief Provides for QWizardPage::registerField() without a real widget. //! @@ -167,6 +199,7 @@ PollWizardDetailsPage::PollWizardDetailsPage(QWidget* parent) ui->responseTypeList->addItem(tr("Multiple Choice")); ChoicesListDelegate* choices_delegate = new ChoicesListDelegate(this); + AdditionalFieldDelegate* additonal_field_delegate = new AdditionalFieldDelegate(this); ui->choicesList->setModel(m_choices_model.get()); ui->choicesList->setItemDelegate(choices_delegate); @@ -174,6 +207,12 @@ PollWizardDetailsPage::PollWizardDetailsPage(QWidget* parent) ui->editChoiceButton->hide(); ui->removeChoiceButton->hide(); + ui->additionalFieldsTableView->setItemDelegate(additonal_field_delegate); + + ui->titleField->setMaxLength(m_voting_model->maxPollTitleLength()); + ui->questionField->setMaxLength(m_voting_model->maxPollQuestionLength()); + ui->urlField->setMaxLength(m_voting_model->maxPollUrlLength()); + connect( ui->responseTypeList, QOverload::of(&QComboBox::currentIndexChanged), this, [=](int index) { diff --git a/src/qt/voting/pollwizardprojectpage.cpp b/src/qt/voting/pollwizardprojectpage.cpp index f825155be5..1b509d3218 100644 --- a/src/qt/voting/pollwizardprojectpage.cpp +++ b/src/qt/voting/pollwizardprojectpage.cpp @@ -31,6 +31,9 @@ PollWizardProjectPage::PollWizardProjectPage(QWidget* parent) ui->removeWidget->hide(); ui->addRemoveStateLineEdit->hide(); + ui->projectNameField->setMaxLength(m_voting_model->maxPollProjectNameLength()); + ui->projectUrlField->setMaxLength(m_voting_model->maxPollProjectUrlLength()); + QStringListModel* project_names_model = new QStringListModel(this); QStringListModel* project_urls_model = new QStringListModel(this); diff --git a/src/qt/voting/votingmodel.cpp b/src/qt/voting/votingmodel.cpp index 2efed942a7..dc55983262 100644 --- a/src/qt/voting/votingmodel.cpp +++ b/src/qt/voting/votingmodel.cpp @@ -217,6 +217,42 @@ int VotingModel::maxPollChoiceLabelLength() return Poll::Choice::MAX_LABEL_SIZE; } +int VotingModel::maxPollAdditionalFieldNameLength() +{ + // Not strictly accurate: the protocol limits the max length in bytes, but + // Qt limits field lengths in UTF-8 characters which may be represented by + // more than one byte. + // + return Poll::AdditionalField::MAX_NAME_SIZE; +} + +int VotingModel::maxPollAdditionalFieldValueLength() +{ + // Not strictly accurate: the protocol limits the max length in bytes, but + // Qt limits field lengths in UTF-8 characters which may be represented by + // more than one byte. + // + return Poll::AdditionalField::MAX_VALUE_SIZE; +} + +int VotingModel::maxPollProjectNameLength() +{ + // Not strictly accurate: the protocol limits the max length in bytes, but + // Qt limits field lengths in UTF-8 characters which may be represented by + // more than one byte. + // + return Project::MAX_NAME_SIZE; +} + +int VotingModel::maxPollProjectUrlLength() +{ + // Not strictly accurate: the protocol limits the max length in bytes, but + // Qt limits field lengths in UTF-8 characters which may be represented by + // more than one byte. + // + return Project::MAX_URL_SIZE; +} + OptionsModel& VotingModel::getOptionsModel() { return m_options_model; diff --git a/src/qt/voting/votingmodel.h b/src/qt/voting/votingmodel.h index f207948ecc..435eef240a 100644 --- a/src/qt/voting/votingmodel.h +++ b/src/qt/voting/votingmodel.h @@ -130,6 +130,10 @@ class VotingModel : public QObject static int maxPollUrlLength(); static int maxPollQuestionLength(); static int maxPollChoiceLabelLength(); + static int maxPollAdditionalFieldNameLength(); + static int maxPollAdditionalFieldValueLength(); + static int maxPollProjectNameLength(); + static int maxPollProjectUrlLength(); OptionsModel& getOptionsModel(); QString getCurrentPollTitle() const;