USBDeviceAddToWhitelistDialog.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // Copyright 2017 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "DolphinQt/Settings/USBDeviceAddToWhitelistDialog.h"
  4. #include <QDialog>
  5. #include <QDialogButtonBox>
  6. #include <QErrorMessage>
  7. #include <QHBoxLayout>
  8. #include <QHeaderView>
  9. #include <QLabel>
  10. #include <QLineEdit>
  11. #include <QListWidget>
  12. #include <QPushButton>
  13. #include <QTimer>
  14. #include <QVBoxLayout>
  15. #include <QWidget>
  16. #include "Common/StringUtil.h"
  17. #include "Core/Config/MainSettings.h"
  18. #include "Core/ConfigManager.h"
  19. #include "DolphinQt/QtUtils/ModalMessageBox.h"
  20. #include "DolphinQt/Settings/WiiPane.h"
  21. #include "UICommon/USBUtils.h"
  22. static bool IsValidUSBIDString(const std::string& string)
  23. {
  24. if (string.empty() || string.length() > 4)
  25. return false;
  26. return std::ranges::all_of(string, Common::IsXDigit);
  27. }
  28. USBDeviceAddToWhitelistDialog::USBDeviceAddToWhitelistDialog(QWidget* parent) : QDialog(parent)
  29. {
  30. InitControls();
  31. setLayout(main_layout);
  32. }
  33. void USBDeviceAddToWhitelistDialog::InitControls()
  34. {
  35. setWindowTitle(tr("Add New USB Device"));
  36. setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
  37. m_whitelist_buttonbox = new QDialogButtonBox();
  38. auto* add_button = new QPushButton(tr("Add"));
  39. auto* cancel_button = new QPushButton(tr("Cancel"));
  40. m_whitelist_buttonbox->addButton(add_button, QDialogButtonBox::AcceptRole);
  41. m_whitelist_buttonbox->addButton(cancel_button, QDialogButtonBox::RejectRole);
  42. connect(add_button, &QPushButton::clicked, this,
  43. &USBDeviceAddToWhitelistDialog::AddUSBDeviceToWhitelist);
  44. connect(cancel_button, &QPushButton::clicked, this, &USBDeviceAddToWhitelistDialog::reject);
  45. add_button->setDefault(true);
  46. main_layout = new QVBoxLayout();
  47. enter_device_id_label = new QLabel(tr("Enter USB device ID"));
  48. enter_device_id_label->setAlignment(Qt::AlignCenter);
  49. main_layout->addWidget(enter_device_id_label);
  50. entry_hbox_layout = new QHBoxLayout();
  51. device_vid_textbox = new QLineEdit();
  52. QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
  53. sizePolicy.setHorizontalStretch(1);
  54. sizePolicy.setVerticalStretch(0);
  55. sizePolicy.setHeightForWidth(device_vid_textbox->sizePolicy().hasHeightForWidth());
  56. device_vid_textbox->setSizePolicy(sizePolicy);
  57. // entry_hbox_layout->setWidget(2, QFormLayout::LabelRole, device_vid_textbox);
  58. entry_hbox_layout->addWidget(device_vid_textbox);
  59. device_pid_textbox = new QLineEdit();
  60. sizePolicy.setHeightForWidth(device_pid_textbox->sizePolicy().hasHeightForWidth());
  61. device_pid_textbox->setSizePolicy(sizePolicy);
  62. entry_hbox_layout->addWidget(device_pid_textbox);
  63. main_layout->addLayout(entry_hbox_layout);
  64. select_label = new QLabel(tr("or select a device"));
  65. select_label->setAlignment(Qt::AlignCenter);
  66. main_layout->addWidget(select_label);
  67. usb_inserted_devices_list = new QListWidget();
  68. m_refresh_devices_timer = new QTimer(this);
  69. connect(usb_inserted_devices_list, &QListWidget::currentItemChanged, this,
  70. &USBDeviceAddToWhitelistDialog::OnDeviceSelection);
  71. connect(usb_inserted_devices_list, &QListWidget::itemDoubleClicked, add_button,
  72. &QPushButton::clicked);
  73. connect(m_refresh_devices_timer, &QTimer::timeout, this,
  74. &USBDeviceAddToWhitelistDialog::RefreshDeviceList);
  75. RefreshDeviceList();
  76. m_refresh_devices_timer->start(1000);
  77. main_layout->addWidget(usb_inserted_devices_list);
  78. main_layout->addWidget(m_whitelist_buttonbox);
  79. // i18n: VID means Vendor ID (in the context of a USB device)
  80. device_vid_textbox->setPlaceholderText(tr("Device VID (e.g., 057e)"));
  81. // i18n: PID means Product ID (in the context of a USB device), not Process ID
  82. device_pid_textbox->setPlaceholderText(tr("Device PID (e.g., 0305)"));
  83. }
  84. void USBDeviceAddToWhitelistDialog::RefreshDeviceList()
  85. {
  86. const auto& current_devices = USBUtils::GetInsertedDevices();
  87. if (current_devices == m_shown_devices)
  88. return;
  89. const auto selection_string = usb_inserted_devices_list->currentItem();
  90. usb_inserted_devices_list->clear();
  91. auto whitelist = Config::GetUSBDeviceWhitelist();
  92. for (const auto& device : current_devices)
  93. {
  94. if (whitelist.contains({device.first.first, device.first.second}))
  95. continue;
  96. usb_inserted_devices_list->addItem(QString::fromStdString(device.second));
  97. }
  98. usb_inserted_devices_list->setCurrentItem(selection_string);
  99. m_shown_devices = current_devices;
  100. }
  101. void USBDeviceAddToWhitelistDialog::AddUSBDeviceToWhitelist()
  102. {
  103. const std::string vid_string(StripWhitespace(device_vid_textbox->text().toStdString()));
  104. const std::string pid_string(StripWhitespace(device_pid_textbox->text().toStdString()));
  105. if (!IsValidUSBIDString(vid_string))
  106. {
  107. ModalMessageBox::critical(this, tr("USB Whitelist Error"),
  108. // i18n: Here, VID means Vendor ID (for a USB device).
  109. tr("The entered VID is invalid."));
  110. return;
  111. }
  112. if (!IsValidUSBIDString(pid_string))
  113. {
  114. ModalMessageBox::critical(this, tr("USB Whitelist Error"),
  115. // i18n: Here, PID means Product ID (for a USB device).
  116. tr("The entered PID is invalid."));
  117. return;
  118. }
  119. const u16 vid = static_cast<u16>(std::stoul(vid_string, nullptr, 16));
  120. const u16 pid = static_cast<u16>(std::stoul(pid_string, nullptr, 16));
  121. auto whitelist = Config::GetUSBDeviceWhitelist();
  122. auto it = whitelist.emplace(vid, pid);
  123. if (!it.second)
  124. {
  125. ModalMessageBox::critical(this, tr("USB Whitelist Error"),
  126. tr("This USB device is already whitelisted."));
  127. return;
  128. }
  129. Config::SetUSBDeviceWhitelist(whitelist);
  130. Config::Save();
  131. accept();
  132. }
  133. void USBDeviceAddToWhitelistDialog::OnDeviceSelection()
  134. {
  135. // Not the nicest way of doing this but...
  136. QString device = usb_inserted_devices_list->currentItem()->text().left(9);
  137. QStringList split = device.split(QString::fromStdString(":"));
  138. QString* vid = new QString(split[0]);
  139. QString* pid = new QString(split[1]);
  140. device_vid_textbox->setText(*vid);
  141. device_pid_textbox->setText(*pid);
  142. }