def toggle_range(self): ''' toggles whether the range is enabled or not ''' if self.limitRange.isChecked(): self.limitRange.setText('Cut') if self.audioStreams.count() > 0: duration_ms = int(self.__stream_duration_micros[ self.audioStreams.currentIndex()] / 1000) if duration_ms > 1: from model.report import block_signals with block_signals(self.rangeFrom): self.rangeFrom.setTimeRange( QTime.fromMSecsSinceStartOfDay(0), QTime.fromMSecsSinceStartOfDay(duration_ms - 1)) self.rangeFrom.setTime( QTime.fromMSecsSinceStartOfDay(0)) self.rangeFrom.setEnabled(True) self.rangeSeparatorLabel.setEnabled(True) with block_signals(self.rangeTo): self.rangeTo.setEnabled(True) self.rangeTo.setTimeRange( QTime.fromMSecsSinceStartOfDay(1), QTime.fromMSecsSinceStartOfDay(duration_ms)) self.rangeTo.setTime( QTime.fromMSecsSinceStartOfDay(duration_ms)) else: self.limitRange.setText('Enable') self.rangeFrom.setEnabled(False) self.rangeSeparatorLabel.setEnabled(False) self.rangeTo.setEnabled(False) if self.__executor is not None: self.__executor.start_time_ms = 0 self.__executor.end_time_ms = 0
def __propagate_y_range(self, _, range): ''' passes the updates range to the fields ''' from model.report import block_signals with block_signals(self.__y_min): self.__y_min.setValue(range[0]) with block_signals(self.__y_max): self.__y_max.setValue(range[1])
def __init_channel_count_fields(self, channels, lfe_index=0): from model.report import block_signals with block_signals(self.lfeChannelIndex): self.lfeChannelIndex.setMaximum(channels) self.lfeChannelIndex.setValue(lfe_index) with block_signals(self.channelCount): self.channelCount.setMaximum(channels) self.channelCount.setValue(channels)
def __select_filter(self, selected_filter): ''' Refreshes the params and display with the selected filter ''' from model.report import block_signals self.__selected_id = selected_filter.id # populate the fields with values if we're editing an existing filter if hasattr(selected_filter, 'gain'): with block_signals(self.filterGain): self.filterGain.setValue(selected_filter.gain) if hasattr(selected_filter, 'q'): with block_signals(self.filterQ): self.filterQ.setValue(selected_filter.q) if hasattr(selected_filter, 'freq'): with block_signals(self.freq): self.freq.setValue(selected_filter.freq) if hasattr(selected_filter, 'order'): with block_signals(self.filterOrder): self.filterOrder.setValue(selected_filter.order) if hasattr(selected_filter, 'type'): displayName = 'Butterworth' if selected_filter.type is FilterType.BUTTERWORTH else 'Linkwitz-Riley' with block_signals(self.passFilterType): self.passFilterType.setCurrentIndex( self.passFilterType.findText(displayName)) if hasattr(selected_filter, 'count') and issubclass( type(selected_filter), Shelf): with block_signals(self.filterCount): self.filterCount.setValue(selected_filter.count) with block_signals(self.filterType): self.filterType.setCurrentText(selected_filter.display_name) # configure visible/enabled fields for the current filter type self.enableFilterParams() with block_signals(self.freq): self.freq.setMaximum(self.__signal.fs / 2.0)
def __reset_time(time_widget): ''' resets and disables the supplied time field. ''' from model.report import block_signals with block_signals(time_widget): time_widget.clearMaximumDateTime() time_widget.setTime(QTime()) time_widget.setEnabled(False)
def filter_content_type(self, txt: str): ''' filters the selected content types to match the given string ''' with block_signals(self.contentTypeFilter): for i in range(self.contentTypeFilter.count()): item: QListWidgetItem = self.contentTypeFilter.item(i) item.setSelected( len(txt.strip()) == 0 or item.text().casefold().find(txt.casefold()) > -1) self.apply_filter()
def filter_max_year(self, max_year: int): ''' sets the max year filter ''' min_year = self.yearMinFilter.value() with block_signals(self.yearFilter): for i in range(self.yearFilter.count()): item: QListWidgetItem = self.yearFilter.item(i) val = int(item.text()) item.setSelected(min_year <= val <= max_year) self.yearMinFilter.setMaximum(max_year - 1) self.apply_filter()
def __ensure_filter_is_selected(self, active_model, active_view): ''' Filter model resets the model on every change, this clears the selection so we have to restore that selection to ensure the row remains visibly selected while also blocking signals to avoid a pointless update of the fields. ''' for idx, f in enumerate(active_model): if f.id == self.__selected_id: from model.report import block_signals with block_signals(active_view): active_view.selectRow(idx)
def __init_resolution_selector(self, signal): ''' sets up the resolution selector based on the size of the underlying file. ''' from model.report import block_signals with block_signals(self.analysisResolution): self.analysisResolution.clear() default_length = signal.get_segment_length() for m in MULTIPLIERS: freq_res = float(signal.fs) / (default_length * m) time_res = (m * default_length) / signal.fs self.analysisResolution.addItem( f"{freq_res:.3f} Hz / {time_res:.3f} s") self.analysisResolution.setCurrentIndex(2)
def __init__(self, preferences, signal_model, allow_load=True): super(AnalyseSignalDialog, self).__init__() self.setupUi(self) self.setWindowFlags(self.windowFlags() | Qt.WindowSystemMenuHint | Qt.WindowMinMaxButtonsHint) self.__preferences = preferences self.filePicker.setIcon(qta.icon('fa5s.folder-open')) self.showLimitsButton.setIcon(qta.icon('fa5s.arrows-alt')) self.updateChart.setIcon(qta.icon('fa5s.sync')) self.saveChart.setIcon(qta.icon('fa5s.save')) self.saveLayout.setIcon(qta.icon('fa5s.save')) self.lockButton.setIcon(qta.icon('fa5s.lock-open')) self.minFreq.setValue(preferences.get(GRAPH_X_MIN)) self.maxUnfilteredFreq.setValue(preferences.get(GRAPH_X_MAX)) self.__info = None self.__signal = None self.__filtered_signals = {} self.__spectrum_analyser = MaxSpectrumByTime(self.spectrumChart, self.__preferences, self) self.__waveform_analyser = Waveform(self.waveformChart, self) self.__signal_model = signal_model from model.report import block_signals with block_signals(self.markerType): self.markerType.addItem(POINT) self.markerType.addItem(ELLIPSE) self.markerType.addItem(SPECTROGRAM_CONTOURED) self.markerType.addItem(SPECTROGRAM_FLAT) self.markerType.setCurrentText(POINT) self.updateChart.setEnabled(False) self.__duration = 0 self.loadButton.setEnabled(False) self.compareSignalsButton.setEnabled(False) self.__init_from_prefs() self.__clear() self.__allow_load = allow_load self.hideSidebar.setVisible(False) if allow_load: self.__init_for_load() else: self.__init_for_compare()
def refresh_selector(self): ''' Updates the selector with the available signals. ''' currently_selected = self.__selector.currentText() from model.report import block_signals with block_signals(self.__selector): self.__selector.clear() self.__selector.addItem(' ') for bm in self.__signal_model.bass_managed_signals: self.__selector.addItem(f"(BM) {bm.name}") for c in bm.channels: if c.signal is not None: self.__selector.addItem(c.name) else: self.__selector.addItem(f"-- {c.name}") for s in self.__signal_model.non_bm_signals: if s.signal is not None: self.__selector.addItem(s.name) else: self.__selector.addItem(f"-- {s.name}") idx = self.__selector.findText(currently_selected) if idx > -1: self.__selector.setCurrentIndex(idx) else: self.__reset_controls()
def update_waveform(self, signal_name): ''' displays the waveform for the selected signal ''' if self.__current_signal is not None: self.__current_signal.unregister_listener(self.on_filter_update) self.__current_signal = self.__get_signal_data(signal_name) if self.__current_signal is None: self.__reset_time(self.__start_time) self.__reset_time(self.__end_time) self.__load_signal_btn.setEnabled(True) self.__bm_headroom.setEnabled(False) self.__bm_lpf_position.setEnabled(False) self.__bm_hpf.setEnabled(False) self.__bm_hpf.setChecked(False) self.__bm_clip_before.setEnabled(False) self.__bm_clip_after.setEnabled(False) self.__show_stats_btn.setEnabled(False) self.__reset_controls() self.__active_signal = None else: self.__load_signal_btn.setEnabled(False) self.__show_stats_btn.setEnabled(True) metadata = self.__current_signal.metadata if metadata is not None: if SIGNAL_CHANNEL in metadata: self.__source_file.setText( f"{metadata[SIGNAL_SOURCE_FILE]} - C{metadata[SIGNAL_CHANNEL]}" ) else: self.__source_file.setText(metadata[SIGNAL_SOURCE_FILE]) from model.report import block_signals if signal_name.startswith('(BM) '): with block_signals(self.__bm_hpf): self.__bm_hpf.setEnabled(False) self.__bm_hpf.setChecked(False) with block_signals(self.__bm_headroom): self.__bm_headroom.setEnabled(True) self.__bm_headroom.setCurrentText( self.__current_signal.bm_headroom_type) with block_signals(self.__bm_lpf_position): self.__bm_lpf_position.setEnabled(True) self.__bm_lpf_position.setCurrentText( self.__current_signal.bm_lpf_position) with block_signals(self.__bm_clip_before): self.__bm_clip_before.setEnabled(True) self.__bm_clip_before.setChecked( self.__current_signal.clip_before) with block_signals(self.__bm_clip_after): self.__bm_clip_after.setEnabled(True) self.__bm_clip_after.setChecked( self.__current_signal.clip_after) else: if signal_name.endswith('LFE'): with block_signals(self.__bm_hpf): self.__bm_hpf.setEnabled(False) self.__bm_hpf.setChecked(False) else: with block_signals(self.__bm_hpf): self.__bm_hpf.setEnabled(True) self.__bm_hpf.setChecked( self.__current_signal.high_pass) self.__bm_headroom.setEnabled(False) self.__bm_lpf_position.setEnabled(False) self.__bm_clip_before.setEnabled(False) self.__bm_clip_after.setEnabled(False) self.__current_signal.register_listener(self.on_filter_update) self.__start_time.setEnabled(True) duration = QTime(0, 0, 0).addMSecs( self.__current_signal.duration_seconds * 1000.0) self.__start_time.setMaximumTime(duration) self.__end_time.setEnabled(True) self.__end_time.setMaximumTime(duration) self.__end_time.setTime(duration) self.toggle_filter( Qt.Checked if self.__is_filtered.isChecked() else Qt.Unchecked)
def __on_mso(self, mso): ''' Handles mso message from the device sent after a getmso is issued. :param mso: the mso. ''' version = mso['versions']['swVer'] version = version[1:] if version[0] == 'v' or version[0] == 'V' else version try: self.__supports_shelf = semver.parse_version_info(version) > semver.parse_version_info('1.4.0') except: logger.error(f"Unable to parse version {mso['versions']['swVer']}") result = QMessageBox.question(self, 'Supports Shelf Filters?', f"Reported software version is " f"\n\n {version}" f"\n\nDoes this version support shelf filters?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) self.__supports_shelf = result == QMessageBox.Yes speakers = mso['speakers']['groups'] channels = ['lf', 'rf'] for group in [s for s, v in speakers.items() if 'present' in v and v['present'] is True]: if group[0:2] == 'lr' and len(group) > 2: channels.append('l' + group[2:]) channels.append('r' + group[2:]) else: channels.append(group) peq_slots = mso['peq']['slots'] class Filters(dict): def __init__(self): super().__init__() def __missing__(self, key): self[key] = CompleteFilter(fs=HTP1_FS, sort_by_id=True) return self[key] tmp1 = Filters() tmp2 = Filters() raw_filters = {c: [] for c in channels} unknown_channels = set() for idx, s in enumerate(peq_slots): for c in channels: if c in s['channels']: tmp1[c].save(self.__convert_to_filter(s['channels'][c], idx)) tmp2[c].save(self.__convert_to_filter(s['channels'][c], idx)) raw_filters[c].append(s['channels'][c]) else: unknown_channels.add(c) if unknown_channels: peq_channels = peq_slots[0]['channels'].keys() logger.error(f"Unknown channels encountered [peq channels: {peq_channels}, unknown: {unknown_channels}]") from model.report import block_signals with block_signals(self.filtersetSelector): now = self.filtersetSelector.currentText() self.filtersetSelector.clear() now_idx = -1 for idx, c in enumerate(channels): self.filtersetSelector.addItem(c) if c == now: now_idx = idx if now_idx > -1: self.filtersetSelector.setCurrentIndex(now_idx) self.__filters_by_channel = tmp1 self.__current_device_filters_by_channel = tmp2 self.__filters.filter = self.__filters_by_channel[self.filtersetSelector.itemText(0)] if not self.__channel_to_signal: self.load_from_signals() self.filterView.selectRow(0) self.__magnitude_model.redraw() self.syncStatus.setIcon(qta.icon('fa5s.link')) self.__last_received_msoupdate = None self.__last_requested_msoupdate = None self.showDetailsButton.setEnabled(False)