diff --git a/damnit/gui/ico/search_icon.png b/damnit/gui/ico/search_icon.png new file mode 100644 index 00000000..b11418b3 Binary files /dev/null and b/damnit/gui/ico/search_icon.png differ diff --git a/damnit/gui/main_window.py b/damnit/gui/main_window.py index 2fcc9894..bcd186f0 100644 --- a/damnit/gui/main_window.py +++ b/damnit/gui/main_window.py @@ -437,8 +437,49 @@ def _create_menu_bar(self) -> None: # Table menu action_columns = QtWidgets.QAction("Select && reorder columns", self) action_columns.triggered.connect(self.open_column_dialog) + self.action_autoscroll = QtWidgets.QAction('Scroll to newly added runs', self) + self.action_autoscroll.setCheckable(True) tableMenu = menu_bar.addMenu("Table") + tableMenu.addAction(action_columns) + tableMenu.addAction(self.action_autoscroll) + + #jump to run + menu_bar_right = QtWidgets.QMenuBar(self) + searchMenu = menu_bar_right.addMenu( + QtGui.QIcon(self.icon_path("search_icon.png")), "&Search Run") + searchMenu.setLayoutDirection(QtCore.Qt.RightToLeft) + self.jump_search_run = QtWidgets.QLineEdit(self) + self.jump_search_run.setPlaceholderText("Jump to run:") + self.jump_search_run.setStyleSheet("width: 120px") + self.jump_search_run.returnPressed.connect(lambda: self.scroll_to_run( + self.jump_search_run.text())) + actionWidget = QtWidgets.QWidgetAction(menu_bar) + actionWidget.setDefaultWidget(self.jump_search_run) + searchMenu.addAction(actionWidget) + menu_bar.setCornerWidget(menu_bar_right, Qt.TopRightCorner) + + + def scroll_to_run(self, run): + try: + run = int(run) + except: + log.info("Invalid input when searching run.") + return + + query_df = self.data[self.data['Run'] == run].index + if len(query_df) == 0: + log.info('Run not found when searching run') + return + + index_row = query_df.values[0] + visible_column = self.table_view.columnAt(0) + if visible_column == -1: + visible_column = 0 + index = self.table_view.model().index(index_row,visible_column) + + self.table_view.scrollTo(index) + self.table_view.selectRow(index.row()) def handle_update(self, message): @@ -557,6 +598,8 @@ def handle_update(self, message): self.table.beginInsertRows(QtCore.QModelIndex(), ix, ix) self.data = new_df self.table.endInsertRows() + if self.action_autoscroll.isChecked(): + self.scroll_to_run(message["Run"]) # update plots and plotting controls self.plot.update_columns() @@ -809,7 +852,7 @@ def _create_view(self) -> None: plot_vertical_layout.addLayout(plot_parameters_horizontal_layout) plotting_group.setLayout(plot_vertical_layout) - + vertical_layout.addWidget(plotting_group) self._view_widget.setLayout(vertical_layout) diff --git a/damnit/gui/table.py b/damnit/gui/table.py index cb8f3d3b..ce483a62 100644 --- a/damnit/gui/table.py +++ b/damnit/gui/table.py @@ -30,6 +30,10 @@ def __init__(self) -> None: self.horizontalHeader().sortIndicatorChanged.connect(self.style_comment_rows) self.verticalHeader().setMinimumSectionSize(ROW_HEIGHT) + self.verticalHeader().setStyleSheet("QHeaderView" + "{" + "background:white;" + "}") # Add the widgets to be used in the column settings dialog self._columns_widget = QtWidgets.QListWidget() @@ -42,7 +46,7 @@ def __init__(self) -> None: self._static_columns_widget.itemChanged.connect(self.item_changed) self._static_columns_widget.setStyleSheet("QListWidget {padding: 0px;} QListWidget::item { margin: 5px; }") self._columns_widget.setStyleSheet("QListWidget {padding: 0px;} QListWidget::item { margin: 5px; }") - + def setModel(self, model): """ Overload of setModel() to make sure that we restyle the comment rows @@ -175,7 +179,8 @@ def get_static_columns(self): def get_static_columns_count(self): return self._static_columns_widget.count() - + + class Table(QtCore.QAbstractTableModel): value_changed = QtCore.pyqtSignal(int, int, str, object) time_comment_changed = QtCore.pyqtSignal(int, str) @@ -400,6 +405,14 @@ def headerData(self, col, orientation, role=Qt.ItemDataRole.DisplayRole): ): name = self._data.columns[col] return self._main_window.column_title(name) + elif( + orientation == Qt.Orientation.Vertical + and role == Qt.ItemDataRole.DisplayRole + ): + row = self._data.iloc[col]['Run'] + if pd.isna(row): + row = '' + return row def flags(self, index) -> Qt.ItemFlag: item_flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled