예제 #1
0
    def __init__(self, project_manager, parent=None):
        super().__init__(parent)
        self.ui = Ui_Interpretation()
        self.ui.setupUi(self)
        self.splitter = QSplitter()
        self.splitter.setStyleSheet(
            "QSplitter::handle:vertical {\nmargin: 4px 0px; background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, \nstop:0 rgba(255, 255, 255, 0), \nstop:0.5 rgba(100, 100, 100, 100), \nstop:1 rgba(255, 255, 255, 0));\n	image: url(:/icons/data/icons/splitter_handle.png);\n}"
        )
        self.splitter.setOrientation(Qt.Vertical)
        self.splitter.setChildrenCollapsible(True)
        self.splitter.setHandleWidth(6)

        placeholder_widget = QWidget()
        placeholder_widget.setSizePolicy(QSizePolicy.Maximum,
                                         QSizePolicy.Maximum)
        self.undo_stack = QUndoStack()
        self.project_manager = project_manager

        self.splitter.addWidget(placeholder_widget)
        self.signal_vlay = QVBoxLayout()
        self.signal_vlay.setContentsMargins(0, 0, 0, 0)
        self.signal_vlay.addWidget(self.splitter)
        self.ui.scrlAreaSignals.setLayout(self.signal_vlay)

        self.drag_pos = None
예제 #2
0
    def __init__(self, project_manager, parent=None):
        super().__init__(parent)
        self.ui = Ui_Interpretation()
        self.ui.setupUi(self)

        self.ui.placeholderLabel.setVisible(False)
        self.getting_started_status = None
        self.__set_getting_started_status(True)

        self.undo_stack = QUndoStack()
        self.project_manager = project_manager

        self.drag_pos = None
예제 #3
0
    def __init__(self, project_manager, parent=None):
        super().__init__(parent)
        self.ui = Ui_Interpretation()
        self.ui.setupUi(self)
        self.splitter = QSplitter()
        self.splitter.setOrientation(Qt.Vertical)
        self.splitter.setChildrenCollapsible(True)
        self.placeholder_widget = QWidget()
        self.placeholder_widget.setSizePolicy(QSizePolicy.Maximum,
                                              QSizePolicy.Maximum)
        self.undo_stack = QUndoStack()
        self.project_manager = project_manager

        self.splitter.addWidget(self.placeholder_widget)
        self.signal_vlay = QVBoxLayout()
        self.signal_vlay.addWidget(self.splitter)
        self.ui.scrlAreaSignals.setLayout(self.signal_vlay)

        self.drag_pos = None
예제 #4
0
    def __init__(self, project_manager, parent=None):
        super().__init__(parent)
        self.ui = Ui_Interpretation()
        self.ui.setupUi(self)

        util.set_splitter_stylesheet(self.ui.splitter)

        self.ui.placeholderLabel.setVisible(False)
        self.getting_started_status = None
        self.__set_getting_started_status(True)

        self.undo_stack = QUndoStack()
        self.project_manager = project_manager

        self.drag_pos = None
예제 #5
0
    def __init__(self, project_manager, parent=None):
        super().__init__(parent)
        self.ui = Ui_Interpretation()
        self.ui.setupUi(self)
        self.splitter = QSplitter()
        self.splitter.setStyleSheet("QSplitter::handle:vertical {\nmargin: 4px 0px; background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, \nstop:0 rgba(255, 255, 255, 0), \nstop:0.5 rgba(100, 100, 100, 100), \nstop:1 rgba(255, 255, 255, 0));\n	image: url(:/icons/data/icons/splitter_handle_horizontal.svg);\n}")
        self.splitter.setOrientation(Qt.Vertical)
        self.splitter.setChildrenCollapsible(True)
        self.splitter.setHandleWidth(6)

        placeholder_widget = QWidget()
        placeholder_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        self.undo_stack = QUndoStack()
        self.project_manager = project_manager

        self.splitter.addWidget(placeholder_widget)
        self.signal_vlay = QVBoxLayout()
        self.signal_vlay.setContentsMargins(0,0,0,0)
        self.signal_vlay.addWidget(self.splitter)
        self.ui.scrlAreaSignals.setLayout(self.signal_vlay)

        self.drag_pos = None
