Skip to content

Commit

Permalink
Merge pull request #21317 from jitseniesen/array-toolbar
Browse files Browse the repository at this point in the history
PR: Add toolbar to array editor (Variable Explorer)
  • Loading branch information
ccordoba12 authored Nov 1, 2023
2 parents ec13a25 + 62a48dd commit 467cf7a
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 53 deletions.
148 changes: 95 additions & 53 deletions spyder/plugins/variableexplorer/widgets/arrayeditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,35 @@
from qtpy.QtCore import (QAbstractTableModel, QItemSelection, QLocale,
QItemSelectionRange, QModelIndex, Qt, Slot)
from qtpy.QtGui import QColor, QCursor, QDoubleValidator, QKeySequence
from qtpy.QtWidgets import (QAbstractItemDelegate, QApplication, QCheckBox,
QComboBox, QDialog, QGridLayout, QHBoxLayout,
QInputDialog, QItemDelegate, QLabel, QLineEdit,
QMenu, QMessageBox, QPushButton, QSpinBox,
QStackedWidget, QTableView, QVBoxLayout,
QWidget)
from qtpy.QtWidgets import (
QAbstractItemDelegate, QApplication, QComboBox, QDialog, QGridLayout,
QHBoxLayout, QInputDialog, QItemDelegate, QLabel, QLineEdit, QMenu,
QMessageBox, QPushButton, QSpinBox, QStackedWidget, QTableView,
QVBoxLayout, QWidget)
from spyder_kernels.utils.nsview import value_to_display
from spyder_kernels.utils.lazymodules import numpy as np

# Local imports
from spyder.api.config.fonts import SpyderFontsMixin, SpyderFontType
from spyder.api.widgets.mixins import SpyderWidgetMixin
from spyder.api.widgets.toolbars import SpyderToolbar
from spyder.config.base import _
from spyder.config.manager import CONF
from spyder.plugins.variableexplorer.widgets.basedialog import BaseDialog
from spyder.py3compat import (is_binary_string, is_string, is_text_string,
to_binary_string, to_text_string)
from spyder.utils.icon_manager import ima
from spyder.utils.qthelpers import add_actions, create_action, keybinding
from spyder.plugins.variableexplorer.widgets.basedialog import BaseDialog
from spyder.utils.stylesheet import PANES_TOOLBAR_STYLESHEET


class ArrayEditorActions:
Copy = 'copy_action'
Edit = 'edit_action'
Format = 'format_action'
Resize = 'resize_action'
ToggleBackgroundColor = 'toggle_background_color_action'


