diff --git a/CHANGELOG.md b/CHANGELOG.md index aa3d18eafa..5f19eb2832 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Changelog ## v2.1.2 (upcoming) -- fix [#468](https://github.com/jopohl/urh/pull/468) - improve python2 interpreter settings for GNU Radio backend with empty ``` urh.ini ``` +- [#469](https://github.com/jopohl/urh/pull/469) - improve device selection in options, use a table instead of a list view +- [#468](https://github.com/jopohl/urh/pull/468) - improve python2 interpreter settings for GNU Radio backend with empty ``` urh.ini ``` --- diff --git a/data/ui/options.ui b/data/ui/options.ui index 4bfbf6e171..87bb1f0b45 100644 --- a/data/ui/options.ui +++ b/data/ui/options.ui @@ -6,8 +6,8 @@ 0 0 - 773 - 749 + 788 + 822 @@ -217,8 +217,8 @@ 0 0 - 98 - 28 + 708 + 447 @@ -311,103 +311,51 @@ - - - - - QAbstractItemView::NoEditTriggers - - - true - - - QListView::ListMode - - - - - - - - - Enabled - - - - - - - &Native backend (recommended) - - - - - - - &Gnuradio backend - - - - - - - - 0 - 0 - - - - Perform a health check for native device extensions. - - - Health Check - - - - .. - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - + + + + true + + + + + + + <html><head/><body><p>Use the checkboxes in the table below to choose device backends and enable or disable devices. Disabled devices will not show up in device related dialogs such as send or receive.</p></body></html> + + + true + + - - - - 0 - 0 - + + + true + + + false + + 200 + + + false + + + + + - 75 false - true - - color: green - - device supports sending and receiving + <html><head/><body><p>Missing a native backend? Perform a <a href="health_check"><span style=" text-decoration: underline; color:#0000ff;">health check</span></a>! If GNU Radio backend is not available double check the GNU Radio settings below.</p></body></html> - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + true diff --git a/src/urh/controller/dialogs/OptionsDialog.py b/src/urh/controller/dialogs/OptionsDialog.py index ffdd32bcb6..58ce322bab 100644 --- a/src/urh/controller/dialogs/OptionsDialog.py +++ b/src/urh/controller/dialogs/OptionsDialog.py @@ -4,14 +4,14 @@ import tempfile import time -from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal, QSize +from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal, QSize, QAbstractTableModel, QModelIndex from PyQt5.QtGui import QCloseEvent, QIcon, QPixmap from PyQt5.QtWidgets import QDialog, QHBoxLayout, QCompleter, QDirModel, QApplication, QHeaderView, QStyleFactory, \ QRadioButton, QFileDialog from urh import constants, colormaps from urh.controller.widgets.PluginFrame import PluginFrame -from urh.dev.BackendHandler import BackendHandler, Backends, BackendContainer +from urh.dev.BackendHandler import BackendHandler, Backends from urh.dev.native import ExtensionHelper from urh.models.FieldTypeTableModel import FieldTypeTableModel from urh.signalprocessing.FieldType import FieldType @@ -22,6 +22,124 @@ from urh.util import util +class DeviceOptionsTableModel(QAbstractTableModel): + header_labels = ["Software Defined Radio", "Info", "Native backend (recommended)", "GNU Radio backend", "State"] + + def __init__(self, backend_handler: BackendHandler, parent=None): + self.backend_handler = backend_handler + + super().__init__(parent) + + def update(self): + self.beginResetModel() + self.endResetModel() + + def columnCount(self, parent: QModelIndex = None, *args, **kwargs): + return len(self.header_labels) + + def rowCount(self, parent: QModelIndex = None, *args, **kwargs): + return len(self.backend_handler.DEVICE_NAMES) + + def headerData(self, section, orientation, role=Qt.DisplayRole): + if role == Qt.DisplayRole and orientation == Qt.Horizontal: + return self.header_labels[section] + return super().headerData(section, orientation, role) + + def get_device_at(self, index: int): + dev_key = self.backend_handler.get_key_from_device_display_text(self.backend_handler.DEVICE_NAMES[index]) + return self.backend_handler.device_backends[dev_key] + + def data(self, index: QModelIndex, role=Qt.DisplayRole): + if not index.isValid(): + return None + + i = index.row() + j = index.column() + device = self.get_device_at(i) + if role == Qt.DisplayRole: + if j == 0: + return self.backend_handler.DEVICE_NAMES[i] + elif j == 1: + if device.supports_rx and device.supports_tx: + device_info = "supports RX and TX" + elif device.supports_rx and not device.supports_tx: + device_info = "supports RX only" + elif not device.supports_rx and device.supports_tx: + device_info = "supports TX only" + else: + device_info = "" + return device_info + elif j == 2: + if device.has_native_backend: + return "" + else: + return "not available" + elif j == 3: + if device.has_gnuradio_backend: + return "" + else: + return "not available" + elif j == 4: + if device.has_native_backend or device.has_gnuradio_backend: + return "enabled" if device.is_enabled else "disabled" + else: + return "no backend available" + elif role == Qt.CheckStateRole: + if j == 2 and device.has_native_backend: + return Qt.Checked if device.selected_backend == Backends.native else Qt.Unchecked + elif j == 3 and device.has_gnuradio_backend: + return Qt.Checked if device.selected_backend == Backends.grc else Qt.Unchecked + elif j == 4 and (device.has_native_backend or device.has_gnuradio_backend): + return Qt.Checked if device.is_enabled else Qt.Unchecked + + def setData(self, index: QModelIndex, value, role=None): + if not index.isValid(): + return False + + i, j = index.row(), index.column() + device = self.get_device_at(i) + if role == Qt.CheckStateRole: + enabled = bool(value) + if j == 2: + if enabled and device.has_native_backend: + device.selected_backend = Backends.native + elif not enabled and device.has_gnuradio_backend: + device.selected_backend = Backends.grc + elif j == 3: + if enabled and device.has_gnuradio_backend: + device.selected_backend = Backends.grc + elif not enabled and device.has_native_backend: + device.selected_backend = Backends.native + elif j == 4: + device.is_enabled = enabled + + self.update() + device.write_settings() + return True + + def flags(self, index: QModelIndex): + if not index.isValid(): + return None + + j = index.column() + device = self.get_device_at(index.row()) + if j in [0, 1, 2, 3] and not device.is_enabled: + return Qt.NoItemFlags + if j == 2 and not device.has_native_backend: + return Qt.NoItemFlags + elif j == 3 and not device.has_gnuradio_backend: + return Qt.NoItemFlags + elif j == 4 and not device.has_native_backend and not device.has_gnuradio_backend: + return Qt.NoItemFlags + + flags = Qt.ItemIsEnabled + + if j in [2, 3, 4]: + flags |= Qt.ItemIsUserCheckable + + return flags + + class OptionsDialog(QDialog): values_changed = pyqtSignal(dict) @@ -29,10 +147,18 @@ def __init__(self, installed_plugins, highlighted_plugins=None, parent=None): super().__init__(parent) self.backend_handler = BackendHandler() + self.backend_handler.set_gnuradio_installed_status() self.ui = Ui_DialogOptions() self.ui.setupUi(self) + self.device_options_model = DeviceOptionsTableModel(self.backend_handler, self) + self.device_options_model.update() + self.ui.tblDevices.setModel(self.device_options_model) + self.ui.tblDevices.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) + + self.ui.tblDevices.setItemDelegateForColumn(1, ComboBoxDelegate(["native", "GNU Radio"])) + self.setAttribute(Qt.WA_DeleteOnClose) layout = QHBoxLayout(self.ui.tab_plugins) self.plugin_controller = PluginFrame(installed_plugins, highlighted_plugins, parent=self) @@ -76,12 +202,6 @@ def __init__(self, installed_plugins, highlighted_plugins=None, parent=None): self.ui.lineEditPython2Interpreter.setCompleter(completer) self.ui.lineEditGnuradioDirectory.setCompleter(completer) - for dev_name in self.backend_handler.DEVICE_NAMES: - self.ui.listWidgetDevices.addItem(dev_name) - - self.set_device_status() - - self.ui.listWidgetDevices.setCurrentRow(0) self.refresh_device_tab() self.create_connects() @@ -108,33 +228,12 @@ def __init__(self, installed_plugins, highlighted_plugins=None, parent=None): except TypeError: pass - @property - def selected_device(self) -> BackendContainer: - try: - devname = self.ui.listWidgetDevices.currentItem().text().lower() - dev_key = self.__get_key_from_device_display_text(devname) - return self.backend_handler.device_backends[dev_key] - except: - return "" - - def __get_key_from_device_display_text(self, displayed_device_name): - displayed_device_name = displayed_device_name.lower() - for key in self.backend_handler.DEVICE_NAMES: - key = key.lower() - if displayed_device_name.startswith(key): - return key - return None - def create_connects(self): self.ui.doubleSpinBoxFuzzingPause.valueChanged.connect(self.on_spinbox_fuzzing_pause_value_changed) self.ui.lineEditPython2Interpreter.editingFinished.connect(self.on_python2_exe_path_edited) self.ui.btnChoosePython2Interpreter.clicked.connect(self.on_btn_choose_python2_interpreter_clicked) self.ui.btnChooseGnuRadioDirectory.clicked.connect(self.on_btn_choose_gnuradio_directory_clicked) self.ui.lineEditGnuradioDirectory.editingFinished.connect(self.on_gnuradio_install_dir_edited) - self.ui.listWidgetDevices.currentRowChanged.connect(self.on_list_widget_devices_current_row_changed) - self.ui.chkBoxDeviceEnabled.clicked.connect(self.on_chk_box_device_enabled_clicked) - self.ui.rbGnuradioBackend.clicked.connect(self.on_rb_gnuradio_backend_clicked) - self.ui.rbNativeBackend.clicked.connect(self.on_rb_native_backend_clicked) self.ui.comboBoxTheme.currentIndexChanged.connect(self.on_combo_box_theme_index_changed) self.ui.checkBoxShowConfirmCloseDialog.clicked.connect(self.on_checkbox_confirm_close_dialog_clicked) self.ui.checkBoxHoldShiftToDrag.clicked.connect(self.on_checkbox_hold_shift_to_drag_clicked) @@ -146,10 +245,10 @@ def create_connects(self): self.ui.radioButtonGnuradioDirectory.clicked.connect(self.on_radio_button_gnuradio_directory_clicked) self.ui.doubleSpinBoxRAMThreshold.valueChanged.connect(self.on_double_spinbox_ram_threshold_value_changed) self.ui.btnRebuildNative.clicked.connect(self.on_btn_rebuild_native_clicked) - self.ui.btnHealthCheck.clicked.connect(self.on_btn_health_check_clicked) self.ui.comboBoxIconTheme.currentIndexChanged.connect(self.on_combobox_icon_theme_index_changed) self.ui.checkBoxMultipleModulations.clicked.connect(self.on_checkbox_multiple_modulations_clicked) self.ui.btnViewBuildLog.clicked.connect(self.on_btn_view_build_log_clicked) + self.ui.labelDeviceMissingInfo.linkActivated.connect(self.on_label_device_missing_info_link_activated) def show_gnuradio_infos(self): self.ui.lineEditPython2Interpreter.setText(self.backend_handler.python2_exe) @@ -163,41 +262,6 @@ def show_gnuradio_infos(self): self.ui.lGnuradioInstalled.setText( self.tr("Gnuradio is not installed or incompatible with python2 interpreter.")) - def show_selected_device_params(self): - if self.ui.listWidgetDevices.currentRow() >= 0: - dev = self.selected_device - - self.ui.chkBoxDeviceEnabled.setEnabled(len(dev.avail_backends) > 0) - self.ui.rbGnuradioBackend.setEnabled(dev.has_gnuradio_backend) - self.ui.rbNativeBackend.setEnabled(dev.has_native_backend) - - self.ui.chkBoxDeviceEnabled.setChecked(dev.is_enabled) - self.ui.rbGnuradioBackend.setChecked(dev.selected_backend == Backends.grc) - self.ui.rbNativeBackend.setChecked(dev.selected_backend == Backends.native) - - if dev.supports_tx and dev.supports_rx: - self.ui.lSupport.setText(self.tr("device supports sending and receiving")) - self.ui.lSupport.setStyleSheet("color: green") - elif dev.supports_rx and not dev.supports_tx: - self.ui.lSupport.setText(self.tr("device supports receiving only")) - self.ui.lSupport.setStyleSheet("color: blue") - elif not dev.supports_rx and dev.supports_tx: - self.ui.lSupport.setText(self.tr("device supports sending only")) - self.ui.lSupport.setStyleSheet("color: blue") - else: - self.ui.lSupport.setText(self.tr("device supports neither sending nor receiving")) - self.ui.lSupport.setStyleSheet("color: red") - - def set_device_status(self): - for i in range(self.ui.listWidgetDevices.count()): - w = self.ui.listWidgetDevices.item(i) - dev_key = self.__get_key_from_device_display_text(w.text()) - is_enabled = self.backend_handler.device_backends[dev_key].is_enabled - selected_backend = self.backend_handler.device_backends[dev_key].selected_backend.value - suffix = self.tr("enabled") if is_enabled else self.tr("disabled") - dev_name = next(dn for dn in BackendHandler.DEVICE_NAMES if dn.lower() == dev_key) - w.setText("{0}\t ({2})\t {1}".format(dev_name, suffix, selected_backend)) - def read_options(self): settings = constants.SETTINGS @@ -213,8 +277,7 @@ def read_options(self): def refresh_device_tab(self): self.backend_handler.get_backends() self.show_gnuradio_infos() - self.show_selected_device_params() - self.set_device_status() + self.device_options_model.update() self.ui.lineEditGnuradioDirectory.setEnabled(self.backend_handler.use_gnuradio_install_dir) self.ui.lineEditPython2Interpreter.setDisabled(self.backend_handler.use_gnuradio_install_dir) @@ -359,36 +422,10 @@ def on_btn_choose_gnuradio_directory_clicked(self): self.ui.lineEditGnuradioDirectory.setText(directory) self.set_gnuradio_status() - @pyqtSlot() - def on_chk_box_device_enabled_clicked(self): - self.selected_device.is_enabled = bool(self.ui.chkBoxDeviceEnabled.isChecked()) - self.selected_device.write_settings() - self.set_device_status() - - @pyqtSlot() - def on_rb_gnuradio_backend_clicked(self): - if Backends.grc in self.selected_device.avail_backends: - self.ui.rbGnuradioBackend.setChecked(True) - self.selected_device.selected_backend = Backends.grc - self.selected_device.write_settings() - self.set_device_status() - - @pyqtSlot() - def on_rb_native_backend_clicked(self): - if Backends.native in self.selected_device.avail_backends: - self.ui.rbNativeBackend.setChecked(True) - self.selected_device.selected_backend = Backends.native - self.selected_device.write_settings() - self.set_device_status() - @pyqtSlot(bool) def on_checkbox_align_labels_clicked(self, checked: bool): constants.SETTINGS.setValue("align_labels", checked) - @pyqtSlot(int) - def on_list_widget_devices_current_row_changed(self, current_row: int): - self.show_selected_device_params() - @pyqtSlot(bool) def on_radio_button_gnuradio_directory_clicked(self, checked: bool): self.set_gnuradio_status() @@ -441,17 +478,6 @@ def on_btn_rebuild_native_clicked(self): self.build_log = p.stdout.read().decode() self.ui.btnViewBuildLog.show() - @pyqtSlot() - def on_btn_health_check_clicked(self): - info = ExtensionHelper.perform_health_check() - info += "\n" + BackendHandler.perform_soundcard_health_check() - - if util.get_shared_library_path(): - info += "\n\n[INFO] Used DLLs from " + util.get_shared_library_path() - - d = util.create_textbox_dialog(info, "Health check for native extensions", self) - d.show() - @pyqtSlot() def on_checkbox_multiple_modulations_clicked(self): constants.SETTINGS.setValue("multiple_modulations", self.ui.checkBoxMultipleModulations.isChecked()) @@ -464,6 +490,21 @@ def on_btn_view_build_log_clicked(self): dialog = util.create_textbox_dialog(self.build_log, "Build log", parent=self) dialog.show() + @pyqtSlot(str) + def on_label_device_missing_info_link_activated(self, link: str): + if link == "health_check": + info = ExtensionHelper.perform_health_check() + info += "\n" + BackendHandler.perform_soundcard_health_check() + + if util.get_shared_library_path(): + if sys.platform == "win32": + info += "\n\n[INFO] Used DLLs from " + util.get_shared_library_path() + else: + info += "\n\n[INFO] Used shared libraries from " + util.get_shared_library_path() + + d = util.create_textbox_dialog(info, "Health check for native extensions", self) + d.show() + @staticmethod def write_default_options(): settings = constants.SETTINGS diff --git a/src/urh/dev/BackendHandler.py b/src/urh/dev/BackendHandler.py index ee12a631e6..c7b46b7460 100644 --- a/src/urh/dev/BackendHandler.py +++ b/src/urh/dev/BackendHandler.py @@ -284,6 +284,14 @@ def get_backends(self): container = BackendContainer(device_name.lower(), ab, rx_suprt, tx_suprt) self.device_backends[device_name.lower()] = container + def get_key_from_device_display_text(self, displayed_device_name): + displayed_device_name = displayed_device_name.lower() + for key in self.DEVICE_NAMES: + key = key.lower() + if displayed_device_name.startswith(key): + return key + return None + @staticmethod def perform_soundcard_health_check(): result = "SoundCard -- " diff --git a/src/urh/ui/ui_options.py b/src/urh/ui/ui_options.py index c4957c4788..5150ec21f1 100644 --- a/src/urh/ui/ui_options.py +++ b/src/urh/ui/ui_options.py @@ -9,7 +9,7 @@ class Ui_DialogOptions(object): def setupUi(self, DialogOptions): DialogOptions.setObjectName("DialogOptions") - DialogOptions.resize(773, 749) + DialogOptions.resize(788, 822) icon = QtGui.QIcon.fromTheme("configure") DialogOptions.setWindowIcon(icon) self.verticalLayout_6 = QtWidgets.QVBoxLayout(DialogOptions) @@ -103,7 +103,7 @@ def setupUi(self, DialogOptions): self.scrollAreaSpectrogramColormap.setWidgetResizable(True) self.scrollAreaSpectrogramColormap.setObjectName("scrollAreaSpectrogramColormap") self.scrollAreaWidgetSpectrogramColormapContents = QtWidgets.QWidget() - self.scrollAreaWidgetSpectrogramColormapContents.setGeometry(QtCore.QRect(0, 0, 98, 28)) + self.scrollAreaWidgetSpectrogramColormapContents.setGeometry(QtCore.QRect(0, 0, 708, 447)) self.scrollAreaWidgetSpectrogramColormapContents.setObjectName("scrollAreaWidgetSpectrogramColormapContents") self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.scrollAreaWidgetSpectrogramColormapContents) self.verticalLayout_4.setObjectName("verticalLayout_4") @@ -147,54 +147,28 @@ def setupUi(self, DialogOptions): self.tabDevices.setObjectName("tabDevices") self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.tabDevices) self.verticalLayout_8.setObjectName("verticalLayout_8") - self.horizontalLayout = QtWidgets.QHBoxLayout() - self.horizontalLayout.setObjectName("horizontalLayout") - self.listWidgetDevices = QtWidgets.QListWidget(self.tabDevices) - self.listWidgetDevices.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) - self.listWidgetDevices.setAlternatingRowColors(True) - self.listWidgetDevices.setViewMode(QtWidgets.QListView.ListMode) - self.listWidgetDevices.setObjectName("listWidgetDevices") - self.horizontalLayout.addWidget(self.listWidgetDevices) - self.verticalLayout_7 = QtWidgets.QVBoxLayout() - self.verticalLayout_7.setObjectName("verticalLayout_7") - self.chkBoxDeviceEnabled = QtWidgets.QCheckBox(self.tabDevices) - self.chkBoxDeviceEnabled.setObjectName("chkBoxDeviceEnabled") - self.verticalLayout_7.addWidget(self.chkBoxDeviceEnabled) - self.rbNativeBackend = QtWidgets.QRadioButton(self.tabDevices) - self.rbNativeBackend.setObjectName("rbNativeBackend") - self.verticalLayout_7.addWidget(self.rbNativeBackend) - self.rbGnuradioBackend = QtWidgets.QRadioButton(self.tabDevices) - self.rbGnuradioBackend.setObjectName("rbGnuradioBackend") - self.verticalLayout_7.addWidget(self.rbGnuradioBackend) - self.btnHealthCheck = QtWidgets.QPushButton(self.tabDevices) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.btnHealthCheck.sizePolicy().hasHeightForWidth()) - self.btnHealthCheck.setSizePolicy(sizePolicy) - icon = QtGui.QIcon.fromTheme("heart") - self.btnHealthCheck.setIcon(icon) - self.btnHealthCheck.setObjectName("btnHealthCheck") - self.verticalLayout_7.addWidget(self.btnHealthCheck) - spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout_7.addItem(spacerItem2) - self.horizontalLayout.addLayout(self.verticalLayout_7) - self.verticalLayout_8.addLayout(self.horizontalLayout) - self.lSupport = QtWidgets.QLabel(self.tabDevices) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.lSupport.sizePolicy().hasHeightForWidth()) - self.lSupport.setSizePolicy(sizePolicy) + self.labelInfoDeviceTable = QtWidgets.QLabel(self.tabDevices) + font = QtGui.QFont() + font.setItalic(True) + self.labelInfoDeviceTable.setFont(font) + self.labelInfoDeviceTable.setToolTip("") + self.labelInfoDeviceTable.setWordWrap(True) + self.labelInfoDeviceTable.setObjectName("labelInfoDeviceTable") + self.verticalLayout_8.addWidget(self.labelInfoDeviceTable) + self.tblDevices = QtWidgets.QTableView(self.tabDevices) + self.tblDevices.setAlternatingRowColors(True) + self.tblDevices.setShowGrid(False) + self.tblDevices.setObjectName("tblDevices") + self.tblDevices.horizontalHeader().setDefaultSectionSize(200) + self.tblDevices.verticalHeader().setVisible(False) + self.verticalLayout_8.addWidget(self.tblDevices) + self.labelDeviceMissingInfo = QtWidgets.QLabel(self.tabDevices) font = QtGui.QFont() - font.setBold(True) font.setItalic(False) - font.setWeight(75) - self.lSupport.setFont(font) - self.lSupport.setStyleSheet("color: green") - self.lSupport.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.lSupport.setObjectName("lSupport") - self.verticalLayout_8.addWidget(self.lSupport) + self.labelDeviceMissingInfo.setFont(font) + self.labelDeviceMissingInfo.setWordWrap(True) + self.labelDeviceMissingInfo.setObjectName("labelDeviceMissingInfo") + self.verticalLayout_8.addWidget(self.labelDeviceMissingInfo) self.line = QtWidgets.QFrame(self.tabDevices) self.line.setFrameShape(QtWidgets.QFrame.HLine) self.line.setFrameShadow(QtWidgets.QFrame.Sunken) @@ -331,12 +305,8 @@ def retranslateUi(self, DialogOptions): self.btnRemoveLabeltype.setText(_translate("DialogOptions", "...")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabFieldtypes), _translate("DialogOptions", "Fieldtypes")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_plugins), _translate("DialogOptions", "Plugins")) - self.chkBoxDeviceEnabled.setText(_translate("DialogOptions", "Enabled")) - self.rbNativeBackend.setText(_translate("DialogOptions", "&Native backend (recommended)")) - self.rbGnuradioBackend.setText(_translate("DialogOptions", "&Gnuradio backend")) - self.btnHealthCheck.setToolTip(_translate("DialogOptions", "Perform a health check for native device extensions.")) - self.btnHealthCheck.setText(_translate("DialogOptions", "Health Check")) - self.lSupport.setText(_translate("DialogOptions", "device supports sending and receiving")) + self.labelInfoDeviceTable.setText(_translate("DialogOptions", "