예제 #6
0
class SignalTabController(QWidget):
    frame_closed = pyqtSignal(SignalFrame)
    not_show_again_changed = pyqtSignal()
    signal_created = pyqtSignal(int, Signal)
    files_dropped = pyqtSignal(list)
    frame_was_dropped = pyqtSignal(int, int)

    @property
    def num_frames(self):
        return len(self.signal_frames)

    @property
    def signal_frames(self):
        """

        :rtype: list of SignalFrame
        """
        splitter = self.ui.splitter
        return [
            splitter.widget(i) for i in range(splitter.count())
            if isinstance(splitter.widget(i), SignalFrame)
        ]

    @property
    def signal_undo_stack(self):
        return self.undo_stack

    def __init__(self, project_manager, parent=None):
        super().__init__(parent)
        self.ui = Ui_Interpretation()
        self.ui.setupUi(self)

        util.set_splitter_stylesheet(self.ui.splitter)

        self.ui.placeholderLabel.setVisible(False)
        self.getting_started_status = None
        self.__set_getting_started_status(True)

        self.undo_stack = QUndoStack()
        self.project_manager = project_manager

        self.drag_pos = None

    def on_files_dropped(self, files):
        self.files_dropped.emit(files)

    def close_frame(self, frame: SignalFrame):
        self.frame_closed.emit(frame)

    def add_signal_frame(self, proto_analyzer, index=-1):
        self.__set_getting_started_status(False)
        sig_frame = SignalFrame(proto_analyzer,
                                self.undo_stack,
                                self.project_manager,
                                parent=self)
        sframes = self.signal_frames

        if len(proto_analyzer.signal.filename) == 0:
            # new signal from "create signal from selection"
            sig_frame.ui.btnSaveSignal.show()

        self.__create_connects_for_signal_frame(signal_frame=sig_frame)
        sig_frame.signal_created.connect(self.emit_signal_created)
        sig_frame.not_show_again_changed.connect(
            self.not_show_again_changed.emit)
        sig_frame.ui.lineEditSignalName.setToolTip(
            self.tr("Sourcefile: ") + proto_analyzer.signal.filename)
        sig_frame.apply_to_all_clicked.connect(self.on_apply_to_all_clicked)

        prev_signal_frame = sframes[-1] if len(sframes) > 0 else None
        if prev_signal_frame is not None and hasattr(prev_signal_frame, "ui"):
            sig_frame.ui.cbProtoView.setCurrentIndex(
                prev_signal_frame.ui.cbProtoView.currentIndex())

        sig_frame.blockSignals(True)

        index = self.num_frames if index == -1 else index
        self.ui.splitter.insertWidget(index, sig_frame)
        sig_frame.blockSignals(False)

        default_view = constants.SETTINGS.value('default_view', 0, int)
        sig_frame.ui.cbProtoView.setCurrentIndex(default_view)

        return sig_frame

    def add_empty_frame(self, filename: str, proto):
        self.__set_getting_started_status(False)
        sig_frame = SignalFrame(proto_analyzer=proto,
                                undo_stack=self.undo_stack,
                                project_manager=self.project_manager,
                                parent=self)

        sig_frame.ui.lineEditSignalName.setText(filename)
        self.__create_connects_for_signal_frame(signal_frame=sig_frame)

        self.ui.splitter.insertWidget(self.num_frames, sig_frame)

        return sig_frame

    def __set_getting_started_status(self, getting_started: bool):
        if getting_started == self.getting_started_status:
            return

        self.getting_started_status = getting_started
        self.ui.labelGettingStarted.setVisible(getting_started)

        if not getting_started:
            w = QWidget()
            w.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
            self.ui.splitter.addWidget(w)

    def __create_connects_for_signal_frame(self, signal_frame: SignalFrame):
        signal_frame.hold_shift = constants.SETTINGS.value(
            'hold_shift_to_drag', True, type=bool)
        signal_frame.drag_started.connect(self.frame_dragged)
        signal_frame.frame_dropped.connect(self.frame_dropped)
        signal_frame.files_dropped.connect(self.on_files_dropped)
        signal_frame.closed.connect(self.close_frame)

    def set_frame_numbers(self):
        for i, f in enumerate(self.signal_frames):
            f.ui.lSignalNr.setText("{0:d}:".format(i + 1))

    @pyqtSlot()
    def save_all(self):
        if self.num_frames == 0:
            return

        settings = constants.SETTINGS
        try:
            not_show = settings.value('not_show_save_dialog',
                                      type=bool,
                                      defaultValue=False)
        except TypeError:
            not_show = False

        if not not_show:
            cb = QCheckBox("Don't ask me again.")
            msg_box = QMessageBox(
                QMessageBox.Question, self.tr("Confirm saving all signals"),
                self.tr("All changed signal files will be overwritten. OK?"))
            msg_box.addButton(QMessageBox.Yes)
            msg_box.addButton(QMessageBox.No)
            msg_box.setCheckBox(cb)

            reply = msg_box.exec()
            not_show_again = cb.isChecked()
            settings.setValue("not_show_save_dialog", not_show_again)
            self.not_show_again_changed.emit()

            if reply != QMessageBox.Yes:
                return

        for f in self.signal_frames:
            if f.signal is None or f.signal.filename == "":
                continue
            f.signal.save()

    @pyqtSlot()
    def close_all(self):
        for f in self.signal_frames:
            f.my_close()

    @pyqtSlot(Signal)
    def on_apply_to_all_clicked(self, signal: Signal):
        for frame in self.signal_frames:
            if frame.signal is not None:
                frame.signal.noise_min_plot = signal.noise_min_plot
                frame.signal.noise_max_plot = signal.noise_max_plot

                frame.signal.block_protocol_update = True
                proto_needs_update = False

                if frame.signal.modulation_type != signal.modulation_type:
                    frame.signal.modulation_type = signal.modulation_type
                    proto_needs_update = True

                if frame.signal.qad_center != signal.qad_center:
                    frame.signal.qad_center = signal.qad_center
                    proto_needs_update = True

                if frame.signal.tolerance != signal.tolerance:
                    frame.signal.tolerance = signal.tolerance
                    proto_needs_update = True

                if frame.signal.noise_threshold != signal.noise_threshold:
                    frame.signal.noise_threshold = signal.noise_threshold
                    proto_needs_update = True

                if frame.signal.bit_len != signal.bit_len:
                    frame.signal.bit_len = signal.bit_len
                    proto_needs_update = True

                if frame.signal.pause_threshold != signal.pause_threshold:
                    frame.signal.pause_threshold = signal.pause_threshold
                    proto_needs_update = True

                if frame.signal.message_length_divisor != signal.message_length_divisor:
                    frame.signal.message_length_divisor = signal.message_length_divisor
                    proto_needs_update = True

                frame.signal.block_protocol_update = False

                if proto_needs_update:
                    frame.signal.protocol_needs_update.emit()

    @pyqtSlot(QPoint)
    def frame_dragged(self, pos: QPoint):
        self.drag_pos = pos

    @pyqtSlot(QPoint)
    def frame_dropped(self, pos: QPoint):
        start = self.drag_pos
        if start is None:
            return

        end = pos
        start_index = -1
        end_index = -1
        if self.num_frames > 1:
            for i, w in enumerate(self.signal_frames):
                if w.geometry().contains(start):
                    start_index = i

                if w.geometry().contains(end):
                    end_index = i

        self.swap_frames(start_index, end_index)
        self.frame_was_dropped.emit(start_index, end_index)

    @pyqtSlot(int, int)
    def swap_frames(self, from_index: int, to_index: int):
        if from_index != to_index:
            start_sig_widget = self.ui.splitter.widget(from_index)
            self.ui.splitter.insertWidget(to_index, start_sig_widget)

    @pyqtSlot()
    def on_participant_changed(self):
        for sframe in self.signal_frames:
            sframe.on_participant_changed()

    def redraw_spectrograms(self):
        for frame in self.signal_frames:
            if frame.ui.gvSpectrogram.width_spectrogram > 0:
                frame.draw_spectrogram(force_redraw=True)

    @pyqtSlot(Signal)
    def emit_signal_created(self, signal):
        try:
            index = self.signal_frames.index(self.sender()) + 1
        except ValueError:
            index = -1

        self.signal_created.emit(index, signal)
