diff --git a/qt/i2pd_qt/ClientTunnelPane.cpp b/qt/i2pd_qt/ClientTunnelPane.cpp index 7f00cb31..4d4bb5ce 100644 --- a/qt/i2pd_qt/ClientTunnelPane.cpp +++ b/qt/i2pd_qt/ClientTunnelPane.cpp @@ -3,8 +3,8 @@ #include "SignatureTypeComboboxFactory.h" #include "QVBoxLayout" -ClientTunnelPane::ClientTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ClientTunnelConfig* tunconf): - TunnelPane(tunnelsPageUpdateListener, tunconf) {} +ClientTunnelPane::ClientTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ClientTunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_): + TunnelPane(tunnelsPageUpdateListener, tunconf, wrongInputPane_, wrongInputLabel_) {} void ClientTunnelPane::setGroupBoxTitle(const QString & title) { clientTunnelNameGroupBox->setTitle(title); diff --git a/qt/i2pd_qt/ClientTunnelPane.h b/qt/i2pd_qt/ClientTunnelPane.h index 511209e5..0b80103e 100644 --- a/qt/i2pd_qt/ClientTunnelPane.h +++ b/qt/i2pd_qt/ClientTunnelPane.h @@ -14,7 +14,7 @@ class TunnelPane; class ClientTunnelPane : public TunnelPane { Q_OBJECT public: - ClientTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ClientTunnelConfig* tunconf); + ClientTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ClientTunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_); virtual ~ClientTunnelPane(){} virtual ServerTunnelPane* asServerTunnelPane(); virtual ClientTunnelPane* asClientTunnelPane(); @@ -68,6 +68,7 @@ private: } protected: virtual bool applyDataFromUIToTunnelConfig() { + QString cannotSaveSettings = QApplication::tr("Cannot save settings."); bool ok=TunnelPane::applyDataFromUIToTunnelConfig(); if(!ok)return false; ClientTunnelConfig* ctc=tunnelConfig->asClientTunnelConfig(); @@ -78,7 +79,11 @@ protected: auto portStr=portLineEdit->text(); int portInt=portStr.toInt(&ok); - if(!ok)return false; + + if(!ok){ + highlightWrongInput(QApplication::tr("Bad port, must be int.")+" "+cannotSaveSettings,portLineEdit); + return false; + } ctc->setport(portInt); ctc->setkeys(keysLineEdit->text().toStdString()); @@ -87,7 +92,10 @@ protected: auto dportStr=destinationPortLineEdit->text(); int dportInt=dportStr.toInt(&ok); - if(!ok)return false; + if(!ok){ + highlightWrongInput(QApplication::tr("Bad destinationPort, must be int.")+" "+cannotSaveSettings,destinationPortLineEdit); + return false; + } ctc->setdestinationPort(dportInt); ctc->setsigType(readSigTypeComboboxUI(sigTypeComboBox)); diff --git a/qt/i2pd_qt/ServerTunnelPane.cpp b/qt/i2pd_qt/ServerTunnelPane.cpp index 827f6a37..a2ba9558 100644 --- a/qt/i2pd_qt/ServerTunnelPane.cpp +++ b/qt/i2pd_qt/ServerTunnelPane.cpp @@ -2,8 +2,8 @@ #include "ClientContext.h" #include "SignatureTypeComboboxFactory.h" -ServerTunnelPane::ServerTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ServerTunnelConfig* tunconf): - TunnelPane(tunnelsPageUpdateListener, tunconf) {} +ServerTunnelPane::ServerTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ServerTunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_): + TunnelPane(tunnelsPageUpdateListener, tunconf, wrongInputPane_, wrongInputLabel_) {} void ServerTunnelPane::setGroupBoxTitle(const QString & title) { serverTunnelNameGroupBox->setTitle(title); diff --git a/qt/i2pd_qt/ServerTunnelPane.h b/qt/i2pd_qt/ServerTunnelPane.h index 4069e339..b7b5ef1c 100644 --- a/qt/i2pd_qt/ServerTunnelPane.h +++ b/qt/i2pd_qt/ServerTunnelPane.h @@ -31,7 +31,7 @@ class ServerTunnelPane : public TunnelPane { Q_OBJECT public: - ServerTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ServerTunnelConfig* tunconf); + ServerTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ServerTunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_); virtual ~ServerTunnelPane(){} virtual ServerTunnelPane* asServerTunnelPane(); @@ -119,6 +119,7 @@ private: protected: virtual bool applyDataFromUIToTunnelConfig() { + QString cannotSaveSettings = QApplication::tr("Cannot save settings."); bool ok=TunnelPane::applyDataFromUIToTunnelConfig(); if(!ok)return false; ServerTunnelConfig* stc=tunnelConfig->asServerTunnelConfig(); @@ -127,14 +128,20 @@ protected: auto portStr=portLineEdit->text(); int portInt=portStr.toInt(&ok); - if(!ok)return false; + if(!ok){ + highlightWrongInput(QApplication::tr("Bad port, must be int.")+" "+cannotSaveSettings,portLineEdit); + return false; + } stc->setport(portInt); stc->setkeys(keysLineEdit->text().toStdString()); auto str=inPortLineEdit->text(); int inPortInt=str.toInt(&ok); - if(!ok)return false; + if(!ok){ + highlightWrongInput(QApplication::tr("Bad inPort, must be int.")+" "+cannotSaveSettings,inPortLineEdit); + return false; + } stc->setinPort(inPortInt); stc->setaccessList(accessListLineEdit->text().toStdString()); @@ -147,7 +154,10 @@ protected: auto mcStr=maxConnsLineEdit->text(); uint32_t mcInt=(uint32_t)mcStr.toInt(&ok); - if(!ok)return false; + if(!ok){ + highlightWrongInput(QApplication::tr("Bad maxConns, must be int.")+" "+cannotSaveSettings,maxConnsLineEdit); + return false; + } stc->setmaxConns(mcInt); stc->setgzip(gzipCheckBox->isChecked()); diff --git a/qt/i2pd_qt/TunnelConfig.cpp b/qt/i2pd_qt/TunnelConfig.cpp index 8cf86d14..81216c0b 100644 --- a/qt/i2pd_qt/TunnelConfig.cpp +++ b/qt/i2pd_qt/TunnelConfig.cpp @@ -6,24 +6,24 @@ void TunnelConfig::saveHeaderToStringStream(std::stringstream& out) { } void TunnelConfig::saveI2CPParametersToStringStream(std::stringstream& out) { - if (i2cpParameters.getInbound_length().toUShort() != i2p::client::DEFAULT_INBOUND_TUNNEL_LENGTH) - out << i2p::client::I2CP_PARAM_INBOUND_TUNNEL_LENGTH << "=" - << i2cpParameters.getInbound_length().toStdString() << "\n"; - if (i2cpParameters.getOutbound_length().toUShort() != i2p::client::DEFAULT_OUTBOUND_TUNNEL_LENGTH) - out << i2p::client::I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH << "=" - << i2cpParameters.getOutbound_length().toStdString() << "\n"; - if (i2cpParameters.getInbound_quantity().toUShort() != i2p::client::DEFAULT_INBOUND_TUNNELS_QUANTITY) - out << i2p::client::I2CP_PARAM_INBOUND_TUNNELS_QUANTITY << "=" - << i2cpParameters.getInbound_quantity().toStdString() << "\n"; - if (i2cpParameters.getOutbound_quantity().toUShort() != i2p::client::DEFAULT_OUTBOUND_TUNNELS_QUANTITY) - out << i2p::client::I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY << "=" - << i2cpParameters.getOutbound_quantity().toStdString() << "\n"; - if (i2cpParameters.getCrypto_tagsToSend().toUShort() != i2p::client::DEFAULT_TAGS_TO_SEND) - out << i2p::client::I2CP_PARAM_TAGS_TO_SEND << "=" - << i2cpParameters.getCrypto_tagsToSend().toStdString() << "\n"; - if (!i2cpParameters.getExplicitPeers().isEmpty()) - out << i2p::client::I2CP_PARAM_EXPLICIT_PEERS << "=" - << i2cpParameters.getExplicitPeers().toStdString() << "\n"; + if (i2cpParameters.getInbound_length().toUShort() != i2p::client::DEFAULT_INBOUND_TUNNEL_LENGTH) + out << i2p::client::I2CP_PARAM_INBOUND_TUNNEL_LENGTH << "=" + << i2cpParameters.getInbound_length().toStdString() << "\n"; + if (i2cpParameters.getOutbound_length().toUShort() != i2p::client::DEFAULT_OUTBOUND_TUNNEL_LENGTH) + out << i2p::client::I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH << "=" + << i2cpParameters.getOutbound_length().toStdString() << "\n"; + if (i2cpParameters.getInbound_quantity().toUShort() != i2p::client::DEFAULT_INBOUND_TUNNELS_QUANTITY) + out << i2p::client::I2CP_PARAM_INBOUND_TUNNELS_QUANTITY << "=" + << i2cpParameters.getInbound_quantity().toStdString() << "\n"; + if (i2cpParameters.getOutbound_quantity().toUShort() != i2p::client::DEFAULT_OUTBOUND_TUNNELS_QUANTITY) + out << i2p::client::I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY << "=" + << i2cpParameters.getOutbound_quantity().toStdString() << "\n"; + if (i2cpParameters.getCrypto_tagsToSend().toUShort() != i2p::client::DEFAULT_TAGS_TO_SEND) + out << i2p::client::I2CP_PARAM_TAGS_TO_SEND << "=" + << i2cpParameters.getCrypto_tagsToSend().toStdString() << "\n"; + if (!i2cpParameters.getExplicitPeers().isEmpty()) //todo #947 + out << i2p::client::I2CP_PARAM_EXPLICIT_PEERS << "=" + << i2cpParameters.getExplicitPeers().toStdString() << "\n"; out << "\n"; } diff --git a/qt/i2pd_qt/TunnelPane.cpp b/qt/i2pd_qt/TunnelPane.cpp index 5f412070..a86adbb1 100644 --- a/qt/i2pd_qt/TunnelPane.cpp +++ b/qt/i2pd_qt/TunnelPane.cpp @@ -1,8 +1,10 @@ #include "TunnelPane.h" #include "QMessageBox" -TunnelPane::TunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener_, TunnelConfig* tunnelConfig_): +TunnelPane::TunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener_, TunnelConfig* tunnelConfig_, QWidget* wrongInputPane_, QLabel* wrongInputLabel_): QObject(), + wrongInputPane(wrongInputPane_), + wrongInputLabel(wrongInputLabel_), tunnelConfig(tunnelConfig_), tunnelsPageUpdateListener(tunnelsPageUpdateListener_), gridLayoutWidget_2(nullptr) {} diff --git a/qt/i2pd_qt/TunnelPane.h b/qt/i2pd_qt/TunnelPane.h index abf0b42d..8d28f07f 100644 --- a/qt/i2pd_qt/TunnelPane.h +++ b/qt/i2pd_qt/TunnelPane.h @@ -28,16 +28,24 @@ class TunnelPane : public QObject { Q_OBJECT public: - TunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener_, TunnelConfig* tunconf); + TunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener_, TunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_); virtual ~TunnelPane(){} void deleteTunnelForm(); + void hideWrongInputLabel() { wrongInputPane->setVisible(false); } + void highlightWrongInput(QString warningText, QWidget* controlWithWrongInput) { + wrongInputPane->setVisible(true); + wrongInputLabel->setText(warningText); + if(controlWithWrongInput)controlWithWrongInput->setFocus(); + } virtual ServerTunnelPane* asServerTunnelPane()=0; virtual ClientTunnelPane* asClientTunnelPane()=0; protected: + QWidget * wrongInputPane; + QLabel* wrongInputLabel; TunnelConfig* tunnelConfig; widgetlockregistry widgetlocks; TunnelsPageUpdateListener* tunnelsPageUpdateListener; @@ -87,6 +95,7 @@ protected: //returns false when invalid data at UI virtual bool applyDataFromUIToTunnelConfig() { + hideWrongInputLabel(); tunnelConfig->setName(nameLineEdit->text().toStdString()); tunnelConfig->setType(readTunnelTypeComboboxData()); I2CPParameters& i2cpParams=tunnelConfig->getI2cpParameters(); diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index 71d7dca7..ec636646 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -82,6 +82,11 @@ MainWindow::MainWindow(QWidget *parent) : ui->settingsContents->setAutoFillBackground(true); ui->settingsContents->setPalette(pal); */ + QPalette pal(palette()); + pal.setColor(QPalette::Background, Qt::red); + ui->wrongInputLabel->setAutoFillBackground(true); + ui->wrongInputLabel->setPalette(pal); + ui->wrongInputLabel->setVisible(false); #ifndef ANDROID createActions(); @@ -565,7 +570,7 @@ void MainWindow::initUInt16Box(ConfigOption option, QLineEdit* numberLineEdit, Q configItems.append(new UInt16StringItem(option, numberLineEdit, fieldNameTranslated)); } void MainWindow::initStringBox(ConfigOption option, QLineEdit* lineEdit){ - configItems.append(new BaseStringItem(option, lineEdit)); + configItems.append(new BaseStringItem(option, lineEdit, QString())); } NonGUIOptionItem* MainWindow::initNonGUIOption(ConfigOption option) { NonGUIOptionItem * retValue; @@ -623,6 +628,9 @@ void MainWindow::loadAllConfigs(){ } /** returns false iff not valid items present and save was aborted */ bool MainWindow::saveAllConfigs(){ + QString cannotSaveSettings = QApplication::tr("Cannot save settings."); + ui->wrongInputLabel->setVisible(false); + programOptionsWriterCurrentSection=""; /*if(!logFileNameOption->lineEdit->text().trimmed().isEmpty())logOption->optionValue=boost::any(std::string("file")); else logOption->optionValue=boost::any(std::string("stdout"));*/ @@ -632,7 +640,10 @@ bool MainWindow::saveAllConfigs(){ std::stringstream out; for(QList::iterator it = configItems.begin(); it!= configItems.end(); ++it) { MainWindowItem* item = *it; - if(!item->isValid()) return false; + if(!item->isValid()){ + highlightWrongInput(QApplication::tr("Invalid value for")+" "+item->getConfigOption().section+"::"+item->getConfigOption().option+". "+item->getRequirementToBeValid()+" "+cannotSaveSettings, item->getWidgetToFocus()); + return false; + } } for(QList::iterator it = configItems.begin(); it!= configItems.end(); ++it) { @@ -688,27 +699,27 @@ void MainWindow::appendTunnelForms(std::string tunnelNameToFocus) { TunnelConfig* tunconf = it->second; ServerTunnelConfig* stc = tunconf->asServerTunnelConfig(); if(stc){ - ServerTunnelPane * tunnelPane=new ServerTunnelPane(&tunnelsPageUpdateListener, stc); + ServerTunnelPane * tunnelPane=new ServerTunnelPane(&tunnelsPageUpdateListener, stc, ui->wrongInputLabel, ui->wrongInputLabel); int h=tunnelPane->appendServerTunnelForm(stc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height); height+=h; - qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size(); + //qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size(); tunnelPanes.push_back(tunnelPane); if(name==tunnelNameToFocus)tunnelPane->getNameLineEdit()->setFocus(); continue; } ClientTunnelConfig* ctc = tunconf->asClientTunnelConfig(); if(ctc){ - ClientTunnelPane * tunnelPane=new ClientTunnelPane(&tunnelsPageUpdateListener, ctc); + ClientTunnelPane * tunnelPane=new ClientTunnelPane(&tunnelsPageUpdateListener, ctc, ui->wrongInputLabel, ui->wrongInputLabel); int h=tunnelPane->appendClientTunnelForm(ctc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height); height+=h; - qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size(); + //qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size(); tunnelPanes.push_back(tunnelPane); if(name==tunnelNameToFocus)tunnelPane->getNameLineEdit()->setFocus(); continue; } throw "unknown TunnelConfig subtype"; } - qDebug() << "tun.setting height:" << height; + //qDebug() << "tun.setting height:" << height; ui->tunnelsScrollAreaWidgetContents->setGeometry(QRect(0, 0, 621, height)); QList childWidgets = ui->tunnelsScrollAreaWidgetContents->findChildren(); foreach(QWidget* widget, childWidgets) @@ -833,3 +844,9 @@ void MainWindow::anchorClickedHandler(const QUrl & link) { void MainWindow::backClickedFromChild() { showStatusPage(statusPage); } + +void MainWindow::highlightWrongInput(QString warningText, QWidget* widgetToFocus) { + ui->wrongInputLabel->setVisible(true); + ui->wrongInputLabel->setText(warningText); + if(widgetToFocus)widgetToFocus->setFocus(); +} diff --git a/qt/i2pd_qt/mainwindow.h b/qt/i2pd_qt/mainwindow.h index c0286d03..46294084 100644 --- a/qt/i2pd_qt/mainwindow.h +++ b/qt/i2pd_qt/mainwindow.h @@ -93,8 +93,13 @@ class MainWindow; class MainWindowItem : public QObject { Q_OBJECT ConfigOption option; + QWidget* widgetToFocus; + QString requirementToBeValid; public: - MainWindowItem(ConfigOption option_) : option(option_) {} + MainWindowItem(ConfigOption option_, QWidget* widgetToFocus_, QString requirementToBeValid_) : option(option_), widgetToFocus(widgetToFocus_), requirementToBeValid(requirementToBeValid_) {} + QWidget* getWidgetToFocus(){return widgetToFocus;} + QString& getRequirementToBeValid() { return requirementToBeValid; } + ConfigOption& getConfigOption() { return option; } boost::any optionValue; virtual ~MainWindowItem(){} virtual void installListeners(MainWindow *mainWindow); @@ -145,7 +150,7 @@ public: }; class NonGUIOptionItem : public MainWindowItem { public: - NonGUIOptionItem(ConfigOption option_) : MainWindowItem(option_) {}; + NonGUIOptionItem(ConfigOption option_) : MainWindowItem(option_, nullptr, QString()) {}; virtual ~NonGUIOptionItem(){} virtual bool isValid() { return true; } }; @@ -153,7 +158,7 @@ class BaseStringItem : public MainWindowItem { Q_OBJECT public: QLineEdit* lineEdit; - BaseStringItem(ConfigOption option_, QLineEdit* lineEdit_) : MainWindowItem(option_), lineEdit(lineEdit_){}; + BaseStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString requirementToBeValid_) : MainWindowItem(option_, lineEdit_, requirementToBeValid_), lineEdit(lineEdit_){}; virtual ~BaseStringItem(){} virtual void installListeners(MainWindow *mainWindow); virtual QString toString(){ @@ -175,7 +180,7 @@ class FileOrFolderChooserItem : public BaseStringItem { public: QPushButton* browsePushButton; FileOrFolderChooserItem(ConfigOption option_, QLineEdit* lineEdit_, QPushButton* browsePushButton_) : - BaseStringItem(option_, lineEdit_), browsePushButton(browsePushButton_) {} + BaseStringItem(option_, lineEdit_, QString()), browsePushButton(browsePushButton_) {} virtual ~FileOrFolderChooserItem(){} }; class FileChooserItem : public FileOrFolderChooserItem { @@ -201,7 +206,7 @@ public: class ComboBoxItem : public MainWindowItem { public: QComboBox* comboBox; - ComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : MainWindowItem(option_), comboBox(comboBox_){}; + ComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : MainWindowItem(option_,comboBox_,QString()), comboBox(comboBox_){}; virtual ~ComboBoxItem(){} virtual void installListeners(MainWindow *mainWindow); virtual void loadFromConfigOption()=0; @@ -260,7 +265,7 @@ public: class CheckBoxItem : public MainWindowItem { public: QCheckBox* checkBox; - CheckBoxItem(ConfigOption option_, QCheckBox* checkBox_) : MainWindowItem(option_), checkBox(checkBox_){}; + CheckBoxItem(ConfigOption option_, QCheckBox* checkBox_) : MainWindowItem(option_,checkBox_,QString()), checkBox(checkBox_){}; virtual ~CheckBoxItem(){} virtual void installListeners(MainWindow *mainWindow); virtual void loadFromConfigOption(){ @@ -276,58 +281,77 @@ public: class BaseFormattedStringItem : public BaseStringItem { public: QString fieldNameTranslated; - BaseFormattedStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) : - BaseStringItem(option_, lineEdit_), fieldNameTranslated(fieldNameTranslated_) {}; + BaseFormattedStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_, QString requirementToBeValid_) : + BaseStringItem(option_, lineEdit_, requirementToBeValid_), fieldNameTranslated(fieldNameTranslated_) {}; virtual ~BaseFormattedStringItem(){} virtual bool isValid()=0; }; class IntegerStringItem : public BaseFormattedStringItem { public: IntegerStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) : - BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {}; + BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be a valid integer.")) {}; virtual ~IntegerStringItem(){} - virtual bool isValid(){return true;} + virtual bool isValid(){ + auto str=lineEdit->text(); + bool ok; + str.toInt(&ok); + return ok; + } virtual QString toString(){return QString::number(boost::any_cast(optionValue));} virtual boost::any fromString(QString s){return boost::any(std::stoi(s.toStdString()));} }; class UShortStringItem : public BaseFormattedStringItem { public: UShortStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) : - BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {}; + BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned short integer.")) {}; virtual ~UShortStringItem(){} - virtual bool isValid(){return true;} + virtual bool isValid(){ + auto str=lineEdit->text(); + bool ok; + str.toUShort(&ok); + return ok; + } virtual QString toString(){return QString::number(boost::any_cast(optionValue));} virtual boost::any fromString(QString s){return boost::any((unsigned short)std::stoi(s.toStdString()));} }; class UInt32StringItem : public BaseFormattedStringItem { public: UInt32StringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) : - BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {}; + BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned 32-bit integer.")) {}; virtual ~UInt32StringItem(){} - virtual bool isValid(){return true;} + virtual bool isValid(){ + auto str=lineEdit->text(); + bool ok; + str.toUInt(&ok); + return ok; + } virtual QString toString(){return QString::number(boost::any_cast(optionValue));} virtual boost::any fromString(QString s){return boost::any((uint32_t)std::stoi(s.toStdString()));} }; class UInt16StringItem : public BaseFormattedStringItem { public: UInt16StringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) : - BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {}; + BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned 16-bit integer")) {}; virtual ~UInt16StringItem(){} - virtual bool isValid(){return true;} + virtual bool isValid(){ + auto str=lineEdit->text(); + bool ok; + str.toUShort(&ok); + return ok; + } virtual QString toString(){return QString::number(boost::any_cast(optionValue));} virtual boost::any fromString(QString s){return boost::any((uint16_t)std::stoi(s.toStdString()));} }; class IPAddressStringItem : public BaseFormattedStringItem { public: IPAddressStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) : - BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {}; - virtual bool isValid(){return true;} + BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be an IPv4 address")) {}; + virtual bool isValid(){return true;}//todo }; class TCPPortStringItem : public UShortStringItem { public: TCPPortStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) : UShortStringItem(option_, lineEdit_, fieldNameTranslated_) {}; - virtual bool isValid(){return true;} }; namespace Ui { @@ -354,6 +378,8 @@ public: void setI2PController(i2p::qt::Controller* controller_); + void highlightWrongInput(QString warningText, QWidget* widgetToFocus); + //typedef std::function DefaultValueGetter; //#ifndef ANDROID diff --git a/qt/i2pd_qt/mainwindow.ui b/qt/i2pd_qt/mainwindow.ui index cf15155b..2363614b 100644 --- a/qt/i2pd_qt/mainwindow.ui +++ b/qt/i2pd_qt/mainwindow.ui @@ -50,7 +50,7 @@ 10 10 888 - 530 + 555 @@ -168,332 +168,770 @@ - - - - 0 - 0 - - - - - 0 - 528 - - - - - 713 - 713 - - - - 1 - - - - - 0 - 0 - - - - - - 0 - 0 + + + + + + 0 + 30 + + + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + 255 + 127 + 127 + + + + + + + 255 + 63 + 63 + + + + + + + 127 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 127 + 127 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + 255 + 127 + 127 + + + + + + + 255 + 63 + 63 + + + + + + + 127 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 127 + 127 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 127 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + 255 + 127 + 127 + + + + + + + 255 + 63 + 63 + + + + + + + 127 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 127 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + TextLabel + + + true + + + 10 + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + 713 - 531 - + 713 + - - - QLayout::SetMaximumSize + + 0 + + + + + 0 + 0 + - - - - - 15 - - - - Status - - - - - + + + + 0 + 0 + 713 + 531 + + + QLayout::SetMaximumSize + + + + + 15 + + + + Status + + + + + + + QLayout::SetMaximumSize + + + - - - - - - - - 0 - 0 - - - - - - 0 - 0 - 711 - 531 - - - - - QLayout::SetMaximumSize + + + + + + 0 + 0 + - - - - - 15 - - - - General settings - - - - - - - Qt::ScrollBarAlwaysOn - - - Qt::ScrollBarAsNeeded - - - QAbstractScrollArea::AdjustIgnored - - - true + + + + 0 + 0 + 711 + 531 + + + + + QLayout::SetMaximumSize - - - - 0 - 0 - 689 - 496 - - - - - 0 - 0 - - - - - - - - - - - - - 0 - 0 - 711 - 531 - - - - - QLayout::SetMinAndMaxSize - - - - - - 15 - + + + + + 15 + + + + General settings + + + + + + + Qt::ScrollBarAlwaysOn + + + Qt::ScrollBarAsNeeded + + + QAbstractScrollArea::AdjustIgnored + + + true + + + + + 0 + 0 + 80 + 26 + + + + + 0 + 0 + + + + + + + + + + + + + 0 + 0 + 711 + 531 + + + + + QLayout::SetMinAndMaxSize - - Tunnels settings + + + + + 15 + + + + Tunnels settings + + + + + + + + + Add Client Tunnel + + + + + + + Add Server Tunnel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::ScrollBarAlwaysOn + + + false + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + 0 + 0 + 699 + 425 + + + + + + + + + + + + + 0 + 0 + 711 + 531 + + + + + QLayout::SetMinAndMaxSize - - - - - + + + + 15 + + - Add Client Tunnel + Restart - + - Add Server Tunnel + Restart i2pd - + - Qt::Horizontal + Qt::Vertical - 40 - 20 + 20 + 40 - - - - - Qt::ScrollBarAlwaysOn - - - false - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - 0 - 0 - 699 - 425 - - - - - - - - - - - - - 0 - 0 - 711 - 531 - - - - - QLayout::SetMinAndMaxSize - - - - - - 15 - - - - Restart - - - - - - - Restart i2pd - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - 0 - 0 - - - - - - 0 - 0 - 711 - 531 - - - - - QLayout::SetMinAndMaxSize + + + + + + 0 + 0 + - - - - - 15 - - - - Quit - - - - - - - Quit Now - - - - - - - Graceful Quit - - - - - - - Qt::Vertical - - - - 20 - 40 - + + + + 0 + 0 + 711 + 531 + + + + + QLayout::SetMinAndMaxSize - - - + + + + + 15 + + + + Quit + + + + + + + Quit Now + + + + + + + Graceful Quit + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + - - + +