From 968e9fcb766d551ac30ab778ea54f0dbd69fe320 Mon Sep 17 00:00:00 2001 From: jbellister-slac Date: Mon, 1 May 2023 13:12:41 -0700 Subject: [PATCH] FIX: Prevent segfaults when filtering the alarm table --- slam/alarm_table_model.py | 6 ++---- slam/alarm_table_view.py | 22 ++++++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/slam/alarm_table_model.py b/slam/alarm_table_model.py index c416dec..039c99b 100644 --- a/slam/alarm_table_model.py +++ b/slam/alarm_table_model.py @@ -89,9 +89,8 @@ def append(self, alarm_item: AlarmItem) -> None: if alarm_item.name in self.alarm_items: logger.warning(f'Attempting to append a row to the alarm table which is already there: {alarm_item.name}') return - self.beginInsertRows(QModelIndex(), len(self.alarm_items), len(self.alarm_items)) + self.layoutAboutToBeChanged.emit() self.alarm_items[alarm_item.name] = alarm_item - self.endInsertRows() self.layoutChanged.emit() def remove_row(self, alarm_name: str): @@ -99,9 +98,8 @@ def remove_row(self, alarm_name: str): if alarm_name not in self.alarm_items: return index_to_remove = list(self.alarm_items.keys()).index(alarm_name) - self.beginRemoveRows(QModelIndex(), index_to_remove, index_to_remove) + self.layoutAboutToBeChanged.emit() del self.alarm_items[alarm_name] - self.endRemoveRows() self.layoutChanged.emit() def sort(self, col: int, order=Qt.AscendingOrder): diff --git a/slam/alarm_table_view.py b/slam/alarm_table_view.py index 31f33f3..447a477 100644 --- a/slam/alarm_table_view.py +++ b/slam/alarm_table_view.py @@ -3,11 +3,11 @@ import socket from functools import partial from kafka.producer import KafkaProducer -from qtpy.QtCore import QEvent, QSortFilterProxyModel, Qt, Signal +from qtpy.QtCore import QEvent, QModelIndex, QSortFilterProxyModel, Qt, Signal from qtpy.QtGui import QCursor from qtpy.QtWidgets import (QAbstractItemView, QAction, QApplication, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMenu, QPushButton, QTableView, QVBoxLayout, QWidget) -from typing import Callable +from typing import Callable, List from .alarm_table_model import AlarmItemsTableModel from .alarm_tree_model import AlarmItemsTreeModel from .permissions import UserAction, can_take_action @@ -122,8 +122,7 @@ def __init__(self, tree_model: AlarmItemsTreeModel, kafka_producer: KafkaProduce self.layout.addWidget(self.filter_active_label) self.layout.addWidget(self.alarmView) - self.alarmModel.rowsInserted.connect(self.update_counter_label) - self.alarmModel.rowsRemoved.connect(self.update_counter_label) + self.alarmModel.layoutChanged.connect(self.update_counter_label) def filter_table(self) -> None: """ Filter the table based on the text typed into the filter bar """ @@ -150,9 +149,16 @@ def alarm_context_menu_event(self, ev: QEvent) -> None: """ Display the right-click context menu for items in the active alarms table """ self.alarm_context_menu.popup(QCursor.pos()) + def get_selected_indices(self) -> List[QModelIndex]: + """ Return the indices which have been selected by the user, applying a mapping if a filter has been applied """ + indices = self.alarmView.selectionModel().selectedRows() + if self.filter_active_label.isVisible(): + indices = [self.alarm_proxy_model.mapToSource(proxy_index) for proxy_index in indices] + return indices + def plot_pv(self) -> None: """ Send off the signal for plotting a PV """ - indices = self.alarmView.selectedIndexes() + indices = self.get_selected_indices() if len(indices) > 0: index = indices[0] alarm_item = list(self.alarmModel.alarm_items.items())[index.row()][1] @@ -160,7 +166,7 @@ def plot_pv(self) -> None: def copy_alarm_name_to_clipboard(self) -> None: """ Copy the selected PV to the user's clipboard """ - indices = self.alarmView.selectionModel().selectedRows() + indices = self.get_selected_indices() if len(indices) > 0: copy_text = '' for index in indices: @@ -174,7 +180,7 @@ def send_acknowledge_action(self, acknowledged: bool) -> None: if not can_take_action(UserAction.ACKNOWLEDGE, log_warning=True): return - indices = self.alarmView.selectionModel().selectedRows() + indices = self.get_selected_indices() if len(indices) > 0: for index in indices: alarm_item = list(self.alarmModel.alarm_items.items())[index.row()][1] @@ -191,4 +197,4 @@ def send_acknowledge_action(self, acknowledged: bool) -> None: self.kafka_producer.send(self.topic + 'Command', key=f'command:{alarm_path}', value={'user': username, 'host': hostname, 'command': command_to_send}) - + self.alarmView.selectionModel().reset()