예제 #7
0
class SignalTabController(QWidget):
    frame_closed = pyqtSignal(SignalFrameController)
    not_show_again_changed = pyqtSignal()
    signal_frame_updated = pyqtSignal(SignalFrameController)
    signal_created = pyqtSignal(Signal)
    files_dropped = pyqtSignal(list)
    frame_was_dropped = pyqtSignal(int, int)

    @property
    def num_signals(self):
        return self.splitter.count() - 1

    @property
    def signal_frames(self):
        """

        :rtype: list of SignalFrameController
        """
        return [self.splitter.widget(i) for i in range(self.num_signals)]

    @property
    def signal_views(self):
        """

        :rtype: list of EpicGraphicView
        """
        return [sWidget.ui.gvSignal for sWidget in self.signal_frames]

    @property
    def signal_numbers(self):
        """

        :rtype: list of int
        """
        return [sw.signal.signal_frame_number for sw in self.signal_frames]

    @property
    def signal_undo_stack(self):
        return self.undo_stack

    def __init__(self, project_manager, parent=None):
        super().__init__(parent)
        self.ui = Ui_Interpretation()
        self.ui.setupUi(self)
        self.splitter = QSplitter()
        self.splitter.setOrientation(Qt.Vertical)
        self.splitter.setChildrenCollapsible(True)
        self.placeholder_widget = QWidget()
        # self.placeholder_widget.setMaximumHeight(1)
        self.placeholder_widget.setSizePolicy(QSizePolicy.Maximum,
                                              QSizePolicy.Maximum)
        self.undo_stack = QUndoStack()
        self.project_manager = project_manager

        self.splitter.addWidget(self.placeholder_widget)
        self.signal_vlay = QVBoxLayout()
        self.signal_vlay.addWidget(self.splitter)
        self.ui.scrlAreaSignals.setLayout(self.signal_vlay)

        self.drag_pos = None

    @pyqtSlot(QPoint)
    def frame_dragged(self, pos: QPoint):
        self.drag_pos = pos

    @pyqtSlot(QPoint)
    def frame_dropped(self, pos: QPoint):
        start = self.drag_pos
        if start is None:
            return

        end = pos
        start_index = -1
        end_index = -1
        if self.num_signals > 1:
            for i, w in enumerate(self.signal_frames):
                if w.geometry().contains(start):
                    start_index = i

                if w.geometry().contains(end):
                    end_index = i

        self.swap_frames(start_index, end_index)
        self.frame_was_dropped.emit(start_index, end_index)

    @pyqtSlot(int, int)
    def swap_frames(self, from_index: int, to_index: int):
        if from_index != to_index:
            start_sig_widget = self.splitter.widget(from_index)
            self.splitter.insertWidget(to_index, start_sig_widget)

    def on_files_dropped(self, files):
        self.files_dropped.emit(files)

    def close_frame(self, frame: SignalFrameController):
        self.frame_closed.emit(frame)

    @pyqtSlot(bool)
    def set_shift_statuslabel(self, shift_pressed):
        if shift_pressed and constants.SETTINGS.value(
                'hold_shift_to_drag', False, type=bool):
            self.ui.lShiftStatus.setText("[SHIFT] Use Mouse to scroll signal.")
            self.ui.lCtrlStatus.clear()

        elif shift_pressed and not constants.SETTINGS.value(
                'hold_shift_to_drag', False, type=bool):
            self.ui.lShiftStatus.setText(
                "[SHIFT] Use mouse to create a selection.")
            self.ui.lCtrlStatus.clear()
        else:
            self.ui.lShiftStatus.clear()

    @pyqtSlot(bool)
    def set_ctrl_statuslabel(self, ctrl_pressed):
        if ctrl_pressed and len(self.ui.lShiftStatus.text()) == 0:
            self.ui.lCtrlStatus.setText(
                "[CTRL] Zoom signal with mousclicks or arrow up/down.")
        else:
            self.ui.lCtrlStatus.clear()

    def reset_all_signalx_zoom(self):
        for gvs in self.signal_views:
            gvs.showing_full_signal = True

    def add_signal_frame(self, proto_analyzer):
        # self.set_tab_busy(True)
        sig_frame = SignalFrameController(proto_analyzer,
                                          self.undo_stack,
                                          self.project_manager,
                                          parent=self)
        sframes = self.signal_frames
        prev_signal_frame = sframes[-1] if len(sframes) > 0 else None

        if len(proto_analyzer.signal.filename) == 0:
            # Neues Signal aus "Create Signal from Selection"
            sig_frame.ui.btnSaveSignal.show()

        self.__create_connects_for_signal_frame(signal_frame=sig_frame)
        sig_frame.signal_created.connect(self.signal_created.emit)
        sig_frame.not_show_again_changed.connect(
            self.not_show_again_changed.emit)
        sig_frame.ui.gvSignal.shift_state_changed.connect(
            self.set_shift_statuslabel)
        sig_frame.ui.gvSignal.ctrl_state_changed.connect(
            self.set_ctrl_statuslabel)
        sig_frame.ui.lineEditSignalName.setToolTip(
            self.tr("Sourcefile: ") + proto_analyzer.signal.filename)
        sig_frame.apply_to_all_clicked.connect(
            self.handle_apply_to_all_clicked)

        if prev_signal_frame is not None:
            sig_frame.ui.cbProtoView.setCurrentIndex(
                prev_signal_frame.ui.cbProtoView.currentIndex())

        sig_frame.blockSignals(True)

        if proto_analyzer.signal.qad_demod_file_loaded:
            sig_frame.ui.cbSignalView.setCurrentIndex(1)
            sig_frame.ui.cbSignalView.setDisabled(True)

        self.splitter.insertWidget(self.num_signals, sig_frame)

        self.reset_all_signalx_zoom()
        sig_frame.blockSignals(False)

        default_view = constants.SETTINGS.value('default_view', 0, int)
        sig_frame.ui.cbProtoView.setCurrentIndex(default_view)

        return sig_frame

    def __create_connects_for_signal_frame(
            self, signal_frame: SignalFrameController):
        signal_frame.hold_shift = constants.SETTINGS.value(
            'hold_shift_to_drag', False, type=bool)
        signal_frame.drag_started.connect(self.frame_dragged)
        signal_frame.frame_dropped.connect(self.frame_dropped)
        signal_frame.files_dropped.connect(self.on_files_dropped)
        signal_frame.closed.connect(self.close_frame)

    def add_empty_frame(self, filename: str, proto):
        sig_frame = SignalFrameController(
            proto_analyzer=proto,
            undo_stack=self.undo_stack,
            project_manager=self.project_manager,
            proto_bits=proto.decoded_proto_bits_str,
            parent=self)

        sig_frame.ui.lineEditSignalName.setText(filename)
        sig_frame.setMinimumHeight(sig_frame.height())
        sig_frame.set_empty_frame_visibilities()
        self.__create_connects_for_signal_frame(signal_frame=sig_frame)

        self.splitter.insertWidget(self.num_signals, sig_frame)
        QCoreApplication.processEvents()

        return sig_frame

    def set_frame_numbers(self):
        for i, f in enumerate(self.signal_frames):
            f.ui.lSignalNr.setText("{0:d}:".format(i + 1))

    def minimize_all(self):
        for f in self.signal_frames:
            f.is_minimized = False
            f.minimize_maximize()

    def maximize_all(self):
        for f in self.signal_frames:
            f.is_minimized = True
            f.minimize_maximize()

    @pyqtSlot()
    def save_all(self):
        if self.num_signals == 0:
            return

        settings = constants.SETTINGS
        try:
            not_show = settings.value('not_show_save_dialog', type=bool)
        except TypeError:
            not_show = False

        if not not_show:
            ok, notshowagain = SaveAllDialog.dialog(self)
            settings.setValue("not_show_save_dialog", notshowagain)
            self.not_show_again_changed.emit()
            if not ok:
                return

        for f in self.signal_frames:
            if f.signal is None or f.signal.filename == "":
                continue
            f.signal.save()

    @pyqtSlot()
    def close_all(self):
        for f in self.signal_frames:
            f.my_close()

    @pyqtSlot(Signal)
    def handle_apply_to_all_clicked(self, signal: Signal):
        for frame in self.signal_frames:
            if frame.signal is not None:
                frame.signal.noise_min_plot = signal.noise_min_plot
                frame.signal.noise_max_plot = signal.noise_max_plot

                frame.signal.block_protocol_update = True
                proto_needs_update = False

                if frame.signal.modulation_type != signal.modulation_type:
                    frame.signal.modulation_type = signal.modulation_type
                    proto_needs_update = True

                if frame.signal.qad_center != signal.qad_center:
                    frame.signal.qad_center = signal.qad_center
                    proto_needs_update = True

                if frame.signal.tolerance != signal.tolerance:
                    frame.signal.tolerance = signal.tolerance
                    proto_needs_update = True

                if frame.signal.noise_threshold != signal.noise_threshold:
                    frame.signal.noise_threshold = signal.noise_threshold
                    proto_needs_update = True

                if frame.signal.bit_len != signal.bit_len:
                    frame.signal.bit_len = signal.bit_len
                    proto_needs_update = True

                frame.signal.block_protocol_update = False

                if proto_needs_update:
                    frame.signal.protocol_needs_update.emit()

    def __get_sorted_positions(self):
        frame_names = [
            sf.ui.lineEditSignalName.text() for sf in self.signal_frames
        ]
        sorted_frame_names = frame_names[:]
        sorted_frame_names.sort()
        sorted_positions = []
        for name in frame_names:
            pos = sorted_frame_names.index(name)
            if pos in sorted_positions:
                pos += 1
            sorted_positions.append(pos)
        return sorted_positions

    def refresh_participant_information(self):
        for sframe in self.signal_frames:
            sframe.on_participant_changed()
