#include "QvUtils.h" #include "QvCoreInteractions.h" #include "w_PrefrencesWindow.h" #include #include #define NEEDRESTART if(finishedLoading) IsConnectionPropertyChanged = true; PrefrencesWindow::PrefrencesWindow(QWidget *parent) : QDialog(parent), CurrentConfig(), ui(new Ui::PrefrencesWindow) { ui->setupUi(this); // We add locales ui->languageComboBox->clear(); QDirIterator it(":/translations"); while (it.hasNext()) { ui->languageComboBox->addItem(it.next().split("/").last().split(".").first()); } // ui->qvVersion->setText(QV2RAY_VERSION_STRING); CurrentConfig = GetGlobalConfig(); // ui->languageComboBox->setCurrentText(QSTRING(CurrentConfig.language)); ui->logLevelComboBox->setCurrentIndex(CurrentConfig.logLevel); ui->tProxyCheckBox->setChecked(CurrentConfig.runAsRoot); // // ui->listenIPTxt->setText(QSTRING(CurrentConfig.inBoundSettings.listenip)); // bool have_http = CurrentConfig.inBoundSettings.http_port != 0; ui->httpCB->setChecked(have_http); ui->httpPortLE->setText(QSTRING(to_string(CurrentConfig.inBoundSettings.http_port))); ui->httpAuthCB->setChecked(CurrentConfig.inBoundSettings.http_useAuth); // ui->httpAuthCB->setEnabled(have_http); ui->httpAuthCB->setChecked(CurrentConfig.inBoundSettings.http_useAuth); ui->httpAuthUsernameTxt->setEnabled(have_http && CurrentConfig.inBoundSettings.http_useAuth); ui->httpAuthPasswordTxt->setEnabled(have_http && CurrentConfig.inBoundSettings.http_useAuth); ui->httpAuthUsernameTxt->setText(QSTRING(CurrentConfig.inBoundSettings.httpAccount.user)); ui->httpAuthPasswordTxt->setText(QSTRING(CurrentConfig.inBoundSettings.httpAccount.pass)); ui->httpPortLE->setValidator(new QIntValidator()); // // bool have_socks = CurrentConfig.inBoundSettings.socks_port != 0; ui->socksCB->setChecked(have_socks); ui->socksPortLE->setText(QSTRING(to_string(CurrentConfig.inBoundSettings.socks_port))); ui->socksAuthCB->setChecked(CurrentConfig.inBoundSettings.socks_useAuth); // ui->socksAuthCB->setEnabled(have_socks); ui->socksAuthCB->setChecked(CurrentConfig.inBoundSettings.socks_useAuth); ui->socksAuthUsernameTxt->setEnabled(have_socks && CurrentConfig.inBoundSettings.socks_useAuth); ui->socksAuthPasswordTxt->setEnabled(have_socks && CurrentConfig.inBoundSettings.socks_useAuth); ui->socksAuthUsernameTxt->setText(QSTRING(CurrentConfig.inBoundSettings.socksAccount.user)); ui->socksAuthPasswordTxt->setText(QSTRING(CurrentConfig.inBoundSettings.socksAccount.pass)); ui->socksPortLE->setValidator(new QIntValidator()); // // ui->vCoreAssetsPathTxt->setText(QSTRING(CurrentConfig.v2AssetsPath)); // // ui->muxEnabledCB->setChecked(CurrentConfig.mux.enabled); ui->muxConcurrencyTxt->setValue(CurrentConfig.mux.concurrency); // ui->proxyCNCb->setChecked(CurrentConfig.proxyCN); ui->proxyDefaultCb->setChecked(CurrentConfig.enableProxy); ui->localDNSCb->setChecked(CurrentConfig.withLocalDNS); // ui->DNSListTxt->clear(); foreach (auto dnsStr, CurrentConfig.dnsList) { auto str = QString::fromStdString(dnsStr).trimmed(); if (!str.isEmpty()) { ui->DNSListTxt->appendPlainText(str); } } foreach (auto connection, CurrentConfig.configs) { ui->autoStartCombo->addItem(QSTRING(connection)); } ui->autoStartCombo->setCurrentText(QSTRING(CurrentConfig.autoStartConfig)); ui->cancelIgnoreVersionBtn->setEnabled(CurrentConfig.ignoredVersion != ""); ui->ignoredNextVersion->setText(QSTRING(CurrentConfig.ignoredVersion)); finishedLoading = true; } PrefrencesWindow::~PrefrencesWindow() { delete ui; } void PrefrencesWindow::on_buttonBox_accepted() { int sp = ui->socksPortLE->text().toInt(); int hp = ui->httpPortLE->text().toInt() ; if (!(sp == 0 || hp == 0) && sp == hp) { QvMessageBox(this, tr("Prefrences"), tr("Port numbers cannot be the same")); return; } SetGlobalConfig(CurrentConfig); emit s_reload_config(IsConnectionPropertyChanged); } void PrefrencesWindow::on_httpCB_stateChanged(int checked) { NEEDRESTART ui->httpPortLE->setEnabled(checked == Qt::Checked); ui->httpAuthCB->setEnabled(checked == Qt::Checked); ui->httpAuthUsernameTxt->setEnabled(checked == Qt::Checked && ui->httpAuthCB->isChecked()); ui->httpAuthPasswordTxt->setEnabled(checked == Qt::Checked && ui->httpAuthCB->isChecked()); CurrentConfig.inBoundSettings.http_port = checked == Qt::Checked ? CurrentConfig.inBoundSettings.http_port : 0; if (checked != Qt::Checked) { ui->httpPortLE->setText("0"); } } void PrefrencesWindow::on_socksCB_stateChanged(int checked) { NEEDRESTART ui->socksPortLE->setEnabled(checked == Qt::Checked); ui->socksAuthCB->setEnabled(checked == Qt::Checked); ui->socksAuthUsernameTxt->setEnabled(checked == Qt::Checked && ui->socksAuthCB->isChecked()); ui->socksAuthPasswordTxt->setEnabled(checked == Qt::Checked && ui->socksAuthCB->isChecked()); CurrentConfig.inBoundSettings.socks_port = checked == Qt::Checked ? CurrentConfig.inBoundSettings.socks_port : 0; if (checked != Qt::Checked) { ui->socksPortLE->setText("0"); } } void PrefrencesWindow::on_httpAuthCB_stateChanged(int checked) { NEEDRESTART ui->httpAuthUsernameTxt->setEnabled(checked == Qt::Checked); ui->httpAuthPasswordTxt->setEnabled(checked == Qt::Checked); CurrentConfig.inBoundSettings.http_useAuth = checked == Qt::Checked; } void PrefrencesWindow::on_socksAuthCB_stateChanged(int checked) { NEEDRESTART ui->socksAuthUsernameTxt->setEnabled(checked == Qt::Checked); ui->socksAuthPasswordTxt->setEnabled(checked == Qt::Checked); CurrentConfig.inBoundSettings.socks_useAuth = checked == Qt::Checked; } void PrefrencesWindow::on_languageComboBox_currentTextChanged(const QString &arg1) { CurrentConfig.language = arg1.toStdString(); // // A strange bug prevents us to change the UI language online // https://github.com/lhy0403/Qv2ray/issues/34 // //if (QApplication::installTranslator(getTranslator(&arg1))) { // LOG(MODULE_UI, "Loaded translations " + arg1.toStdString()) // ui->retranslateUi(this); //} else { // QvMessageBox(this, tr("#Prefrences"), tr("#SwitchTranslationError")); //} } void PrefrencesWindow::on_logLevelComboBox_currentIndexChanged(int index) { NEEDRESTART CurrentConfig.logLevel = index; } void PrefrencesWindow::on_vCoreAssetsPathTxt_textEdited(const QString &arg1) { NEEDRESTART CurrentConfig.v2AssetsPath = arg1.toStdString(); } void PrefrencesWindow::on_muxEnabledCB_stateChanged(int arg1) { NEEDRESTART CurrentConfig.mux.enabled = arg1 == Qt::Checked; } void PrefrencesWindow::on_muxConcurrencyTxt_valueChanged(int arg1) { NEEDRESTART CurrentConfig.mux.concurrency = arg1; } void PrefrencesWindow::on_listenIPTxt_textEdited(const QString &arg1) { NEEDRESTART CurrentConfig.inBoundSettings.listenip = arg1.toStdString(); } void PrefrencesWindow::on_socksPortLE_textEdited(const QString &arg1) { NEEDRESTART CurrentConfig.inBoundSettings.socks_port = stoi(arg1.toStdString()); } void PrefrencesWindow::on_httpPortLE_textEdited(const QString &arg1) { NEEDRESTART CurrentConfig.inBoundSettings.http_port = stoi(arg1.toStdString()); } void PrefrencesWindow::on_httpAuthUsernameTxt_textEdited(const QString &arg1) { NEEDRESTART CurrentConfig.inBoundSettings.httpAccount.user = arg1.toStdString(); } void PrefrencesWindow::on_httpAuthPasswordTxt_textEdited(const QString &arg1) { NEEDRESTART CurrentConfig.inBoundSettings.httpAccount.pass = arg1.toStdString(); } void PrefrencesWindow::on_socksAuthUsernameTxt_textEdited(const QString &arg1) { NEEDRESTART CurrentConfig.inBoundSettings.socksAccount.user = arg1.toStdString(); } void PrefrencesWindow::on_socksAuthPasswordTxt_textEdited(const QString &arg1) { NEEDRESTART CurrentConfig.inBoundSettings.socksAccount.pass = arg1.toStdString(); } void PrefrencesWindow::on_proxyCNCb_stateChanged(int arg1) { NEEDRESTART CurrentConfig.proxyCN = arg1 == Qt::Checked; } void PrefrencesWindow::on_proxyDefaultCb_stateChanged(int arg1) { NEEDRESTART CurrentConfig.enableProxy = arg1 == Qt::Checked; } void PrefrencesWindow::on_localDNSCb_stateChanged(int arg1) { NEEDRESTART CurrentConfig.withLocalDNS = arg1 == Qt::Checked; } void PrefrencesWindow::on_selectVAssetBtn_clicked() { NEEDRESTART QString dir = QFileDialog::getExistingDirectory(this, tr("Open v2ray assets folder"), QDir::currentPath()); ui->vCoreAssetsPathTxt->setText(dir); on_vCoreAssetsPathTxt_textEdited(dir); } void PrefrencesWindow::on_DNSListTxt_textChanged() { if (finishedLoading) { try { QStringList hosts = ui->DNSListTxt->toPlainText().replace("\r", "").split("\n"); CurrentConfig.dnsList.clear(); foreach (auto host, hosts) { if (host != "" && host != "\r") { // Not empty, so we save. CurrentConfig.dnsList.push_back(host.toStdString()); NEEDRESTART } } BLACK(DNSListTxt) } catch (...) { RED(DNSListTxt) } } } void PrefrencesWindow::on_autoStartCombo_currentTextChanged(const QString &arg1) { CurrentConfig.autoStartConfig = arg1.toStdString(); } void PrefrencesWindow::on_aboutQt_clicked() { QApplication::aboutQt(); } void PrefrencesWindow::on_cancelIgnoreVersionBtn_clicked() { CurrentConfig.ignoredVersion.clear(); ui->cancelIgnoreVersionBtn->setEnabled(false); } void PrefrencesWindow::on_tProxyCheckBox_stateChanged(int arg1) { #ifdef __linux if (finishedLoading) { //LOG(MODULE_UI, "Running getcap....") //QProcess::execute("getcap " + QV2RAY_V2RAY_CORE_PATH); // Set UID and GID for linux // Steps: // --> 1. Copy v2ray core files to the #CONFIG_DIR#/vcore/ dir. // --> 2. Change GlobalConfig.v2CorePath. // --> 3. Call `pkexec setcap CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE=eip` on the v2ray core. if (arg1 == Qt::Checked) { // We enable it! if (QvMessageBoxAsk(this, tr("Enable tProxy Support"), tr("This will append capabilities to the v2ray executable.") + "\r\n" + tr("If anything goes wrong after enabling this, please refer to issue #57 or the link below:") + "\r\n" + " https://github.com/lhy0403/Qv2ray/blob/master/docs/FAQ.md ") != QMessageBox::Yes) { ui->tProxyCheckBox->setChecked(false); LOG(MODULE_UI, "Canceled enabling tProxy feature.") } int ret = QProcess::execute("pkexec setcap CAP_NET_ADMIN,CAP_NET_RAW,CAP_NET_BIND_SERVICE=eip " + QV2RAY_V2RAY_CORE_PATH); if (ret != 0) { LOG(MODULE_UI, "WARN: setcap exits with code: " + to_string(ret)) QvMessageBox(this, tr("Prefrences"), tr("Failed to setcap onto v2ray executable. You may need to run `setcap` manually.")); } CurrentConfig.runAsRoot = true; NEEDRESTART } else { int ret = QProcess::execute("pkexec setcap -r " + QV2RAY_V2RAY_CORE_PATH); if (ret != 0) { LOG(MODULE_UI, "WARN: setcap exits with code: " + to_string(ret)) QvMessageBox(this, tr("Prefrences"), tr("Failed to setcap onto v2ray executable. You may need to run `setcap` manually.")); } CurrentConfig.runAsRoot = false; NEEDRESTART } } #else Q_UNUSED(arg1) ui->tProxyCheckBox->setChecked(false); // No such uid gid thing on Windows and MacOS QvMessageBox(this, tr("Prefrences"), tr("tProxy is not supported on MacOS and Windows")); #endif }