Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ on:
- '**/*.md'
- '**/*.rst'
- '**/*.txt'
- 'hyperspy_gui_traitsui/_external/*.py'
schedule:
# run once a week
- cron: '16 13 * * 5'
Expand Down
9 changes: 6 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ jobs:
# correct version with setuptools_scm
run: |
git remote add upstream https://github.com/hyperspy/hyperspy_gui_traitsui.git
git fetch --prune --unshallow
git fetch upstream --tags

- uses: actions/setup-python@v5
Expand Down Expand Up @@ -76,12 +75,16 @@ jobs:
- name: Install HyperSpy (RELEASE_next_major)
if: contains( matrix.LABEL, 'RnM')
run: |
pip install git+https://github.com/hyperspy/hyperspy.git@RELEASE_next_major
# pip install git+https://github.com/hyperspy/hyperspy.git@RELEASE_next_major
# revert back when hyperspy 2.1 is released
pip install git+https://github.com/hyperspy/hyperspy.git@RELEASE_next_minor

- name: Install HyperSpy (RELEASE_next_patch)
if: contains( matrix.LABEL, 'RnP')
run: |
pip install git+https://github.com/hyperspy/hyperspy.git@RELEASE_next_patch
# pip install git+https://github.com/hyperspy/hyperspy.git@RELEASE_next_patch
# revert back when hyperspy 2.1 is released
pip install git+https://github.com/hyperspy/hyperspy.git@RELEASE_next_minor

- name: Install exSpy
if: ${{ ! contains( matrix.LABEL, 'minimum') }}
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

## v2.1 (UNRELEASED)