예제 #8
0
class SignalTabController(QWidget):
    frame_closed = pyqtSignal(SignalFrameController)
    not_show_again_changed = pyqtSignal()
    signal_created = pyqtSignal(Signal)
    files_dropped = pyqtSignal(list)
    frame_was_dropped = pyqtSignal(int, int)

    @property
    def num_frames(self):
        return self.splitter.count() - 1

    @property
    def signal_frames(self):
        """

        :rtype: list of SignalFrameController
        """
        return [self.splitter.widget(i) for i in range(self.num_frames)]

    @property
    def signal_undo_stack(self):
        return self.undo_stack

    def __init__(self, project_manager, parent=None):
        super().__init__(parent)
        self.ui = Ui_Interpretation()
        self.ui.setupUi(self)
        self.splitter = QSplitter()
        self.splitter.setStyleSheet("QSplitter::handle:vertical {\nmargin: 4px 0px; background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, \nstop:0 rgba(255, 255, 255, 0), \nstop:0.5 rgba(100, 100, 100, 100), \nstop:1 rgba(255, 255, 255, 0));\n	image: url(:/icons/data/icons/splitter_handle_horizontal.svg);\n}")
        self.splitter.setOrientation(Qt.Vertical)
        self.splitter.setChildrenCollapsible(True)
        self.splitter.setHandleWidth(6)

        placeholder_widget = QWidget()
        placeholder_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        self.undo_stack = QUndoStack()
        self.project_manager = project_manager

        self.splitter.addWidget(placeholder_widget)
        self.signal_vlay = QVBoxLayout()
        self.signal_vlay.setContentsMargins(0,0,0,0)
        self.signal_vlay.addWidget(self.splitter)
        self.ui.scrlAreaSignals.setLayout(self.signal_vlay)

        self.drag_pos = None

    def on_files_dropped(self, files):
        self.files_dropped.emit(files)

    def close_frame(self, frame:SignalFrameController):
        self.frame_closed.emit(frame)

    def add_signal_frame(self, proto_analyzer):
        sig_frame = SignalFrameController(proto_analyzer, self.undo_stack, self.project_manager, parent=self)
        sframes = self.signal_frames


        if len(proto_analyzer.signal.filename) == 0:
            # new signal from "create signal from selection"
            sig_frame.ui.btnSaveSignal.show()

        self.__create_connects_for_signal_frame(signal_frame=sig_frame)
        sig_frame.signal_created.connect(self.signal_created.emit)
        sig_frame.not_show_again_changed.connect(self.not_show_again_changed.emit)
        sig_frame.ui.lineEditSignalName.setToolTip(self.tr("Sourcefile: ") + proto_analyzer.signal.filename)
        sig_frame.apply_to_all_clicked.connect(self.on_apply_to_all_clicked)

        prev_signal_frame = sframes[-1] if len(sframes) > 0 else None
        if prev_signal_frame is not None and hasattr(prev_signal_frame, "ui"):
            sig_frame.ui.cbProtoView.setCurrentIndex(prev_signal_frame.ui.cbProtoView.currentIndex())

        sig_frame.blockSignals(True)

        if proto_analyzer.signal.qad_demod_file_loaded:
            sig_frame.ui.cbSignalView.setCurrentIndex(1)
            sig_frame.ui.cbSignalView.setDisabled(True)

        self.splitter.insertWidget(self.num_frames, sig_frame)
        sig_frame.blockSignals(False)

        default_view = constants.SETTINGS.value('default_view', 0, int)
        sig_frame.ui.cbProtoView.setCurrentIndex(default_view)

        return sig_frame

    def __create_connects_for_signal_frame(self, signal_frame: SignalFrameController):
        signal_frame.hold_shift = constants.SETTINGS.value('hold_shift_to_drag', False, type=bool)
        signal_frame.drag_started.connect(self.frame_dragged)
        signal_frame.frame_dropped.connect(self.frame_dropped)
        signal_frame.files_dropped.connect(self.on_files_dropped)
        signal_frame.closed.connect(self.close_frame)

    def add_empty_frame(self, filename: str, proto):
        sig_frame = SignalFrameController(proto_analyzer=proto, undo_stack=self.undo_stack,
                                          project_manager=self.project_manager, proto_bits=proto.decoded_proto_bits_str,
                                          parent=self)

        sig_frame.ui.lineEditSignalName.setText(filename)
        sig_frame.setMinimumHeight(sig_frame.height())
        sig_frame.set_empty_frame_visibilities()
        self.__create_connects_for_signal_frame(signal_frame=sig_frame)

        self.splitter.insertWidget(self.num_frames, sig_frame)

        return sig_frame

    def set_frame_numbers(self):
        for i, f in enumerate(self.signal_frames):
            f.ui.lSignalNr.setText("{0:d}:".format(i + 1))

    @pyqtSlot()
    def save_all(self):
        if self.num_frames == 0:
            return

        settings = constants.SETTINGS
        try:
            not_show = settings.value('not_show_save_dialog', type=bool, defaultValue=False)
        except TypeError:
            not_show = False

        if not not_show:
            cb = QCheckBox("Don't ask me again.")
            msg_box = QMessageBox(QMessageBox.Question, self.tr("Confirm saving all signals"),
                                  self.tr("All changed signal files will be overwritten. OK?"))
            msg_box.addButton(QMessageBox.Yes)
            msg_box.addButton(QMessageBox.No)
            msg_box.setCheckBox(cb)

            reply = msg_box.exec()
            not_show_again = cb.isChecked()
            settings.setValue("not_show_save_dialog", not_show_again)
            self.not_show_again_changed.emit()

            if reply != QMessageBox.Yes:
                return

        for f in self.signal_frames:
            if f.signal is None or f.signal.filename == "":
                continue
            f.signal.save()

    @pyqtSlot()
    def close_all(self):
        for f in self.signal_frames:
            f.my_close()

    @pyqtSlot(Signal)
    def on_apply_to_all_clicked(self, signal: Signal):
        for frame in self.signal_frames:
            if frame.signal is not None:
                frame.signal.noise_min_plot = signal.noise_min_plot
                frame.signal.noise_max_plot = signal.noise_max_plot

                frame.signal.block_protocol_update = True
                proto_needs_update = False

                if frame.signal.modulation_type != signal.modulation_type:
                    frame.signal.modulation_type = signal.modulation_type
                    proto_needs_update = True

                if frame.signal.qad_center != signal.qad_center:
                    frame.signal.qad_center = signal.qad_center
                    proto_needs_update = True

                if frame.signal.tolerance != signal.tolerance:
                    frame.signal.tolerance = signal.tolerance
                    proto_needs_update = True

                if frame.signal.noise_threshold != signal.noise_threshold:
                    frame.signal.noise_threshold = signal.noise_threshold
                    proto_needs_update = True

                if frame.signal.bit_len != signal.bit_len:
                    frame.signal.bit_len = signal.bit_len
                    proto_needs_update = True

                frame.signal.block_protocol_update = False

                if proto_needs_update:
                    frame.signal.protocol_needs_update.emit()

    @pyqtSlot(QPoint)
    def frame_dragged(self, pos: QPoint):
        self.drag_pos = pos

    @pyqtSlot(QPoint)
    def frame_dropped(self, pos: QPoint):
        start = self.drag_pos
        if start is None:
            return

        end = pos
        start_index = -1
        end_index = -1
        if self.num_frames > 1:
            for i, w in enumerate(self.signal_frames):
                if w.geometry().contains(start):
                    start_index = i

                if w.geometry().contains(end):
                    end_index = i

        self.swap_frames(start_index, end_index)
        self.frame_was_dropped.emit(start_index, end_index)

    @pyqtSlot(int, int)
    def swap_frames(self, from_index: int, to_index: int):
        if from_index != to_index:
            start_sig_widget = self.splitter.widget(from_index)
            self.splitter.insertWidget(to_index, start_sig_widget)

    @pyqtSlot()
    def on_participant_changed(self):
        for sframe in self.signal_frames:
            sframe.on_participant_changed()
