From d7afa8824c06acce67e2b3bdf3b7d52a8b9fddfa Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Sun, 21 Nov 2021 19:09:34 -0500 Subject: [PATCH] Fix some small linting issues. (#41) * fix some linting * add tests * update versions * update setup --- .pre-commit-config.yaml | 12 ++--- examples/collapsible.py | 3 +- setup.cfg | 3 +- src/superqt/collapsible/_collapsible.py | 63 ++++++++++++++++--------- tests/test_collapsible.py | 34 ++++++++++--- 5 files changed, 78 insertions(+), 37 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3c0a891..1eb17b9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,11 +5,11 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/asottile/setup-cfg-fmt - rev: v1.17.0 + rev: v1.20.0 hooks: - id: setup-cfg-fmt - repo: https://github.com/PyCQA/flake8 - rev: 3.9.2 + rev: 4.0.1 hooks: - id: flake8 additional_dependencies: [flake8-typing-imports==1.7.0] @@ -20,20 +20,20 @@ repos: - id: autoflake args: ["--in-place", "--remove-all-unused-imports"] - repo: https://github.com/PyCQA/isort - rev: 5.8.0 + rev: 5.10.1 hooks: - id: isort - repo: https://github.com/asottile/pyupgrade - rev: v2.19.1 + rev: v2.29.1 hooks: - id: pyupgrade args: [--py37-plus, --keep-runtime-typing] - repo: https://github.com/psf/black - rev: 21.5b2 + rev: 21.11b1 hooks: - id: black - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.910 + rev: v0.910-1 hooks: - id: mypy exclude: examples diff --git a/examples/collapsible.py b/examples/collapsible.py index ea3401d..8d4eedf 100644 --- a/examples/collapsible.py +++ b/examples/collapsible.py @@ -1,7 +1,6 @@ """Example for QCollapsible""" -from PySide2.QtWidgets import QLabel from superqt import QCollapsible -from superqt.qtcompat.QtWidgets import QApplication, QPushButton, QLabel +from superqt.qtcompat.QtWidgets import QApplication, QLabel, QPushButton app = QApplication([]) diff --git a/setup.cfg b/setup.cfg index f06e20b..580cb69 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,6 +20,7 @@ classifiers = Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 Programming Language :: Python :: Implementation :: CPython Topic :: Desktop Environment Topic :: Software Development @@ -40,7 +41,7 @@ include_package_data = True package_dir = =src setup_requires = - setuptools_scm + setuptools-scm zip_safe = False [options.packages.find] diff --git a/src/superqt/collapsible/_collapsible.py b/src/superqt/collapsible/_collapsible.py index a42297c..773c976 100644 --- a/src/superqt/collapsible/_collapsible.py +++ b/src/superqt/collapsible/_collapsible.py @@ -1,13 +1,18 @@ """A collapsible widget to hide and unhide child widgets""" from typing import Optional -from ..qtcompat.QtCore import QAbstractAnimation, QEasingCurve, QPropertyAnimation, Qt, QMargins +from ..qtcompat.QtCore import ( + QAbstractAnimation, + QEasingCurve, + QMargins, + QPropertyAnimation, + Qt, +) from ..qtcompat.QtWidgets import QFrame, QPushButton, QVBoxLayout, QWidget class QCollapsible(QFrame): - """ - A collapsible widget to hide and unhide child widgets. + """A collapsible widget to hide and unhide child widgets. Based on https://stackoverflow.com/a/68141638 """ @@ -21,9 +26,8 @@ class QCollapsible(QFrame): self._toggle_btn = QPushButton(self._COLLAPSED + title) self._toggle_btn.setCheckable(True) - self._toggle_btn.setChecked(False) self._toggle_btn.setStyleSheet("text-align: left; background: transparent;") - self._toggle_btn.clicked.connect(self._toggle) + self._toggle_btn.toggled.connect(self._toggle) # frame layout self.setLayout(QVBoxLayout()) @@ -41,44 +45,69 @@ class QCollapsible(QFrame): _content = QWidget() _content.setLayout(QVBoxLayout()) _content.setMaximumHeight(0) - _content.layout().setContentsMargins(QMargins(5,0,0,0)) + _content.layout().setContentsMargins(QMargins(5, 0, 0, 0)) self.setContent(_content) def setText(self, text: str): + """Set the text of the toggle button.""" current = self._toggle_btn.text()[: len(self._EXPANDED)] self._toggle_btn.setText(current + text) + def text(self) -> str: + """Return the text of the toggle button.""" + return self._toggle_btn.text()[len(self._EXPANDED) :] + def setContent(self, content: QWidget): + """Replace central widget (the widget that gets expanded/collapsed).""" self._content = content self.layout().addWidget(self._content) self._animation.setTargetObject(content) def content(self) -> QWidget: + """Return the current content widget.""" return self._content def setDuration(self, msecs: int): + """Set duration of the collapse/expand animation.""" self._animation.setDuration(msecs) def setEasingCurve(self, easing: QEasingCurve): + """Set the easing curve for the collapse/expand animation""" self._animation.setEasingCurve(easing) def addWidget(self, widget: QWidget): + """Add a widget to the central content widget's layout.""" self._content.layout().addWidget(widget) def removeWidget(self, widget: QWidget): + """Remove widget from the central content widget's layout.""" self._content.layout().removeWidget(widget) def expand(self, animate: bool = True): + """Expand (show) the collapsible section""" self._expand_collapse(QAbstractAnimation.Direction.Forward, animate) def collapse(self, animate: bool = True): + """Collapse (hide) the collapsible section""" self._expand_collapse(QAbstractAnimation.Direction.Backward, animate) - def expanded(self): + def isExpanded(self) -> bool: + """Return whether the collapsible section is visible""" return self._toggle_btn.isChecked() - def _expand_collapse(self, direction: QAbstractAnimation.Direction, animate:bool = True): - if self._locked is True: + def setLocked(self, locked: bool = True): + """Set whether collapse/expand is disabled""" + self._locked = locked + self._toggle_btn.setCheckable(not locked) + + def locked(self) -> bool: + """Return True if collapse/expand is disabled""" + return self._locked + + def _expand_collapse( + self, direction: QAbstractAnimation.Direction, animate: bool = True + ): + if self._locked: return forward = direction == QAbstractAnimation.Direction.Forward @@ -87,21 +116,13 @@ class QCollapsible(QFrame): self._toggle_btn.setChecked(forward) self._toggle_btn.setText(text + self._toggle_btn.text()[len(self._EXPANDED) :]) + _content_height = self._content.sizeHint().height() + 10 if animate: self._animation.setDirection(direction) - self._animation.setEndValue(self._content.sizeHint().height() + 10) + self._animation.setEndValue(_content_height) self._animation.start() else: - height = 0 if forward==False else (self._content.sizeHint().height() + 10) - self._content.setMaximumHeight(height) + self._content.setMaximumHeight(_content_height if forward else 0) def _toggle(self): - if self._locked is True: - self._toggle_btn.setChecked(not self._toggle_btn.isChecked) - self.expand() if self._toggle_btn.isChecked() else self.collapse() - - def setLocked(self, locked: bool = True): - self._locked = locked - - def locked(self) -> bool: - return self._locked + self.expand() if self.isExpanded() else self.collapse() diff --git a/tests/test_collapsible.py b/tests/test_collapsible.py index d7e77e6..13f0df8 100644 --- a/tests/test_collapsible.py +++ b/tests/test_collapsible.py @@ -9,12 +9,12 @@ def test_checked_initialization(qtbot): """Test simple collapsible""" wdg1 = QCollapsible("Advanced analysis") wdg1.expand(False) - assert wdg1.expanded() is True + assert wdg1.isExpanded() assert wdg1._content.maximumHeight() > 0 wdg2 = QCollapsible("Advanced analysis") wdg1.collapse(False) - assert wdg2.expanded() is False + assert not wdg2.isExpanded() assert wdg2._content.maximumHeight() == 0 @@ -27,11 +27,11 @@ def test_content_hide_show(qtbot): collapsible.addWidget(QPushButton(f"Content button {i + 1}")) collapsible.collapse(False) - assert collapsible.expanded() is False + assert not collapsible.isExpanded() assert collapsible._content.maximumHeight() == 0 collapsible.expand(False) - assert collapsible.expanded() is True + assert collapsible.isExpanded() assert collapsible._content.maximumHeight() > 0 @@ -41,12 +41,24 @@ def test_locking(qtbot): assert wdg1.locked() is False wdg1.setLocked(True) assert wdg1.locked() is True + assert not wdg1.isExpanded() - # Simulate button press wdg1._toggle_btn.setChecked(True) - wdg1._toggle() + assert not wdg1.isExpanded() - assert wdg1.expanded() is False + wdg1._toggle() + assert not wdg1.isExpanded() + + wdg1.expand() + assert not wdg1.isExpanded() + + wdg1._toggle_btn.setChecked(False) + assert not wdg1.isExpanded() + + wdg1.setLocked(False) + wdg1.expand() + assert wdg1.isExpanded() + assert wdg1._toggle_btn.isChecked() def test_changing_animation_settings(qtbot): @@ -64,3 +76,11 @@ def test_changing_content(qtbot): wdg = QCollapsible() wdg.setContent(content) assert wdg._content == content + + +def test_changing_text(qtbot): + """Test changing the content""" + wdg = QCollapsible() + wdg.setText("Hi new text") + assert wdg.text() == "Hi new text" + assert wdg._toggle_btn.text() == QCollapsible._COLLAPSED + "Hi new text"