Use the checkboxes in the table below to choose device backends and enable or disable devices. Disabled devices will not show up in device related dialogs such as send or receive.

")) + self.labelDeviceMissingInfo.setText(_translate("DialogOptions", "

Missing a native backend? Perform a health check! If GNU Radio backend is not available double check the GNU Radio settings below.

")) self.groupBoxNativeOptions.setTitle(_translate("DialogOptions", "Native options")) self.labelRebuildNativeStatus.setText(_translate("DialogOptions", "Rebuild new device extensions. Please restart URH to use them.")) self.labelLibDirs.setText(_translate("DialogOptions", "Library directories:")) diff --git a/tests/.coveragerc b/tests/.coveragerc index 40eb2407a7..f932c32e3a 100644 --- a/tests/.coveragerc +++ b/tests/.coveragerc @@ -35,3 +35,4 @@ exclude_lines = def export_to_fta def export_demodulated def main + class DeviceOptionsTableModel diff --git a/tests/test_options_gui.py b/tests/test_options_gui.py index b221381068..e55b0dadb9 100644 --- a/tests/test_options_gui.py +++ b/tests/test_options_gui.py @@ -1,5 +1,6 @@ from tests.QtTestCase import QtTestCase from urh.controller.dialogs.OptionsDialog import OptionsDialog +from urh.dev.BackendHandler import BackendHandler from urh.models.PluginListModel import PluginListModel from urh.plugins.PluginManager import PluginManager @@ -43,13 +44,7 @@ def test_device_tab(self): self.dialog.ui.tabWidget.setCurrentIndex(4) self.assertEqual(self.dialog.ui.tabWidget.tabText(4), "Device") - self.dialog.ui.listWidgetDevices.setCurrentRow(0) - dev_name = self.dialog.ui.listWidgetDevices.currentItem().text() - for i in range(1, self.dialog.ui.listWidgetDevices.count()): - self.dialog.ui.listWidgetDevices.setCurrentRow(i) - self.assertNotEqual(dev_name, self.dialog.ui.listWidgetDevices.currentItem().text()) - dev_name = self.dialog.ui.listWidgetDevices.currentItem().text() - + self.assertEqual(self.dialog.ui.tblDevices.model().rowCount(), len(BackendHandler.DEVICE_NAMES)) self.dialog.ui.radioButtonPython2Interpreter.click() self.assertTrue(self.dialog.ui.lineEditPython2Interpreter.isEnabled())