예제 #9
0
class SignalTabController(QWidget):
    frame_closed = pyqtSignal(SignalFrameController)
    not_show_again_changed = pyqtSignal()
    signal_created = pyqtSignal(Signal)
    files_dropped = pyqtSignal(list)
    frame_was_dropped = pyqtSignal(int, int)

    @property
    def num_frames(self):
        return self.splitter.count() - 1

    @property
    def signal_frames(self):
        """

        :rtype: list of SignalFrameController
        """
        return [self.splitter.widget(i) for i in range(self.num_frames)]

    @property
    def signal_undo_stack(self):
        return self.undo_stack

    def __init__(self, project_manager, parent=None):
        super().__init__(parent)
        self.ui = Ui_Interpretation()
        self.ui.setupUi(self)
        self.splitter = QSplitter()
        self.splitter.setStyleSheet(
            "QSplitter::handle:vertical {\nmargin: 4px 0px; background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, \nstop:0 rgba(255, 255, 255, 0), \nstop:0.5 rgba(100, 100, 100, 100), \nstop:1 rgba(255, 255, 255, 0));\n	image: url(:/icons/data/icons/splitter_handle.png);\n}"
        )
        self.splitter.setOrientation(Qt.Vertical)
        self.splitter.setChildrenCollapsible(True)
        self.splitter.setHandleWidth(6)

        placeholder_widget = QWidget()
        placeholder_widget.setSizePolicy(QSizePolicy.Maximum,
                                         QSizePolicy.Maximum)
        self.undo_stack = QUndoStack()
        self.project_manager = project_manager

        self.splitter.addWidget(placeholder_widget)
        self.signal_vlay = QVBoxLayout()
        self.signal_vlay.setContentsMargins(0, 0, 0, 0)
        self.signal_vlay.addWidget(self.splitter)
        self.ui.scrlAreaSignals.setLayout(self.signal_vlay)

        self.drag_pos = None

    def on_files_dropped(self, files):
        self.files_dropped.emit(files)

    def close_frame(self, frame: SignalFrameController):
        self.frame_closed.emit(frame)

    def add_signal_frame(self, proto_analyzer):
        sig_frame = SignalFrameController(proto_analyzer,
                                          self.undo_stack,
                                          self.project_manager,
                                          parent=self)
        sframes = self.signal_frames

        if len(proto_analyzer.signal.filename) == 0:
            # new signal from "create signal from selection"
            sig_frame.ui.btnSaveSignal.show()

        self.__create_connects_for_signal_frame(signal_frame=sig_frame)
        sig_frame.signal_created.connect(self.signal_created.emit)
        sig_frame.not_show_again_changed.connect(
            self.not_show_again_changed.emit)
        sig_frame.ui.gvSignal.shift_state_changed.connect(
            self.set_shift_statuslabel)
        sig_frame.ui.lineEditSignalName.setToolTip(
            self.tr("Sourcefile: ") + proto_analyzer.signal.filename)
        sig_frame.apply_to_all_clicked.connect(self.on_apply_to_all_clicked)

        prev_signal_frame = sframes[-1] if len(sframes) > 0 else None
        if prev_signal_frame is not None and hasattr(prev_signal_frame, "ui"):
            sig_frame.ui.cbProtoView.setCurrentIndex(
                prev_signal_frame.ui.cbProtoView.currentIndex())

        sig_frame.blockSignals(True)

        if proto_analyzer.signal.qad_demod_file_loaded:
            sig_frame.ui.cbSignalView.setCurrentIndex(1)
            sig_frame.ui.cbSignalView.setDisabled(True)

        self.splitter.insertWidget(self.num_frames, sig_frame)
        sig_frame.blockSignals(False)

        default_view = constants.SETTINGS.value('default_view', 0, int)
        sig_frame.ui.cbProtoView.setCurrentIndex(default_view)

        return sig_frame

    def __create_connects_for_signal_frame(
            self, signal_frame: SignalFrameController):
        signal_frame.hold_shift = constants.SETTINGS.value(
            'hold_shift_to_drag', False, type=bool)
        signal_frame.drag_started.connect(self.frame_dragged)
        signal_frame.frame_dropped.connect(self.frame_dropped)
        signal_frame.files_dropped.connect(self.on_files_dropped)
        signal_frame.closed.connect(self.close_frame)

    def add_empty_frame(self, filename: str, proto):
        sig_frame = SignalFrameController(
            proto_analyzer=proto,
            undo_stack=self.undo_stack,
            project_manager=self.project_manager,
            proto_bits=proto.decoded_proto_bits_str,
            parent=self)

        sig_frame.ui.lineEditSignalName.setText(filename)
        sig_frame.setMinimumHeight(sig_frame.height())
        sig_frame.set_empty_frame_visibilities()
        self.__create_connects_for_signal_frame(signal_frame=sig_frame)

        self.splitter.insertWidget(self.num_frames, sig_frame)

        return sig_frame

    def set_frame_numbers(self):
        for i, f in enumerate(self.signal_frames):
            f.ui.lSignalNr.setText("{0:d}:".format(i + 1))

    @pyqtSlot()
    def save_all(self):
        if self.num_frames == 0:
            return

        settings = constants.SETTINGS
        try:
            not_show = settings.value('not_show_save_dialog',
                                      type=bool,
                                      defaultValue=False)
        except TypeError:
            not_show = False

        if not not_show:
            cb = QCheckBox("Don't ask me again.")
            msg_box = QMessageBox(
                QMessageBox.Question, self.tr("Confirm saving all signals"),
                self.tr("All changed signal files will be overwritten. OK?"))
            msg_box.addButton(QMessageBox.Yes)
            msg_box.addButton(QMessageBox.No)
            msg_box.setCheckBox(cb)

            reply = msg_box.exec()
            not_show_again = cb.isChecked()
            settings.setValue("not_show_save_dialog", not_show_again)
            self.not_show_again_changed.emit()

            if reply != QMessageBox.Yes:
                return

        for f in self.signal_frames:
            if f.signal is None or f.signal.filename == "":
                continue
            f.signal.save()

    @pyqtSlot()
    def close_all(self):
        for f in self.signal_frames:
            f.my_close()

    @pyqtSlot(Signal)
    def on_apply_to_all_clicked(self, signal: Signal):
        for frame in self.signal_frames:
            if frame.signal is not None:
                frame.signal.noise_min_plot = signal.noise_min_plot
                frame.signal.noise_max_plot = signal.noise_max_plot

                frame.signal.block_protocol_update = True
                proto_needs_update = False

                if frame.signal.modulation_type != signal.modulation_type:
                    frame.signal.modulation_type = signal.modulation_type
                    proto_needs_update = True

                if frame.signal.qad_center != signal.qad_center:
                    frame.signal.qad_center = signal.qad_center
                    proto_needs_update = True

                if frame.signal.tolerance != signal.tolerance:
                    frame.signal.tolerance = signal.tolerance
                    proto_needs_update = True

                if frame.signal.noise_threshold != signal.noise_threshold:
                    frame.signal.noise_threshold = signal.noise_threshold
                    proto_needs_update = True

                if frame.signal.bit_len != signal.bit_len:
                    frame.signal.bit_len = signal.bit_len
                    proto_needs_update = True

                frame.signal.block_protocol_update = False

                if proto_needs_update:
                    frame.signal.protocol_needs_update.emit()

    @pyqtSlot(QPoint)
    def frame_dragged(self, pos: QPoint):
        self.drag_pos = pos

    @pyqtSlot(QPoint)
    def frame_dropped(self, pos: QPoint):
        start = self.drag_pos
        if start is None:
            return

        end = pos
        start_index = -1
        end_index = -1
        if self.num_frames > 1:
            for i, w in enumerate(self.signal_frames):
                if w.geometry().contains(start):
                    start_index = i

                if w.geometry().contains(end):
                    end_index = i

        self.swap_frames(start_index, end_index)
        self.frame_was_dropped.emit(start_index, end_index)

    @pyqtSlot(int, int)
    def swap_frames(self, from_index: int, to_index: int):
        if from_index != to_index:
            start_sig_widget = self.splitter.widget(from_index)
            self.splitter.insertWidget(to_index, start_sig_widget)

    @pyqtSlot(bool)
    def set_shift_statuslabel(self, shift_pressed):
        if shift_pressed and constants.SETTINGS.value(
                'hold_shift_to_drag', False, type=bool):
            self.ui.lShiftStatus.setText("[SHIFT] Use Mouse to scroll signal.")

        elif shift_pressed and not constants.SETTINGS.value(
                'hold_shift_to_drag', False, type=bool):
            self.ui.lShiftStatus.setText(
                "[SHIFT] Use mouse to create a selection.")
        else:
            self.ui.lShiftStatus.clear()

    @pyqtSlot()
    def on_participant_changed(self):
        for sframe in self.signal_frames:
            sframe.on_participant_changed()
