Exemple #1
0
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        layout = QHBoxLayout()

        # video player object
        self.video_player = VideoPlayer(self)

        # Tracks table
        self.tracks_table = QTableView()

        # Keeps display options
        self.display_options = {"show_tracks": True,
                                "show_traces": True,
                                "show_labels": True}

        layout.addWidget(self.video_player)
        layout.addWidget(self.tracks_table)

        # Create tracks model and items to show in tracks table.
        self.tracks_model = QStandardItemModel()
        self.tracks_model.setHorizontalHeaderLabels(["Id", "State", "Age"])
        self.tracks_table.setModel(self.tracks_model)
        self.track_items = {}

        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)

        self.setMinimumHeight(800)
        self.setMinimumWidth(1000)

        self.tracks_table.setFixedWidth(300)

        toolbar = QToolBar("Main")
        self.addToolBar(toolbar)

        open_button = QAction(self.style().standardIcon(QStyle.SP_DirOpenIcon), "Open Video File", self)
        open_button.setStatusTip("Open Video File")
        open_button.triggered.connect(self.video_player.open_video_file)
        toolbar.addAction(open_button)

        toolbar.addWidget(QLabel("Tracks"))
        self.tracks_check_box = QCheckBox()
        self.tracks_check_box.toggle()
        self.tracks_check_box.stateChanged.connect(self.tracks)
        toolbar.addWidget(self.tracks_check_box)

        toolbar.addWidget(QLabel("Traces"))
        self.traces_check_box = QCheckBox()
        self.traces_check_box.toggle()
        self.traces_check_box.stateChanged.connect(self.traces)
        toolbar.addWidget(self.traces_check_box)

        toolbar.addWidget(QLabel("Labels"))
        self.labels_check_box = QCheckBox()
        self.labels_check_box.toggle()
        self.labels_check_box.stateChanged.connect(self.labels)
        toolbar.addWidget(self.labels_check_box)

        self.status_bar = QStatusBar()
        self.vps_server_label = QLabel("")
        self.tps_server_label = QLabel("")

        self.status_bar.addWidget(self.vps_server_label)
        self.status_bar.addWidget(self.tps_server_label)

        self.setStatusBar(self.status_bar)

    def get_or_create_track_row(self, track: dict) -> ():
        """
        Get or create a track row in tracks table

        Args:
            track: Track label and trace
        """

        track_id = track[0]
        if track_id not in self.track_items:
            self.track_items[track_id] = self.add_track_row(track)
        return self.track_items[track_id]

    def add_track_row(self, track):
        """
        Adds a track row to the tracks table model.

        Args:
            track: Track label and trace

        Returns:
            id_item
            status_item
            age_item
        """
        id_item = QStandardItem()
        id_item.setText(track[0])
        id_item.setBackground(QBrush(QColor(
            get_random_color(int(track[0]))
        )))
        id_item.setEditable(False)

        status_item = QStandardItem()
        status_item.setTextAlignment(Qt.AlignCenter | Qt.AlignVCenter)
        status_item.setEditable(False)

        age_item = QStandardItem()
        age_item.setTextAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        age_item.setEditable(False)

        self.tracks_model.appendRow([id_item, status_item, age_item])
        self.tracks_model.sort(0)
        return id_item, status_item, age_item

    def update_track_row(self, track_id, trace):
        """
        Updates track list and model

        Args:
            track_id
            trace
        """
        status = "Active"
        if track_id in self.track_items:
            # If length of the track trace is not changed
            # Track is passive
            if len(self.track_items[track_id]) == len(trace):
                status = "Passive"
        track_id, track_status, track_age = self.get_or_create_track_row(track_id)
        track_status.setText(status)
        track_age.setText(f"{len(trace)//24}")

    def reset_tracks_table(self):
        """Reset tracks_model and track_items"""
        self.tracks_model.removeRows(0, len(self.track_items))
        self.track_items = {}

    def update_server_stats(self, vps_stats_summary, tps_stats_summary):
        """
        Updates server statistics.

        Args:
            vps_stats_summary: Video Processing Server statistics
            tps_stats_summary: Track Processing Server statistics
        """
        self.tps_server_label.setText(tps_stats_summary)
        self.vps_server_label.setText(vps_stats_summary)

    def update_track_viewer(self, tracks):
        """
        Update tracks table

        Args:
            tracks
        """
        if not tracks:  # Skip update if we have no data.
            return

        for track_id, trace in tracks.items():
            self.update_track_row(track_id, trace)

    def traces(self):
        """Changes trace display options."""
        self.display_options["show_traces"] = not self.display_options["show_traces"]

    def labels(self):
        """Changes labels display options."""
        self.display_options["show_labels"] = not self.display_options["show_labels"]

    def tracks(self):
        """Changes tracks display options."""
        self.display_options["show_tracks"] = not self.display_options["show_tracks"]

    def closeEvent(self, event):
        """Exit application."""
        reply = QMessageBox.question(self, 'Window Close', 'Are you sure you want to close the window?',
                                     QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            self.video_player.close()
            event.accept()

        else:
            event.ignore()
class VStdAttributesDialog(QDialog):
    def __init__(self, parent, sig_attribute_edition: Signal, student: Student,
                 attributes: list):
        """
        Confirm dialog for dangerous actions

        :param parent: gui's main window
        :param sig_attribute_edition: Signal to emit in order to edit the selected attribute
        :param student: Current student
        :param attributes: List of attributes
        """
        QDialog.__init__(self, parent)

        self.setFixedSize(QSize(350, 350))
        self.setWindowFlag(Qt.WindowStaysOnTopHint)

        self.student = student
        self.attributes = attributes

        # Widgets
        self.std_info = QLabel(f"{student.firstname} {student.lastname}")

        self.table_attributes = QTableView()
        self.table_attributes.setFixedWidth(300)
        self.table_attributes.horizontalHeader().setStretchLastSection(True)
        self.table_attributes.horizontalHeader().hide()
        self.table_attributes.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table_attributes.setSelectionMode(
            QAbstractItemView.SingleSelection)
        self.table_attributes.verticalHeader().setSectionResizeMode(
            QHeaderView.Fixed)
        self.table_attributes.verticalHeader().setFixedWidth(150)

        self.dm: AttributesTableModel = None
        self.attr_idx = {
        }  # Attributes ids to indexes -> {attr_id: attr_idx, ...}

        # Close button
        self.ok_btn = QPushButton("Ok")
        self.ok_btn.clicked.connect(self.accept)
        self.ok_btn.setFixedSize(QSize(60, 33))

        # Signals
        self.sig_attribute_edition = sig_attribute_edition
        self.table_attributes.clicked.connect(self.on_attr_clicked)

        # Layout
        layout = QVBoxLayout()
        layout.addWidget(self.std_info)
        layout.setAlignment(self.std_info, Qt.AlignCenter)
        layout.addWidget(self.table_attributes)
        layout.addWidget(self.ok_btn)
        layout.setAlignment(self.ok_btn, Qt.AlignCenter)
        self.setLayout(layout)

        self.setStyleSheet(get_stylesheet("dialog"))

        # Initialization with the given attributes
        self.attributes_updated(self.attributes)

    def attributes_updated(self, attributes: list) -> None:
        """
        Called when an attribute changed and needs to be updated in the tableview

        :param attributes: List of attributes
        """
        self.attributes = attributes

        header = [a[1] for a in attributes]  # Table Header
        data_for_model = [a[2] for a in attributes]  # Table data

        # Save indexes
        self.attr_idx = {}
        i = 0
        for attr_id, _, _ in attributes:
            self.attr_idx[attr_id] = i
            i += 1

        # Create the table model
        self.dm = AttributesTableModel(self.table_attributes, data_for_model,
                                       header)

    def on_attr_clicked(self, item) -> None:
        """
        Triggered when a cell is clicked. Emits a signal with the attribute and student ids
        """
        attr_id = None
        for a in self.attr_idx:
            if self.attr_idx[a] == item.row():
                attr_id = a

        self.sig_attribute_edition.emit(attr_id, self.student.id)