20
20
QDoubleValidator, QDialog, QDialogButtonBox,
21
21
QMessageBox, QPushButton, QInputDialog, QMenu,
22
22
QApplication, QKeySequence, QLabel, QComboBox,
23
QStackedWidget, QWidget, QVBoxLayout)
23
QSpinBox, QStackedWidget, QWidget, QVBoxLayout)
24
24
from spyderlib.qt.QtCore import (Qt, QModelIndex, QAbstractTableModel, SIGNAL,
26
26
from spyderlib.qt.compat import to_qvariant, from_qvariant
446
446
self.arraywidget = None
447
447
self.stack = None
448
448
self.layout = None
449
# Values for 3d array editor
450
self.dim_indexes = [{}, {}, {}]
451
self.last_dim = 0 # Adjust this for changing the startup dimension
450
453
def setup_and_check(self, data, title='', readonly=False,
451
454
xlabels=None, ylabels=None):
474
477
if not is_record_array:
475
478
dtn = data.dtype.name
476
if dtn not in SUPPORTED_FORMATS and not dtn.startswith('string') \
479
if dtn not in SUPPORTED_FORMATS and not dtn.startswith('str') \
477
480
and not dtn.startswith('unicode'):
478
481
arr = _("%s arrays") % data.dtype.name
479
482
self.error(_("%s are currently not supported") % arr)
529
534
names.append(text)
531
536
names = [_('Masked data'), _('Data'), _('Mask')]
532
ra_combo = QComboBox(self)
533
self.connect(ra_combo, SIGNAL('currentIndexChanged(int)'),
534
self.stack.setCurrentIndex)
535
ra_combo.addItems(names)
536
btn_layout.addWidget(ra_combo)
539
self.index_spin = QSpinBox(self, keyboardTracking=False)
540
self.connect(self.index_spin, SIGNAL('valueChanged(int)'),
541
self.change_active_widget)
543
names = [str(i) for i in range(3)]
544
ra_combo = QComboBox(self)
545
ra_combo.addItems(names)
546
self.connect(ra_combo, SIGNAL('currentIndexChanged(int)'),
547
self.current_dim_changed)
548
# Adding the widgets to layout
549
label = QLabel(_("Axis:"))
550
btn_layout.addWidget(label)
551
btn_layout.addWidget(ra_combo)
552
self.shape_label = QLabel()
553
btn_layout.addWidget(self.shape_label)
554
label = QLabel(_("Index:"))
555
btn_layout.addWidget(label)
556
btn_layout.addWidget(self.index_spin)
557
self.slicing_label = QLabel()
558
btn_layout.addWidget(self.slicing_label)
559
# set the widget to display when launched
560
self.current_dim_changed(self.last_dim)
562
ra_combo = QComboBox(self)
563
self.connect(ra_combo, SIGNAL('currentIndexChanged(int)'),
564
self.stack.setCurrentIndex)
565
ra_combo.addItems(names)
566
btn_layout.addWidget(ra_combo)
537
567
if is_masked_array:
538
568
label = QLabel(_("<u>Warning</u>: changes are applied separately"))
539
569
label.setToolTip(_("For performance reasons, changes applied "\
546
576
self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()"))
547
577
btn_layout.addWidget(bbox)
548
578
self.layout.addLayout(btn_layout, 2, 0)
550
580
self.setMinimumSize(400, 300)
552
582
# Make the dialog act as a window
553
583
self.setWindowFlags(Qt.Window)
557
587
def current_widget_changed(self, index):
558
self.arraywidget = self.stack.widget(index)
588
self.arraywidget = self.stack.widget(index)
590
def change_active_widget(self, index):
592
This is implemented for handling negative values in index for
593
3d arrays, to give the same behavior as slicing
595
string_index = [':']*3
596
string_index[self.last_dim] = '<font color=red>%i</font>'
597
self.slicing_label.setText((r"Slicing: [" + ", ".join(string_index) +
600
data_index = self.data.shape[self.last_dim] + index
603
slice_index = [slice(None)]*3
604
slice_index[self.last_dim] = data_index
606
stack_index = self.dim_indexes[self.last_dim].get(data_index)
607
if stack_index == None:
608
stack_index = self.stack.count()
609
self.stack.addWidget(ArrayEditorWidget(self,
610
self.data[slice_index]))
611
self.dim_indexes[self.last_dim][data_index] = stack_index
613
self.stack.setCurrentIndex(stack_index)
615
def current_dim_changed(self, index):
617
This change the active axis the array editor is plotting over
620
self.last_dim = index
621
string_size = ['%i']*3
622
string_size[index] = '<font color=red>%i</font>'
623
self.shape_label.setText(('Shape: (' + ', '.join(string_size) +
624
') ') % self.data.shape)
625
if self.index_spin.value() != 0:
626
self.index_spin.setValue(0)
628
# this is done since if the value is currently 0 it does not emit
629
# currentIndexChanged(int)
630
self.change_active_widget(0)
631
self.index_spin.setRange(-self.data.shape[index],
632
self.data.shape[index]-1)
560
634
def accept(self):
561
635
"""Reimplement Qt method"""
562
636
for index in range(self.stack.count()):
628
702
print(arr_in is arr_out)
629
703
arr = np.array([1, 2, 3], dtype="int8")
630
704
print("out:", test_edit(arr, "int array"))
705
arr = np.zeros((3,3,4))
709
print("out:", test_edit(arr))
633
712
if __name__ == "__main__":