예제 #10
0
class SignalTabController(QWidget):
    frame_closed = pyqtSignal(SignalFrame)
    not_show_again_changed = pyqtSignal()
    signal_created = pyqtSignal(int, Signal)
    files_dropped = pyqtSignal(list)
    frame_was_dropped = pyqtSignal(int, int)

    @property
    def num_frames(self):
        return len(self.signal_frames)

    @property
    def signal_frames(self):
        """

        :rtype: list of SignalFrame
        """
        splitter = self.ui.splitter
        return [splitter.widget(i) for i in range(splitter.count())
                if isinstance(splitter.widget(i), SignalFrame)]

    @property
    def signal_undo_stack(self):
        return self.undo_stack

    def __init__(self, project_manager, parent=None):
        super().__init__(parent)
        self.ui = Ui_Interpretation()
        self.ui.setupUi(self)

        util.set_splitter_stylesheet(self.ui.splitter)

        self.ui.placeholderLabel.setVisible(False)
        self.getting_started_status = None
        self.__set_getting_started_status(True)

        self.undo_stack = QUndoStack()
        self.project_manager = project_manager

        self.drag_pos = None

    def on_files_dropped(self, files):
        self.files_dropped.emit(files)

    def close_frame(self, frame:SignalFrame):
        self.frame_closed.emit(frame)

    def add_signal_frame(self, proto_analyzer, index=-1):
        self.__set_getting_started_status(False)
        sig_frame = SignalFrame(proto_analyzer, self.undo_stack, self.project_manager, parent=self)
        sframes = self.signal_frames

        if len(proto_analyzer.signal.filename) == 0:
            # new signal from "create signal from selection"
            sig_frame.ui.btnSaveSignal.show()

        self.__create_connects_for_signal_frame(signal_frame=sig_frame)
        sig_frame.signal_created.connect(self.emit_signal_created)
        sig_frame.not_show_again_changed.connect(self.not_show_again_changed.emit)
        sig_frame.ui.lineEditSignalName.setToolTip(self.tr("Sourcefile: ") + proto_analyzer.signal.filename)
        sig_frame.apply_to_all_clicked.connect(self.on_apply_to_all_clicked)

        prev_signal_frame = sframes[-1] if len(sframes) > 0 else None
        if prev_signal_frame is not None and hasattr(prev_signal_frame, "ui"):
            sig_frame.ui.cbProtoView.setCurrentIndex(prev_signal_frame.ui.cbProtoView.currentIndex())

        sig_frame.blockSignals(True)

        index = self.num_frames if index == -1 else index
        self.ui.splitter.insertWidget(index, sig_frame)
        sig_frame.blockSignals(False)

        default_view = constants.SETTINGS.value('default_view', 0, int)
        sig_frame.ui.cbProtoView.setCurrentIndex(default_view)

        return sig_frame

    def add_empty_frame(self, filename: str, proto):
        self.__set_getting_started_status(False)
        sig_frame = SignalFrame(proto_analyzer=proto, undo_stack=self.undo_stack, project_manager=self.project_manager,
                                parent=self)

        sig_frame.ui.lineEditSignalName.setText(filename)
        self.__create_connects_for_signal_frame(signal_frame=sig_frame)

        self.ui.splitter.insertWidget(self.num_frames, sig_frame)

        return sig_frame

    def __set_getting_started_status(self, getting_started: bool):
        if getting_started == self.getting_started_status:
            return

        self.getting_started_status = getting_started
        self.ui.labelGettingStarted.setVisible(getting_started)

        if not getting_started:
            w = QWidget()
            w.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
            self.ui.splitter.addWidget(w)

    def __create_connects_for_signal_frame(self, signal_frame: SignalFrame):
        signal_frame.hold_shift = constants.SETTINGS.value('hold_shift_to_drag', True, type=bool)
        signal_frame.drag_started.connect(self.frame_dragged)
        signal_frame.frame_dropped.connect(self.frame_dropped)
        signal_frame.files_dropped.connect(self.on_files_dropped)
        signal_frame.closed.connect(self.close_frame)

    def set_frame_numbers(self):
        for i, f in enumerate(self.signal_frames):
            f.ui.lSignalNr.setText("{0:d}:".format(i + 1))

    @pyqtSlot()
    def save_all(self):
        if self.num_frames == 0:
            return

        settings = constants.SETTINGS
        try:
            not_show = settings.value('not_show_save_dialog', type=bool, defaultValue=False)
        except TypeError:
            not_show = False

        if not not_show:
            cb = QCheckBox("Don't ask me again.")
            msg_box = QMessageBox(QMessageBox.Question, self.tr("Confirm saving all signals"),
                                  self.tr("All changed signal files will be overwritten. OK?"))
            msg_box.addButton(QMessageBox.Yes)
            msg_box.addButton(QMessageBox.No)
            msg_box.setCheckBox(cb)

            reply = msg_box.exec()
            not_show_again = cb.isChecked()
            settings.setValue("not_show_save_dialog", not_show_again)
            self.not_show_again_changed.emit()

            if reply != QMessageBox.Yes:
                return

        for f in self.signal_frames:
            if f.signal is None or f.signal.filename == "":
                continue
            f.signal.save()

    @pyqtSlot()
    def close_all(self):
        for f in self.signal_frames:
            f.my_close()

    @pyqtSlot(Signal)
    def on_apply_to_all_clicked(self, signal: Signal):
        for frame in self.signal_frames:
            if frame.signal is not None:
                frame.signal.noise_min_plot = signal.noise_min_plot
                frame.signal.noise_max_plot = signal.noise_max_plot

                frame.signal.block_protocol_update = True
                proto_needs_update = False

                if frame.signal.modulation_type != signal.modulation_type:
                    frame.signal.modulation_type = signal.modulation_type
                    proto_needs_update = True

                if frame.signal.qad_center != signal.qad_center:
                    frame.signal.qad_center = signal.qad_center
                    proto_needs_update = True

                if frame.signal.tolerance != signal.tolerance:
                    frame.signal.tolerance = signal.tolerance
                    proto_needs_update = True

                if frame.signal.noise_threshold != signal.noise_threshold:
                    frame.signal.noise_threshold = signal.noise_threshold
                    proto_needs_update = True

                if frame.signal.bit_len != signal.bit_len:
                    frame.signal.bit_len = signal.bit_len
                    proto_needs_update = True

                if frame.signal.pause_threshold != signal.pause_threshold:
                    frame.signal.pause_threshold = signal.pause_threshold
                    proto_needs_update = True

                if frame.signal.message_length_divisor != signal.message_length_divisor:
                    frame.signal.message_length_divisor = signal.message_length_divisor
                    proto_needs_update = True

                frame.signal.block_protocol_update = False

                if proto_needs_update:
                    frame.signal.protocol_needs_update.emit()

    @pyqtSlot(QPoint)
    def frame_dragged(self, pos: QPoint):
        self.drag_pos = pos

    @pyqtSlot(QPoint)
    def frame_dropped(self, pos: QPoint):
        start = self.drag_pos
        if start is None:
            return

        end = pos
        start_index = -1
        end_index = -1
        if self.num_frames > 1:
            for i, w in enumerate(self.signal_frames):
                if w.geometry().contains(start):
                    start_index = i

                if w.geometry().contains(end):
                    end_index = i

        self.swap_frames(start_index, end_index)
        self.frame_was_dropped.emit(start_index, end_index)

    @pyqtSlot(int, int)
    def swap_frames(self, from_index: int, to_index: int):
        if from_index != to_index:
            start_sig_widget = self.ui.splitter.widget(from_index)
            self.ui.splitter.insertWidget(to_index, start_sig_widget)

    @pyqtSlot()
    def on_participant_changed(self):
        for sframe in self.signal_frames:
            sframe.on_participant_changed()

    def redraw_spectrograms(self):
        for frame in self.signal_frames:
            if frame.ui.gvSpectrogram.width_spectrogram > 0:
                frame.draw_spectrogram(force_redraw=True)

    @pyqtSlot(Signal)
    def emit_signal_created(self, signal):
        try:
            index = self.signal_frames.index(self.sender()) + 1
        except ValueError:
            index = -1

        self.signal_created.emit(index, signal)