diff --git a/nexus/StationSelectDialog.py b/nexus/StationSelectDialog.py new file mode 100644 index 0000000000000000000000000000000000000000..03a4ac0d81ce49a5ce470a4a9965d01a4da14ff5 --- /dev/null +++ b/nexus/StationSelectDialog.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*-*# +""" +Dialog for selecting stations to copy +Datalogger Type, Sensor Type and Gain +""" + +import sys +import os + +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QApplication, QTableWidgetItem, QAbstractItemView +from PySide6.QtUiTools import loadUiType + +from .obspyImproved import utc_to_str + +def load_ui(filename): + """ + Helper function + Load a ui file relative to this source file + """ + path = os.path.join(os.path.dirname(__file__), filename) + try: + ret = loadUiType(path) + except Exception as e: + print(e) + raise e + return ret + +class StationSelectDialog(*load_ui('StationSelectDialog.ui')): + def __init__(self, stations, copy, parent=None): + super().__init__(parent) + self.stations = stations + self.stat_map = {} + self.copy = copy + self.setupUi() + + def accept(self): + rows = set(item.row() for item in self.tableWidget.selectedItems()) + self.selected_stations = [] + for row in rows: + self.selected_stations.append(self.stations[row]) + super().accept() + + def sort_table(self, column): + """ + Sort Station Select Dialog table based on column + header selected by user. + """ + row_map = {0: 'code', 1: 'start_date', 2: 'end_date'} + order = self.tableWidget.horizontalHeader().sortIndicatorOrder() + descending = False if order == Qt.AscendingOrder else True + self.stat_map = {ind: v for ind, (_, v) in enumerate(sorted(self.stat_map.items(), + key=lambda item: getattr(item[1], row_map[column]), + reverse=descending))} + + def setupUi(self): + super().setupUi(self) + self.setWindowTitle('Select Stations') + self.tableWidget.setSelectionMode(QAbstractItemView.ExtendedSelection) + + if self.copy == 'type & gain': + self.typeCB.setChecked(True) + self.gainCB.setChecked(True) + else: + self.sensorCB.setChecked(True) + self.tableWidget.setRowCount(len(self.stations)) + self.tableWidget.horizontalHeader().sectionClicked.connect(self.sort_table) + # Add stations to table + for row, stat in enumerate(self.stations): + self.tableWidget.setItem( + row, 0, QTableWidgetItem('{:<3s}'.format(stat.code))) + self.tableWidget.setItem( + row, 1, QTableWidgetItem(utc_to_str(stat.start_date))) + self.tableWidget.setItem( + row, 2, QTableWidgetItem(utc_to_str(stat.end_date))) + self.stat_map[row] = stat + row += 1 + self.tableWidget.resizeColumnsToContents() diff --git a/nexus/StationSelectDialog.ui b/nexus/StationSelectDialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..3bcb50426f874349d34b161690d16df135873b3e --- /dev/null +++ b/nexus/StationSelectDialog.ui @@ -0,0 +1,179 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Dialog</class> + <widget class="QDialog" name="Dialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>469</width> + <height>612</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QCheckBox" name="typeCB"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Copy Datalogger Type</string> + </property> + <property name="toolTip"> + <string>Copy datalogger type from main window to selected stations in table</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="gainCB"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Copy Datalogger Gain</string> + </property> + <property name="toolTip"> + <string>Copy datalogger gain from main window to selected stations in table</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="sensorCB"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Copy Sensor Type</string> + </property> + <property name="toolTip"> + <string>Copy sensor type from main window to selected stations in table</string> + </property> + </widget> + </item> + <item> + <widget class="QTableWidget" name="tableWidget"> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::MultiSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + <property name="cornerButtonEnabled"> + <bool>false</bool> + </property> + <attribute name="horizontalHeaderDefaultSectionSize"> + <number>50</number> + </attribute> + <attribute name="horizontalHeaderShowSortIndicator" stdset="0"> + <bool>true</bool> + </attribute> + <attribute name="horizontalHeaderStretchLastSection"> + <bool>true</bool> + </attribute> + <attribute name="verticalHeaderShowSortIndicator" stdset="0"> + <bool>false</bool> + </attribute> + <attribute name="verticalHeaderStretchLastSection"> + <bool>false</bool> + </attribute> + <column> + <property name="text"> + <string>Stat</string> + </property> + <property name="textAlignment"> + <set>AlignCenter</set> + </property> + </column> + <column> + <property name="text"> + <string>Start</string> + </property> + <property name="textAlignment"> + <set>AlignCenter</set> + </property> + </column> + <column> + <property name="text"> + <string>End</string> + </property> + <property name="textAlignment"> + <set>AlignCenter</set> + </property> + </column> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>Dialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>Dialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> \ No newline at end of file diff --git a/nexus/StationWidget.ui b/nexus/StationWidget.ui index 04fab390a35103fc3cf70481beedc4a333be7cbe..c31e7468238d8e40eeef8cc9a69f3522fbb55354 100644 --- a/nexus/StationWidget.ui +++ b/nexus/StationWidget.ui @@ -71,6 +71,13 @@ </property> </widget> </item> + <item row="3" column="0" colspan="2"> + <widget class="QPushButton" name="copyDL_button"> + <property name="text"> + <string>Copy Type && Gain to More Stations</string> + </property> + </widget> + </item> </layout> </widget> </item> @@ -119,6 +126,13 @@ </property> </widget> </item> + <item row="3" column="0" colspan="2"> + <widget class="QPushButton" name="copySensor_button"> + <property name="text"> + <string>Copy Type to More Stations</string> + </property> + </widget> + </item> </layout> </widget> </item> diff --git a/nexus/nexus.py b/nexus/nexus.py index 377d34a35d66d8ebdc74e7bb0ee28418122d7bd4..dea1058a65d4f43fc436aada67289ade5ea1438e 100755 --- a/nexus/nexus.py +++ b/nexus/nexus.py @@ -22,6 +22,7 @@ from .NRLWizard import NRLWizard, DATALOGGER, SENSOR from . import obspyImproved from . import hardware from .ChannelSelectDialog import ChannelSelectDialog +from .StationSelectDialog import StationSelectDialog # function to display status message, initially just print status_message = print @@ -1190,6 +1191,8 @@ class StationWidget(WidgetBase, *load_ui("StationWidget.ui")): def __init__(self, parent=None): super().__init__(parent) self.build_dl_combo() + self.copyDL_button.clicked.connect(self.copy_dltype_and_gain) + self.copySensor_button.clicked.connect(self.copy_sensor) self.uiDLType.activated.connect(self.combo_changed) self.build_sensor_combo() self.uiSensorType.activated.connect(self.combo_changed) @@ -1284,6 +1287,57 @@ class StationWidget(WidgetBase, *load_ui("StationWidget.ui")): self._data_mapper.addMapping(self.uiSiteRegion, n.col(n.site_region)) self._data_mapper.addMapping(self.uiSiteCountry, n.col(n.site_country)) + def copy_dltype_and_gain(self): + stations = self.get_stations() + self.copy_to_stations(stations, 'type & gain') + + def copy_sensor(self): + stations = self.get_stations() + self.copy_to_stations(stations, 'sensor') + + def copy_to_stations(self, stations, caller): + dialog = StationSelectDialog(stations, caller, parent=self) + if dialog.exec_(): + checked_boxes = {"DLtype": dialog.typeCB.isChecked(), + "DLgain": dialog.gainCB.isChecked(), + "Stype": dialog.sensorCB.isChecked()} + self.update_inventory(dialog.selected_stations, checked_boxes) + + def update_inventory(self, stations, checked_boxes): + for stat in stations: + for node, obj in self.stat_node_to_obj_map.items(): + if stat == obj: + for key, value in checked_boxes.items(): + if value: + if key == "DLtype": + node.set_dl_type(self.uiDLType.currentIndex()) + elif key == "DLgain": + node.set_dl_gain(self.uiDLGain.text()) + else: + node.set_sensor_type(self.uiSensorType.currentIndex()) + break + + def get_stations(self): + """ + Get all stations from inventory to + add to Station Select Dialogue + """ + net = self._data_mapper.rootIndex() + self.stat_node_to_obj_map = {} + stations = [] + net_row = 0 + try: + while True: + for r in range(self._model.rowCount(net)): + station_index = self._model.index(r, 0, net) + station_node = station_index.model().get_node(station_index) + station_obj = station_node._inv_obj + stations.append(station_obj) + self.stat_node_to_obj_map[station_node] = station_obj + net_row += 1 + net = self._model.sibling(net_row, 0, net) + except IndexError: + return stations class ChannelWidget(WidgetBase, *load_ui("ChannelWidget.ui")):