# Note: string and unicode data types will be formatted with 's' (see below)
SUPPORTED_FORMATS = {
Expand Down Expand Up @@ -581,6 +592,12 @@ def copy(self):
clipboard = QApplication.clipboard()
clipboard.setText(cliptxt)

def edit_item(self):
"""Edit item"""
index = self.currentIndex()
if index.isValid():
self.edit(index)


class ArrayEditorWidget(QWidget):

Expand Down Expand Up @@ -634,8 +651,11 @@ def change_format(self):
self.model.set_format_spec(format_spec)


class ArrayEditor(BaseDialog):
class ArrayEditor(BaseDialog, SpyderWidgetMixin):
"""Array Editor Dialog"""

CONF_SECTION = 'variable_explorer'

def __init__(self, parent=None):
super().__init__(parent)

Expand Down Expand Up @@ -755,13 +775,60 @@ def setup_and_check(self, data, title='', readonly=False,
self.stack.currentChanged.connect(self.current_widget_changed)
self.layout.addWidget(self.stack, 1, 0)

# ---- Top row of buttons
btn_layout_top = None
# ---- Toolbar and actions
toolbar = SpyderToolbar(parent=self, title='Editor toolbar')
toolbar.setStyleSheet(str(PANES_TOOLBAR_STYLESHEET))

self.copy_action = self.create_action(
ArrayEditorActions.Copy,
text=_('Copy'),
icon=self.create_icon('editcopy'),
triggered=self.arraywidget.view.copy)
toolbar.add_item(self.copy_action)

self.edit_action = self.create_action(
ArrayEditorActions.Edit,
text=_('Edit'),
icon=self.create_icon('edit'),
triggered=self.arraywidget.view.edit_item)
toolbar.add_item(self.edit_action)

self.format_action = self.create_action(
ArrayEditorActions.Format,
text=_('Format'),
icon=self.create_icon('format_float'),
tip=_('Set format of floating-point numbers'),
triggered=self.arraywidget.change_format)
self.format_action.setEnabled(is_float(self.arraywidget.data.dtype))
toolbar.add_item(self.format_action)

self.resize_action = self.create_action(
ArrayEditorActions.Resize,
text=_('Resize'),
icon=self.create_icon('collapse_column'),
tip=_('Resize columns to contents'),
triggered=self.arraywidget.view.resize_to_contents)
toolbar.add_item(self.resize_action)

self.toggle_bgcolor_action = self.create_action(
ArrayEditorActions.ToggleBackgroundColor,
text=_('Background color'),
icon=self.create_icon('background_color'),
toggled=lambda state: self.arraywidget.model.bgcolor(state),
initial=self.arraywidget.model.bgcolor_enabled)
self.toggle_bgcolor_action.setEnabled(
self.arraywidget.model.bgcolor_enabled)
toolbar.add_item(self.toggle_bgcolor_action)

toolbar._render()
self.layout.addWidget(toolbar, 0, 0)

# ---- Buttons in bottom left, if any
btn_layout = QHBoxLayout()
if is_record_array or is_masked_array or data.ndim == 3:
btn_layout_top = QHBoxLayout()

if is_record_array:
btn_layout_top.addWidget(QLabel(_("Record array fields:")))
btn_layout.addWidget(QLabel(_("Record array fields:")))
names = []
for name in data.dtype.names:
field = data.dtype.fields[name]
Expand All @@ -784,20 +851,20 @@ def setup_and_check(self, data, title='', readonly=False,

# Adding the widgets to layout
label = QLabel(_("Axis:"))
btn_layout_top.addWidget(label)
btn_layout_top.addWidget(ra_combo)
btn_layout_top.addWidget(self.shape_label)
btn_layout.addWidget(label)
btn_layout.addWidget(ra_combo)
btn_layout.addWidget(self.shape_label)

label = QLabel(_("Index:"))
btn_layout_top.addWidget(label)
btn_layout_top.addWidget(self.index_spin)
btn_layout.addWidget(label)
btn_layout.addWidget(self.index_spin)

btn_layout_top.addWidget(self.slicing_label)
btn_layout.addWidget(self.slicing_label)
else:
ra_combo = QComboBox(self)
ra_combo.currentIndexChanged.connect(self.stack.setCurrentIndex)
ra_combo.addItems(names)
btn_layout_top.addWidget(ra_combo)
btn_layout.addWidget(ra_combo)

if is_masked_array:
label = QLabel(
Expand All @@ -806,52 +873,26 @@ def setup_and_check(self, data, title='', readonly=False,
label.setToolTip(_("For performance reasons, changes applied "
"to masked arrays won't be reflected in "
"array's data (and vice-versa)."))
btn_layout_top.addWidget(label)

btn_layout_top.addStretch()

# ---- Bottom row of buttons
btn_layout_bottom = QHBoxLayout()

btn_format = QPushButton(_("Format"))
# disable format button for int type
btn_format.setEnabled(is_float(self.arraywidget.data.dtype))
btn_layout_bottom.addWidget(btn_format)
btn_format.clicked.connect(self.arraywidget.change_format)
btn_layout.addWidget(label)

btn_resize = QPushButton(_("Resize"))
btn_layout_bottom.addWidget(btn_resize)
btn_resize.clicked.connect(self.arraywidget.view.resize_to_contents)

self.bgcolor = QCheckBox(_('Background color'))
self.bgcolor.setEnabled(self.arraywidget.model.bgcolor_enabled)
self.bgcolor.setChecked(self.arraywidget.model.bgcolor_enabled)
self.bgcolor.stateChanged.connect(
lambda state: self.arraywidget.model.bgcolor(state))
btn_layout_bottom.addWidget(self.bgcolor)

btn_layout_bottom.addStretch()
# ---- Buttons on bottom right
btn_layout.addStretch()

if not readonly:
self.btn_save_and_close = QPushButton(_('Save and Close'))
self.btn_save_and_close.setDisabled(True)
self.btn_save_and_close.clicked.connect(self.accept)
btn_layout_bottom.addWidget(self.btn_save_and_close)
btn_layout.addWidget(self.btn_save_and_close)

self.btn_close = QPushButton(_('Close'))
self.btn_close.setAutoDefault(True)
self.btn_close.setDefault(True)
self.btn_close.clicked.connect(self.reject)
btn_layout_bottom.addWidget(self.btn_close)
btn_layout.addWidget(self.btn_close)

# ---- Final layout
btn_layout_bottom.setContentsMargins(4, 4, 4, 4)
if btn_layout_top is not None:
btn_layout_top.setContentsMargins(4, 4, 4, 4)
self.layout.addLayout(btn_layout_top, 2, 0)
self.layout.addLayout(btn_layout_bottom, 3, 0)
else:
self.layout.addLayout(btn_layout_bottom, 2, 0)
btn_layout.setContentsMargins(4, 4, 4, 4)
self.layout.addLayout(btn_layout, 2, 0)

# Set minimum size
self.setMinimumSize(500, 300)
Expand All @@ -872,7 +913,8 @@ def save_and_close_enable(self, left_top, bottom_right):
def current_widget_changed(self, index):
self.arraywidget = self.stack.widget(index)
self.arraywidget.model.dataChanged.connect(self.save_and_close_enable)
self.bgcolor.setChecked(self.arraywidget.model.bgcolor_enabled)
self.toggle_bgcolor_action.setChecked(
self.arraywidget.model.bgcolor_enabled)

def change_active_widget(self, index):
"""
Expand Down
2 changes: 2 additions & 0 deletions spyder/utils/icon_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ def __init__(self):
'collapse_column': [('mdi.arrow-collapse-horizontal',), {'color': self.MAIN_FG_COLOR}],
'collapse_row': [('mdi.arrow-collapse-vertical',), {'color': self.MAIN_FG_COLOR}],
'edit_remove': [('mdi.minus',), {'color': self.MAIN_FG_COLOR}],
'format_float': [('mdi.decimal-increase',), {'color': self.MAIN_FG_COLOR}],
'background_color': [('mdi.format-color-fill',), {'color': self.MAIN_FG_COLOR}],
'browse_tab': [('mdi.tab',), {'color': self.MAIN_FG_COLOR}],
'filelist': [('mdi.view-list',), {'color': self.MAIN_FG_COLOR}],
'newwindow': [('mdi.window-maximize',), {'color': self.MAIN_FG_COLOR}],
Expand Down

0 comments on commit 467cf7a

Please sign in to comment.