* Fix slider in image contrast editor on python >=3.10 ([#76](https://github.com/hyperspy/hyperspy_gui_traitsui/pull/76)).
* Fix getting version with editable installation ([#75](https://github.com/hyperspy/hyperspy_gui_traitsui/pull/75)).
* Add releasing guide and release script ([#75](https://github.com/hyperspy/hyperspy_gui_traitsui/pull/75)).
* Fix regression with editable installation ([#74](https://github.com/hyperspy/hyperspy_gui_traitsui/pull/74)).
Expand Down
211 changes: 211 additions & 0 deletions hyperspy_gui_traitsui/_external/bounds_editor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
# (C) Copyright 2004-2023 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!

# Use upstream version when https://github.com/enthought/traitsui/pull/2048
# is merged and release

from pyface.qt import QtGui, QtCore

from traits.api import Float, Any, Str, Union

from traitsui.editors.api import RangeEditor
try:
from traitsui.qt.editor import Editor
except:

Check notice

Code scanning / CodeQL

Except block handles 'BaseException'

Except block directly handles BaseException.
from traitsui.qt4.editor import Editor
from .range_slider import RangeSlider


class _BoundsEditor(Editor):

evaluate = Any()

min = Any()
max = Any()
low = Any()
high = Any()
format_str = Str()

def init(self, parent):
"""Finishes initializing the editor by creating the underlying toolkit
widget.
"""
factory = self.factory
if not factory.low_name:
self.low = factory.low

if not factory.high_name:
self.high = factory.high

self.max = factory.max
self.min = factory.min

self.format_str = factory.format_str

self.evaluate = factory.evaluate
self.sync_value(factory.evaluate_name, "evaluate", "from")

self.sync_value(factory.low_name, "low", "both")
self.sync_value(factory.high_name, "high", "both")

self.control = QtGui.QWidget()
panel = QtGui.QHBoxLayout(self.control)
panel.setContentsMargins(0, 0, 0, 0)

self._label_lo = QtGui.QLineEdit(self.format_str % self.low)
self._label_lo.editingFinished.connect(self.update_low_on_enter)
panel.addWidget(self._label_lo)

# The default size is a bit too big and probably doesn't need to grow.
sh = self._label_lo.sizeHint()
sh.setWidth(sh.width() // 2)
self._label_lo.setMaximumSize(sh)

self.control.slider = slider = RangeSlider(QtCore.Qt.Orientation.Horizontal)
slider.setTracking(factory.auto_set)
slider.setMinimum(0)
slider.setMaximum(10000)
slider.setPageStep(1000)
slider.setSingleStep(100)
slider.setLow(self._convert_to_slider(self.low))
slider.setHigh(self._convert_to_slider(self.high))

slider.sliderMoved.connect(self.update_object_on_scroll)
panel.addWidget(slider)

self._label_hi = QtGui.QLineEdit(self.format_str % self.high)
self._label_hi.editingFinished.connect(self.update_high_on_enter)
panel.addWidget(self._label_hi)

# The default size is a bit too big and probably doesn't need to grow.
sh = self._label_hi.sizeHint()
sh.setWidth(sh.width() // 2)
self._label_hi.setMaximumSize(sh)

self.set_tooltip(slider)
self.set_tooltip(self._label_lo)
self.set_tooltip(self._label_hi)

def update_low_on_enter(self):
try:
try:
low = eval(str(self._label_lo.text()).strip())
if self.evaluate is not None:
low = self.evaluate(low)
except Exception as ex:
low = self.low
self._label_lo.setText(self.format_str % self.low)

if not self.factory.is_float:
low = int(low)

if low > self.high:
low = self.high - self._step_size()
self._label_lo.setText(self.format_str % low)

self.control.slider.setLow(self._convert_to_slider(low))
self.low = low
except:

Check notice

Code scanning / CodeQL

Empty except

'except' clause does nothing but pass and there is no explanatory comment.

Check notice

Code scanning / CodeQL

Except block handles 'BaseException'

Except block directly handles BaseException.
pass

def update_high_on_enter(self):
try:
try:
high = eval(str(self._label_hi.text()).strip())
if self.evaluate is not None:
high = self.evaluate(high)
except:

Check notice

Code scanning / CodeQL

Except block handles 'BaseException'

Except block directly handles BaseException.
high = self.high
self._label_hi.setText(self.format_str % self.high)

if not self.factory.is_float:
high = int(high)

if high < self.low:
high = self.low + self._step_size()
self._label_hi.setText(self.format_str % high)

self.control.slider.setHigh(self._convert_to_slider(high))
self.high = high
except:

Check notice

Code scanning / CodeQL

Empty except

'except' clause does nothing but pass and there is no explanatory comment.

Check notice

Code scanning / CodeQL

Except block handles 'BaseException'

Except block directly handles BaseException.
pass

def update_object_on_scroll(self, pos):
low = self._convert_from_slider(self.control.slider.low())
high = self._convert_from_slider(self.control.slider.high())

if self.factory.is_float:
self.low = low
self.high = high
else:
self.low = int(low)
self.high = int(high)

# update the sliders to the int values or the sliders
# will jiggle
self.control.slider.setLow(self._convert_to_slider(low))
self.control.slider.setHigh(self._convert_to_slider(high))

def update_editor(self):
return

def _check_max_and_min(self):
# check if max & min have been defined:
if self.max is None:
self.max = self.high
if self.min is None:
self.min = self.low

def _step_size(self):
slider_delta = (
self.control.slider.maximum() - self.control.slider.minimum()
)
range_delta = self.max - self.min

return float(range_delta) / slider_delta

def _convert_from_slider(self, slider_val):
self._check_max_and_min()
return self.min + slider_val * self._step_size()

def _convert_to_slider(self, value):
self._check_max_and_min()
return (
self.control.slider.minimum()
+ (value - self.min) / self._step_size()
)

def _low_changed(self, low):
if self.control is None:
return
if self._label_lo is not None:
self._label_lo.setText(self.format_str % low)

self.control.slider.setLow(self._convert_to_slider(low))

def _high_changed(self, high):
if self.control is None:
return
if self._label_hi is not None:
self._label_hi.setText(self.format_str % high)

self.control.slider.setHigh(self._convert_to_slider(self.high))


class BoundsEditor(RangeEditor):

min = Union(None, Float)
max = Union(None, Float)

def _get_simple_editor_class(self):
return _BoundsEditor

def _get_custom_editor_class(self):
return _BoundsEditor
Loading