summaryrefslogtreecommitdiff
path: root/silx/gui/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/widgets')
-rw-r--r--silx/gui/widgets/ElidedLabel.py137
-rwxr-xr-xsilx/gui/widgets/LegendIconWidget.py7
-rw-r--r--silx/gui/widgets/MultiModeAction.py83
-rw-r--r--silx/gui/widgets/RangeSlider.py8
-rw-r--r--silx/gui/widgets/UrlSelectionTable.py8
-rw-r--r--silx/gui/widgets/test/__init__.py2
-rw-r--r--silx/gui/widgets/test/test_elidedlabel.py111
7 files changed, 349 insertions, 7 deletions
diff --git a/silx/gui/widgets/ElidedLabel.py b/silx/gui/widgets/ElidedLabel.py
new file mode 100644
index 0000000..58513c7
--- /dev/null
+++ b/silx/gui/widgets/ElidedLabel.py
@@ -0,0 +1,137 @@
+# coding: utf-8
+# /*##########################################################################
+#
+# Copyright (c) 2004-2020 European Synchrotron Radiation Facility
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+# ###########################################################################*/
+"""Module contains an elidable label
+"""
+
+__license__ = "MIT"
+__date__ = "07/12/2018"
+
+from silx.gui import qt
+
+
+class ElidedLabel(qt.QLabel):
+ """QLabel with an edile property.
+
+ By default if the text is too big, it is elided on the right.
+
+ This mode can be changed with :func:`setElideMode`.
+
+ In case the text is elided, the full content is displayed as part of the
+ tool tip. This behavior can be disabled with :func:`setTextAsToolTip`.
+ """
+
+ def __init__(self, parent=None):
+ super(ElidedLabel, self).__init__(parent)
+ self.__text = ""
+ self.__toolTip = ""
+ self.__textAsToolTip = True
+ self.__textIsElided = False
+ self.__elideMode = qt.Qt.ElideRight
+ self.__updateMinimumSize()
+
+ def resizeEvent(self, event):
+ self.__updateText()
+ return qt.QLabel.resizeEvent(self, event)
+
+ def setFont(self, font):
+ qt.QLabel.setFont(self, font)
+ self.__updateMinimumSize()
+ self.__updateText()
+
+ def __updateMinimumSize(self):
+ metrics = qt.QFontMetrics(self.font())
+ width = metrics.width("...")
+ self.setMinimumWidth(width)
+
+ def __updateText(self):
+ metrics = qt.QFontMetrics(self.font())
+ elidedText = metrics.elidedText(self.__text, self.__elideMode, self.width())
+ qt.QLabel.setText(self, elidedText)
+ wasElided = self.__textIsElided
+ self.__textIsElided = elidedText != self.__text
+ if self.__textIsElided or wasElided != self.__textIsElided:
+ self.__updateToolTip()
+
+ def __updateToolTip(self):
+ if self.__textIsElided and self.__textAsToolTip:
+ qt.QLabel.setToolTip(self, self.__text + "<br/>" + self.__toolTip)
+ else:
+ qt.QLabel.setToolTip(self, self.__toolTip)
+
+ # Properties
+
+ def setText(self, text):
+ self.__text = text
+ self.__updateText()
+
+ def getText(self):
+ return self.__text
+
+ text = qt.Property(str, getText, setText)
+
+ def setToolTip(self, toolTip):
+ self.__toolTip = toolTip
+ self.__updateToolTip()
+
+ def getToolTip(self):
+ return self.__toolTip
+
+ toolTip = qt.Property(str, getToolTip, setToolTip)
+
+ def setElideMode(self, elideMode):
+ """Set the elide mode.
+
+ :param qt.Qt.TextElideMode elidMode: Elide mode to use
+ """
+ self.__elideMode = elideMode
+ self.__updateText()
+
+ def getElideMode(self):
+ """Returns the used elide mode.
+
+ :rtype: qt.Qt.TextElideMode
+ """
+ return self.__elideMode
+
+ elideMode = qt.Property(qt.Qt.TextElideMode, getToolTip, setToolTip)
+
+ def setTextAsToolTip(self, enabled):
+ """Enable displaying text as part of the tooltip if it is elided.
+
+ :param bool enabled: Enable the behavior
+ """
+ if self.__textAsToolTip == enabled:
+ return
+ self.__textAsToolTip = enabled
+ self.__updateToolTip()
+
+ def getTextAsToolTip(self):
+ """True if an elided text is displayed as part of the tooltip.
+
+ :rtype: bool
+ """
+ return self.__textAsToolTip
+
+ textAsToolTip = qt.Property(bool, getTextAsToolTip, setTextAsToolTip)
diff --git a/silx/gui/widgets/LegendIconWidget.py b/silx/gui/widgets/LegendIconWidget.py
index 1a403cb..1c95e41 100755
--- a/silx/gui/widgets/LegendIconWidget.py
+++ b/silx/gui/widgets/LegendIconWidget.py
@@ -336,10 +336,11 @@ class LegendIconWidget(qt.QWidget):
pixmapRect = qt.QRect(0, 0, _COLORMAP_PIXMAP_SIZE, 1)
widthMargin = 0
halfHeight = 4
+ widgetRect = self.rect()
dest = qt.QRect(
- rect.left() + widthMargin,
- rect.center().y() - halfHeight + 1,
- rect.width() - widthMargin * 2,
+ widgetRect.left() + widthMargin,
+ widgetRect.center().y() - halfHeight + 1,
+ widgetRect.width() - widthMargin * 2,
halfHeight * 2,
)
painter.drawImage(dest, image, pixmapRect)
diff --git a/silx/gui/widgets/MultiModeAction.py b/silx/gui/widgets/MultiModeAction.py
new file mode 100644
index 0000000..502275d
--- /dev/null
+++ b/silx/gui/widgets/MultiModeAction.py
@@ -0,0 +1,83 @@
+# coding: utf-8
+# /*##########################################################################
+#
+# Copyright (c) 2004-2018 European Synchrotron Radiation Facility
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+# ###########################################################################*/
+"""Action to hold many mode actions, usually for a tool bar.
+"""
+
+__authors__ = ["V. Valls"]
+__license__ = "MIT"
+__data__ = "22/04/2020"
+
+
+from silx.gui import qt
+
+
+class MultiModeAction(qt.QWidgetAction):
+ """This action provides a default checkable action from a list of checkable
+ actions.
+
+ The default action can be selected from a drop down list. The last one used
+ became the default one.
+
+ The default action is directly usable without using the drop down list.
+ """
+
+ def __init__(self, parent=None):
+ assert isinstance(parent, qt.QWidget)
+ qt.QWidgetAction.__init__(self, parent)
+ button = qt.QToolButton(parent)
+ button.setPopupMode(qt.QToolButton.MenuButtonPopup)
+ self.setDefaultWidget(button)
+ self.__button = button
+
+ def getMenu(self):
+ """Returns the menu.
+
+ :rtype: qt.QMenu
+ """
+ button = self.__button
+ menu = button.menu()
+ if menu is None:
+ menu = qt.QMenu(button)
+ button.setMenu(menu)
+ return menu
+
+ def addAction(self, action):
+ """Add a new action to the list.
+
+ :param qt.QAction action: New action
+ """
+ menu = self.getMenu()
+ button = self.__button
+ menu.addAction(action)
+ if button.defaultAction() is None:
+ button.setDefaultAction(action)
+ if action.isCheckable():
+ action.toggled.connect(self._toggled)
+
+ def _toggled(self, checked):
+ if checked:
+ action = self.sender()
+ button = self.__button
+ button.setDefaultAction(action)
diff --git a/silx/gui/widgets/RangeSlider.py b/silx/gui/widgets/RangeSlider.py
index c352147..31dbd4e 100644
--- a/silx/gui/widgets/RangeSlider.py
+++ b/silx/gui/widgets/RangeSlider.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2015-2019 European Synchrotron Radiation Facility
+# Copyright (c) 2015-2020 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -606,9 +606,9 @@ class RangeSlider(qt.QWidget):
-self._SLIDER_WIDTH, 0)
def __sliderAreaRect(self):
- return self.__drawArea().adjusted(self._SLIDER_WIDTH / 2.,
+ return self.__drawArea().adjusted(self._SLIDER_WIDTH // 2,
0,
- -self._SLIDER_WIDTH / 2. + 1,
+ -self._SLIDER_WIDTH // 2 + 1,
0)
def __pixMapRect(self):
@@ -722,7 +722,7 @@ class RangeSlider(qt.QWidget):
buttonColor = option.palette.button().color()
val = qt.qGray(buttonColor.rgb())
buttonColor = buttonColor.lighter(100 + max(1, (180 - val) // 6))
- buttonColor.setHsv(buttonColor.hue(), buttonColor.saturation() * 0.75, buttonColor.value())
+ buttonColor.setHsv(buttonColor.hue(), (buttonColor.saturation() * 3) // 4, buttonColor.value())
grooveColor = qt.QColor()
grooveColor.setHsv(buttonColor.hue(),
diff --git a/silx/gui/widgets/UrlSelectionTable.py b/silx/gui/widgets/UrlSelectionTable.py
index 4ac0381..27ea363 100644
--- a/silx/gui/widgets/UrlSelectionTable.py
+++ b/silx/gui/widgets/UrlSelectionTable.py
@@ -74,6 +74,14 @@ class UrlSelectionTable(TableWidget):
self.setSortingEnabled(True)
self._checkBoxes = {}
+ def setUrls(self, urls: list) -> None:
+ """
+
+ :param urls: urls to be displayed
+ """
+ for url in urls:
+ self.addUrl(url=url)
+
def addUrl(self, url, **kwargs):
"""
diff --git a/silx/gui/widgets/test/__init__.py b/silx/gui/widgets/test/__init__.py
index 8d179bc..b868171 100644
--- a/silx/gui/widgets/test/__init__.py
+++ b/silx/gui/widgets/test/__init__.py
@@ -33,6 +33,7 @@ from . import test_framebrowser
from . import test_boxlayoutdockwidget
from . import test_rangeslider
from . import test_flowlayout
+from . import test_elidedlabel
__authors__ = ["V. Valls", "P. Knobel"]
__license__ = "MIT"
@@ -51,5 +52,6 @@ def suite():
test_boxlayoutdockwidget.suite(),
test_rangeslider.suite(),
test_flowlayout.suite(),
+ test_elidedlabel.suite(),
])
return test_suite
diff --git a/silx/gui/widgets/test/test_elidedlabel.py b/silx/gui/widgets/test/test_elidedlabel.py
new file mode 100644
index 0000000..2856733
--- /dev/null
+++ b/silx/gui/widgets/test/test_elidedlabel.py
@@ -0,0 +1,111 @@
+# coding: utf-8
+# /*##########################################################################
+#
+# Copyright (c) 2020 European Synchrotron Radiation Facility
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+# ###########################################################################*/
+"""Tests for ElidedLabel"""
+
+__license__ = "MIT"
+__date__ = "08/06/2020"
+
+import unittest
+
+from silx.gui import qt
+from silx.gui.widgets.ElidedLabel import ElidedLabel
+from silx.gui.utils import testutils
+
+
+class TestElidedLabel(testutils.TestCaseQt):
+
+ def setUp(self):
+ self.label = ElidedLabel()
+ self.label.show()
+ self.qWaitForWindowExposed(self.label)
+
+ def tearDown(self):
+ self.label.setAttribute(qt.Qt.WA_DeleteOnClose)
+ self.label.close()
+ del self.label
+ self.qapp.processEvents()
+
+ def testElidedValue(self):
+ """Test elided text"""
+ raw = "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"
+ self.label.setText(raw)
+ self.label.setFixedWidth(30)
+ displayedText = qt.QLabel.text(self.label)
+ self.assertNotEqual(raw, displayedText)
+ self.assertIn("…", displayedText)
+ self.assertIn("m", displayedText)
+
+ def testNotElidedValue(self):
+ """Test elided text"""
+ raw = "mmmmmmm"
+ self.label.setText(raw)
+ self.label.setFixedWidth(200)
+ displayedText = qt.QLabel.text(self.label)
+ self.assertNotIn("…", displayedText)
+ self.assertEqual(raw, displayedText)
+
+ def testUpdateFromElidedToNotElided(self):
+ """Test tooltip when not elided"""
+ raw1 = "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"
+ raw2 = "nn"
+ self.label.setText(raw1)
+ self.label.setFixedWidth(30)
+ self.label.setText(raw2)
+ displayedTooltip = qt.QLabel.toolTip(self.label)
+ self.assertNotIn(raw1, displayedTooltip)
+ self.assertNotIn(raw2, displayedTooltip)
+
+ def testUpdateFromNotElidedToElided(self):
+ """Test tooltip when elided"""
+ raw1 = "nn"
+ raw2 = "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"
+ self.label.setText(raw1)
+ self.label.setFixedWidth(30)
+ self.label.setText(raw2)
+ displayedTooltip = qt.QLabel.toolTip(self.label)
+ self.assertNotIn(raw1, displayedTooltip)
+ self.assertIn(raw2, displayedTooltip)
+
+ def testUpdateFromElidedToElided(self):
+ """Test tooltip when elided"""
+ raw1 = "nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"
+ raw2 = "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"
+ self.label.setText(raw1)
+ self.label.setFixedWidth(30)
+ self.label.setText(raw2)
+ displayedTooltip = qt.QLabel.toolTip(self.label)
+ self.assertNotIn(raw1, displayedTooltip)
+ self.assertIn(raw2, displayedTooltip)
+
+
+def suite():
+ loader = unittest.defaultTestLoader.loadTestsFromTestCase
+ test_suite = unittest.TestSuite()
+ test_suite.addTest(loader(TestElidedLabel))
+ return test_suite
+
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='suite')