Source code for wonambi.widgets.modal_widgets
from datetime import timedelta
from operator import itemgetter
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QAbstractItemView,
QComboBox,
QDateTimeEdit,
QDialog,
QDialogButtonBox,
QFileDialog,
QFormLayout,
QLabel,
QListWidget,
QListWidgetItem,
QPushButton,
QSpinBox,
)
from .utils import FormMenu, STAGE_NAME
[docs]class ChannelDialog(QDialog):
"""Template dialog for event detection.
Attributes
----------
parent : instance of QMainWindow
the main window
groups : list of dict
information about groups from Channels
index : dict of FormFloat
Contains detection parameters.
bbox : QDialogButtonBox
Button box with Ok and Cancel
idx_group : FormMenu
Combo box of channel groups.
idx_chan : QListWidget
List widget containing all channels for selected group.
idx_stage : QListWidget
List widget containing all stages.
idx_cycle : QListWidget
List widget containing all marked cycles.
one_grp : dict
info about selected group from Channels
"""
def __init__(self, parent):
super().__init__(None, Qt.WindowSystemMenuHint | Qt.WindowTitleHint)
self.parent = parent
self.setWindowModality(Qt.WindowModal)
self.groups = self.parent.channels.groups
self.index = {}
self.cycles = None
self.create_widgets()
[docs] def create_widgets(self):
"""Build basic components of dialog."""
self.bbox = QDialogButtonBox(
QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.idx_ok = self.bbox.button(QDialogButtonBox.Ok)
self.idx_cancel = self.bbox.button(QDialogButtonBox.Cancel)
self.idx_group = FormMenu([gr['name'] for gr in self.groups])
chan_box = QListWidget()
self.idx_chan = chan_box
stage_box = QListWidget()
stage_box.addItems(STAGE_NAME)
stage_box.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.idx_stage = stage_box
cycle_box = QListWidget()
cycle_box.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.idx_cycle = cycle_box
[docs] def update_groups(self):
"""Update the channel groups list when dialog is opened."""
self.groups = self.parent.channels.groups
self.idx_group.clear()
for gr in self.groups:
self.idx_group.addItem(gr['name'])
self.update_channels()
[docs] def update_channels(self):
"""Update the channels list when a new group is selected."""
group_dict = {k['name']: i for i, k in enumerate(self.groups)}
group_index = group_dict[self.idx_group.currentText()]
self.one_grp = self.groups[group_index]
self.idx_chan.clear()
self.idx_chan.setSelectionMode(QAbstractItemView.ExtendedSelection)
for chan in self.one_grp['chan_to_plot']:
name = chan + '—(' + '+'.join(self.one_grp['ref_chan']) + ')'
item = QListWidgetItem(name)
self.idx_chan.addItem(item)
[docs] def update_cycles(self):
"""Enable cycles checkbox only if there are cycles marked, with no
errors."""
self.idx_cycle.clear()
try:
self.cycles = self.parent.notes.annot.get_cycles()
except ValueError as err:
self.idx_cycle.setEnabled(False)
msg = 'There is a problem with the cycle markers: ' + str(err)
self.parent.statusBar().showMessage(msg)
else:
if self.cycles is None:
self.idx_cycle.setEnabled(False)
else:
self.idx_cycle.setEnabled(True)
for i in range(len(self.cycles)):
self.idx_cycle.addItem(str(i+1))
[docs] def get_channels(self):
"""Get the selected channel(s in order).
Returns
-------
list of str
name of each channel (without group), in original record order
"""
selectedItems = self.idx_chan.selectedItems()
selected_chan = [x.text().split('—')[0] for x in selectedItems]
chan_in_order = []
for chan in self.one_grp['chan_to_plot']:
if chan in selected_chan:
chan_in_order.append(chan)
return chan_in_order
[docs] def get_cycles(self):
"""Get the selected cycle(s in order).
Returns
-------
list of tuple
Each tuple is (start time (sec), end time (sec), index (starting
at 1)."""
idx_cyc_sel = [
int(x.text()) - 1 for x in self.idx_cycle.selectedItems()]
if not idx_cyc_sel:
cycle = None
else:
cycle = itemgetter(*idx_cyc_sel)(self.cycles)
if len(idx_cyc_sel) == 1:
cycle = [cycle]
return cycle
[docs]class DateTimeDialog(QDialog):
"""Dialog to specify time in the recordings, either as seconds from the
start of the recordings or absolute time.
Parameters
----------
title : str
'Lights out' or 'Lights on'
start_time : datetime
absolute start time of the recordings
dur : int
total duration of the recordings
Notes
-----
The value of interest is in self.idx_seconds.value(), which is seconds
from the start of the recordings.
"""
def __init__(self, title, start_time, dur):
super().__init__()
self.start_time = start_time
self.dur = dur
end_time = start_time + timedelta(seconds=dur)
self.setWindowTitle(title)
bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.idx_ok = bbox.button(QDialogButtonBox.Ok)
self.idx_cancel = bbox.button(QDialogButtonBox.Cancel)
bbox.clicked.connect(self.button_clicked)
self.idx_seconds = QSpinBox()
self.idx_seconds.setMinimum(0)
self.idx_seconds.setMaximum(dur)
self.idx_seconds.valueChanged.connect(self.changed_spin)
self.idx_datetime = QDateTimeEdit(start_time)
self.idx_datetime.setMinimumDate(start_time)
self.idx_datetime.setMaximumDate(end_time)
self.idx_datetime.setDisplayFormat('dd-MMM-yyyy HH:mm:ss')
self.idx_datetime.dateTimeChanged.connect(self.changed_datetime)
layout = QFormLayout()
layout.addRow('', QLabel('Enter ' + title + ' time'))
layout.addRow('Seconds from recording start', self.idx_seconds)
layout.addRow('Absolute time', self.idx_datetime)
layout.addRow(bbox)
self.setLayout(layout)
[docs] def button_clicked(self, button):
if button == self.idx_ok:
self.accept()
elif button == self.idx_cancel:
self.reject()
[docs] def changed_spin(self, i):
self.idx_datetime.blockSignals(True)
self.idx_datetime.setDateTime(self.start_time + timedelta(seconds=i))
self.idx_datetime.blockSignals(False)
[docs] def changed_datetime(self, dt):
val = (dt.toPyDateTime() - self.start_time).total_seconds()
if val < 0 or val >= self.dur:
val = min(self.dur, max(val, 0))
self.changed_spin(val)
self.idx_seconds.blockSignals(True)
self.idx_seconds.setValue(val)
self.idx_seconds.blockSignals(False)
[docs]class SVGDialog(QDialog):
def __init__(self, dirname):
super().__init__()
self.dirname = str(dirname)
self.setWindowTitle('Export to SVG')
bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.idx_ok = bbox.button(QDialogButtonBox.Ok)
self.idx_cancel = bbox.button(QDialogButtonBox.Cancel)
bbox.clicked.connect(self.button_clicked)
self.idx_list = QComboBox()
self.idx_list.addItems(['Traces', 'Overview'])
self.idx_file = QPushButton()
self.idx_file.setText('(click to choose file)')
self.idx_file.clicked.connect(self.select_filename)
layout = QFormLayout()
layout.addRow('Which Panel', self.idx_list)
layout.addRow('File Name', self.idx_file)
layout.addRow(bbox)
self.setLayout(layout)
[docs] def button_clicked(self, button):
if button == self.idx_ok:
self.accept()
elif button == self.idx_cancel:
self.reject()
[docs] def select_filename(self):
filename, _ = QFileDialog.getSaveFileName(
self, 'Export screenshot', self.dirname, 'Image (*.svg)')
if filename == '':
return
self.idx_file.setText(filename)