diff --git a/download_window.py b/download_window.py
index 764de5d..9ba58e7 100644
--- a/download_window.py
+++ b/download_window.py
@@ -59,11 +59,11 @@ class DownloadWindow(QWidget, Ui_Download_window):
@pyqtSlot()
def wait_close(self):
- if self.download_thread.status == ThreadStatus.ok:
+ if self.download_thread.status == ThreadStatus.OK:
self.close()
- elif self.download_thread.status == ThreadStatus.no_connection_err:
+ elif self.download_thread.status == ThreadStatus.NO_CONNECTION_ERR:
self.show_no_connection_warning()
- elif self.download_thread.status == ThreadStatus.bad_download_err:
+ elif self.download_thread.status == ThreadStatus.BAD_DOWNLOAD_ERR:
self.show_bad_download_warning
else:
self.close()
diff --git a/main.py b/main.py
index 9423216..8c6c90f 100644
--- a/main.py
+++ b/main.py
@@ -10,8 +10,10 @@ from PyQt5.QtWidgets import (QMainWindow,
QMessageBox,
qApp,
QDesktopWidget,
- QListWidgetItem,)
-from PyQt5.QtGui import QPixmap
+ QListWidgetItem,
+ QTreeView,
+ QTreeWidgetItem)
+from PyQt5.QtGui import QPixmap, QStandardItemModel, QStandardItem
from PyQt5 import uic
from PyQt5.QtCore import (QFileInfo,
QSize,
@@ -35,7 +37,6 @@ class MyApp(QMainWindow, Ui_MainWindow):
self.download_window = DownloadWindow()
self.actionExit.triggered.connect(qApp.quit)
self.action_update_database.triggered.connect(self.download_db)
- self.db_version = None
self.db = None
self.current_signal_name = ''
self.signal_names = []
@@ -267,6 +268,17 @@ class MyApp(QMainWindow, Ui_MainWindow):
self.url_button.clicked.connect(self.go_to_web_page_signal)
+ # Set modulation TreeView
+
+ self.set_mode_tree_widget()
+ self.mode_tree_widget.itemSelectionChanged.connect(self.manage_mode_selections)
+ self.reset_mode_filters_btn.clicked.connect(self.reset_mode_filters)
+ self.apply_remove_mode_filter_btn.set_texts("Apply", "Remove")
+ self.apply_remove_mode_filter_btn.set_slave_filters([self.mode_tree_widget])
+ self.apply_remove_mode_filter_btn.clicked.connect(self.display_signals)
+ self.reset_mode_filters_btn.clicked.connect(self.reset_mode_filters)
+
+# ##########################################################################################
self.show()
self.load_db()
@@ -279,7 +291,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
self.volume,
self.audio_progress,
Constants.data_folder,
- Constants.audio_folder)
+ Constants.audio_folder) # Da togliere/////////////////
BandLabel = namedtuple("BandLabel", ["left", "center", "right"])
self.band_labels = [
@@ -296,6 +308,24 @@ class MyApp(QMainWindow, Ui_MainWindow):
BandLabel(self.ehf_left, self.ehf, self.ehf_right),
]
+ def set_mode_tree_widget(self):
+ for parent, children in Constants.modes.items():
+ iparent = QTreeWidgetItem([parent])
+ self.mode_tree_widget.addTopLevelItem(iparent)
+ for child in children:
+ ichild = QTreeWidgetItem([child])
+ iparent.addChild(ichild)
+ self.mode_tree_widget.expandAll()
+
+ def manage_mode_selections(self):
+ selected_items = self.mode_tree_widget.selectedItems()
+ parents = Constants.modes.keys()
+ for parent in parents:
+ for item in selected_items:
+ if parent == item.text(0):
+ for i in range(len(Constants.modes[parent])):
+ item.child(i).setSelected(True)
+
def set_initial_size(self):
"""
Function to handle high resolution screens. The function sets bigger sizes
@@ -494,7 +524,8 @@ class MyApp(QMainWindow, Ui_MainWindow):
if text.lower() in signal.lower() and \
self.frequency_filters_ok(signal) and \
self.band_filters_ok(signal) and \
- self.category_filters_ok(signal):
+ self.category_filters_ok(signal) and \
+ self.mode_filters_ok(signal):
self.result_list.addItem(signal)
available_signals += 1
self.update_status_tip(available_signals)
@@ -552,6 +583,13 @@ class MyApp(QMainWindow, Ui_MainWindow):
f.setChecked(False) if f.isChecked() else None
self.cat_at_least_one.setChecked(True)
+ def reset_mode_filters(self):
+ if self.apply_remove_mode_filter_btn.isChecked():
+ self.apply_remove_mode_filter_btn.setChecked(False)
+ self.apply_remove_mode_filter_btn.clicked.emit()
+ for item in self.mode_tree_widget.selectedItems():
+ item.setSelected(False)
+
def frequency_filters_ok(self, signal_name):
if not self.apply_remove_freq_filter_btn.isChecked():
return True
@@ -632,6 +670,22 @@ class MyApp(QMainWindow, Ui_MainWindow):
else:
return cat_checked == positive_cases and cat_checked > 0
+ def mode_filters_ok(self, signal_name):
+ if not self.apply_remove_mode_filter_btn.isChecked():
+ return True
+ selected_items = [item for item in self.mode_tree_widget.selectedItems()]
+ selected_items_text = [i.text(0) for i in selected_items]
+ parents = [item for item in selected_items_text if item in Constants.modes.keys()]
+ children = [item for item in selected_items_text if item not in parents]
+ signal_mode = self.db.at[signal_name, "mode"]
+ ok = []
+ for item in selected_items:
+ if item.text(0) in parents:
+ ok.append(item.text(0) in signal_mode)
+ elif not item.parent().isSelected():
+ ok.append(item.text(0) == signal_mode)
+ return any(ok)
+
@staticmethod
def filters_ok(spinbox, filter_unit, confidence, sign = 1):
band_filter = spinbox.value() * Constants.conversion_factors[filter_unit.currentText()]
@@ -779,6 +833,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
self.reset_frequency_filters_btn.clicked.emit()
self.reset_band_filters_btn.clicked.emit()
self.reset_cat_filters_btn.clicked.emit()
+ self.reset_mode_filters_btn.clicked.emit()
@pyqtSlot()
def go_to_web_page_signal(self):
diff --git a/main_window.ui b/main_window.ui
index 32fcc1d..aaae821 100644
--- a/main_window.ui
+++ b/main_window.ui
@@ -323,7 +323,7 @@ QPushButton:!enabled {
QTabWidget::Rounded
- 0
+ 1
true
@@ -1962,7 +1962,7 @@ QPushButton:checked {
- 0
+ 3
true
@@ -3691,6 +3691,142 @@ Inactive
Mode
+
+ -
+
+
+ QWidget#mode_filter_container {
+ border: 1px solid gray;
+ border-radius: 15px;
+}
+
+QWidget#FM_container, QWidget#SK_container, QWidget#SB_container{
+ border: 1px solid gray;
+ border-radius: 10px;
+}
+
+QWidget#xFM_container, QWidget#xSK_container, QWidget#xSB_container{
+ border: 1px solid gray;
+ border-radius: 8px;
+}
+
+
+
-
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Include unknown modulations
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 12
+ 75
+ true
+
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ QAbstractItemView::MultiSelection
+
+
+ QAbstractItemView::SelectItems
+
+
+ true
+
+
+ true
+
+
+ 1
+
+
+
+ 1
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Apply
+
+
+ true
+
+
+
+ -
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Reset
+
+
+
+
diff --git a/threads.py b/threads.py
index 86596a0..99db647 100644
--- a/threads.py
+++ b/threads.py
@@ -9,15 +9,15 @@ from PyQt5.QtCore import QThread
from utilities import checksum_ok, Constants
class ThreadStatus(Enum):
- ok = auto()
- no_connection_err = auto()
- no_file_err = auto()
- bad_download_err = auto()
+ OK = auto()
+ NO_CONNECTION_ERR = auto()
+ UNKNOWN_ERR = auto()
+ BAD_DOWNLOAD_ERR = auto()
class DownloadThread(QThread):
def __init__(self):
super().__init__()
- self.__status = ThreadStatus.ok
+ self.__status = ThreadStatus.OK
self.reason = 0
@property
@@ -34,14 +34,14 @@ class DownloadThread(QThread):
# db = urllib.request.urlopen(Constants.db_location)
# raise urllib.error.URLError('Test')
except urllib3.exceptions.MaxRetryError: # No internet connection.
- self.__status = ThreadStatus.no_connection_err
+ self.__status = ThreadStatus.NO_CONNECTION_ERR
return
if db.status != 200:
self.reason = db.reason
- self.__status = ThreadStatus.bad_download_err
+ self.__status = ThreadStatus.BAD_DOWNLOAD_ERR
return
if not checksum_ok(db.data, "folder"):
- self.__status = ThreadStatus.bad_download_err
+ self.__status = ThreadStatus.BAD_DOWNLOAD_ERR
return
if os.path.exists(Constants.data_folder):
rmtree(Constants.data_folder)
@@ -50,4 +50,4 @@ class DownloadThread(QThread):
with ZipFile(BytesIO(db.data)) as zipped:
zipped.extractall()
except:
- self.__status = ThreadStatus.bad_file_err
+ self.__status = ThreadStatus.UNKNOWN_ERR
diff --git a/utilities.py b/utilities.py
index a787a69..4196783 100644
--- a/utilities.py
+++ b/utilities.py
@@ -36,6 +36,16 @@ class Constants(object):
active_color = _ReadOnlyProperty("#39eaff")
inactive_color = _ReadOnlyProperty("#9f9f9f")
conversion_factors = _ReadOnlyProperty({"Hz":1, "kHz":1000, "MHz":1000000, "GHz":1000000000})
+ modes = _ReadOnlyProperty({"FM": ["NFM", "WFM"],
+ "AM": [],
+ "CW": [],
+ "SK": ["FSK", "PSK", "MSK"],
+ "SB": ["LSB", "USB", "DSB"],
+ "Chirp Spread Spectrum": [],
+ "FHSS-TDM": [],
+ "RAW": [],
+ "SC-FDMA": [],}
+ )
def checksum_ok(data, what):