From adf9dba559e004ba09ea10d2a0f965cb62d36e9a Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Thu, 14 Apr 2016 11:17:10 -0700 Subject: [PATCH 01/29] working on implementing multiple gm editors --- cdatgui/editors/boxfill.py | 87 ++------------------ cdatgui/editors/graphics_method_editor.py | 96 +++++++++++++++++++++++ cdatgui/editors/isofill.py | 29 +++++++ cdatgui/editors/level_editor.py | 13 ++- cdatgui/editors/model/legend.py | 8 +- cdatgui/editors/widgets/adjust_values.py | 1 + cdatgui/editors/widgets/legend_widget.py | 26 ++++-- cdatgui/graphics/dialog.py | 13 ++- cdatgui/sidebar/inspector_widget.py | 10 +-- 9 files changed, 183 insertions(+), 100 deletions(-) create mode 100644 cdatgui/editors/graphics_method_editor.py create mode 100644 cdatgui/editors/isofill.py diff --git a/cdatgui/editors/boxfill.py b/cdatgui/editors/boxfill.py index 6252146..8a0c5a1 100644 --- a/cdatgui/editors/boxfill.py +++ b/cdatgui/editors/boxfill.py @@ -1,26 +1,20 @@ from PySide import QtGui, QtCore from collections import OrderedDict -from level_editor import LevelEditor + from widgets.legend_widget import LegendEditorWidget from model.legend import VCSLegend -from axis_editor import AxisEditorWidget -from model.vcsaxis import VCSAxis +from .graphics_method_editor import GraphicsMethodEditorWidget -class BoxfillEditor(QtGui.QWidget): +class BoxfillEditor(GraphicsMethodEditorWidget): """Configures a boxfill graphics method.""" - graphicsMethodUpdated = QtCore.Signal(object) - def __init__(self, parent=None): """Initialize the object.""" super(BoxfillEditor, self).__init__(parent=parent) - self._gm = None - self.var = None - self.tmpl = None - layout = QtGui.QVBoxLayout() - self.setLayout(layout) + legend_button = QtGui.QPushButton("Edit Legend") + legend_button.clicked.connect(self.editLegend) self.boxfill_types = OrderedDict( Linear="linear", @@ -37,67 +31,14 @@ def __init__(self, parent=None): button_layout.addWidget(radiobutton) self.type_group.addButton(radiobutton) - layout.addLayout(button_layout) - - levels_button = QtGui.QPushButton("Edit Levels") - levels_button.clicked.connect(self.editLevels) - legend_button = QtGui.QPushButton("Edit Legend") - legend_button.clicked.connect(self.editLegend) - - left_axis = QtGui.QPushButton("Edit Left Ticks") - left_axis.clicked.connect(self.editLeft) - right_axis = QtGui.QPushButton("Edit Right Ticks") - right_axis.clicked.connect(self.editRight) - bottom_axis = QtGui.QPushButton("Edit Bottom Ticks") - bottom_axis.clicked.connect(self.editBottom) - top_axis = QtGui.QPushButton("Edit Top Ticks") - top_axis.clicked.connect(self.editTop) - - layout.addWidget(levels_button) - layout.addWidget(legend_button) - layout.addWidget(left_axis) - layout.addWidget(right_axis) - layout.addWidget(top_axis) - layout.addWidget(bottom_axis) - - self.level_editor = None - self.legend_editor = None - self.axis_editor = None self.type_group.buttonClicked.connect(self.setBoxfillType) - def editAxis(self, axis): - if self.axis_editor is None: - self.axis_editor = AxisEditorWidget(axis[0]) - self.axis_editor.okPressed.connect(self.updated) - axis = VCSAxis(self._gm, self.tmpl, axis, self.var) - self.axis_editor.setAxisObject(axis) - self.axis_editor.show() - self.axis_editor.raise_() - - def editLeft(self): - self.editAxis("y1") - - def editRight(self): - self.editAxis("y2") - - def editBottom(self): - self.editAxis("x1") - - def editTop(self): - self.editAxis("x2") - - def editLevels(self): - """Edit the levels of this GM.""" - if self.level_editor is None: - self.level_editor = LevelEditor() - self.level_editor.levelsUpdated.connect(self.updated) - self.level_editor.gm = self.gm - self.level_editor.var = self.var.var - self.level_editor.show() - self.level_editor.raise_() + self.button_layout.insertLayout(0, button_layout) + self.button_layout.insertWidget(2, legend_button) def editLegend(self): if self.legend_editor is None: + print "launching boxfill legend editor" self.legend_editor = LegendEditorWidget() self.legend_editor.okPressed.connect(self.updated) legend = VCSLegend(self.gm, self.var.var) @@ -105,17 +46,6 @@ def editLegend(self): self.legend_editor.show() self.legend_editor.raise_() - def updated(self): - if self.legend_editor is not None: - self.legend_editor = None - if self.axis_editor is not None: - self.axis_editor = None - if self.level_editor is not None: - self.level_editor = None - print "Emitting updated" - self.graphicsMethodUpdated.emit(self._gm) - print "Updated" - @property def gm(self): """GM property.""" @@ -123,7 +53,6 @@ def gm(self): @gm.setter def gm(self, value): - """GM setter.""" self._gm = value type_real_vals = self.boxfill_types.values() index = type_real_vals.index(value.boxfill_type) diff --git a/cdatgui/editors/graphics_method_editor.py b/cdatgui/editors/graphics_method_editor.py new file mode 100644 index 0000000..dd4bb8e --- /dev/null +++ b/cdatgui/editors/graphics_method_editor.py @@ -0,0 +1,96 @@ +from PySide import QtGui, QtCore +from level_editor import LevelEditor +from axis_editor import AxisEditorWidget +from model.vcsaxis import VCSAxis + + +class GraphicsMethodEditorWidget(QtGui.QWidget): + """Configures a boxfill graphics method.""" + + graphicsMethodUpdated = QtCore.Signal(object) + + def __init__(self, parent=None): + """Initialize the object.""" + super(GraphicsMethodEditorWidget, self).__init__(parent=parent) + self._gm = None + self.var = None + self.tmpl = None + + self.button_layout = QtGui.QVBoxLayout() + self.setLayout(self.button_layout) + + levels_button = QtGui.QPushButton("Edit Levels") + levels_button.clicked.connect(self.editLevels) + + left_axis = QtGui.QPushButton("Edit Left Ticks") + left_axis.clicked.connect(self.editLeft) + right_axis = QtGui.QPushButton("Edit Right Ticks") + right_axis.clicked.connect(self.editRight) + bottom_axis = QtGui.QPushButton("Edit Bottom Ticks") + bottom_axis.clicked.connect(self.editBottom) + top_axis = QtGui.QPushButton("Edit Top Ticks") + top_axis.clicked.connect(self.editTop) + + self.button_layout.addWidget(levels_button) + self.button_layout.addWidget(left_axis) + self.button_layout.addWidget(right_axis) + self.button_layout.addWidget(top_axis) + self.button_layout.addWidget(bottom_axis) + + self.level_editor = None + self.legend_editor = None + self.axis_editor = None + + def editAxis(self, axis): + if self.axis_editor is None: + self.axis_editor = AxisEditorWidget(axis[0]) + self.axis_editor.okPressed.connect(self.updated) + axis = VCSAxis(self._gm, self.tmpl, axis, self.var) + self.axis_editor.setAxisObject(axis) + self.axis_editor.show() + self.axis_editor.raise_() + + def editLeft(self): + self.editAxis("y1") + + def editRight(self): + self.editAxis("y2") + + def editBottom(self): + self.editAxis("x1") + + def editTop(self): + self.editAxis("x2") + + def editLevels(self): + """Edit the levels of this GM.""" + if self.level_editor is None: + self.level_editor = LevelEditor() + self.level_editor.levelsUpdated.connect(self.updated) + self.level_editor.gm = self.gm + self.level_editor.var = self.var.var + self.level_editor.show() + self.level_editor.raise_() + + def updated(self): + if self.legend_editor is not None: + self.legend_editor = None + if self.axis_editor is not None: + self.axis_editor = None + if self.level_editor is not None: + self.level_editor = None + print "Emitting updated" + self.graphicsMethodUpdated.emit(self._gm) + print "Updated" + # pdb.set_trace() + + @property + def gm(self): + """GM property.""" + return self._gm + + @gm.setter + def gm(self, value): + """GM setter.""" + self._gm = value + diff --git a/cdatgui/editors/isofill.py b/cdatgui/editors/isofill.py new file mode 100644 index 0000000..f54c3d3 --- /dev/null +++ b/cdatgui/editors/isofill.py @@ -0,0 +1,29 @@ +from PySide import QtGui, QtCore +from widgets.legend_widget import LegendEditorWidget +from model.legend import VCSLegend +from .graphics_method_editor import GraphicsMethodEditorWidget + + +class IsofillEditor(GraphicsMethodEditorWidget): + """Configures a boxfill graphics method.""" + + def __init__(self, parent=None): + """Initialize the object.""" + super(IsofillEditor, self).__init__(parent=parent) + + legend_button = QtGui.QPushButton("Edit Legend") + legend_button.clicked.connect(self.editLegend) + + self.button_layout.insertWidget(1, legend_button) + + def editLegend(self): + if self.legend_editor is None: + self.legend_editor = LegendEditorWidget() + print "disabling start and end color widgets." + # self.legend_editor.end_color_widget.setEnabled(False) + # self.legend_editor.start_color_widget.setEnabled(False) + self.legend_editor.okPressed.connect(self.updated) + legend = VCSLegend(self.gm, self.var.var) + self.legend_editor.setObject(legend) + self.legend_editor.show() + self.legend_editor.raise_() \ No newline at end of file diff --git a/cdatgui/editors/level_editor.py b/cdatgui/editors/level_editor.py index a358cc4..a807a9f 100644 --- a/cdatgui/editors/level_editor.py +++ b/cdatgui/editors/level_editor.py @@ -42,7 +42,6 @@ def __init__(self, parent=None): button_layout.addWidget(self.reset) button_layout.addWidget(self.apply) - def reset_levels(self): self.gm.levels = self.orig_levs self.update_levels(self.gm.levels) @@ -67,7 +66,9 @@ def var(self, value): flat = self._var.flatten() var_min, var_max = vcs.minmax(flat) # Check if we're using auto levels + print "HAS GM LEVELS?", self.has_set_gm_levels() if self._gm is None or not self.has_set_gm_levels(): + print "MAKING SCALE" # Update the automatic levels with this variable levs = vcs.utils.mkscale(var_min, var_max) else: @@ -75,6 +76,7 @@ def var(self, value): levs = self._gm.levels self.canvas.clear() + print "updating value slider. min->{0} max->{1}".format(var_min, var_max) self.value_sliders.update(var_min, var_max, levs) self.update_levels(levs, clear=True) @@ -93,6 +95,11 @@ def gm(self, value): self.value_sliders.update(var_min, var_max, levs) self.update_levels(levs, clear=True) - def has_set_gm_levels(self): - return len(self._gm.levels) != 2 or not numpy.allclose(self._gm.levels, [1e+20] * 2) + print "checking gm levels", len(self._gm.levels) != 2, not numpy.allclose(self._gm.levels, [1e+20] * 2) + # print self._gm.levels, [1e+20] * 2 + try: + length = len(self._gm.levels[0]) + except: + length = len(self._gm.levels) + return length != 2 or not numpy.allclose(self._gm.levels, [1e+20] * 2) diff --git a/cdatgui/editors/model/legend.py b/cdatgui/editors/model/legend.py index d8542de..445e5dc 100644 --- a/cdatgui/editors/model/legend.py +++ b/cdatgui/editors/model/legend.py @@ -38,6 +38,7 @@ def vcs_colors(self): """Used internally, don't worry about it.""" levs = self.levels if self._gm.fillareacolors: + print "fill area colors", self._gm.fillareacolors colors = self._gm.fillareacolors return colors else: @@ -46,7 +47,12 @@ def vcs_colors(self): levs = levs[1:] if self.ext_right: levs = levs[:-1] - colors = vcs.getcolors(levs, colors=range(self.color_1, self.color_2)) + if self.color_1 and self.color_2: + print "getting colors from color1 and color2" + colors = vcs.getcolors(levs, colors=range(self.color_1, self.color_2)) + else: + print "COLOR1, COLOR2 None", self.levels + # colors = vcs.getcolors(levs, colors=range(min(self.levels), max(self.levels))) levs = real_levs if len(colors) < len(levs): # Pad out colors to the right number of buckets diff --git a/cdatgui/editors/widgets/adjust_values.py b/cdatgui/editors/widgets/adjust_values.py index 241133a..eaed19f 100644 --- a/cdatgui/editors/widgets/adjust_values.py +++ b/cdatgui/editors/widgets/adjust_values.py @@ -34,6 +34,7 @@ def add_level(self): self.send_values() def update(self, minval, maxval, values): + print "UPDATING:", minval, maxval, values if minval >= maxval: raise ValueError("Minimum value %d >= maximum value %d" % (minval, maxval)) self.min_val = minval diff --git a/cdatgui/editors/widgets/legend_widget.py b/cdatgui/editors/widgets/legend_widget.py index 3e6603a..13d7dc6 100644 --- a/cdatgui/editors/widgets/legend_widget.py +++ b/cdatgui/editors/widgets/legend_widget.py @@ -286,10 +286,14 @@ def __init__(self, parent=None): start_color_layout.addWidget(start_color_label) start_color_layout.addWidget(self.start_color_spin) start_color_layout.addWidget(self.start_color_button) + self.start_color_widget = QtGui.QWidget() + self.start_color_widget.setLayout(start_color_layout) end_color_layout.addWidget(end_color_label) end_color_layout.addWidget(self.end_color_spin) end_color_layout.addWidget(self.end_color_button) + self.end_color_widget = QtGui.QWidget() + self.end_color_widget.setLayout(end_color_layout) extend_layout.addWidget(extend_left_check) extend_layout.addWidget(extend_left_label) @@ -307,8 +311,8 @@ def __init__(self, parent=None): # Insert layouts self.vertical_layout.insertLayout(1, colormap_layout) - self.vertical_layout.insertLayout(2, start_color_layout) - self.vertical_layout.insertLayout(3, end_color_layout) + self.vertical_layout.insertWidget(2, self.start_color_widget) + self.vertical_layout.insertWidget(3, self.end_color_widget) self.vertical_layout.insertLayout(4, extend_layout) self.vertical_layout.insertLayout(5, custom_fill_layout) self.vertical_layout.insertLayout(6, labels_layout) @@ -316,13 +320,19 @@ def __init__(self, parent=None): def setObject(self, legend): self.object = legend - self.start_color_spin.setValue(self.object.color_1) - self.updateButtonColor(self.start_color_button, self.object.color_1) - self.start_color_button.setFixedSize(100, 25) + try: + self.start_color_spin.setValue(self.object.color_1) + self.updateButtonColor(self.start_color_button, self.object.color_1) + self.start_color_button.setFixedSize(100, 25) + except TypeError: + self.start_color_widget.setEnabled(False) - self.end_color_spin.setValue(self.object.color_2) - self.updateButtonColor(self.end_color_button, self.object.color_2) - self.end_color_button.setFixedSize(100, 25) + try: + self.end_color_spin.setValue(self.object.color_2) + self.updateButtonColor(self.end_color_button, self.object.color_2) + self.end_color_button.setFixedSize(100, 25) + except TypeError: + self.end_color_widget.setEnabled(False) self.preview.setLegendObject(legend) self.preview.update() diff --git a/cdatgui/graphics/dialog.py b/cdatgui/graphics/dialog.py index e2dd3a8..ddffc68 100644 --- a/cdatgui/graphics/dialog.py +++ b/cdatgui/graphics/dialog.py @@ -1,17 +1,21 @@ from PySide import QtGui, QtCore from cdatgui.editors.boxfill import BoxfillEditor +from cdatgui.editors.isofill import IsofillEditor import vcs -class BoxfillDialog(QtGui.QDialog): +class GraphcisMethodDialog(QtGui.QDialog): editedGM = QtCore.Signal(object) createdGM = QtCore.Signal(object) def __init__(self, gm, var, tmpl, parent=None): - super(BoxfillDialog, self).__init__(parent=parent) + super(GraphcisMethodDialog, self).__init__(parent=parent) + # self.graphics_methods = ['boxfill', 'isofill', 'isoline', 'meshfill', '3d_scalar', '3d_dual_scalar', + layout = QtGui.QVBoxLayout() self.gm = gm - self.editor = BoxfillEditor() + self.editor = eval('{0}Editor()'.format(vcs.graphicsmethodtype(self.gm).capitalize())) + # self.editor = BoxfillEditor() self.editor.gm = gm self.editor.var = var self.editor.tmpl = tmpl @@ -44,5 +48,6 @@ def save(self, name=None): if name is None: self.editedGM.emit(self.gm) else: - gm = vcs.createboxfill(name, self.gm) + # gm = vcs.createboxfill(name, self.gm) + gm = eval('vcs.create{0}(name, self.gm)'.format(vcs.graphicsmethodtype(self.gm))) self.createdGM.emit(gm) diff --git a/cdatgui/sidebar/inspector_widget.py b/cdatgui/sidebar/inspector_widget.py index 0628013..1698554 100644 --- a/cdatgui/sidebar/inspector_widget.py +++ b/cdatgui/sidebar/inspector_widget.py @@ -6,7 +6,7 @@ from cdatgui.templates import get_templates from cdatgui.variables.edit_variable_widget import EditVariableDialog from cdatgui.templates.dialog import TemplateEditorDialog -from cdatgui.graphics.dialog import BoxfillDialog +from cdatgui.graphics.dialog import GraphcisMethodDialog import vcs @@ -168,7 +168,7 @@ def editSecondVar(self, var): self.editVariable(var) def editGraphicsMethod(self, gm): - get_gms().replace(get_gms().indexOf("boxfill", gm), gm) + get_gms().replace(get_gms().indexOf(vcs.graphicsmethodtype(gm), gm), gm) self.current_plot.graphics_method = gm def makeGraphicsMethod(self, gm): @@ -184,7 +184,7 @@ def editGM(self): if self.gm_editor: self.gm_editor.reject() self.gm_editor.deleteLater() - self.gm_editor = BoxfillDialog(gm, self.var_combos[0].currentObj(), self.template_combo.currentObj()) + self.gm_editor = GraphcisMethodDialog(gm, self.var_combos[0].currentObj(), self.template_combo.currentObj()) self.gm_editor.createdGM.connect(self.makeGraphicsMethod) self.gm_editor.editedGM.connect(self.editGraphicsMethod) self.gm_editor.show() @@ -220,6 +220,7 @@ def setTemplate(self, template): self.current_plot.template = template def updateGM(self, index): + self.edit_gm_button.setEnabled(True) gm_type = self.gm_type_combo.currentText() gm_name = self.gm_instance_combo.currentText() @@ -261,7 +262,7 @@ def selectPlot(self, plot): block = self.template_combo.blockSignals(True) self.template_combo.setCurrentIndex(self.template_combo.findText(plot.template.name)) self.template_combo.blockSignals(block) - if self.gm_type_combo.currentText() == "boxfill": + if self.gm_type_combo.currentText() == "boxfill" and self.gm_instance_combo.currentText() != '': self.edit_gm_button.setEnabled(True) else: self.edit_gm_button.setEnabled(False) @@ -275,7 +276,6 @@ def selectPlot(self, plot): v.setEnabled(False) def selection_change(self, selected): - plots = [] self.cells = [] self.plots.clear() for cell in selected: From 1534eff21ae4d8c483b8bce8f9a1fae41181a9f7 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Fri, 15 Apr 2016 12:43:23 -0700 Subject: [PATCH 02/29] Working on creating editors for graphics methods. fixed bugs with communication between inspector PlotInfo and console --- cdatgui/bases/window_widget.py | 1 + cdatgui/cdat/plotter.py | 13 ++++++ cdatgui/cdat/vcswidget.py | 19 +++++++- cdatgui/editors/boxfill.py | 19 ++------ cdatgui/editors/cdat1d.py | 57 +++++++++++++++++++++++ cdatgui/editors/graphics_method_editor.py | 26 +++++++++-- cdatgui/editors/isofill.py | 22 +-------- cdatgui/editors/isoline.py | 30 ++++++++++++ cdatgui/editors/level_editor.py | 16 +++++-- cdatgui/editors/meshfill.py | 20 ++++++++ cdatgui/editors/model/legend.py | 13 ++---- cdatgui/editors/preview/legend_preview.py | 7 ++- cdatgui/editors/widgets/adjust_values.py | 5 +- cdatgui/editors/widgets/legend_widget.py | 2 + cdatgui/graphics/dialog.py | 39 +++++++++++++--- cdatgui/sidebar/inspector_widget.py | 9 +++- cdatgui/spreadsheet/vtk_classes.py | 1 + 17 files changed, 233 insertions(+), 66 deletions(-) create mode 100644 cdatgui/editors/cdat1d.py create mode 100644 cdatgui/editors/isoline.py create mode 100644 cdatgui/editors/meshfill.py diff --git a/cdatgui/bases/window_widget.py b/cdatgui/bases/window_widget.py index 0d83f1b..65ef296 100644 --- a/cdatgui/bases/window_widget.py +++ b/cdatgui/bases/window_widget.py @@ -1,5 +1,6 @@ from PySide import QtCore, QtGui + class BaseSaveWindowWidget(QtGui.QWidget): savePressed = QtCore.Signal(str) diff --git a/cdatgui/cdat/plotter.py b/cdatgui/cdat/plotter.py index c8f4be9..6e7588f 100644 --- a/cdatgui/cdat/plotter.py +++ b/cdatgui/cdat/plotter.py @@ -167,6 +167,7 @@ def set_gm(self, gm): self._gm = gm if self.can_plot(): self.plot() + self.source.gm_label.setText(self._gm.name) graphics_method = property(gm, set_gm) @@ -192,6 +193,16 @@ def set_vars(self, v): if self.can_plot(): self.plot() + valid_vars = [] + for v in self._vars: + try: + if v.all(): + valid_vars.append(v) + except AttributeError: + continue + + self.source.variableSync(valid_vars) + variables = property(get_vars, set_vars) def templ(self): @@ -203,6 +214,8 @@ def set_templ(self, template): if self.can_plot(): self.plot() + self.source.tmpl_label.setText(self.template.name) + template = property(templ, set_templ) def remove(self): diff --git a/cdatgui/cdat/vcswidget.py b/cdatgui/cdat/vcswidget.py index d64c44f..69d46ca 100644 --- a/cdatgui/cdat/vcswidget.py +++ b/cdatgui/cdat/vcswidget.py @@ -31,6 +31,7 @@ def __init__(self, parent=None): self.visibilityChanged.connect(self.manageCanvas) self.displays = [] + self.timer = None self.to_plot = [] def plot(self, *args, **kwargs): @@ -58,6 +59,8 @@ def update(self): self.canvas.update() def manageCanvas(self, showing): + self.timer.deleteLater() + self.timer = None """Make sure that the canvas isn't opened till we're really ready.""" if showing and self.canvas is None: self.canvas = vcs.init(backend=self.mRenWin) @@ -75,15 +78,25 @@ def manageCanvas(self, showing): self.canvas.onClosing((0, 0)) self.canvas = None + def doTimer(self, func): + if self.timer is not None: + self.timer.stop() + self.timer.deleteLater() + self.timer = None + self.timer = QtCore.QTimer(parent=self) + self.timer.setSingleShot(True) + self.timer.timeout.connect(func) + self.timer.start(0) + def showEvent(self, e): "Handle twitchy VTK resources appropriately." super(QVCSWidget, self).showEvent(e) - QtCore.QTimer.singleShot(0, self.becameVisible) + self.doTimer(self.becameVisible) def hideEvent(self, e): "Handle twitchy VTK resources appropriately." super(QVCSWidget, self).hideEvent(e) - QtCore.QTimer.singleShot(0, self.becameHidden) + self.doTimer(self.becameHidden) def deleteLater(self): """ @@ -93,6 +106,8 @@ def deleteLater(self): deallocating. Overriding PyQt deleteLater to free up resources """ + if self.timer is not None: + self.timer.stop() if self.canvas: self.canvas.onClosing((0, 0)) self.canvas = None diff --git a/cdatgui/editors/boxfill.py b/cdatgui/editors/boxfill.py index 8a0c5a1..c4a1665 100644 --- a/cdatgui/editors/boxfill.py +++ b/cdatgui/editors/boxfill.py @@ -13,9 +13,6 @@ def __init__(self, parent=None): """Initialize the object.""" super(BoxfillEditor, self).__init__(parent=parent) - legend_button = QtGui.QPushButton("Edit Legend") - legend_button.clicked.connect(self.editLegend) - self.boxfill_types = OrderedDict( Linear="linear", Logarithmic="log10", @@ -34,17 +31,7 @@ def __init__(self, parent=None): self.type_group.buttonClicked.connect(self.setBoxfillType) self.button_layout.insertLayout(0, button_layout) - self.button_layout.insertWidget(2, legend_button) - - def editLegend(self): - if self.legend_editor is None: - print "launching boxfill legend editor" - self.legend_editor = LegendEditorWidget() - self.legend_editor.okPressed.connect(self.updated) - legend = VCSLegend(self.gm, self.var.var) - self.legend_editor.setObject(legend) - self.legend_editor.show() - self.legend_editor.raise_() + self.levels_button.setEnabled(False) @property def gm(self): @@ -60,6 +47,10 @@ def gm(self, value): def setBoxfillType(self, radio): """Take in a radio button and set the GM boxfill_type.""" + if radio.text() == 'Custom': + self.levels_button.setEnabled(True) + else: + self.levels_button.setEnabled(False) box_type = self.boxfill_types[radio.text()] self._gm.boxfill_type = box_type self.graphicsMethodUpdated.emit(self._gm) diff --git a/cdatgui/editors/cdat1d.py b/cdatgui/editors/cdat1d.py new file mode 100644 index 0000000..0dc1981 --- /dev/null +++ b/cdatgui/editors/cdat1d.py @@ -0,0 +1,57 @@ +from PySide import QtGui +from .graphics_method_editor import GraphicsMethodEditorWidget +from .secondary.editor.marker import MarkerEditorWidget +from .secondary.editor.line import LineEditorWidget +import vcs + +class Cdat1dEditor(GraphicsMethodEditorWidget): + """Configures a meshfill graphics method.""" + + def __init__(self, parent=None): + """Initialize the object.""" + super(Cdat1dEditor, self).__init__(parent=parent) + + self.button_layout.takeAt(0).widget().deleteLater() + self.button_layout.takeAt(0).widget().deleteLater() + + marker_button = QtGui.QPushButton("Edit Marker") + marker_button.clicked.connect(self.editMarker) + + line_button = QtGui.QPushButton("Edit Line") + line_button.clicked.connect(self.editLine) + + self.button_layout.insertWidget(0, line_button) + self.button_layout.insertWidget(0, marker_button) + + self.marker_editor = None + self.line_editor = None + + def editMarker(self): + if not self.marker_editor: + self.marker_editor = MarkerEditorWidget() + self.marker_editor.savePressed.connect(self.updateMarker) + + mark_obj = vcs.createmarker(mtype=self.gm.marker, color=self.gm.markercolor, size=self.gm.markersize) + self.marker_editor.setMarkerObject(mark_obj) + self.marker_editor.raise_() + self.marker_editor.show() + + def editLine(self): + if not self.line_editor: + self.line_editor = LineEditorWidget() + self.line_editor.savePressed.connect(self.updateLine) + line_obj = vcs.createline(ltype=self.gm.line, color=self.gm.linecolor, width=self.gm.linewidth) + self.line_editor.setLineObject(line_obj) + self.line_editor.raise_() + self.line_editor.show() + + def updateMarker(self, name): + self.gm.marker = self.marker_editor.object.type[0] + self.gm.markercolor = self.marker_editor.object.color[0] + self.gm.markersize = self.marker_editor.object.size[0] + + def updateLine(self, name): + self.gm.line = self.line_editor.object.type[0] + self.gm.linecolor = self.line_editor.object.color[0] + self.gm.line = self.line_editor.object.width[0] + diff --git a/cdatgui/editors/graphics_method_editor.py b/cdatgui/editors/graphics_method_editor.py index dd4bb8e..2521659 100644 --- a/cdatgui/editors/graphics_method_editor.py +++ b/cdatgui/editors/graphics_method_editor.py @@ -1,4 +1,7 @@ from PySide import QtGui, QtCore + +from cdatgui.editors.model.legend import VCSLegend +from cdatgui.editors.widgets.legend_widget import LegendEditorWidget from level_editor import LevelEditor from axis_editor import AxisEditorWidget from model.vcsaxis import VCSAxis @@ -19,9 +22,13 @@ def __init__(self, parent=None): self.button_layout = QtGui.QVBoxLayout() self.setLayout(self.button_layout) - levels_button = QtGui.QPushButton("Edit Levels") - levels_button.clicked.connect(self.editLevels) - + self.levels_button = QtGui.QPushButton("Edit Levels") + self.levels_button.clicked.connect(self.editLevels) + self.levels_button.setDefault(False) + self.levels_button.setAutoDefault(False) + legend_button = QtGui.QPushButton("Edit Legend") + legend_button.clicked.connect(self.editLegend) + legend_button.setAutoDefault(False) left_axis = QtGui.QPushButton("Edit Left Ticks") left_axis.clicked.connect(self.editLeft) right_axis = QtGui.QPushButton("Edit Right Ticks") @@ -31,7 +38,8 @@ def __init__(self, parent=None): top_axis = QtGui.QPushButton("Edit Top Ticks") top_axis.clicked.connect(self.editTop) - self.button_layout.addWidget(levels_button) + self.button_layout.addWidget(self.levels_button) + self.button_layout.addWidget(legend_button) self.button_layout.addWidget(left_axis) self.button_layout.addWidget(right_axis) self.button_layout.addWidget(top_axis) @@ -78,6 +86,7 @@ def updated(self): if self.axis_editor is not None: self.axis_editor = None if self.level_editor is not None: + self.level_editor.deleteLater() self.level_editor = None print "Emitting updated" self.graphicsMethodUpdated.emit(self._gm) @@ -94,3 +103,12 @@ def gm(self, value): """GM setter.""" self._gm = value + def editLegend(self): + if self.legend_editor is None: + self.legend_editor = LegendEditorWidget() + self.legend_editor.okPressed.connect(self.updated) + legend = VCSLegend(self.gm, self.var.var) + self.legend_editor.setObject(legend) + self.legend_editor.show() + self.legend_editor + diff --git a/cdatgui/editors/isofill.py b/cdatgui/editors/isofill.py index f54c3d3..8dacb87 100644 --- a/cdatgui/editors/isofill.py +++ b/cdatgui/editors/isofill.py @@ -1,29 +1,9 @@ -from PySide import QtGui, QtCore -from widgets.legend_widget import LegendEditorWidget -from model.legend import VCSLegend from .graphics_method_editor import GraphicsMethodEditorWidget class IsofillEditor(GraphicsMethodEditorWidget): - """Configures a boxfill graphics method.""" + """Configures a Isofill graphics method.""" def __init__(self, parent=None): """Initialize the object.""" super(IsofillEditor, self).__init__(parent=parent) - - legend_button = QtGui.QPushButton("Edit Legend") - legend_button.clicked.connect(self.editLegend) - - self.button_layout.insertWidget(1, legend_button) - - def editLegend(self): - if self.legend_editor is None: - self.legend_editor = LegendEditorWidget() - print "disabling start and end color widgets." - # self.legend_editor.end_color_widget.setEnabled(False) - # self.legend_editor.start_color_widget.setEnabled(False) - self.legend_editor.okPressed.connect(self.updated) - legend = VCSLegend(self.gm, self.var.var) - self.legend_editor.setObject(legend) - self.legend_editor.show() - self.legend_editor.raise_() \ No newline at end of file diff --git a/cdatgui/editors/isoline.py b/cdatgui/editors/isoline.py new file mode 100644 index 0000000..b9fce50 --- /dev/null +++ b/cdatgui/editors/isoline.py @@ -0,0 +1,30 @@ +from PySide import QtGui + +from .graphics_method_editor import GraphicsMethodEditorWidget +from .secondary.editor.text import TextStyleEditorWidget + + +class IsolineEditor(GraphicsMethodEditorWidget): + """Configures a meshfill graphics method.""" + + def __init__(self, parent=None): + """Initialize the object.""" + super(IsolineEditor, self).__init__(parent=parent) + + edit_text_button = QtGui.QPushButton('Edit Text') + edit_text_button.clicked.connect(self.editText) + self.button_layout.insertWidget(0, edit_text_button) + + self.text_edit_widget = None + + def editText(self): + if not self.text_edit_widget: + self.text_edit_widget = TextStyleEditorWidget() + self.text_edit_widget.show() + self.text_edit_widget._raise() + + def editLine(self): + if not self.line_edit_widget: + # self.line_edit_widget = Line() + self.line_edit_widget.show() + self.line_edit_widget._raise() diff --git a/cdatgui/editors/level_editor.py b/cdatgui/editors/level_editor.py index a807a9f..6474133 100644 --- a/cdatgui/editors/level_editor.py +++ b/cdatgui/editors/level_editor.py @@ -50,11 +50,17 @@ def reset_levels(self): def update_levels(self, levs, clear=False): self.histo.bins = levs if clear: + print "Clearing" self.canvas.clear() + print "Cleared, now plotting" self.canvas.plot(self._var, self.histo) + print "Plotted" else: + print "Updating" self.canvas.update() + print "Updated" self._gm.levels = levs + print 'Updated levels' @property def var(self): @@ -66,9 +72,7 @@ def var(self, value): flat = self._var.flatten() var_min, var_max = vcs.minmax(flat) # Check if we're using auto levels - print "HAS GM LEVELS?", self.has_set_gm_levels() if self._gm is None or not self.has_set_gm_levels(): - print "MAKING SCALE" # Update the automatic levels with this variable levs = vcs.utils.mkscale(var_min, var_max) else: @@ -96,10 +100,14 @@ def gm(self, value): self.update_levels(levs, clear=True) def has_set_gm_levels(self): - print "checking gm levels", len(self._gm.levels) != 2, not numpy.allclose(self._gm.levels, [1e+20] * 2) + # print "Levels:", self._gm.levels + # print "checking gm levels", len(self._gm.levels) != 2, not numpy.allclose(self._gm.levels, [1e+20] * 2) # print self._gm.levels, [1e+20] * 2 try: length = len(self._gm.levels[0]) except: length = len(self._gm.levels) - return length != 2 or not numpy.allclose(self._gm.levels, [1e+20] * 2) + try: + return length != 2 or not numpy.allclose(self._gm.levels, [1e+20] * 2) + except ValueError: + return True diff --git a/cdatgui/editors/meshfill.py b/cdatgui/editors/meshfill.py new file mode 100644 index 0000000..de4f487 --- /dev/null +++ b/cdatgui/editors/meshfill.py @@ -0,0 +1,20 @@ +from .graphics_method_editor import GraphicsMethodEditorWidget + +class MeshfillEditor(GraphicsMethodEditorWidget): + """Configures a meshfill graphics method.""" + + def __init__(self, parent=None): + """Initialize the object.""" + super(MeshfillEditor, self).__init__(parent=parent) + + @property + def gm(self): + """GM property.""" + return self._gm + + + @gm.setter + def gm(self, value): + """GM setter.""" + self._gm = value + self._gm.fillareaindices = [1] diff --git a/cdatgui/editors/model/legend.py b/cdatgui/editors/model/legend.py index 445e5dc..11c804a 100644 --- a/cdatgui/editors/model/legend.py +++ b/cdatgui/editors/model/legend.py @@ -37,8 +37,7 @@ def rgba_from_index(self, index): def vcs_colors(self): """Used internally, don't worry about it.""" levs = self.levels - if self._gm.fillareacolors: - print "fill area colors", self._gm.fillareacolors + if self._gm.fillareacolors and self._gm.fillareacolors != [1]: colors = self._gm.fillareacolors return colors else: @@ -47,12 +46,10 @@ def vcs_colors(self): levs = levs[1:] if self.ext_right: levs = levs[:-1] - if self.color_1 and self.color_2: - print "getting colors from color1 and color2" - colors = vcs.getcolors(levs, colors=range(self.color_1, self.color_2)) + if self.color_1 is None and self.color_2 is None: + colors = vcs.getcolors(levs, split=0) else: - print "COLOR1, COLOR2 None", self.levels - # colors = vcs.getcolors(levs, colors=range(min(self.levels), max(self.levels))) + colors = vcs.getcolors(levs, colors=range(self.color_1, self.color_2)) levs = real_levs if len(colors) < len(levs): # Pad out colors to the right number of buckets @@ -205,7 +202,7 @@ def level_color(self, i): return self.vcs_colors[i] def set_level_color(self, i, v): - if self._gm.fillareacolors is None: + if self._gm.fillareacolors is None or self._gm.fillareacolors == [1]: self._gm.fillareacolors = self.vcs_colors if len(self._gm.fillareacolors) < len(self.levels): self._gm.fillareacolors += (len(self.levels) - len(self._gm.fillareacolors)) * self._gm.fillareacolors[-1:] diff --git a/cdatgui/editors/preview/legend_preview.py b/cdatgui/editors/preview/legend_preview.py index 0c984be..1b8a69a 100644 --- a/cdatgui/editors/preview/legend_preview.py +++ b/cdatgui/editors/preview/legend_preview.py @@ -33,8 +33,11 @@ def update(self): template.legend.textorientation = text_orientation.name template.drawColorBar(self.legend.vcs_colors, self.legend.levels, self.legend.labels, ext_1=self.legend.ext_left, - ext_2=self.legend.ext_right, x=self.canvas, cmap=self.legend.colormap, - style=[self.legend.fill_style], index=self.legend._gm.fillareaindices, + ext_2=self.legend.ext_right, + x=self.canvas, + cmap=self.legend.colormap, + style=[self.legend.fill_style], + index=self.legend._gm.fillareaindices, opacity=self.legend._gm.fillareaopacity) self.canvas.backend.renWin.Render() diff --git a/cdatgui/editors/widgets/adjust_values.py b/cdatgui/editors/widgets/adjust_values.py index eaed19f..72551d2 100644 --- a/cdatgui/editors/widgets/adjust_values.py +++ b/cdatgui/editors/widgets/adjust_values.py @@ -34,7 +34,7 @@ def add_level(self): self.send_values() def update(self, minval, maxval, values): - print "UPDATING:", minval, maxval, values + block = self.blockSignals(True) if minval >= maxval: raise ValueError("Minimum value %d >= maximum value %d" % (minval, maxval)) self.min_val = minval @@ -47,6 +47,7 @@ def update(self, minval, maxval, values): self.insert_line() self.slides[ind].setValue(value) self.clearing = False + self.blockSignals(False) def adjust_slides(self, slide, cur_val): cur_index = self.slides.index(slide) @@ -101,7 +102,7 @@ def insert_line(self): row.addWidget(slide) # set slide attributes - slide.setRange(self.min_val, self.max_val) + slide.setRange(float(self.min_val), float(self.max_val)) slide.setValue(self.max_val) slide.setTickPosition(QSlider.TicksAbove) slide.valueChanged.connect(partial(self.change_label, lab, slide)) diff --git a/cdatgui/editors/widgets/legend_widget.py b/cdatgui/editors/widgets/legend_widget.py index 13d7dc6..64f093f 100644 --- a/cdatgui/editors/widgets/legend_widget.py +++ b/cdatgui/editors/widgets/legend_widget.py @@ -326,6 +326,7 @@ def setObject(self, legend): self.start_color_button.setFixedSize(100, 25) except TypeError: self.start_color_widget.setEnabled(False) + self.start_color_widget.hide() try: self.end_color_spin.setValue(self.object.color_2) @@ -333,6 +334,7 @@ def setObject(self, legend): self.end_color_button.setFixedSize(100, 25) except TypeError: self.end_color_widget.setEnabled(False) + self.end_color_widget.hide() self.preview.setLegendObject(legend) self.preview.update() diff --git a/cdatgui/graphics/dialog.py b/cdatgui/graphics/dialog.py index ddffc68..bccf27e 100644 --- a/cdatgui/graphics/dialog.py +++ b/cdatgui/graphics/dialog.py @@ -1,6 +1,9 @@ from PySide import QtGui, QtCore from cdatgui.editors.boxfill import BoxfillEditor from cdatgui.editors.isofill import IsofillEditor +from cdatgui.editors.meshfill import MeshfillEditor +from cdatgui.editors.isoline import IsolineEditor +from cdatgui.editors.cdat1d import Cdat1dEditor import vcs @@ -10,12 +13,28 @@ class GraphcisMethodDialog(QtGui.QDialog): def __init__(self, gm, var, tmpl, parent=None): super(GraphcisMethodDialog, self).__init__(parent=parent) - # self.graphics_methods = ['boxfill', 'isofill', 'isoline', 'meshfill', '3d_scalar', '3d_dual_scalar', layout = QtGui.QVBoxLayout() self.gm = gm - self.editor = eval('{0}Editor()'.format(vcs.graphicsmethodtype(self.gm).capitalize())) - # self.editor = BoxfillEditor() + + self.gmtype = vcs.graphicsmethodtype(self.gm) + if self.gmtype == "boxfill": + self.editor = BoxfillEditor() + self.create = vcs.createboxfill + elif self.gmtype == "isofill": + self.editor = IsofillEditor() + self.create = vcs.createisofill + elif self.gmtype == "meshfill": + self.editor = MeshfillEditor() + self.create = vcs.createmeshfill + elif self.gmtype == "isoline": + self.editor = IsolineEditor() + self.create = vcs.createisoline + elif self.gmtype == "1d": + self.editor = Cdat1dEditor() + else: + raise NotImplementedError("No editor exists for type %s" % self.gmtype) + self.editor.gm = gm self.editor.var = var self.editor.tmpl = tmpl @@ -41,13 +60,19 @@ def __init__(self, gm, var, tmpl, parent=None): self.setLayout(layout) def customName(self): - name = QtGui.QInputDialog.getText(self, u"Save As", u"Name for Boxfill:") - self.save(name) + name = QtGui.QInputDialog.getText(self, u"Save As", u"Name for {0}:".format(unicode(self.gmtype))) + if name[1]: + self.save(name) def save(self, name=None): if name is None: self.editedGM.emit(self.gm) else: - # gm = vcs.createboxfill(name, self.gm) - gm = eval('vcs.create{0}(name, self.gm)'.format(vcs.graphicsmethodtype(self.gm))) + gm = self.create(name, self.gm) self.createdGM.emit(gm) + + def create(self, name, gm): + print "NAME:", self.gm + # gm = vcs.creategraphicsmethod(self.gmtype, self.gm) + print "CREATED GM", gm.list() + return gm diff --git a/cdatgui/sidebar/inspector_widget.py b/cdatgui/sidebar/inspector_widget.py index 1698554..bc90ef3 100644 --- a/cdatgui/sidebar/inspector_widget.py +++ b/cdatgui/sidebar/inspector_widget.py @@ -59,12 +59,13 @@ def select(self, ind): class InspectorWidget(StaticDockWidget): - plotters_updated = QtCore.Signal(list) + plotters_updated = QtCore.Signal() def __init__(self, spreadsheet, parent=None): super(InspectorWidget, self).__init__("Inspector", parent=parent) self.allowed_sides = [QtCore.Qt.DockWidgetArea.RightDockWidgetArea] spreadsheet.selectionChanged.connect(self.selection_change) + self.plotters_updated.connect(spreadsheet.tabController.currentWidget().totalPlotsChanged) self.cells = [] self.current_plot = None self.plots = PlotterListModel() @@ -218,6 +219,7 @@ def setGMRoot(self, index): def setTemplate(self, template): self.current_plot.template = template + self.plotters_updated.emit() def updateGM(self, index): self.edit_gm_button.setEnabled(True) @@ -226,12 +228,15 @@ def updateGM(self, index): gm = vcs.getgraphicsmethod(gm_type, gm_name) self.current_plot.graphics_method = gm + self.plotters_updated.emit() def setFirstVar(self, var): self.current_plot.variables = [var, self.current_plot.variables[1]] + self.plotters_updated.emit() def setSecondVar(self, var): self.current_plot.variables = [self.current_plot.variables[0], var] + self.plotters_updated.emit() def selectPlot(self, plot): plotIndex = self.plot_combo.currentIndex() @@ -262,7 +267,7 @@ def selectPlot(self, plot): block = self.template_combo.blockSignals(True) self.template_combo.setCurrentIndex(self.template_combo.findText(plot.template.name)) self.template_combo.blockSignals(block) - if self.gm_type_combo.currentText() == "boxfill" and self.gm_instance_combo.currentText() != '': + if self.gm_instance_combo.currentText() != '': self.edit_gm_button.setEnabled(True) else: self.edit_gm_button.setEnabled(False) diff --git a/cdatgui/spreadsheet/vtk_classes.py b/cdatgui/spreadsheet/vtk_classes.py index 8653263..1d148b7 100755 --- a/cdatgui/spreadsheet/vtk_classes.py +++ b/cdatgui/spreadsheet/vtk_classes.py @@ -126,6 +126,7 @@ def dropEvent(self, event): self.iren.show() self.dragTarget.hide() self.plotAdded.emit() + self.emitAllPlots.emit() def dragEnterEvent(self, event): accepted = set([cdms_mime, vcs_gm_mime, vcs_template_mime]) From 4b6f68c12f3ebba05e3251f737db25908e18cfdc Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Tue, 19 Apr 2016 12:54:06 -0700 Subject: [PATCH 03/29] Added import as to variables list. Fixed bug in line editor. Added flip to 1d. --- cdatgui/bases/value_slider.py | 30 ++++---- cdatgui/editors/boxfill.py | 22 +++++- cdatgui/editors/cdat1d.py | 32 ++++++++- cdatgui/editors/graphics_method_editor.py | 6 +- cdatgui/editors/level_editor.py | 26 ++++--- cdatgui/editors/secondary/editor/line.py | 33 +++++---- cdatgui/editors/secondary/editor/marker.py | 33 +++++---- cdatgui/editors/secondary/preview/line.py | 1 + cdatgui/editors/vector.py | 37 ++++++++++ cdatgui/editors/widgets/adjust_values.py | 40 ++++++----- cdatgui/editors/widgets/legend_widget.py | 17 ++++- cdatgui/graphics/dialog.py | 37 +++++++--- cdatgui/graphics/models.py | 2 +- cdatgui/sidebar/inspector_widget.py | 8 ++- cdatgui/variables/variable_add.py | 84 +++++++++++++++++++--- cdatgui/variables/variable_widget.py | 1 + 16 files changed, 308 insertions(+), 101 deletions(-) create mode 100644 cdatgui/editors/vector.py diff --git a/cdatgui/bases/value_slider.py b/cdatgui/bases/value_slider.py index ebc9a13..d300303 100644 --- a/cdatgui/bases/value_slider.py +++ b/cdatgui/bases/value_slider.py @@ -2,19 +2,23 @@ class ValueSlider(QtGui.QSlider): - realValueChanged = QtCore.Signal(object) - def __init__(self, values, parent=None): - super(ValueSlider, self).__init__(parent=parent) - self.values = values - self.setMinimum(0) - self.setMaximum(len(values) - 1) - self.valueChanged.connect(self.emitReal) + realValueChanged = QtCore.Signal(object) - def emitReal(self, val): - self.realValueChanged.emit(self.values[val]) + def __init__(self, values, parent=None): + super(ValueSlider, self).__init__(parent=parent) + self.values = values + self.setMinimum(0) + self.setMaximum(len(values) - 1) + self.valueChanged.connect(self.emitReal) - def realValue(self): - return self.values[self.value()] + def emitReal(self, val): + self.realValueChanged.emit(self.values[val]) - def setRealValue(self, realValue): - self.setValue(self.values.index(realValue)) \ No newline at end of file + def realValue(self): + return self.values[self.value()] + + def setRealValue(self, realValue): + # print "VALUES:", self.values + val = self.values.index(realValue) + print "VAL", val + self.setValue(val) diff --git a/cdatgui/editors/boxfill.py b/cdatgui/editors/boxfill.py index c4a1665..8c6be15 100644 --- a/cdatgui/editors/boxfill.py +++ b/cdatgui/editors/boxfill.py @@ -12,7 +12,7 @@ class BoxfillEditor(GraphicsMethodEditorWidget): def __init__(self, parent=None): """Initialize the object.""" super(BoxfillEditor, self).__init__(parent=parent) - + print "CREATING BOXFILL EDITOR" self.boxfill_types = OrderedDict( Linear="linear", Logarithmic="log10", @@ -25,6 +25,9 @@ def __init__(self, parent=None): self.type_group = QtGui.QButtonGroup() for label in self.boxfill_types: radiobutton = QtGui.QRadioButton(label) + if label == "Linear": + print "SETTING CHECKED" + radiobutton.setChecked(True) button_layout.addWidget(radiobutton) self.type_group.addButton(radiobutton) @@ -53,4 +56,19 @@ def setBoxfillType(self, radio): self.levels_button.setEnabled(False) box_type = self.boxfill_types[radio.text()] self._gm.boxfill_type = box_type - self.graphicsMethodUpdated.emit(self._gm) + + def editLegend(self): + if self.legend_editor is None: + if self.type_group.checkedButton().text() == 'Custom': + self.legend_editor = LegendEditorWidget() + else: + self.legend_editor = LegendEditorWidget(False) + self.legend_editor.okPressed.connect(self.updated) + elif self.type_group.checkedButton().text() == 'Custom': + self.legend_editor.enableCustom() + else: + self.legend_editor.disableCustom() + legend = VCSLegend(self.gm, self.var.var) + self.legend_editor.setObject(legend) + self.legend_editor.show() + self.legend_editor.raise_() diff --git a/cdatgui/editors/cdat1d.py b/cdatgui/editors/cdat1d.py index 0dc1981..a64e34f 100644 --- a/cdatgui/editors/cdat1d.py +++ b/cdatgui/editors/cdat1d.py @@ -1,4 +1,4 @@ -from PySide import QtGui +from PySide import QtGui, QtCore from .graphics_method_editor import GraphicsMethodEditorWidget from .secondary.editor.marker import MarkerEditorWidget from .secondary.editor.line import LineEditorWidget @@ -14,6 +14,14 @@ def __init__(self, parent=None): self.button_layout.takeAt(0).widget().deleteLater() self.button_layout.takeAt(0).widget().deleteLater() + self.flip_check = QtGui.QCheckBox() + self.flip_check.stateChanged.connect(self.flipGraph) + + flip_layout = QtGui.QHBoxLayout() + flip_layout.addWidget(QtGui.QLabel("Flip")) + flip_layout.addWidget(self.flip_check) + flip_layout.addStretch(1) + marker_button = QtGui.QPushButton("Edit Marker") marker_button.clicked.connect(self.editMarker) @@ -22,6 +30,7 @@ def __init__(self, parent=None): self.button_layout.insertWidget(0, line_button) self.button_layout.insertWidget(0, marker_button) + self.button_layout.insertLayout(0, flip_layout) self.marker_editor = None self.line_editor = None @@ -40,6 +49,8 @@ def editLine(self): if not self.line_editor: self.line_editor = LineEditorWidget() self.line_editor.savePressed.connect(self.updateLine) + if self.gm.linewidth < 1: + self.gm.linewidth = 1 line_obj = vcs.createline(ltype=self.gm.line, color=self.gm.linecolor, width=self.gm.linewidth) self.line_editor.setLineObject(line_obj) self.line_editor.raise_() @@ -53,5 +64,22 @@ def updateMarker(self, name): def updateLine(self, name): self.gm.line = self.line_editor.object.type[0] self.gm.linecolor = self.line_editor.object.color[0] - self.gm.line = self.line_editor.object.width[0] + self.gm.linewidth = self.line_editor.object.width[0] + + def flipGraph(self, state): + if state == QtCore.Qt.Checked: + self.gm.flip = True + elif state == QtCore.Qt.Unchecked: + self.gm.flip = False + + @property + def gm(self): + """GM property.""" + return self._gm + @gm.setter + def gm(self, value): + """GM setter.""" + self._gm = value + print value.flip + self.flip_check.setChecked(value.flip) diff --git a/cdatgui/editors/graphics_method_editor.py b/cdatgui/editors/graphics_method_editor.py index 2521659..fe840d3 100644 --- a/cdatgui/editors/graphics_method_editor.py +++ b/cdatgui/editors/graphics_method_editor.py @@ -1,4 +1,5 @@ from PySide import QtGui, QtCore +import vcs from cdatgui.editors.model.legend import VCSLegend from cdatgui.editors.widgets.legend_widget import LegendEditorWidget @@ -88,10 +89,7 @@ def updated(self): if self.level_editor is not None: self.level_editor.deleteLater() self.level_editor = None - print "Emitting updated" - self.graphicsMethodUpdated.emit(self._gm) - print "Updated" - # pdb.set_trace() + # self.graphicsMethodUpdated.emit(self._gm) @property def gm(self): diff --git a/cdatgui/editors/level_editor.py b/cdatgui/editors/level_editor.py index 6474133..23e4676 100644 --- a/cdatgui/editors/level_editor.py +++ b/cdatgui/editors/level_editor.py @@ -44,7 +44,7 @@ def __init__(self, parent=None): def reset_levels(self): self.gm.levels = self.orig_levs - self.update_levels(self.gm.levels) + #self.update_levels(self.gm.levels) self.levelsUpdated.emit() def update_levels(self, levs, clear=False): @@ -60,6 +60,7 @@ def update_levels(self, levs, clear=False): self.canvas.update() print "Updated" self._gm.levels = levs + print levs print 'Updated levels' @property @@ -69,19 +70,31 @@ def var(self): @var.setter def var(self, value): self._var = value - flat = self._var.flatten() + flat = self._var.data + flat = sorted(numpy.unique(flat.flatten())) + ''' + if flat[0] == -1e20: + flat = flat[1:] + if flat[-1] == 1e20: + flat = flat[:-1] + ''' var_min, var_max = vcs.minmax(flat) + print "MIN MAX", var_min, var_max # Check if we're using auto levels if self._gm is None or not self.has_set_gm_levels(): # Update the automatic levels with this variable levs = vcs.utils.mkscale(var_min, var_max) + print "GENERATED LEVELS", levs else: # Otherwise, just use what the levels are levs = self._gm.levels + step = (levs[-1] - levs[0])/1000 + values = list(numpy.arange(levs[0], levs[-1]+step, step)) + self.canvas.clear() - print "updating value slider. min->{0} max->{1}".format(var_min, var_max) - self.value_sliders.update(var_min, var_max, levs) + print "VALUES:", values, len(values) + self.value_sliders.update(values, levs) self.update_levels(levs, clear=True) @property @@ -96,13 +109,10 @@ def gm(self, value): levs = self._gm.levels flat = self._var.flatten() var_min, var_max = vcs.minmax(flat) - self.value_sliders.update(var_min, var_max, levs) + self.value_sliders.update(flat, levs) self.update_levels(levs, clear=True) def has_set_gm_levels(self): - # print "Levels:", self._gm.levels - # print "checking gm levels", len(self._gm.levels) != 2, not numpy.allclose(self._gm.levels, [1e+20] * 2) - # print self._gm.levels, [1e+20] * 2 try: length = len(self._gm.levels[0]) except: diff --git a/cdatgui/editors/secondary/editor/line.py b/cdatgui/editors/secondary/editor/line.py index 934340f..f46f4a9 100644 --- a/cdatgui/editors/secondary/editor/line.py +++ b/cdatgui/editors/secondary/editor/line.py @@ -17,43 +17,46 @@ def __init__(self): row = QtGui.QHBoxLayout() # create type combo box - type_box = QtGui.QComboBox() - type_box.addItems(["solid", "dash", "dot", "dash-dot", "long-dash"]) - type_box.currentIndexChanged[str].connect(self.updateType) + self.type_box = QtGui.QComboBox() + self.type_box.addItems(["solid", "dash", "dot", "dash-dot", "long-dash"]) + self.type_box.currentIndexChanged[str].connect(self.updateType) # create color spin box - color_box = QtGui.QSpinBox() - color_box.setRange(0, 255) - color_box.valueChanged.connect(self.updateColor) + self.color_box = QtGui.QSpinBox() + self.color_box.setRange(0, 255) + self.color_box.valueChanged.connect(self.updateColor) # create color spin box - width_box = QtGui.QSpinBox() - width_box.setRange(1, 300) - width_box.valueChanged.connect(self.updateWidth) + self.width_box = QtGui.QSpinBox() + self.width_box.setRange(1, 300) + self.width_box.valueChanged.connect(self.updateWidth) row.addWidget(type_label) - row.addWidget(type_box) + row.addWidget(self.type_box) row.addWidget(color_label) - row.addWidget(color_box) + row.addWidget(self.color_box) row.addWidget(width_label) - row.addWidget(width_box) + row.addWidget(self.width_box) self.vertical_layout.insertLayout(1, row) def setLineObject(self, line_obj): self.object = line_obj self.preview.setLineObject(self.object) + self.type_box.setCurrentIndex(self.type_box.findText(self.object.type[0])) + self.color_box.setValue(self.object.color[0]) + self.width_box.setValue(self.object.width[0]) def updateType(self, cur_item): - self.object.type = str(cur_item) + self.object.type = [str(cur_item)] self.preview.update() def updateColor(self, color): - self.object.color = color + self.object.color = [color] self.preview.update() def updateWidth(self, width): - self.object.width = width + self.object.width = [width] self.preview.update() diff --git a/cdatgui/editors/secondary/editor/marker.py b/cdatgui/editors/secondary/editor/marker.py index d80a1e4..c390bcf 100644 --- a/cdatgui/editors/secondary/editor/marker.py +++ b/cdatgui/editors/secondary/editor/marker.py @@ -17,8 +17,8 @@ def __init__(self): row = QtGui.QHBoxLayout() # create type combo box - type_box = QtGui.QComboBox() - type_box.addItems(["dot", "plus", "star", "circle", "cross", "diamond", "triangle_up", "triangle_down", + self.type_box = QtGui.QComboBox() + self.type_box.addItems(["dot", "plus", "star", "circle", "cross", "diamond", "triangle_up", "triangle_down", "triangle_left", "triangle_right", "square", "diamond_fill", "triangle_up_fill", "triangle_down_fill", "triangle_left_fill", "triangle_right_fill", "square_fill",'hurricane', 'w00', 'w01', 'w02', 'w03', 'w04', 'w05', 'w06', 'w07', 'w08', 'w09', 'w10', 'w11', 'w12', @@ -29,41 +29,44 @@ def __init__(self): 'w65', 'w66', 'w67', 'w68', 'w69', 'w70', 'w71', 'w72', 'w73', 'w74', 'w75', 'w76', 'w77', 'w78', 'w79', 'w80', 'w81', 'w82', 'w83', 'w84', 'w85', 'w86', 'w87', 'w88', 'w89', 'w90', 'w91', 'w92', 'w93', 'w94', 'w95', 'w96', 'w97', 'w98', 'w99', 'w100', 'w101', 'w102']) - type_box.currentIndexChanged[str].connect(self.updateType) + self.type_box.currentIndexChanged[str].connect(self.updateType) # create color spin box - color_box = QtGui.QSpinBox() - color_box.setRange(0, 255) - color_box.valueChanged.connect(self.updateColor) + self.color_box = QtGui.QSpinBox() + self.color_box.setRange(0, 255) + self.color_box.valueChanged.connect(self.updateColor) # create size spin box - size_box = QtGui.QSpinBox() - size_box.setRange(1, 300) - size_box.valueChanged.connect(self.updateSize) + self.size_box = QtGui.QSpinBox() + self.size_box.setRange(1, 300) + self.size_box.valueChanged.connect(self.updateSize) row.addWidget(type_label) - row.addWidget(type_box) + row.addWidget(self.type_box) row.addWidget(color_label) - row.addWidget(color_box) + row.addWidget(self.color_box) row.addWidget(size_label) - row.addWidget(size_box) + row.addWidget(self.size_box) self.vertical_layout.insertLayout(1, row) def setMarkerObject(self, mark_obj): self.object = mark_obj self.preview.setMarkerObject(self.object) + self.type_box.setCurrentIndex(self.type_box.findText(self.object.type[0])) + self.color_box.setValue(self.object.color[0]) + self.size_box.setValue(self.object.size[0]) def updateType(self, cur_item): - self.object.type = str(cur_item) + self.object.type = [str(cur_item)] self.preview.update() def updateColor(self, color): - self.object.color = color + self.object.color = [color] self.preview.update() def updateSize(self, size): - self.object.size = size + self.object.size = [size] self.preview.update() \ No newline at end of file diff --git a/cdatgui/editors/secondary/preview/line.py b/cdatgui/editors/secondary/preview/line.py index 085659f..301abf1 100644 --- a/cdatgui/editors/secondary/preview/line.py +++ b/cdatgui/editors/secondary/preview/line.py @@ -8,6 +8,7 @@ def __init__(self, parent=None): self.lineobj = None def setLineObject(self, lineobject): + print 'LINE OBJECT', lineobject self.lineobj = lineobject tmpobj = vcs.createline(source=self.lineobj) tmpobj.x = [.25, .75] diff --git a/cdatgui/editors/vector.py b/cdatgui/editors/vector.py new file mode 100644 index 0000000..4336f46 --- /dev/null +++ b/cdatgui/editors/vector.py @@ -0,0 +1,37 @@ +from PySide import QtGui +from .graphics_method_editor import GraphicsMethodEditorWidget +from .secondary.editor.marker import MarkerEditorWidget +from .secondary.editor.line import LineEditorWidget +import vcs + +class VectorEditor(GraphicsMethodEditorWidget): + """Configures a meshfill graphics method.""" + + def __init__(self, parent=None): + """Initialize the object.""" + super(VectorEditor, self).__init__(parent=parent) + + self.button_layout.takeAt(0).widget().deleteLater() + self.button_layout.takeAt(0).widget().deleteLater() + + line_button = QtGui.QPushButton("Edit Line") + line_button.clicked.connect(self.editLine) + + self.button_layout.insertWidget(0, line_button) + + self.marker_editor = None + self.line_editor = None + + def editLine(self): + if not self.line_editor: + self.line_editor = LineEditorWidget() + self.line_editor.savePressed.connect(self.updateLine) + line_obj = vcs.createline(ltype=self.gm.line, color=self.gm.linecolor, width=self.gm.linewidth) + self.line_editor.setLineObject(line_obj) + self.line_editor.raise_() + self.line_editor.show() + + def updateLine(self, name): + self.gm.line = self.line_editor.object.type[0] + self.gm.linecolor = self.line_editor.object.color[0] + self.gm.line = self.line_editor.object.width[0] diff --git a/cdatgui/editors/widgets/adjust_values.py b/cdatgui/editors/widgets/adjust_values.py index 72551d2..bfd4e32 100644 --- a/cdatgui/editors/widgets/adjust_values.py +++ b/cdatgui/editors/widgets/adjust_values.py @@ -1,6 +1,8 @@ +import numpy from PySide.QtCore import * from PySide.QtGui import * from functools import partial +from cdatgui.bases.value_slider import ValueSlider class AdjustValues(QWidget): @@ -9,9 +11,9 @@ class AdjustValues(QWidget): def __init__(self, parent=None): super(AdjustValues, self).__init__(parent=parent) - self.min_val = 0 self.max_val = 1 + self.values = None self.slides = [] # Insert Sliders self.wrap = QVBoxLayout() @@ -29,23 +31,23 @@ def __init__(self, parent=None): self.setLayout(self.wrap) def add_level(self): - self.insert_line() + new_slide = self.insert_line() + new_slide.setRealValue(new_slide.values[-1]) + if self.clearing is False: self.send_values() - def update(self, minval, maxval, values): + def update(self, values, levs): block = self.blockSignals(True) - if minval >= maxval: - raise ValueError("Minimum value %d >= maximum value %d" % (minval, maxval)) - self.min_val = minval - self.max_val = maxval + self.values = values self.clearing = True for ind in range(len(self.rows)): self.remove_level(self.rows[0]) - - for ind, value in enumerate(values): - self.insert_line() - self.slides[ind].setValue(value) + print "UPDATING LEVS", levs, len(levs) + for ind, value in enumerate(levs): + cur_slide = self.insert_line() + print "SETTING SLIDE VALUE", value, ind + cur_slide.setRealValue(value) self.clearing = False self.blockSignals(False) @@ -65,11 +67,11 @@ def send_values(self): positions = [] for slide in self.slides: - positions.append(slide.sliderPosition()) + positions.append(slide.realValue()) self.valuesChanged.emit(positions) def change_label(self, lab, slide, cur_val): - lab.setText(str(slide.sliderPosition())) + lab.setText(str(slide.realValue())) def remove_level(self, row): child = row.takeAt(0) @@ -89,7 +91,9 @@ def remove_level(self, row): def insert_line(self): row = QHBoxLayout() lab = QLabel(str(self.max_val)) - slide = QSlider(Qt.Horizontal) + lab.setMinimumWidth(50) + slide = ValueSlider(self.values) + slide.setOrientation(Qt.Horizontal) # remove button rem_button = QPushButton() @@ -102,8 +106,10 @@ def insert_line(self): row.addWidget(slide) # set slide attributes - slide.setRange(float(self.min_val), float(self.max_val)) - slide.setValue(self.max_val) + # slide.setRange(self.min_val, self.max_val) + + # slide.setValue(self.max_val) + slide.setTickInterval(len(self.values) / 20) slide.setTickPosition(QSlider.TicksAbove) slide.valueChanged.connect(partial(self.change_label, lab, slide)) slide.valueChanged.connect(partial(self.adjust_slides, slide)) @@ -115,3 +121,5 @@ def insert_line(self): # add to list self.slides.append(slide) self.rows.append(row) + + return slide diff --git a/cdatgui/editors/widgets/legend_widget.py b/cdatgui/editors/widgets/legend_widget.py index 64f093f..e1c2c25 100644 --- a/cdatgui/editors/widgets/legend_widget.py +++ b/cdatgui/editors/widgets/legend_widget.py @@ -175,7 +175,7 @@ def validate(self, input, pos): class LegendEditorWidget(BaseOkWindowWidget): - def __init__(self, parent=None): + def __init__(self, custom=True, parent=None): super(LegendEditorWidget, self).__init__() # Variables @@ -190,7 +190,7 @@ def __init__(self, parent=None): end_color_label = QtGui.QLabel("End Color:") extend_left_label = QtGui.QLabel("Extend Left") extend_right_label = QtGui.QLabel("Extend Right") - custom_fill_label = QtGui.QLabel("Custom Fill") + self.custom_fill_label = QtGui.QLabel("Custom Fill") labels_label = QtGui.QLabel("Labels:") # Timers @@ -240,6 +240,8 @@ def __init__(self, parent=None): self.custom_fill_icon = QtGui.QToolButton() self.custom_fill_icon.setArrowType(QtCore.Qt.RightArrow) self.custom_fill_icon.clicked.connect(self.updateArrowType) + if not custom: + self.disableCustom() # Create custom fill section self.custom_vertical_layout = QtGui.QVBoxLayout() @@ -302,7 +304,7 @@ def __init__(self, parent=None): extend_layout.insertStretch(2, 1) custom_fill_layout.addWidget(self.custom_fill_icon) - custom_fill_layout.addWidget(custom_fill_label) + custom_fill_layout.addWidget(self.custom_fill_label) # Add preview self.setPreview(LegendPreviewWidget()) @@ -546,6 +548,15 @@ def handleEndColorInvalidInput(self): self.end_color_button.setStyleSheet( self.end_color_button.styleSheet() + "border: 1px solid red;") + def enableCustom(self): + self.custom_fill_icon.setEnabled(True) + self.custom_fill_icon.show() + self.custom_fill_label.show() + + def disableCustom(self): + self.custom_fill_icon.setEnabled(False) + self.custom_fill_icon.hide() + self.custom_fill_label.hide() if __name__ == "__main__": import cdms2, vcs diff --git a/cdatgui/graphics/dialog.py b/cdatgui/graphics/dialog.py index bccf27e..817aa8f 100644 --- a/cdatgui/graphics/dialog.py +++ b/cdatgui/graphics/dialog.py @@ -4,6 +4,7 @@ from cdatgui.editors.meshfill import MeshfillEditor from cdatgui.editors.isoline import IsolineEditor from cdatgui.editors.cdat1d import Cdat1dEditor +from cdatgui.editors.vector import VectorEditor import vcs @@ -15,11 +16,11 @@ def __init__(self, gm, var, tmpl, parent=None): super(GraphcisMethodDialog, self).__init__(parent=parent) layout = QtGui.QVBoxLayout() - self.gm = gm - self.gmtype = vcs.graphicsmethodtype(self.gm) + self.gmtype = vcs.graphicsmethodtype(gm) if self.gmtype == "boxfill": self.editor = BoxfillEditor() + self.editor.type_group.checkedButton().clicked.emit() self.create = vcs.createboxfill elif self.gmtype == "isofill": self.editor = IsofillEditor() @@ -32,24 +33,28 @@ def __init__(self, gm, var, tmpl, parent=None): self.create = vcs.createisoline elif self.gmtype == "1d": self.editor = Cdat1dEditor() + self.create = vcs.create1d + elif self.gmtype == "vector": + self.editor = VectorEditor() + self.create = vcs.createvector else: raise NotImplementedError("No editor exists for type %s" % self.gmtype) - self.editor.gm = gm self.editor.var = var self.editor.tmpl = tmpl layout.addWidget(self.editor) buttons = QtGui.QHBoxLayout() cancel = QtGui.QPushButton("Cancel") + cancel.setAutoDefault(True) cancel.clicked.connect(self.reject) save_as = QtGui.QPushButton("Save As") save_as.clicked.connect(self.customName) save = QtGui.QPushButton("Save") + save.setDefault(True) save.clicked.connect(self.accept) self.accepted.connect(self.save) - save.setDefault(True) buttons.addWidget(cancel) buttons.addStretch() @@ -59,6 +64,18 @@ def __init__(self, gm, var, tmpl, parent=None): self.setLayout(layout) + print "GM NAME", gm.name + if gm.name == 'default': + self.gm = self.create('new', gm) + save.setEnabled(False) + else: + self.gm = gm + + self.editor.gm = self.gm + + def updateGM(self, gm): + self.gm = gm + def customName(self): name = QtGui.QInputDialog.getText(self, u"Save As", u"Name for {0}:".format(unicode(self.gmtype))) if name[1]: @@ -68,11 +85,11 @@ def save(self, name=None): if name is None: self.editedGM.emit(self.gm) else: - gm = self.create(name, self.gm) + gm = self.create(name[0], self.gm) + self.close() self.createdGM.emit(gm) - def create(self, name, gm): - print "NAME:", self.gm - # gm = vcs.creategraphicsmethod(self.gmtype, self.gm) - print "CREATED GM", gm.list() - return gm + def reject(self): + super(GraphcisMethodDialog, self).reject() + if 'new' in vcs.elements[vcs.graphicsmethodtype(self.gm)].keys(): + del vcs.elements[vcs.graphicsmethodtype(self.gm)]['new'] diff --git a/cdatgui/graphics/models.py b/cdatgui/graphics/models.py index 76d6233..e9abbb4 100644 --- a/cdatgui/graphics/models.py +++ b/cdatgui/graphics/models.py @@ -73,7 +73,7 @@ def insertRows(self, row, count, gms, parent=QtCore.QModelIndex()): parent_name = self.data(parent) self.beginInsertRows(parent, row, row + count) - self.gms = self.gms[parent_name][:row] + gms + self.gms[parent_name][row:] + self.gms[parent_name] = self.gms[parent_name][:row] + gms + self.gms[parent_name][row:] self.endInsertRows() def rowCount(self, modelIndex=QtCore.QModelIndex()): diff --git a/cdatgui/sidebar/inspector_widget.py b/cdatgui/sidebar/inspector_widget.py index bc90ef3..1ec2e7d 100644 --- a/cdatgui/sidebar/inspector_widget.py +++ b/cdatgui/sidebar/inspector_widget.py @@ -235,7 +235,13 @@ def setFirstVar(self, var): self.plotters_updated.emit() def setSecondVar(self, var): - self.current_plot.variables = [self.current_plot.variables[0], var] + old_vars = self.current_plot.variables + try: + self.current_plot.variables = [self.current_plot.variables[0], var] + except ValueError: + print "SETTING TO OLD VARS" + self.current_plot.variables = old_vars + self.plotters_updated.emit() def selectPlot(self, plot): diff --git a/cdatgui/variables/variable_add.py b/cdatgui/variables/variable_add.py index 0cb5416..a68724c 100644 --- a/cdatgui/variables/variable_add.py +++ b/cdatgui/variables/variable_add.py @@ -1,13 +1,29 @@ -from PySide import QtGui -from cdms_file_tree import CDMSFileTree +from PySide import QtGui, QtCore + +import re +from functools import partial + from cdatgui.toolbars import AddEditRemoveToolbar from cdms_file_chooser import CDMSFileChooser +from cdms_file_tree import CDMSFileTree from manager import manager +from . import get_variables + + +class dummyVar(object): + def __init__(self, id): + self.id = id class AddDialog(QtGui.QDialog): def __init__(self, parent=None, f=0): super(AddDialog, self).__init__(parent=parent, f=f) + self.renameVar = None + self.dialog = None + self.reserved_words = ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global', 'or', 'with', + 'assert', 'else', 'if', 'pass', 'yield', 'break', 'except', 'import', 'print', 'class', + 'exec', 'in', 'raise', 'continue', 'finally', 'is', 'return', 'def', 'for', 'lambda', + 'try'] wrap = QtGui.QVBoxLayout() @@ -15,19 +31,21 @@ def __init__(self, parent=None, f=0): wrap.addLayout(horiz, 10) - buttons = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | - QtGui.QDialogButtonBox.Cancel) + self.buttons = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | + QtGui.QDialogButtonBox.Cancel) + import_button = QtGui.QPushButton("Import As") + import_button.clicked.connect(self.rename_file) + self.buttons.addButton(import_button, QtGui.QDialogButtonBox.ActionRole) + self.buttons.accepted.connect(self.verify_selected_files) + self.buttons.rejected.connect(self.reject) - buttons.accepted.connect(self.accept) - buttons.rejected.connect(self.reject) - - ok = buttons.button(QtGui.QDialogButtonBox.StandardButton.Ok) - cancel = buttons.button(QtGui.QDialogButtonBox.StandardButton.Cancel) + ok = self.buttons.button(QtGui.QDialogButtonBox.StandardButton.Ok) + cancel = self.buttons.button(QtGui.QDialogButtonBox.StandardButton.Cancel) ok.setDefault(True) cancel.setDefault(False) - wrap.addWidget(buttons) + wrap.addWidget(self.buttons) self.setLayout(wrap) @@ -54,7 +72,12 @@ def addFileToTree(self, file): self.tree.add_file(file) def selected_variables(self): - return self.tree.get_selected() + if self.renameVar: + var = self.renameVar + self.renameVar = None + return [var] + else: + return self.tree.get_selected() def add_file(self): self.chooser.show() # pragma: no cover @@ -66,3 +89,42 @@ def added_files(self): def remove_file(self): pass # pragma: no cover + + def rename_file(self): + var = self.tree.get_selected() + if len(var) > 1: + QtGui.QMessageBox.warning(self, "Error", "Please select one variable to import as") + return + var = var[0] + + while True: + name = QtGui.QInputDialog.getText(self, u"Import As", u"Enter new variable name") + if not name[1] or (name[1] and self.isValidName(name[0])): + break + + QtGui.QMessageBox.warning(self, "Error", "Invalid name") + + str_name = name[0] + var.id = str_name + self.renameVar = var + if name[1]: + self.buttons.accepted.emit() + else: + self.buttons.rejected.emit() + self.close() + + def isValidName(self, name): + if name in self.reserved_words or not re.search("^[a-zA-Z_]", name) or name == '' \ + or re.search(' +', name) or re.search("[^a-zA-Z0-9_]+", name) \ + or get_variables().variable_exists(dummyVar(name)): + return False + return True + + def verify_selected_files(self): + if not self.renameVar: + vars = self.tree.get_selected() + for var in vars: + if not self.isValidName(var.id): + QtGui.QMessageBox.warning(self, "Error", "Invalid name for selected var(s)") + return + self.accept() diff --git a/cdatgui/variables/variable_widget.py b/cdatgui/variables/variable_widget.py index bf01686..add3711 100644 --- a/cdatgui/variables/variable_widget.py +++ b/cdatgui/variables/variable_widget.py @@ -34,6 +34,7 @@ def select_variable(self, index): def add_variable(self): new_variables = self.add_dialog.selected_variables() + print "ADDING VARIABLES", new_variables for var in new_variables: self.variable_widget.add_variable(var) From ae342bfdec0cd3952bd4ca2f0d2d6cc046361a47 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Tue, 19 Apr 2016 15:20:32 -0700 Subject: [PATCH 04/29] vector graphing now works much better.' --- cdatgui/cdat/plotter.py | 2 +- cdatgui/sidebar/inspector_widget.py | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/cdatgui/cdat/plotter.py b/cdatgui/cdat/plotter.py index 6e7588f..243eb2b 100644 --- a/cdatgui/cdat/plotter.py +++ b/cdatgui/cdat/plotter.py @@ -156,7 +156,6 @@ def can_plot(self): @property def canvas(self): - # print "MANAGER CANVAS:", self.source.canvas return self.source.canvas def gm(self): @@ -177,6 +176,7 @@ def get_vars(self): def set_vars(self, v): try: self._vars = (v[0], v[1]) + self.graphics_method = vcs.createvector() except TypeError: self._vars = (v, None) except IndexError: diff --git a/cdatgui/sidebar/inspector_widget.py b/cdatgui/sidebar/inspector_widget.py index 1ec2e7d..e2970ca 100644 --- a/cdatgui/sidebar/inspector_widget.py +++ b/cdatgui/sidebar/inspector_widget.py @@ -225,6 +225,19 @@ def updateGM(self, index): self.edit_gm_button.setEnabled(True) gm_type = self.gm_type_combo.currentText() gm_name = self.gm_instance_combo.currentText() + if gm_type in ['vector', '3d_vector']: + self.var_combos[1].setEnabled(True) + enabled = True + else: + block = self.var_combos[1].blockSignals(True) + self.var_combos[1].setCurrentIndex(-1) + self.var_combos[1].blockSignals(block) + self.var_combos[1].setEnabled(False) + enabled = False + self.current_plot._vars = (self.current_plot.variables[0], None) + + if enabled and self.var_combos[1].currentIndex() == -1: + return gm = vcs.getgraphicsmethod(gm_type, gm_name) self.current_plot.graphics_method = gm @@ -237,9 +250,9 @@ def setFirstVar(self, var): def setSecondVar(self, var): old_vars = self.current_plot.variables try: - self.current_plot.variables = [self.current_plot.variables[0], var] + self.current_plot.variables = [self.current_plot.variables[0], var.var] except ValueError: - print "SETTING TO OLD VARS" + print "SETTING TO OLD VARS", old_vars self.current_plot.variables = old_vars self.plotters_updated.emit() From cebe1ee16d0ce795d7db246e75744944817533ee Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Tue, 19 Apr 2016 15:35:27 -0700 Subject: [PATCH 05/29] vector graphing now works much better.' --- cdatgui/editors/boxfill.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cdatgui/editors/boxfill.py b/cdatgui/editors/boxfill.py index 8c6be15..5ebd43c 100644 --- a/cdatgui/editors/boxfill.py +++ b/cdatgui/editors/boxfill.py @@ -25,9 +25,6 @@ def __init__(self, parent=None): self.type_group = QtGui.QButtonGroup() for label in self.boxfill_types: radiobutton = QtGui.QRadioButton(label) - if label == "Linear": - print "SETTING CHECKED" - radiobutton.setChecked(True) button_layout.addWidget(radiobutton) self.type_group.addButton(radiobutton) @@ -46,7 +43,9 @@ def gm(self, value): self._gm = value type_real_vals = self.boxfill_types.values() index = type_real_vals.index(value.boxfill_type) - self.type_group.buttons()[index].setChecked(True) + button = self.type_group.buttons()[index] + button.setChecked(True) + self.setBoxfillType(button) def setBoxfillType(self, radio): """Take in a radio button and set the GM boxfill_type.""" From a84b129446d13a34eaf0ddb3c2cf874d455b9d79 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Tue, 19 Apr 2016 15:38:18 -0700 Subject: [PATCH 06/29] fixed bug when reopening boxfill editor --- cdatgui/graphics/dialog.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cdatgui/graphics/dialog.py b/cdatgui/graphics/dialog.py index 817aa8f..a909411 100644 --- a/cdatgui/graphics/dialog.py +++ b/cdatgui/graphics/dialog.py @@ -20,7 +20,6 @@ def __init__(self, gm, var, tmpl, parent=None): self.gmtype = vcs.graphicsmethodtype(gm) if self.gmtype == "boxfill": self.editor = BoxfillEditor() - self.editor.type_group.checkedButton().clicked.emit() self.create = vcs.createboxfill elif self.gmtype == "isofill": self.editor = IsofillEditor() From f2b6e960f129fcaf8b1ec7658ebd4bef6ea78aaa Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Thu, 21 Apr 2016 14:58:13 -0700 Subject: [PATCH 07/29] multi line editing for isoline --- cdatgui/bases/dynamic_grid_layout.py | 4 +- cdatgui/cdat/plotter.py | 15 ++-- cdatgui/editors/isoline.py | 39 ++++++-- cdatgui/editors/model/legend.py | 28 +----- cdatgui/editors/model/levels_base.py | 32 +++++++ cdatgui/editors/model/line_model.py | 43 +++++++++ cdatgui/editors/secondary/preview/line.py | 1 - cdatgui/editors/widgets/dict_editor.py | 2 +- cdatgui/editors/widgets/multi_line_editor.py | 95 ++++++++++++++++++++ cdatgui/graphics/dialog.py | 1 - cdatgui/sidebar/inspector_widget.py | 13 ++- cdatgui/vcsmodel/secondary.py | 3 + 12 files changed, 229 insertions(+), 47 deletions(-) create mode 100644 cdatgui/editors/model/levels_base.py create mode 100644 cdatgui/editors/model/line_model.py create mode 100644 cdatgui/editors/widgets/multi_line_editor.py diff --git a/cdatgui/bases/dynamic_grid_layout.py b/cdatgui/bases/dynamic_grid_layout.py index b605561..7f198df 100644 --- a/cdatgui/bases/dynamic_grid_layout.py +++ b/cdatgui/bases/dynamic_grid_layout.py @@ -49,7 +49,7 @@ def buildGrid(self, rect, force=False): return # clearing - self.clearWidget() + self.clearWidgets() # calculate full_columns = possible_columns - 1 @@ -77,7 +77,7 @@ def buildGrid(self, rect, force=False): self.cur_col_count = possible_columns - def clearWidget(self): + def clearWidgets(self): """clears widgets from the grid layout. Does not delete widgets""" for col, row_count in enumerate(self.counts): if row_count: diff --git a/cdatgui/cdat/plotter.py b/cdatgui/cdat/plotter.py index 243eb2b..d6b7844 100644 --- a/cdatgui/cdat/plotter.py +++ b/cdatgui/cdat/plotter.py @@ -161,11 +161,16 @@ def canvas(self): def gm(self): return self._gm - def set_gm(self, gm): + def set_gm(self, args): + """If args is a tuple, assume they are passing in False. Tuple used to designate do not plot""" # check gm vs vars - self._gm = gm - if self.can_plot(): - self.plot() + if isinstance(args, tuple): + self._gm = args[0] + else: + self._gm = args + if self.can_plot(): + print "PLOTTING" + self.plot() self.source.gm_label.setText(self._gm.name) graphics_method = property(gm, set_gm) @@ -176,7 +181,7 @@ def get_vars(self): def set_vars(self, v): try: self._vars = (v[0], v[1]) - self.graphics_method = vcs.createvector() + # self.graphics_method = vcs.createvector() except TypeError: self._vars = (v, None) except IndexError: diff --git a/cdatgui/editors/isoline.py b/cdatgui/editors/isoline.py index b9fce50..4579928 100644 --- a/cdatgui/editors/isoline.py +++ b/cdatgui/editors/isoline.py @@ -2,6 +2,8 @@ from .graphics_method_editor import GraphicsMethodEditorWidget from .secondary.editor.text import TextStyleEditorWidget +from .widgets.multi_line_editor import MultiLineEditor +from .model.line_model import LineModel class IsolineEditor(GraphicsMethodEditorWidget): @@ -10,21 +12,44 @@ class IsolineEditor(GraphicsMethodEditorWidget): def __init__(self, parent=None): """Initialize the object.""" super(IsolineEditor, self).__init__(parent=parent) + self._var = None edit_text_button = QtGui.QPushButton('Edit Text') edit_text_button.clicked.connect(self.editText) + + edit_line_button = QtGui.QPushButton('Edit Lines') + edit_line_button.clicked.connect(self.editLines) + self.button_layout.insertWidget(0, edit_text_button) + self.button_layout.insertWidget(0, edit_line_button) self.text_edit_widget = None + self.line_edit_widget = None def editText(self): if not self.text_edit_widget: self.text_edit_widget = TextStyleEditorWidget() self.text_edit_widget.show() - self.text_edit_widget._raise() - - def editLine(self): - if not self.line_edit_widget: - # self.line_edit_widget = Line() - self.line_edit_widget.show() - self.line_edit_widget._raise() + self.text_edit_widget.raise_() + + def editLines(self): + if self.line_edit_widget: + self.line_edit_widget.close() + self.line_edit_widget.deleteLater() + self.line_edit_widget = MultiLineEditor() + self.line_edit_widget.setObject(LineModel(self._gm, self._var)) + self.line_edit_widget.okPressed.connect(self.update) + self.line_edit_widget.show() + self.line_edit_widget.raise_() + + def update(self): + # self._gm.list() + pass + + @property + def var(self): + return self._var + + @var.setter + def var(self, v): + self._var = v diff --git a/cdatgui/editors/model/legend.py b/cdatgui/editors/model/legend.py index 11c804a..27497bd 100644 --- a/cdatgui/editors/model/legend.py +++ b/cdatgui/editors/model/legend.py @@ -1,5 +1,6 @@ import vcs import numpy +from .levels_base import LevelsBaseModel def get_colormaps(): @@ -7,7 +8,7 @@ def get_colormaps(): return sorted(vcs.elements["colormap"].keys()) -class VCSLegend(object): +class VCSLegend(LevelsBaseModel): def __init__(self, gm, var, canvas=None): self._gm = gm self._var = var @@ -118,31 +119,6 @@ def ext_right(self): def ext_right(self, v): self._gm.ext_2 = v - @property - def levels(self): - """Used internally, don't worry about it.""" - levs = list(self._gm.levels) - # Check if they're autolevels - if numpy.allclose(levs, 1e20): - if vcs.isboxfill(self._gm) == 1: - nlevs = self.color_2 - self.color_1 + 1 - minval, maxval = vcs.minmax(self._var) - levs = vcs.mkscale(minval, maxval) - if len(levs) == 1: - levs.append(levs[0] + .00001) - delta = (levs[-1] - levs[0]) / nlevs - levs = list(numpy.arange(levs[0], levs[-1] + delta, delta)) - else: - levs = vcs.mkscale(*vcs.minmax(self._var)) - - # Now adjust for ext_1 nad ext_2 - if self.ext_left: - levs.insert(0, -1e20) - if self.ext_right: - levs.append(1e20) - - return levs - @property def level_names(self): """Returns a string repr for each level. Use for Custom Fill's labels.""" diff --git a/cdatgui/editors/model/levels_base.py b/cdatgui/editors/model/levels_base.py new file mode 100644 index 0000000..6b0624a --- /dev/null +++ b/cdatgui/editors/model/levels_base.py @@ -0,0 +1,32 @@ +import numpy, vcs + + +class LevelsBaseModel(object): + + @property + def levels(self): + """Used internally, don't worry about it.""" + levs = list(self._gm.levels) + # Check if they're autolevels + if numpy.allclose(levs, 1e20): + if vcs.isboxfill(self._gm) == 1: + nlevs = self.color_2 - self.color_1 + 1 + minval, maxval = vcs.minmax(self._var) + levs = vcs.mkscale(minval, maxval) + if len(levs) == 1: + levs.append(levs[0] + .00001) + delta = (levs[-1] - levs[0]) / nlevs + levs = list(numpy.arange(levs[0], levs[-1] + delta, delta)) + else: + levs = vcs.mkscale(*vcs.minmax(self._var)) + + # Now adjust for ext_1 nad ext_2 + try: + if self.ext_left: + levs.insert(0, -1e20) + if self.ext_right: + levs.append(1e20) + except AttributeError: + pass + + return levs \ No newline at end of file diff --git a/cdatgui/editors/model/line_model.py b/cdatgui/editors/model/line_model.py new file mode 100644 index 0000000..307d844 --- /dev/null +++ b/cdatgui/editors/model/line_model.py @@ -0,0 +1,43 @@ +from .levels_base import LevelsBaseModel +from cdatgui.vcsmodel import get_lines +import vcs + + +class LineModel(LevelsBaseModel): + def __init__(self, gm, var, canvas=None): + self._gm = gm + self._var = var + self._canvas = canvas + self.count = 1 + + @property + def line(self): + print "LINELIST", self._gm.line + while len(self._gm.line) < len(self._gm.levels): + while True: + try: + old_line = vcs.getline(self._gm.line[-1]) + + name = "line_{0}".format(self.count) + new_line = vcs.createline(str(name)) + new_line.type = old_line.type + new_line.color = old_line.color + new_line.width = old_line.width + get_lines().updated(name) + self.count += 1 + break + except vcs.vcsError as e: + self.count += 1 + self._gm.line.append(new_line.name) + while len(self._gm.line) > len(self._gm.levels): + self._gm.line.remove(self._gm.line[-1]) + return self._gm.line + + @property + def linecolors(self): + return self._gm.linecolors + + @property + def linewidths(self): + return self._gm.linewidths + diff --git a/cdatgui/editors/secondary/preview/line.py b/cdatgui/editors/secondary/preview/line.py index 301abf1..085659f 100644 --- a/cdatgui/editors/secondary/preview/line.py +++ b/cdatgui/editors/secondary/preview/line.py @@ -8,7 +8,6 @@ def __init__(self, parent=None): self.lineobj = None def setLineObject(self, lineobject): - print 'LINE OBJECT', lineobject self.lineobj = lineobject tmpobj = vcs.createline(source=self.lineobj) tmpobj.x = [.25, .75] diff --git a/cdatgui/editors/widgets/dict_editor.py b/cdatgui/editors/widgets/dict_editor.py index b4ca49f..1e8950f 100644 --- a/cdatgui/editors/widgets/dict_editor.py +++ b/cdatgui/editors/widgets/dict_editor.py @@ -213,7 +213,7 @@ def dict(self): return dict(zip(keys, values)) def clear(self): - self.grid.clearWidget() + self.grid.clearWidgets() self.clearing = True while self.key_value_rows: diff --git a/cdatgui/editors/widgets/multi_line_editor.py b/cdatgui/editors/widgets/multi_line_editor.py new file mode 100644 index 0000000..dcfbc5c --- /dev/null +++ b/cdatgui/editors/widgets/multi_line_editor.py @@ -0,0 +1,95 @@ +from PySide import QtCore, QtGui +from functools import partial + +from cdatgui.editors.secondary.editor.line import LineEditorWidget +from cdatgui.bases.window_widget import BaseOkWindowWidget +from cdatgui.bases.dynamic_grid_layout import DynamicGridLayout +import vcs +from cdatgui.vcsmodel import get_lines + + +class MultiLineEditor(BaseOkWindowWidget): + + def __init__(self): + super(MultiLineEditor, self).__init__() + self.isoline_model = None + self.line_editor = None + self.line_combos = [] + self.dynamic_grid = DynamicGridLayout(400) + self.vertical_layout.insertLayout(0, self.dynamic_grid) + + def setObject(self, object): + self.isoline_model = object + widgets = [] + + # clear grid + grid_widgets = self.dynamic_grid.getWidgets() + self.dynamic_grid.clearWidgets() + + for widget in grid_widgets: + self.dynamic_grid.removeWidget(widget) + + # repopulate + for ind, lev in enumerate(self.isoline_model.levels): + row = QtGui.QHBoxLayout() + line_label = QtGui.QLabel("Line:") + + line_combo = QtGui.QComboBox() + line_combo.setModel(get_lines()) + line_combo.currentIndexChanged.connect(partial(self.changeLine, ind)) + line_combo.setCurrentIndex(get_lines().elements.index(self.isoline_model.line[ind])) + self.line_combos.append(line_combo) + + edit_line = QtGui.QPushButton('Edit Line') + edit_line.clicked.connect(partial(self.editLine, ind)) + + # add everything to layout + row.addWidget(line_label) + row.addWidget(line_combo) + row.addWidget(edit_line) + + row_widget = QtGui.QWidget() + row_widget.setLayout(row) + widgets.append(row_widget) + + print object._gm.linecolors + + self.dynamic_grid.addNewWidgets(widgets) + + def editLine(self, index): + if self.line_editor: + self.line_editor.close() + self.line_editor.deleteLater() + self.line_editor = LineEditorWidget() + + line = self.isoline_model.line[index] + line_obj = vcs.getline(line) + + self.line_editor.setLineObject(line_obj) + self.line_editor.savePressed.connect(partial(self.update, index)) + + self.line_editor.show() + self.line_editor.raise_() + + def changeLine(self, row_index, combo_index): + self.isoline_model.line[row_index] = get_lines().elements[combo_index] + + def update(self, index, name): # TODO: restructure name so that it saves a line not pass the name back + self.isoline_model.line[index] = str(name) + self.line_combos[index].setCurrentIndex(self.line_combos[index].findText(name)) + print self.isoline_model._gm.list() + + def okClicked(self): + self.updateGM() + self.okPressed.emit() + self.close() + + def updateGM(self): + colors = [] + widths = [] + for line in self.isoline_model.line: + colors.append(vcs.getline(line).color[0]) + widths.append(vcs.getline(line).width[0]) + + self.isoline_model._gm.linecolors = colors + self.isoline_model._gm.linewidths = widths diff --git a/cdatgui/graphics/dialog.py b/cdatgui/graphics/dialog.py index a909411..6583df1 100644 --- a/cdatgui/graphics/dialog.py +++ b/cdatgui/graphics/dialog.py @@ -63,7 +63,6 @@ def __init__(self, gm, var, tmpl, parent=None): self.setLayout(layout) - print "GM NAME", gm.name if gm.name == 'default': self.gm = self.create('new', gm) save.setEnabled(False) diff --git a/cdatgui/sidebar/inspector_widget.py b/cdatgui/sidebar/inspector_widget.py index e2970ca..9aa3e0f 100644 --- a/cdatgui/sidebar/inspector_widget.py +++ b/cdatgui/sidebar/inspector_widget.py @@ -170,6 +170,9 @@ def editSecondVar(self, var): def editGraphicsMethod(self, gm): get_gms().replace(get_gms().indexOf(vcs.graphicsmethodtype(gm), gm), gm) + print "SETTING GM", gm.list() + for line in gm.line: + vcs.getline(line).list() self.current_plot.graphics_method = gm def makeGraphicsMethod(self, gm): @@ -237,10 +240,12 @@ def updateGM(self, index): self.current_plot._vars = (self.current_plot.variables[0], None) if enabled and self.var_combos[1].currentIndex() == -1: - return - - gm = vcs.getgraphicsmethod(gm_type, gm_name) - self.current_plot.graphics_method = gm + gm = vcs.getgraphicsmethod(gm_type, gm_name) + self.current_plot.graphics_method = (gm, False) + else: + gm = vcs.getgraphicsmethod(gm_type, gm_name) + self.current_plot.graphics_method = gm + self.plotters_updated.emit() def setFirstVar(self, var): diff --git a/cdatgui/vcsmodel/secondary.py b/cdatgui/vcsmodel/secondary.py index 7e96444..64bfb01 100644 --- a/cdatgui/vcsmodel/secondary.py +++ b/cdatgui/vcsmodel/secondary.py @@ -4,6 +4,7 @@ class LineElementsModel(VCSElementsModel): el_type = "line" + def __init__(self): super(LineElementsModel, self).__init__() self.isa = vcs.isline @@ -46,6 +47,7 @@ def tooltip(self, name, obj): class FillareaElementsModel(VCSElementsModel): el_type = "fillarea" + def __init__(self): super(FillareaElementsModel, self).__init__() self.isa = vcs.isfillarea @@ -57,6 +59,7 @@ def tooltip(self, name, obj): class MarkerElementsModel(VCSElementsModel): el_type = "marker" + def __init__(self): super(MarkerElementsModel, self).__init__() self.isa = vcs.ismarker From 70e2653950cc7b90cabfd36d7f3c9d9635a5cad3 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Fri, 22 Apr 2016 09:37:01 -0700 Subject: [PATCH 08/29] created my own dialog to implement proper validation for saving variables/secondaries --- cdatgui/bases/input_dialog.py | 58 ++++++++++++++++++++ cdatgui/bases/window_widget.py | 13 +++-- cdatgui/cdat/plotter.py | 1 - cdatgui/editors/graphics_method_editor.py | 1 - cdatgui/editors/isoline.py | 40 ++++++++++++-- cdatgui/editors/model/line_model.py | 1 - cdatgui/editors/secondary/editor/line.py | 25 ++++++++- cdatgui/editors/widgets/multi_line_editor.py | 20 ++++++- cdatgui/spreadsheet/vtk_classes.py | 3 +- cdatgui/vcsmodel/elements.py | 2 + 10 files changed, 148 insertions(+), 16 deletions(-) create mode 100644 cdatgui/bases/input_dialog.py diff --git a/cdatgui/bases/input_dialog.py b/cdatgui/bases/input_dialog.py new file mode 100644 index 0000000..a6e4495 --- /dev/null +++ b/cdatgui/bases/input_dialog.py @@ -0,0 +1,58 @@ +from PySide import QtCore, QtGui + + +class ValidatingInputDialog(QtGui.QWidget): + accepted = QtCore.Signal() + rejected = QtCore.Signal() + + def __init__(self): + super(ValidatingInputDialog, self).__init__() + + vertical_layout = QtGui.QVBoxLayout() + + self.label = QtGui.QLabel() + self.edit = QtGui.QLineEdit() + + self.save_button = QtGui.QPushButton('Save') + self.save_button.clicked.connect(self.save) + self.save_button.setEnabled(False) + self.save_button.setDefault(True) + cancel_button = QtGui.QPushButton('Cancel') + cancel_button.clicked.connect(self.rejected.emit) + + self.edit.returnPressed.connect(self.save_button.click) + + edit_line_layout = QtGui.QHBoxLayout() + edit_line_layout.addWidget(self.label) + edit_line_layout.addWidget(self.edit) + + save_cancel_layout = QtGui.QHBoxLayout() + save_cancel_layout.addWidget(cancel_button) + save_cancel_layout.addWidget(self.save_button) + + vertical_layout.addLayout(edit_line_layout) + vertical_layout.addLayout(save_cancel_layout) + + self.setLayout(vertical_layout) + + self.setMaximumSize(300, 100) + + def save(self): + self.close() + self.accepted.emit() + + def setLabelText(self, text): + self.label.setText(text) + + def setValidator(self, validator): + + self.edit.setValidator(validator) + + try: + validator.invalidInput.connect(lambda: self.save_button.setEnabled(False)) + validator.validInput.connect(lambda: self.save_button.setEnabled(True)) + except AttributeError: + pass + + def textValue(self): + return self.edit.text().strip() diff --git a/cdatgui/bases/window_widget.py b/cdatgui/bases/window_widget.py index 65ef296..ae997d7 100644 --- a/cdatgui/bases/window_widget.py +++ b/cdatgui/bases/window_widget.py @@ -9,6 +9,7 @@ def __init__(self): self.object = None self.preview = None + self.dialog = QtGui.QInputDialog() # Layout to add new elements self.vertical_layout = QtGui.QVBoxLayout() @@ -22,14 +23,14 @@ def __init__(self): saveas_button.setText("Save As") saveas_button.clicked.connect(self.saveAs) - save_button = QtGui.QPushButton() - save_button.setText("Save") - save_button.clicked.connect(self.save) + self.save_button = QtGui.QPushButton() + self.save_button.setText("Save") + self.save_button.clicked.connect(self.save) save_cancel_row = QtGui.QHBoxLayout() save_cancel_row.addWidget(cancel_button) save_cancel_row.addWidget(saveas_button) - save_cancel_row.addWidget(save_button) + save_cancel_row.addWidget(self.save_button) save_cancel_row.insertStretch(1, 1) # Set up vertical_layout @@ -47,7 +48,7 @@ def setPreview(self, preview): def saveAs(self): - self.win = QtGui.QInputDialog() + self.win = self.dialog self.win.setLabelText("Enter New Name:") self.win.accepted.connect(self.save) @@ -67,6 +68,8 @@ def save(self): self.savePressed.emit(name) self.close() + def setSaveDialog(self, dialog): + self.dialog = dialog class BaseOkWindowWidget(QtGui.QWidget): okPressed = QtCore.Signal() diff --git a/cdatgui/cdat/plotter.py b/cdatgui/cdat/plotter.py index d6b7844..1e88da3 100644 --- a/cdatgui/cdat/plotter.py +++ b/cdatgui/cdat/plotter.py @@ -169,7 +169,6 @@ def set_gm(self, args): else: self._gm = args if self.can_plot(): - print "PLOTTING" self.plot() self.source.gm_label.setText(self._gm.name) diff --git a/cdatgui/editors/graphics_method_editor.py b/cdatgui/editors/graphics_method_editor.py index fe840d3..54f0622 100644 --- a/cdatgui/editors/graphics_method_editor.py +++ b/cdatgui/editors/graphics_method_editor.py @@ -89,7 +89,6 @@ def updated(self): if self.level_editor is not None: self.level_editor.deleteLater() self.level_editor = None - # self.graphicsMethodUpdated.emit(self._gm) @property def gm(self): diff --git a/cdatgui/editors/isoline.py b/cdatgui/editors/isoline.py index 4579928..30de497 100644 --- a/cdatgui/editors/isoline.py +++ b/cdatgui/editors/isoline.py @@ -1,4 +1,4 @@ -from PySide import QtGui +from PySide import QtGui, QtCore from .graphics_method_editor import GraphicsMethodEditorWidget from .secondary.editor.text import TextStyleEditorWidget @@ -14,14 +14,25 @@ def __init__(self, parent=None): super(IsolineEditor, self).__init__(parent=parent) self._var = None - edit_text_button = QtGui.QPushButton('Edit Text') - edit_text_button.clicked.connect(self.editText) + self.edit_label_button = QtGui.QPushButton('Edit Labels') + self.edit_label_button.clicked.connect(self.editText) edit_line_button = QtGui.QPushButton('Edit Lines') edit_line_button.clicked.connect(self.editLines) - self.button_layout.insertWidget(0, edit_text_button) + self.label_check = QtGui.QCheckBox() + self.label_check.stateChanged.connect(self.updateLabel) + + label = QtGui.QLabel('Label') + + label_layout = QtGui.QHBoxLayout() + label_layout.addWidget(label) + label_layout.addWidget(self.label_check) + label_layout.addStretch(1) + self.button_layout.insertWidget(0, edit_line_button) + self.button_layout.insertWidget(0, self.edit_label_button) + self.button_layout.insertLayout(0, label_layout) self.text_edit_widget = None self.line_edit_widget = None @@ -42,6 +53,14 @@ def editLines(self): self.line_edit_widget.show() self.line_edit_widget.raise_() + def updateLabel(self, state): + if state == QtCore.Qt.Unchecked: + self._gm.label = False + self.edit_label_button.setEnabled(False) + elif state == QtCore.Qt.Checked: + self._gm.label = True + self.edit_label_button.setEnabled(True) + def update(self): # self._gm.list() pass @@ -53,3 +72,16 @@ def var(self): @var.setter def var(self, v): self._var = v + + @property + def gm(self): + """GM property.""" + return self._gm + + @gm.setter + def gm(self, value): + """GM setter.""" + self._gm = value + self.label_check.setChecked(self._gm.label) + self.edit_label_button.setEnabled(self._gm.label) + diff --git a/cdatgui/editors/model/line_model.py b/cdatgui/editors/model/line_model.py index 307d844..cc7cf5a 100644 --- a/cdatgui/editors/model/line_model.py +++ b/cdatgui/editors/model/line_model.py @@ -12,7 +12,6 @@ def __init__(self, gm, var, canvas=None): @property def line(self): - print "LINELIST", self._gm.line while len(self._gm.line) < len(self._gm.levels): while True: try: diff --git a/cdatgui/editors/secondary/editor/line.py b/cdatgui/editors/secondary/editor/line.py index f46f4a9..14e10d2 100644 --- a/cdatgui/editors/secondary/editor/line.py +++ b/cdatgui/editors/secondary/editor/line.py @@ -1,14 +1,17 @@ from PySide import QtGui, QtCore from cdatgui.bases.window_widget import BaseSaveWindowWidget from cdatgui.editors.secondary.preview.line import LinePreviewWidget +import vcs +from cdatgui.vcsmodel import get_lines class LineEditorWidget(BaseSaveWindowWidget): - def __init__(self): super(LineEditorWidget, self).__init__() self.setPreview(LinePreviewWidget()) + self.savePressed.connect(self.saveNewLine) + # create labels type_label = QtGui.QLabel("Type:") color_label = QtGui.QLabel("Color:") @@ -43,8 +46,13 @@ def __init__(self): self.vertical_layout.insertLayout(1, row) def setLineObject(self, line_obj): + if line_obj.name == 'default': + line_obj = vcs.createline('new', line_obj.name) + self.save_button.setEnabled(False) + self.object = line_obj self.preview.setLineObject(self.object) + self.type_box.setCurrentIndex(self.type_box.findText(self.object.type[0])) self.color_box.setValue(self.object.color[0]) self.width_box.setValue(self.object.width[0]) @@ -60,3 +68,18 @@ def updateColor(self, color): def updateWidth(self, width): self.object.width = [width] self.preview.update() + + def saveNewLine(self, name): + if name not in vcs.elements['line']: + print "NAME:", name + + vcs.createline(name, source=self.object.name) + + # if the name was default, delete the new line that was created to allow editing + if self.object.name == 'new': + del vcs.elements['line']['new'] + elif name != 'default': + vcs.elements['line'][name] = self.object + + # add/update line with given name + get_lines().updated(str(name)) diff --git a/cdatgui/editors/widgets/multi_line_editor.py b/cdatgui/editors/widgets/multi_line_editor.py index dcfbc5c..7948d57 100644 --- a/cdatgui/editors/widgets/multi_line_editor.py +++ b/cdatgui/editors/widgets/multi_line_editor.py @@ -6,10 +6,24 @@ from cdatgui.bases.dynamic_grid_layout import DynamicGridLayout import vcs from cdatgui.vcsmodel import get_lines +from cdatgui.bases.input_dialog import ValidatingInputDialog -class MultiLineEditor(BaseOkWindowWidget): +class LineTextValidator(QtGui.QValidator): + invalidInput = QtCore.Signal() + validInput = QtCore.Signal() + + def validate(self, inp, pos): + inp = inp.strip() + if not inp or inp == 'default': + self.invalidInput.emit() + return QtGui.QValidator.Intermediate + + self.validInput.emit() + return QtGui.QValidator.Acceptable + +class MultiLineEditor(BaseOkWindowWidget): def __init__(self): super(MultiLineEditor, self).__init__() self.isoline_model = None @@ -61,6 +75,9 @@ def editLine(self, index): self.line_editor.close() self.line_editor.deleteLater() self.line_editor = LineEditorWidget() + dialog = ValidatingInputDialog() + dialog.setValidator(LineTextValidator()) + self.line_editor.setSaveDialog(dialog) line = self.isoline_model.line[index] line_obj = vcs.getline(line) @@ -77,7 +94,6 @@ def changeLine(self, row_index, combo_index): def update(self, index, name): # TODO: restructure name so that it saves a line not pass the name back self.isoline_model.line[index] = str(name) self.line_combos[index].setCurrentIndex(self.line_combos[index].findText(name)) - print self.isoline_model._gm.list() def okClicked(self): self.updateGM() diff --git a/cdatgui/spreadsheet/vtk_classes.py b/cdatgui/spreadsheet/vtk_classes.py index 1d148b7..40b89f0 100755 --- a/cdatgui/spreadsheet/vtk_classes.py +++ b/cdatgui/spreadsheet/vtk_classes.py @@ -7,11 +7,11 @@ from functools import partial from cdatgui.variables import get_variables - cdms_mime = "application/x-cdms-variable-list" vcs_gm_mime = "application/x-vcs-gm" vcs_template_mime = "application/x-vcs-template" + class QCDATWidget(QtGui.QFrame): # TODO: Add a signal for addedPlots plotAdded = QtCore.Signal() @@ -36,6 +36,7 @@ def __init__(self, row, col, parent=None): self.setAcceptDrops(True) self.mRenWin = vtk.vtkRenderWindow() + self.mRenWin.StencilCapableOn() self.iren = QVTKRenderWindowInteractor(parent=self, rw=self.mRenWin) self.canvas = None diff --git a/cdatgui/vcsmodel/elements.py b/cdatgui/vcsmodel/elements.py index f4c9604..08522ea 100644 --- a/cdatgui/vcsmodel/elements.py +++ b/cdatgui/vcsmodel/elements.py @@ -34,10 +34,12 @@ def tooltip(self, name, obj): def updated(self, el_name): try: + print "Updating element", el_name ind = self.elements.index(el_name) model_ind = self.index(ind) self.dataChanged.emit(model_ind, model_ind) except ValueError: + print "Inserting Element", el_name new_els = [] insert_ind = -1 insert_me = el_name From 838e4a4bc2f6c1deed6b5d7022ab98da911725c0 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Fri, 22 Apr 2016 13:52:27 -0700 Subject: [PATCH 09/29] patched level editor to the point of working on isoline. still cant set levels == to each other --- cdatgui/bases/input_dialog.py | 10 ++++- cdatgui/bases/value_slider.py | 6 +-- cdatgui/editors/isoline.py | 1 - cdatgui/editors/level_editor.py | 36 ++++++++--------- cdatgui/editors/secondary/editor/line.py | 41 +++++++++++++++++--- cdatgui/editors/widgets/adjust_values.py | 7 +--- cdatgui/editors/widgets/multi_line_editor.py | 23 +++++++++-- cdatgui/sidebar/inspector_widget.py | 4 +- 8 files changed, 87 insertions(+), 41 deletions(-) diff --git a/cdatgui/bases/input_dialog.py b/cdatgui/bases/input_dialog.py index a6e4495..2d4b20c 100644 --- a/cdatgui/bases/input_dialog.py +++ b/cdatgui/bases/input_dialog.py @@ -8,6 +8,10 @@ class ValidatingInputDialog(QtGui.QWidget): def __init__(self): super(ValidatingInputDialog, self).__init__() + self.setWindowModality(QtCore.Qt.ApplicationModal) + shortcut = QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Escape), self) + shortcut.activated.connect(self.cancel) + vertical_layout = QtGui.QVBoxLayout() self.label = QtGui.QLabel() @@ -18,7 +22,7 @@ def __init__(self): self.save_button.setEnabled(False) self.save_button.setDefault(True) cancel_button = QtGui.QPushButton('Cancel') - cancel_button.clicked.connect(self.rejected.emit) + cancel_button.clicked.connect(self.cancel) self.edit.returnPressed.connect(self.save_button.click) @@ -37,6 +41,10 @@ def __init__(self): self.setMaximumSize(300, 100) + def cancel(self): + self.close() + self.rejected.emit() + def save(self): self.close() self.accepted.emit() diff --git a/cdatgui/bases/value_slider.py b/cdatgui/bases/value_slider.py index d300303..3338678 100644 --- a/cdatgui/bases/value_slider.py +++ b/cdatgui/bases/value_slider.py @@ -18,7 +18,7 @@ def realValue(self): return self.values[self.value()] def setRealValue(self, realValue): - # print "VALUES:", self.values - val = self.values.index(realValue) - print "VAL", val + if isinstance(realValue, list): + realValue = realValue[0] + val = min(range(len(self.values)), key=lambda i: abs(self.values[i]-realValue)) self.setValue(val) diff --git a/cdatgui/editors/isoline.py b/cdatgui/editors/isoline.py index 30de497..9f96c52 100644 --- a/cdatgui/editors/isoline.py +++ b/cdatgui/editors/isoline.py @@ -62,7 +62,6 @@ def updateLabel(self, state): self.edit_label_button.setEnabled(True) def update(self): - # self._gm.list() pass @property diff --git a/cdatgui/editors/level_editor.py b/cdatgui/editors/level_editor.py index 23e4676..fbd2aba 100644 --- a/cdatgui/editors/level_editor.py +++ b/cdatgui/editors/level_editor.py @@ -1,4 +1,5 @@ """Provides a widget to manipulate the levels for a graphics method.""" +from bisect import bisect_left from cdatgui.cdat.vcswidget import QVCSWidget from PySide import QtCore, QtGui @@ -44,24 +45,16 @@ def __init__(self, parent=None): def reset_levels(self): self.gm.levels = self.orig_levs - #self.update_levels(self.gm.levels) self.levelsUpdated.emit() def update_levels(self, levs, clear=False): self.histo.bins = levs if clear: - print "Clearing" self.canvas.clear() - print "Cleared, now plotting" self.canvas.plot(self._var, self.histo) - print "Plotted" else: - print "Updating" self.canvas.update() - print "Updated" self._gm.levels = levs - print levs - print 'Updated levels' @property def var(self): @@ -72,28 +65,29 @@ def var(self, value): self._var = value flat = self._var.data flat = sorted(numpy.unique(flat.flatten())) - ''' - if flat[0] == -1e20: - flat = flat[1:] - if flat[-1] == 1e20: - flat = flat[:-1] - ''' + var_min, var_max = vcs.minmax(flat) - print "MIN MAX", var_min, var_max + # Check if we're using auto levels - if self._gm is None or not self.has_set_gm_levels(): + if vcs.graphicsmethodtype(self._gm) =='isoline' and not self.isoline_has_set_gm_levels(): + levs = vcs.utils.mkscale(var_min, var_max) + elif self._gm is None or not self.has_set_gm_levels(): # Update the automatic levels with this variable levs = vcs.utils.mkscale(var_min, var_max) - print "GENERATED LEVELS", levs else: # Otherwise, just use what the levels are levs = self._gm.levels + if isinstance(levs[0], list): + levs = [item[0] for item in levs] + step = (levs[-1] - levs[0])/1000 values = list(numpy.arange(levs[0], levs[-1]+step, step)) + for lev in levs: + if lev not in values: + values.insert(bisect_left(values, lev), lev) self.canvas.clear() - print "VALUES:", values, len(values) self.value_sliders.update(values, levs) self.update_levels(levs, clear=True) @@ -108,7 +102,6 @@ def gm(self, value): if self.has_set_gm_levels() and self.var is not None: levs = self._gm.levels flat = self._var.flatten() - var_min, var_max = vcs.minmax(flat) self.value_sliders.update(flat, levs) self.update_levels(levs, clear=True) @@ -118,6 +111,11 @@ def has_set_gm_levels(self): except: length = len(self._gm.levels) try: + print self._gm.levels return length != 2 or not numpy.allclose(self._gm.levels, [1e+20] * 2) except ValueError: return True + + def isoline_has_set_gm_levels(self): + length = len(self._gm.levels[0]) + return length != 2 or not numpy.allclose(self._gm.levels, [0.0, 1e+20]) diff --git a/cdatgui/editors/secondary/editor/line.py b/cdatgui/editors/secondary/editor/line.py index 14e10d2..0653518 100644 --- a/cdatgui/editors/secondary/editor/line.py +++ b/cdatgui/editors/secondary/editor/line.py @@ -6,11 +6,13 @@ class LineEditorWidget(BaseSaveWindowWidget): + saved = QtCore.Signal(str) + def __init__(self): super(LineEditorWidget, self).__init__() self.setPreview(LinePreviewWidget()) - self.savePressed.connect(self.saveNewLine) + self.orig_name = None # create labels type_label = QtGui.QLabel("Type:") @@ -46,10 +48,17 @@ def __init__(self): self.vertical_layout.insertLayout(1, row) def setLineObject(self, line_obj): + self.setWindowTitle('Edit {0} line'.format(line_obj.name)) + self.orig_name = line_obj.name + if line_obj.name == 'default': - line_obj = vcs.createline('new', line_obj.name) self.save_button.setEnabled(False) + if 'new' in vcs.elements['line']: + del vcs.elements['line']['new'] + + line_obj = vcs.createline('new', line_obj.name) + self.object = line_obj self.preview.setLineObject(self.object) @@ -70,16 +79,38 @@ def updateWidth(self, width): self.preview.update() def saveNewLine(self, name): - if name not in vcs.elements['line']: + name = str(name) + print "NAME", name + print "ORIG NAME", self.orig_name + + if name == "new": + if self.orig_name in vcs.elements['line']: + del vcs.elements['line'][self.orig_name] + + vcs.createline(self.orig_name, source=name) + # vcs.elements['line'][self.orig_name] = self.object + get_lines().updated(self.orig_name) + self.saved.emit(self.orig_name) + else: + if name in vcs.elements['line']: + del vcs.elements['line'][name] + vcs.createline(name, source='new') + get_lines().updated(name) + self.saved.emit(name) + + + ''' + # if name not in vcs.elements['line']: print "NAME:", name - vcs.createline(name, source=self.object.name) + vcs.createline(self.orig_name, source=self.object.name) # if the name was default, delete the new line that was created to allow editing - if self.object.name == 'new': + # if self.object.name == 'new': del vcs.elements['line']['new'] elif name != 'default': vcs.elements['line'][name] = self.object # add/update line with given name get_lines().updated(str(name)) + ''' diff --git a/cdatgui/editors/widgets/adjust_values.py b/cdatgui/editors/widgets/adjust_values.py index bfd4e32..ae783a8 100644 --- a/cdatgui/editors/widgets/adjust_values.py +++ b/cdatgui/editors/widgets/adjust_values.py @@ -43,13 +43,11 @@ def update(self, values, levs): self.clearing = True for ind in range(len(self.rows)): self.remove_level(self.rows[0]) - print "UPDATING LEVS", levs, len(levs) for ind, value in enumerate(levs): cur_slide = self.insert_line() - print "SETTING SLIDE VALUE", value, ind cur_slide.setRealValue(value) self.clearing = False - self.blockSignals(False) + self.blockSignals(block) def adjust_slides(self, slide, cur_val): cur_index = self.slides.index(slide) @@ -106,9 +104,6 @@ def insert_line(self): row.addWidget(slide) # set slide attributes - # slide.setRange(self.min_val, self.max_val) - - # slide.setValue(self.max_val) slide.setTickInterval(len(self.values) / 20) slide.setTickPosition(QSlider.TicksAbove) slide.valueChanged.connect(partial(self.change_label, lab, slide)) diff --git a/cdatgui/editors/widgets/multi_line_editor.py b/cdatgui/editors/widgets/multi_line_editor.py index 7948d57..153bd8a 100644 --- a/cdatgui/editors/widgets/multi_line_editor.py +++ b/cdatgui/editors/widgets/multi_line_editor.py @@ -9,6 +9,21 @@ from cdatgui.bases.input_dialog import ValidatingInputDialog +class LineNameDialog(ValidatingInputDialog): + def save(self): + print "SAVING" + if self.textValue() in vcs.elements['line']: + check = QtGui.QMessageBox.question(self, "Overwrite line?", + "Line {0} already exists. Overwrite?".format(self.textValue()), + buttons=QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) + if check == QtGui.QDialogButtonBox.FirstButton: + self.close() + self.accepted.emit() + else: + self.close() + self.accepted.emit() + + class LineTextValidator(QtGui.QValidator): invalidInput = QtCore.Signal() validInput = QtCore.Signal() @@ -31,6 +46,7 @@ def __init__(self): self.line_combos = [] self.dynamic_grid = DynamicGridLayout(400) self.vertical_layout.insertLayout(0, self.dynamic_grid) + self.setWindowTitle("Edit Lines") def setObject(self, object): self.isoline_model = object @@ -75,7 +91,7 @@ def editLine(self, index): self.line_editor.close() self.line_editor.deleteLater() self.line_editor = LineEditorWidget() - dialog = ValidatingInputDialog() + dialog = LineNameDialog() dialog.setValidator(LineTextValidator()) self.line_editor.setSaveDialog(dialog) @@ -83,7 +99,7 @@ def editLine(self, index): line_obj = vcs.getline(line) self.line_editor.setLineObject(line_obj) - self.line_editor.savePressed.connect(partial(self.update, index)) + self.line_editor.saved.connect(partial(self.update, index)) self.line_editor.show() self.line_editor.raise_() @@ -91,8 +107,9 @@ def editLine(self, index): def changeLine(self, row_index, combo_index): self.isoline_model.line[row_index] = get_lines().elements[combo_index] - def update(self, index, name): # TODO: restructure name so that it saves a line not pass the name back + def update(self, index, name): self.isoline_model.line[index] = str(name) + print "SETTING COMBO", name self.line_combos[index].setCurrentIndex(self.line_combos[index].findText(name)) def okClicked(self): diff --git a/cdatgui/sidebar/inspector_widget.py b/cdatgui/sidebar/inspector_widget.py index 9aa3e0f..8341aaf 100644 --- a/cdatgui/sidebar/inspector_widget.py +++ b/cdatgui/sidebar/inspector_widget.py @@ -170,9 +170,6 @@ def editSecondVar(self, var): def editGraphicsMethod(self, gm): get_gms().replace(get_gms().indexOf(vcs.graphicsmethodtype(gm), gm), gm) - print "SETTING GM", gm.list() - for line in gm.line: - vcs.getline(line).list() self.current_plot.graphics_method = gm def makeGraphicsMethod(self, gm): @@ -219,6 +216,7 @@ def deletePlot(self, plot): def setGMRoot(self, index): self.gm_instance_combo.setRootModelIndex(get_gms().index(index, 0)) + self.edit_gm_button.setEnabled(False) def setTemplate(self, template): self.current_plot.template = template From 61d7e915db4a960b5e0910c59117c99dd04d1607 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Tue, 26 Apr 2016 12:24:05 -0700 Subject: [PATCH 10/29] fixed bug with random changeLine call --- cdatgui/bases/dynamic_grid_layout.py | 6 ++- cdatgui/editors/level_editor.py | 8 ++- cdatgui/editors/model/line_model.py | 18 ++----- cdatgui/editors/secondary/editor/line.py | 17 ------ cdatgui/editors/widgets/multi_line_editor.py | 21 +++++--- cdatgui/variables/variable_add.py | 54 ++++++++++++++------ 6 files changed, 65 insertions(+), 59 deletions(-) diff --git a/cdatgui/bases/dynamic_grid_layout.py b/cdatgui/bases/dynamic_grid_layout.py index 7f198df..75222fb 100644 --- a/cdatgui/bases/dynamic_grid_layout.py +++ b/cdatgui/bases/dynamic_grid_layout.py @@ -78,7 +78,7 @@ def buildGrid(self, rect, force=False): self.cur_col_count = possible_columns def clearWidgets(self): - """clears widgets from the grid layout. Does not delete widgets""" + """Clears widgets from the grid layout. Does not delete widgets""" for col, row_count in enumerate(self.counts): if row_count: for row in range(row_count): @@ -93,7 +93,9 @@ def getWidgets(self): return self.widgets def removeWidget(self, widget): - """removes widgets from gridlayout and updates list and counts""" + """Removes widgets from gridlayout and updates list and counts + Does Not Delete Widget + """ for i in self.widgets: if i == widget: diff --git a/cdatgui/editors/level_editor.py b/cdatgui/editors/level_editor.py index fbd2aba..3e854a6 100644 --- a/cdatgui/editors/level_editor.py +++ b/cdatgui/editors/level_editor.py @@ -80,9 +80,13 @@ def var(self, value): if isinstance(levs[0], list): levs = [item[0] for item in levs] + try: + step = (levs[-1] - levs[0])/1000 + values = list(numpy.arange(levs[0], levs[-1]+step, step)) + except: + step = (levs[-1][0] - levs[0][0])/1000 + values = list(numpy.arange(levs[0][0], levs[-1][0]+step, step)) - step = (levs[-1] - levs[0])/1000 - values = list(numpy.arange(levs[0], levs[-1]+step, step)) for lev in levs: if lev not in values: values.insert(bisect_left(values, lev), lev) diff --git a/cdatgui/editors/model/line_model.py b/cdatgui/editors/model/line_model.py index cc7cf5a..81a312b 100644 --- a/cdatgui/editors/model/line_model.py +++ b/cdatgui/editors/model/line_model.py @@ -5,6 +5,7 @@ class LineModel(LevelsBaseModel): def __init__(self, gm, var, canvas=None): + print "CREATING LINE MODEL" self._gm = gm self._var = var self._canvas = canvas @@ -13,23 +14,10 @@ def __init__(self, gm, var, canvas=None): @property def line(self): while len(self._gm.line) < len(self._gm.levels): - while True: - try: - old_line = vcs.getline(self._gm.line[-1]) - - name = "line_{0}".format(self.count) - new_line = vcs.createline(str(name)) - new_line.type = old_line.type - new_line.color = old_line.color - new_line.width = old_line.width - get_lines().updated(name) - self.count += 1 - break - except vcs.vcsError as e: - self.count += 1 - self._gm.line.append(new_line.name) + self._gm.line.append(self._gm.line[-1]) while len(self._gm.line) > len(self._gm.levels): self._gm.line.remove(self._gm.line[-1]) + print "RETURNING:", self._gm.line return self._gm.line @property diff --git a/cdatgui/editors/secondary/editor/line.py b/cdatgui/editors/secondary/editor/line.py index 0653518..8d2f9e9 100644 --- a/cdatgui/editors/secondary/editor/line.py +++ b/cdatgui/editors/secondary/editor/line.py @@ -97,20 +97,3 @@ def saveNewLine(self, name): vcs.createline(name, source='new') get_lines().updated(name) self.saved.emit(name) - - - ''' - # if name not in vcs.elements['line']: - print "NAME:", name - - vcs.createline(self.orig_name, source=self.object.name) - - # if the name was default, delete the new line that was created to allow editing - # if self.object.name == 'new': - del vcs.elements['line']['new'] - elif name != 'default': - vcs.elements['line'][name] = self.object - - # add/update line with given name - get_lines().updated(str(name)) - ''' diff --git a/cdatgui/editors/widgets/multi_line_editor.py b/cdatgui/editors/widgets/multi_line_editor.py index 153bd8a..18e595a 100644 --- a/cdatgui/editors/widgets/multi_line_editor.py +++ b/cdatgui/editors/widgets/multi_line_editor.py @@ -48,7 +48,8 @@ def __init__(self): self.vertical_layout.insertLayout(0, self.dynamic_grid) self.setWindowTitle("Edit Lines") - def setObject(self, object): + def setObject(self, object, *args): + print "SETTING OBJECT" self.isoline_model = object widgets = [] @@ -58,6 +59,7 @@ def setObject(self, object): for widget in grid_widgets: self.dynamic_grid.removeWidget(widget) + widget.deleteLater() # repopulate for ind, lev in enumerate(self.isoline_model.levels): @@ -66,13 +68,21 @@ def setObject(self, object): line_combo = QtGui.QComboBox() line_combo.setModel(get_lines()) - line_combo.currentIndexChanged.connect(partial(self.changeLine, ind)) - line_combo.setCurrentIndex(get_lines().elements.index(self.isoline_model.line[ind])) + # must call to adjust values for length of levels before indexing into levels + lines = self.isoline_model.line + item = self.isoline_model.line[ind] + + print "LINES", lines + print "ITEM:", item + print "ELEMENTS:", get_lines().elements + line_combo.setCurrentIndex(get_lines().elements.index(item)) self.line_combos.append(line_combo) edit_line = QtGui.QPushButton('Edit Line') edit_line.clicked.connect(partial(self.editLine, ind)) + line_combo.currentIndexChanged.connect(partial(self.changeLine, ind)) + # add everything to layout row.addWidget(line_label) row.addWidget(line_combo) @@ -82,8 +92,6 @@ def setObject(self, object): row_widget.setLayout(row) widgets.append(row_widget) - print object._gm.linecolors - self.dynamic_grid.addNewWidgets(widgets) def editLine(self, index): @@ -105,11 +113,12 @@ def editLine(self, index): self.line_editor.raise_() def changeLine(self, row_index, combo_index): + print "ChangeLine, row_i, combo_i", row_index, combo_index self.isoline_model.line[row_index] = get_lines().elements[combo_index] def update(self, index, name): + print "UPDATING:", index, name self.isoline_model.line[index] = str(name) - print "SETTING COMBO", name self.line_combos[index].setCurrentIndex(self.line_combos[index].findText(name)) def okClicked(self): diff --git a/cdatgui/variables/variable_add.py b/cdatgui/variables/variable_add.py index a68724c..dec7b15 100644 --- a/cdatgui/variables/variable_add.py +++ b/cdatgui/variables/variable_add.py @@ -8,6 +8,7 @@ from cdms_file_tree import CDMSFileTree from manager import manager from . import get_variables +from cdatgui.bases.input_dialog import ValidatingInputDialog class dummyVar(object): @@ -15,10 +16,31 @@ def __init__(self, id): self.id = id +class FileNameValidator(QtGui.QValidator): + invalidInput = QtCore.Signal() + validInput = QtCore.Signal() + + def __init__(self): + super(FileNameValidator, self).__init__() + self.reserved_words = ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global', 'or', 'with', + 'assert', 'else', 'if', 'pass', 'yield', 'break', 'except', 'import', 'print', 'class', + 'exec', 'in', 'raise', 'continue', 'finally', 'is', 'return', 'def', 'for', 'lambda', + 'try'] + + def validate(self, name, pos): + if name in self.reserved_words or not re.search("^[a-zA-Z_]", name) or name == '' \ + or re.search(' +', name) or re.search("[^a-zA-Z0-9_]+", name) \ + or get_variables().variable_exists(dummyVar(name)): + self.invalidInput.emit() + return QtGui.QValidator.Intermediate + self.validInput.emit() + return QtGui.QValidator.Acceptable + + class AddDialog(QtGui.QDialog): def __init__(self, parent=None, f=0): super(AddDialog, self).__init__(parent=parent, f=f) - self.renameVar = None + self.renameVar = [] self.dialog = None self.reserved_words = ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global', 'or', 'with', 'assert', 'else', 'if', 'pass', 'yield', 'break', 'except', 'import', 'print', 'class', @@ -73,9 +95,9 @@ def addFileToTree(self, file): def selected_variables(self): if self.renameVar: - var = self.renameVar - self.renameVar = None - return [var] + var_list = self.renameVar + self.renameVar = [] + return var_list else: return self.tree.get_selected() @@ -97,21 +119,19 @@ def rename_file(self): return var = var[0] - while True: - name = QtGui.QInputDialog.getText(self, u"Import As", u"Enter new variable name") - if not name[1] or (name[1] and self.isValidName(name[0])): - break + self.dialog = ValidatingInputDialog() + self.dialog.setValidator(FileNameValidator()) + self.dialog.accepted.connect(partial(self.setRenameVar, var)) + self.dialog.setWindowTitle("Import As") + self.dialog.setLabelText("Enter New Name:") - QtGui.QMessageBox.warning(self, "Error", "Invalid name") + self.dialog.show() + self.dialog.raise_() - str_name = name[0] - var.id = str_name - self.renameVar = var - if name[1]: - self.buttons.accepted.emit() - else: - self.buttons.rejected.emit() - self.close() + def setRenameVar(self, var): + self.renameVar.append(var) + self.renameVar[-1].id = self.dialog.textValue() + self.dialog.close() def isValidName(self, name): if name in self.reserved_words or not re.search("^[a-zA-Z_]", name) or name == '' \ From 202d93081701911f7d2927699394be304e7b75ff Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Wed, 27 Apr 2016 11:07:29 -0700 Subject: [PATCH 11/29] added multi text editor. fixed insert bug in multi line editor --- cdatgui/editors/isoline.py | 13 +- .../model/{line_model.py => isoline_model.py} | 19 ++- cdatgui/editors/secondary/editor/text.py | 133 ++++++++++++------ cdatgui/editors/secondary/preview/text.py | 2 +- cdatgui/editors/widgets/multi_line_editor.py | 9 +- cdatgui/editors/widgets/multi_text_editor.py | 119 ++++++++++++++++ cdatgui/variables/variable_add.py | 1 + cdatgui/vcsmodel/elements.py | 3 +- cdatgui/vcsmodel/secondary.py | 2 + 9 files changed, 241 insertions(+), 60 deletions(-) rename cdatgui/editors/model/{line_model.py => isoline_model.py} (55%) create mode 100644 cdatgui/editors/widgets/multi_text_editor.py diff --git a/cdatgui/editors/isoline.py b/cdatgui/editors/isoline.py index 9f96c52..cb175ff 100644 --- a/cdatgui/editors/isoline.py +++ b/cdatgui/editors/isoline.py @@ -1,9 +1,9 @@ from PySide import QtGui, QtCore from .graphics_method_editor import GraphicsMethodEditorWidget -from .secondary.editor.text import TextStyleEditorWidget from .widgets.multi_line_editor import MultiLineEditor -from .model.line_model import LineModel +from .model.isoline_model import IsolineModel +from .widgets.multi_text_editor import MultiTextEditor class IsolineEditor(GraphicsMethodEditorWidget): @@ -39,7 +39,8 @@ def __init__(self, parent=None): def editText(self): if not self.text_edit_widget: - self.text_edit_widget = TextStyleEditorWidget() + self.text_edit_widget = MultiTextEditor() + self.text_edit_widget.setObject(IsolineModel(self._gm, self._var)) self.text_edit_widget.show() self.text_edit_widget.raise_() @@ -48,8 +49,7 @@ def editLines(self): self.line_edit_widget.close() self.line_edit_widget.deleteLater() self.line_edit_widget = MultiLineEditor() - self.line_edit_widget.setObject(LineModel(self._gm, self._var)) - self.line_edit_widget.okPressed.connect(self.update) + self.line_edit_widget.setObject(IsolineModel(self._gm, self._var)) self.line_edit_widget.show() self.line_edit_widget.raise_() @@ -61,9 +61,6 @@ def updateLabel(self, state): self._gm.label = True self.edit_label_button.setEnabled(True) - def update(self): - pass - @property def var(self): return self._var diff --git a/cdatgui/editors/model/line_model.py b/cdatgui/editors/model/isoline_model.py similarity index 55% rename from cdatgui/editors/model/line_model.py rename to cdatgui/editors/model/isoline_model.py index 81a312b..ac73ac6 100644 --- a/cdatgui/editors/model/line_model.py +++ b/cdatgui/editors/model/isoline_model.py @@ -1,11 +1,11 @@ from .levels_base import LevelsBaseModel -from cdatgui.vcsmodel import get_lines +from cdatgui.vcsmodel import get_textstyles import vcs -class LineModel(LevelsBaseModel): +class IsolineModel(LevelsBaseModel): def __init__(self, gm, var, canvas=None): - print "CREATING LINE MODEL" + print "CREATING ISOLINE MODEL" self._gm = gm self._var = var self._canvas = canvas @@ -28,3 +28,16 @@ def linecolors(self): def linewidths(self): return self._gm.linewidths + @property + def text(self): + if not self._gm.text: + self._gm.text = ['default'] + while len(self._gm.text) < len(self._gm.levels): + self._gm.text.append(self._gm.text[-1]) + while len(self._gm.text) > len(self._gm.levels): + self._gm.text.remove(self._gm.text[-1]) + return self._gm.text + + @property + def textcolors(self): + return self._gm.textcolors diff --git a/cdatgui/editors/secondary/editor/text.py b/cdatgui/editors/secondary/editor/text.py index a410afa..a15c54d 100755 --- a/cdatgui/editors/secondary/editor/text.py +++ b/cdatgui/editors/secondary/editor/text.py @@ -2,12 +2,17 @@ from cdatgui.editors.secondary.preview.text import TextStylePreviewWidget from PySide import QtCore, QtGui from cdatgui.bases.window_widget import BaseSaveWindowWidget +from cdatgui.vcsmodel import get_textstyles class TextStyleEditorWidget(BaseSaveWindowWidget): + saved = QtCore.Signal(str) + def __init__(self): super(TextStyleEditorWidget, self).__init__() self.setPreview(TextStylePreviewWidget()) + self.savePressed.connect(self.saveNewText) + self.orig_names = [] # Set up vertical align self.va_group = QtGui.QButtonGroup() @@ -90,12 +95,27 @@ def __init__(self): self.vertical_layout.insertLayout(2, font_size_row) def setTextObject(self, text_object): - self.textObject = text_object - self.preview.setTextObject(self.textObject) - self.setWindowTitle('Edit Style "%s"' % self.textObject.name) + self.orig_names = [text_object.name, text_object.Tt_name, text_object.To_name] + + if text_object.Tt_name == 'default' and text_object.To_name == 'default': + self.save_button.setEnabled(False) + + if 'new:::new' in vcs.elements['textcombined']: + del vcs.elements['textcombined']['new:::new'] + try: + del vcs.elements['textorientation']['new'] + del vcs.elements['texttable']['new'] + except KeyError: + pass + + text_object = vcs.createtextcombined('new', text_object.Tt_name, 'new', text_object.To_name) + + self.object = text_object + self.preview.setTextObject(self.object) + self.setWindowTitle('Edit Style "%s"' % self.object.name.split(':::')[0]) # set initial values - cur_valign = self.textObject.valign + cur_valign = self.object.valign for button in self.va_group.buttons(): if cur_valign == 0 and button.text() == "Top": button.setChecked(True) @@ -104,7 +124,7 @@ def setTextObject(self, text_object): elif cur_valign == 4 and button.text() == "Bot": button.setChecked(True) - cur_halign = self.textObject.halign + cur_halign = self.object.halign for button in self.ha_group.buttons(): if cur_halign == 0 and button.text() == "Left": button.setChecked(True) @@ -113,66 +133,97 @@ def setTextObject(self, text_object): elif cur_halign == 2 and button.text() == "Right": button.setChecked(True) - self.angle_slider.setSliderPosition(self.textObject.angle) - - self.size_box.setValue(self.textObject.height) + self.angle_slider.setSliderPosition(self.object.angle) + self.size_box.setValue(self.object.height) def updateButton(self, button): if button.text() == "Top": - self.textObject.valign = "top" - + self.object.valign = "top" elif button.text() == "Mid": - self.textObject.valign = "half" - + self.object.valign = "half" elif button.text() == "Bot": - self.textObject.valign = "bottom" - + self.object.valign = "bottom" elif button.text() == "Left": - self.textObject.halign = "left" - + self.object.halign = "left" elif button.text() == "Center": - self.textObject.halign = "center" - + self.object.halign = "center" elif button.text() == "Right": - self.textObject.halign = "right" - + self.object.halign = "right" self.preview.update() def updateAngle(self, angle): + self.object.angle = angle % 360 # angle cannot be higher than 360 + self.preview.update() - self.textObject.angle = angle % 360 # angle cannot be higher than 360 + def updateFont(self, font): + self.object.font = str(font) + self.preview.update() + def updateSize(self, size): + self.object.height = size self.preview.update() - def updateFont(self, font): + def saveNewText(self, name): + name = str(name) - self.textObject.font = str(font) + if name != 'new:::new': + # getting object + to = vcs.elements['textorientation']['new'] + tt = vcs.elements['texttable']['new'] - self.preview.update() + # deleting if already exists. This will only happen if they want to overwrite + if name in vcs.elements['texttable']: + del vcs.elements['texttable'][name] + if name in vcs.elements['textorientation']: + del vcs.elements['textorientation'][name] - def updateSize(self, size): + # inserting new object + new_tt = vcs.createtexttable(name, source=tt) + new_to = vcs.createtextorientation(name, source=to) + vcs.elements['textorientation'][name] = new_to + vcs.elements['texttable'][name] = new_tt - self.textObject.height = size + # removing old object from key + vcs.elements['textorientation'].pop('new') + vcs.elements['texttable'].pop('new') - self.preview.update() + tc = vcs.createtextcombined() + tc.Tt = new_tt + tc.To = new_to + + # inserting into model + get_textstyles().updated(name) + + # adding to list + self.saved.emit(name) + + else: + # recover original info + old_tt = vcs.elements['texttable'][self.orig_names[1]] + old_to = vcs.elements['textorientation'][self.orig_names[2]] - def saveAs(self): + # get new info + new_tt = vcs.elements['texttable']['new'] + new_to = vcs.elements['textorientation']['new'] - self.win = QtGui.QInputDialog() + # delete old tt and to + old_tt_name = old_tt.name + old_to_name = old_to.name - self.win.setLabelText("Enter New Name:") - self.win.accepted.connect(self.save) + del vcs.elements['texttable'][self.orig_names[1]] + del vcs.elements['textorientation'][self.orig_names[2]] - self.win.show() - self.win.raise_() + # create new tt and to objects with old name and new attributes + brand_new_tt = vcs.createtexttable(old_tt_name, source=new_tt) + brand_new_to = vcs.createtextorientation(old_to_name, source=new_to) - def save(self): + tc = vcs.createtextcombined() + tc.Tt = brand_new_tt + tc.To = brand_new_to + vcs.elements['textcombined'][self.orig_names[0]] = tc - try: - name = self.win.textValue() - self.win.close() - except: - name = self.textObject.name + # inserting into model + get_textstyles().updated(old_tt_name) - self.savePressed.emit(name) - self.close() + # adding to list + self.saved.emit(old_tt_name) diff --git a/cdatgui/editors/secondary/preview/text.py b/cdatgui/editors/secondary/preview/text.py index 2e73445..e21c24b 100755 --- a/cdatgui/editors/secondary/preview/text.py +++ b/cdatgui/editors/secondary/preview/text.py @@ -9,7 +9,7 @@ def __init__(self, parent=None): def setTextObject(self, textobject): self.textobj = textobject - tmpobj = vcs.createtext(Tt_source=self.textobj.Tt, To_source=self.textobj.To) + tmpobj = vcs.createtext(Tt_source=self.textobj.Tt_name, To_source=self.textobj.To_name) tmpobj.string = ["%s Preview" % self.textobj.name] tmpobj.x = [.5] tmpobj.y = [.5] diff --git a/cdatgui/editors/widgets/multi_line_editor.py b/cdatgui/editors/widgets/multi_line_editor.py index 18e595a..36a4092 100644 --- a/cdatgui/editors/widgets/multi_line_editor.py +++ b/cdatgui/editors/widgets/multi_line_editor.py @@ -47,6 +47,7 @@ def __init__(self): self.dynamic_grid = DynamicGridLayout(400) self.vertical_layout.insertLayout(0, self.dynamic_grid) self.setWindowTitle("Edit Lines") + self.resize(300, self.height()) def setObject(self, object, *args): print "SETTING OBJECT" @@ -68,13 +69,9 @@ def setObject(self, object, *args): line_combo = QtGui.QComboBox() line_combo.setModel(get_lines()) - # must call to adjust values for length of levels before indexing into levels - lines = self.isoline_model.line - item = self.isoline_model.line[ind] - print "LINES", lines - print "ITEM:", item - print "ELEMENTS:", get_lines().elements + # set to current line + item = self.isoline_model.line[ind] line_combo.setCurrentIndex(get_lines().elements.index(item)) self.line_combos.append(line_combo) diff --git a/cdatgui/editors/widgets/multi_text_editor.py b/cdatgui/editors/widgets/multi_text_editor.py new file mode 100644 index 0000000..e9aa9bd --- /dev/null +++ b/cdatgui/editors/widgets/multi_text_editor.py @@ -0,0 +1,119 @@ +from PySide import QtCore, QtGui +from functools import partial + +from cdatgui.editors.secondary.editor.text import TextStyleEditorWidget +from cdatgui.bases.window_widget import BaseOkWindowWidget +from cdatgui.bases.dynamic_grid_layout import DynamicGridLayout +import vcs +from cdatgui.bases.input_dialog import ValidatingInputDialog +from cdatgui.vcsmodel import get_textstyles + + +class TextNameDialog(ValidatingInputDialog): + def save(self): + if self.textValue() in vcs.elements['texttable'] or self.textValue() in vcs.elements['textorientation']: + check = QtGui.QMessageBox.question(self, "Overwrite text?", + "Text {0} already exists. Overwrite?".format(self.textValue()), + buttons=QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) + if check == QtGui.QDialogButtonBox.FirstButton: + self.close() + self.accepted.emit() + else: + self.close() + self.accepted.emit() + + +class TextNameValidator(QtGui.QValidator): + invalidInput = QtCore.Signal() + validInput = QtCore.Signal() + + def validate(self, inp, pos): + inp = inp.strip() + if not inp or inp == 'default': + self.invalidInput.emit() + return QtGui.QValidator.Intermediate + + self.validInput.emit() + return QtGui.QValidator.Acceptable + + +class MultiTextEditor(BaseOkWindowWidget): + def __init__(self): + super(MultiTextEditor, self).__init__() + self.isoline_model = None + self.text_editor = None + self.text_combos = [] + self.dynamic_grid = DynamicGridLayout(400) + self.vertical_layout.insertLayout(0, self.dynamic_grid) + self.setWindowTitle("Edit Texts") + self.resize(300, self.height()) + + def setObject(self, object): + print "SETTING OBJECT" + self.isoline_model = object + widgets = [] + + # clear grid + grid_widgets = self.dynamic_grid.getWidgets() + self.dynamic_grid.clearWidgets() + + for widget in grid_widgets: + self.dynamic_grid.removeWidget(widget) + widget.deleteLater() + + # repopulate + for ind, lev in enumerate(self.isoline_model.levels): + row = QtGui.QHBoxLayout() + text_label = QtGui.QLabel("Text:") + + text_combo = QtGui.QComboBox() + text_combo.setModel(get_textstyles()) + + # set to current text + item = self.isoline_model.text[ind] + text_combo.setCurrentIndex(get_textstyles().elements.index(item)) + self.text_combos.append(text_combo) + + edit_text = QtGui.QPushButton('Edit Text') + edit_text.clicked.connect(partial(self.editText, ind)) + + text_combo.currentIndexChanged[str].connect(partial(self.changeText, ind)) + + # add everything to layout + row.addWidget(text_label) + row.addWidget(text_combo) + row.addWidget(edit_text) + + row_widget = QtGui.QWidget() + row_widget.setLayout(row) + widgets.append(row_widget) + + self.dynamic_grid.addNewWidgets(widgets) + + def editText(self, index): + if self.text_editor: + self.text_editor.close() + self.text_editor.deleteLater() + self.text_editor = TextStyleEditorWidget() + dialog = TextNameDialog() + dialog.setValidator(TextNameValidator()) + self.text_editor.setSaveDialog(dialog) + + text = self.isoline_model.text[index] + text_obj = get_textstyles().get_el(text) + + self.text_editor.setTextObject(text_obj) + self.text_editor.saved.connect(partial(self.update, index)) + + self.text_editor.show() + self.text_editor.raise_() + + def changeText(self, row_index, combo_index): + self.isoline_model.text[row_index] = get_textstyles().elements[get_textstyles().elements.index(combo_index)] + + def update(self, index, name): + self.text_combos[index].setCurrentIndex(self.text_combos[index].findText(name)) + + def okClicked(self): + self.okPressed.emit() + self.close() diff --git a/cdatgui/variables/variable_add.py b/cdatgui/variables/variable_add.py index dec7b15..a8620e5 100644 --- a/cdatgui/variables/variable_add.py +++ b/cdatgui/variables/variable_add.py @@ -131,6 +131,7 @@ def rename_file(self): def setRenameVar(self, var): self.renameVar.append(var) self.renameVar[-1].id = self.dialog.textValue() + self.accepted.emit() self.dialog.close() def isValidName(self, name): diff --git a/cdatgui/vcsmodel/elements.py b/cdatgui/vcsmodel/elements.py index 08522ea..5c92000 100644 --- a/cdatgui/vcsmodel/elements.py +++ b/cdatgui/vcsmodel/elements.py @@ -53,6 +53,7 @@ def updated(self, el_name): if insert_ind == -1: new_els.append(el_name) insert_ind = len(self.elements) - self.beginInsertRows(QtCore.QModelIndex(), insert_ind, 1) + self.beginInsertRows(QtCore.QModelIndex(), insert_ind, insert_ind) + print "NEW ELEMENTS:", new_els self.elements = new_els self.endInsertRows() diff --git a/cdatgui/vcsmodel/secondary.py b/cdatgui/vcsmodel/secondary.py index 64bfb01..d0ccbbd 100644 --- a/cdatgui/vcsmodel/secondary.py +++ b/cdatgui/vcsmodel/secondary.py @@ -33,9 +33,11 @@ def get_el(self, name): tc = vcs.gettextcombined(tc) if tc.To_name == name and tc.Tt_name == name: return tc + tc = vcs.createtextcombined() tc.Tt = tt tc.To = to + return tc def isa(self, obj): From da6a6ff592d9ef6c86e17fab3110a8f5be15f2bf Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Thu, 28 Apr 2016 10:33:45 -0700 Subject: [PATCH 12/29] writing new tests for gm editors and reworking old tests --- cdatgui/bases/window_widget.py | 3 + cdatgui/editors/axis_editor.py | 1 - cdatgui/editors/boxfill.py | 1 - cdatgui/editors/colormap.py | 1 + cdatgui/editors/graphics_method_editor.py | 11 +-- cdatgui/editors/isoline.py | 12 +-- cdatgui/editors/level_editor.py | 4 +- cdatgui/editors/model/isoline_model.py | 2 - cdatgui/editors/model/vcsaxis.py | 5 +- cdatgui/editors/secondary/editor/line.py | 3 - cdatgui/editors/secondary/editor/text.py | 5 ++ cdatgui/editors/widgets/legend_widget.py | 38 +++++--- cdatgui/editors/widgets/multi_line_editor.py | 3 +- cdatgui/editors/widgets/multi_text_editor.py | 3 +- cdatgui/graphics/dialog.py | 3 +- cdatgui/variables/cdms_file_chooser.py | 2 +- cdatgui/variables/variable_add.py | 4 +- cdatgui/vcsmodel/elements.py | 3 - tests/test_GmDialog.py | 93 ++++++++++++++++++++ tests/test_TextStyleEditor.py | 56 +++++++----- 20 files changed, 192 insertions(+), 61 deletions(-) create mode 100644 tests/test_GmDialog.py diff --git a/cdatgui/bases/window_widget.py b/cdatgui/bases/window_widget.py index ae997d7..52f5d37 100644 --- a/cdatgui/bases/window_widget.py +++ b/cdatgui/bases/window_widget.py @@ -10,6 +10,7 @@ def __init__(self): self.object = None self.preview = None self.dialog = QtGui.QInputDialog() + self.setWindowModality(QtCore.Qt.ApplicationModal) # Layout to add new elements self.vertical_layout = QtGui.QVBoxLayout() @@ -71,6 +72,7 @@ def save(self): def setSaveDialog(self, dialog): self.dialog = dialog + class BaseOkWindowWidget(QtGui.QWidget): okPressed = QtCore.Signal() @@ -79,6 +81,7 @@ def __init__(self): self.object = None self.preview = None + self.setWindowModality(QtCore.Qt.ApplicationModal) # Layout to add new elements self.vertical_layout = QtGui.QVBoxLayout() diff --git a/cdatgui/editors/axis_editor.py b/cdatgui/editors/axis_editor.py index 4ee84e7..ec08f1c 100644 --- a/cdatgui/editors/axis_editor.py +++ b/cdatgui/editors/axis_editor.py @@ -56,7 +56,6 @@ def __init__(self, axis, parent=None): self.tickmark_button_group.buttonClicked.connect(self.updateTickmark) # create preset combo box - # This in only being tracked for debugging preset_box = QtGui.QComboBox() preset_box.addItem("default") preset_box.addItems(vcs.listelements("list")) diff --git a/cdatgui/editors/boxfill.py b/cdatgui/editors/boxfill.py index 5ebd43c..0ae5cda 100644 --- a/cdatgui/editors/boxfill.py +++ b/cdatgui/editors/boxfill.py @@ -12,7 +12,6 @@ class BoxfillEditor(GraphicsMethodEditorWidget): def __init__(self, parent=None): """Initialize the object.""" super(BoxfillEditor, self).__init__(parent=parent) - print "CREATING BOXFILL EDITOR" self.boxfill_types = OrderedDict( Linear="linear", Logarithmic="log10", diff --git a/cdatgui/editors/colormap.py b/cdatgui/editors/colormap.py index e12c91b..de40be1 100644 --- a/cdatgui/editors/colormap.py +++ b/cdatgui/editors/colormap.py @@ -12,6 +12,7 @@ class QColormapEditor(QtGui.QColorDialog): def __init__(self, mode=COLORMAP_MODE, parent=None): QtGui.QColorDialog.__init__(self, parent) + self.setWindowModality(QtCore.Qt.ApplicationModal) self.parent = parent self.setOption(QtGui.QColorDialog.DontUseNativeDialog, True) self.setOption(QtGui.QColorDialog.NoButtons) diff --git a/cdatgui/editors/graphics_method_editor.py b/cdatgui/editors/graphics_method_editor.py index 54f0622..a13c12c 100644 --- a/cdatgui/editors/graphics_method_editor.py +++ b/cdatgui/editors/graphics_method_editor.py @@ -51,9 +51,11 @@ def __init__(self, parent=None): self.axis_editor = None def editAxis(self, axis): - if self.axis_editor is None: - self.axis_editor = AxisEditorWidget(axis[0]) - self.axis_editor.okPressed.connect(self.updated) + if self.axis_editor: + self.axis_editor.close() + self.axis_editor.deleteLater() + self.axis_editor = AxisEditorWidget(axis[0]) + self.axis_editor.okPressed.connect(self.updated) axis = VCSAxis(self._gm, self.tmpl, axis, self.var) self.axis_editor.setAxisObject(axis) self.axis_editor.show() @@ -107,5 +109,4 @@ def editLegend(self): legend = VCSLegend(self.gm, self.var.var) self.legend_editor.setObject(legend) self.legend_editor.show() - self.legend_editor - + self.legend_editor.raise_() diff --git a/cdatgui/editors/isoline.py b/cdatgui/editors/isoline.py index cb175ff..784b966 100644 --- a/cdatgui/editors/isoline.py +++ b/cdatgui/editors/isoline.py @@ -38,11 +38,13 @@ def __init__(self, parent=None): self.line_edit_widget = None def editText(self): - if not self.text_edit_widget: - self.text_edit_widget = MultiTextEditor() - self.text_edit_widget.setObject(IsolineModel(self._gm, self._var)) - self.text_edit_widget.show() - self.text_edit_widget.raise_() + if self.text_edit_widget: + self.text_edit_widget.close() + self.text_edit_widget.deleteLater() + self.text_edit_widget = MultiTextEditor() + self.text_edit_widget.setObject(IsolineModel(self._gm, self._var)) + self.text_edit_widget.show() + self.text_edit_widget.raise_() def editLines(self): if self.line_edit_widget: diff --git a/cdatgui/editors/level_editor.py b/cdatgui/editors/level_editor.py index 3e854a6..f7bf08b 100644 --- a/cdatgui/editors/level_editor.py +++ b/cdatgui/editors/level_editor.py @@ -20,6 +20,8 @@ def __init__(self, parent=None): self._var = None self._gm = None + self.setWindowModality(QtCore.Qt.ApplicationModal) + self.canvas = QVCSWidget() self.value_sliders = AdjustValues() self.value_sliders.valuesChanged.connect(self.update_levels) @@ -90,7 +92,7 @@ def var(self, value): for lev in levs: if lev not in values: values.insert(bisect_left(values, lev), lev) - + print "LEVS:", levs self.canvas.clear() self.value_sliders.update(values, levs) self.update_levels(levs, clear=True) diff --git a/cdatgui/editors/model/isoline_model.py b/cdatgui/editors/model/isoline_model.py index ac73ac6..799ff8c 100644 --- a/cdatgui/editors/model/isoline_model.py +++ b/cdatgui/editors/model/isoline_model.py @@ -5,7 +5,6 @@ class IsolineModel(LevelsBaseModel): def __init__(self, gm, var, canvas=None): - print "CREATING ISOLINE MODEL" self._gm = gm self._var = var self._canvas = canvas @@ -17,7 +16,6 @@ def line(self): self._gm.line.append(self._gm.line[-1]) while len(self._gm.line) > len(self._gm.levels): self._gm.line.remove(self._gm.line[-1]) - print "RETURNING:", self._gm.line return self._gm.line @property diff --git a/cdatgui/editors/model/vcsaxis.py b/cdatgui/editors/model/vcsaxis.py index 8acfc74..c5e3fd8 100644 --- a/cdatgui/editors/model/vcsaxis.py +++ b/cdatgui/editors/model/vcsaxis.py @@ -1,5 +1,6 @@ import vcs + class VCSAxis(object): def __init__(self, gm, tmpl, axis, var): self.gm = gm @@ -120,7 +121,8 @@ def step(self): ticks = vcs.elements["list"][ticks] ticks = sorted(ticks) left, right = vcs.minmax(self.axis) - return (right - left) / len(ticks) + print "STEP", right, left, len(ticks) + return (right - left) / (len(ticks) - 1) # pretty sure this need to be - @step.setter def step(self, value): @@ -142,6 +144,7 @@ def step(self, value): cur_val += value self.ticks = {i: i for i in tick_vals} + print "SET TICKS", self.ticks @property def show_miniticks(self): diff --git a/cdatgui/editors/secondary/editor/line.py b/cdatgui/editors/secondary/editor/line.py index 8d2f9e9..108553c 100644 --- a/cdatgui/editors/secondary/editor/line.py +++ b/cdatgui/editors/secondary/editor/line.py @@ -80,15 +80,12 @@ def updateWidth(self, width): def saveNewLine(self, name): name = str(name) - print "NAME", name - print "ORIG NAME", self.orig_name if name == "new": if self.orig_name in vcs.elements['line']: del vcs.elements['line'][self.orig_name] vcs.createline(self.orig_name, source=name) - # vcs.elements['line'][self.orig_name] = self.object get_lines().updated(self.orig_name) self.saved.emit(self.orig_name) else: diff --git a/cdatgui/editors/secondary/editor/text.py b/cdatgui/editors/secondary/editor/text.py index a15c54d..e6690d5 100755 --- a/cdatgui/editors/secondary/editor/text.py +++ b/cdatgui/editors/secondary/editor/text.py @@ -167,7 +167,12 @@ def saveNewText(self, name): name = str(name) if name != 'new:::new': + # for el in vcs.listelements('textorientation'): + # for el in vcs.listelements('textcombined'): + # print el + # print vcs.elements['textcombined'] # getting object + # import traceback;traceback.print_stack() to = vcs.elements['textorientation']['new'] tt = vcs.elements['texttable']['new'] diff --git a/cdatgui/editors/widgets/legend_widget.py b/cdatgui/editors/widgets/legend_widget.py index e1c2c25..79cdde5 100644 --- a/cdatgui/editors/widgets/legend_widget.py +++ b/cdatgui/editors/widgets/legend_widget.py @@ -9,6 +9,7 @@ from cdatgui.utils import pattern_thumbnail from cdatgui.bases.dynamic_grid_layout import DynamicGridLayout from functools import partial +import vcs class ForceResizeScrollArea(QtGui.QScrollArea): @@ -231,10 +232,10 @@ def __init__(self, custom=True, parent=None): self.end_color_button.clicked.connect(partial(self.createColormap, self.end_color_spin)) # Create extend check boxes - extend_left_check = QtGui.QCheckBox() - extend_left_check.stateChanged.connect(self.updateExtendLeft) - extend_right_check = QtGui.QCheckBox() - extend_right_check.stateChanged.connect(self.updateExtendRight) + self.extend_left_check = QtGui.QCheckBox() + self.extend_left_check.stateChanged.connect(self.updateExtendLeft) + self.extend_right_check = QtGui.QCheckBox() + self.extend_right_check.stateChanged.connect(self.updateExtendRight) # Create custom fill icon self.custom_fill_icon = QtGui.QToolButton() @@ -297,9 +298,9 @@ def __init__(self, custom=True, parent=None): self.end_color_widget = QtGui.QWidget() self.end_color_widget.setLayout(end_color_layout) - extend_layout.addWidget(extend_left_check) + extend_layout.addWidget(self.extend_left_check) extend_layout.addWidget(extend_left_label) - extend_layout.addWidget(extend_right_check) + extend_layout.addWidget(self.extend_right_check) extend_layout.addWidget(extend_right_label) extend_layout.insertStretch(2, 1) @@ -338,6 +339,21 @@ def setObject(self, legend): self.end_color_widget.setEnabled(False) self.end_color_widget.hide() + self.extend_left_check.setChecked(self.object.ext_left) + self.extend_right_check.setChecked(self.object.ext_right) + print "IS BOXFILL?", vcs.isboxfill(self.object) + if vcs.isboxfill(self.object._gm): + if self.object._gm.boxfill_type == 'custom' and self.custom_fill_icon.arrowType() == QtCore.Qt.RightArrow: + self.updateArrowType() + else: + print "NOPE" + try: + if self.object.fill_style != 'solid' and self.custom_fill_icon.arrowType() == QtCore.Qt.RightArrow: + print "UPDATING" + self.updateArrowType() + except AttributeError as e: + print "ERROR", e + self.preview.setLegendObject(legend) self.preview.update() @@ -407,7 +423,7 @@ def updateArrowType(self): self.fill_style_widget.setVisible(True) self.vertical_layout.insertLayout(6, self.custom_vertical_layout) self.custom_vertical_layout.addWidget(self.createCustomFillBox()) - self.initateFillStyle(self.fill_button_group.button(-2)) + self.initateFillStyle() else: self.object.fill_style = "Solid" self.fill_style_widget.setVisible(False) @@ -416,10 +432,10 @@ def updateArrowType(self): self.preview.update() - def initateFillStyle(self, old_button): + def initateFillStyle(self): """Used when creating custom fill to initalize fill style to Solid""" for button in self.fill_button_group.buttons(): - if button.text() == old_button.text(): + if button.text() == self.object.fill_style.capitalize(): button.click() def updateCustomFillBox(self): @@ -427,7 +443,8 @@ def updateCustomFillBox(self): self.deleteCustomFillBox() self.custom_vertical_layout.addWidget(self.createCustomFillBox()) self.vertical_layout.insertLayout(6, self.custom_vertical_layout) - self.initateFillStyle(self.fill_button_group.checkedButton()) + # self.initateFillStyle(self.fill_button_group.checkedButton()) + self.initateFillStyle() def createCustomFillBox(self): # create layout for custom fill @@ -558,6 +575,7 @@ def disableCustom(self): self.custom_fill_icon.hide() self.custom_fill_label.hide() + if __name__ == "__main__": import cdms2, vcs diff --git a/cdatgui/editors/widgets/multi_line_editor.py b/cdatgui/editors/widgets/multi_line_editor.py index 36a4092..cfa3401 100644 --- a/cdatgui/editors/widgets/multi_line_editor.py +++ b/cdatgui/editors/widgets/multi_line_editor.py @@ -50,7 +50,6 @@ def __init__(self): self.resize(300, self.height()) def setObject(self, object, *args): - print "SETTING OBJECT" self.isoline_model = object widgets = [] @@ -65,7 +64,7 @@ def setObject(self, object, *args): # repopulate for ind, lev in enumerate(self.isoline_model.levels): row = QtGui.QHBoxLayout() - line_label = QtGui.QLabel("Line:") + line_label = QtGui.QLabel(str(lev)) line_combo = QtGui.QComboBox() line_combo.setModel(get_lines()) diff --git a/cdatgui/editors/widgets/multi_text_editor.py b/cdatgui/editors/widgets/multi_text_editor.py index e9aa9bd..4f58ac2 100644 --- a/cdatgui/editors/widgets/multi_text_editor.py +++ b/cdatgui/editors/widgets/multi_text_editor.py @@ -49,7 +49,6 @@ def __init__(self): self.resize(300, self.height()) def setObject(self, object): - print "SETTING OBJECT" self.isoline_model = object widgets = [] @@ -64,7 +63,7 @@ def setObject(self, object): # repopulate for ind, lev in enumerate(self.isoline_model.levels): row = QtGui.QHBoxLayout() - text_label = QtGui.QLabel("Text:") + text_label = QtGui.QLabel(str(lev)) text_combo = QtGui.QComboBox() text_combo.setModel(get_textstyles()) diff --git a/cdatgui/graphics/dialog.py b/cdatgui/graphics/dialog.py index 6583df1..768d2a5 100644 --- a/cdatgui/graphics/dialog.py +++ b/cdatgui/graphics/dialog.py @@ -14,6 +14,7 @@ class GraphcisMethodDialog(QtGui.QDialog): def __init__(self, gm, var, tmpl, parent=None): super(GraphcisMethodDialog, self).__init__(parent=parent) + self.setWindowModality(QtCore.Qt.ApplicationModal) layout = QtGui.QVBoxLayout() @@ -38,7 +39,7 @@ def __init__(self, gm, var, tmpl, parent=None): self.create = vcs.createvector else: raise NotImplementedError("No editor exists for type %s" % self.gmtype) - + print "Var", var self.editor.var = var self.editor.tmpl = tmpl layout.addWidget(self.editor) diff --git a/cdatgui/variables/cdms_file_chooser.py b/cdatgui/variables/cdms_file_chooser.py index 3322faf..5c1e8ee 100644 --- a/cdatgui/variables/cdms_file_chooser.py +++ b/cdatgui/variables/cdms_file_chooser.py @@ -7,7 +7,7 @@ class CDMSFileChooser(QtGui.QDialog): def __init__(self, parent=None, f=0): super(CDMSFileChooser, self).__init__(parent=parent, f=f) - + self.setWindowModality(QtCore.Qt.ApplicationModal) self.tabs = VerticalTabWidget() layout = QtGui.QVBoxLayout() diff --git a/cdatgui/variables/variable_add.py b/cdatgui/variables/variable_add.py index a8620e5..ca613ce 100644 --- a/cdatgui/variables/variable_add.py +++ b/cdatgui/variables/variable_add.py @@ -40,6 +40,7 @@ def validate(self, name, pos): class AddDialog(QtGui.QDialog): def __init__(self, parent=None, f=0): super(AddDialog, self).__init__(parent=parent, f=f) + self.setWindowModality(QtCore.Qt.ApplicationModal) self.renameVar = [] self.dialog = None self.reserved_words = ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global', 'or', 'with', @@ -114,7 +115,7 @@ def remove_file(self): def rename_file(self): var = self.tree.get_selected() - if len(var) > 1: + if len(var) > 1 or len(var) < 1: QtGui.QMessageBox.warning(self, "Error", "Please select one variable to import as") return var = var[0] @@ -133,6 +134,7 @@ def setRenameVar(self, var): self.renameVar[-1].id = self.dialog.textValue() self.accepted.emit() self.dialog.close() + self.tree.clearSelection() def isValidName(self, name): if name in self.reserved_words or not re.search("^[a-zA-Z_]", name) or name == '' \ diff --git a/cdatgui/vcsmodel/elements.py b/cdatgui/vcsmodel/elements.py index 5c92000..b85bbe4 100644 --- a/cdatgui/vcsmodel/elements.py +++ b/cdatgui/vcsmodel/elements.py @@ -34,12 +34,10 @@ def tooltip(self, name, obj): def updated(self, el_name): try: - print "Updating element", el_name ind = self.elements.index(el_name) model_ind = self.index(ind) self.dataChanged.emit(model_ind, model_ind) except ValueError: - print "Inserting Element", el_name new_els = [] insert_ind = -1 insert_me = el_name @@ -54,6 +52,5 @@ def updated(self, el_name): new_els.append(el_name) insert_ind = len(self.elements) self.beginInsertRows(QtCore.QModelIndex(), insert_ind, insert_ind) - print "NEW ELEMENTS:", new_els self.elements = new_els self.endInsertRows() diff --git a/tests/test_GmDialog.py b/tests/test_GmDialog.py new file mode 100644 index 0000000..33575e5 --- /dev/null +++ b/tests/test_GmDialog.py @@ -0,0 +1,93 @@ +import pytest, vcs, cdms2, os +from cdatgui.graphics.dialog import GraphcisMethodDialog +from cdatgui.cdat.metadata import FileMetadataWrapper +from PySide import QtCore, QtGui + + +@pytest.fixture +def boxfill_dialog(): + s = get_var() + d = GraphcisMethodDialog(vcs.getboxfill('default'), s, vcs.createtemplate()) + d.createdGM.connect(saveAs) + return d + + +@pytest.fixture +def isoline_dialog(): + s = get_var() + d = GraphcisMethodDialog(vcs.getisoline('default'), s, vcs.createtemplate()) + d.createdGM.connect(saveAs) + return d + + +def get_var(): + f = cdms2.open(os.path.join(vcs.sample_data, 'clt.nc')) + f = FileMetadataWrapper(f) + s = f('clt') + return s + + +def saveAs(gm): + assert gm.name == 'test' + + +def test_boxfillDialog(qtbot, boxfill_dialog): + """Test boxfill gm editor as well as basic dialog functionality and GraphicsMethodEditor functionality""" + editor = boxfill_dialog.editor + assert editor.levels_button.isEnabled() == False + + for button in editor.type_group.buttons(): + if button.text() == 'Custom': + button.click() + break + + assert editor.levels_button.isEnabled() == True + assert editor.gm.boxfill_type == 'custom' + + editor.levels_button.click() + assert editor.level_editor + editor.level_editor.close() + + for button in editor.type_group.buttons(): + if button.text() == 'Logarithmic': + button.click() + break + + assert editor.levels_button.isEnabled() == False + save_button = boxfill_dialog.layout().itemAt(1).layout().itemAt(3).widget() + assert save_button.isEnabled() == False + boxfill_dialog.save(('test', True)) + + # test ticks dialogs + editor.editLeft() + assert editor.axis_editor + assert editor.axis_editor.axis == 'y' + + editor.editRight() + assert editor.axis_editor.axis == 'y' + + editor.editBottom() + assert editor.axis_editor.axis == 'x' + + editor.editTop() + assert editor.axis_editor.axis == 'x' + + +def test_isolineDialog(qtbot, isoline_dialog): + editor = isoline_dialog.editor + + assert not editor.text_edit_widget + assert not editor.line_edit_widget + + assert editor.label_check.isChecked() == False + assert editor.edit_label_button.isEnabled() == False + + editor.updateLabel(QtCore.Qt.Checked) + + assert editor.edit_label_button.isEnabled() == True + + editor.editText() + assert editor.text_edit_widget + + editor.editLines() + assert editor.line_edit_widget diff --git a/tests/test_TextStyleEditor.py b/tests/test_TextStyleEditor.py index 9e8a3f8..75fe1d9 100755 --- a/tests/test_TextStyleEditor.py +++ b/tests/test_TextStyleEditor.py @@ -1,26 +1,33 @@ import pytest +import re import vcs from PySide import QtCore, QtGui from cdatgui.editors.secondary.editor.text import TextStyleEditorWidget +from cdatgui.vcsmodel import get_textstyles @pytest.fixture def editors(): + for name in ['header', 'header2', 'header3']: + try: + del vcs.elements['textcombined']['{0}:::{1}'.format(name, name)] + del vcs.elements['texttable'][name] + del vcs.elements['textorientation'][name] + except: + print "didnt delete all" + edit1 = TextStyleEditorWidget() - t = vcs.createtext() - t.name = "header" + t = vcs.createtext('header') edit1.setTextObject(t) edit2 = TextStyleEditorWidget() - t = vcs.createtext() - t.name = "header" + t = vcs.createtext('header2') t.valign = 0 t.halign = 1 edit2.setTextObject(t) edit3 = TextStyleEditorWidget() - t = vcs.createtext() - t.name = "header" + t = vcs.createtext('header3') t.valign = 4 t.halign = 2 edit3.setTextObject(t) @@ -29,13 +36,14 @@ def editors(): def save_check(name): - assert name == "header" + # assert name in vcs.listelements('textcombined') + assert re.match("header[0-9]*", name) def test_save(qtbot, editors): for editor in editors: - editor.savePressed.connect(save_check) + editor.saved.connect(save_check) editor.save() @@ -43,52 +51,52 @@ def test_alignment(editors): for editor in editors: # test valign editor.updateButton(editor.va_group.buttons()[0]) - assert editor.textObject.valign == 0 + assert editor.object.valign == 0 editor.updateButton(editor.va_group.buttons()[2]) - assert editor.textObject.valign == 4 + assert editor.object.valign == 4 editor.updateButton(editor.va_group.buttons()[1]) - assert editor.textObject.valign == 2 + assert editor.object.valign == 2 # test halign editor.updateButton(editor.ha_group.buttons()[2]) - assert editor.textObject.halign == 2 + assert editor.object.halign == 2 editor.updateButton(editor.ha_group.buttons()[1]) - assert editor.textObject.halign == 1 + assert editor.object.halign == 1 editor.updateButton(editor.ha_group.buttons()[0]) - assert editor.textObject.halign == 0 + assert editor.object.halign == 0 def test_angle(editors): for editor in editors: - assert editor.textObject.angle == 0 + assert editor.object.angle == 0 editor.updateAngle(50) - assert editor.textObject.angle == 50 + assert editor.object.angle == 50 editor.updateAngle(440) - assert editor.textObject.angle == 80 + assert editor.object.angle == 80 def test_font(editors): for editor in editors: editor.updateFont("Helvetica") - assert editor.textObject.font == 4 + assert editor.object.font == 4 editor.updateFont("Chinese") - assert editor.textObject.font == 8 + assert editor.object.font == 8 def test_size(editors): for editor in editors: - assert editor.textObject.height == 14 + assert editor.object.height == 14 editor.updateSize(50) - assert editor.textObject.height == 50 + assert editor.object.height == 50 def saveas_check(name): @@ -98,7 +106,7 @@ def saveas_check(name): def test_saveas(qtbot, editors): for editor in editors: - editor.savePressed.connect(saveas_check) + editor.saved.connect(saveas_check) editor.saveAs() try: @@ -109,3 +117,7 @@ def test_saveas(qtbot, editors): editor.win.setTextValue("test.txt") qtbot.keyPress(editor.win, QtCore.Qt.Key_Enter) + assert "test.txt" in vcs.listelements('texttable') + assert "test.txt" in vcs.listelements('textorientation') + assert "test.txt" in get_textstyles().elements + assert False From 74b5f35594d7a57dd46bb6066bdf21653903e5b5 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Thu, 28 Apr 2016 14:12:11 -0700 Subject: [PATCH 13/29] Initial commit for tests for multi editors for isoline gm --- cdatgui/editors/cdat1d.py | 17 +-- cdatgui/editors/widgets/multi_line_editor.py | 5 +- cdatgui/graphics/dialog.py | 1 - tests/test_GmDialog.py | 39 ++++++- tests/test_MultiLineEditor.py | 113 +++++++++++++++++++ 5 files changed, 162 insertions(+), 13 deletions(-) create mode 100644 tests/test_MultiLineEditor.py diff --git a/cdatgui/editors/cdat1d.py b/cdatgui/editors/cdat1d.py index a64e34f..08ac36c 100644 --- a/cdatgui/editors/cdat1d.py +++ b/cdatgui/editors/cdat1d.py @@ -36,19 +36,22 @@ def __init__(self, parent=None): self.line_editor = None def editMarker(self): - if not self.marker_editor: - self.marker_editor = MarkerEditorWidget() - self.marker_editor.savePressed.connect(self.updateMarker) - + if self.marker_editor: + self.marker_editor.close() + self.marker_editor.deleteLater() + self.marker_editor = MarkerEditorWidget() + self.marker_editor.savePressed.connect(self.updateMarker) mark_obj = vcs.createmarker(mtype=self.gm.marker, color=self.gm.markercolor, size=self.gm.markersize) self.marker_editor.setMarkerObject(mark_obj) self.marker_editor.raise_() self.marker_editor.show() def editLine(self): - if not self.line_editor: - self.line_editor = LineEditorWidget() - self.line_editor.savePressed.connect(self.updateLine) + if self.line_editor: + self.line_editor.close() + self.line_editor.deleteLater() + self.line_editor = LineEditorWidget() + self.line_editor.savePressed.connect(self.updateLine) if self.gm.linewidth < 1: self.gm.linewidth = 1 line_obj = vcs.createline(ltype=self.gm.line, color=self.gm.linecolor, width=self.gm.linewidth) diff --git a/cdatgui/editors/widgets/multi_line_editor.py b/cdatgui/editors/widgets/multi_line_editor.py index cfa3401..1aa3546 100644 --- a/cdatgui/editors/widgets/multi_line_editor.py +++ b/cdatgui/editors/widgets/multi_line_editor.py @@ -11,7 +11,6 @@ class LineNameDialog(ValidatingInputDialog): def save(self): - print "SAVING" if self.textValue() in vcs.elements['line']: check = QtGui.QMessageBox.question(self, "Overwrite line?", "Line {0} already exists. Overwrite?".format(self.textValue()), @@ -109,11 +108,11 @@ def editLine(self, index): self.line_editor.raise_() def changeLine(self, row_index, combo_index): - print "ChangeLine, row_i, combo_i", row_index, combo_index + """Changed line to an already existing line in the line model""" self.isoline_model.line[row_index] = get_lines().elements[combo_index] def update(self, index, name): - print "UPDATING:", index, name + """Updated line from line editor""" self.isoline_model.line[index] = str(name) self.line_combos[index].setCurrentIndex(self.line_combos[index].findText(name)) diff --git a/cdatgui/graphics/dialog.py b/cdatgui/graphics/dialog.py index 768d2a5..aa2a214 100644 --- a/cdatgui/graphics/dialog.py +++ b/cdatgui/graphics/dialog.py @@ -39,7 +39,6 @@ def __init__(self, gm, var, tmpl, parent=None): self.create = vcs.createvector else: raise NotImplementedError("No editor exists for type %s" % self.gmtype) - print "Var", var self.editor.var = var self.editor.tmpl = tmpl layout.addWidget(self.editor) diff --git a/tests/test_GmDialog.py b/tests/test_GmDialog.py index 33575e5..3df39b1 100644 --- a/tests/test_GmDialog.py +++ b/tests/test_GmDialog.py @@ -1,6 +1,7 @@ import pytest, vcs, cdms2, os from cdatgui.graphics.dialog import GraphcisMethodDialog from cdatgui.cdat.metadata import FileMetadataWrapper +from cdatgui.editors import boxfill, isoline, cdat1d from PySide import QtCore, QtGui @@ -16,7 +17,13 @@ def boxfill_dialog(): def isoline_dialog(): s = get_var() d = GraphcisMethodDialog(vcs.getisoline('default'), s, vcs.createtemplate()) - d.createdGM.connect(saveAs) + return d + + +@pytest.fixture +def oned_dialog(): + s = get_var() + d = GraphcisMethodDialog(vcs.get1d('default'), s, vcs.createtemplate()) return d @@ -34,6 +41,7 @@ def saveAs(gm): def test_boxfillDialog(qtbot, boxfill_dialog): """Test boxfill gm editor as well as basic dialog functionality and GraphicsMethodEditor functionality""" editor = boxfill_dialog.editor + assert isinstance(editor, boxfill.BoxfillEditor) assert editor.levels_button.isEnabled() == False for button in editor.type_group.buttons(): @@ -45,6 +53,7 @@ def test_boxfillDialog(qtbot, boxfill_dialog): assert editor.gm.boxfill_type == 'custom' editor.levels_button.click() + qtbot.addWidget(editor.level_editor) assert editor.level_editor editor.level_editor.close() @@ -70,11 +79,13 @@ def test_boxfillDialog(qtbot, boxfill_dialog): assert editor.axis_editor.axis == 'x' editor.editTop() + qtbot.addWidget(editor.axis_editor) assert editor.axis_editor.axis == 'x' def test_isolineDialog(qtbot, isoline_dialog): editor = isoline_dialog.editor + assert isinstance(editor, isoline.IsolineEditor) assert not editor.text_edit_widget assert not editor.line_edit_widget @@ -83,11 +94,35 @@ def test_isolineDialog(qtbot, isoline_dialog): assert editor.edit_label_button.isEnabled() == False editor.updateLabel(QtCore.Qt.Checked) - + assert editor.gm.label == True assert editor.edit_label_button.isEnabled() == True editor.editText() + qtbot.addWidget(editor.text_edit_widget) assert editor.text_edit_widget editor.editLines() + qtbot.addWidget(editor.line_edit_widget) assert editor.line_edit_widget + + editor.updateLabel(QtCore.Qt.Unchecked) + assert editor.gm.label == False + assert editor.edit_label_button.isEnabled() == False + + +def test_1dDialog(qtbot, oned_dialog): + # really only testing this because it has a marker button. + editor = oned_dialog.editor + assert isinstance(editor, cdat1d.Cdat1dEditor) + + editor.flipGraph(QtCore.Qt.Checked) + assert editor.gm.flip == True + + editor.editMarker() + qtbot.addWidget(editor.marker_editor) + assert editor.marker_editor + + editor.editLine() + qtbot.addWidget(editor.line_editor) + assert editor.line_editor + diff --git a/tests/test_MultiLineEditor.py b/tests/test_MultiLineEditor.py new file mode 100644 index 0000000..1d8c253 --- /dev/null +++ b/tests/test_MultiLineEditor.py @@ -0,0 +1,113 @@ +import pytest, vcs, cdms2, os +from cdatgui.editors.widgets.multi_line_editor import MultiLineEditor +from cdatgui.editors.widgets.multi_text_editor import MultiTextEditor +from cdatgui.cdat.metadata import FileMetadataWrapper +from cdatgui.editors.model.isoline_model import IsolineModel +from cdatgui.vcsmodel import get_lines, get_textstyles + + +@pytest.fixture +def line_editor(): + """ + Multi Editors are only being tested with set levels due to odd behavior with autolabels + that is waiting for merge + """ + editor = MultiLineEditor() + gm = vcs.getisoline('a_isoline') + gm.levels = range(10, 80, 10) + editor.setObject(IsolineModel(gm, get_var())) + return editor, gm + + +@pytest.fixture +def text_editor(): + """ + Multi Editors are only being tested with set levels due to odd behavior with autolabels + that is waiting for merge + """ + editor = MultiTextEditor() + gm = vcs.getisoline('a_isoline') + gm.levels = range(10, 80, 10) + editor.setObject(IsolineModel(gm, get_var())) + return editor, gm + + +def get_var(): + f = cdms2.open(os.path.join(vcs.sample_data, 'clt.nc')) + f = FileMetadataWrapper(f) + s = f('clt') + return s + + +def test_MultiLineEditor(qtbot, line_editor): + editor = line_editor[0] + gm = line_editor[1] + for combo in editor.line_combos: + assert combo.currentIndex() != -1 + + editor.line_combos[2].setCurrentIndex(10) + assert editor.isoline_model.line[2] == 'pink' + + editor.editLine(6) + qtbot.addWidget(editor.line_editor) + assert editor.line_editor + assert isinstance(editor.line_editor.object, vcs.line.Tl) + + # simulate editing a line and updating it + l = vcs.createline('dummy') + l.color = [55] + l.type = ['dash-dot'] + l.width = [8] + get_lines().updated('dummy') + + editor.update(4, 'dummy') + assert editor.line_combos[4].currentText() == 'dummy' + + editor.okClicked() + + # check and see if the isoline was updated when combo changed and ok was pressed + assert gm.linecolors[2] == 254 + assert gm.linewidths[2] == 2 + assert vcs.getline(gm.line[2]).name == 'pink' + assert vcs.getline(gm.line[2]).type == ['dash'] + + assert gm.linecolors[4] == 55 + assert gm.linewidths[4] == 8 + assert vcs.getline(gm.line[4]).name == 'dummy' + assert vcs.getline(gm.line[4]).type == ['dash-dot'] + + +def test_MultiTextEditor(qtbot, text_editor): + editor = text_editor[0] + gm = text_editor[1] + for combo in editor.text_combos: + assert combo.currentIndex() != -1 + + editor.text_combos[2].setCurrentIndex(3) + assert editor.isoline_model.text[2] == 'qa' + + editor.editText(1) + qtbot.addWidget(editor.text_editor) + assert editor.text_editor + assert isinstance(editor.text_editor.object, vcs.textcombined.Tc) + + # simulate editing a line and updating it + tc = vcs.createtextcombined('dummy') + tc.angle = 30 + tc.font = 'Chinese' + tc.halign = 1 + tc.valign = 1 + tc.height = 24 + get_textstyles().updated('dummy') + + editor.update(3, 'dummy') + assert editor.text_combos[3].currentText() == 'dummy' + + editor.okClicked() + + # check and see if the isoline was updated when combo changed and ok was pressed + assert vcs.gettextcombined(gm.text[3], gm.text[3]).name == 'dummy:::dummy' + assert vcs.gettextcombined(gm.text[3], gm.text[3]).font == 8 # 'Chinese' + assert vcs.gettextcombined(gm.text[3], gm.text[3]).halign == 1 + assert vcs.gettextcombined(gm.text[3], gm.text[3]).valign == 1 + assert vcs.gettextcombined(gm.text[3], gm.text[3]).height == 24 From 5158ec8b75458258856e813267fc62d936cc5420 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Fri, 29 Apr 2016 14:51:22 -0700 Subject: [PATCH 14/29] added projection editor --- cdatgui/bases/window_widget.py | 7 +- cdatgui/editors/boxfill.py | 22 +-- cdatgui/editors/graphics_method_editor.py | 19 ++- cdatgui/editors/model/legend.py | 16 +- cdatgui/editors/projection_editor.py | 193 ++++++++++++++++++++++ cdatgui/editors/widgets/legend_widget.py | 27 ++- cdatgui/graphics/dialog.py | 6 +- cdatgui/sidebar/inspector_widget.py | 3 +- cdatgui/variables/variable_widget.py | 1 - 9 files changed, 255 insertions(+), 39 deletions(-) create mode 100644 cdatgui/editors/projection_editor.py diff --git a/cdatgui/bases/window_widget.py b/cdatgui/bases/window_widget.py index 52f5d37..2daeda2 100644 --- a/cdatgui/bases/window_widget.py +++ b/cdatgui/bases/window_widget.py @@ -10,7 +10,10 @@ def __init__(self): self.object = None self.preview = None self.dialog = QtGui.QInputDialog() + self.dialog.setModal(QtCore.Qt.ApplicationModal) self.setWindowModality(QtCore.Qt.ApplicationModal) + shortcut = QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Escape), self) + shortcut.activated.connect(self.close) # Layout to add new elements self.vertical_layout = QtGui.QVBoxLayout() @@ -18,7 +21,7 @@ def __init__(self): # Save and Cancel Buttons cancel_button = QtGui.QPushButton() cancel_button.setText("Cancel") - cancel_button.clicked.connect(lambda: self.close()) + cancel_button.clicked.connect(self.close) saveas_button = QtGui.QPushButton() saveas_button.setText("Save As") @@ -82,6 +85,8 @@ def __init__(self): self.object = None self.preview = None self.setWindowModality(QtCore.Qt.ApplicationModal) + shortcut = QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Escape), self) + shortcut.activated.connect(self.close) # Layout to add new elements self.vertical_layout = QtGui.QVBoxLayout() diff --git a/cdatgui/editors/boxfill.py b/cdatgui/editors/boxfill.py index 0ae5cda..d2b1dfc 100644 --- a/cdatgui/editors/boxfill.py +++ b/cdatgui/editors/boxfill.py @@ -12,6 +12,8 @@ class BoxfillEditor(GraphicsMethodEditorWidget): def __init__(self, parent=None): """Initialize the object.""" super(BoxfillEditor, self).__init__(parent=parent) + + self.orig_type = None self.boxfill_types = OrderedDict( Linear="linear", Logarithmic="log10", @@ -43,7 +45,7 @@ def gm(self, value): type_real_vals = self.boxfill_types.values() index = type_real_vals.index(value.boxfill_type) button = self.type_group.buttons()[index] - button.setChecked(True) + button.click() self.setBoxfillType(button) def setBoxfillType(self, radio): @@ -53,20 +55,8 @@ def setBoxfillType(self, radio): else: self.levels_button.setEnabled(False) box_type = self.boxfill_types[radio.text()] + + if not self.orig_type: + self.orig_type = box_type self._gm.boxfill_type = box_type - def editLegend(self): - if self.legend_editor is None: - if self.type_group.checkedButton().text() == 'Custom': - self.legend_editor = LegendEditorWidget() - else: - self.legend_editor = LegendEditorWidget(False) - self.legend_editor.okPressed.connect(self.updated) - elif self.type_group.checkedButton().text() == 'Custom': - self.legend_editor.enableCustom() - else: - self.legend_editor.disableCustom() - legend = VCSLegend(self.gm, self.var.var) - self.legend_editor.setObject(legend) - self.legend_editor.show() - self.legend_editor.raise_() diff --git a/cdatgui/editors/graphics_method_editor.py b/cdatgui/editors/graphics_method_editor.py index a13c12c..da6655f 100644 --- a/cdatgui/editors/graphics_method_editor.py +++ b/cdatgui/editors/graphics_method_editor.py @@ -3,6 +3,7 @@ from cdatgui.editors.model.legend import VCSLegend from cdatgui.editors.widgets.legend_widget import LegendEditorWidget +from cdatgui.editors.projection_editor import ProjectionEditor from level_editor import LevelEditor from axis_editor import AxisEditorWidget from model.vcsaxis import VCSAxis @@ -38,6 +39,8 @@ def __init__(self, parent=None): bottom_axis.clicked.connect(self.editBottom) top_axis = QtGui.QPushButton("Edit Top Ticks") top_axis.clicked.connect(self.editTop) + projection = QtGui.QPushButton('Edit Projection') + projection.clicked.connect(self.editProjection) self.button_layout.addWidget(self.levels_button) self.button_layout.addWidget(legend_button) @@ -45,10 +48,12 @@ def __init__(self, parent=None): self.button_layout.addWidget(right_axis) self.button_layout.addWidget(top_axis) self.button_layout.addWidget(bottom_axis) + self.button_layout.addWidget(projection) self.level_editor = None self.legend_editor = None self.axis_editor = None + self.projection_editor = None def editAxis(self, axis): if self.axis_editor: @@ -56,7 +61,7 @@ def editAxis(self, axis): self.axis_editor.deleteLater() self.axis_editor = AxisEditorWidget(axis[0]) self.axis_editor.okPressed.connect(self.updated) - axis = VCSAxis(self._gm, self.tmpl, axis, self.var) + axis = VCSAxis(self.gm, self.tmpl, axis, self.var) self.axis_editor.setAxisObject(axis) self.axis_editor.show() self.axis_editor.raise_() @@ -85,6 +90,7 @@ def editLevels(self): def updated(self): if self.legend_editor is not None: + print self.legend_editor.object._gm.list() self.legend_editor = None if self.axis_editor is not None: self.axis_editor = None @@ -110,3 +116,14 @@ def editLegend(self): self.legend_editor.setObject(legend) self.legend_editor.show() self.legend_editor.raise_() + + def editProjection(self): + if self.projection_editor: + self.projection_editor.close() + self.projection_editor.deleteLater() + self.projection_editor = ProjectionEditor() + self.projection_editor.setProjectionObject(vcs.getprojection(self.gm.projection)) + self.projection_editor.gm = self.gm + self.projection_editor.show() + self.projection_editor.raise_() + diff --git a/cdatgui/editors/model/legend.py b/cdatgui/editors/model/legend.py index 27497bd..3f7d6ef 100644 --- a/cdatgui/editors/model/legend.py +++ b/cdatgui/editors/model/legend.py @@ -67,11 +67,25 @@ def set_color(self, index, color): @property def fill_style(self): """Use for custom fill's radio buttons.""" - return self._gm.fillareastyle + if hasattr(self._gm, 'fillareastyle'): + return self._gm.fillareastyle + return None @fill_style.setter def fill_style(self, style): self._gm.fillareastyle = style.lower() + self._gm.fillareacolors = self.vcs_colors + self.adjust_to_level_length(self._gm.fillareaindices) + # this should just be temporary until merge of missing level branch + self.adjust_to_level_length(self._gm.fillareaopacity) + self.adjust_to_level_length(self._gm.fillareacolors) + + def adjust_to_level_length(self, lst): + # +1 for invisible level + while len(lst) < len(self.levels)+1: + lst.append(lst[-1]) + while len(lst) > len(self.levels)+1: + lst.pop() @property def color_1(self): diff --git a/cdatgui/editors/projection_editor.py b/cdatgui/editors/projection_editor.py new file mode 100644 index 0000000..b78659f --- /dev/null +++ b/cdatgui/editors/projection_editor.py @@ -0,0 +1,193 @@ +from PySide import QtCore, QtGui +import vcs, sys +from cdatgui.bases.window_widget import BaseSaveWindowWidget +from cStringIO import StringIO +from cdatgui.utils import label + + +class ProjectionEditor(BaseSaveWindowWidget): + def __init__(self): + super(ProjectionEditor, self).__init__() + self.orig_projection = None + self.cur_projection_name = None + self.gm = None + self.savePressed.connect(self.savingNewProjection) + self.editors = [] + + self.proj_combo = QtGui.QComboBox() + self.proj_combo.addItems(vcs.listelements('projection')) + self.proj_combo.currentIndexChanged[str].connect(self.updateCurrentProjection) + + types = ["linear", + "utm", + "state plane", + "albers equal area", "albers", + "lambert", + "lambert conformal c", + "lambert conformal conic", + "mercator", + "polar", + "polar stereographic", + "polyconic", + "equid conic a", + "equid conic", + "equid conic b", + "transverse mercator", + "stereographic", + "lambert azimuthal", + "azimuthal", + "gnomonic", + "orthographic", + "gen. vert. near per", + "gen vert near per", + "sinusoidal", + "equirectangular", + "miller", + "miller cylindrical", + "van der grinten", + "hotin", + "hotin oblique", + "hotin oblique merc", + "hotin oblique merc a", + "hotin oblique merc b", + "hotin oblique mercator", + "hotin oblique mercator a", + "hotin oblique mercator b", + "robinson", + "space oblique", + "space oblique merc", + "space oblique merc a", + "space oblique merc b", + "alaska", "alaska conformal", + "interrupted goode", "goode", + "mollweide", + "interrupted mollweide", + "interrupt mollweide", + "hammer", + "wagner iv", + "wagner 4", + "wagner4", + "wagner vii", + "wagner 7", + "wagner7", + "oblated", + "oblated equal area"] + self.type_combo = QtGui.QComboBox() + self.type_combo.addItems(types) + self.type_combo.currentIndexChanged[str].connect(self.updateProjectionType) + + name_label = label("Select Projection:") + type_label = label("Type:") + + name_row = QtGui.QHBoxLayout() + name_row.addWidget(name_label) + name_row.addWidget(self.proj_combo) + + type_row = QtGui.QHBoxLayout() + type_row.addWidget(type_label) + type_row.addWidget(self.type_combo) + + self.vertical_layout.insertLayout(0, name_row) + self.vertical_layout.insertLayout(1, type_row) + + def setProjectionObject(self, obj): + self.orig_projection = obj + self.cur_projection_name = obj.name + self.object = vcs.createprojection('new', obj) + # self.object = obj + self.updateAttributes() + + def updateAttributes(self): + obj = self.object + + for i in range(2, self.vertical_layout.count() - 1): + row = self.vertical_layout.takeAt(2).layout() + row.takeAt(0).widget().deleteLater() + row.takeAt(0).widget().deleteLater() + row.deleteLater() + self.editors = [] + + orig_out = sys.stdout + sys.stdout = myout = StringIO() + obj.list() + sys.stdout = orig_out + lst = myout.getvalue().split('\n') + print 'LIST', lst + for item in lst[2:-1]: + left, right = item.split('=') + left = left.strip() + right = right.strip() + + if left == 'name': + block = self.proj_combo.blockSignals(True) + self.proj_combo.setCurrentIndex(self.proj_combo.findText(self.cur_projection_name)) + self.proj_combo.blockSignals(block) + continue + if left == 'type': + block = self.type_combo.blockSignals(True) + self.type_combo.setCurrentIndex(self.type_combo.findText(right)) + self.type_combo.blockSignals(block) + continue + + edit_attr = QtGui.QLineEdit() + edit_attr.setText(right) + self.editors.append((edit_attr, left)) + + row = QtGui.QHBoxLayout() + row.addWidget(label(left.capitalize() + ":")) + row.addWidget(edit_attr) + + self.vertical_layout.insertLayout(self.vertical_layout.count() - 1, row) + + def updateCurrentProjection(self, proj): + proj = str(proj) + self.cur_projection_name = proj + self.object = vcs.getprojection(proj) + self.updateAttributes() + + def updateProjectionType(self, type): + type = str(type) + self.object.type = type + self.updateAttributes() + + def savingNewProjection(self, name): + if name == 'new': + + vcs.elements['projection'].pop(self.cur_projection_name) + vcs.createprojection(self.cur_projection_name, self.object) + # del vcs.elements['projection'][self.cur_projection_name] + name = self.cur_projection_name + else: + vcs.createprojection(name, vcs.elements['projection']['new']) + + new = vcs.elements['projection'].pop('new') + del new + + self.gm.projection = name + ''' + def updateGM(self, name): + if name not in vcs.elements['projection']: + projection = vcs.createprojection(name, vcs.elements['projection'][self.cur_projection_name]) + else: + projection = vcs.elements['projection'][self.cur_projection_name] + + for editor, attr in self.editors: + if isinstance(editor, QtGui.QComboBox): + text = editor.currentText() + else: + text = editor.text() + + try: + text = float(text) + except ValueError: + pass + + setattr(projection, attr, text) + self.gm.projection = projection.name + ''' + def close(self): + if 'new' in vcs.elements['projection']: + + new = vcs.elements['projection'].pop('new') + del new + super(ProjectionEditor, self).close() diff --git a/cdatgui/editors/widgets/legend_widget.py b/cdatgui/editors/widgets/legend_widget.py index 79cdde5..cf31e12 100644 --- a/cdatgui/editors/widgets/legend_widget.py +++ b/cdatgui/editors/widgets/legend_widget.py @@ -176,7 +176,7 @@ def validate(self, input, pos): class LegendEditorWidget(BaseOkWindowWidget): - def __init__(self, custom=True, parent=None): + def __init__(self, parent=None): super(LegendEditorWidget, self).__init__() # Variables @@ -241,8 +241,6 @@ def __init__(self, custom=True, parent=None): self.custom_fill_icon = QtGui.QToolButton() self.custom_fill_icon.setArrowType(QtCore.Qt.RightArrow) self.custom_fill_icon.clicked.connect(self.updateArrowType) - if not custom: - self.disableCustom() # Create custom fill section self.custom_vertical_layout = QtGui.QVBoxLayout() @@ -341,18 +339,17 @@ def setObject(self, legend): self.extend_left_check.setChecked(self.object.ext_left) self.extend_right_check.setChecked(self.object.ext_right) - print "IS BOXFILL?", vcs.isboxfill(self.object) + if vcs.isboxfill(self.object._gm): - if self.object._gm.boxfill_type == 'custom' and self.custom_fill_icon.arrowType() == QtCore.Qt.RightArrow: - self.updateArrowType() + if self.object._gm.boxfill_type == 'custom': + self.enableCustom(self.object._gm.fillareastyle != 'solid') + else: + self.disableCustom() + + elif self.object.fill_style: + self.enableCustom(self.object.fill_style != 'solid') else: - print "NOPE" - try: - if self.object.fill_style != 'solid' and self.custom_fill_icon.arrowType() == QtCore.Qt.RightArrow: - print "UPDATING" - self.updateArrowType() - except AttributeError as e: - print "ERROR", e + self.disableCustom() self.preview.setLegendObject(legend) self.preview.update() @@ -565,10 +562,12 @@ def handleEndColorInvalidInput(self): self.end_color_button.setStyleSheet( self.end_color_button.styleSheet() + "border: 1px solid red;") - def enableCustom(self): + def enableCustom(self, show=False): self.custom_fill_icon.setEnabled(True) self.custom_fill_icon.show() self.custom_fill_label.show() + if show and self.custom_fill_icon.arrowType() == QtCore.Qt.RightArrow: + self.updateArrowType() def disableCustom(self): self.custom_fill_icon.setEnabled(False) diff --git a/cdatgui/graphics/dialog.py b/cdatgui/graphics/dialog.py index aa2a214..08e483e 100644 --- a/cdatgui/graphics/dialog.py +++ b/cdatgui/graphics/dialog.py @@ -71,9 +71,6 @@ def __init__(self, gm, var, tmpl, parent=None): self.editor.gm = self.gm - def updateGM(self, gm): - self.gm = gm - def customName(self): name = QtGui.QInputDialog.getText(self, u"Save As", u"Name for {0}:".format(unicode(self.gmtype))) if name[1]: @@ -89,5 +86,8 @@ def save(self, name=None): def reject(self): super(GraphcisMethodDialog, self).reject() + if isinstance(self.editor, BoxfillEditor): + self.gm.boxfill_type = self.editor.orig_type + if 'new' in vcs.elements[vcs.graphicsmethodtype(self.gm)].keys(): del vcs.elements[vcs.graphicsmethodtype(self.gm)]['new'] diff --git a/cdatgui/sidebar/inspector_widget.py b/cdatgui/sidebar/inspector_widget.py index 8341aaf..9f7dcce 100644 --- a/cdatgui/sidebar/inspector_widget.py +++ b/cdatgui/sidebar/inspector_widget.py @@ -183,7 +183,7 @@ def editGM(self): gm = vcs.getgraphicsmethod(gm_type, gm_name) if self.gm_editor: - self.gm_editor.reject() + self.gm_editor.close() self.gm_editor.deleteLater() self.gm_editor = GraphcisMethodDialog(gm, self.var_combos[0].currentObj(), self.template_combo.currentObj()) self.gm_editor.createdGM.connect(self.makeGraphicsMethod) @@ -255,7 +255,6 @@ def setSecondVar(self, var): try: self.current_plot.variables = [self.current_plot.variables[0], var.var] except ValueError: - print "SETTING TO OLD VARS", old_vars self.current_plot.variables = old_vars self.plotters_updated.emit() diff --git a/cdatgui/variables/variable_widget.py b/cdatgui/variables/variable_widget.py index add3711..bf01686 100644 --- a/cdatgui/variables/variable_widget.py +++ b/cdatgui/variables/variable_widget.py @@ -34,7 +34,6 @@ def select_variable(self, index): def add_variable(self): new_variables = self.add_dialog.selected_variables() - print "ADDING VARIABLES", new_variables for var in new_variables: self.variable_widget.add_variable(var) From 0628eef3b2fc510d366837cd688adc1414298dd0 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Mon, 2 May 2016 10:55:37 -0700 Subject: [PATCH 15/29] tests for projection. Split custom vcs elements dialog into its own file --- cdatgui/bases/input_dialog.py | 3 + cdatgui/bases/vcs_elements_dialog.py | 35 ++++++++++ cdatgui/bases/window_widget.py | 1 - cdatgui/editors/projection_editor.py | 40 ++++------- cdatgui/editors/widgets/multi_line_editor.py | 34 +-------- cdatgui/editors/widgets/multi_text_editor.py | 34 +-------- tests/test_ProjectionEditor.py | 72 ++++++++++++++++++++ 7 files changed, 128 insertions(+), 91 deletions(-) create mode 100644 cdatgui/bases/vcs_elements_dialog.py create mode 100644 tests/test_ProjectionEditor.py diff --git a/cdatgui/bases/input_dialog.py b/cdatgui/bases/input_dialog.py index 2d4b20c..e03684c 100644 --- a/cdatgui/bases/input_dialog.py +++ b/cdatgui/bases/input_dialog.py @@ -64,3 +64,6 @@ def setValidator(self, validator): def textValue(self): return self.edit.text().strip() + + def setTextValue(self, text): + self.edit.setText(text) diff --git a/cdatgui/bases/vcs_elements_dialog.py b/cdatgui/bases/vcs_elements_dialog.py new file mode 100644 index 0000000..2db71ed --- /dev/null +++ b/cdatgui/bases/vcs_elements_dialog.py @@ -0,0 +1,35 @@ +from cdatgui.bases.input_dialog import ValidatingInputDialog +from PySide import QtCore, QtGui +import vcs + + +class VcsElementsDialog(ValidatingInputDialog): + def __init__(self, element): + super(VcsElementsDialog, self).__init__() + self.element = element + + def save(self): + if self.textValue() in vcs.elements[self.element]: + check = QtGui.QMessageBox.question(self, "Overwrite {0}?".format(self.element), + "{0} '{1}' already exists. Overwrite?".format(self.element.capitalize(), self.textValue()), + buttons=QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) + if check == QtGui.QDialogButtonBox.FirstButton: + self.close() + self.accepted.emit() + else: + self.close() + self.accepted.emit() + + +class VcsElementsValidator(QtGui.QValidator): + invalidInput = QtCore.Signal() + validInput = QtCore.Signal() + + def validate(self, inp, pos): + inp = inp.strip() + if not inp or inp == 'default': + self.invalidInput.emit() + return QtGui.QValidator.Intermediate + + self.validInput.emit() + return QtGui.QValidator.Acceptable diff --git a/cdatgui/bases/window_widget.py b/cdatgui/bases/window_widget.py index 2daeda2..3e93d21 100644 --- a/cdatgui/bases/window_widget.py +++ b/cdatgui/bases/window_widget.py @@ -44,7 +44,6 @@ def __init__(self): def setPreview(self, preview): if self.preview: self.vertical_layout.removeWidget(self.preview) - print "P: ", self.preview self.preview.deleteLater() self.preview = preview diff --git a/cdatgui/editors/projection_editor.py b/cdatgui/editors/projection_editor.py index b78659f..9d80e9c 100644 --- a/cdatgui/editors/projection_editor.py +++ b/cdatgui/editors/projection_editor.py @@ -3,11 +3,15 @@ from cdatgui.bases.window_widget import BaseSaveWindowWidget from cStringIO import StringIO from cdatgui.utils import label +from cdatgui.bases.vcs_elements_dialog import VcsElementsDialog, VcsElementsValidator class ProjectionEditor(BaseSaveWindowWidget): def __init__(self): super(ProjectionEditor, self).__init__() + dialog = VcsElementsDialog('projection') + dialog.setValidator(VcsElementsValidator()) + self.setSaveDialog(dialog) self.orig_projection = None self.cur_projection_name = None self.gm = None @@ -91,10 +95,11 @@ def __init__(self): self.vertical_layout.insertLayout(1, type_row) def setProjectionObject(self, obj): + if obj.name == 'default': + self.save_button.setEnabled(False) self.orig_projection = obj self.cur_projection_name = obj.name self.object = vcs.createprojection('new', obj) - # self.object = obj self.updateAttributes() def updateAttributes(self): @@ -142,20 +147,20 @@ def updateAttributes(self): def updateCurrentProjection(self, proj): proj = str(proj) self.cur_projection_name = proj - self.object = vcs.getprojection(proj) + if 'new' in vcs.listelements('projection'): + del vcs.elements['projection']['new'] + vcs.getprojection(proj).list() + self.object = vcs.createprojection('new', vcs.getprojection(proj)) self.updateAttributes() def updateProjectionType(self, type): - type = str(type) - self.object.type = type + self.object.type = str(type) self.updateAttributes() def savingNewProjection(self, name): if name == 'new': - vcs.elements['projection'].pop(self.cur_projection_name) vcs.createprojection(self.cur_projection_name, self.object) - # del vcs.elements['projection'][self.cur_projection_name] name = self.cur_projection_name else: vcs.createprojection(name, vcs.elements['projection']['new']) @@ -164,30 +169,9 @@ def savingNewProjection(self, name): del new self.gm.projection = name - ''' - def updateGM(self, name): - if name not in vcs.elements['projection']: - projection = vcs.createprojection(name, vcs.elements['projection'][self.cur_projection_name]) - else: - projection = vcs.elements['projection'][self.cur_projection_name] - - for editor, attr in self.editors: - if isinstance(editor, QtGui.QComboBox): - text = editor.currentText() - else: - text = editor.text() - - try: - text = float(text) - except ValueError: - pass - - setattr(projection, attr, text) - self.gm.projection = projection.name - ''' + def close(self): if 'new' in vcs.elements['projection']: - new = vcs.elements['projection'].pop('new') del new super(ProjectionEditor, self).close() diff --git a/cdatgui/editors/widgets/multi_line_editor.py b/cdatgui/editors/widgets/multi_line_editor.py index 1aa3546..e2ec2f0 100644 --- a/cdatgui/editors/widgets/multi_line_editor.py +++ b/cdatgui/editors/widgets/multi_line_editor.py @@ -6,35 +6,7 @@ from cdatgui.bases.dynamic_grid_layout import DynamicGridLayout import vcs from cdatgui.vcsmodel import get_lines -from cdatgui.bases.input_dialog import ValidatingInputDialog - - -class LineNameDialog(ValidatingInputDialog): - def save(self): - if self.textValue() in vcs.elements['line']: - check = QtGui.QMessageBox.question(self, "Overwrite line?", - "Line {0} already exists. Overwrite?".format(self.textValue()), - buttons=QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) - if check == QtGui.QDialogButtonBox.FirstButton: - self.close() - self.accepted.emit() - else: - self.close() - self.accepted.emit() - - -class LineTextValidator(QtGui.QValidator): - invalidInput = QtCore.Signal() - validInput = QtCore.Signal() - - def validate(self, inp, pos): - inp = inp.strip() - if not inp or inp == 'default': - self.invalidInput.emit() - return QtGui.QValidator.Intermediate - - self.validInput.emit() - return QtGui.QValidator.Acceptable +from cdatgui.bases.vcs_elements_dialog import VcsElementsDialog, VcsElementsValidator class MultiLineEditor(BaseOkWindowWidget): @@ -94,8 +66,8 @@ def editLine(self, index): self.line_editor.close() self.line_editor.deleteLater() self.line_editor = LineEditorWidget() - dialog = LineNameDialog() - dialog.setValidator(LineTextValidator()) + dialog = VcsElementsDialog('line') + dialog.setValidator(VcsElementsValidator()) self.line_editor.setSaveDialog(dialog) line = self.isoline_model.line[index] diff --git a/cdatgui/editors/widgets/multi_text_editor.py b/cdatgui/editors/widgets/multi_text_editor.py index 4f58ac2..04d369f 100644 --- a/cdatgui/editors/widgets/multi_text_editor.py +++ b/cdatgui/editors/widgets/multi_text_editor.py @@ -5,36 +5,8 @@ from cdatgui.bases.window_widget import BaseOkWindowWidget from cdatgui.bases.dynamic_grid_layout import DynamicGridLayout import vcs -from cdatgui.bases.input_dialog import ValidatingInputDialog from cdatgui.vcsmodel import get_textstyles - - -class TextNameDialog(ValidatingInputDialog): - def save(self): - if self.textValue() in vcs.elements['texttable'] or self.textValue() in vcs.elements['textorientation']: - check = QtGui.QMessageBox.question(self, "Overwrite text?", - "Text {0} already exists. Overwrite?".format(self.textValue()), - buttons=QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) - if check == QtGui.QDialogButtonBox.FirstButton: - self.close() - self.accepted.emit() - else: - self.close() - self.accepted.emit() - - -class TextNameValidator(QtGui.QValidator): - invalidInput = QtCore.Signal() - validInput = QtCore.Signal() - - def validate(self, inp, pos): - inp = inp.strip() - if not inp or inp == 'default': - self.invalidInput.emit() - return QtGui.QValidator.Intermediate - - self.validInput.emit() - return QtGui.QValidator.Acceptable +from cdatgui.bases.vcs_elements_dialog import VcsElementsDialog, VcsElementsValidator class MultiTextEditor(BaseOkWindowWidget): @@ -94,8 +66,8 @@ def editText(self, index): self.text_editor.close() self.text_editor.deleteLater() self.text_editor = TextStyleEditorWidget() - dialog = TextNameDialog() - dialog.setValidator(TextNameValidator()) + dialog = VcsElementsDialog('texttable') + dialog.setValidator(VcsElementsValidator()) self.text_editor.setSaveDialog(dialog) text = self.isoline_model.text[index] diff --git a/tests/test_ProjectionEditor.py b/tests/test_ProjectionEditor.py new file mode 100644 index 0000000..6ea1523 --- /dev/null +++ b/tests/test_ProjectionEditor.py @@ -0,0 +1,72 @@ +import vcs, cdms2, pytest +from PySide import QtCore, QtGui +from cdatgui.editors.projection_editor import ProjectionEditor + + +@pytest.fixture +def editor(): + edit = ProjectionEditor() + gm = vcs.createboxfill() + proj_obj = vcs.getprojection('linear') + edit.setProjectionObject(proj_obj) + edit.gm = gm + return edit + + +def test_changingNameAndType(qtbot, editor): + orig_ortho = vcs.elements['projection']['orthographic'] + assert editor.vertical_layout.count() == 3 + assert editor.proj_combo.currentText() == 'linear' + assert editor.type_combo.currentText() == 'linear' + + editor.proj_combo.setCurrentIndex(5) + assert editor.cur_projection_name == 'orthographic' + assert editor.type_combo.currentText() == 'orthographic' + assert len(editor.editors) == 5 + + editor.type_combo.setCurrentIndex(editor.type_combo.findText('hotin oblique merc')) + assert len(editor.editors) == 11 + assert editor.cur_projection_name == 'orthographic' + assert editor.type_combo.currentText() == 'hotin oblique merc' + + editor.save() + + assert vcs.elements['projection']['orthographic'] != orig_ortho + assert vcs.elements['projection']['orthographic'].type == 'hotin oblique merc' + assert 'new' not in vcs.listelements('projection') + + +def test_savAs(qtbot, editor): + orig_poly = vcs.elements['projection']['polyconic'] + assert editor.vertical_layout.count() == 3 + assert editor.proj_combo.currentText() == 'linear' + assert editor.type_combo.currentText() == 'linear' + + editor.proj_combo.setCurrentIndex(7) + assert editor.cur_projection_name == 'polyconic' + assert editor.type_combo.currentText() == 'polyconic' + assert len(editor.editors) == 6 + + editor.saveAs() + qtbot.addWidget(editor.win) + editor.win.setTextValue('test') + editor.win.accepted.emit() + + assert vcs.elements['projection']['polyconic'] == orig_poly + assert 'test' in vcs.listelements('projection') + assert 'new' not in vcs.listelements('projection') + + +def test_close(qtbot, editor): + assert 'new' in vcs.listelements('projection') + assert editor.cur_projection_name == 'linear' + assert editor.object.type == 'linear' + + editor.updateCurrentProjection('mollweide') + assert editor.cur_projection_name == 'mollweide' + assert editor.object.type == 'mollweide' + editor.close() + + assert 'new' not in vcs.listelements('projection') + assert vcs.getprojection('linear').name == 'linear' + assert vcs.getprojection('linear').type == 'linear' From 2ed93a566f881f456e034cd92ecd0191dcd025b1 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Tue, 3 May 2016 09:38:44 -0700 Subject: [PATCH 16/29] fixed tests and refactored adding 'new' vcs var --- cdatgui/bases/window_widget.py | 5 +- cdatgui/console/console_widget.py | 8 +- cdatgui/editors/projection_editor.py | 40 +++++-- cdatgui/editors/secondary/editor/line.py | 8 +- cdatgui/editors/secondary/editor/text.py | 23 ++-- cdatgui/variables/__init__.py | 9 +- cdatgui/variables/cdms_file_tree.py | 6 +- cdatgui/variables/manager.py | 5 + cdatgui/variables/variable_add.py | 30 +++--- cdatgui/vcsmodel/elements.py | 22 ++++ tests/test_LineEditor.py | 28 ++++- tests/test_MultiLineEditor.py | 2 + tests/test_TextStyleEditor.py | 127 ++++++++++------------- 13 files changed, 195 insertions(+), 118 deletions(-) diff --git a/cdatgui/bases/window_widget.py b/cdatgui/bases/window_widget.py index 3e93d21..0d68890 100644 --- a/cdatgui/bases/window_widget.py +++ b/cdatgui/bases/window_widget.py @@ -6,7 +6,7 @@ class BaseSaveWindowWidget(QtGui.QWidget): def __init__(self): super(BaseSaveWindowWidget, self).__init__() - + self.auto_close = True self.object = None self.preview = None self.dialog = QtGui.QInputDialog() @@ -69,7 +69,8 @@ def save(self): name = self.object.name self.savePressed.emit(name) - self.close() + if self.auto_close: + self.close() def setSaveDialog(self, dialog): self.dialog = dialog diff --git a/cdatgui/console/console_widget.py b/cdatgui/console/console_widget.py index dfb638e..aa7487c 100644 --- a/cdatgui/console/console_widget.py +++ b/cdatgui/console/console_widget.py @@ -8,7 +8,7 @@ from qtconsole.rich_jupyter_widget import RichJupyterWidget from cdatgui.cdat.metadata import FileMetadataWrapper, VariableMetadataWrapper -from cdatgui.variables import get_variables +from cdatgui.variables import get_variables, reserved_words def is_cdms_var(v): @@ -37,10 +37,6 @@ def __init__(self, parent=None): self.shell_vars = {} self.gm_count = {} self.letters = list(string.ascii_uppercase) - self.reserved_words = ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global', 'or', 'with', - 'assert', 'else', 'if', 'pass', 'yield', 'break', 'except', 'import', 'print', 'class', - 'exec', 'in', 'raise', 'continue', 'finally', 'is', 'return', 'def', 'for', 'lambda', - 'try'] # Create ipython widget self.kernel_manager = QtInProcessKernelManager() @@ -183,7 +179,7 @@ def codeExecuted(self, *varargs): def fixInvalidVariables(self, var): var = re.sub(' +', '_', var) var = re.sub("[^a-zA-Z0-9_]+", '', var) - if var in self.reserved_words or not re.match("^[a-zA-Z_]", var): + if var in reserved_words() or not re.match("^[a-zA-Z_]", var): var = 'cdat_' + var return var diff --git a/cdatgui/editors/projection_editor.py b/cdatgui/editors/projection_editor.py index 9d80e9c..f76b125 100644 --- a/cdatgui/editors/projection_editor.py +++ b/cdatgui/editors/projection_editor.py @@ -17,6 +17,7 @@ def __init__(self): self.gm = None self.savePressed.connect(self.savingNewProjection) self.editors = [] + self.auto_close = False self.proj_combo = QtGui.QComboBox() self.proj_combo.addItems(vcs.listelements('projection')) @@ -95,8 +96,6 @@ def __init__(self): self.vertical_layout.insertLayout(1, type_row) def setProjectionObject(self, obj): - if obj.name == 'default': - self.save_button.setEnabled(False) self.orig_projection = obj self.cur_projection_name = obj.name self.object = vcs.createprojection('new', obj) @@ -104,6 +103,10 @@ def setProjectionObject(self, obj): def updateAttributes(self): obj = self.object + if self.cur_projection_name == 'default': + self.save_button.setEnabled(False) + else: + self.save_button.setEnabled(True) for i in range(2, self.vertical_layout.count() - 1): row = self.vertical_layout.takeAt(2).layout() @@ -117,7 +120,7 @@ def updateAttributes(self): obj.list() sys.stdout = orig_out lst = myout.getvalue().split('\n') - print 'LIST', lst + # print 'LIST', lst for item in lst[2:-1]: left, right = item.split('=') left = left.strip() @@ -157,18 +160,43 @@ def updateProjectionType(self, type): self.object.type = str(type) self.updateAttributes() + def updateGM(self): + + for editor, attr in self.editors: + if isinstance(editor, QtGui.QComboBox): + text = editor.currentText() + else: + text = editor.text() + try: + text = float(text) + except ValueError: + QtGui.QMessageBox.critical(self, "Invalid Type", + "Value '{0}' for {1} is not valid.".format(text, attr.capitalize())) + return False + + setattr(self.object, attr, text) + return True + def savingNewProjection(self, name): + if not self.updateGM(): + print "invalid, returning not closing" + return + if name == 'new': + print "name is new", self.object.list() vcs.elements['projection'].pop(self.cur_projection_name) vcs.createprojection(self.cur_projection_name, self.object) name = self.cur_projection_name + c_obj = vcs.elements['projection'][name] + print "CREATED OBJECT", c_obj.list() + print "SMAJOR", c_obj._getsmajor() else: + if name in vcs.listelements('projection'): + del vcs.elements['projection'][name] vcs.createprojection(name, vcs.elements['projection']['new']) - new = vcs.elements['projection'].pop('new') - del new - self.gm.projection = name + self.close() def close(self): if 'new' in vcs.elements['projection']: diff --git a/cdatgui/editors/secondary/editor/line.py b/cdatgui/editors/secondary/editor/line.py index 108553c..641703e 100644 --- a/cdatgui/editors/secondary/editor/line.py +++ b/cdatgui/editors/secondary/editor/line.py @@ -54,9 +54,6 @@ def setLineObject(self, line_obj): if line_obj.name == 'default': self.save_button.setEnabled(False) - if 'new' in vcs.elements['line']: - del vcs.elements['line']['new'] - line_obj = vcs.createline('new', line_obj.name) self.object = line_obj @@ -94,3 +91,8 @@ def saveNewLine(self, name): vcs.createline(name, source='new') get_lines().updated(name) self.saved.emit(name) + + def close(self): + if 'new' in vcs.elements['line']: + del vcs.elements['line']['new'] + super(LineEditorWidget, self).close() diff --git a/cdatgui/editors/secondary/editor/text.py b/cdatgui/editors/secondary/editor/text.py index e6690d5..4d38d27 100755 --- a/cdatgui/editors/secondary/editor/text.py +++ b/cdatgui/editors/secondary/editor/text.py @@ -100,14 +100,6 @@ def setTextObject(self, text_object): if text_object.Tt_name == 'default' and text_object.To_name == 'default': self.save_button.setEnabled(False) - if 'new:::new' in vcs.elements['textcombined']: - del vcs.elements['textcombined']['new:::new'] - try: - del vcs.elements['textorientation']['new'] - del vcs.elements['texttable']['new'] - except KeyError: - pass - text_object = vcs.createtextcombined('new', text_object.Tt_name, 'new', text_object.To_name) self.object = text_object @@ -167,12 +159,6 @@ def saveNewText(self, name): name = str(name) if name != 'new:::new': - # for el in vcs.listelements('textorientation'): - # for el in vcs.listelements('textcombined'): - # print el - # print vcs.elements['textcombined'] - # getting object - # import traceback;traceback.print_stack() to = vcs.elements['textorientation']['new'] tt = vcs.elements['texttable']['new'] @@ -232,3 +218,12 @@ def saveNewText(self, name): # adding to list self.saved.emit(old_tt_name) + + def close(self): + if 'new:::new' in vcs.elements['textcombined']: + del vcs.elements['textcombined']['new:::new'] + if 'new' in vcs.listelements('textorientation'): + del vcs.elements['textorientation']['new'] + if 'new' in vcs.listelements('texttable'): + del vcs.elements['texttable']['new'] + super(TextStyleEditorWidget, self).close() diff --git a/cdatgui/variables/__init__.py b/cdatgui/variables/__init__.py index d76cd4c..56c95b2 100644 --- a/cdatgui/variables/__init__.py +++ b/cdatgui/variables/__init__.py @@ -7,4 +7,11 @@ def get_variables(): global __variables__ if __variables__ is None: __variables__ = models.CDMSVariableListModel() - return __variables__ \ No newline at end of file + return __variables__ + + +def reserved_words(): + return ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global', 'or', 'with', + 'assert', 'else', 'if', 'pass', 'yield', 'break', 'except', 'import', 'print', 'class', + 'exec', 'in', 'raise', 'continue', 'finally', 'is', 'return', 'def', 'for', 'lambda', + 'try'] diff --git a/cdatgui/variables/cdms_file_tree.py b/cdatgui/variables/cdms_file_tree.py index ebd1fe6..dc23040 100644 --- a/cdatgui/variables/cdms_file_tree.py +++ b/cdatgui/variables/cdms_file_tree.py @@ -11,7 +11,7 @@ class CDMSFileItem(QtGui.QTreeWidgetItem): - def __init__(self, text, parent=None): + def __init__(self, text, uri, parent=None): global label_font, label_icon_size, label_icon if label_font is None: @@ -21,6 +21,8 @@ def __init__(self, text, parent=None): label_icon = icon("bluefile.png") super(CDMSFileItem, self).__init__(parent=parent) + + self.uri = uri self.setSizeHint(0, label_icon_size) self.setIcon(0, label_icon) self.setText(1, text) @@ -52,7 +54,7 @@ def add_file(self, cdmsfile): file_name = os.path.basename(parsed.path) - file_item = CDMSFileItem(file_name) + file_item = CDMSFileItem(file_name, cdmsfile.uri) for var in cdmsfile.variables: var_item = QtGui.QTreeWidgetItem() diff --git a/cdatgui/variables/manager.py b/cdatgui/variables/manager.py index ef6e672..d376c0b 100644 --- a/cdatgui/variables/manager.py +++ b/cdatgui/variables/manager.py @@ -50,3 +50,8 @@ def add_file(self, file): self.usedFile.emit(fmw) return fmw + + def remove_file(self, file): + if file.uri not in self.files: + raise Exception("File not in manager.") + del self.files[file.uri] diff --git a/cdatgui/variables/variable_add.py b/cdatgui/variables/variable_add.py index ca613ce..cba9940 100644 --- a/cdatgui/variables/variable_add.py +++ b/cdatgui/variables/variable_add.py @@ -7,7 +7,7 @@ from cdms_file_chooser import CDMSFileChooser from cdms_file_tree import CDMSFileTree from manager import manager -from . import get_variables +from . import get_variables, reserved_words from cdatgui.bases.input_dialog import ValidatingInputDialog @@ -22,13 +22,9 @@ class FileNameValidator(QtGui.QValidator): def __init__(self): super(FileNameValidator, self).__init__() - self.reserved_words = ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global', 'or', 'with', - 'assert', 'else', 'if', 'pass', 'yield', 'break', 'except', 'import', 'print', 'class', - 'exec', 'in', 'raise', 'continue', 'finally', 'is', 'return', 'def', 'for', 'lambda', - 'try'] def validate(self, name, pos): - if name in self.reserved_words or not re.search("^[a-zA-Z_]", name) or name == '' \ + if name in reserved_words() or not re.search("^[a-zA-Z_]", name) or name == '' \ or re.search(' +', name) or re.search("[^a-zA-Z0-9_]+", name) \ or get_variables().variable_exists(dummyVar(name)): self.invalidInput.emit() @@ -43,10 +39,6 @@ def __init__(self, parent=None, f=0): self.setWindowModality(QtCore.Qt.ApplicationModal) self.renameVar = [] self.dialog = None - self.reserved_words = ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global', 'or', 'with', - 'assert', 'else', 'if', 'pass', 'yield', 'break', 'except', 'import', 'print', 'class', - 'exec', 'in', 'raise', 'continue', 'finally', 'is', 'return', 'def', 'for', 'lambda', - 'try'] wrap = QtGui.QVBoxLayout() @@ -111,7 +103,21 @@ def added_files(self): self.tree.add_file(cdmsfile) def remove_file(self): - pass # pragma: no cover + sel = self.tree.selectedItems() + for item in sel: + i = item.parent().takeChild(item.parent().indexOfChild(item)) + del i + + file_count = self.tree.topLevelItemCount() + i = 0 + while i < file_count: + if not self.tree.topLevelItem(i).childCount(): + file = self.tree.takeTopLevelItem(i) + manager().remove_file(file) + del file + file_count -= 1 + else: + i += 1 def rename_file(self): var = self.tree.get_selected() @@ -137,7 +143,7 @@ def setRenameVar(self, var): self.tree.clearSelection() def isValidName(self, name): - if name in self.reserved_words or not re.search("^[a-zA-Z_]", name) or name == '' \ + if name in reserved_words() or not re.search("^[a-zA-Z_]", name) or name == '' \ or re.search(' +', name) or re.search("[^a-zA-Z0-9_]+", name) \ or get_variables().variable_exists(dummyVar(name)): return False diff --git a/cdatgui/vcsmodel/elements.py b/cdatgui/vcsmodel/elements.py index b85bbe4..f6c977b 100644 --- a/cdatgui/vcsmodel/elements.py +++ b/cdatgui/vcsmodel/elements.py @@ -54,3 +54,25 @@ def updated(self, el_name): self.beginInsertRows(QtCore.QModelIndex(), insert_ind, insert_ind) self.elements = new_els self.endInsertRows() + + def remove(self, el_name): + print "in remove" + new_els = [] + remove_ind = -1 + remove_me = el_name + for ind, name in enumerate(self.elements): + if remove_me is not None and name == remove_me: + remove_ind = ind + remove_me = None + else: + new_els.append(name) + + if remove_ind == -1: + print "returning" + return + + self.beginRemoveRows(QtCore.QModelIndex(), remove_ind, remove_ind) + print "REMOVING" + self.elements = new_els + self.endRemoveRows() + diff --git a/tests/test_LineEditor.py b/tests/test_LineEditor.py index 9fe7863..d875a7e 100644 --- a/tests/test_LineEditor.py +++ b/tests/test_LineEditor.py @@ -1,22 +1,48 @@ import pytest import vcs, cdms2 from cdatgui.editors.secondary.editor.line import LineEditorWidget +from cdatgui.vcsmodel import get_lines + @pytest.fixture def editor(): editor = LineEditorWidget() - line = vcs.createline() + line = vcs.getline('cyan') editor.setLineObject(line) return editor + def test_type(qtbot, editor): editor.updateType('dash') assert editor.object.type == ['dash'] + editor.save() + assert vcs.elements['line']['cyan'].type == ['dash'] + assert 'new' not in vcs.listelements('line') + + def test_color(qtbot, editor): editor.updateColor(55) assert editor.object.color == [55] + editor.saveAs() + editor.win.setTextValue('check') + editor.save() + assert 'check' in vcs.listelements('line') + assert vcs.elements['line']['check'].color == [55] + + del vcs.elements['line']['check'] + assert 'check' not in vcs.listelements('line') + assert 'new' not in vcs.listelements('line') + + def test_width(qtbot, editor): editor.updateWidth(250) assert editor.object.width == [250] + + editor.save() + assert vcs.elements['line']['cyan'].width == [250] + assert 'new' not in vcs.listelements('line') + + get_lines().remove('check') + get_lines().remove('new') diff --git a/tests/test_MultiLineEditor.py b/tests/test_MultiLineEditor.py index 1d8c253..6bd5567 100644 --- a/tests/test_MultiLineEditor.py +++ b/tests/test_MultiLineEditor.py @@ -46,6 +46,8 @@ def test_MultiLineEditor(qtbot, line_editor): assert combo.currentIndex() != -1 editor.line_combos[2].setCurrentIndex(10) + print editor.line_combos[2].model().elements + print editor.isoline_model.line assert editor.isoline_model.line[2] == 'pink' editor.editLine(6) diff --git a/tests/test_TextStyleEditor.py b/tests/test_TextStyleEditor.py index 75fe1d9..a9380b7 100755 --- a/tests/test_TextStyleEditor.py +++ b/tests/test_TextStyleEditor.py @@ -1,5 +1,4 @@ import pytest -import re import vcs from PySide import QtCore, QtGui from cdatgui.editors.secondary.editor.text import TextStyleEditorWidget @@ -7,7 +6,8 @@ @pytest.fixture -def editors(): +def editor(): + print "in editor" for name in ['header', 'header2', 'header3']: try: del vcs.elements['textcombined']['{0}:::{1}'.format(name, name)] @@ -20,104 +20,89 @@ def editors(): t = vcs.createtext('header') edit1.setTextObject(t) - edit2 = TextStyleEditorWidget() - t = vcs.createtext('header2') - t.valign = 0 - t.halign = 1 - edit2.setTextObject(t) - - edit3 = TextStyleEditorWidget() - t = vcs.createtext('header3') - t.valign = 4 - t.halign = 2 - edit3.setTextObject(t) - - return edit1, edit2, edit3 + return edit1 def save_check(name): - # assert name in vcs.listelements('textcombined') - assert re.match("header[0-9]*", name) + assert name == 'header' -def test_save(qtbot, editors): - for editor in editors: +def test_alignment(qtbot, editor): - editor.saved.connect(save_check) - editor.save() + # test valign + editor.updateButton(editor.va_group.buttons()[0]) + assert editor.object.valign == 0 + editor.updateButton(editor.va_group.buttons()[2]) + assert editor.object.valign == 4 -def test_alignment(editors): - for editor in editors: - # test valign - editor.updateButton(editor.va_group.buttons()[0]) - assert editor.object.valign == 0 + editor.updateButton(editor.va_group.buttons()[1]) + assert editor.object.valign == 2 - editor.updateButton(editor.va_group.buttons()[2]) - assert editor.object.valign == 4 + # test halign + editor.updateButton(editor.ha_group.buttons()[2]) + assert editor.object.halign == 2 - editor.updateButton(editor.va_group.buttons()[1]) - assert editor.object.valign == 2 + editor.updateButton(editor.ha_group.buttons()[1]) + assert editor.object.halign == 1 - # test halign - editor.updateButton(editor.ha_group.buttons()[2]) - assert editor.object.halign == 2 + editor.updateButton(editor.ha_group.buttons()[0]) + assert editor.object.halign == 0 - editor.updateButton(editor.ha_group.buttons()[1]) - assert editor.object.halign == 1 + # test save as well + editor.saved.connect(save_check) + editor.save() - editor.updateButton(editor.ha_group.buttons()[0]) - assert editor.object.halign == 0 +def test_angle(editor): + assert editor.object.angle == 0 -def test_angle(editors): - for editor in editors: + editor.updateAngle(50) + assert editor.object.angle == 50 - assert editor.object.angle == 0 + editor.updateAngle(440) + assert editor.object.angle == 80 - editor.updateAngle(50) - assert editor.object.angle == 50 + editor.save() - editor.updateAngle(440) - assert editor.object.angle == 80 +def test_font(editor): + editor.updateFont("Helvetica") + assert editor.object.font == 4 -def test_font(editors): - for editor in editors: - editor.updateFont("Helvetica") - assert editor.object.font == 4 + editor.updateFont("Chinese") + assert editor.object.font == 8 - editor.updateFont("Chinese") - assert editor.object.font == 8 + editor.save() -def test_size(editors): - for editor in editors: - assert editor.object.height == 14 +def test_size(editor): + assert editor.object.height == 14 - editor.updateSize(50) - assert editor.object.height == 50 + editor.updateSize(50) + assert editor.object.height == 50 + + editor.save() def saveas_check(name): assert name == "test.txt" -def test_saveas(qtbot, editors): - for editor in editors: +def test_saveas(qtbot, editor): - editor.saved.connect(saveas_check) - editor.saveAs() + editor.saved.connect(saveas_check) + editor.saveAs() + + try: + print editor.win + except: + print "Did not create save as dialog" + assert 0 + + editor.win.setTextValue("test.txt") + qtbot.keyPress(editor.win, QtCore.Qt.Key_Enter) + assert "test.txt" in vcs.listelements('texttable') + assert "test.txt" in vcs.listelements('textorientation') + assert "test.txt" in get_textstyles().elements - try: - print editor.win - except: - print "Did not create save as dialog" - assert 0 - - editor.win.setTextValue("test.txt") - qtbot.keyPress(editor.win, QtCore.Qt.Key_Enter) - assert "test.txt" in vcs.listelements('texttable') - assert "test.txt" in vcs.listelements('textorientation') - assert "test.txt" in get_textstyles().elements - assert False From a846bf8269e53fa1f4da1717c93ff85baa167d66 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Wed, 4 May 2016 14:54:58 -0700 Subject: [PATCH 17/29] Adding new gm implemented in side gm list --- cdatgui/bases/input_dialog.py | 44 +++--- cdatgui/editors/graphics_method_editor.py | 1 - cdatgui/editors/level_editor.py | 1 + cdatgui/editors/preview/axis_preview.py | 4 + cdatgui/editors/preview/legend_preview.py | 4 + cdatgui/editors/projection_editor.py | 71 ++++------ cdatgui/editors/secondary/editor/line.py | 12 +- cdatgui/editors/secondary/editor/text.py | 32 +++-- cdatgui/graphics/dialog.py | 63 ++++++--- cdatgui/graphics/graphics_method_widget.py | 151 ++++++++++++++++++++- cdatgui/graphics/vcs_gm_list.py | 17 +-- cdatgui/persistence/db.py | 9 ++ cdatgui/sidebar/inspector_widget.py | 4 +- cdatgui/variables/cdms_file_tree.py | 2 +- cdatgui/variables/manager.py | 3 +- tests/mocks/PlotInfo.py | 2 +- tests/test_GmDialog.py | 8 +- tests/test_LineEditor.py | 8 +- tests/test_ProjectionEditor.py | 28 +++- tests/test_save_load.py | 17 ++- tests/test_variables.py | 2 +- 21 files changed, 341 insertions(+), 142 deletions(-) diff --git a/cdatgui/bases/input_dialog.py b/cdatgui/bases/input_dialog.py index e03684c..03da402 100644 --- a/cdatgui/bases/input_dialog.py +++ b/cdatgui/bases/input_dialog.py @@ -1,43 +1,32 @@ from PySide import QtCore, QtGui -class ValidatingInputDialog(QtGui.QWidget): +class AccessableButtonDialog(QtGui.QWidget): accepted = QtCore.Signal() rejected = QtCore.Signal() def __init__(self): - super(ValidatingInputDialog, self).__init__() + super(AccessableButtonDialog, self).__init__() self.setWindowModality(QtCore.Qt.ApplicationModal) shortcut = QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Escape), self) shortcut.activated.connect(self.cancel) - vertical_layout = QtGui.QVBoxLayout() - - self.label = QtGui.QLabel() - self.edit = QtGui.QLineEdit() - self.save_button = QtGui.QPushButton('Save') self.save_button.clicked.connect(self.save) self.save_button.setEnabled(False) self.save_button.setDefault(True) - cancel_button = QtGui.QPushButton('Cancel') - cancel_button.clicked.connect(self.cancel) - - self.edit.returnPressed.connect(self.save_button.click) - - edit_line_layout = QtGui.QHBoxLayout() - edit_line_layout.addWidget(self.label) - edit_line_layout.addWidget(self.edit) + self.cancel_button = QtGui.QPushButton('Cancel') + self.cancel_button.clicked.connect(self.cancel) save_cancel_layout = QtGui.QHBoxLayout() - save_cancel_layout.addWidget(cancel_button) + save_cancel_layout.addWidget(self.cancel_button) save_cancel_layout.addWidget(self.save_button) - vertical_layout.addLayout(edit_line_layout) - vertical_layout.addLayout(save_cancel_layout) + self.vertical_layout = QtGui.QVBoxLayout() + self.vertical_layout.addLayout(save_cancel_layout) - self.setLayout(vertical_layout) + self.setLayout(self.vertical_layout) self.setMaximumSize(300, 100) @@ -49,11 +38,26 @@ def save(self): self.close() self.accepted.emit() + +class ValidatingInputDialog(AccessableButtonDialog): + def __init__(self): + super(ValidatingInputDialog, self).__init__() + + self.label = QtGui.QLabel() + self.edit = QtGui.QLineEdit() + + self.edit.returnPressed.connect(self.save_button.click) + + edit_line_layout = QtGui.QHBoxLayout() + edit_line_layout.addWidget(self.label) + edit_line_layout.addWidget(self.edit) + + self.vertical_layout.insertLayout(0, edit_line_layout) + def setLabelText(self, text): self.label.setText(text) def setValidator(self, validator): - self.edit.setValidator(validator) try: diff --git a/cdatgui/editors/graphics_method_editor.py b/cdatgui/editors/graphics_method_editor.py index da6655f..92b7c25 100644 --- a/cdatgui/editors/graphics_method_editor.py +++ b/cdatgui/editors/graphics_method_editor.py @@ -90,7 +90,6 @@ def editLevels(self): def updated(self): if self.legend_editor is not None: - print self.legend_editor.object._gm.list() self.legend_editor = None if self.axis_editor is not None: self.axis_editor = None diff --git a/cdatgui/editors/level_editor.py b/cdatgui/editors/level_editor.py index f7bf08b..4ed7480 100644 --- a/cdatgui/editors/level_editor.py +++ b/cdatgui/editors/level_editor.py @@ -64,6 +64,7 @@ def var(self): @var.setter def var(self, value): + print "VAR", value, type(value) self._var = value flat = self._var.data flat = sorted(numpy.unique(flat.flatten())) diff --git a/cdatgui/editors/preview/axis_preview.py b/cdatgui/editors/preview/axis_preview.py index 16a0338..2a6cf2a 100644 --- a/cdatgui/editors/preview/axis_preview.py +++ b/cdatgui/editors/preview/axis_preview.py @@ -7,6 +7,7 @@ def __init__(self, parent=None): super(AxisPreviewWidget, self).__init__(parent=parent) self.axis = None self.visibilityChanged.connect(self.visibility_toggled) + self.template_name = None def visibility_toggled(self, showing): if showing: @@ -17,7 +18,10 @@ def update(self): if self.canvas is None: return self.canvas.clear(render=False) + if self.template_name: + del vcs.elements['template'][self.template_name] template = vcs.createtemplate(source=self.axis.tmpl) + self.template_name = template.name template.blank() axis_orientation = self.axis._axis[0] diff --git a/cdatgui/editors/preview/legend_preview.py b/cdatgui/editors/preview/legend_preview.py index 1b8a69a..169c3ec 100644 --- a/cdatgui/editors/preview/legend_preview.py +++ b/cdatgui/editors/preview/legend_preview.py @@ -7,6 +7,7 @@ def __init__(self, parent=None): super(LegendPreviewWidget, self).__init__(parent=parent) self.legend = None self.visibilityChanged.connect(self.visibility_toggled) + self.template_name = None def visibility_toggled(self, showing): if showing: @@ -16,7 +17,10 @@ def update(self): if self.canvas is None: return self.canvas.clear(render=False) + if self.template_name: + del vcs.elements['template'][self.template_name] template = vcs.createtemplate() + self.template_name = template.name template.blank() template.legend.priority = 1 diff --git a/cdatgui/editors/projection_editor.py b/cdatgui/editors/projection_editor.py index f76b125..f8049d2 100644 --- a/cdatgui/editors/projection_editor.py +++ b/cdatgui/editors/projection_editor.py @@ -18,6 +18,7 @@ def __init__(self): self.savePressed.connect(self.savingNewProjection) self.editors = [] self.auto_close = False + self.newprojection_name = None self.proj_combo = QtGui.QComboBox() self.proj_combo.addItems(vcs.listelements('projection')) @@ -98,11 +99,13 @@ def __init__(self): def setProjectionObject(self, obj): self.orig_projection = obj self.cur_projection_name = obj.name - self.object = vcs.createprojection('new', obj) + self.object = vcs.createprojection(source=obj) + self.newprojection_name = self.object.name + self.updateAttributes() def updateAttributes(self): - obj = self.object + if self.cur_projection_name == 'default': self.save_button.setEnabled(False) else: @@ -115,34 +118,25 @@ def updateAttributes(self): row.deleteLater() self.editors = [] - orig_out = sys.stdout - sys.stdout = myout = StringIO() - obj.list() - sys.stdout = orig_out - lst = myout.getvalue().split('\n') - # print 'LIST', lst - for item in lst[2:-1]: - left, right = item.split('=') - left = left.strip() - right = right.strip() - - if left == 'name': - block = self.proj_combo.blockSignals(True) - self.proj_combo.setCurrentIndex(self.proj_combo.findText(self.cur_projection_name)) - self.proj_combo.blockSignals(block) - continue - if left == 'type': - block = self.type_combo.blockSignals(True) - self.type_combo.setCurrentIndex(self.type_combo.findText(right)) - self.type_combo.blockSignals(block) - continue + # set name + block = self.proj_combo.blockSignals(True) + self.proj_combo.setCurrentIndex(self.proj_combo.findText(self.cur_projection_name)) + self.proj_combo.blockSignals(block) + + # set type + block = self.type_combo.blockSignals(True) + self.type_combo.setCurrentIndex(self.type_combo.findText(self.object.type)) + self.type_combo.blockSignals(block) + + for name in self.object.attributes: + value = getattr(self.object, name) edit_attr = QtGui.QLineEdit() - edit_attr.setText(right) - self.editors.append((edit_attr, left)) + edit_attr.setText(str(value)) + self.editors.append((edit_attr, name)) row = QtGui.QHBoxLayout() - row.addWidget(label(left.capitalize() + ":")) + row.addWidget(label(name.capitalize() + ":")) row.addWidget(edit_attr) self.vertical_layout.insertLayout(self.vertical_layout.count() - 1, row) @@ -150,18 +144,18 @@ def updateAttributes(self): def updateCurrentProjection(self, proj): proj = str(proj) self.cur_projection_name = proj - if 'new' in vcs.listelements('projection'): - del vcs.elements['projection']['new'] + if self.newprojection_name in vcs.listelements('projection'): + del vcs.elements['projection'][self.newprojection_name] vcs.getprojection(proj).list() - self.object = vcs.createprojection('new', vcs.getprojection(proj)) + self.object = vcs.createprojection(source=vcs.getprojection(proj)) + self.newprojection_name = self.object.name self.updateAttributes() def updateProjectionType(self, type): self.object.type = str(type) self.updateAttributes() - def updateGM(self): - + def updateProjection(self): for editor, attr in self.editors: if isinstance(editor, QtGui.QComboBox): text = editor.currentText() @@ -178,28 +172,23 @@ def updateGM(self): return True def savingNewProjection(self, name): - if not self.updateGM(): - print "invalid, returning not closing" + if not self.updateProjection(): return - if name == 'new': - print "name is new", self.object.list() + if name == self.newprojection_name: vcs.elements['projection'].pop(self.cur_projection_name) vcs.createprojection(self.cur_projection_name, self.object) name = self.cur_projection_name c_obj = vcs.elements['projection'][name] - print "CREATED OBJECT", c_obj.list() - print "SMAJOR", c_obj._getsmajor() else: if name in vcs.listelements('projection'): del vcs.elements['projection'][name] - vcs.createprojection(name, vcs.elements['projection']['new']) + vcs.createprojection(name, vcs.elements['projection'][self.newprojection_name]) self.gm.projection = name self.close() def close(self): - if 'new' in vcs.elements['projection']: - new = vcs.elements['projection'].pop('new') - del new + if self.newprojection_name in vcs.elements['projection']: + del vcs.elements['projection'][self.newprojection_name] super(ProjectionEditor, self).close() diff --git a/cdatgui/editors/secondary/editor/line.py b/cdatgui/editors/secondary/editor/line.py index 641703e..8a1a486 100644 --- a/cdatgui/editors/secondary/editor/line.py +++ b/cdatgui/editors/secondary/editor/line.py @@ -13,6 +13,7 @@ def __init__(self): self.setPreview(LinePreviewWidget()) self.savePressed.connect(self.saveNewLine) self.orig_name = None + self.newline_name = None # create labels type_label = QtGui.QLabel("Type:") @@ -54,7 +55,8 @@ def setLineObject(self, line_obj): if line_obj.name == 'default': self.save_button.setEnabled(False) - line_obj = vcs.createline('new', line_obj.name) + line_obj = vcs.createline(source=line_obj.name) + self.newline_name = line_obj.name self.object = line_obj self.preview.setLineObject(self.object) @@ -78,7 +80,7 @@ def updateWidth(self, width): def saveNewLine(self, name): name = str(name) - if name == "new": + if name == self.newline_name: if self.orig_name in vcs.elements['line']: del vcs.elements['line'][self.orig_name] @@ -88,11 +90,11 @@ def saveNewLine(self, name): else: if name in vcs.elements['line']: del vcs.elements['line'][name] - vcs.createline(name, source='new') + vcs.createline(name, source=self.newline_name) get_lines().updated(name) self.saved.emit(name) def close(self): - if 'new' in vcs.elements['line']: - del vcs.elements['line']['new'] + if self.newline_name in vcs.elements['line']: + del vcs.elements['line'][self.newline_name] super(LineEditorWidget, self).close() diff --git a/cdatgui/editors/secondary/editor/text.py b/cdatgui/editors/secondary/editor/text.py index 4d38d27..e44efb9 100755 --- a/cdatgui/editors/secondary/editor/text.py +++ b/cdatgui/editors/secondary/editor/text.py @@ -13,6 +13,7 @@ def __init__(self): self.setPreview(TextStylePreviewWidget()) self.savePressed.connect(self.saveNewText) self.orig_names = [] + self.newtextcombined_name = None # Set up vertical align self.va_group = QtGui.QButtonGroup() @@ -100,7 +101,8 @@ def setTextObject(self, text_object): if text_object.Tt_name == 'default' and text_object.To_name == 'default': self.save_button.setEnabled(False) - text_object = vcs.createtextcombined('new', text_object.Tt_name, 'new', text_object.To_name) + text_object = vcs.createtextcombined(Tt_source=text_object.Tt_name, To_source=text_object.To_name) + self.newtextcombined_name = text_object.name self.object = text_object self.preview.setTextObject(self.object) @@ -157,10 +159,11 @@ def updateSize(self, size): def saveNewText(self, name): name = str(name) + tt_name, to_name = self.newtextcombined_name.split(':::') - if name != 'new:::new': - to = vcs.elements['textorientation']['new'] - tt = vcs.elements['texttable']['new'] + if name != self.newtextcombined_name: + to = vcs.elements['textorientation'][to_name] + tt = vcs.elements['texttable'][tt_name] # deleting if already exists. This will only happen if they want to overwrite if name in vcs.elements['texttable']: @@ -175,8 +178,8 @@ def saveNewText(self, name): vcs.elements['texttable'][name] = new_tt # removing old object from key - vcs.elements['textorientation'].pop('new') - vcs.elements['texttable'].pop('new') + vcs.elements['textorientation'].pop(to_name) + vcs.elements['texttable'].pop(tt_name) tc = vcs.createtextcombined() tc.Tt = new_tt @@ -194,8 +197,8 @@ def saveNewText(self, name): old_to = vcs.elements['textorientation'][self.orig_names[2]] # get new info - new_tt = vcs.elements['texttable']['new'] - new_to = vcs.elements['textorientation']['new'] + new_tt = vcs.elements['texttable'][tt_name] + new_to = vcs.elements['textorientation'][to_name] # delete old tt and to old_tt_name = old_tt.name @@ -220,10 +223,11 @@ def saveNewText(self, name): self.saved.emit(old_tt_name) def close(self): - if 'new:::new' in vcs.elements['textcombined']: - del vcs.elements['textcombined']['new:::new'] - if 'new' in vcs.listelements('textorientation'): - del vcs.elements['textorientation']['new'] - if 'new' in vcs.listelements('texttable'): - del vcs.elements['texttable']['new'] + tt_name, to_name = self.newtextcombined_name.split(':::') + if self.newtextcombined_name in vcs.elements['textcombined']: + del vcs.elements['textcombined'][self.newtextcombined_name] + if to_name in vcs.listelements('textorientation'): + del vcs.elements['textorientation'][to_name] + if tt_name in vcs.listelements('texttable'): + del vcs.elements['texttable'][tt_name] super(TextStyleEditorWidget, self).close() diff --git a/cdatgui/graphics/dialog.py b/cdatgui/graphics/dialog.py index 08e483e..66b2bba 100644 --- a/cdatgui/graphics/dialog.py +++ b/cdatgui/graphics/dialog.py @@ -8,13 +8,14 @@ import vcs -class GraphcisMethodDialog(QtGui.QDialog): +class GraphicsMethodDialog(QtGui.QDialog): editedGM = QtCore.Signal(object) createdGM = QtCore.Signal(object) def __init__(self, gm, var, tmpl, parent=None): - super(GraphcisMethodDialog, self).__init__(parent=parent) + super(GraphicsMethodDialog, self).__init__(parent=parent) self.setWindowModality(QtCore.Qt.ApplicationModal) + self.newgm_name = None layout = QtGui.QVBoxLayout() @@ -41,30 +42,49 @@ def __init__(self, gm, var, tmpl, parent=None): raise NotImplementedError("No editor exists for type %s" % self.gmtype) self.editor.var = var self.editor.tmpl = tmpl + self.gm = gm + self.editor.gm = gm + layout.addWidget(self.editor) - buttons = QtGui.QHBoxLayout() + self.buttons = QtGui.QHBoxLayout() cancel = QtGui.QPushButton("Cancel") cancel.setAutoDefault(True) cancel.clicked.connect(self.reject) + + self.buttons.addWidget(cancel) + self.buttons.addStretch() + + layout.addLayout(self.buttons) + + self.setLayout(layout) + + def reject(self): + super(GraphicsMethodDialog, self).reject() + if isinstance(self.editor, BoxfillEditor): + self.gm.boxfill_type = self.editor.orig_type + + if self.newgm_name in vcs.elements[vcs.graphicsmethodtype(self.gm)].keys(): + del vcs.elements[vcs.graphicsmethodtype(self.gm)][self.newgm_name] + + +class GraphicsMethodSaveDialog(GraphicsMethodDialog): + def __init__(self, gm, var, tmpl, parent=None): + super(GraphicsMethodSaveDialog, self).__init__(gm, var, tmpl, parent) + save_as = QtGui.QPushButton("Save As") save_as.clicked.connect(self.customName) save = QtGui.QPushButton("Save") save.setDefault(True) save.clicked.connect(self.accept) - self.accepted.connect(self.save) - - buttons.addWidget(cancel) - buttons.addStretch() - buttons.addWidget(save_as) - buttons.addWidget(save) - layout.addLayout(buttons) - - self.setLayout(layout) + self.buttons.addWidget(save_as) + self.buttons.addWidget(save) + self.accepted.connect(self.save) if gm.name == 'default': - self.gm = self.create('new', gm) + self.gm = self.create(source=gm) + self.newgm_name = self.gm.name save.setEnabled(False) else: self.gm = gm @@ -81,13 +101,16 @@ def save(self, name=None): self.editedGM.emit(self.gm) else: gm = self.create(name[0], self.gm) - self.close() self.createdGM.emit(gm) - def reject(self): - super(GraphcisMethodDialog, self).reject() - if isinstance(self.editor, BoxfillEditor): - self.gm.boxfill_type = self.editor.orig_type + self.close() + + +class GraphicsMethodOkDialog(GraphicsMethodDialog): + def __init__(self, gm, var, tmpl, parent=None): + super(GraphicsMethodOkDialog, self).__init__(gm, var, tmpl, parent) + + ok_button = QtGui.QPushButton('OK') + ok_button.clicked.connect(self.accept) + self.buttons.addWidget(ok_button) - if 'new' in vcs.elements[vcs.graphicsmethodtype(self.gm)].keys(): - del vcs.elements[vcs.graphicsmethodtype(self.gm)]['new'] diff --git a/cdatgui/graphics/graphics_method_widget.py b/cdatgui/graphics/graphics_method_widget.py index df4d746..47243ae 100644 --- a/cdatgui/graphics/graphics_method_widget.py +++ b/cdatgui/graphics/graphics_method_widget.py @@ -1,11 +1,153 @@ -from PySide import QtCore +import copy +from PySide import QtCore, QtGui from cdatgui.bases import StaticDockWidget from cdatgui.toolbars import AddEditRemoveToolbar from vcs_gm_list import GraphicsMethodList +from cdatgui.bases.input_dialog import ValidatingInputDialog +from cdatgui.graphics import get_gms +from cdatgui.graphics.dialog import GraphicsMethodOkDialog +from cdatgui.utils import label +from cdatgui.cdat.metadata import FileMetadataWrapper +import vcs, cdms2, os -class GraphicsMethodWidget(StaticDockWidget): +class NameValidator(QtGui.QValidator): + invalidInput = QtCore.Signal() + validInput = QtCore.Signal() + + def __init__(self): + super(NameValidator, self).__init__() + self.gm_type = None + + def validate(self, inp, pos): + if not self.gm_type: + raise Exception("Must set gm_type") + if not inp or inp in vcs.listelements(self.gm_type): + self.invalidInput.emit() + return QtGui.QValidator.Intermediate + else: + self.validInput.emit() + return QtGui.QValidator.Acceptable + + +class CreateGM(ValidatingInputDialog): + def __init__(self, currently_selected, parent=None): + super(CreateGM, self).__init__() + + self.edit_gm_name = None + self.edit_dialog = None + self.edit_tmpl_name = None + + validator = NameValidator() + self.setValidator(validator) + self.setLabelText('Name:') + + self.gm_type_combo = QtGui.QComboBox() + self.gm_type_combo.setModel(get_gms()) + if currently_selected: + self.gm_type_combo.setCurrentIndex(self.gm_type_combo.findText(currently_selected[0])) + self.gm_type_combo.currentIndexChanged.connect(self.setGMRoot) + self.edit.validator().gm_type = self.gm_type_combo.currentText() + + # Create the instance combo first so the setGMRoot function can update it properly + self.gm_instance_combo = QtGui.QComboBox() + self.gm_instance_combo.setModel(get_gms()) + self.gm_instance_combo.setRootModelIndex(get_gms().index(self.gm_type_combo.currentIndex(), 0)) + if currently_selected and len(currently_selected) > 1: + self.gm_instance_combo.setCurrentIndex(self.gm_instance_combo.findText(currently_selected[1])) + else: + self.gm_instance_combo.setCurrentIndex(self.gm_instance_combo.findText('default')) + + type_layout = QtGui.QHBoxLayout() + type_layout.addWidget(label('Graphics Method Type:')) + type_layout.addWidget(self.gm_type_combo) + + instance_layout = QtGui.QHBoxLayout() + instance_layout.addWidget(label('Graphics Method:')) + instance_layout.addWidget(self.gm_instance_combo) + + self.vertical_layout.insertLayout(0, instance_layout) + self.vertical_layout.insertLayout(0, type_layout) + + # add customize button + button_layout = self.vertical_layout.itemAt(self.vertical_layout.count() - 1).layout() + customize_button = QtGui.QPushButton('Customize') + customize_button.clicked.connect(self.editGM) + button_layout.insertWidget(1, customize_button) + + self.accepted.connect(self.createGM) + + def setGMRoot(self, index): + self.edit.validator().gm_type = self.gm_type_combo.currentText() + self.gm_instance_combo.setRootModelIndex(get_gms().index(index, 0)) + self.gm_instance_combo.setCurrentIndex(self.gm_instance_combo.findText('default')) + self.edit.validator().validate(self.edit.text(), 0) + def createGM(self): + if self.edit_gm_name: + get_gms().add_gm( + vcs.creategraphicsmethod(str(self.gm_type_combo.currentText()), + self.edit_gm_name, + str(self.textValue()) + )) + del vcs.elements[self.gm_type_combo.currentText()][self.edit_gm_name] + + else: + get_gms().add_gm( + vcs.creategraphicsmethod(str(self.gm_type_combo.currentText()), + str(self.gm_instance_combo.currentText()), + str(self.textValue()) + )) + + def editGM(self): + f = cdms2.open(os.path.join(vcs.sample_data, 'clt.nc')) + f = FileMetadataWrapper(f) + s = f('clt') + + gm = vcs.creategraphicsmethod(str(self.gm_type_combo.currentText()), str(self.gm_instance_combo.currentText())) + tmpl = vcs.createtemplate() + + self.edit_tmpl_name = tmpl.name + self.edit_gm_name = gm.name + self.edit_dialog = GraphicsMethodOkDialog(gm, s, tmpl) + + # replace saveas and save with ok button + ''' + dialog_layout = self.edit_dialog.layout() + button_layout = dialog_layout.itemAt(dialog_layout.count() - 1).layout() + button_layout.takeAt(button_layout.count() - 1).widget().deleteLater() + button_layout.takeAt(button_layout.count() - 1).widget().deleteLater() + ok_button = QtGui.QPushButton('OK') + ok_button.clicked.connect(self.edit_dialog.accept) + button_layout.addWidget(ok_button) + ''' + + self.edit_dialog.rejected.connect(self.resetGM) + + self.edit_dialog.show() + self.edit_dialog.raise_() + + def resetGM(self): + if self.edit_gm_name: + del vcs.elements[self.gm_type_combo.currentText()][self.edit_gm_name] + self.edit_gm_name = None + + def resetTmpl(self): + if self.edit_tmpl_name: + del vcs.elements['template'][self.edit_tmpl_name] + self.edit_tmpl_name = None + + def save(self): + self.resetTmpl() + super(CreateGM, self).save() + + def cancel(self): + self.resetTmpl() + self.resetGM() + super(CreateGM, self).cancel() + + +class GraphicsMethodWidget(StaticDockWidget): def __init__(self, parent=None, flags=0): super(GraphicsMethodWidget, self).__init__("Graphics Methods", parent=parent, flags=flags) self.allowed_sides = [QtCore.Qt.DockWidgetArea.LeftDockWidgetArea] @@ -16,6 +158,7 @@ def __init__(self, parent=None, flags=0): self.remove_gm)) self.list = GraphicsMethodList() self.setWidget(self.list) + self.add_gm_widget = None def selection_change(self): selected = self.list.get_selected() @@ -24,7 +167,9 @@ def selection_change(self): self.selectedGraphicsMethod.emit(selected) def add_gm(self): - pass + self.add_gm_widget = CreateGM(self.list.get_selected()) + self.add_gm_widget.show() + self.add_gm_widget.raise_() def edit_gm(self): pass diff --git a/cdatgui/graphics/vcs_gm_list.py b/cdatgui/graphics/vcs_gm_list.py index 6745cb0..8a852f6 100644 --- a/cdatgui/graphics/vcs_gm_list.py +++ b/cdatgui/graphics/vcs_gm_list.py @@ -12,18 +12,11 @@ def __init__(self, parent=None): self.setIndentation(10) def get_selected(self): - items = self.selectedItems() - sel = None + items = self.selectedIndexes() for selected in items: - if selected.parent() is None: - continue + if not selected.parent().isValid(): + return [selected.data()] - p = selected.parent() - - t = self.types[p.text(0)] - gm = t[selected.text(0)] - sel = gm - break - - return sel + return [selected.parent().data(), selected.data()] + return None diff --git a/cdatgui/persistence/db.py b/cdatgui/persistence/db.py index a6b728b..7c808c4 100644 --- a/cdatgui/persistence/db.py +++ b/cdatgui/persistence/db.py @@ -39,6 +39,7 @@ def db_version(filename): def connect(): global __dbconn__ if __dbconn__ is None: + # TODO: Use vcs.getdotdir() or whatever it is dotdir = os.path.expanduser("~/.uvcdat") path = os.path.expanduser(os.path.join(dotdir, "cdatgui_%s.db" % cdatgui.info.version)) @@ -89,3 +90,11 @@ def add_data_source(uri): matching.last_accessed = datetime.date.today() matching.times_used += 1 db.commit() + +def remove_data_source(uri): + db = connect() + + matching = db.query(DataSource).filter_by(uri=uri).first() + if matching is not None: + db.delete(matching) + db.commit() diff --git a/cdatgui/sidebar/inspector_widget.py b/cdatgui/sidebar/inspector_widget.py index 9f7dcce..aa7f2a6 100644 --- a/cdatgui/sidebar/inspector_widget.py +++ b/cdatgui/sidebar/inspector_widget.py @@ -6,7 +6,7 @@ from cdatgui.templates import get_templates from cdatgui.variables.edit_variable_widget import EditVariableDialog from cdatgui.templates.dialog import TemplateEditorDialog -from cdatgui.graphics.dialog import GraphcisMethodDialog +from cdatgui.graphics.dialog import GraphicsMethodSaveDialog import vcs @@ -185,7 +185,7 @@ def editGM(self): if self.gm_editor: self.gm_editor.close() self.gm_editor.deleteLater() - self.gm_editor = GraphcisMethodDialog(gm, self.var_combos[0].currentObj(), self.template_combo.currentObj()) + self.gm_editor = GraphicsMethodSaveDialog(gm, self.var_combos[0].currentObj(), self.template_combo.currentObj()) self.gm_editor.createdGM.connect(self.makeGraphicsMethod) self.gm_editor.editedGM.connect(self.editGraphicsMethod) self.gm_editor.show() diff --git a/cdatgui/variables/cdms_file_tree.py b/cdatgui/variables/cdms_file_tree.py index dc23040..033e78f 100644 --- a/cdatgui/variables/cdms_file_tree.py +++ b/cdatgui/variables/cdms_file_tree.py @@ -28,7 +28,7 @@ def __init__(self, text, uri, parent=None): self.setText(1, text) self.setFont(1, label_font) self.setExpanded(True) - self.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled) + self.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled) class CDMSFileTree(QtGui.QTreeWidget): diff --git a/cdatgui/variables/manager.py b/cdatgui/variables/manager.py index d376c0b..5268f7b 100644 --- a/cdatgui/variables/manager.py +++ b/cdatgui/variables/manager.py @@ -1,5 +1,5 @@ import cdms2 -from cdatgui.persistence.db import get_data_sources, add_data_source +from cdatgui.persistence.db import get_data_sources, add_data_source, remove_data_source import cdatgui.cdat.metadata from PySide import QtCore @@ -55,3 +55,4 @@ def remove_file(self, file): if file.uri not in self.files: raise Exception("File not in manager.") del self.files[file.uri] + remove_data_source(file.uri) diff --git a/tests/mocks/PlotInfo.py b/tests/mocks/PlotInfo.py index 9fc7859..cd42bb0 100644 --- a/tests/mocks/PlotInfo.py +++ b/tests/mocks/PlotInfo.py @@ -1,2 +1,2 @@ import vcs -canvas = vcs.init() \ No newline at end of file +canvas = vcs.init() diff --git a/tests/test_GmDialog.py b/tests/test_GmDialog.py index 3df39b1..988c2e7 100644 --- a/tests/test_GmDialog.py +++ b/tests/test_GmDialog.py @@ -1,5 +1,5 @@ import pytest, vcs, cdms2, os -from cdatgui.graphics.dialog import GraphcisMethodDialog +from cdatgui.graphics.dialog import GraphicsMethodDialog from cdatgui.cdat.metadata import FileMetadataWrapper from cdatgui.editors import boxfill, isoline, cdat1d from PySide import QtCore, QtGui @@ -8,7 +8,7 @@ @pytest.fixture def boxfill_dialog(): s = get_var() - d = GraphcisMethodDialog(vcs.getboxfill('default'), s, vcs.createtemplate()) + d = GraphicsMethodDialog(vcs.getboxfill('default'), s, vcs.createtemplate()) d.createdGM.connect(saveAs) return d @@ -16,14 +16,14 @@ def boxfill_dialog(): @pytest.fixture def isoline_dialog(): s = get_var() - d = GraphcisMethodDialog(vcs.getisoline('default'), s, vcs.createtemplate()) + d = GraphicsMethodDialog(vcs.getisoline('default'), s, vcs.createtemplate()) return d @pytest.fixture def oned_dialog(): s = get_var() - d = GraphcisMethodDialog(vcs.get1d('default'), s, vcs.createtemplate()) + d = GraphicsMethodDialog(vcs.get1d('default'), s, vcs.createtemplate()) return d diff --git a/tests/test_LineEditor.py b/tests/test_LineEditor.py index d875a7e..20cf8b5 100644 --- a/tests/test_LineEditor.py +++ b/tests/test_LineEditor.py @@ -18,7 +18,7 @@ def test_type(qtbot, editor): editor.save() assert vcs.elements['line']['cyan'].type == ['dash'] - assert 'new' not in vcs.listelements('line') + assert editor.newline_name not in vcs.listelements('line') def test_color(qtbot, editor): @@ -33,7 +33,7 @@ def test_color(qtbot, editor): del vcs.elements['line']['check'] assert 'check' not in vcs.listelements('line') - assert 'new' not in vcs.listelements('line') + assert editor.newline_name not in vcs.listelements('line') def test_width(qtbot, editor): @@ -42,7 +42,7 @@ def test_width(qtbot, editor): editor.save() assert vcs.elements['line']['cyan'].width == [250] - assert 'new' not in vcs.listelements('line') + assert editor.newline_name not in vcs.listelements('line') get_lines().remove('check') - get_lines().remove('new') + get_lines().remove(editor.newline_name) diff --git a/tests/test_ProjectionEditor.py b/tests/test_ProjectionEditor.py index 6ea1523..75e0523 100644 --- a/tests/test_ProjectionEditor.py +++ b/tests/test_ProjectionEditor.py @@ -33,10 +33,10 @@ def test_changingNameAndType(qtbot, editor): assert vcs.elements['projection']['orthographic'] != orig_ortho assert vcs.elements['projection']['orthographic'].type == 'hotin oblique merc' - assert 'new' not in vcs.listelements('projection') + assert editor.newprojection_name not in vcs.listelements('projection') -def test_savAs(qtbot, editor): +def test_saveAs(qtbot, editor): orig_poly = vcs.elements['projection']['polyconic'] assert editor.vertical_layout.count() == 3 assert editor.proj_combo.currentText() == 'linear' @@ -54,11 +54,11 @@ def test_savAs(qtbot, editor): assert vcs.elements['projection']['polyconic'] == orig_poly assert 'test' in vcs.listelements('projection') - assert 'new' not in vcs.listelements('projection') + assert editor.newprojection_name not in vcs.listelements('projection') def test_close(qtbot, editor): - assert 'new' in vcs.listelements('projection') + assert editor.newprojection_name in vcs.listelements('projection') assert editor.cur_projection_name == 'linear' assert editor.object.type == 'linear' @@ -67,6 +67,24 @@ def test_close(qtbot, editor): assert editor.object.type == 'mollweide' editor.close() - assert 'new' not in vcs.listelements('projection') + assert editor.newprojection_name not in vcs.listelements('projection') assert vcs.getprojection('linear').name == 'linear' assert vcs.getprojection('linear').type == 'linear' + + +def test_settingAttributes(qtbot, editor): + old_proj_name = editor.gm.projection + editor.type_combo.setCurrentIndex(editor.type_combo.findText('robinson')) + editor.editors[0][0].setText('12') + + editor.save() + + old_proj = vcs.getprojection(old_proj_name) + assert old_proj.type == 'robinson' + assert old_proj.sphere == 12.0 + + new_editor = ProjectionEditor() + new_editor.setProjectionObject(old_proj) + new_editor.gm = editor.gm + assert new_editor.editors[0][0].text() == '12.0' + assert new_editor.editors[0][1] == 'sphere' diff --git a/tests/test_save_load.py b/tests/test_save_load.py index 6be43dc..883aa3f 100644 --- a/tests/test_save_load.py +++ b/tests/test_save_load.py @@ -1,6 +1,6 @@ import pytest # noqa from cdatgui.cdat.importer import import_script -from cdatgui.cdat.plotter import PlotManager +from cdatgui.cdat.plotter import PlotManager, PlotInfo from cdatgui.cdat.exporter import diff, export_script from cdatgui.cdat.metadata import VariableMetadataWrapper, FileMetadataWrapper import mocks @@ -28,14 +28,16 @@ def test_load_script(canvas): assert len(script.templates) == 3 -def test_save_and_load_script(tmpdir): +def test_save_and_load_script(tmpdir, qtbot): save_file = tmpdir.join("simple_vis.py") # File shouldn't exist assert save_file.exists() is False path = str(save_file.realpath()) - pm = PlotManager(mocks.PlotInfo) + pi = PlotInfo(vcs.init(), 0, 0) + qtbot.addWidget(pi) + pm = PlotManager(pi) pm.graphics_method = vcs.getboxfill("default") pm.template = vcs.gettemplate('default') @@ -44,7 +46,7 @@ def test_save_and_load_script(tmpdir): clt = fmw["clt"] pm.variables = [clt.var, None] - mocks.PlotInfo.canvas.close() + pi.canvas.close() export_script(path, [clt], [[pm]]) @@ -68,7 +70,7 @@ def test_save_and_load_script(tmpdir): assert len(obj.templates) == 1 -def test_save_loaded_script(tmpdir): +def test_save_loaded_script(tmpdir, qtbot): _ = vcs.init() dirpath = os.path.dirname(__file__) load_file = os.path.join(dirpath, "data", "clt_u_v_iso.py") @@ -85,7 +87,9 @@ def test_save_loaded_script(tmpdir): for display_group in canvas_displays: pm_group = [] for display in display_group: - pm = PlotManager(mocks.PlotInfo) + pi = PlotInfo(vcs.init(), 0, 0) + qtbot.addWidget(pi) + pm = PlotManager(pi) # Determine which of the graphics methods created in loaded gm = vcs.getgraphicsmethod(display.g_type, display.g_name) pm.graphics_method = closest(gm, loaded.graphics_methods) @@ -93,7 +97,6 @@ def test_save_loaded_script(tmpdir): pm.variables = display.array pm_group.append(pm) plot_managers.append(pm_group) - mocks.PlotInfo.canvas.close() export_script(str(save_file), loaded.variables.values(), plot_managers) diff --git a/tests/test_variables.py b/tests/test_variables.py index a5ade10..a9676fc 100644 --- a/tests/test_variables.py +++ b/tests/test_variables.py @@ -158,7 +158,7 @@ def test_add_dialog(qtbot, var_manager): def test_variable_widget(qtbot): - w = cdatgui.variables.VariableWidget() + w = cdatgui.variables.variable_widget.VariableWidget() qtbot.addWidget(w) w.add_dialog = mocks.VariableAddDialog From 563ebd0a06e224f7a96dd7bf0332a567c5595383 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Wed, 4 May 2016 15:57:11 -0700 Subject: [PATCH 18/29] added the edit gm editor for gm list --- cdatgui/graphics/dialog.py | 2 + cdatgui/graphics/graphics_method_widget.py | 104 ++++++++++++--------- cdatgui/graphics/vcs_gm_list.py | 6 ++ 3 files changed, 70 insertions(+), 42 deletions(-) diff --git a/cdatgui/graphics/dialog.py b/cdatgui/graphics/dialog.py index 66b2bba..9cb5713 100644 --- a/cdatgui/graphics/dialog.py +++ b/cdatgui/graphics/dialog.py @@ -45,6 +45,8 @@ def __init__(self, gm, var, tmpl, parent=None): self.gm = gm self.editor.gm = gm + self.setWindowTitle('Editing ' + self.gm.name) + layout.addWidget(self.editor) self.buttons = QtGui.QHBoxLayout() diff --git a/cdatgui/graphics/graphics_method_widget.py b/cdatgui/graphics/graphics_method_widget.py index 47243ae..7547a5d 100644 --- a/cdatgui/graphics/graphics_method_widget.py +++ b/cdatgui/graphics/graphics_method_widget.py @@ -30,13 +30,39 @@ def validate(self, inp, pos): return QtGui.QValidator.Acceptable +class EditGmDialog(GraphicsMethodOkDialog): + def __init__(self, gtype, ginstance): + self.gtype = gtype + self.ginstance = ginstance + f = cdms2.open(os.path.join(vcs.sample_data, 'clt.nc')) + f = FileMetadataWrapper(f) + var = f('clt') + + gm = vcs.creategraphicsmethod(str(gtype), str(ginstance)) + tmpl = vcs.createtemplate() + + self.edit_tmpl_name = tmpl.name + self.edit_gm_name = gm.name + super(EditGmDialog, self).__init__(gm, var, tmpl) + + self.rejected.connect(self.resetGM) + + def resetGM(self): + if self.edit_gm_name: + del vcs.elements[self.gtype][self.edit_gm_name] + self.edit_gm_name = None + + def resetTmpl(self): + if self.edit_tmpl_name: + del vcs.elements['template'][self.edit_tmpl_name] + self.edit_tmpl_name = None + + class CreateGM(ValidatingInputDialog): def __init__(self, currently_selected, parent=None): super(CreateGM, self).__init__() - self.edit_gm_name = None self.edit_dialog = None - self.edit_tmpl_name = None validator = NameValidator() self.setValidator(validator) @@ -84,10 +110,10 @@ def setGMRoot(self, index): self.edit.validator().validate(self.edit.text(), 0) def createGM(self): - if self.edit_gm_name: + if self.edit_dialog and self.edit_dialog.edit_gm_name: get_gms().add_gm( vcs.creategraphicsmethod(str(self.gm_type_combo.currentText()), - self.edit_gm_name, + self.edit_dialog.edit_gm_name, str(self.textValue()) )) del vcs.elements[self.gm_type_combo.currentText()][self.edit_gm_name] @@ -100,50 +126,20 @@ def createGM(self): )) def editGM(self): - f = cdms2.open(os.path.join(vcs.sample_data, 'clt.nc')) - f = FileMetadataWrapper(f) - s = f('clt') - - gm = vcs.creategraphicsmethod(str(self.gm_type_combo.currentText()), str(self.gm_instance_combo.currentText())) - tmpl = vcs.createtemplate() - - self.edit_tmpl_name = tmpl.name - self.edit_gm_name = gm.name - self.edit_dialog = GraphicsMethodOkDialog(gm, s, tmpl) - - # replace saveas and save with ok button - ''' - dialog_layout = self.edit_dialog.layout() - button_layout = dialog_layout.itemAt(dialog_layout.count() - 1).layout() - button_layout.takeAt(button_layout.count() - 1).widget().deleteLater() - button_layout.takeAt(button_layout.count() - 1).widget().deleteLater() - ok_button = QtGui.QPushButton('OK') - ok_button.clicked.connect(self.edit_dialog.accept) - button_layout.addWidget(ok_button) - ''' - - self.edit_dialog.rejected.connect(self.resetGM) + self.edit_dialog = EditGmDialog(self.gm_type_combo.currentText(), self.gm_instance_combo.currentText()) self.edit_dialog.show() self.edit_dialog.raise_() - def resetGM(self): - if self.edit_gm_name: - del vcs.elements[self.gm_type_combo.currentText()][self.edit_gm_name] - self.edit_gm_name = None - - def resetTmpl(self): - if self.edit_tmpl_name: - del vcs.elements['template'][self.edit_tmpl_name] - self.edit_tmpl_name = None - def save(self): - self.resetTmpl() + if self.edit_dialog: + self.edit_dialog.resetTmpl() super(CreateGM, self).save() def cancel(self): - self.resetTmpl() - self.resetGM() + if self.edit_dialog: + self.edit_dialog.resetTmpl() + self.edit_dialog.resetGM() super(CreateGM, self).cancel() @@ -156,15 +152,36 @@ def __init__(self, parent=None, flags=0): self.add_gm, self.edit_gm, self.remove_gm)) + + self.titleBarWidget().edit.setEnabled(False) self.list = GraphicsMethodList() + self.list.changedSelection.connect(self.selection_change) self.setWidget(self.list) self.add_gm_widget = None + self.edit_dialog = None + self.ginstance = None + self.gtype = None def selection_change(self): selected = self.list.get_selected() if selected is None: return - self.selectedGraphicsMethod.emit(selected) + if selected: + self.gtype = selected[0] + if len(selected) > 1: + self.ginstance = selected[1] + self.titleBarWidget().edit.setEnabled(True) + else: + self.titleBarWidget().edit.setEnabled(False) + return + if self.ginstance == 'default': + self.titleBarWidget().edit.setEnabled(False) + return + elif not self.ginstance: + self.titleBarWidget().edit.setEnabled(False) + return + + # self.selectedGraphicsMethod.emit(selected) def add_gm(self): self.add_gm_widget = CreateGM(self.list.get_selected()) @@ -172,7 +189,10 @@ def add_gm(self): self.add_gm_widget.raise_() def edit_gm(self): - pass + self.edit_dialog = EditGmDialog(self.gtype, self.ginstance) + + self.edit_dialog.show() + self.edit_dialog.raise_() def remove_gm(self): pass diff --git a/cdatgui/graphics/vcs_gm_list.py b/cdatgui/graphics/vcs_gm_list.py index 8a852f6..53a97f3 100644 --- a/cdatgui/graphics/vcs_gm_list.py +++ b/cdatgui/graphics/vcs_gm_list.py @@ -4,6 +4,8 @@ class GraphicsMethodList(QtGui.QTreeView): + changedSelection = QtCore.Signal() + def __init__(self, parent=None): super(GraphicsMethodList, self).__init__(parent=parent) self.setModel(get_gms()) @@ -20,3 +22,7 @@ def get_selected(self): return [selected.parent().data(), selected.data()] return None + + def selectionChanged(self, selected, deselected): + super(GraphicsMethodList, self).selectionChanged(selected, deselected) + self.changedSelection.emit() From 17229d106ec1fbc97eaaf8a377180a14e141b085 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Thu, 5 May 2016 16:16:53 -0700 Subject: [PATCH 19/29] fixed stupid segfault and added remove gm and fixed updating gm vars in console and plotter --- cdatgui/bases/input_dialog.py | 2 + cdatgui/cdat/plotter.py | 32 ++++++------ cdatgui/editors/model/vcsaxis.py | 1 - cdatgui/editors/projection_editor.py | 1 - cdatgui/graphics/graphics_method_widget.py | 32 ++++++++++-- cdatgui/graphics/models.py | 59 ++++++++++++++-------- cdatgui/graphics/vcs_gm_list.py | 2 +- cdatgui/main_window.py | 2 + cdatgui/sidebar/inspector_widget.py | 1 + cdatgui/spreadsheet/tab.py | 18 ++++++- cdatgui/spreadsheet/tabcontroller.py | 49 +++++++++--------- 11 files changed, 131 insertions(+), 68 deletions(-) diff --git a/cdatgui/bases/input_dialog.py b/cdatgui/bases/input_dialog.py index 03da402..3a686b4 100644 --- a/cdatgui/bases/input_dialog.py +++ b/cdatgui/bases/input_dialog.py @@ -54,6 +54,8 @@ def __init__(self): self.vertical_layout.insertLayout(0, edit_line_layout) + # self.edit.setFocus() + def setLabelText(self, text): self.label.setText(text) diff --git a/cdatgui/cdat/plotter.py b/cdatgui/cdat/plotter.py index 1e88da3..02a1085 100644 --- a/cdatgui/cdat/plotter.py +++ b/cdatgui/cdat/plotter.py @@ -124,6 +124,7 @@ def __init__(self, source): self._gm = None self._vars = None self._template = None + self._type = None def name(self): if self.can_plot() is False: @@ -141,13 +142,16 @@ def name(self): except AttributeError: vars.append(v.id) - gm_type = vcs.graphicsmethodtype(self._gm) + # gm_type = vcs.graphicsmethodtype(self.gm) + # gm_type = vcs.graphicsmethodtype(self.gm) vars = " x ".join(vars) - return "%s (%s)" % (vars, gm_type) + return "%s (%s)" % (vars, self._type) def load(self, display): self.dp = display - self._gm = vcs.getgraphicsmethod(display.g_type, display.g_name) + # self._gm = vcs.getgraphicsmethod(display.g_type, display.g_name) + self._gm = display.g_name + self._type = display.g_type self._vars = display.array self._template = vcs.gettemplate(display._template_origin) @@ -159,18 +163,14 @@ def canvas(self): return self.source.canvas def gm(self): - return self._gm + return vcs.getgraphicsmethod(self._type, self._gm) - def set_gm(self, args): - """If args is a tuple, assume they are passing in False. Tuple used to designate do not plot""" - # check gm vs vars - if isinstance(args, tuple): - self._gm = args[0] - else: - self._gm = args - if self.can_plot(): - self.plot() - self.source.gm_label.setText(self._gm.name) + def set_gm(self, gm): + self._gm = gm.name + self._type = vcs.graphicsmethodtype(gm) + if self.can_plot(): + self.plot() + self.source.gm_label.setText(self._gm) graphics_method = property(gm, set_gm) @@ -264,4 +264,6 @@ def plot(self): if self.template is None: self._template = vcs.gettemplate(self.dp._template_origin) if self.graphics_method is None: - self._gm = vcs.getgraphicsmethod(self.dp.g_type, self.dp.g_name) + # self._gm = vcs.getgraphicsmethod(self.dp.g_type, self.dp.g_name) + self._gm = self.dp.g_name + self._type = self.dp.g_type diff --git a/cdatgui/editors/model/vcsaxis.py b/cdatgui/editors/model/vcsaxis.py index c5e3fd8..ba9c5cf 100644 --- a/cdatgui/editors/model/vcsaxis.py +++ b/cdatgui/editors/model/vcsaxis.py @@ -121,7 +121,6 @@ def step(self): ticks = vcs.elements["list"][ticks] ticks = sorted(ticks) left, right = vcs.minmax(self.axis) - print "STEP", right, left, len(ticks) return (right - left) / (len(ticks) - 1) # pretty sure this need to be - @step.setter diff --git a/cdatgui/editors/projection_editor.py b/cdatgui/editors/projection_editor.py index f8049d2..e295e03 100644 --- a/cdatgui/editors/projection_editor.py +++ b/cdatgui/editors/projection_editor.py @@ -179,7 +179,6 @@ def savingNewProjection(self, name): vcs.elements['projection'].pop(self.cur_projection_name) vcs.createprojection(self.cur_projection_name, self.object) name = self.cur_projection_name - c_obj = vcs.elements['projection'][name] else: if name in vcs.listelements('projection'): del vcs.elements['projection'][name] diff --git a/cdatgui/graphics/graphics_method_widget.py b/cdatgui/graphics/graphics_method_widget.py index 7547a5d..bd0d333 100644 --- a/cdatgui/graphics/graphics_method_widget.py +++ b/cdatgui/graphics/graphics_method_widget.py @@ -45,7 +45,12 @@ def __init__(self, gtype, ginstance): self.edit_gm_name = gm.name super(EditGmDialog, self).__init__(gm, var, tmpl) + self.setWindowTitle('Editing ' + self.ginstance) + self.rejected.connect(self.resetGM) + self.rejected.connect(self.resetTmpl) + + self.accepted.connect(self.createGM) def resetGM(self): if self.edit_gm_name: @@ -57,6 +62,18 @@ def resetTmpl(self): del vcs.elements['template'][self.edit_tmpl_name] self.edit_tmpl_name = None + def createGM(self): + print "deleting", self.gtype, self.ginstance + cur_index = get_gms().indexOf(self.gtype, vcs.getgraphicsmethod(self.gtype, self.ginstance)) + del vcs.elements[self.gtype][self.ginstance] + if self.edit_gm_name: + print "creating gm type {0} from {1} with name {2}".format(self.gtype, self.edit_gm_name, self.ginstance) + gm = vcs.creategraphicsmethod(self.gtype, self.edit_gm_name, self.ginstance) + get_gms().replace(cur_index, gm) + #import pdb; pdb.set_trace() + self.resetTmpl() + self.resetGM() + class CreateGM(ValidatingInputDialog): def __init__(self, currently_selected, parent=None): @@ -144,6 +161,8 @@ def cancel(self): class GraphicsMethodWidget(StaticDockWidget): + editedGM = QtCore.Signal() + def __init__(self, parent=None, flags=0): super(GraphicsMethodWidget, self).__init__("Graphics Methods", parent=parent, flags=flags) self.allowed_sides = [QtCore.Qt.DockWidgetArea.LeftDockWidgetArea] @@ -154,6 +173,7 @@ def __init__(self, parent=None, flags=0): self.remove_gm)) self.titleBarWidget().edit.setEnabled(False) + self.titleBarWidget().remove.setEnabled(False) self.list = GraphicsMethodList() self.list.changedSelection.connect(self.selection_change) self.setWidget(self.list) @@ -164,6 +184,7 @@ def __init__(self, parent=None, flags=0): def selection_change(self): selected = self.list.get_selected() + self.ginstance = None if selected is None: return if selected: @@ -171,18 +192,20 @@ def selection_change(self): if len(selected) > 1: self.ginstance = selected[1] self.titleBarWidget().edit.setEnabled(True) + self.titleBarWidget().remove.setEnabled(True) else: self.titleBarWidget().edit.setEnabled(False) + self.titleBarWidget().remove.setEnabled(False) return if self.ginstance == 'default': self.titleBarWidget().edit.setEnabled(False) + self.titleBarWidget().remove.setEnabled(False) return elif not self.ginstance: self.titleBarWidget().edit.setEnabled(False) + self.titleBarWidget().remove.setEnabled(False) return - # self.selectedGraphicsMethod.emit(selected) - def add_gm(self): self.add_gm_widget = CreateGM(self.list.get_selected()) self.add_gm_widget.show() @@ -190,9 +213,10 @@ def add_gm(self): def edit_gm(self): self.edit_dialog = EditGmDialog(self.gtype, self.ginstance) - + self.edit_dialog.accepted.connect(self.editedGM.emit) self.edit_dialog.show() self.edit_dialog.raise_() def remove_gm(self): - pass + model_index = get_gms().indexOf(self.gtype, vcs.getgraphicsmethod(self.gtype, self.ginstance)) + get_gms().removeRows(model_index.row(), 1, parent=model_index.parent()) diff --git a/cdatgui/graphics/models.py b/cdatgui/graphics/models.py index e9abbb4..d6f8c3a 100644 --- a/cdatgui/graphics/models.py +++ b/cdatgui/graphics/models.py @@ -10,11 +10,22 @@ def __init__(self, parent=None): self.gm_types = sorted(vcs.graphicsmethodlist()) self.gms = {gmtype: [el for el in vcs.elements[gmtype].values() if el.name[:1] != "__"] for gmtype in vcs.graphicsmethodlist()} + self.next_id = 0 + self.keys = {} def add_gm(self, gm): parent_row = self.gm_types.index(vcs.graphicsmethodtype(gm)) self.insertRows(self.rowCount(), 1, [gm], self.index(parent_row, 0)) + def removeRows(self, row, count, parent=QtCore.QModelIndex()): + if not parent.isValid(): + # Can't remove graphics method types + return False + self.beginRemoveRows(parent, row, row + count - 1) + del self.gms[self.gm_types[parent.row()]][row:row + count] + self.endRemoveRows() + return True + def indexOf(self, gmtype, gm): parent = self.gm_types.index(gmtype) actual = self.gms[gmtype].index(gm) @@ -45,24 +56,31 @@ def get_dropped(self, md): def index(self, row, col, parent=QtCore.QModelIndex()): if parent.isValid(): - # Grab the child of parent - gm_type = self.gm_types[parent.row()] - pointer = self.gms[gm_type][row] + key = (parent.row(), row) else: - pointer = self.gm_types[row] - - return self.createIndex(row, col, pointer) + key = (row, None) + if key in self.keys: + internalid = self.keys[key] + else: + internalid = self.next_id + self.keys[key] = internalid + self.next_id += 1 + return self.createIndex(row, col, internalid) def parent(self, qmi): - if qmi.internalPointer() in self.gm_types: - # Root level item, no work required + if not qmi.isValid(): return QtCore.QModelIndex() - for ind, gtype in enumerate(self.gm_types): - if qmi.internalPointer() in self.gms[gtype]: - return self.index(ind, 0) + for key in self.keys: + if qmi.internalId() == self.keys[key]: + break + else: + return QtCore.QModelIndex() - return QtCore.QModelIndex() + if key[1] is None: + return QtCore.QModelIndex() + else: + return self.index(key[0], 0) def columnCount(self, qmi=QtCore.QModelIndex()): return 1 @@ -86,14 +104,15 @@ def rowCount(self, modelIndex=QtCore.QModelIndex()): def data(self, index, role=QtCore.Qt.DisplayRole): if role != QtCore.Qt.DisplayRole: return None - parent = index.parent() - if parent.isValid(): - # index is a GM - gtype = parent.internalPointer() - gm = self.gms[gtype][index.row()] - return unicode(gm.name) - else: - return unicode(self.gm_types[index.row()]) + + for key in self.keys: + if self.keys[key] == index.internalId(): + break + gm_type = self.gm_types[key[0]] + if key[1] is None: + return unicode(gm_type) + gm = self.gms[gm_type][key[1]] + return unicode(gm.name) def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole): return u"Graphics Method" diff --git a/cdatgui/graphics/vcs_gm_list.py b/cdatgui/graphics/vcs_gm_list.py index 53a97f3..dc3fedc 100644 --- a/cdatgui/graphics/vcs_gm_list.py +++ b/cdatgui/graphics/vcs_gm_list.py @@ -15,7 +15,7 @@ def __init__(self, parent=None): def get_selected(self): items = self.selectedIndexes() - + print 'get_selected' for selected in items: if not selected.parent().isValid(): return [selected.data()] diff --git a/cdatgui/main_window.py b/cdatgui/main_window.py index a325f1e..70c413d 100644 --- a/cdatgui/main_window.py +++ b/cdatgui/main_window.py @@ -23,9 +23,11 @@ def __init__(self, parent=None, f=QtCore.Qt.WindowFlags()): self.add_left_dock(var_widget) gm_widget = GraphicsMethodWidget(parent=self) + gm_widget.editedGM.connect(self.spreadsheet.tabController.currentWidget().replotPlottersUpdateVars) self.add_left_dock(gm_widget) tmpl_widget = TemplateWidget(parent=self) + # tmpl_widget.editedTmpl.connect(self.spreadsheet.tabController.currentWidget().totalPlotsChanged) self.add_left_dock(tmpl_widget) inspector = InspectorWidget(self.spreadsheet, parent=self) diff --git a/cdatgui/sidebar/inspector_widget.py b/cdatgui/sidebar/inspector_widget.py index aa7f2a6..2e76cfa 100644 --- a/cdatgui/sidebar/inspector_widget.py +++ b/cdatgui/sidebar/inspector_widget.py @@ -182,6 +182,7 @@ def editGM(self): gm_name = self.gm_instance_combo.currentText() gm = vcs.getgraphicsmethod(gm_type, gm_name) + print "GOT GM", gm if self.gm_editor: self.gm_editor.close() self.gm_editor.deleteLater() diff --git a/cdatgui/spreadsheet/tab.py b/cdatgui/spreadsheet/tab.py index 2b087ed..bf9a555 100755 --- a/cdatgui/spreadsheet/tab.py +++ b/cdatgui/spreadsheet/tab.py @@ -492,7 +492,6 @@ def createContainers(self): widget = QCDATWidget(r, c) widget.plotAdded.connect(self.selectionChange) widget.emitAllPlots.connect(self.totalPlotsChanged) - # widget.emitAllPlots.connect(self.totalPlotsChanged) cellWidget = QCellContainer(widget) self.setCellByWidget(r, c, cellWidget) @@ -538,6 +537,22 @@ def colSpinBoxChanged(self): self.createContainers() self.totalPlotsChanged() + def replotPlottersUpdateVars(self): + total_tabs = [] + plots = [] + for row in range(self.toolBar.rowSpinBox.value()): + for col in range(self.toolBar.colSpinBox.value()): + total_tabs.append(self.sheet.cellWidget(row, col)) + for cell in total_tabs: + cell = cell.containedWidget + # cell is now a QCDATWidget + plotter = cell.getPlotters() + plots.extend(plotter) + for plot in plots: + if plot.can_plot(): + plot.plot() + self.emitAllPlots.emit(total_tabs) + def totalPlotsChanged(self): total_tabs = [] for row in range(self.toolBar.rowSpinBox.value()): @@ -546,7 +561,6 @@ def totalPlotsChanged(self): self.emitAllPlots.emit(total_tabs) ### Belows are API Wrappers to connect to self.sheet - def getDimension(self): """ getDimension() -> tuple Get the sheet dimensions diff --git a/cdatgui/spreadsheet/tabcontroller.py b/cdatgui/spreadsheet/tabcontroller.py index 0f0242a..0691d34 100755 --- a/cdatgui/spreadsheet/tabcontroller.py +++ b/cdatgui/spreadsheet/tabcontroller.py @@ -82,12 +82,11 @@ def __init__(self, parent=None): self.tabBar().tabTextChanged.connect(self.changeTabText) self.addAction(self.showNextTabAction()) self.addAction(self.showPrevTabAction()) - self.executedPipelines = [[],{},{}] + self.executedPipelines = [[], {}, {}] self.monitoredPipelines = {} self.spreadsheetFileName = None self.tabCloseRequested.connect(self.delete_sheet_by_index) - def create_first_sheet(self): self.addTabWidget(StandardWidgetSheetTab(self), 'Sheet 1') @@ -202,11 +201,13 @@ def uvcdatPreferencesAction(self): themeMenu = prefMenu.addMenu("Icons Theme") defaultThemeAction = themeMenu.addAction("Default") defaultThemeAction.setCheckable(True) - defaultThemeAction.setStatusTip("Use the default theme (the application must be restarted for changes to take effect)") + defaultThemeAction.setStatusTip( + "Use the default theme (the application must be restarted for changes to take effect)") minimalThemeAction = themeMenu.addAction("Minimal") minimalThemeAction.setCheckable(True) - minimalThemeAction.setStatusTip("Use the minimal theme (the application must be restarted for changes to take effect)") + minimalThemeAction.setStatusTip( + "Use the minimal theme (the application must be restarted for changes to take effect)") themegroup = QtGui.QActionGroup(self) themegroup.addAction(defaultThemeAction) themegroup.addAction(minimalThemeAction) @@ -284,7 +285,7 @@ def newSheetActionTriggered(self, checked=False): """ self.setCurrentIndex(self.addTabWidget(StandardWidgetSheetTab(self), - 'Sheet %d' % (self.count()+1))) + 'Sheet %d' % (self.count() + 1))) self.currentWidget().sheet.stretchCells() def tabInserted(self, index): @@ -314,7 +315,7 @@ def deleteSheetActionTriggered(self, checked=False): Actual code to delete the current sheet """ - if self.count()>0: + if self.count() > 0: widget = self.currentWidget() self.tabWidgets.remove(widget) self.removeTab(self.currentIndex()) @@ -328,7 +329,7 @@ def clearTabs(self): Clear and reset the controller """ - while self.count()>0: + while self.count() > 0: self.deleteSheetActionTriggered() for i in reversed(range(len(self.tabWidgets))): t = self.tabWidgets[i] @@ -344,7 +345,7 @@ def insertTab(self, idx, tabWidget, tabText): QTabWidget or a QStackedWidget """ - if self.operatingWidget!=self: + if self.operatingWidget != self: ret = self.operatingWidget.insertWidget(idx, tabWidget) self.operatingWidget.setCurrentIndex(ret) return ret @@ -379,14 +380,14 @@ def moveTab(self, tabIdx, destination): Move a tab at tabIdx to a different position at destination """ - if (tabIdx<0 or tabIdx>self.count() or - destination<0 or destination>self.count()): + if (tabIdx < 0 or tabIdx > self.count() or + destination < 0 or destination > self.count()): return tabText = self.tabText(tabIdx) tabWidget = self.widget(tabIdx) self.removeTab(tabIdx) self.insertTab(destination, tabWidget, tabText) - if tabIdx==self.currentIndex(): + if tabIdx == self.currentIndex(): self.setCurrentIndex(destination) def splitTab(self, tabIdx, pos=None): @@ -394,7 +395,7 @@ def splitTab(self, tabIdx, pos=None): Split a tab to be a stand alone window and move to position pos """ - if tabIdx<0 or tabIdx>self.count() or self.count()==0: + if tabIdx < 0 or tabIdx > self.count() or self.count() == 0: return tabWidget = self.widget(tabIdx) self.removeTab(tabIdx) @@ -411,9 +412,9 @@ def mergeTab(self, frame, tabIdx): Merge a tab dock widget back to the controller at position tabIdx """ - if tabIdx<0 or tabIdx>self.count(): + if tabIdx < 0 or tabIdx > self.count(): return - if tabIdx==self.count(): tabIdx = -1 + if tabIdx == self.count(): tabIdx = -1 tabWidget = frame.widget() frame.setWidget(None) while frame in self.floatingTabWidgets: @@ -437,8 +438,8 @@ def insertTabWidget(self, index, tabWidget, sheetLabel): Insert a tab widget to the controller at some location """ - if sheetLabel==None: - sheetLabel = 'Sheet %d' % (len(self.tabWidgets)+1) + if sheetLabel == None: + sheetLabel = 'Sheet %d' % (len(self.tabWidgets) + 1) if not tabWidget in self.tabWidgets: self.tabWidgets.append(tabWidget) tabWidget.setWindowTitle(sheetLabel) @@ -454,7 +455,7 @@ def tabWidgetUnderMouse(self): if t.underMouse(): result = t else: - t.showHelpers(False, QtCore.QPoint(-1,-1)) + t.showHelpers(False, QtCore.QPoint(-1, -1)) return result def showNextTab(self): @@ -462,8 +463,8 @@ def showNextTab(self): Bring the next tab up """ - if self.operatingWidget.currentIndex()0: - index = self.operatingWidget.currentIndex()-1 + if self.operatingWidget.currentIndex() > 0: + index = self.operatingWidget.currentIndex() - 1 self.operatingWidget.setCurrentIndex(index) def tabPopupMenu(self): @@ -481,10 +482,10 @@ def tabPopupMenu(self): """ menu = QtGui.QMenu(self) - en = self.operatingWidget.currentIndex()0 + en = self.operatingWidget.currentIndex() > 0 self.showPrevTabAction().setEnabled(en) menu.addAction(self.showPrevTabAction()) menu.addSeparator() @@ -492,7 +493,7 @@ def tabPopupMenu(self): t = self.operatingWidget.widget(idx) action = menu.addAction(t.windowTitle()) action.setData(idx) - if t==self.operatingWidget.currentWidget(): + if t == self.operatingWidget.currentWidget(): action.setIcon(QtGui.QIcon(':/images/ok.png')) return menu From 0e340818ca20636be395cc8ccc4ff157237024cd Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Fri, 6 May 2016 10:43:33 -0700 Subject: [PATCH 20/29] added remove var functionality and import file functionality --- cdatgui/bases/input_dialog.py | 2 +- cdatgui/bases/list_model.py | 5 ++-- cdatgui/editors/projection_editor.py | 33 ++++------------------ cdatgui/graphics/graphics_method_widget.py | 3 -- cdatgui/graphics/vcs_gm_list.py | 1 - cdatgui/variables/cdms_file_tree.py | 25 +++++++++++----- cdatgui/variables/cdms_var_list.py | 3 +- cdatgui/variables/variable_widget.py | 26 ++++++++++++++--- 8 files changed, 52 insertions(+), 46 deletions(-) diff --git a/cdatgui/bases/input_dialog.py b/cdatgui/bases/input_dialog.py index 3a686b4..efa8beb 100644 --- a/cdatgui/bases/input_dialog.py +++ b/cdatgui/bases/input_dialog.py @@ -54,7 +54,7 @@ def __init__(self): self.vertical_layout.insertLayout(0, edit_line_layout) - # self.edit.setFocus() + self.edit.setFocus() def setLabelText(self, text): self.label.setText(text) diff --git a/cdatgui/bases/list_model.py b/cdatgui/bases/list_model.py index f183aea..5dc8377 100644 --- a/cdatgui/bases/list_model.py +++ b/cdatgui/bases/list_model.py @@ -29,7 +29,7 @@ def replace(self, index, value): self.dataChanged.emit(ind, ind) def remove(self, ind): - self.removeRows(ind, 1) + return self.removeRows(ind, 1) def clear(self): self.removeRows(0, len(self.values)) @@ -40,9 +40,10 @@ def insertRows(self, row, count, values, parent=QtCore.QModelIndex()): self.endInsertRows() def removeRows(self, row, count, parent=QtCore.QModelIndex()): - self.beginRemoveRows(parent, row, row + count) + self.beginRemoveRows(parent, row, row + count - 1) self.values = self.values[:row] + self.values[row + count:] self.endRemoveRows() + return True def rowCount(self, modelIndex=None): return len(self.values) diff --git a/cdatgui/editors/projection_editor.py b/cdatgui/editors/projection_editor.py index e295e03..0f3ea3e 100644 --- a/cdatgui/editors/projection_editor.py +++ b/cdatgui/editors/projection_editor.py @@ -27,17 +27,12 @@ def __init__(self): types = ["linear", "utm", "state plane", - "albers equal area", "albers", - "lambert", + "albers equal area", "lambert conformal c", - "lambert conformal conic", "mercator", - "polar", "polar stereographic", "polyconic", - "equid conic a", "equid conic", - "equid conic b", "transverse mercator", "stereographic", "lambert azimuthal", @@ -45,39 +40,23 @@ def __init__(self): "gnomonic", "orthographic", "gen. vert. near per", - "gen vert near per", "sinusoidal", "equirectangular", - "miller", "miller cylindrical", "van der grinten", - "hotin", - "hotin oblique", "hotin oblique merc", - "hotin oblique merc a", - "hotin oblique merc b", - "hotin oblique mercator", - "hotin oblique mercator a", - "hotin oblique mercator b", "robinson", - "space oblique", "space oblique merc", - "space oblique merc a", - "space oblique merc b", - "alaska", "alaska conformal", - "interrupted goode", "goode", + "alaska conformal", + "interrupted goode", "mollweide", - "interrupted mollweide", "interrupt mollweide", "hammer", "wagner iv", - "wagner 4", - "wagner4", "wagner vii", - "wagner 7", - "wagner7", - "oblated", - "oblated equal area"] + "oblated equal area" + ] + self.type_combo = QtGui.QComboBox() self.type_combo.addItems(types) self.type_combo.currentIndexChanged[str].connect(self.updateProjectionType) diff --git a/cdatgui/graphics/graphics_method_widget.py b/cdatgui/graphics/graphics_method_widget.py index bd0d333..3555cef 100644 --- a/cdatgui/graphics/graphics_method_widget.py +++ b/cdatgui/graphics/graphics_method_widget.py @@ -63,14 +63,11 @@ def resetTmpl(self): self.edit_tmpl_name = None def createGM(self): - print "deleting", self.gtype, self.ginstance cur_index = get_gms().indexOf(self.gtype, vcs.getgraphicsmethod(self.gtype, self.ginstance)) del vcs.elements[self.gtype][self.ginstance] if self.edit_gm_name: - print "creating gm type {0} from {1} with name {2}".format(self.gtype, self.edit_gm_name, self.ginstance) gm = vcs.creategraphicsmethod(self.gtype, self.edit_gm_name, self.ginstance) get_gms().replace(cur_index, gm) - #import pdb; pdb.set_trace() self.resetTmpl() self.resetGM() diff --git a/cdatgui/graphics/vcs_gm_list.py b/cdatgui/graphics/vcs_gm_list.py index dc3fedc..cb258c8 100644 --- a/cdatgui/graphics/vcs_gm_list.py +++ b/cdatgui/graphics/vcs_gm_list.py @@ -15,7 +15,6 @@ def __init__(self, parent=None): def get_selected(self): items = self.selectedIndexes() - print 'get_selected' for selected in items: if not selected.parent().isValid(): return [selected.data()] diff --git a/cdatgui/variables/cdms_file_tree.py b/cdatgui/variables/cdms_file_tree.py index 033e78f..1fc6e9e 100644 --- a/cdatgui/variables/cdms_file_tree.py +++ b/cdatgui/variables/cdms_file_tree.py @@ -1,5 +1,7 @@ from PySide import QtGui, QtCore import os.path +from collections import OrderedDict + from cdatgui.utils import icon import urlparse @@ -66,11 +68,20 @@ def add_file(self, cdmsfile): def get_selected(self): items = self.selectedItems() - variables = [] + variables = OrderedDict() for item in items: - var_name = item.text(1) - file_index = self.indexOfTopLevelItem(item.parent()) - cdmsfile = self.files_ordered[file_index] - variables.append(cdmsfile(var_name)) - - return variables + new_vars = [] + if isinstance(item, CDMSFileItem): + for index in range(item.childCount()): + new_vars.append(item.child(index)) + else: + new_vars.append(item) + for var in new_vars: + var_name = var.text(1) + file_index = self.indexOfTopLevelItem(var.parent()) + cdmsfile = self.files_ordered[file_index] + var_meta_item = cdmsfile(var_name) + if var.text(1) not in variables.values(): + variables[var_meta_item] = var.text(1) + + return variables.keys() diff --git a/cdatgui/variables/cdms_var_list.py b/cdatgui/variables/cdms_var_list.py index 76f5a6f..ad9ec15 100644 --- a/cdatgui/variables/cdms_var_list.py +++ b/cdatgui/variables/cdms_var_list.py @@ -24,7 +24,8 @@ def remove_variable(self, variable): break else: raise ValueError("Variable %s not in Variable List" % (variable.id)) - self.model().remove_variable(ind) + res = self.model().remove_variable(ind) + return res def add_variable(self, cdmsvar): self.model().add_variable(cdmsvar) diff --git a/cdatgui/variables/variable_widget.py b/cdatgui/variables/variable_widget.py index bf01686..1aff9dd 100644 --- a/cdatgui/variables/variable_widget.py +++ b/cdatgui/variables/variable_widget.py @@ -1,7 +1,7 @@ from functools import partial from cdatgui.bases import StaticDockWidget -from PySide import QtCore +from PySide import QtCore, QtGui from cdatgui.toolbars import AddEditRemoveToolbar from variable_add import AddDialog from cdms_var_list import CDMSVariableList @@ -9,7 +9,6 @@ class VariableWidget(StaticDockWidget): - selectedVariable = QtCore.Signal(object) def __init__(self, parent=None, flags=0): @@ -55,5 +54,24 @@ def edit_variable(self): e.show() def remove_variable(self): - # Confirm removal dialog - pass # pragma: nocover + indices = self.variable_widget.selectedIndexes() + indices = sorted(indices, key=lambda x: x.row()) + if len(indices) < 1: + return + names = [] + for index in indices: + names.append(index.data()) + if len(names) > 1: + var_text = 'variables' + else: + var_text = 'variable' + var_name_text = "" + for name in names: + var_name_text += name + ", " + var_name_text = var_name_text[:-2] + answer = QtGui.QMessageBox.question(self, "Confirmation", + "Are you sure you want to delete {0} {1}?".format(var_text, var_name_text), + buttons=QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) + if answer == QtGui.QMessageBox.StandardButton.Ok: + for count, index in enumerate(indices): + self.variable_widget.remove_variable(index.row() - count) From 3af2e13ab9b8334f2b05ed1ab379960c33f5c925 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Fri, 6 May 2016 14:54:07 -0700 Subject: [PATCH 21/29] add, edit, and remove functionality works for template. Fixed small bugs in template dialog and implemented use of vcs elements dialog --- cdatgui/bases/vcs_elements_dialog.py | 1 + cdatgui/graphics/models.py | 2 +- cdatgui/main_window.py | 2 +- cdatgui/sidebar/inspector_widget.py | 21 ++++-------- cdatgui/templates/dialog.py | 44 ++++++++++++++++++++---- cdatgui/templates/models.py | 17 ++++++++-- cdatgui/templates/template_list.py | 20 +++++++++-- cdatgui/templates/template_widget.py | 51 ++++++++++++++++++++++++---- 8 files changed, 123 insertions(+), 35 deletions(-) diff --git a/cdatgui/bases/vcs_elements_dialog.py b/cdatgui/bases/vcs_elements_dialog.py index 2db71ed..850812c 100644 --- a/cdatgui/bases/vcs_elements_dialog.py +++ b/cdatgui/bases/vcs_elements_dialog.py @@ -7,6 +7,7 @@ class VcsElementsDialog(ValidatingInputDialog): def __init__(self, element): super(VcsElementsDialog, self).__init__() self.element = element + self.setValidator(VcsElementsValidator()) def save(self): if self.textValue() in vcs.elements[self.element]: diff --git a/cdatgui/graphics/models.py b/cdatgui/graphics/models.py index d6f8c3a..9bca3f8 100644 --- a/cdatgui/graphics/models.py +++ b/cdatgui/graphics/models.py @@ -90,7 +90,7 @@ def insertRows(self, row, count, gms, parent=QtCore.QModelIndex()): raise ValueError("Can't insert new Graphics Method Types") parent_name = self.data(parent) - self.beginInsertRows(parent, row, row + count) + self.beginInsertRows(parent, row, row + count - 1) self.gms[parent_name] = self.gms[parent_name][:row] + gms + self.gms[parent_name][row:] self.endInsertRows() diff --git a/cdatgui/main_window.py b/cdatgui/main_window.py index 70c413d..9590b48 100644 --- a/cdatgui/main_window.py +++ b/cdatgui/main_window.py @@ -27,7 +27,7 @@ def __init__(self, parent=None, f=QtCore.Qt.WindowFlags()): self.add_left_dock(gm_widget) tmpl_widget = TemplateWidget(parent=self) - # tmpl_widget.editedTmpl.connect(self.spreadsheet.tabController.currentWidget().totalPlotsChanged) + tmpl_widget.editedTmpl.connect(self.spreadsheet.tabController.currentWidget().replotPlottersUpdateVars) self.add_left_dock(tmpl_widget) inspector = InspectorWidget(self.spreadsheet, parent=self) diff --git a/cdatgui/sidebar/inspector_widget.py b/cdatgui/sidebar/inspector_widget.py index 2e76cfa..c0136e5 100644 --- a/cdatgui/sidebar/inspector_widget.py +++ b/cdatgui/sidebar/inspector_widget.py @@ -65,7 +65,7 @@ def __init__(self, spreadsheet, parent=None): super(InspectorWidget, self).__init__("Inspector", parent=parent) self.allowed_sides = [QtCore.Qt.DockWidgetArea.RightDockWidgetArea] spreadsheet.selectionChanged.connect(self.selection_change) - self.plotters_updated.connect(spreadsheet.tabController.currentWidget().totalPlotsChanged) + self.plotters_updated.connect(spreadsheet.tabController.currentWidget().replotPlottersUpdateVars) self.cells = [] self.current_plot = None self.plots = PlotterListModel() @@ -182,7 +182,6 @@ def editGM(self): gm_name = self.gm_instance_combo.currentText() gm = vcs.getgraphicsmethod(gm_type, gm_name) - print "GOT GM", gm if self.gm_editor: self.gm_editor.close() self.gm_editor.deleteLater() @@ -192,24 +191,16 @@ def editGM(self): self.gm_editor.show() self.gm_editor.raise_() - def makeTmpl(self, template): - get_templates().add_template(template) - - def editTmpl(self, template): - ind = get_templates().indexOf(template) - if ind.isValid(): - get_templates.replace(ind.row(), template) - def editTemplate(self, tmpl): - if self.tmpl_editor: - self.tmpl_editor.reject() - self.tmpl_editor.deleteLater() self.tmpl_editor = TemplateEditorDialog(tmpl) - self.tmpl_editor.createdTemplate.connect(self.makeTmpl) - self.tmpl_editor.editedTemplate.connect(self.editTmpl) + self.tmpl_editor.doneEditing.connect(self.setTemplateCombo) self.tmpl_editor.show() self.tmpl_editor.raise_() + def setTemplateCombo(self, tmpl_name): + self.template_combo.setCurrentIndex(self.template_combo.findText(tmpl_name)) + self.plotters_updated.emit() + def deletePlot(self, plot): ind = self.plot_combo.currentIndex() self.plots.remove(ind) diff --git a/cdatgui/templates/dialog.py b/cdatgui/templates/dialog.py index ee8c000..977a08b 100644 --- a/cdatgui/templates/dialog.py +++ b/cdatgui/templates/dialog.py @@ -2,6 +2,9 @@ from cdatgui.editors.template import TemplateEditor import vcs import copy +from cdatgui.bases.vcs_elements_dialog import VcsElementsDialog + +from cdatgui.templates import get_templates def sync_template(self, src): @@ -60,11 +63,13 @@ def sync_template(self, src): class TemplateEditorDialog(QtGui.QDialog): - createdTemplate = QtCore.Signal(object) - editedTemplate = QtCore.Signal(object) + doneEditing = QtCore.Signal(str) def __init__(self, tmpl, parent=None): super(TemplateEditorDialog, self).__init__(parent=parent) + self.setWindowModality(QtCore.Qt.ApplicationModal) + shortcut = QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Escape), self) + shortcut.activated.connect(self.close) self.real_tmpl = tmpl self.tmpl = vcs.createtemplate(source=tmpl) l = QtGui.QVBoxLayout() @@ -91,15 +96,40 @@ def __init__(self, tmpl, parent=None): l.addLayout(buttons) self.setLayout(l) + self.dialog = None def customName(self): - name = QtGui.QInputDialog.getText(self, u"Save As", u"Name for template:") - self.save(name) + # name = QtGui.QInputDialog.getText(self, u"Save As", u"Name for template:") + self.dialog = VcsElementsDialog('template') + self.dialog.setLabelText('Name:') + self.dialog.setWindowTitle('Save As') + + self.dialog.accepted.connect(self.grabName) + self.dialog.show() + self.dialog.raise_() + + def grabName(self): + self.save(self.dialog.textValue()) def save(self, name=None): if name is None: sync_template(self.real_tmpl, self.tmpl) - self.editedTemplate.emit(self.real_tmpl) + self.editTmpl(self.real_tmpl) + name = self.real_tmpl.name else: - template = vcs.createtemplate(name, self.tmpl.name) - self.createdTemplate.emit(template) + if name in vcs.listelements('template'): + del vcs.elements['template'][name] + template = vcs.createtemplate(str(name), self.tmpl.name) + self.makeTmpl(template) + + self.doneEditing.emit(name) + self.close() + + def editTmpl(self, template): + ind = get_templates().indexOf(template) + if ind.isValid(): + get_templates().replace(ind.row(), template) + + def makeTmpl(self, template): + get_templates().add_template(template) + diff --git a/cdatgui/templates/models.py b/cdatgui/templates/models.py index 41a26c2..bfc57f5 100644 --- a/cdatgui/templates/models.py +++ b/cdatgui/templates/models.py @@ -10,7 +10,8 @@ class VCSTemplateListModel(QtCore.QAbstractListModel): def __init__(self, tmpl_filter=None, parent=None): super(VCSTemplateListModel, self).__init__(parent=parent) if tmpl_filter is not None: - self.templates = [template for template in vcs.elements["template"].values() if tmpl_filter.search(template.name) is None] + self.templates = [template for template in vcs.elements["template"].values() if + tmpl_filter.search(template.name) is None] else: self.templates = vcs.elements["template"].values() @@ -23,6 +24,13 @@ def template_key(tmpl): self.templates = sorted(self.templates, key=template_key) + def replace(self, ind, tmpl): + if ind < len(self.templates): + self.templates[ind] = tmpl + self.dataChanged.emit(ind, ind) + else: + raise IndexError("Index %d out of range." % ind) + def get(self, ind): return self.templates[ind] @@ -51,10 +59,15 @@ def get_dropped(self, md): return vcs.elements["template"][template_name] def insertRows(self, row, count, templates, parent=QtCore.QModelIndex()): - self.beginInsertRows(parent, row, row + count) + self.beginInsertRows(parent, row, row + count - 1) self.templates = self.templates[:row] + templates + self.templates[row:] self.endInsertRows() + def removeRows(self, row, count, parent=QtCore.QModelIndex()): + self.beginRemoveRows(parent, row, row + count - 1) + self.templates.pop(row) + self.endRemoveRows() + def rowCount(self, modelIndex=None): return len(self.templates) diff --git a/cdatgui/templates/template_list.py b/cdatgui/templates/template_list.py index 05f2afc..ca491c9 100644 --- a/cdatgui/templates/template_list.py +++ b/cdatgui/templates/template_list.py @@ -1,16 +1,30 @@ -from PySide import QtGui -from models import VCSTemplateListModel +from PySide import QtGui, QtCore +from . import get_templates import re class TemplateList(QtGui.QListView): + changedSelection = QtCore.Signal() + def __init__(self, parent=None): super(TemplateList, self).__init__(parent=parent) - self.setModel(VCSTemplateListModel()) + self.setModel(get_templates()) self.setDragEnabled(True) + def currentRow(self): + if self.selectedIndexes(): + return self.selectedIndexes()[0].row() + return -1 + + def remove(self, tmpl): + self.model().removeRows(self.model().indexOf(tmpl).row(), 1) + def get_selected(self): ind = self.currentRow() if ind == -1: return None return self.model().templates[ind] + + def selectionChanged(self, *args, **kwargs): + super(TemplateList, self).selectionChanged(*args, **kwargs) + self.changedSelection.emit() diff --git a/cdatgui/templates/template_widget.py b/cdatgui/templates/template_widget.py index 43a9261..c6ece24 100644 --- a/cdatgui/templates/template_widget.py +++ b/cdatgui/templates/template_widget.py @@ -1,10 +1,14 @@ from PySide import QtCore from cdatgui.bases import StaticDockWidget +from cdatgui.templates import get_templates from cdatgui.toolbars import AddEditRemoveToolbar from template_list import TemplateList +from cdatgui.templates.dialog import TemplateEditorDialog +import vcs class TemplateWidget(StaticDockWidget): + editedTmpl = QtCore.Signal() def __init__(self, parent=None): super(TemplateWidget, self).__init__("Templates", parent=parent) @@ -15,19 +19,54 @@ def __init__(self, parent=None): self.edit_template, self.remove_template)) self.list = TemplateList() + self.list.changedSelection.connect(self.selection_change) + self.dialog = None self.setWidget(self.list) + self.titleBarWidget().edit.setEnabled(False) + self.titleBarWidget().remove.setEnabled(False) def selection_change(self): selected = self.list.get_selected() - if selected is None: - return - self.selectedTemplate.emit(selected) + if selected is None or selected.name == 'default': + self.titleBarWidget().edit.setEnabled(False) + self.titleBarWidget().remove.setEnabled(False) + else: + self.titleBarWidget().edit.setEnabled(True) + self.titleBarWidget().remove.setEnabled(True) def add_template(self): - pass + # get template object + sel = self.list.get_selected() + if sel is None: + sel = vcs.gettemplate('default') + + self.dialog = TemplateEditorDialog(sel) + self.dialog.doneEditing.connect(self.template_edited) + + # remove save button + v_layout = self.dialog.layout() + v_layout.itemAt(v_layout.count() - 1).takeAt(3).widget().deleteLater() + + self.dialog.show() + self.dialog.raise_() def edit_template(self): - pass + sel = self.list.get_selected() + self.dialog = TemplateEditorDialog(sel) + + #remove save as button + v_layout = self.dialog.layout() + v_layout.itemAt(v_layout.count() - 1).takeAt(2).widget().deleteLater() + + self.dialog.doneEditing.connect(self.template_edited) + self.dialog.show() + self.dialog.raise_() def remove_template(self): - pass + sel = self.list.get_selected() + self.list.remove(sel) + + def template_edited(self, *args, **kargs): + self.editedTmpl.emit() + + From 626af6806e88e986768ca795670f3734a191482c Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Mon, 9 May 2016 09:30:01 -0700 Subject: [PATCH 22/29] fixed bugs with saving gm from gm dialog and edit_gm_dialog on sidebar. axis editor broken --- cdatgui/editors/axis_editor.py | 9 ++++- cdatgui/editors/boxfill.py | 5 +-- cdatgui/editors/isoline.py | 1 + cdatgui/editors/projection_editor.py | 1 - cdatgui/graphics/dialog.py | 50 +++++++++++++++++++--------- cdatgui/graphics/models.py | 5 ++- cdatgui/sidebar/inspector_widget.py | 1 + tests/test_GmDialog.py | 31 ++++++++++++++--- 8 files changed, 77 insertions(+), 26 deletions(-) diff --git a/cdatgui/editors/axis_editor.py b/cdatgui/editors/axis_editor.py index ec08f1c..82ea756 100644 --- a/cdatgui/editors/axis_editor.py +++ b/cdatgui/editors/axis_editor.py @@ -68,7 +68,7 @@ def __init__(self, axis, parent=None): self.ticks_slider = QtGui.QSlider() self.ticks_slider.setRange(1, 100) self.ticks_slider.setOrientation(QtCore.Qt.Horizontal) - self.ticks_slider.sliderMoved.connect(self.updateTicks) + self.ticks_slider.valueChanged.connect(self.updateTicks) # create step edit box step_validator = QtGui.QDoubleValidator() @@ -129,6 +129,11 @@ def setPreview(self, preview): def setAxisObject(self, axis_obj): self.object = axis_obj self.preview.setAxisObject(self.object) + if self.object.numticks < 0: + self.negative_check.setChecked(True) + else: + self.negative_check.setChecked(True) + self.updateTicks(self.object.numticks) self.preview.update() # Update mode essentially @@ -196,7 +201,9 @@ def updateStep(self): self.negative_check.setCheckState(QtCore.Qt.Unchecked) self.object.step = cur_val self.state = "step" + block = self.ticks_slider.blockSignals(True) self.ticks_slider.setValue(self.object.numticks) + self.ticks_slider.blockSignals(block) self.preview.update() diff --git a/cdatgui/editors/boxfill.py b/cdatgui/editors/boxfill.py index d2b1dfc..510d654 100644 --- a/cdatgui/editors/boxfill.py +++ b/cdatgui/editors/boxfill.py @@ -1,8 +1,6 @@ from PySide import QtGui, QtCore from collections import OrderedDict -from widgets.legend_widget import LegendEditorWidget -from model.legend import VCSLegend from .graphics_method_editor import GraphicsMethodEditorWidget @@ -42,6 +40,7 @@ def gm(self): @gm.setter def gm(self, value): self._gm = value + self.orig_type = self._gm.boxfill_type type_real_vals = self.boxfill_types.values() index = type_real_vals.index(value.boxfill_type) button = self.type_group.buttons()[index] @@ -56,7 +55,5 @@ def setBoxfillType(self, radio): self.levels_button.setEnabled(False) box_type = self.boxfill_types[radio.text()] - if not self.orig_type: - self.orig_type = box_type self._gm.boxfill_type = box_type diff --git a/cdatgui/editors/isoline.py b/cdatgui/editors/isoline.py index 784b966..b739f67 100644 --- a/cdatgui/editors/isoline.py +++ b/cdatgui/editors/isoline.py @@ -80,6 +80,7 @@ def gm(self): def gm(self, value): """GM setter.""" self._gm = value + print "label", self._gm.label self.label_check.setChecked(self._gm.label) self.edit_label_button.setEnabled(self._gm.label) diff --git a/cdatgui/editors/projection_editor.py b/cdatgui/editors/projection_editor.py index 0f3ea3e..2c5e9fb 100644 --- a/cdatgui/editors/projection_editor.py +++ b/cdatgui/editors/projection_editor.py @@ -125,7 +125,6 @@ def updateCurrentProjection(self, proj): self.cur_projection_name = proj if self.newprojection_name in vcs.listelements('projection'): del vcs.elements['projection'][self.newprojection_name] - vcs.getprojection(proj).list() self.object = vcs.createprojection(source=vcs.getprojection(proj)) self.newprojection_name = self.object.name self.updateAttributes() diff --git a/cdatgui/graphics/dialog.py b/cdatgui/graphics/dialog.py index 9cb5713..57a6fa2 100644 --- a/cdatgui/graphics/dialog.py +++ b/cdatgui/graphics/dialog.py @@ -1,4 +1,6 @@ from PySide import QtGui, QtCore + +from cdatgui.bases.vcs_elements_dialog import VcsElementsDialog from cdatgui.editors.boxfill import BoxfillEditor from cdatgui.editors.isofill import IsofillEditor from cdatgui.editors.meshfill import MeshfillEditor @@ -16,6 +18,7 @@ def __init__(self, gm, var, tmpl, parent=None): super(GraphicsMethodDialog, self).__init__(parent=parent) self.setWindowModality(QtCore.Qt.ApplicationModal) self.newgm_name = None + self.origgm_name = gm.name layout = QtGui.QVBoxLayout() @@ -42,10 +45,11 @@ def __init__(self, gm, var, tmpl, parent=None): raise NotImplementedError("No editor exists for type %s" % self.gmtype) self.editor.var = var self.editor.tmpl = tmpl - self.gm = gm - self.editor.gm = gm + self.gm = self.create(source=gm) + self.newgm_name = self.gm.name + self.editor.gm = self.gm - self.setWindowTitle('Editing ' + self.gm.name) + self.setWindowTitle('Editing ' + gm.name) layout.addWidget(self.editor) @@ -73,6 +77,7 @@ def reject(self): class GraphicsMethodSaveDialog(GraphicsMethodDialog): def __init__(self, gm, var, tmpl, parent=None): super(GraphicsMethodSaveDialog, self).__init__(gm, var, tmpl, parent) + self.dialog = None save_as = QtGui.QPushButton("Save As") save_as.clicked.connect(self.customName) @@ -84,27 +89,34 @@ def __init__(self, gm, var, tmpl, parent=None): self.buttons.addWidget(save) self.accepted.connect(self.save) - if gm.name == 'default': - self.gm = self.create(source=gm) - self.newgm_name = self.gm.name - save.setEnabled(False) - else: - self.gm = gm - self.editor.gm = self.gm + if self.origgm_name == 'default': + save.setEnabled(False) def customName(self): - name = QtGui.QInputDialog.getText(self, u"Save As", u"Name for {0}:".format(unicode(self.gmtype))) - if name[1]: - self.save(name) + self.dialog = VcsElementsDialog('boxfill') + self.dialog.setLabelText('Name for {0}'.format(unicode(self.gmtype))) + self.dialog.setWindowTitle('Save As') + self.dialog.accepted.connect(self.grabGm) + self.dialog.show() + self.dialog.raise_() + + def grabGm(self): + self.save(self.dialog.textValue()) def save(self, name=None): if name is None: - self.editedGM.emit(self.gm) + del vcs.elements[self.gmtype][self.origgm_name] + gm = vcs.creategraphicsmethod(self.gmtype, self.newgm_name, self.origgm_name) + self.editedGM.emit(gm) else: - gm = self.create(name[0], self.gm) + if name in vcs.listelements(self.gmtype): + del vcs.elements[self.gmtype][name] + gm = self.create(name, self.newgm_name) self.createdGM.emit(gm) + del vcs.elements[self.gmtype][self.newgm_name] + self.close() @@ -114,5 +126,13 @@ def __init__(self, gm, var, tmpl, parent=None): ok_button = QtGui.QPushButton('OK') ok_button.clicked.connect(self.accept) + + self.accepted.connect(self.okClicked) self.buttons.addWidget(ok_button) + def okClicked(self): + del vcs.elements[self.gmtype][self.origgm_name] + gm = vcs.creategraphicsmethod(self.gmtype, self.newgm_name, self.origgm_name) + self.editedGM.emit(gm) + + del vcs.elements[self.gmtype][self.newgm_name] diff --git a/cdatgui/graphics/models.py b/cdatgui/graphics/models.py index 9bca3f8..3c9493f 100644 --- a/cdatgui/graphics/models.py +++ b/cdatgui/graphics/models.py @@ -28,7 +28,10 @@ def removeRows(self, row, count, parent=QtCore.QModelIndex()): def indexOf(self, gmtype, gm): parent = self.gm_types.index(gmtype) - actual = self.gms[gmtype].index(gm) + for list_gm in self.gms[gmtype]: + if list_gm.name == gm.name: + actual = self.gms[gmtype].index(list_gm) + break return self.index(actual, 0, parent=self.index(parent, 0)) def replace(self, index, gm): diff --git a/cdatgui/sidebar/inspector_widget.py b/cdatgui/sidebar/inspector_widget.py index c0136e5..ba0da25 100644 --- a/cdatgui/sidebar/inspector_widget.py +++ b/cdatgui/sidebar/inspector_widget.py @@ -169,6 +169,7 @@ def editSecondVar(self, var): self.editVariable(var) def editGraphicsMethod(self, gm): + print "GM NAME:", gm.name get_gms().replace(get_gms().indexOf(vcs.graphicsmethodtype(gm), gm), gm) self.current_plot.graphics_method = gm diff --git a/tests/test_GmDialog.py b/tests/test_GmDialog.py index 988c2e7..671e89d 100644 --- a/tests/test_GmDialog.py +++ b/tests/test_GmDialog.py @@ -1,5 +1,5 @@ import pytest, vcs, cdms2, os -from cdatgui.graphics.dialog import GraphicsMethodDialog +from cdatgui.graphics.dialog import * from cdatgui.cdat.metadata import FileMetadataWrapper from cdatgui.editors import boxfill, isoline, cdat1d from PySide import QtCore, QtGui @@ -27,6 +27,18 @@ def oned_dialog(): return d +def save_dialog(): + s = get_var() + d = GraphicsMethodSaveDialog(vcs.getmeshfill('a_meshfill'), s, vcs.createtemplate()) + return d + + +def ok_dialog(): + s = get_var() + d = GraphicsMethodOkDialog(vcs.getvector('default'), s, vcs.createtemplate()) + return d + + def get_var(): f = cdms2.open(os.path.join(vcs.sample_data, 'clt.nc')) f = FileMetadataWrapper(f) @@ -63,9 +75,9 @@ def test_boxfillDialog(qtbot, boxfill_dialog): break assert editor.levels_button.isEnabled() == False - save_button = boxfill_dialog.layout().itemAt(1).layout().itemAt(3).widget() - assert save_button.isEnabled() == False - boxfill_dialog.save(('test', True)) + # save_button = boxfill_dialog.layout().itemAt(1).layout().itemAt(3).widget() + # assert save_button.isEnabled() == False + # boxfill_dialog.save(('test', True)) # test ticks dialogs editor.editLeft() @@ -126,3 +138,14 @@ def test_1dDialog(qtbot, oned_dialog): qtbot.addWidget(editor.line_editor) assert editor.line_editor + +def test_saveDialog(qtbot, save_dialog): + assert save_dialog.gm.name == 'a_meshfill' + save_button = save_dialog.layout().itemAt(1).layout().itemAt(3).widget() + assert save_button.isEnabled() == True + + + + + + # boxfill_dialog.save(('test', True)) From 2c54f0062c8dde9d103692b61ff4c3057b88608c Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Tue, 10 May 2016 14:27:26 -0700 Subject: [PATCH 23/29] fixed level editor seg fault. createGM from dock fixed and tested --- cdatgui/bases/window_widget.py | 26 +++-- cdatgui/editors/axis_editor.py | 42 ++++--- cdatgui/editors/cdat1d.py | 4 +- cdatgui/editors/graphics_method_editor.py | 38 +++---- cdatgui/editors/isoline.py | 4 +- cdatgui/editors/level_editor.py | 31 +++--- cdatgui/editors/model/legend.py | 14 ++- cdatgui/editors/model/vcsaxis.py | 29 ++++- cdatgui/editors/projection_editor.py | 5 +- cdatgui/editors/secondary/editor/line.py | 2 +- cdatgui/editors/secondary/editor/text.py | 2 +- cdatgui/editors/vector.py | 2 +- cdatgui/editors/widgets/legend_widget.py | 15 ++- cdatgui/editors/widgets/multi_line_editor.py | 3 +- cdatgui/editors/widgets/multi_text_editor.py | 2 +- cdatgui/editors/widgets/template/labels.py | 2 +- cdatgui/graphics/dialog.py | 9 +- cdatgui/graphics/graphics_method_widget.py | 64 +++++++---- tests/test_BaseWindow.py | 4 +- tests/test_CreateGmWidget.py | 109 +++++++++++++++++++ tests/test_GmDialog.py | 60 +++++++++- 21 files changed, 350 insertions(+), 117 deletions(-) create mode 100644 tests/test_CreateGmWidget.py diff --git a/cdatgui/bases/window_widget.py b/cdatgui/bases/window_widget.py index 0d68890..2a4110a 100644 --- a/cdatgui/bases/window_widget.py +++ b/cdatgui/bases/window_widget.py @@ -2,9 +2,10 @@ class BaseSaveWindowWidget(QtGui.QWidget): - savePressed = QtCore.Signal(str) + accepted = QtCore.Signal(str) + rejected = QtCore.Signal() - def __init__(self): + def __init__(self, parent=None): super(BaseSaveWindowWidget, self).__init__() self.auto_close = True self.object = None @@ -21,7 +22,7 @@ def __init__(self): # Save and Cancel Buttons cancel_button = QtGui.QPushButton() cancel_button.setText("Cancel") - cancel_button.clicked.connect(self.close) + cancel_button.clicked.connect(self.cancel) saveas_button = QtGui.QPushButton() saveas_button.setText("Save As") @@ -68,18 +69,23 @@ def save(self): except: name = self.object.name - self.savePressed.emit(name) + self.accepted.emit(name) if self.auto_close: self.close() def setSaveDialog(self, dialog): self.dialog = dialog + def cancel(self): + self.rejected.emit() + self.close() + class BaseOkWindowWidget(QtGui.QWidget): - okPressed = QtCore.Signal() + accepted = QtCore.Signal() + rejected = QtCore.Signal() - def __init__(self): + def __init__(self, parent=None): super(BaseOkWindowWidget, self).__init__() self.object = None @@ -94,7 +100,7 @@ def __init__(self): # Save and Cancel Buttons cancel_button = QtGui.QPushButton() cancel_button.setText("Cancel") - cancel_button.clicked.connect(lambda: self.close()) + cancel_button.clicked.connect(self.cancel) ok_button = QtGui.QPushButton() ok_button.setText("OK") @@ -118,5 +124,9 @@ def setPreview(self, preview): self.vertical_layout.insertWidget(0, self.preview) def okClicked(self): - self.okPressed.emit() + self.accepted.emit() + self.close() + + def cancel(self): + self.rejected.emit() self.close() diff --git a/cdatgui/editors/axis_editor.py b/cdatgui/editors/axis_editor.py index 82ea756..21b74d8 100644 --- a/cdatgui/editors/axis_editor.py +++ b/cdatgui/editors/axis_editor.py @@ -66,7 +66,7 @@ def __init__(self, axis, parent=None): # create slider for Ticks self.ticks_slider = QtGui.QSlider() - self.ticks_slider.setRange(1, 100) + self.ticks_slider.setRange(2, 100) self.ticks_slider.setOrientation(QtCore.Qt.Horizontal) self.ticks_slider.valueChanged.connect(self.updateTicks) @@ -89,18 +89,18 @@ def __init__(self, axis, parent=None): ticks_row.addWidget(self.step_edit) # create show mini ticks check box - show_mini_check_box = QtGui.QCheckBox() - show_mini_check_box.stateChanged.connect(self.updateShowMiniTicks) + self.show_mini_check_box = QtGui.QCheckBox() + self.show_mini_check_box.stateChanged.connect(self.updateShowMiniTicks) # create mini tick spin box - mini_tick_box = QtGui.QSpinBox() - mini_tick_box.setRange(0, 255) - mini_tick_box.valueChanged.connect(self.updateMiniTicks) + self.mini_tick_box = QtGui.QSpinBox() + self.mini_tick_box.setRange(0, 255) + self.mini_tick_box.valueChanged.connect(self.updateMiniTicks) mini_ticks_row.addWidget(show_mini_label) - mini_ticks_row.addWidget(show_mini_check_box) + mini_ticks_row.addWidget(self.show_mini_check_box) mini_ticks_row.addWidget(mini_per_tick_label) - mini_ticks_row.addWidget(mini_tick_box) + mini_ticks_row.addWidget(self.mini_tick_box) self.adjuster_layout = QtGui.QVBoxLayout() @@ -121,26 +121,34 @@ def setPreview(self, preview): self.preview.setMinimumWidth(150) self.preview.setMaximumWidth(350) - if self.axis == "y": + if self.axis[0] == "y": self.horizontal_layout.insertWidget(0, self.preview) - elif self.axis == "x": + elif self.axis[0] == "x": self.adjuster_layout.insertWidget(0, self.preview) def setAxisObject(self, axis_obj): self.object = axis_obj self.preview.setAxisObject(self.object) - if self.object.numticks < 0: - self.negative_check.setChecked(True) - else: - self.negative_check.setChecked(True) - self.updateTicks(self.object.numticks) + if self.object.numticks: + if self.object.is_positive(): + self.negative_check.setChecked(False) + else: + self.negative_check.setChecked(True) + self.updateTicks(self.object.numticks) + block = self.ticks_slider.blockSignals(True) + self.ticks_slider.setValue(self.object.numticks) + self.ticks_slider.blockSignals(block) + self.show_mini_check_box.setChecked(self.object.show_miniticks) + self.mini_tick_box.setValue(self.object.minitick_count) self.preview.update() + self.accepted.connect(self.object.save) + self.rejected.connect(self.object.cancel) # Update mode essentially def updateTickmark(self, button): - if self.axis == "x": + if self.axis[0] == "x": index = 2 - elif self.axis == "y": + elif self.axis[0] == "y": index = 1 while self.adjuster_layout.count() > index + 1: widget = self.adjuster_layout.takeAt(index).widget() diff --git a/cdatgui/editors/cdat1d.py b/cdatgui/editors/cdat1d.py index 08ac36c..8de435d 100644 --- a/cdatgui/editors/cdat1d.py +++ b/cdatgui/editors/cdat1d.py @@ -40,7 +40,7 @@ def editMarker(self): self.marker_editor.close() self.marker_editor.deleteLater() self.marker_editor = MarkerEditorWidget() - self.marker_editor.savePressed.connect(self.updateMarker) + self.marker_editor.accepted.connect(self.updateMarker) mark_obj = vcs.createmarker(mtype=self.gm.marker, color=self.gm.markercolor, size=self.gm.markersize) self.marker_editor.setMarkerObject(mark_obj) self.marker_editor.raise_() @@ -51,7 +51,7 @@ def editLine(self): self.line_editor.close() self.line_editor.deleteLater() self.line_editor = LineEditorWidget() - self.line_editor.savePressed.connect(self.updateLine) + self.line_editor.accepted.connect(self.updateLine) if self.gm.linewidth < 1: self.gm.linewidth = 1 line_obj = vcs.createline(ltype=self.gm.line, color=self.gm.linecolor, width=self.gm.linewidth) diff --git a/cdatgui/editors/graphics_method_editor.py b/cdatgui/editors/graphics_method_editor.py index 92b7c25..0c36403 100644 --- a/cdatgui/editors/graphics_method_editor.py +++ b/cdatgui/editors/graphics_method_editor.py @@ -28,9 +28,9 @@ def __init__(self, parent=None): self.levels_button.clicked.connect(self.editLevels) self.levels_button.setDefault(False) self.levels_button.setAutoDefault(False) - legend_button = QtGui.QPushButton("Edit Legend") - legend_button.clicked.connect(self.editLegend) - legend_button.setAutoDefault(False) + self.legend_button = QtGui.QPushButton("Edit Legend") + self.legend_button.clicked.connect(self.editLegend) + self.legend_button.setAutoDefault(False) left_axis = QtGui.QPushButton("Edit Left Ticks") left_axis.clicked.connect(self.editLeft) right_axis = QtGui.QPushButton("Edit Right Ticks") @@ -43,7 +43,7 @@ def __init__(self, parent=None): projection.clicked.connect(self.editProjection) self.button_layout.addWidget(self.levels_button) - self.button_layout.addWidget(legend_button) + self.button_layout.addWidget(self.legend_button) self.button_layout.addWidget(left_axis) self.button_layout.addWidget(right_axis) self.button_layout.addWidget(top_axis) @@ -56,11 +56,9 @@ def __init__(self, parent=None): self.projection_editor = None def editAxis(self, axis): - if self.axis_editor: - self.axis_editor.close() - self.axis_editor.deleteLater() - self.axis_editor = AxisEditorWidget(axis[0]) - self.axis_editor.okPressed.connect(self.updated) + self.axis_editor = AxisEditorWidget(axis) + self.axis_editor.accepted.connect(self.updated) + self.axis_editor.rejected.connect(self.updated) axis = VCSAxis(self.gm, self.tmpl, axis, self.var) self.axis_editor.setAxisObject(axis) self.axis_editor.show() @@ -80,9 +78,8 @@ def editTop(self): def editLevels(self): """Edit the levels of this GM.""" - if self.level_editor is None: - self.level_editor = LevelEditor() - self.level_editor.levelsUpdated.connect(self.updated) + self.level_editor = LevelEditor() + self.level_editor.levelsUpdated.connect(self.updated) self.level_editor.gm = self.gm self.level_editor.var = self.var.var self.level_editor.show() @@ -90,12 +87,17 @@ def editLevels(self): def updated(self): if self.legend_editor is not None: + self.legend_editor.deleteLater() self.legend_editor = None if self.axis_editor is not None: + self.axis_editor.deleteLater() self.axis_editor = None if self.level_editor is not None: self.level_editor.deleteLater() self.level_editor = None + if self.projection_editor is not None: + self.projection_editor.deleteLater() + self.projection_editor = None @property def gm(self): @@ -108,21 +110,19 @@ def gm(self, value): self._gm = value def editLegend(self): - if self.legend_editor is None: - self.legend_editor = LegendEditorWidget() - self.legend_editor.okPressed.connect(self.updated) + self.legend_editor = LegendEditorWidget() + self.legend_editor.accepted.connect(self.updated) + self.legend_editor.rejected.connect(self.updated) legend = VCSLegend(self.gm, self.var.var) self.legend_editor.setObject(legend) self.legend_editor.show() self.legend_editor.raise_() def editProjection(self): - if self.projection_editor: - self.projection_editor.close() - self.projection_editor.deleteLater() self.projection_editor = ProjectionEditor() + self.projection_editor.rejected.connect(self.updated) + self.projection_editor.accepted.connect(self.updated) self.projection_editor.setProjectionObject(vcs.getprojection(self.gm.projection)) self.projection_editor.gm = self.gm self.projection_editor.show() self.projection_editor.raise_() - diff --git a/cdatgui/editors/isoline.py b/cdatgui/editors/isoline.py index b739f67..046a57a 100644 --- a/cdatgui/editors/isoline.py +++ b/cdatgui/editors/isoline.py @@ -37,6 +37,9 @@ def __init__(self, parent=None): self.text_edit_widget = None self.line_edit_widget = None + self.legend_button.setEnabled(False) + self.legend_button.hide() + def editText(self): if self.text_edit_widget: self.text_edit_widget.close() @@ -80,7 +83,6 @@ def gm(self): def gm(self, value): """GM setter.""" self._gm = value - print "label", self._gm.label self.label_check.setChecked(self._gm.label) self.edit_label_button.setEnabled(self._gm.label) diff --git a/cdatgui/editors/level_editor.py b/cdatgui/editors/level_editor.py index 4ed7480..97e1e1c 100644 --- a/cdatgui/editors/level_editor.py +++ b/cdatgui/editors/level_editor.py @@ -4,12 +4,13 @@ from cdatgui.cdat.vcswidget import QVCSWidget from PySide import QtCore, QtGui from .widgets.adjust_values import AdjustValues +from cdatgui.bases.window_widget import BaseOkWindowWidget import vcsaddons import vcs import numpy -class LevelEditor(QtGui.QWidget): +class LevelEditor(BaseOkWindowWidget): """Uses DictEditor to select levels for a GM and displays a histogram.""" levelsUpdated = QtCore.Signal() @@ -26,29 +27,25 @@ def __init__(self, parent=None): self.value_sliders = AdjustValues() self.value_sliders.valuesChanged.connect(self.update_levels) - layout = QtGui.QVBoxLayout() - layout.addWidget(self.canvas) - layout.addWidget(self.value_sliders) - self.setLayout(layout) + self.vertical_layout.insertWidget(0,self.canvas) + self.vertical_layout.insertWidget(1, self.value_sliders) + self.setLayout(self.vertical_layout) self.histo = vcsaddons.histograms.Ghg() - self.reset = QtGui.QPushButton(u"Cancel") - self.reset.clicked.connect(self.reset_levels) - - self.apply = QtGui.QPushButton(u"Apply") - self.apply.clicked.connect(self.levelsUpdated.emit) - self.orig_levs = None - button_layout = QtGui.QHBoxLayout() - layout.addLayout(button_layout) - button_layout.addWidget(self.reset) - button_layout.addWidget(self.apply) + self.rejected.connect(self.reset_levels) + self.accepted.connect(self.updated_levels) def reset_levels(self): + self.close() self.gm.levels = self.orig_levs self.levelsUpdated.emit() + def updated_levels(self): + self.close() + self.levelsUpdated.emit() + def update_levels(self, levs, clear=False): self.histo.bins = levs if clear: @@ -64,7 +61,7 @@ def var(self): @var.setter def var(self, value): - print "VAR", value, type(value) + # print "VAR", value, type(value) self._var = value flat = self._var.data flat = sorted(numpy.unique(flat.flatten())) @@ -93,7 +90,7 @@ def var(self, value): for lev in levs: if lev not in values: values.insert(bisect_left(values, lev), lev) - print "LEVS:", levs + # print "LEVS:", levs self.canvas.clear() self.value_sliders.update(values, levs) self.update_levels(levs, clear=True) diff --git a/cdatgui/editors/model/legend.py b/cdatgui/editors/model/legend.py index 3f7d6ef..3a18c07 100644 --- a/cdatgui/editors/model/legend.py +++ b/cdatgui/editors/model/legend.py @@ -119,19 +119,25 @@ def color_2(self, c): @property def ext_left(self): - return self._gm.ext_1 + if hasattr(self._gm, "ext_1"): + return self._gm.ext_1 + return None @ext_left.setter def ext_left(self, v): - self._gm.ext_1 = v + if hasattr(self._gm, "ext_1"): + self._gm.ext_1 = v @property def ext_right(self): - return self._gm.ext_2 + if hasattr(self._gm, "ext_2"): + return self._gm.ext_2 + return None @ext_right.setter def ext_right(self, v): - self._gm.ext_2 = v + if hasattr(self._gm, "ext_2"): + self._gm.ext_2 = v @property def level_names(self): diff --git a/cdatgui/editors/model/vcsaxis.py b/cdatgui/editors/model/vcsaxis.py index ba9c5cf..06c1f8d 100644 --- a/cdatgui/editors/model/vcsaxis.py +++ b/cdatgui/editors/model/vcsaxis.py @@ -3,8 +3,10 @@ class VCSAxis(object): def __init__(self, gm, tmpl, axis, var): - self.gm = gm - self.tmpl = tmpl + self.gm = vcs.creategraphicsmethod(vcs.graphicsmethodtype(gm), gm.name) + self.orig_gm_name = gm.name + self.tmpl = vcs.createtemplate(source=tmpl) + self.orig_tmpl_name = tmpl.name self._axis = axis self.var = var @@ -114,6 +116,10 @@ def numticks(self, num): step = (right - left) / float(num) self.ticks = {right + n * step: right + n * step for n in range(-1 * num)} + def is_positive(self): + left, right = vcs.minmax(self.axis) + return left in self.ticks + @property def step(self): ticks = self.ticks @@ -121,6 +127,7 @@ def step(self): ticks = vcs.elements["list"][ticks] ticks = sorted(ticks) left, right = vcs.minmax(self.axis) + # print "LEFT = {0} RIGHT = {1} len(ticks) = {2} ticks = {3}".format(left, right, len(ticks), ticks) return (right - left) / (len(ticks) - 1) # pretty sure this need to be - @step.setter @@ -211,6 +218,18 @@ def ticks_as_dict(self): ticks = vcs.elements["list"][ticks] return ticks - def save(self, name): - vcs.elements["list"][name] = self.ticks - vcs.elements["list"][name + "_miniticks"] = self.miniticks + def save(self): + gtype = vcs.graphicsmethodtype(self.gm) + del vcs.elements[gtype][self.orig_gm_name] + vcs.elements[gtype][self.orig_gm_name] = self.gm + del vcs.elements['template'][self.orig_tmpl_name] + vcs.elements['template'][self.orig_tmpl_name] = self.tmpl + + # vcs.elements["list"][name] = self.ticks + # vcs.elements["list"][name + "_miniticks"] = self.miniticks + + def cancel(self): + gtype = vcs.graphicsmethodtype(self.gm) + del vcs.elements[gtype][self.gm.name] + del vcs.elements['template'][self.tmpl.name] + diff --git a/cdatgui/editors/projection_editor.py b/cdatgui/editors/projection_editor.py index 2c5e9fb..a641441 100644 --- a/cdatgui/editors/projection_editor.py +++ b/cdatgui/editors/projection_editor.py @@ -15,7 +15,7 @@ def __init__(self): self.orig_projection = None self.cur_projection_name = None self.gm = None - self.savePressed.connect(self.savingNewProjection) + self.accepted.connect(self.savingNewProjection) self.editors = [] self.auto_close = False self.newprojection_name = None @@ -80,6 +80,7 @@ def setProjectionObject(self, obj): self.cur_projection_name = obj.name self.object = vcs.createprojection(source=obj) self.newprojection_name = self.object.name + print "NEW PROJECTION", self.newprojection_name self.updateAttributes() @@ -154,7 +155,7 @@ def savingNewProjection(self, name): return if name == self.newprojection_name: - vcs.elements['projection'].pop(self.cur_projection_name) + del vcs.elements['projection'][self.cur_projection_name] vcs.createprojection(self.cur_projection_name, self.object) name = self.cur_projection_name else: diff --git a/cdatgui/editors/secondary/editor/line.py b/cdatgui/editors/secondary/editor/line.py index 8a1a486..1806ea8 100644 --- a/cdatgui/editors/secondary/editor/line.py +++ b/cdatgui/editors/secondary/editor/line.py @@ -11,7 +11,7 @@ class LineEditorWidget(BaseSaveWindowWidget): def __init__(self): super(LineEditorWidget, self).__init__() self.setPreview(LinePreviewWidget()) - self.savePressed.connect(self.saveNewLine) + self.accepted.connect(self.saveNewLine) self.orig_name = None self.newline_name = None diff --git a/cdatgui/editors/secondary/editor/text.py b/cdatgui/editors/secondary/editor/text.py index e44efb9..a8ff8bd 100755 --- a/cdatgui/editors/secondary/editor/text.py +++ b/cdatgui/editors/secondary/editor/text.py @@ -11,7 +11,7 @@ class TextStyleEditorWidget(BaseSaveWindowWidget): def __init__(self): super(TextStyleEditorWidget, self).__init__() self.setPreview(TextStylePreviewWidget()) - self.savePressed.connect(self.saveNewText) + self.accepted.connect(self.saveNewText) self.orig_names = [] self.newtextcombined_name = None diff --git a/cdatgui/editors/vector.py b/cdatgui/editors/vector.py index 4336f46..c38a8e6 100644 --- a/cdatgui/editors/vector.py +++ b/cdatgui/editors/vector.py @@ -25,7 +25,7 @@ def __init__(self, parent=None): def editLine(self): if not self.line_editor: self.line_editor = LineEditorWidget() - self.line_editor.savePressed.connect(self.updateLine) + self.line_editor.accepted.connect(self.updateLine) line_obj = vcs.createline(ltype=self.gm.line, color=self.gm.linecolor, width=self.gm.linewidth) self.line_editor.setLineObject(line_obj) self.line_editor.raise_() diff --git a/cdatgui/editors/widgets/legend_widget.py b/cdatgui/editors/widgets/legend_widget.py index cf31e12..02594fd 100644 --- a/cdatgui/editors/widgets/legend_widget.py +++ b/cdatgui/editors/widgets/legend_widget.py @@ -337,9 +337,20 @@ def setObject(self, legend): self.end_color_widget.setEnabled(False) self.end_color_widget.hide() - self.extend_left_check.setChecked(self.object.ext_left) - self.extend_right_check.setChecked(self.object.ext_right) + # disable the extend left and right if the gm does not have any - might not actually be needed + if self.object.ext_left is not None: + self.extend_left_check.setChecked(self.object.ext_left) + else: + self.extend_left_check.setEnabled(False) + self.extend_left_check.hide() + + if self.object.ext_right is not None: + self.extend_right_check.setChecked(self.object.ext_right) + else: + self.extend_right_check.setEnabled(False) + self.extend_right_check.hide() + # disable the custom fill option if the fill style is not custom if vcs.isboxfill(self.object._gm): if self.object._gm.boxfill_type == 'custom': self.enableCustom(self.object._gm.fillareastyle != 'solid') diff --git a/cdatgui/editors/widgets/multi_line_editor.py b/cdatgui/editors/widgets/multi_line_editor.py index e2ec2f0..3a0a319 100644 --- a/cdatgui/editors/widgets/multi_line_editor.py +++ b/cdatgui/editors/widgets/multi_line_editor.py @@ -90,12 +90,13 @@ def update(self, index, name): def okClicked(self): self.updateGM() - self.okPressed.emit() + self.accepted.emit() self.close() def updateGM(self): colors = [] widths = [] + print "updating GM", self.isoline_model.line for line in self.isoline_model.line: colors.append(vcs.getline(line).color[0]) widths.append(vcs.getline(line).width[0]) diff --git a/cdatgui/editors/widgets/multi_text_editor.py b/cdatgui/editors/widgets/multi_text_editor.py index 04d369f..11c064b 100644 --- a/cdatgui/editors/widgets/multi_text_editor.py +++ b/cdatgui/editors/widgets/multi_text_editor.py @@ -86,5 +86,5 @@ def update(self, index, name): self.text_combos[index].setCurrentIndex(self.text_combos[index].findText(name)) def okClicked(self): - self.okPressed.emit() + self.accepted.emit() self.close() diff --git a/cdatgui/editors/widgets/template/labels.py b/cdatgui/editors/widgets/template/labels.py index b499df2..5c2426a 100644 --- a/cdatgui/editors/widgets/template/labels.py +++ b/cdatgui/editors/widgets/template/labels.py @@ -132,7 +132,7 @@ def __init__(self, parent=None): self._template = None self.member_groups = {group: TemplateLabelGroup(group) for group in members} self.style_editor = TextStyleEditorWidget() - self.style_editor.savePressed.connect(self.save_style) + self.style_editor.accepted.connect(self.save_style) for group, widget in self.member_groups.iteritems(): widget.labelUpdated.connect(self.labelUpdated.emit) widget.moveLabel.connect(self.moveLabel.emit) diff --git a/cdatgui/graphics/dialog.py b/cdatgui/graphics/dialog.py index 57a6fa2..27bfceb 100644 --- a/cdatgui/graphics/dialog.py +++ b/cdatgui/graphics/dialog.py @@ -45,7 +45,7 @@ def __init__(self, gm, var, tmpl, parent=None): raise NotImplementedError("No editor exists for type %s" % self.gmtype) self.editor.var = var self.editor.tmpl = tmpl - self.gm = self.create(source=gm) + self.gm = self.createNewGM(gm) self.newgm_name = self.gm.name self.editor.gm = self.gm @@ -65,8 +65,14 @@ def __init__(self, gm, var, tmpl, parent=None): self.setLayout(layout) + def createNewGM(self, gm): + """This is here so it can be overridden when inherited""" + return self.create(source=gm) + def reject(self): + print "rejecting in gm dialog" super(GraphicsMethodDialog, self).reject() + if isinstance(self.editor, BoxfillEditor): self.gm.boxfill_type = self.editor.orig_type @@ -134,5 +140,4 @@ def okClicked(self): del vcs.elements[self.gmtype][self.origgm_name] gm = vcs.creategraphicsmethod(self.gmtype, self.newgm_name, self.origgm_name) self.editedGM.emit(gm) - del vcs.elements[self.gmtype][self.newgm_name] diff --git a/cdatgui/graphics/graphics_method_widget.py b/cdatgui/graphics/graphics_method_widget.py index 3555cef..558d345 100644 --- a/cdatgui/graphics/graphics_method_widget.py +++ b/cdatgui/graphics/graphics_method_widget.py @@ -31,7 +31,8 @@ def validate(self, inp, pos): class EditGmDialog(GraphicsMethodOkDialog): - def __init__(self, gtype, ginstance): + def __init__(self, gtype, ginstance, store=True): + """Store designates whether the gm is to be saved on okPressed for use when creating new gms""" self.gtype = gtype self.ginstance = ginstance f = cdms2.open(os.path.join(vcs.sample_data, 'clt.nc')) @@ -50,19 +51,32 @@ def __init__(self, gtype, ginstance): self.rejected.connect(self.resetGM) self.rejected.connect(self.resetTmpl) - self.accepted.connect(self.createGM) + if not store: + print "connecting to createGM" + self.accepted.connect(self.createGM) + + def createNewGM(self, gm): + print "calling my new createNewGM" + return gm + + def okClicked(self): + print "okclicked, hiding" + self.hide() def resetGM(self): + print "resetting gm" if self.edit_gm_name: del vcs.elements[self.gtype][self.edit_gm_name] self.edit_gm_name = None def resetTmpl(self): + print "resetting tmpl" if self.edit_tmpl_name: del vcs.elements['template'][self.edit_tmpl_name] self.edit_tmpl_name = None def createGM(self): + print "creating gm. should only be calling this if no store" cur_index = get_gms().indexOf(self.gtype, vcs.getgraphicsmethod(self.gtype, self.ginstance)) del vcs.elements[self.gtype][self.ginstance] if self.edit_gm_name: @@ -118,44 +132,46 @@ def __init__(self, currently_selected, parent=None): self.accepted.connect(self.createGM) def setGMRoot(self, index): + if self.edit_dialog is not None: + print "changing root" + self.edit_dialog.deleteLater() + self.edit_dialog = None self.edit.validator().gm_type = self.gm_type_combo.currentText() self.gm_instance_combo.setRootModelIndex(get_gms().index(index, 0)) self.gm_instance_combo.setCurrentIndex(self.gm_instance_combo.findText('default')) self.edit.validator().validate(self.edit.text(), 0) def createGM(self): + # print "edit dialog, edit_gm_name", self.edit_dialog, self.edit_dialog.edit_gm_name if self.edit_dialog and self.edit_dialog.edit_gm_name: - get_gms().add_gm( - vcs.creategraphicsmethod(str(self.gm_type_combo.currentText()), + # print "createing gm from edit dialog", vcs.getboxfill(self.edit_dialog.edit_gm_name).list() + gm = vcs.creategraphicsmethod(str(self.gm_type_combo.currentText()), self.edit_dialog.edit_gm_name, - str(self.textValue()) - )) - del vcs.elements[self.gm_type_combo.currentText()][self.edit_gm_name] + str(self.textValue())) + get_gms().add_gm(gm) + del vcs.elements[self.gm_type_combo.currentText()][self.edit_dialog.edit_gm_name] else: - get_gms().add_gm( - vcs.creategraphicsmethod(str(self.gm_type_combo.currentText()), + print "creating gm without using customize as source" + gm = vcs.creategraphicsmethod(str(self.gm_type_combo.currentText()), str(self.gm_instance_combo.currentText()), - str(self.textValue()) - )) + str(self.textValue())) + get_gms().add_gm(gm) + + if self.edit_dialog: + self.edit_dialog.deleteLater() + self.edit_dialog = None def editGM(self): - self.edit_dialog = EditGmDialog(self.gm_type_combo.currentText(), self.gm_instance_combo.currentText()) + if not self.edit_dialog: + print "making new edit dialog" + self.edit_dialog = EditGmDialog(self.gm_type_combo.currentText(), self.gm_instance_combo.currentText()) + else: + print "reusing edit dialog" self.edit_dialog.show() self.edit_dialog.raise_() - def save(self): - if self.edit_dialog: - self.edit_dialog.resetTmpl() - super(CreateGM, self).save() - - def cancel(self): - if self.edit_dialog: - self.edit_dialog.resetTmpl() - self.edit_dialog.resetGM() - super(CreateGM, self).cancel() - class GraphicsMethodWidget(StaticDockWidget): editedGM = QtCore.Signal() @@ -209,7 +225,7 @@ def add_gm(self): self.add_gm_widget.raise_() def edit_gm(self): - self.edit_dialog = EditGmDialog(self.gtype, self.ginstance) + self.edit_dialog = EditGmDialog(self.gtype, self.ginstance, False) self.edit_dialog.accepted.connect(self.editedGM.emit) self.edit_dialog.show() self.edit_dialog.raise_() diff --git a/tests/test_BaseWindow.py b/tests/test_BaseWindow.py index 5e2e98c..ec8cfcc 100644 --- a/tests/test_BaseWindow.py +++ b/tests/test_BaseWindow.py @@ -28,13 +28,13 @@ def save_as(name): def test_save(qtbot, window): base = window - base.savePressed.connect(save) + base.accepted.connect(save) base.save() def test_save_as(qtbot, window): base = window - base.savePressed.connect(save_as) + base.accepted.connect(save_as) base.saveAs() base.win.setTextValue("pizza") base.win.accepted.emit() diff --git a/tests/test_CreateGmWidget.py b/tests/test_CreateGmWidget.py new file mode 100644 index 0000000..b83b436 --- /dev/null +++ b/tests/test_CreateGmWidget.py @@ -0,0 +1,109 @@ +import pytest, vcs, cdms2, os +# from cdatgui.graphics.dialog import * +# from cdatgui.cdat.metadata import FileMetadataWrapper +# from cdatgui.editors import boxfill, isoline, cdat1d +from cdatgui.graphics import get_gms +from cdatgui.graphics.graphics_method_widget import CreateGM, EditGmDialog +from PySide import QtCore, QtGui + + +@pytest.fixture +def creategm_dialog(): + cgm = CreateGM(['boxfill', 'a_boxfill']) + return cgm + + +@pytest.fixture +def editgm_dialog_store(): + egmd = EditGmDialog('boxfill', 'a_boxfill') + return egmd + + +@pytest.fixture +def editgm_dialog_nostore(): + egmd = EditGmDialog('boxfill', 'a_boxfill', False) + return egmd + + +def test_createGM(qtbot, creategm_dialog): + assert creategm_dialog.gm_type_combo.currentText() == 'boxfill' + assert creategm_dialog.gm_instance_combo.currentText() == 'a_boxfill' + + # assure its passing in the correct value to the customize dialog + # print "editing gm" + creategm_dialog.editGM() + assert creategm_dialog.edit_dialog.gtype == 'boxfill' + assert creategm_dialog.edit_dialog.ginstance == 'a_boxfill' + # print "emitting accept" + # import pdb; pdb.set_trace() + creategm_dialog.edit_dialog.accepted.emit() + # print "after emitting accept" + + creategm_dialog.gm_type_combo.setCurrentIndex(creategm_dialog.gm_type_combo.findText('isoline')) + assert creategm_dialog.gm_instance_combo.currentText() == 'default' + assert creategm_dialog.gm_instance_combo.rootModelIndex().row() == 6 + assert creategm_dialog.edit_dialog is None + # print "adjusting root" + + # assert the validator type gets updated + assert creategm_dialog.edit.validator().gm_type == 'isoline' + + assert creategm_dialog.save_button.isEnabled() == False + creategm_dialog.setTextValue('new_isoline') + assert creategm_dialog.save_button.isEnabled() == True + creategm_dialog.createGM() + + assert vcs.getisoline('new_isoline') in get_gms().gms['isoline'] + + +def test_createGM_using_customize_gm(qtbot, creategm_dialog): + creategm_dialog.editGM() + assert creategm_dialog.edit_dialog.gtype == 'boxfill' + assert creategm_dialog.edit_dialog.ginstance == 'a_boxfill' + print "loaded edit gm" + creategm_dialog.edit_dialog.gm.projection = 'robinson' + creategm_dialog.edit_dialog.reject() + creategm_dialog.setTextValue('new_boxfill') + creategm_dialog.createGM() + print "rejected gm create" + + assert vcs.getboxfill('new_boxfill') in get_gms().gms['boxfill'] + assert vcs.getboxfill('new_boxfill').projection == 'linear' + + creategm_dialog.editGM() + assert creategm_dialog.edit_dialog.gtype == 'boxfill' + assert creategm_dialog.edit_dialog.ginstance == 'a_boxfill' + + creategm_dialog.edit_dialog.gm.projection = 'robinson' + print "EDITED GM", creategm_dialog.edit_dialog.gm.list() + creategm_dialog.edit_dialog.accepted.emit() + + # test for reopening + creategm_dialog.editGM() + assert creategm_dialog.edit_dialog.gm.projection == 'robinson' + print "REOPENED NON EDITED GM", creategm_dialog.edit_dialog.gm.list() + creategm_dialog.edit_dialog.accepted.emit() + + creategm_dialog.setTextValue('new_boxfill2') + creategm_dialog.createGM() + + assert vcs.getboxfill('new_boxfill2') in get_gms().gms['boxfill'] + assert vcs.getboxfill('new_boxfill2').projection == 'robinson' + + +def test_EditGmDialogStore(qtbot, editgm_dialog_store): + editgm_dialog_store.rejected.emit() + assert editgm_dialog_store.edit_tmpl_name not in vcs.listelements('template') + assert editgm_dialog_store.edit_gm_name not in vcs.listelements('boxfill') + + +def test_EditGmDialogNoStore(qtbot, editgm_dialog_nostore): + dialog = editgm_dialog_nostore + orig_gm = vcs.getboxfill(dialog.ginstance) + dialog.createGM() + new_gm = vcs.getboxfill(dialog.ginstance) + assert new_gm != orig_gm + assert new_gm in get_gms().gms[dialog.gtype] + assert orig_gm not in get_gms().gms[dialog.gtype] + assert editgm_dialog_nostore.edit_tmpl_name not in vcs.listelements('template') + assert editgm_dialog_nostore.edit_gm_name not in vcs.listelements('boxfill') diff --git a/tests/test_GmDialog.py b/tests/test_GmDialog.py index 671e89d..9060913 100644 --- a/tests/test_GmDialog.py +++ b/tests/test_GmDialog.py @@ -1,4 +1,6 @@ import pytest, vcs, cdms2, os + +from cdatgui.editors.model.legend import VCSLegend from cdatgui.graphics.dialog import * from cdatgui.cdat.metadata import FileMetadataWrapper from cdatgui.editors import boxfill, isoline, cdat1d @@ -27,15 +29,17 @@ def oned_dialog(): return d +@pytest.fixture def save_dialog(): s = get_var() d = GraphicsMethodSaveDialog(vcs.getmeshfill('a_meshfill'), s, vcs.createtemplate()) return d +@pytest.fixture def ok_dialog(): s = get_var() - d = GraphicsMethodOkDialog(vcs.getvector('default'), s, vcs.createtemplate()) + d = GraphicsMethodOkDialog(vcs.getboxfill('a_boxfill'), s, vcs.createtemplate()) return d @@ -53,6 +57,7 @@ def saveAs(gm): def test_boxfillDialog(qtbot, boxfill_dialog): """Test boxfill gm editor as well as basic dialog functionality and GraphicsMethodEditor functionality""" editor = boxfill_dialog.editor + assert isinstance(editor, boxfill.BoxfillEditor) assert editor.levels_button.isEnabled() == False @@ -82,17 +87,46 @@ def test_boxfillDialog(qtbot, boxfill_dialog): # test ticks dialogs editor.editLeft() assert editor.axis_editor - assert editor.axis_editor.axis == 'y' + assert editor.axis_editor.axis == 'y1' + + editor.updated() + assert editor.axis_editor is None editor.editRight() - assert editor.axis_editor.axis == 'y' + assert editor.axis_editor.axis == 'y2' + + editor.updated() + assert editor.axis_editor is None editor.editBottom() - assert editor.axis_editor.axis == 'x' + assert editor.axis_editor.axis == 'x1' + + editor.updated() + assert editor.axis_editor is None editor.editTop() qtbot.addWidget(editor.axis_editor) - assert editor.axis_editor.axis == 'x' + assert editor.axis_editor.axis == 'x2' + + editor.updated() + + # testing legend crashes with autolabels error. autolabels not supposed to implemented? + # editor.editLegend() + # assert editor.legend_editor + # assert isinstance(editor.object, VCSLegend) + + # editor.updated() + + editor.editProjection() + assert editor.projection_editor + assert editor.projection_editor.cur_projection_name == 'linear' + editor.projection_editor.close() + + editor.updated() + assert editor.axis_editor is None + assert editor.projection_editor is None + + boxfill_dialog.reject() def test_isolineDialog(qtbot, isoline_dialog): @@ -138,14 +172,28 @@ def test_1dDialog(qtbot, oned_dialog): qtbot.addWidget(editor.line_editor) assert editor.line_editor + oned_dialog.reject() + assert oned_dialog.newgm_name not in vcs.listelements('1d') + def test_saveDialog(qtbot, save_dialog): - assert save_dialog.gm.name == 'a_meshfill' + assert save_dialog.origgm_name == 'a_meshfill' save_button = save_dialog.layout().itemAt(1).layout().itemAt(3).widget() assert save_button.isEnabled() == True + save_dialog.customName() + assert isinstance(save_dialog.dialog, VcsElementsDialog) +def test_okDialog(qtbot, ok_dialog): + assert ok_dialog.origgm_name == 'a_boxfill' + ok_dialog.okClicked() + assert ok_dialog.newgm_name not in vcs.listelements('boxfill') +def test_saveButtonDisabled(qtbot): + s = get_var() + d = GraphicsMethodSaveDialog(vcs.getisoline('default'), s, vcs.createtemplate()) + save_button = d.layout().itemAt(1).layout().itemAt(3).widget() + assert save_button.isEnabled() == False # boxfill_dialog.save(('test', True)) From a4ba92ce5eaad8b3667f402c6f580a3a9367b58e Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Wed, 11 May 2016 13:28:21 -0700 Subject: [PATCH 24/29] fixing lots of bugs. hopefully their actually fixed --- cdatgui/bases/background_delegate.py | 2 +- cdatgui/bases/window_widget.py | 18 ++++----- cdatgui/cdat/plotter.py | 42 +++++++++++++++----- cdatgui/console/console_dock.py | 2 +- cdatgui/console/console_widget.py | 6 ++- cdatgui/editors/axis_editor.py | 37 ++++++++++++++--- cdatgui/editors/cdat1d.py | 1 - cdatgui/editors/level_editor.py | 3 -- cdatgui/editors/model/vcsaxis.py | 10 +++-- cdatgui/editors/projection_editor.py | 17 +++++--- cdatgui/editors/widgets/adjust_values.py | 4 +- cdatgui/editors/widgets/multi_line_editor.py | 3 +- cdatgui/editors/widgets/multi_text_editor.py | 2 +- cdatgui/graphics/__init__.py | 6 ++- cdatgui/graphics/dialog.py | 1 - cdatgui/graphics/graphics_method_widget.py | 25 ++++-------- cdatgui/sidebar/inspector_widget.py | 26 +++++++----- cdatgui/spreadsheet/cell.py | 4 +- cdatgui/spreadsheet/sheet.py | 2 +- cdatgui/spreadsheet/tab.py | 8 ++-- cdatgui/vcsmodel/elements.py | 3 -- tests/test_AxisEditor.py | 25 +++++++++--- tests/test_BaseWindow.py | 2 +- tests/test_GmDialog.py | 2 +- tests/test_LineEditor.py | 6 +-- tests/test_MultiLineEditor.py | 4 +- tests/test_ProjectionEditor.py | 4 +- tests/test_TextStyleEditor.py | 8 ++-- 28 files changed, 169 insertions(+), 104 deletions(-) diff --git a/cdatgui/bases/background_delegate.py b/cdatgui/bases/background_delegate.py index d9b9569..d179225 100644 --- a/cdatgui/bases/background_delegate.py +++ b/cdatgui/bases/background_delegate.py @@ -7,7 +7,7 @@ def paint(self, painter, option, index): painter.fillRect(option.rect, bg) super(BorderHighlightStyleDelegate, self).paint(painter, option, index) if option.state & QtGui.QStyle.State_Selected: - painter.save() + painter.accept() color = QtGui.QColor(76, 177 ,255) pen = QtGui.QPen(color, 2, QtCore.Qt.SolidLine, QtCore.Qt.SquareCap, QtCore.Qt.MiterJoin) w = pen.width() / 2 diff --git a/cdatgui/bases/window_widget.py b/cdatgui/bases/window_widget.py index 2a4110a..3a59ade 100644 --- a/cdatgui/bases/window_widget.py +++ b/cdatgui/bases/window_widget.py @@ -22,7 +22,7 @@ def __init__(self, parent=None): # Save and Cancel Buttons cancel_button = QtGui.QPushButton() cancel_button.setText("Cancel") - cancel_button.clicked.connect(self.cancel) + cancel_button.clicked.connect(self.reject) saveas_button = QtGui.QPushButton() saveas_button.setText("Save As") @@ -30,7 +30,7 @@ def __init__(self, parent=None): self.save_button = QtGui.QPushButton() self.save_button.setText("Save") - self.save_button.clicked.connect(self.save) + self.save_button.clicked.connect(self.accept) save_cancel_row = QtGui.QHBoxLayout() save_cancel_row.addWidget(cancel_button) @@ -55,12 +55,12 @@ def saveAs(self): self.win = self.dialog self.win.setLabelText("Enter New Name:") - self.win.accepted.connect(self.save) + self.win.accepted.connect(self.accept) self.win.show() self.win.raise_() - def save(self): + def accept(self): try: name = self.win.textValue() @@ -76,7 +76,7 @@ def save(self): def setSaveDialog(self, dialog): self.dialog = dialog - def cancel(self): + def reject(self): self.rejected.emit() self.close() @@ -100,11 +100,11 @@ def __init__(self, parent=None): # Save and Cancel Buttons cancel_button = QtGui.QPushButton() cancel_button.setText("Cancel") - cancel_button.clicked.connect(self.cancel) + cancel_button.clicked.connect(self.reject) ok_button = QtGui.QPushButton() ok_button.setText("OK") - ok_button.clicked.connect(self.okClicked) + ok_button.clicked.connect(self.accept) ok_cancel_row = QtGui.QHBoxLayout() ok_cancel_row.addWidget(cancel_button) @@ -123,10 +123,10 @@ def setPreview(self, preview): self.preview = preview self.vertical_layout.insertWidget(0, self.preview) - def okClicked(self): + def accept(self): self.accepted.emit() self.close() - def cancel(self): + def reject(self): self.rejected.emit() self.close() diff --git a/cdatgui/cdat/plotter.py b/cdatgui/cdat/plotter.py index 02a1085..3bccb3b 100644 --- a/cdatgui/cdat/plotter.py +++ b/cdatgui/cdat/plotter.py @@ -142,14 +142,11 @@ def name(self): except AttributeError: vars.append(v.id) - # gm_type = vcs.graphicsmethodtype(self.gm) - # gm_type = vcs.graphicsmethodtype(self.gm) vars = " x ".join(vars) return "%s (%s)" % (vars, self._type) def load(self, display): self.dp = display - # self._gm = vcs.getgraphicsmethod(display.g_type, display.g_name) self._gm = display.g_name self._type = display.g_type self._vars = display.array @@ -166,9 +163,14 @@ def gm(self): return vcs.getgraphicsmethod(self._type, self._gm) def set_gm(self, gm): + plot = True + if isinstance(gm, tuple): + plot = gm[1] + gm = gm[0] + self._gm = gm.name self._type = vcs.graphicsmethodtype(gm) - if self.can_plot(): + if plot and self.can_plot(): self.plot() self.source.gm_label.setText(self._gm) @@ -178,9 +180,12 @@ def get_vars(self): return self._vars def set_vars(self, v): + plot = True + if len(v) > 2: + plot = v[2] + v = v[:2] try: self._vars = (v[0], v[1]) - # self.graphics_method = vcs.createvector() except TypeError: self._vars = (v, None) except IndexError: @@ -194,7 +199,7 @@ def set_vars(self, v): else: new_vars.append(var) self._vars = new_vars - if self.can_plot(): + if plot and self.can_plot(): self.plot() valid_vars = [] @@ -214,8 +219,13 @@ def templ(self): def set_templ(self, template): # Check if gm supports templates + plot = True + if isinstance(template, tuple): + plot = template[1] + template = template[0] + self._template = template - if self.can_plot(): + if plot and self.can_plot(): self.plot() self.source.tmpl_label.setText(self.template.name) @@ -246,7 +256,22 @@ def plot(self): self.dp.g_type = vcs.graphicsmethodtype(self.graphics_method) # Update the canvas - self.canvas.update() + # self.canvas.update() use this once update is not broken + args = [] + for var in self.variables: + if var is not None: + args.append(var) + if self.template is not None: + args.append(self.template.name) + else: + args.append("default") + if self.graphics_method is not None: + args.append(vcs.graphicsmethodtype(self.graphics_method)) + args.append(self.graphics_method.name) + + print "updating by clear and replotting" + self.canvas.clear(preserve_display=True, render=False) + self.dp = self.canvas.plot(*args) else: args = [] @@ -264,6 +289,5 @@ def plot(self): if self.template is None: self._template = vcs.gettemplate(self.dp._template_origin) if self.graphics_method is None: - # self._gm = vcs.getgraphicsmethod(self.dp.g_type, self.dp.g_name) self._gm = self.dp.g_name self._type = self.dp.g_type diff --git a/cdatgui/console/console_dock.py b/cdatgui/console/console_dock.py index 3db307a..0c515a9 100644 --- a/cdatgui/console/console_dock.py +++ b/cdatgui/console/console_dock.py @@ -11,7 +11,7 @@ def __init__(self, spreadsheet, parent=None): self.console.createdPlot.connect(self.added_plot) self.console.createdPlot.connect(spreadsheet.tabController.currentWidget().totalPlotsChanged) - self.console.updatedVar.connect(spreadsheet.tabController.currentWidget().totalPlotsChanged) + self.console.updatedVar.connect(spreadsheet.tabController.currentWidget().replotPlottersUpdateVars) spreadsheet.emitAllPlots.connect(self.updateAllPlots) self.setWidget(self.console) diff --git a/cdatgui/console/console_widget.py b/cdatgui/console/console_widget.py index aa7487c..33797aa 100644 --- a/cdatgui/console/console_widget.py +++ b/cdatgui/console/console_widget.py @@ -144,6 +144,7 @@ def updateAllPlots(self, plots): def codeExecuted(self, *varargs): namespace = self.kernel.shell.user_ns cur_keys = set(namespace) + variable_updated = False # get last output out_dict = namespace["Out"] @@ -166,7 +167,7 @@ def codeExecuted(self, *varargs): self.variable_list.add_variable(cdms_var) else: self.variable_list.update_variable(cdms_var, key) - self.updatedVar.emit() + variable_updated = True elif is_displayplot(value) and value not in self.display_plots: self.display_plots.append(value) @@ -176,6 +177,9 @@ def codeExecuted(self, *varargs): self.display_plots.append(last_line) self.createdPlot.emit(last_line) + if variable_updated: + self.updatedVar.emit() + def fixInvalidVariables(self, var): var = re.sub(' +', '_', var) var = re.sub("[^a-zA-Z0-9_]+", '', var) diff --git a/cdatgui/editors/axis_editor.py b/cdatgui/editors/axis_editor.py index 21b74d8..7c22d4d 100644 --- a/cdatgui/editors/axis_editor.py +++ b/cdatgui/editors/axis_editor.py @@ -56,13 +56,13 @@ def __init__(self, axis, parent=None): self.tickmark_button_group.buttonClicked.connect(self.updateTickmark) # create preset combo box - preset_box = QtGui.QComboBox() - preset_box.addItem("default") - preset_box.addItems(vcs.listelements("list")) - preset_box.currentIndexChanged[str].connect(self.updatePreset) + self.preset_box = QtGui.QComboBox() + self.preset_box.addItem("default") + self.preset_box.addItems(vcs.listelements("list")) + self.preset_box.currentIndexChanged[str].connect(self.updatePreset) preset_row.addWidget(preset_label) - preset_row.addWidget(preset_box) + preset_row.addWidget(self.preset_box) # create slider for Ticks self.ticks_slider = QtGui.QSlider() @@ -140,6 +140,14 @@ def setAxisObject(self, axis_obj): self.ticks_slider.blockSignals(block) self.show_mini_check_box.setChecked(self.object.show_miniticks) self.mini_tick_box.setValue(self.object.minitick_count) + + # set initial mode + for button in self.tickmark_button_group.buttons(): + if isinstance(self.object.ticks, dict) and button.text() == 'Even': + button.click() + elif self.object.ticks == '*' and button.text() == 'Manual': + button.setEnabled(False) + self.preview.update() self.accepted.connect(self.object.save) self.rejected.connect(self.object.cancel) @@ -157,16 +165,22 @@ def updateTickmark(self, button): if button.text() == "Auto": self.adjuster_layout.insertWidget(index, self.preset_widget) self.preset_widget.setVisible(True) + self.updatePreset(self.preset_box.currentText()) elif button.text() == "Even": self.adjuster_layout.insertWidget(index, self.ticks_widget) self.ticks_widget.setVisible(True) self.state = "count" + self.mini_tick_box.setEnabled(True) + self.show_mini_check_box.setEnabled(True) + for button in self.tickmark_button_group.buttons(): + if button.text() == 'Manual': + button.setEnabled(True) elif button.text() == "Manual": self.adjuster_layout.insertWidget(index, self.scroll_area) self.dict_widget.setDict(self.object.ticks_as_dict()) - self.dict_widget.setVisible(True) + self.scroll_area.setVisible(True) self.object.mode = button.text().lower() self.preview.update() @@ -174,8 +188,19 @@ def updateTickmark(self, button): def updatePreset(self, preset): if preset == "default": self.object.ticks = "*" + self.mini_tick_box.setEnabled(False) + self.show_mini_check_box.setEnabled(False) + for button in self.tickmark_button_group.buttons(): + if button.text() == 'Manual': + button.setEnabled(False) else: self.object.ticks = preset + self.mini_tick_box.setEnabled(True) + self.show_mini_check_box.setEnabled(True) + for button in self.tickmark_button_group.buttons(): + if button.text() == 'Manual': + button.setEnabled(True) + self.preview.update() def updateShowMiniTicks(self, state): diff --git a/cdatgui/editors/cdat1d.py b/cdatgui/editors/cdat1d.py index 8de435d..385bd4f 100644 --- a/cdatgui/editors/cdat1d.py +++ b/cdatgui/editors/cdat1d.py @@ -84,5 +84,4 @@ def gm(self): def gm(self, value): """GM setter.""" self._gm = value - print value.flip self.flip_check.setChecked(value.flip) diff --git a/cdatgui/editors/level_editor.py b/cdatgui/editors/level_editor.py index 97e1e1c..4fee5de 100644 --- a/cdatgui/editors/level_editor.py +++ b/cdatgui/editors/level_editor.py @@ -61,7 +61,6 @@ def var(self): @var.setter def var(self, value): - # print "VAR", value, type(value) self._var = value flat = self._var.data flat = sorted(numpy.unique(flat.flatten())) @@ -90,7 +89,6 @@ def var(self, value): for lev in levs: if lev not in values: values.insert(bisect_left(values, lev), lev) - # print "LEVS:", levs self.canvas.clear() self.value_sliders.update(values, levs) self.update_levels(levs, clear=True) @@ -115,7 +113,6 @@ def has_set_gm_levels(self): except: length = len(self._gm.levels) try: - print self._gm.levels return length != 2 or not numpy.allclose(self._gm.levels, [1e+20] * 2) except ValueError: return True diff --git a/cdatgui/editors/model/vcsaxis.py b/cdatgui/editors/model/vcsaxis.py index 06c1f8d..b34f458 100644 --- a/cdatgui/editors/model/vcsaxis.py +++ b/cdatgui/editors/model/vcsaxis.py @@ -95,8 +95,12 @@ def mode(self): @mode.setter def mode(self, value): - if value == "auto" and isinstance(self.ticks, dict): - self.ticks = "*" + # if value == "auto" and isinstance(self.ticks, dict): + # self.ticks = "*" + if value == 'even' and isinstance(self.ticks, str): + if self.ticks != "*": + step = self.step + self.step = step @property def numticks(self): @@ -127,7 +131,6 @@ def step(self): ticks = vcs.elements["list"][ticks] ticks = sorted(ticks) left, right = vcs.minmax(self.axis) - # print "LEFT = {0} RIGHT = {1} len(ticks) = {2} ticks = {3}".format(left, right, len(ticks), ticks) return (right - left) / (len(ticks) - 1) # pretty sure this need to be - @step.setter @@ -150,7 +153,6 @@ def step(self, value): cur_val += value self.ticks = {i: i for i in tick_vals} - print "SET TICKS", self.ticks @property def show_miniticks(self): diff --git a/cdatgui/editors/projection_editor.py b/cdatgui/editors/projection_editor.py index a641441..e06b790 100644 --- a/cdatgui/editors/projection_editor.py +++ b/cdatgui/editors/projection_editor.py @@ -72,15 +72,21 @@ def __init__(self): type_row.addWidget(type_label) type_row.addWidget(self.type_combo) + well = QtGui.QFrame() + well.setFrameShape(QtGui.QFrame.StyledPanel) + well.setFrameShadow(QtGui.QFrame.Sunken) + self.well_layout = QtGui.QVBoxLayout() + well.setLayout(self.well_layout) + self.well_layout.addLayout(type_row) + self.vertical_layout.insertLayout(0, name_row) - self.vertical_layout.insertLayout(1, type_row) + self.vertical_layout.insertWidget(1, well) def setProjectionObject(self, obj): self.orig_projection = obj self.cur_projection_name = obj.name self.object = vcs.createprojection(source=obj) self.newprojection_name = self.object.name - print "NEW PROJECTION", self.newprojection_name self.updateAttributes() @@ -91,8 +97,8 @@ def updateAttributes(self): else: self.save_button.setEnabled(True) - for i in range(2, self.vertical_layout.count() - 1): - row = self.vertical_layout.takeAt(2).layout() + for i in range(1, self.well_layout.count()): + row = self.well_layout.takeAt(1).layout() row.takeAt(0).widget().deleteLater() row.takeAt(0).widget().deleteLater() row.deleteLater() @@ -119,7 +125,8 @@ def updateAttributes(self): row.addWidget(label(name.capitalize() + ":")) row.addWidget(edit_attr) - self.vertical_layout.insertLayout(self.vertical_layout.count() - 1, row) + # self.vertical_layout.insertLayout(self.vertical_layout.count() - 1, row) + self.well_layout.addLayout(row) def updateCurrentProjection(self, proj): proj = str(proj) diff --git a/cdatgui/editors/widgets/adjust_values.py b/cdatgui/editors/widgets/adjust_values.py index ae783a8..bd71544 100644 --- a/cdatgui/editors/widgets/adjust_values.py +++ b/cdatgui/editors/widgets/adjust_values.py @@ -55,10 +55,10 @@ def adjust_slides(self, slide, cur_val): for i, s in enumerate(self.slides): if i < cur_index: - if s.sliderPosition() > slide.sliderPosition(): + if s.sliderPosition() >= slide.sliderPosition(): s.setValue(slide.sliderPosition()) else: - if s.sliderPosition() < slide.sliderPosition(): + if s.sliderPosition() <= slide.sliderPosition(): s.setValue(slide.sliderPosition()) def send_values(self): diff --git a/cdatgui/editors/widgets/multi_line_editor.py b/cdatgui/editors/widgets/multi_line_editor.py index 3a0a319..473c134 100644 --- a/cdatgui/editors/widgets/multi_line_editor.py +++ b/cdatgui/editors/widgets/multi_line_editor.py @@ -88,7 +88,7 @@ def update(self, index, name): self.isoline_model.line[index] = str(name) self.line_combos[index].setCurrentIndex(self.line_combos[index].findText(name)) - def okClicked(self): + def accept(self): self.updateGM() self.accepted.emit() self.close() @@ -96,7 +96,6 @@ def okClicked(self): def updateGM(self): colors = [] widths = [] - print "updating GM", self.isoline_model.line for line in self.isoline_model.line: colors.append(vcs.getline(line).color[0]) widths.append(vcs.getline(line).width[0]) diff --git a/cdatgui/editors/widgets/multi_text_editor.py b/cdatgui/editors/widgets/multi_text_editor.py index 11c064b..bf6d6b0 100644 --- a/cdatgui/editors/widgets/multi_text_editor.py +++ b/cdatgui/editors/widgets/multi_text_editor.py @@ -85,6 +85,6 @@ def changeText(self, row_index, combo_index): def update(self, index, name): self.text_combos[index].setCurrentIndex(self.text_combos[index].findText(name)) - def okClicked(self): + def accept(self): self.accepted.emit() self.close() diff --git a/cdatgui/graphics/__init__.py b/cdatgui/graphics/__init__.py index a19622c..a65d2fc 100644 --- a/cdatgui/graphics/__init__.py +++ b/cdatgui/graphics/__init__.py @@ -1,10 +1,14 @@ from models import VCSGraphicsMethodModel - __gms__ = None + def get_gms(): global __gms__ if __gms__ is None: __gms__ = VCSGraphicsMethodModel() return __gms__ + + +gms_with_non_implemented_editors = ['scatter', '1d', '3d_dual_scalar', '3d_scalar', '3d_vector', 'isoline', 'scatter', + 'taylordiagram', 'xvsy', 'xyvsy', 'yxvsx'] diff --git a/cdatgui/graphics/dialog.py b/cdatgui/graphics/dialog.py index 27bfceb..57478e4 100644 --- a/cdatgui/graphics/dialog.py +++ b/cdatgui/graphics/dialog.py @@ -70,7 +70,6 @@ def createNewGM(self, gm): return self.create(source=gm) def reject(self): - print "rejecting in gm dialog" super(GraphicsMethodDialog, self).reject() if isinstance(self.editor, BoxfillEditor): diff --git a/cdatgui/graphics/graphics_method_widget.py b/cdatgui/graphics/graphics_method_widget.py index 558d345..e6599bc 100644 --- a/cdatgui/graphics/graphics_method_widget.py +++ b/cdatgui/graphics/graphics_method_widget.py @@ -8,6 +8,7 @@ from cdatgui.graphics.dialog import GraphicsMethodOkDialog from cdatgui.utils import label from cdatgui.cdat.metadata import FileMetadataWrapper +from . import gms_with_non_implemented_editors import vcs, cdms2, os @@ -52,31 +53,25 @@ def __init__(self, gtype, ginstance, store=True): self.rejected.connect(self.resetTmpl) if not store: - print "connecting to createGM" self.accepted.connect(self.createGM) def createNewGM(self, gm): - print "calling my new createNewGM" return gm def okClicked(self): - print "okclicked, hiding" self.hide() def resetGM(self): - print "resetting gm" if self.edit_gm_name: del vcs.elements[self.gtype][self.edit_gm_name] self.edit_gm_name = None def resetTmpl(self): - print "resetting tmpl" if self.edit_tmpl_name: del vcs.elements['template'][self.edit_tmpl_name] self.edit_tmpl_name = None def createGM(self): - print "creating gm. should only be calling this if no store" cur_index = get_gms().indexOf(self.gtype, vcs.getgraphicsmethod(self.gtype, self.ginstance)) del vcs.elements[self.gtype][self.ginstance] if self.edit_gm_name: @@ -124,16 +119,16 @@ def __init__(self, currently_selected, parent=None): self.vertical_layout.insertLayout(0, type_layout) # add customize button - button_layout = self.vertical_layout.itemAt(self.vertical_layout.count() - 1).layout() - customize_button = QtGui.QPushButton('Customize') - customize_button.clicked.connect(self.editGM) - button_layout.insertWidget(1, customize_button) + if not (currently_selected and currently_selected[0] in gms_with_non_implemented_editors): + button_layout = self.vertical_layout.itemAt(self.vertical_layout.count() - 1).layout() + customize_button = QtGui.QPushButton('Customize') + customize_button.clicked.connect(self.editGM) + button_layout.insertWidget(1, customize_button) self.accepted.connect(self.createGM) def setGMRoot(self, index): if self.edit_dialog is not None: - print "changing root" self.edit_dialog.deleteLater() self.edit_dialog = None self.edit.validator().gm_type = self.gm_type_combo.currentText() @@ -142,9 +137,7 @@ def setGMRoot(self, index): self.edit.validator().validate(self.edit.text(), 0) def createGM(self): - # print "edit dialog, edit_gm_name", self.edit_dialog, self.edit_dialog.edit_gm_name if self.edit_dialog and self.edit_dialog.edit_gm_name: - # print "createing gm from edit dialog", vcs.getboxfill(self.edit_dialog.edit_gm_name).list() gm = vcs.creategraphicsmethod(str(self.gm_type_combo.currentText()), self.edit_dialog.edit_gm_name, str(self.textValue())) @@ -152,7 +145,6 @@ def createGM(self): del vcs.elements[self.gm_type_combo.currentText()][self.edit_dialog.edit_gm_name] else: - print "creating gm without using customize as source" gm = vcs.creategraphicsmethod(str(self.gm_type_combo.currentText()), str(self.gm_instance_combo.currentText()), str(self.textValue())) @@ -164,10 +156,7 @@ def createGM(self): def editGM(self): if not self.edit_dialog: - print "making new edit dialog" self.edit_dialog = EditGmDialog(self.gm_type_combo.currentText(), self.gm_instance_combo.currentText()) - else: - print "reusing edit dialog" self.edit_dialog.show() self.edit_dialog.raise_() @@ -202,7 +191,7 @@ def selection_change(self): return if selected: self.gtype = selected[0] - if len(selected) > 1: + if len(selected) > 1 and self.gtype not in gms_with_non_implemented_editors: self.ginstance = selected[1] self.titleBarWidget().edit.setEnabled(True) self.titleBarWidget().remove.setEnabled(True) diff --git a/cdatgui/sidebar/inspector_widget.py b/cdatgui/sidebar/inspector_widget.py index ba0da25..771a637 100644 --- a/cdatgui/sidebar/inspector_widget.py +++ b/cdatgui/sidebar/inspector_widget.py @@ -7,6 +7,7 @@ from cdatgui.variables.edit_variable_widget import EditVariableDialog from cdatgui.templates.dialog import TemplateEditorDialog from cdatgui.graphics.dialog import GraphicsMethodSaveDialog +from cdatgui.graphics import gms_with_non_implemented_editors import vcs @@ -169,14 +170,15 @@ def editSecondVar(self, var): self.editVariable(var) def editGraphicsMethod(self, gm): - print "GM NAME:", gm.name get_gms().replace(get_gms().indexOf(vcs.graphicsmethodtype(gm), gm), gm) - self.current_plot.graphics_method = gm + self.current_plot.graphics_method = (gm, False) + self.plotters_updated.emit() def makeGraphicsMethod(self, gm): get_gms().add_gm(gm) self.gm_instance_combo.setCurrentIndex(self.gm_instance_combo.count() - 1) - self.current_plot.graphics_method = gm + self.current_plot.graphics_method = (gm, False) + self.plotters_updated.emit() def editGM(self): gm_type = self.gm_type_combo.currentText() @@ -212,14 +214,15 @@ def setGMRoot(self, index): self.edit_gm_button.setEnabled(False) def setTemplate(self, template): - self.current_plot.template = template + self.current_plot.template = (template, False) self.plotters_updated.emit() def updateGM(self, index): - self.edit_gm_button.setEnabled(True) + if self.gm_type_combo.currentText() not in gms_with_non_implemented_editors: + self.edit_gm_button.setEnabled(True) gm_type = self.gm_type_combo.currentText() gm_name = self.gm_instance_combo.currentText() - if gm_type in ['vector', '3d_vector']: + if gm_type in ['vector', '3d_vector', '3d_dual_scalar']: self.var_combos[1].setEnabled(True) enabled = True else: @@ -235,19 +238,20 @@ def updateGM(self, index): self.current_plot.graphics_method = (gm, False) else: gm = vcs.getgraphicsmethod(gm_type, gm_name) - self.current_plot.graphics_method = gm - + self.current_plot.graphics_method = (gm, False) + self.plotters_updated.emit() def setFirstVar(self, var): - self.current_plot.variables = [var, self.current_plot.variables[1]] + self.current_plot.variables = [var, self.current_plot.variables[1], False] self.plotters_updated.emit() def setSecondVar(self, var): old_vars = self.current_plot.variables try: - self.current_plot.variables = [self.current_plot.variables[0], var.var] + self.current_plot.variables = [self.current_plot.variables[0], var.var, False] except ValueError: + old_vars.append(False) self.current_plot.variables = old_vars self.plotters_updated.emit() @@ -281,7 +285,7 @@ def selectPlot(self, plot): block = self.template_combo.blockSignals(True) self.template_combo.setCurrentIndex(self.template_combo.findText(plot.template.name)) self.template_combo.blockSignals(block) - if self.gm_instance_combo.currentText() != '': + if self.gm_instance_combo.currentText() != '' and self.gm_type_combo.currentText() not in gms_with_non_implemented_editors: self.edit_gm_button.setEnabled(True) else: self.edit_gm_button.setEnabled(False) diff --git a/cdatgui/spreadsheet/cell.py b/cdatgui/spreadsheet/cell.py index 3aaaa3a..bdc801d 100755 --- a/cdatgui/spreadsheet/cell.py +++ b/cdatgui/spreadsheet/cell.py @@ -118,11 +118,11 @@ def dumpToFile(self, filename): pixmap = self.grabWindowPixmap() ext = os.path.splitext(filename)[1].lower() if not ext: - pixmap.save(filename, 'PNG') + pixmap.accept(filename, 'PNG') elif ext == '.pdf': self.saveToPDF(filename) else: - pixmap.save(filename) + pixmap.accept(filename) def saveToPDF(self, filename): printer = QtGui.QPrinter() diff --git a/cdatgui/spreadsheet/sheet.py b/cdatgui/spreadsheet/sheet.py index fc11820..f0d3593 100755 --- a/cdatgui/spreadsheet/sheet.py +++ b/cdatgui/spreadsheet/sheet.py @@ -232,7 +232,7 @@ def paint(self, painter, option, index): """ QtGui.QItemDelegate.paint(self, painter, option, index) if ((index.row(), index.column()) == self.table.activeCell): - painter.save() + painter.accept() painter.setPen(QtGui.QPen(QtGui.QBrush( QtGui.QColor(0.8549 * 255, 0.6971 * 255, 0.2255 * 255)), self.padding)) r = self.table.visualRect(index) diff --git a/cdatgui/spreadsheet/tab.py b/cdatgui/spreadsheet/tab.py index bf9a555..1942fd6 100755 --- a/cdatgui/spreadsheet/tab.py +++ b/cdatgui/spreadsheet/tab.py @@ -411,9 +411,9 @@ def exportSheetToImages(self, dirPath, format='png'): for c in xrange(cCount): widget = self.getCell(r, c) if widget: - widget.grabWindowPixmap().save(dirPath + '/' + - chr(c + ord('a')) + - str(r + 1) + + widget.grabWindowPixmap().accept(dirPath + '/' + + chr(c + ord('a')) + + str(r + 1) + '.' + format) def setSpan(self, row, col, rowSpan, colSpan): @@ -538,6 +538,7 @@ def colSpinBoxChanged(self): self.totalPlotsChanged() def replotPlottersUpdateVars(self): + total_tabs = [] plots = [] for row in range(self.toolBar.rowSpinBox.value()): @@ -550,6 +551,7 @@ def replotPlottersUpdateVars(self): plots.extend(plotter) for plot in plots: if plot.can_plot(): + print "plotting cause updated", plot.variables[0].id, plot.graphics_method.name plot.plot() self.emitAllPlots.emit(total_tabs) diff --git a/cdatgui/vcsmodel/elements.py b/cdatgui/vcsmodel/elements.py index f6c977b..b3162a6 100644 --- a/cdatgui/vcsmodel/elements.py +++ b/cdatgui/vcsmodel/elements.py @@ -56,7 +56,6 @@ def updated(self, el_name): self.endInsertRows() def remove(self, el_name): - print "in remove" new_els = [] remove_ind = -1 remove_me = el_name @@ -68,11 +67,9 @@ def remove(self, el_name): new_els.append(name) if remove_ind == -1: - print "returning" return self.beginRemoveRows(QtCore.QModelIndex(), remove_ind, remove_ind) - print "REMOVING" self.elements = new_els self.endRemoveRows() diff --git a/tests/test_AxisEditor.py b/tests/test_AxisEditor.py index 04c7217..3baa8df 100644 --- a/tests/test_AxisEditor.py +++ b/tests/test_AxisEditor.py @@ -7,14 +7,13 @@ @pytest.fixture def editors(): - box = vcs.createboxfill() - tmpl = vcs.createtemplate() var = cdms2.open(vcs.sample_data + "/clt.nc")("clt") - axis = VCSAxis(box, tmpl, "y1", var) + axis = VCSAxis(vcs.createboxfill(), vcs.createtemplate(), "y1", var) edit_1 = AxisEditorWidget("x") edit_1.setAxisObject(axis) + axis = VCSAxis(vcs.createboxfill(), vcs.createtemplate(), "y1", var) edit_2 = AxisEditorWidget("y") edit_2.setAxisObject(axis) @@ -30,27 +29,41 @@ def test_presets(qtbot, editors): assert editor.object.ticks == "lat5" -def test_miniticks(editors): +def test_miniticks(qtbot, editors): for index, editor in enumerate(editors): # don't need this line once default is fixed + editor.preset_box.setCurrentIndex(editor.preset_box.findText('lat5')) editor.updatePreset("lat5") + assert editor.object.ticks == "lat5" button_list = editor.tickmark_button_group.buttons() for button in button_list: + print "button", button.text() + assert editor.object.gm.name in vcs.listelements('boxfill') editor.updateTickmark(button) + print "after update tickmark" + assert editor.object.gm.name in vcs.listelements('boxfill') show_mini_check_box = editor.adjuster_layout.itemAt(3 - index).layout().itemAt(1).widget() show_mini_check_box.setCheckState(QtCore.Qt.Checked) assert editor.object.show_miniticks + print "after update show mini" + assert editor.object.gm.name in vcs.listelements('boxfill') + mini_ticks_box = editor.adjuster_layout.itemAt(3 - index).layout().itemAt(3).widget() mini_ticks_box.setValue(4) assert editor.object.minitick_count == 4 + print "after update mini count" + assert editor.object.gm.name in vcs.listelements('boxfill') + show_mini_check_box.setCheckState(QtCore.Qt.Unchecked) assert not editor.object.show_miniticks + assert editor.object.gm.name in vcs.listelements('boxfill') + editor.reject() def test_step_ticks_negative(qtbot, editors): @@ -104,7 +117,7 @@ def test_step_ticks_negative(qtbot, editors): editor.negative_check.setCheckState(QtCore.Qt.Checked) -def test_dict(editors): +def test_dict(qtbot, editors): for editor in editors: dict = {30: "30N", 20: "20N", 10: "10N", 0: "0"} editor.updateAxisWithDict(dict) @@ -112,7 +125,7 @@ def test_dict(editors): assert editor.object.ticks == dict -def test_reset_preview(editors): +def test_reset_preview(qtbot, editors): for editor in editors: with pytest.raises(Exception): editor.setPreview(AxisPreviewWidget()) diff --git a/tests/test_BaseWindow.py b/tests/test_BaseWindow.py index ec8cfcc..9f1fffd 100644 --- a/tests/test_BaseWindow.py +++ b/tests/test_BaseWindow.py @@ -29,7 +29,7 @@ def save_as(name): def test_save(qtbot, window): base = window base.accepted.connect(save) - base.save() + base.accept() def test_save_as(qtbot, window): diff --git a/tests/test_GmDialog.py b/tests/test_GmDialog.py index 9060913..6e795d5 100644 --- a/tests/test_GmDialog.py +++ b/tests/test_GmDialog.py @@ -186,7 +186,7 @@ def test_saveDialog(qtbot, save_dialog): def test_okDialog(qtbot, ok_dialog): assert ok_dialog.origgm_name == 'a_boxfill' - ok_dialog.okClicked() + ok_dialog.accept() assert ok_dialog.newgm_name not in vcs.listelements('boxfill') diff --git a/tests/test_LineEditor.py b/tests/test_LineEditor.py index 20cf8b5..142e44f 100644 --- a/tests/test_LineEditor.py +++ b/tests/test_LineEditor.py @@ -16,7 +16,7 @@ def test_type(qtbot, editor): editor.updateType('dash') assert editor.object.type == ['dash'] - editor.save() + editor.accept() assert vcs.elements['line']['cyan'].type == ['dash'] assert editor.newline_name not in vcs.listelements('line') @@ -27,7 +27,7 @@ def test_color(qtbot, editor): editor.saveAs() editor.win.setTextValue('check') - editor.save() + editor.accept() assert 'check' in vcs.listelements('line') assert vcs.elements['line']['check'].color == [55] @@ -40,7 +40,7 @@ def test_width(qtbot, editor): editor.updateWidth(250) assert editor.object.width == [250] - editor.save() + editor.accept() assert vcs.elements['line']['cyan'].width == [250] assert editor.newline_name not in vcs.listelements('line') diff --git a/tests/test_MultiLineEditor.py b/tests/test_MultiLineEditor.py index 6bd5567..0cd4b1f 100644 --- a/tests/test_MultiLineEditor.py +++ b/tests/test_MultiLineEditor.py @@ -65,7 +65,7 @@ def test_MultiLineEditor(qtbot, line_editor): editor.update(4, 'dummy') assert editor.line_combos[4].currentText() == 'dummy' - editor.okClicked() + editor.accept() # check and see if the isoline was updated when combo changed and ok was pressed assert gm.linecolors[2] == 254 @@ -105,7 +105,7 @@ def test_MultiTextEditor(qtbot, text_editor): editor.update(3, 'dummy') assert editor.text_combos[3].currentText() == 'dummy' - editor.okClicked() + editor.accept() # check and see if the isoline was updated when combo changed and ok was pressed assert vcs.gettextcombined(gm.text[3], gm.text[3]).name == 'dummy:::dummy' diff --git a/tests/test_ProjectionEditor.py b/tests/test_ProjectionEditor.py index 75e0523..8320c58 100644 --- a/tests/test_ProjectionEditor.py +++ b/tests/test_ProjectionEditor.py @@ -29,7 +29,7 @@ def test_changingNameAndType(qtbot, editor): assert editor.cur_projection_name == 'orthographic' assert editor.type_combo.currentText() == 'hotin oblique merc' - editor.save() + editor.accept() assert vcs.elements['projection']['orthographic'] != orig_ortho assert vcs.elements['projection']['orthographic'].type == 'hotin oblique merc' @@ -77,7 +77,7 @@ def test_settingAttributes(qtbot, editor): editor.type_combo.setCurrentIndex(editor.type_combo.findText('robinson')) editor.editors[0][0].setText('12') - editor.save() + editor.accept() old_proj = vcs.getprojection(old_proj_name) assert old_proj.type == 'robinson' diff --git a/tests/test_TextStyleEditor.py b/tests/test_TextStyleEditor.py index a9380b7..415dde0 100755 --- a/tests/test_TextStyleEditor.py +++ b/tests/test_TextStyleEditor.py @@ -51,7 +51,7 @@ def test_alignment(qtbot, editor): # test save as well editor.saved.connect(save_check) - editor.save() + editor.accept() def test_angle(editor): @@ -63,7 +63,7 @@ def test_angle(editor): editor.updateAngle(440) assert editor.object.angle == 80 - editor.save() + editor.accept() def test_font(editor): @@ -73,7 +73,7 @@ def test_font(editor): editor.updateFont("Chinese") assert editor.object.font == 8 - editor.save() + editor.accept() def test_size(editor): @@ -82,7 +82,7 @@ def test_size(editor): editor.updateSize(50) assert editor.object.height == 50 - editor.save() + editor.accept() def saveas_check(name): From 9a0e9c97571e902d4f7f758a5959cdd1784774b0 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Thu, 19 May 2016 13:25:28 -0700 Subject: [PATCH 25/29] PR update. Added save ticks option --- cdatgui/bases/input_dialog.py | 6 ++--- cdatgui/bases/vcs_elements_dialog.py | 10 +++---- cdatgui/cdat/plotter.py | 1 - cdatgui/console/console_widget.py | 3 ++- cdatgui/constants.py | 5 ++++ cdatgui/editors/axis_editor.py | 24 ++++++++++++++--- cdatgui/editors/model/vcsaxis.py | 28 +++++++++++++++----- cdatgui/editors/projection_editor.py | 6 ++--- cdatgui/editors/widgets/color_table.py | 1 - cdatgui/editors/widgets/multi_line_editor.py | 6 ++--- cdatgui/editors/widgets/multi_text_editor.py | 6 ++--- cdatgui/graphics/dialog.py | 4 +-- cdatgui/spreadsheet/tab.py | 1 - cdatgui/templates/dialog.py | 4 +-- cdatgui/variables/__init__.py | 7 ----- cdatgui/variables/models.py | 1 - cdatgui/variables/variable_add.py | 3 ++- tests/test_GmDialog.py | 2 +- 18 files changed, 74 insertions(+), 44 deletions(-) create mode 100644 cdatgui/constants.py diff --git a/cdatgui/bases/input_dialog.py b/cdatgui/bases/input_dialog.py index efa8beb..38c7766 100644 --- a/cdatgui/bases/input_dialog.py +++ b/cdatgui/bases/input_dialog.py @@ -1,12 +1,12 @@ from PySide import QtCore, QtGui -class AccessableButtonDialog(QtGui.QWidget): +class AccessibleButtonDialog(QtGui.QWidget): accepted = QtCore.Signal() rejected = QtCore.Signal() def __init__(self): - super(AccessableButtonDialog, self).__init__() + super(AccessibleButtonDialog, self).__init__() self.setWindowModality(QtCore.Qt.ApplicationModal) shortcut = QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Escape), self) @@ -39,7 +39,7 @@ def save(self): self.accepted.emit() -class ValidatingInputDialog(AccessableButtonDialog): +class ValidatingInputDialog(AccessibleButtonDialog): def __init__(self): super(ValidatingInputDialog, self).__init__() diff --git a/cdatgui/bases/vcs_elements_dialog.py b/cdatgui/bases/vcs_elements_dialog.py index 850812c..c45dd12 100644 --- a/cdatgui/bases/vcs_elements_dialog.py +++ b/cdatgui/bases/vcs_elements_dialog.py @@ -3,14 +3,14 @@ import vcs -class VcsElementsDialog(ValidatingInputDialog): +class VCSElementsDialog(ValidatingInputDialog): def __init__(self, element): - super(VcsElementsDialog, self).__init__() + super(VCSElementsDialog, self).__init__() self.element = element - self.setValidator(VcsElementsValidator()) + self.setValidator(VCSElementsValidator()) def save(self): - if self.textValue() in vcs.elements[self.element]: + if self.textValue() in vcs.elements[self.element] or self.textValue() + '_miniticks' in vcs.elements[self.element]: check = QtGui.QMessageBox.question(self, "Overwrite {0}?".format(self.element), "{0} '{1}' already exists. Overwrite?".format(self.element.capitalize(), self.textValue()), buttons=QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) @@ -22,7 +22,7 @@ def save(self): self.accepted.emit() -class VcsElementsValidator(QtGui.QValidator): +class VCSElementsValidator(QtGui.QValidator): invalidInput = QtCore.Signal() validInput = QtCore.Signal() diff --git a/cdatgui/cdat/plotter.py b/cdatgui/cdat/plotter.py index 3bccb3b..a8b3d5e 100644 --- a/cdatgui/cdat/plotter.py +++ b/cdatgui/cdat/plotter.py @@ -269,7 +269,6 @@ def plot(self): args.append(vcs.graphicsmethodtype(self.graphics_method)) args.append(self.graphics_method.name) - print "updating by clear and replotting" self.canvas.clear(preserve_display=True, render=False) self.dp = self.canvas.plot(*args) diff --git a/cdatgui/console/console_widget.py b/cdatgui/console/console_widget.py index 33797aa..7f27887 100644 --- a/cdatgui/console/console_widget.py +++ b/cdatgui/console/console_widget.py @@ -8,7 +8,8 @@ from qtconsole.rich_jupyter_widget import RichJupyterWidget from cdatgui.cdat.metadata import FileMetadataWrapper, VariableMetadataWrapper -from cdatgui.variables import get_variables, reserved_words +from cdatgui.variables import get_variables +from cdatgui.constants import reserved_words def is_cdms_var(v): diff --git a/cdatgui/constants.py b/cdatgui/constants.py new file mode 100644 index 0000000..fb3efa0 --- /dev/null +++ b/cdatgui/constants.py @@ -0,0 +1,5 @@ +def reserved_words(): + return ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global', 'or', 'with', + 'assert', 'else', 'if', 'pass', 'yield', 'break', 'except', 'import', 'print', 'class', + 'exec', 'in', 'raise', 'continue', 'finally', 'is', 'return', 'def', 'for', 'lambda', + 'try'] diff --git a/cdatgui/editors/axis_editor.py b/cdatgui/editors/axis_editor.py index 7c22d4d..23e195f 100644 --- a/cdatgui/editors/axis_editor.py +++ b/cdatgui/editors/axis_editor.py @@ -1,15 +1,18 @@ from PySide import QtGui, QtCore -from cdatgui.bases.window_widget import BaseOkWindowWidget + +from cdatgui.bases.vcs_elements_dialog import VCSElementsDialog +from cdatgui.bases.window_widget import BaseSaveWindowWidget from cdatgui.editors.preview.axis_preview import AxisPreviewWidget from cdatgui.editors.widgets.dict_editor import DictEditorWidget import vcs -class AxisEditorWidget(BaseOkWindowWidget): +class AxisEditorWidget(BaseSaveWindowWidget): def __init__(self, axis, parent=None): super(AxisEditorWidget, self).__init__() self.axis = axis self.state = None + self.setSaveDialog(VCSElementsDialog('line')) # create layout so you can set the preview self.horizontal_layout = QtGui.QHBoxLayout() @@ -128,6 +131,16 @@ def setPreview(self, preview): def setAxisObject(self, axis_obj): self.object = axis_obj + + # initialize combo value + if isinstance(axis_obj.ticks, str): + if axis_obj.ticks == '*': + ticks = 'default' + else: + ticks = axis_obj.ticks + self.preset_box.setCurrentIndex(self.preset_box.findText(ticks)) + self.updatePreset(ticks) + self.preview.setAxisObject(self.object) if self.object.numticks: if self.object.is_positive(): @@ -149,7 +162,7 @@ def setAxisObject(self, axis_obj): button.setEnabled(False) self.preview.update() - self.accepted.connect(self.object.save) + self.accepted.connect(self.saveTicks) self.rejected.connect(self.object.cancel) # Update mode essentially @@ -188,6 +201,7 @@ def updateTickmark(self, button): def updatePreset(self, preset): if preset == "default": self.object.ticks = "*" + self.save_button.setEnabled(False) self.mini_tick_box.setEnabled(False) self.show_mini_check_box.setEnabled(False) for button in self.tickmark_button_group.buttons(): @@ -195,6 +209,7 @@ def updatePreset(self, preset): button.setEnabled(False) else: self.object.ticks = preset + self.save_button.setEnabled(True) self.mini_tick_box.setEnabled(True) self.show_mini_check_box.setEnabled(True) for button in self.tickmark_button_group.buttons(): @@ -268,3 +283,6 @@ def updateTickSign(self): self.step_edit.setText(str(-val)) self.preview.update() + + def saveTicks(self, name): + self.object.save(name) diff --git a/cdatgui/editors/model/vcsaxis.py b/cdatgui/editors/model/vcsaxis.py index b34f458..bd09bee 100644 --- a/cdatgui/editors/model/vcsaxis.py +++ b/cdatgui/editors/model/vcsaxis.py @@ -9,6 +9,7 @@ def __init__(self, gm, tmpl, axis, var): self.orig_tmpl_name = tmpl.name self._axis = axis self.var = var + self.name = None @property def axis(self): @@ -45,6 +46,12 @@ def ticks(self, val): minitick_count = self.minitick_count else: minitick_count = 0 + if isinstance(val, str): + if val == '*': + self.name = None + else: + self.name = val + if self._axis == "x1": self.gm.xticlabels1 = val if self._axis == "x2": @@ -96,7 +103,7 @@ def mode(self): @mode.setter def mode(self, value): # if value == "auto" and isinstance(self.ticks, dict): - # self.ticks = "*" + # self.ticks = "*" if value == 'even' and isinstance(self.ticks, str): if self.ticks != "*": step = self.step @@ -220,18 +227,27 @@ def ticks_as_dict(self): ticks = vcs.elements["list"][ticks] return ticks - def save(self): + def save(self, name): + if name is None: + raise Exception( + "Non str name cannot be used to save ticks") # something got through your rock solid wall of logic + + if isinstance(self.ticks, str): + vcs.elements["list"][name] = vcs.elements['list'][self.ticks] + else: + vcs.elements["list"][name] = self.ticks + vcs.elements["list"][name + "_miniticks"] = self.miniticks + + self.ticks = name + self.miniticks = name + "_miniticks" + gtype = vcs.graphicsmethodtype(self.gm) del vcs.elements[gtype][self.orig_gm_name] vcs.elements[gtype][self.orig_gm_name] = self.gm del vcs.elements['template'][self.orig_tmpl_name] vcs.elements['template'][self.orig_tmpl_name] = self.tmpl - # vcs.elements["list"][name] = self.ticks - # vcs.elements["list"][name + "_miniticks"] = self.miniticks - def cancel(self): gtype = vcs.graphicsmethodtype(self.gm) del vcs.elements[gtype][self.gm.name] del vcs.elements['template'][self.tmpl.name] - diff --git a/cdatgui/editors/projection_editor.py b/cdatgui/editors/projection_editor.py index e06b790..495da88 100644 --- a/cdatgui/editors/projection_editor.py +++ b/cdatgui/editors/projection_editor.py @@ -3,14 +3,14 @@ from cdatgui.bases.window_widget import BaseSaveWindowWidget from cStringIO import StringIO from cdatgui.utils import label -from cdatgui.bases.vcs_elements_dialog import VcsElementsDialog, VcsElementsValidator +from cdatgui.bases.vcs_elements_dialog import VCSElementsDialog, VCSElementsValidator class ProjectionEditor(BaseSaveWindowWidget): def __init__(self): super(ProjectionEditor, self).__init__() - dialog = VcsElementsDialog('projection') - dialog.setValidator(VcsElementsValidator()) + dialog = VCSElementsDialog('projection') + dialog.setValidator(VCSElementsValidator()) self.setSaveDialog(dialog) self.orig_projection = None self.cur_projection_name = None diff --git a/cdatgui/editors/widgets/color_table.py b/cdatgui/editors/widgets/color_table.py index 5a94df2..b3b40d3 100644 --- a/cdatgui/editors/widgets/color_table.py +++ b/cdatgui/editors/widgets/color_table.py @@ -63,7 +63,6 @@ def update_selection(self): self.singleColorSelected.emit(self.row_col_to_ind(sel.topRow(), sel.leftColumn())) return else: - print "Emitting None" self.singleColorSelected.emit(None) diff --git a/cdatgui/editors/widgets/multi_line_editor.py b/cdatgui/editors/widgets/multi_line_editor.py index 473c134..5d1047c 100644 --- a/cdatgui/editors/widgets/multi_line_editor.py +++ b/cdatgui/editors/widgets/multi_line_editor.py @@ -6,7 +6,7 @@ from cdatgui.bases.dynamic_grid_layout import DynamicGridLayout import vcs from cdatgui.vcsmodel import get_lines -from cdatgui.bases.vcs_elements_dialog import VcsElementsDialog, VcsElementsValidator +from cdatgui.bases.vcs_elements_dialog import VCSElementsDialog, VCSElementsValidator class MultiLineEditor(BaseOkWindowWidget): @@ -66,8 +66,8 @@ def editLine(self, index): self.line_editor.close() self.line_editor.deleteLater() self.line_editor = LineEditorWidget() - dialog = VcsElementsDialog('line') - dialog.setValidator(VcsElementsValidator()) + dialog = VCSElementsDialog('line') + dialog.setValidator(VCSElementsValidator()) self.line_editor.setSaveDialog(dialog) line = self.isoline_model.line[index] diff --git a/cdatgui/editors/widgets/multi_text_editor.py b/cdatgui/editors/widgets/multi_text_editor.py index bf6d6b0..1a87b0e 100644 --- a/cdatgui/editors/widgets/multi_text_editor.py +++ b/cdatgui/editors/widgets/multi_text_editor.py @@ -6,7 +6,7 @@ from cdatgui.bases.dynamic_grid_layout import DynamicGridLayout import vcs from cdatgui.vcsmodel import get_textstyles -from cdatgui.bases.vcs_elements_dialog import VcsElementsDialog, VcsElementsValidator +from cdatgui.bases.vcs_elements_dialog import VCSElementsDialog, VCSElementsValidator class MultiTextEditor(BaseOkWindowWidget): @@ -66,8 +66,8 @@ def editText(self, index): self.text_editor.close() self.text_editor.deleteLater() self.text_editor = TextStyleEditorWidget() - dialog = VcsElementsDialog('texttable') - dialog.setValidator(VcsElementsValidator()) + dialog = VCSElementsDialog('texttable') + dialog.setValidator(VCSElementsValidator()) self.text_editor.setSaveDialog(dialog) text = self.isoline_model.text[index] diff --git a/cdatgui/graphics/dialog.py b/cdatgui/graphics/dialog.py index 57478e4..fddf51c 100644 --- a/cdatgui/graphics/dialog.py +++ b/cdatgui/graphics/dialog.py @@ -1,6 +1,6 @@ from PySide import QtGui, QtCore -from cdatgui.bases.vcs_elements_dialog import VcsElementsDialog +from cdatgui.bases.vcs_elements_dialog import VCSElementsDialog from cdatgui.editors.boxfill import BoxfillEditor from cdatgui.editors.isofill import IsofillEditor from cdatgui.editors.meshfill import MeshfillEditor @@ -99,7 +99,7 @@ def __init__(self, gm, var, tmpl, parent=None): save.setEnabled(False) def customName(self): - self.dialog = VcsElementsDialog('boxfill') + self.dialog = VCSElementsDialog('boxfill') self.dialog.setLabelText('Name for {0}'.format(unicode(self.gmtype))) self.dialog.setWindowTitle('Save As') self.dialog.accepted.connect(self.grabGm) diff --git a/cdatgui/spreadsheet/tab.py b/cdatgui/spreadsheet/tab.py index 1942fd6..9563f22 100755 --- a/cdatgui/spreadsheet/tab.py +++ b/cdatgui/spreadsheet/tab.py @@ -551,7 +551,6 @@ def replotPlottersUpdateVars(self): plots.extend(plotter) for plot in plots: if plot.can_plot(): - print "plotting cause updated", plot.variables[0].id, plot.graphics_method.name plot.plot() self.emitAllPlots.emit(total_tabs) diff --git a/cdatgui/templates/dialog.py b/cdatgui/templates/dialog.py index 977a08b..d05c663 100644 --- a/cdatgui/templates/dialog.py +++ b/cdatgui/templates/dialog.py @@ -2,7 +2,7 @@ from cdatgui.editors.template import TemplateEditor import vcs import copy -from cdatgui.bases.vcs_elements_dialog import VcsElementsDialog +from cdatgui.bases.vcs_elements_dialog import VCSElementsDialog from cdatgui.templates import get_templates @@ -100,7 +100,7 @@ def __init__(self, tmpl, parent=None): def customName(self): # name = QtGui.QInputDialog.getText(self, u"Save As", u"Name for template:") - self.dialog = VcsElementsDialog('template') + self.dialog = VCSElementsDialog('template') self.dialog.setLabelText('Name:') self.dialog.setWindowTitle('Save As') diff --git a/cdatgui/variables/__init__.py b/cdatgui/variables/__init__.py index 56c95b2..4217627 100644 --- a/cdatgui/variables/__init__.py +++ b/cdatgui/variables/__init__.py @@ -8,10 +8,3 @@ def get_variables(): if __variables__ is None: __variables__ = models.CDMSVariableListModel() return __variables__ - - -def reserved_words(): - return ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global', 'or', 'with', - 'assert', 'else', 'if', 'pass', 'yield', 'break', 'except', 'import', 'print', 'class', - 'exec', 'in', 'raise', 'continue', 'finally', 'is', 'return', 'def', 'for', 'lambda', - 'try'] diff --git a/cdatgui/variables/models.py b/cdatgui/variables/models.py index d03f345..71a901b 100644 --- a/cdatgui/variables/models.py +++ b/cdatgui/variables/models.py @@ -11,7 +11,6 @@ def get_variable(self, var_name_or_index): return self.get(var_name_or_index) else: for v in self.values: - # print "Stored", type(v) if v[0] == var_name_or_index: return v[1] raise ValueError("No variable found with ID %s" % var_name_or_index) diff --git a/cdatgui/variables/variable_add.py b/cdatgui/variables/variable_add.py index cba9940..40c3a0a 100644 --- a/cdatgui/variables/variable_add.py +++ b/cdatgui/variables/variable_add.py @@ -7,7 +7,8 @@ from cdms_file_chooser import CDMSFileChooser from cdms_file_tree import CDMSFileTree from manager import manager -from . import get_variables, reserved_words +from . import get_variables +from cdatgui.constants import reserved_words from cdatgui.bases.input_dialog import ValidatingInputDialog diff --git a/tests/test_GmDialog.py b/tests/test_GmDialog.py index 6e795d5..b4cdf64 100644 --- a/tests/test_GmDialog.py +++ b/tests/test_GmDialog.py @@ -181,7 +181,7 @@ def test_saveDialog(qtbot, save_dialog): save_button = save_dialog.layout().itemAt(1).layout().itemAt(3).widget() assert save_button.isEnabled() == True save_dialog.customName() - assert isinstance(save_dialog.dialog, VcsElementsDialog) + assert isinstance(save_dialog.dialog, VCSElementsDialog) def test_okDialog(qtbot, ok_dialog): From 2b0fffab3dcd4ead54b72fb0768fc72cd26b83f9 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Thu, 19 May 2016 14:26:09 -0700 Subject: [PATCH 26/29] fixed plotter and tests --- cdatgui/cdat/plotter.py | 23 ++--------------------- cdatgui/sidebar/inspector_widget.py | 14 +++++++------- cdatgui/spreadsheet/vtk_classes.py | 2 ++ tests/test_GmDialog.py | 6 ++++++ tests/test_ProjectionEditor.py | 1 + tests/test_save_load.py | 8 +++++--- 6 files changed, 23 insertions(+), 31 deletions(-) diff --git a/cdatgui/cdat/plotter.py b/cdatgui/cdat/plotter.py index a8b3d5e..a27ea96 100644 --- a/cdatgui/cdat/plotter.py +++ b/cdatgui/cdat/plotter.py @@ -163,15 +163,8 @@ def gm(self): return vcs.getgraphicsmethod(self._type, self._gm) def set_gm(self, gm): - plot = True - if isinstance(gm, tuple): - plot = gm[1] - gm = gm[0] - self._gm = gm.name self._type = vcs.graphicsmethodtype(gm) - if plot and self.can_plot(): - self.plot() self.source.gm_label.setText(self._gm) graphics_method = property(gm, set_gm) @@ -180,10 +173,6 @@ def get_vars(self): return self._vars def set_vars(self, v): - plot = True - if len(v) > 2: - plot = v[2] - v = v[:2] try: self._vars = (v[0], v[1]) except TypeError: @@ -199,8 +188,6 @@ def set_vars(self, v): else: new_vars.append(var) self._vars = new_vars - if plot and self.can_plot(): - self.plot() valid_vars = [] for v in self._vars: @@ -219,15 +206,7 @@ def templ(self): def set_templ(self, template): # Check if gm supports templates - plot = True - if isinstance(template, tuple): - plot = template[1] - template = template[0] - self._template = template - if plot and self.can_plot(): - self.plot() - self.source.tmpl_label.setText(self.template.name) template = property(templ, set_templ) @@ -240,6 +219,8 @@ def remove(self): self.removed.emit() def plot(self): + if not self.can_plot(): + raise Exception("Attempted plot when can_plot not valid") if self.variables is None: raise ValueError("No variables specified") diff --git a/cdatgui/sidebar/inspector_widget.py b/cdatgui/sidebar/inspector_widget.py index 771a637..9be1247 100644 --- a/cdatgui/sidebar/inspector_widget.py +++ b/cdatgui/sidebar/inspector_widget.py @@ -171,13 +171,13 @@ def editSecondVar(self, var): def editGraphicsMethod(self, gm): get_gms().replace(get_gms().indexOf(vcs.graphicsmethodtype(gm), gm), gm) - self.current_plot.graphics_method = (gm, False) + self.current_plot.graphics_method = gm self.plotters_updated.emit() def makeGraphicsMethod(self, gm): get_gms().add_gm(gm) self.gm_instance_combo.setCurrentIndex(self.gm_instance_combo.count() - 1) - self.current_plot.graphics_method = (gm, False) + self.current_plot.graphics_method = gm self.plotters_updated.emit() def editGM(self): @@ -214,7 +214,7 @@ def setGMRoot(self, index): self.edit_gm_button.setEnabled(False) def setTemplate(self, template): - self.current_plot.template = (template, False) + self.current_plot.template = template self.plotters_updated.emit() def updateGM(self, index): @@ -235,21 +235,21 @@ def updateGM(self, index): if enabled and self.var_combos[1].currentIndex() == -1: gm = vcs.getgraphicsmethod(gm_type, gm_name) - self.current_plot.graphics_method = (gm, False) + self.current_plot.graphics_method = gm else: gm = vcs.getgraphicsmethod(gm_type, gm_name) - self.current_plot.graphics_method = (gm, False) + self.current_plot.graphics_method = gm self.plotters_updated.emit() def setFirstVar(self, var): - self.current_plot.variables = [var, self.current_plot.variables[1], False] + self.current_plot.variables = [var, self.current_plot.variables[1]] self.plotters_updated.emit() def setSecondVar(self, var): old_vars = self.current_plot.variables try: - self.current_plot.variables = [self.current_plot.variables[0], var.var, False] + self.current_plot.variables = [self.current_plot.variables[0], var.var] except ValueError: old_vars.append(False) self.current_plot.variables = old_vars diff --git a/cdatgui/spreadsheet/vtk_classes.py b/cdatgui/spreadsheet/vtk_classes.py index 40b89f0..4ffa8d3 100755 --- a/cdatgui/spreadsheet/vtk_classes.py +++ b/cdatgui/spreadsheet/vtk_classes.py @@ -123,6 +123,8 @@ def dropEvent(self, event): if vcs_gm_mime in event.mimeData().formats(): event.accept() target.graphics_method(dropped) + if target.manager.can_plot(): + target.manager.plot() self.iren.show() self.dragTarget.hide() diff --git a/tests/test_GmDialog.py b/tests/test_GmDialog.py index b4cdf64..b3451a1 100644 --- a/tests/test_GmDialog.py +++ b/tests/test_GmDialog.py @@ -86,6 +86,7 @@ def test_boxfillDialog(qtbot, boxfill_dialog): # test ticks dialogs editor.editLeft() + qtbot.addWidget(editor.axis_editor) assert editor.axis_editor assert editor.axis_editor.axis == 'y1' @@ -93,12 +94,14 @@ def test_boxfillDialog(qtbot, boxfill_dialog): assert editor.axis_editor is None editor.editRight() + qtbot.addWidget(editor.axis_editor) assert editor.axis_editor.axis == 'y2' editor.updated() assert editor.axis_editor is None editor.editBottom() + qtbot.addWidget(editor.axis_editor) assert editor.axis_editor.axis == 'x1' editor.updated() @@ -118,6 +121,7 @@ def test_boxfillDialog(qtbot, boxfill_dialog): # editor.updated() editor.editProjection() + qtbot.addWidget(editor.projection_editor) assert editor.projection_editor assert editor.projection_editor.cur_projection_name == 'linear' editor.projection_editor.close() @@ -181,6 +185,7 @@ def test_saveDialog(qtbot, save_dialog): save_button = save_dialog.layout().itemAt(1).layout().itemAt(3).widget() assert save_button.isEnabled() == True save_dialog.customName() + qtbot.addWidget(save_dialog.dialog) assert isinstance(save_dialog.dialog, VCSElementsDialog) @@ -193,6 +198,7 @@ def test_okDialog(qtbot, ok_dialog): def test_saveButtonDisabled(qtbot): s = get_var() d = GraphicsMethodSaveDialog(vcs.getisoline('default'), s, vcs.createtemplate()) + qtbot.addWidget(d) save_button = d.layout().itemAt(1).layout().itemAt(3).widget() assert save_button.isEnabled() == False diff --git a/tests/test_ProjectionEditor.py b/tests/test_ProjectionEditor.py index 8320c58..5d1246e 100644 --- a/tests/test_ProjectionEditor.py +++ b/tests/test_ProjectionEditor.py @@ -84,6 +84,7 @@ def test_settingAttributes(qtbot, editor): assert old_proj.sphere == 12.0 new_editor = ProjectionEditor() + qtbot.addWidget(new_editor) new_editor.setProjectionObject(old_proj) new_editor.gm = editor.gm assert new_editor.editors[0][0].text() == '12.0' diff --git a/tests/test_save_load.py b/tests/test_save_load.py index 883aa3f..6367a13 100644 --- a/tests/test_save_load.py +++ b/tests/test_save_load.py @@ -38,14 +38,15 @@ def test_save_and_load_script(tmpdir, qtbot): pi = PlotInfo(vcs.init(), 0, 0) qtbot.addWidget(pi) pm = PlotManager(pi) - pm.graphics_method = vcs.getboxfill("default") - pm.template = vcs.gettemplate('default') - + pm.graphics_method = vcs.createboxfill(source="default") + pm.template = vcs.createtemplate(source='default') f = cdms2.open(vcs.sample_data + "/clt.nc") fmw = FileMetadataWrapper(f) clt = fmw["clt"] pm.variables = [clt.var, None] + + pm.plot() pi.canvas.close() export_script(path, [clt], [[pm]]) @@ -96,6 +97,7 @@ def test_save_loaded_script(tmpdir, qtbot): pm.template = vcs.gettemplate(display._template_origin) pm.variables = display.array pm_group.append(pm) + pm.plot() plot_managers.append(pm_group) export_script(str(save_file), loaded.variables.values(), plot_managers) From a643900f155a9f74250f6ed7fc5e2fb7cd5673f3 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Thu, 26 May 2016 10:18:24 -0700 Subject: [PATCH 27/29] fixed colormap editor and fixed part of legend editor to incorporate vcs fixes. Missing level stil in legend --- cdatgui/bases/background_delegate.py | 24 +++++++++---------- cdatgui/editors/boxfill.py | 17 ++++++++++++-- cdatgui/editors/colormap.py | 12 ++++++---- cdatgui/editors/graphics_method_editor.py | 9 ++++---- cdatgui/editors/model/legend.py | 12 ++++++---- cdatgui/editors/model/levels_base.py | 11 +++------ cdatgui/editors/widgets/color_table.py | 10 +++++++- cdatgui/editors/widgets/legend_widget.py | 28 ++++++++++++++++++++--- cdatgui/spreadsheet/sheet.py | 2 +- 9 files changed, 85 insertions(+), 40 deletions(-) diff --git a/cdatgui/bases/background_delegate.py b/cdatgui/bases/background_delegate.py index d179225..b67d2a5 100644 --- a/cdatgui/bases/background_delegate.py +++ b/cdatgui/bases/background_delegate.py @@ -2,15 +2,15 @@ class BorderHighlightStyleDelegate(QtGui.QStyledItemDelegate): - def paint(self, painter, option, index): - bg = index.data(QtCore.Qt.BackgroundRole) - painter.fillRect(option.rect, bg) - super(BorderHighlightStyleDelegate, self).paint(painter, option, index) - if option.state & QtGui.QStyle.State_Selected: - painter.accept() - color = QtGui.QColor(76, 177 ,255) - pen = QtGui.QPen(color, 2, QtCore.Qt.SolidLine, QtCore.Qt.SquareCap, QtCore.Qt.MiterJoin) - w = pen.width() / 2 - painter.setPen(pen) - painter.drawRect(option.rect.adjusted(w, w, -w, -w)) - painter.restore() + def paint(self, painter, option, index): + bg = index.data(QtCore.Qt.BackgroundRole) + painter.fillRect(option.rect, bg) + super(BorderHighlightStyleDelegate, self).paint(painter, option, index) + if option.state & QtGui.QStyle.State_Selected: + painter.save() + color = QtGui.QColor(76, 177, 255) + pen = QtGui.QPen(color, 2, QtCore.Qt.SolidLine, QtCore.Qt.SquareCap, QtCore.Qt.MiterJoin) + w = pen.width() / 2 + painter.setPen(pen) + painter.drawRect(option.rect.adjusted(w, w, -w, -w)) + painter.restore() diff --git a/cdatgui/editors/boxfill.py b/cdatgui/editors/boxfill.py index 510d654..f5ade0b 100644 --- a/cdatgui/editors/boxfill.py +++ b/cdatgui/editors/boxfill.py @@ -1,6 +1,8 @@ from PySide import QtGui, QtCore from collections import OrderedDict +import numpy, vcs + from .graphics_method_editor import GraphicsMethodEditorWidget @@ -32,6 +34,15 @@ def __init__(self, parent=None): self.button_layout.insertLayout(0, button_layout) self.levels_button.setEnabled(False) + self.graphicsMethodUpdated.connect(self.updateLegendButton) + + def updateLegendButton(self): + levs = self._gm.getlevels(*vcs.minmax(self.var)) + if len(levs) == 2 and numpy.allclose(levs, [1e+20] * 2): + self.legend_button.setEnabled(False) + else: + self.legend_button.setEnabled(True) + @property def gm(self): """GM property.""" @@ -49,11 +60,13 @@ def gm(self, value): def setBoxfillType(self, radio): """Take in a radio button and set the GM boxfill_type.""" + box_type = self.boxfill_types[radio.text()] + self._gm.boxfill_type = box_type + if radio.text() == 'Custom': self.levels_button.setEnabled(True) + self.updateLegendButton() else: self.levels_button.setEnabled(False) - box_type = self.boxfill_types[radio.text()] - self._gm.boxfill_type = box_type diff --git a/cdatgui/editors/colormap.py b/cdatgui/editors/colormap.py index de40be1..5148bdb 100644 --- a/cdatgui/editors/colormap.py +++ b/cdatgui/editors/colormap.py @@ -95,10 +95,13 @@ def __init__(self, mode=COLORMAP_MODE, parent=None): def acceptClicked(self): # Make sure the colormap changes take effect - self.applyChanges() - self.choseColormap.emit(str(self.colormap.currentText())) - if self.mode == COLOR_MODE: - self.choseColorIndex.emit(self.cell) + if self.colormap.currentText() == 'default': + QtGui.QMessageBox.information(self, 'Cannot Modify', 'Cannot modify the default colormap') + else: + self.applyChanges() + self.choseColormap.emit(str(self.colormap.currentText())) + if self.mode == COLOR_MODE: + self.choseColorIndex.emit(self.cell) def selectedCell(self, ind): self.cell = ind @@ -135,6 +138,7 @@ def colorChanged(self): self.colors.set_cell(self.cell, cr, cg, cb, ca) def rejectChanges(self): + self.colors.reject() self.close() def save(self): diff --git a/cdatgui/editors/graphics_method_editor.py b/cdatgui/editors/graphics_method_editor.py index 0c36403..ffe2ea7 100644 --- a/cdatgui/editors/graphics_method_editor.py +++ b/cdatgui/editors/graphics_method_editor.py @@ -1,7 +1,6 @@ from PySide import QtGui, QtCore import vcs -from cdatgui.editors.model.legend import VCSLegend from cdatgui.editors.widgets.legend_widget import LegendEditorWidget from cdatgui.editors.projection_editor import ProjectionEditor from level_editor import LevelEditor @@ -11,8 +10,7 @@ class GraphicsMethodEditorWidget(QtGui.QWidget): """Configures a boxfill graphics method.""" - - graphicsMethodUpdated = QtCore.Signal(object) + graphicsMethodUpdated = QtCore.Signal() def __init__(self, parent=None): """Initialize the object.""" @@ -87,6 +85,7 @@ def editLevels(self): def updated(self): if self.legend_editor is not None: + self._gm = self.legend_editor.gm self.legend_editor.deleteLater() self.legend_editor = None if self.axis_editor is not None: @@ -98,6 +97,7 @@ def updated(self): if self.projection_editor is not None: self.projection_editor.deleteLater() self.projection_editor = None + self.graphicsMethodUpdated.emit() @property def gm(self): @@ -113,8 +113,7 @@ def editLegend(self): self.legend_editor = LegendEditorWidget() self.legend_editor.accepted.connect(self.updated) self.legend_editor.rejected.connect(self.updated) - legend = VCSLegend(self.gm, self.var.var) - self.legend_editor.setObject(legend) + self.legend_editor.createAndSetObject(self.gm, self.var.var) self.legend_editor.show() self.legend_editor.raise_() diff --git a/cdatgui/editors/model/legend.py b/cdatgui/editors/model/legend.py index 3a18c07..9d41bf4 100644 --- a/cdatgui/editors/model/legend.py +++ b/cdatgui/editors/model/legend.py @@ -82,9 +82,9 @@ def fill_style(self, style): def adjust_to_level_length(self, lst): # +1 for invisible level - while len(lst) < len(self.levels)+1: + while len(lst) < len(self.levels) + 1: lst.append(lst[-1]) - while len(lst) > len(self.levels)+1: + while len(lst) > len(self.levels) + 1: lst.pop() @property @@ -181,13 +181,17 @@ def label_mode(self, v): self.labels = {} else: if vcs.isboxfill(self._gm): - self.labels = self._gm.autolabels(self._var) + min, max = vcs.minmax(self._var) + levels = self._gm.getlevels(min, max) + self.labels = self._gm.getlegendlabels(levels) @property def labels(self): if self._gm.legend is None: if vcs.isboxfill(self._gm): - return self._gm.autolabels(self._var) + min, max = vcs.minmax(self._var) + levels = self._gm.getlevels(min, max) + return self._gm.getlegendlabels(levels) return self._gm.legend @labels.setter diff --git a/cdatgui/editors/model/levels_base.py b/cdatgui/editors/model/levels_base.py index 6b0624a..6a32620 100644 --- a/cdatgui/editors/model/levels_base.py +++ b/cdatgui/editors/model/levels_base.py @@ -10,13 +10,8 @@ def levels(self): # Check if they're autolevels if numpy.allclose(levs, 1e20): if vcs.isboxfill(self._gm) == 1: - nlevs = self.color_2 - self.color_1 + 1 - minval, maxval = vcs.minmax(self._var) - levs = vcs.mkscale(minval, maxval) - if len(levs) == 1: - levs.append(levs[0] + .00001) - delta = (levs[-1] - levs[0]) / nlevs - levs = list(numpy.arange(levs[0], levs[-1] + delta, delta)) + min, max = vcs.minmax(self._var) + levs = self._gm.getlevels(min, max).tolist() else: levs = vcs.mkscale(*vcs.minmax(self._var)) @@ -26,7 +21,7 @@ def levels(self): levs.insert(0, -1e20) if self.ext_right: levs.append(1e20) - except AttributeError: + except AttributeError as e: pass return levs \ No newline at end of file diff --git a/cdatgui/editors/widgets/color_table.py b/cdatgui/editors/widgets/color_table.py index b3b40d3..95f5ca8 100644 --- a/cdatgui/editors/widgets/color_table.py +++ b/cdatgui/editors/widgets/color_table.py @@ -110,15 +110,23 @@ def cmap(self): @cmap.setter def cmap(self, value): - if not vcs.iscolormap(value): + try: value = vcs.getcolormap(value) + except KeyError: + raise KeyError('Invalid value {0} for colormap name'.format(value)) self._real_map = value + if self._cmap is not None: + del vcs.elements['colormap'][self._cmap.name] self._cmap = vcs.createcolormap(Cp_name_src=self._real_map.name) self.update_table() def apply(self): for ind in range(256): self._real_map.index[ind] = self._cmap.index[ind] + del vcs.elements['colormap'][self._cmap.name] + + def reject(self): + del vcs.elements['colormap'][self._cmap.name] def reset(self): for ind in range(256): diff --git a/cdatgui/editors/widgets/legend_widget.py b/cdatgui/editors/widgets/legend_widget.py index 02594fd..a6a1d02 100644 --- a/cdatgui/editors/widgets/legend_widget.py +++ b/cdatgui/editors/widgets/legend_widget.py @@ -1,5 +1,6 @@ from types import FunctionType +from cdatgui.editors.model.legend import VCSLegend from cdatgui.editors.widgets.dict_editor import DictEditorWidget from PySide import QtCore, QtGui from cdatgui.editors.model import legend @@ -184,6 +185,8 @@ def __init__(self, parent=None): self.cur_button = None self.cur_index = None self.colormap_editor = None + self.gm = None + self.orig_gm = None # Create Labels colormap_label = QtGui.QLabel("Colormap:") @@ -318,8 +321,10 @@ def __init__(self, parent=None): self.vertical_layout.insertLayout(5, custom_fill_layout) self.vertical_layout.insertLayout(6, labels_layout) - def setObject(self, legend): - self.object = legend + def createAndSetObject(self, gm, var): + self.orig_gm = gm + self.gm = vcs.creategraphicsmethod(vcs.graphicsmethodtype(gm), gm.name) + self.object = VCSLegend(self.gm, var) try: self.start_color_spin.setValue(self.object.color_1) @@ -362,7 +367,11 @@ def setObject(self, legend): else: self.disableCustom() - self.preview.setLegendObject(legend) + # select correct colormap index + if gm.colormap is not None: + self.colormap_dropdown.setCurrentIndex(self.colormap_dropdown.findText(gm.colormap)) + + self.preview.setLegendObject(self.object) self.preview.update() def updateColormap(self, cur_item, recreate=True): @@ -584,6 +593,19 @@ def disableCustom(self): self.custom_fill_icon.setEnabled(False) self.custom_fill_icon.hide() self.custom_fill_label.hide() + + def accept(self): + orig_name = self.orig_gm.name + if orig_name in vcs.elements[vcs.graphicsmethodtype(self.orig_gm)]: + del vcs.elements[vcs.graphicsmethodtype(self.orig_gm)][orig_name] + + new_gm = vcs.creategraphicsmethod(vcs.graphicsmethodtype(self.orig_gm), self.gm.name, orig_name) + super(LegendEditorWidget, self).accept() + + def reject(self): + if self.gm.name in vcs.elements[vcs.graphicsmethodtype(self.orig_gm)]: + del vcs.elements[vcs.graphicsmethodtype(self.orig_gm)][self.gm.name] + super(LegendEditorWidget, self).reject() if __name__ == "__main__": diff --git a/cdatgui/spreadsheet/sheet.py b/cdatgui/spreadsheet/sheet.py index f0d3593..fc11820 100755 --- a/cdatgui/spreadsheet/sheet.py +++ b/cdatgui/spreadsheet/sheet.py @@ -232,7 +232,7 @@ def paint(self, painter, option, index): """ QtGui.QItemDelegate.paint(self, painter, option, index) if ((index.row(), index.column()) == self.table.activeCell): - painter.accept() + painter.save() painter.setPen(QtGui.QPen(QtGui.QBrush( QtGui.QColor(0.8549 * 255, 0.6971 * 255, 0.2255 * 255)), self.padding)) r = self.table.visualRect(index) From 1d0bb6990f38aa699ca0b97e415d5fd565533f18 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Wed, 1 Jun 2016 12:10:50 -0700 Subject: [PATCH 28/29] fixed rename colormap --- cdatgui/editors/colormap.py | 2 ++ cdatgui/editors/widgets/color_table.py | 1 + cdatgui/editors/widgets/legend_widget.py | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cdatgui/editors/colormap.py b/cdatgui/editors/colormap.py index 5148bdb..2b69ae3 100644 --- a/cdatgui/editors/colormap.py +++ b/cdatgui/editors/colormap.py @@ -9,6 +9,7 @@ class QColormapEditor(QtGui.QColorDialog): choseColormap = QtCore.Signal(str) choseColorIndex = QtCore.Signal(int) + colormapCreated = QtCore.Signal(str) def __init__(self, mode=COLORMAP_MODE, parent=None): QtGui.QColorDialog.__init__(self, parent) @@ -155,6 +156,7 @@ def renamed(self): self.colormap.model().sort(0) self.colormap.setCurrentIndex(self.colormap.findText(newname)) self.newname.setText("") + self.colormapCreated.emit(newname) def blend(self): min_index, max_index = self.colors.get_color_range() diff --git a/cdatgui/editors/widgets/color_table.py b/cdatgui/editors/widgets/color_table.py index 95f5ca8..41cf70a 100644 --- a/cdatgui/editors/widgets/color_table.py +++ b/cdatgui/editors/widgets/color_table.py @@ -117,6 +117,7 @@ def cmap(self, value): self._real_map = value if self._cmap is not None: del vcs.elements['colormap'][self._cmap.name] + self._cmap = vcs.createcolormap(Cp_name_src=self._real_map.name) self.update_table() diff --git a/cdatgui/editors/widgets/legend_widget.py b/cdatgui/editors/widgets/legend_widget.py index a6a1d02..bd004cc 100644 --- a/cdatgui/editors/widgets/legend_widget.py +++ b/cdatgui/editors/widgets/legend_widget.py @@ -379,8 +379,7 @@ def updateColormap(self, cur_item, recreate=True): return self.object.colormap = cur_item - items = [self.colormap_dropdown.itemText(i) for i in range(self.colormap_dropdown.count())] - self.colormap_dropdown.setCurrentIndex(items.index(cur_item)) + self.colormap_dropdown.setCurrentIndex(self.colormap_dropdown.findText(cur_item)) self.preview.update() self.level_count = len(self.object.levels) @@ -530,6 +529,7 @@ def createColormap(self, obj): self.colormap_editor.colormap.setCurrentIndex(items.index(self.colormap_dropdown.currentText())) self.colormap_editor.choseColormap.connect(partial(self.updateColormap, recreate=False)) self.colormap_editor.choseColorIndex.connect(partial(self.performActionAndClose, obj)) + self.colormap_editor.colormapCreated.connect(self.colormap_dropdown.addItem) self.colormap_editor.show() if self.start_timer.isActive(): self.start_timer.stop() From 72465afcb3a1d4de22e2f7d795432cfa5725fbf6 Mon Sep 17 00:00:00 2001 From: Bryce Sampson Date: Thu, 2 Jun 2016 16:06:32 -0700 Subject: [PATCH 29/29] found stupid gosh darn off by one error in legend editor for missing level --- cdatgui/editors/model/legend.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/cdatgui/editors/model/legend.py b/cdatgui/editors/model/legend.py index 9d41bf4..c7f57d4 100644 --- a/cdatgui/editors/model/legend.py +++ b/cdatgui/editors/model/legend.py @@ -52,7 +52,7 @@ def vcs_colors(self): else: colors = vcs.getcolors(levs, colors=range(self.color_1, self.color_2)) levs = real_levs - if len(colors) < len(levs): + if len(colors) < len(levs) - 1: # Pad out colors to the right number of buckets diff = len(levs) - len(colors) colors += diff * colors[-1:] @@ -75,17 +75,6 @@ def fill_style(self): def fill_style(self, style): self._gm.fillareastyle = style.lower() self._gm.fillareacolors = self.vcs_colors - self.adjust_to_level_length(self._gm.fillareaindices) - # this should just be temporary until merge of missing level branch - self.adjust_to_level_length(self._gm.fillareaopacity) - self.adjust_to_level_length(self._gm.fillareacolors) - - def adjust_to_level_length(self, lst): - # +1 for invisible level - while len(lst) < len(self.levels) + 1: - lst.append(lst[-1]) - while len(lst) > len(self.levels) + 1: - lst.pop() @property def color_1(self):