summaryrefslogtreecommitdiff
path: root/silx/gui/qt
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/qt')
-rw-r--r--silx/gui/qt/__init__.py60
-rw-r--r--silx/gui/qt/_macosx.py68
-rw-r--r--silx/gui/qt/_pyside_dynamic.py239
-rw-r--r--silx/gui/qt/_pyside_missing.py274
-rw-r--r--silx/gui/qt/_qt.py289
-rw-r--r--silx/gui/qt/_utils.py71
-rw-r--r--silx/gui/qt/inspect.py87
7 files changed, 0 insertions, 1088 deletions
diff --git a/silx/gui/qt/__init__.py b/silx/gui/qt/__init__.py
deleted file mode 100644
index ace2841..0000000
--- a/silx/gui/qt/__init__.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2004-2021 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.
-#
-# ###########################################################################*/
-"""Common wrapper over Python Qt bindings:
-
-- `PyQt5 <http://pyqt.sourceforge.net/Docs/PyQt5/>`_
-- `PySide2 <https://wiki.qt.io/Qt_for_Python>`_
-- `PyQt4 <http://pyqt.sourceforge.net/Docs/PyQt4/>`_
-
-If a Qt binding is already loaded, it will use it, otherwise the different
-Qt bindings are tried in this order: PyQt5, PyQt4, PySide2.
-
-The name of the loaded Qt binding is stored in the BINDING variable.
-
-This module provides a flat namespace over Qt bindings by importing
-all symbols from **QtCore** and **QtGui** packages and if available
-from **QtOpenGL** and **QtSvg** packages.
-For **PyQt5**, it also imports all symbols from **QtWidgets** and
-**QtPrintSupport** packages.
-
-Example of using :mod:`silx.gui.qt` module:
-
->>> from silx.gui import qt
->>> app = qt.QApplication([])
->>> widget = qt.QWidget()
-
-For an alternative solution providing a structured namespace,
-see `qtpy <https://pypi.org/project/QtPy/>`_ which
-provides the namespace of PyQt5 over PyQt4, PySide and PySide2.
-"""
-
-from ._qt import * # noqa
-from ._utils import * # noqa
-
-
-if sys.platform == "darwin":
- if BINDING in ["PySide", "PyQt4"]:
- from . import _macosx
- _macosx.patch_QUrl_toLocalFile()
diff --git a/silx/gui/qt/_macosx.py b/silx/gui/qt/_macosx.py
deleted file mode 100644
index 07f3143..0000000
--- a/silx/gui/qt/_macosx.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2004-2016 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.
-#
-# ###########################################################################*/
-"""
-Patches for Mac OS X
-"""
-
-__authors__ = ["V. Valls"]
-__license__ = "MIT"
-__date__ = "30/11/2016"
-
-
-def patch_QUrl_toLocalFile():
- """Apply a monkey-patch on qt.QUrl to allow to reach filename when the URL
- come from a MIME data from a file drop. Without, `QUrl.toLocalName` with
- some version of Mac OS X returns a path which looks like
- `/.file/id=180.112`.
-
- Qt5 is or will be patch, but Qt4 and PySide are not.
-
- This fix uses the file URL and use an subprocess with an
- AppleScript. The script convert the URI into a posix path.
- The interpreter (osascript) is available on default OS X installs.
-
- See https://bugreports.qt.io/browse/QTBUG-40449
- """
- from ._qt import QUrl
- import subprocess
-
- def QUrl_toLocalFile(self):
- path = QUrl._oldToLocalFile(self)
- if not path.startswith("/.file/id="):
- return path
-
- url = self.toString()
- script = 'get posix path of my posix file \"%s\" -- kthxbai' % url
- try:
- p = subprocess.Popen(["osascript", "-e", script], stdout=subprocess.PIPE)
- out, _err = p.communicate()
- if p.returncode == 0:
- return out.strip()
- except OSError:
- pass
- return path
-
- QUrl._oldToLocalFile = QUrl.toLocalFile
- QUrl.toLocalFile = QUrl_toLocalFile
diff --git a/silx/gui/qt/_pyside_dynamic.py b/silx/gui/qt/_pyside_dynamic.py
deleted file mode 100644
index 6013416..0000000
--- a/silx/gui/qt/_pyside_dynamic.py
+++ /dev/null
@@ -1,239 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Taken from: https://gist.github.com/cpbotha/1b42a20c8f3eb9bb7cb8
-# Plus: https://github.com/spyder-ide/qtpy/commit/001a862c401d757feb63025f88dbb4601d353c84
-
-# Copyright (c) 2011 Sebastian Wiesner <lunaryorn@gmail.com>
-# Modifications by Charl Botha <cpbotha@vxlabs.com>
-# * customWidgets support (registerCustomWidget() causes segfault in
-# pyside 1.1.2 on Ubuntu 12.04 x86_64)
-# * workingDirectory support in loadUi
-
-# found this here:
-# https://github.com/lunaryorn/snippets/blob/master/qt4/designer/pyside_dynamic.py
-
-# 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.
-
-"""
- How to load a user interface dynamically with PySide.
-
- .. moduleauthor:: Sebastian Wiesner <lunaryorn@gmail.com>
-"""
-
-from __future__ import (print_function, division, unicode_literals,
- absolute_import)
-
-import logging
-import sys
-
-if "PySide.QtCore" in sys.modules:
- from PySide.QtCore import QMetaObject
- from PySide.QtUiTools import QUiLoader
-else: # PySide2
- from PySide2.QtCore import QMetaObject, Property, Qt
- from PySide2.QtWidgets import QFrame
- from PySide2.QtUiTools import QUiLoader
-
-_logger = logging.getLogger(__name__)
-
-
-class UiLoader(QUiLoader):
- """
- Subclass :class:`~PySide.QtUiTools.QUiLoader` to create the user interface
- in a base instance.
-
- Unlike :class:`~PySide.QtUiTools.QUiLoader` itself this class does not
- create a new instance of the top-level widget, but creates the user
- interface in an existing instance of the top-level class.
-
- This mimics the behaviour of :func:`PyQt*.uic.loadUi`.
- """
-
- def __init__(self, baseinstance, customWidgets=None):
- """
- Create a loader for the given ``baseinstance``.
-
- The user interface is created in ``baseinstance``, which must be an
- instance of the top-level class in the user interface to load, or a
- subclass thereof.
-
- ``customWidgets`` is a dictionary mapping from class name to class
- object for widgets that you've promoted in the Qt Designer
- interface. Usually, this should be done by calling
- registerCustomWidget on the QUiLoader, but
- with PySide 1.1.2 on Ubuntu 12.04 x86_64 this causes a segfault.
-
- ``parent`` is the parent object of this loader.
- """
-
- QUiLoader.__init__(self, baseinstance)
- self.baseinstance = baseinstance
- self.customWidgets = {}
- self.uifile = None
- self.customWidgets.update(customWidgets)
-
- def createWidget(self, class_name, parent=None, name=''):
- """
- Function that is called for each widget defined in ui file,
- overridden here to populate baseinstance instead.
- """
-
- if parent is None and self.baseinstance:
- # supposed to create the top-level widget, return the base instance
- # instead
- return self.baseinstance
-
- else:
- if class_name in self.availableWidgets():
- # create a new widget for child widgets
- widget = QUiLoader.createWidget(self, class_name, parent, name)
-
- else:
- # if not in the list of availableWidgets,
- # must be a custom widget
- # this will raise KeyError if the user has not supplied the
- # relevant class_name in the dictionary, or TypeError, if
- # customWidgets is None
- if class_name not in self.customWidgets:
- raise Exception('No custom widget ' + class_name +
- ' found in customWidgets param of' +
- 'UiFile %s.' % self.uifile)
- try:
- widget = self.customWidgets[class_name](parent)
- except Exception:
- _logger.error("Fail to instanciate widget %s from file %s", class_name, self.uifile)
- raise
-
- if self.baseinstance:
- # set an attribute for the new child widget on the base
- # instance, just like PyQt*.uic.loadUi does.
- setattr(self.baseinstance, name, widget)
-
- # this outputs the various widget names, e.g.
- # sampleGraphicsView, dockWidget, samplesTableView etc.
- # print(name)
-
- return widget
-
- def _parse_custom_widgets(self, ui_file):
- """
- This function is used to parse a ui file and look for the <customwidgets>
- section, then automatically load all the custom widget classes.
- """
- import importlib
- from xml.etree.ElementTree import ElementTree
-
- # Parse the UI file
- etree = ElementTree()
- ui = etree.parse(ui_file)
-
- # Get the customwidgets section
- custom_widgets = ui.find('customwidgets')
-
- if custom_widgets is None:
- return
-
- custom_widget_classes = {}
-
- for custom_widget in custom_widgets.getchildren():
-
- cw_class = custom_widget.find('class').text
- cw_header = custom_widget.find('header').text
-
- module = importlib.import_module(cw_header)
-
- custom_widget_classes[cw_class] = getattr(module, cw_class)
-
- self.customWidgets.update(custom_widget_classes)
-
- def load(self, uifile):
- self._parse_custom_widgets(uifile)
- self.uifile = uifile
- return QUiLoader.load(self, uifile)
-
-
-if "PySide2.QtCore" in sys.modules:
-
- class _Line(QFrame):
- """Widget to use as 'Line' Qt designer"""
- def __init__(self, parent=None):
- super(_Line, self).__init__(parent)
- self.setFrameShape(QFrame.HLine)
- self.setFrameShadow(QFrame.Sunken)
-
- def getOrientation(self):
- shape = self.frameShape()
- if shape == QFrame.HLine:
- return Qt.Horizontal
- elif shape == QFrame.VLine:
- return Qt.Vertical
- else:
- raise RuntimeError("Wrong shape: %d", shape)
-
- def setOrientation(self, orientation):
- if orientation == Qt.Horizontal:
- self.setFrameShape(QFrame.HLine)
- elif orientation == Qt.Vertical:
- self.setFrameShape(QFrame.VLine)
- else:
- raise ValueError("Unsupported orientation %s" % str(orientation))
-
- orientation = Property("Qt::Orientation", getOrientation, setOrientation)
-
- CUSTOM_WIDGETS = {"Line": _Line}
- """Default custom widgets for `loadUi`"""
-
-else: # PySide support
- CUSTOM_WIDGETS = {}
- """Default custom widgets for `loadUi`"""
-
-
-def loadUi(uifile, baseinstance=None, package=None, resource_suffix=None):
- """
- Dynamically load a user interface from the given ``uifile``.
-
- ``uifile`` is a string containing a file name of the UI file to load.
-
- If ``baseinstance`` is ``None``, the a new instance of the top-level widget
- will be created. Otherwise, the user interface is created within the given
- ``baseinstance``. In this case ``baseinstance`` must be an instance of the
- top-level widget class in the UI file to load, or a subclass thereof. In
- other words, if you've created a ``QMainWindow`` interface in the designer,
- ``baseinstance`` must be a ``QMainWindow`` or a subclass thereof, too. You
- cannot load a ``QMainWindow`` UI file with a plain
- :class:`~PySide.QtGui.QWidget` as ``baseinstance``.
-
- :method:`~PySide.QtCore.QMetaObject.connectSlotsByName()` is called on the
- created user interface, so you can implemented your slots according to its
- conventions in your widget class.
-
- Return ``baseinstance``, if ``baseinstance`` is not ``None``. Otherwise
- return the newly created instance of the user interface.
- """
- if package is not None:
- _logger.warning(
- "loadUi package parameter not implemented with PySide")
- if resource_suffix is not None:
- _logger.warning(
- "loadUi resource_suffix parameter not implemented with PySide")
-
- loader = UiLoader(baseinstance, customWidgets=CUSTOM_WIDGETS)
- widget = loader.load(uifile)
- QMetaObject.connectSlotsByName(widget)
- return widget
diff --git a/silx/gui/qt/_pyside_missing.py b/silx/gui/qt/_pyside_missing.py
deleted file mode 100644
index a7e2781..0000000
--- a/silx/gui/qt/_pyside_missing.py
+++ /dev/null
@@ -1,274 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2017 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.
-#
-# ###########################################################################*/
-"""
-Python implementation of classes which are not provided by default by PySide.
-"""
-
-__authors__ = ["V. Valls"]
-__license__ = "MIT"
-__date__ = "17/01/2017"
-
-
-from PySide.QtGui import QAbstractProxyModel
-from PySide.QtCore import QModelIndex
-from PySide.QtCore import Qt
-from PySide.QtGui import QItemSelection
-from PySide.QtGui import QItemSelectionRange
-
-
-class QIdentityProxyModel(QAbstractProxyModel):
- """Python translation of the source code of Qt c++ file"""
-
- def __init__(self, parent=None):
- super(QIdentityProxyModel, self).__init__(parent)
- self.__ignoreNextLayoutAboutToBeChanged = False
- self.__ignoreNextLayoutChanged = False
- self.__persistentIndexes = []
-
- def columnCount(self, parent):
- parent = self.mapToSource(parent)
- return self.sourceModel().columnCount(parent)
-
- def dropMimeData(self, data, action, row, column, parent):
- parent = self.mapToSource(parent)
- return self.sourceModel().dropMimeData(data, action, row, column, parent)
-
- def index(self, row, column, parent=QModelIndex()):
- parent = self.mapToSource(parent)
- i = self.sourceModel().index(row, column, parent)
- return self.mapFromSource(i)
-
- def insertColumns(self, column, count, parent=QModelIndex()):
- parent = self.mapToSource(parent)
- return self.sourceModel().insertColumns(column, count, parent)
-
- def insertRows(self, row, count, parent=QModelIndex()):
- parent = self.mapToSource(parent)
- return self.sourceModel().insertRows(row, count, parent)
-
- def mapFromSource(self, sourceIndex):
- if self.sourceModel() is None or not sourceIndex.isValid():
- return QModelIndex()
- index = self.createIndex(sourceIndex.row(), sourceIndex.column(), sourceIndex.internalPointer())
- return index
-
- def mapSelectionFromSource(self, sourceSelection):
- proxySelection = QItemSelection()
- if self.sourceModel() is None:
- return proxySelection
-
- cursor = sourceSelection.constBegin()
- end = sourceSelection.constEnd()
- while cursor != end:
- topLeft = self.mapFromSource(cursor.topLeft())
- bottomRight = self.mapFromSource(cursor.bottomRight())
- proxyRange = QItemSelectionRange(topLeft, bottomRight)
- proxySelection.append(proxyRange)
- cursor += 1
- return proxySelection
-
- def mapSelectionToSource(self, proxySelection):
- sourceSelection = QItemSelection()
- if self.sourceModel() is None:
- return sourceSelection
-
- cursor = proxySelection.constBegin()
- end = proxySelection.constEnd()
- while cursor != end:
- topLeft = self.mapToSource(cursor.topLeft())
- bottomRight = self.mapToSource(cursor.bottomRight())
- sourceRange = QItemSelectionRange(topLeft, bottomRight)
- sourceSelection.append(sourceRange)
- cursor += 1
- return sourceSelection
-
- def mapToSource(self, proxyIndex):
- if self.sourceModel() is None or not proxyIndex.isValid():
- return QModelIndex()
- return self.sourceModel().createIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalPointer())
-
- def match(self, start, role, value, hits=1, flags=Qt.MatchFlags(Qt.MatchStartsWith | Qt.MatchWrap)):
- if self.sourceModel() is None:
- return []
-
- start = self.mapToSource(start)
- sourceList = self.sourceModel().match(start, role, value, hits, flags)
- proxyList = []
- for cursor in sourceList:
- proxyList.append(self.mapFromSource(cursor))
- return proxyList
-
- def parent(self, child):
- sourceIndex = self.mapToSource(child)
- sourceParent = sourceIndex.parent()
- index = self.mapFromSource(sourceParent)
- return index
-
- def removeColumns(self, column, count, parent=QModelIndex()):
- parent = self.mapToSource(parent)
- return self.sourceModel().removeColumns(column, count, parent)
-
- def removeRows(self, row, count, parent=QModelIndex()):
- parent = self.mapToSource(parent)
- return self.sourceModel().removeRows(row, count, parent)
-
- def rowCount(self, parent=QModelIndex()):
- parent = self.mapToSource(parent)
- return self.sourceModel().rowCount(parent)
-
- def setSourceModel(self, newSourceModel):
- """Bind and unbind the source model events"""
- self.beginResetModel()
-
- sourceModel = self.sourceModel()
- if sourceModel is not None:
- sourceModel.rowsAboutToBeInserted.disconnect(self.__rowsAboutToBeInserted)
- sourceModel.rowsInserted.disconnect(self.__rowsInserted)
- sourceModel.rowsAboutToBeRemoved.disconnect(self.__rowsAboutToBeRemoved)
- sourceModel.rowsRemoved.disconnect(self.__rowsRemoved)
- sourceModel.rowsAboutToBeMoved.disconnect(self.__rowsAboutToBeMoved)
- sourceModel.rowsMoved.disconnect(self.__rowsMoved)
- sourceModel.columnsAboutToBeInserted.disconnect(self.__columnsAboutToBeInserted)
- sourceModel.columnsInserted.disconnect(self.__columnsInserted)
- sourceModel.columnsAboutToBeRemoved.disconnect(self.__columnsAboutToBeRemoved)
- sourceModel.columnsRemoved.disconnect(self.__columnsRemoved)
- sourceModel.columnsAboutToBeMoved.disconnect(self.__columnsAboutToBeMoved)
- sourceModel.columnsMoved.disconnect(self.__columnsMoved)
- sourceModel.modelAboutToBeReset.disconnect(self.__modelAboutToBeReset)
- sourceModel.modelReset.disconnect(self.__modelReset)
- sourceModel.dataChanged.disconnect(self.__dataChanged)
- sourceModel.headerDataChanged.disconnect(self.__headerDataChanged)
- sourceModel.layoutAboutToBeChanged.disconnect(self.__layoutAboutToBeChanged)
- sourceModel.layoutChanged.disconnect(self.__layoutChanged)
-
- super(QIdentityProxyModel, self).setSourceModel(newSourceModel)
-
- sourceModel = self.sourceModel()
- if sourceModel is not None:
- sourceModel.rowsAboutToBeInserted.connect(self.__rowsAboutToBeInserted)
- sourceModel.rowsInserted.connect(self.__rowsInserted)
- sourceModel.rowsAboutToBeRemoved.connect(self.__rowsAboutToBeRemoved)
- sourceModel.rowsRemoved.connect(self.__rowsRemoved)
- sourceModel.rowsAboutToBeMoved.connect(self.__rowsAboutToBeMoved)
- sourceModel.rowsMoved.connect(self.__rowsMoved)
- sourceModel.columnsAboutToBeInserted.connect(self.__columnsAboutToBeInserted)
- sourceModel.columnsInserted.connect(self.__columnsInserted)
- sourceModel.columnsAboutToBeRemoved.connect(self.__columnsAboutToBeRemoved)
- sourceModel.columnsRemoved.connect(self.__columnsRemoved)
- sourceModel.columnsAboutToBeMoved.connect(self.__columnsAboutToBeMoved)
- sourceModel.columnsMoved.connect(self.__columnsMoved)
- sourceModel.modelAboutToBeReset.connect(self.__modelAboutToBeReset)
- sourceModel.modelReset.connect(self.__modelReset)
- sourceModel.dataChanged.connect(self.__dataChanged)
- sourceModel.headerDataChanged.connect(self.__headerDataChanged)
- sourceModel.layoutAboutToBeChanged.connect(self.__layoutAboutToBeChanged)
- sourceModel.layoutChanged.connect(self.__layoutChanged)
-
- self.endResetModel()
-
- def __columnsAboutToBeInserted(self, parent, start, end):
- parent = self.mapFromSource(parent)
- self.beginInsertColumns(parent, start, end)
-
- def __columnsAboutToBeMoved(self, sourceParent, sourceStart, sourceEnd, destParent, dest):
- sourceParent = self.mapFromSource(sourceParent)
- destParent = self.mapFromSource(destParent)
- self.beginMoveColumns(sourceParent, sourceStart, sourceEnd, destParent, dest)
-
- def __columnsAboutToBeRemoved(self, parent, start, end):
- parent = self.mapFromSource(parent)
- self.beginRemoveColumns(parent, start, end)
-
- def __columnsInserted(self, parent, start, end):
- self.endInsertColumns()
-
- def __columnsMoved(self, sourceParent, sourceStart, sourceEnd, destParent, dest):
- self.endMoveColumns()
-
- def __columnsRemoved(self, parent, start, end):
- self.endRemoveColumns()
-
- def __dataChanged(self, topLeft, bottomRight):
- topLeft = self.mapFromSource(topLeft)
- bottomRight = self.mapFromSource(bottomRight)
- self.dataChanged(topLeft, bottomRight)
-
- def __headerDataChanged(self, orientation, first, last):
- self.headerDataChanged(orientation, first, last)
-
- def __layoutAboutToBeChanged(self):
- """Store persistent indexes"""
- if self.__ignoreNextLayoutAboutToBeChanged:
- return
-
- for proxyPersistentIndex in self.persistentIndexList():
- self.__proxyIndexes.append()
- sourcePersistentIndex = self.mapToSource(proxyPersistentIndex)
- mapping = proxyPersistentIndex, sourcePersistentIndex
- self.__persistentIndexes.append(mapping)
-
- self.layoutAboutToBeChanged()
-
- def __layoutChanged(self):
- """Restore persistent indexes"""
- if self.__ignoreNextLayoutChanged:
- return
-
- for mapping in self.__persistentIndexes:
- proxyIndex, sourcePersistentIndex = mapping
- sourcePersistentIndex = self.mapFromSource(sourcePersistentIndex)
- self.changePersistentIndex(proxyIndex, sourcePersistentIndex)
-
- self.__persistentIndexes = []
-
- self.layoutChanged()
-
- def __modelAboutToBeReset(self):
- self.beginResetModel()
-
- def __modelReset(self):
- self.endResetModel()
-
- def __rowsAboutToBeInserted(self, parent, start, end):
- parent = self.mapFromSource(parent)
- self.beginInsertRows(parent, start, end)
-
- def __rowsAboutToBeMoved(self, sourceParent, sourceStart, sourceEnd, destParent, dest):
- sourceParent = self.mapFromSource(sourceParent)
- destParent = self.mapFromSource(destParent)
- self.beginMoveRows(sourceParent, sourceStart, sourceEnd, destParent, dest)
-
- def __rowsAboutToBeRemoved(self, parent, start, end):
- parent = self.mapFromSource(parent)
- self.beginRemoveRows(parent, start, end)
-
- def __rowsInserted(self, parent, start, end):
- self.endInsertRows()
-
- def __rowsMoved(self, sourceParent, sourceStart, sourceEnd, destParent, dest):
- self.endMoveRows()
-
- def __rowsRemoved(self, parent, start, end):
- self.endRemoveRows()
diff --git a/silx/gui/qt/_qt.py b/silx/gui/qt/_qt.py
deleted file mode 100644
index 29a6354..0000000
--- a/silx/gui/qt/_qt.py
+++ /dev/null
@@ -1,289 +0,0 @@
-# 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.
-#
-# ###########################################################################*/
-"""Load Qt binding"""
-
-__authors__ = ["V.A. Sole"]
-__license__ = "MIT"
-__date__ = "23/05/2018"
-
-
-import logging
-import sys
-import traceback
-
-from ...utils.deprecation import deprecated_warning
-
-
-_logger = logging.getLogger(__name__)
-
-
-BINDING = None
-"""The name of the Qt binding in use: PyQt5, PyQt4 or PySide2."""
-
-QtBinding = None # noqa
-"""The Qt binding module in use: PyQt5, PyQt4 or PySide2."""
-
-HAS_SVG = False
-"""True if Qt provides support for Scalable Vector Graphics (QtSVG)."""
-
-HAS_OPENGL = False
-"""True if Qt provides support for OpenGL (QtOpenGL)."""
-
-# First check for an already loaded wrapper
-if 'PySide2.QtCore' in sys.modules:
- BINDING = 'PySide2'
-
-elif 'PySide.QtCore' in sys.modules:
- BINDING = 'PySide'
-
-elif 'PyQt5.QtCore' in sys.modules:
- BINDING = 'PyQt5'
-
-elif 'PyQt4.QtCore' in sys.modules:
- BINDING = 'PyQt4'
-
-else: # Then try Qt bindings
- try:
- import PyQt5.QtCore # noqa
- except ImportError:
- if 'PyQt5' in sys.modules:
- del sys.modules["PyQt5"]
- try:
- import sip
- sip.setapi("QString", 2)
- sip.setapi("QVariant", 2)
- sip.setapi('QDate', 2)
- sip.setapi('QDateTime', 2)
- sip.setapi('QTextStream', 2)
- sip.setapi('QTime', 2)
- sip.setapi('QUrl', 2)
- import PyQt4.QtCore # noqa
- except ImportError:
- if 'PyQt4' in sys.modules:
- del sys.modules["sip"]
- del sys.modules["PyQt4"]
- try:
- import PySide2.QtCore # noqa
- except ImportError:
- if 'PySide2' in sys.modules:
- del sys.modules["PySide2"]
- try:
- import PySide.QtCore # noqa
- except ImportError:
- if 'PySide' in sys.modules:
- del sys.modules["PySide"]
- raise ImportError(
- 'No Qt wrapper found. Install PyQt5, PyQt4 or PySide2.')
- else:
- BINDING = 'PySide'
- else:
- BINDING = 'PySide2'
- else:
- BINDING = 'PyQt4'
- else:
- BINDING = 'PyQt5'
-
-
-if BINDING == 'PyQt4':
- _logger.debug('Using PyQt4 bindings')
- deprecated_warning("Qt Binding", "PyQt4",
- replacement='PyQt5',
- since_version='0.9.0')
-
- if sys.version_info < (3, ):
- try:
- import sip
- sip.setapi("QString", 2)
- sip.setapi("QVariant", 2)
- sip.setapi('QDate', 2)
- sip.setapi('QDateTime', 2)
- sip.setapi('QTextStream', 2)
- sip.setapi('QTime', 2)
- sip.setapi('QUrl', 2)
- except:
- _logger.warning("Cannot set sip API")
-
- import PyQt4 as QtBinding # noqa
-
- from PyQt4.QtCore import * # noqa
- from PyQt4.QtGui import * # noqa
-
- try:
- from PyQt4.QtOpenGL import * # noqa
- except ImportError:
- _logger.info("PyQt4.QtOpenGL not available")
- HAS_OPENGL = False
- else:
- HAS_OPENGL = True
-
- try:
- from PyQt4.QtSvg import * # noqa
- except ImportError:
- _logger.info("PyQt4.QtSvg not available")
- HAS_SVG = False
- else:
- HAS_SVG = True
-
- from PyQt4.uic import loadUi # noqa
-
- Signal = pyqtSignal
-
- Property = pyqtProperty
-
- Slot = pyqtSlot
-
-elif BINDING == 'PySide':
- _logger.debug('Using PySide bindings')
- deprecated_warning("Qt Binding", "PySide",
- replacement='PySide2',
- since_version='0.9.0')
-
- import PySide as QtBinding # noqa
-
- from PySide.QtCore import * # noqa
- from PySide.QtGui import * # noqa
-
- try:
- from PySide.QtOpenGL import * # noqa
- except ImportError:
- _logger.info("PySide.QtOpenGL not available")
- HAS_OPENGL = False
- else:
- HAS_OPENGL = True
-
- try:
- from PySide.QtSvg import * # noqa
- except ImportError:
- _logger.info("PySide.QtSvg not available")
- HAS_SVG = False
- else:
- HAS_SVG = True
-
- pyqtSignal = Signal
-
- # Import loadUi wrapper for PySide
- from ._pyside_dynamic import loadUi # noqa
-
- # Import missing classes
- if not hasattr(locals(), "QIdentityProxyModel"):
- from ._pyside_missing import QIdentityProxyModel # noqa
-
-elif BINDING == 'PyQt5':
- _logger.debug('Using PyQt5 bindings')
-
- import PyQt5 as QtBinding # noqa
-
- from PyQt5.QtCore import * # noqa
- from PyQt5.QtGui import * # noqa
- from PyQt5.QtWidgets import * # noqa
- from PyQt5.QtPrintSupport import * # noqa
-
- try:
- from PyQt5.QtOpenGL import * # noqa
- except ImportError:
- _logger.info("PySide.QtOpenGL not available")
- HAS_OPENGL = False
- else:
- HAS_OPENGL = True
-
- try:
- from PyQt5.QtSvg import * # noqa
- except ImportError:
- _logger.info("PyQt5.QtSvg not available")
- HAS_SVG = False
- else:
- HAS_SVG = True
-
- from PyQt5.uic import loadUi # noqa
-
- Signal = pyqtSignal
-
- Property = pyqtProperty
-
- Slot = pyqtSlot
-
- # Disable PyQt5's cooperative multi-inheritance since other bindings do not provide it.
- # See https://www.riverbankcomputing.com/static/Docs/PyQt5/multiinheritance.html?highlight=inheritance
- class _Foo(object): pass
- class QObject(QObject, _Foo): pass
-
-
-elif BINDING == 'PySide2':
- _logger.debug('Using PySide2 bindings')
-
- import PySide2 as QtBinding # noqa
-
- from PySide2.QtCore import * # noqa
- from PySide2.QtGui import * # noqa
- from PySide2.QtWidgets import * # noqa
- from PySide2.QtPrintSupport import * # noqa
-
- try:
- from PySide2.QtOpenGL import * # noqa
- except ImportError:
- _logger.info("PySide2.QtOpenGL not available")
- HAS_OPENGL = False
- else:
- HAS_OPENGL = True
-
- try:
- from PySide2.QtSvg import * # noqa
- except ImportError:
- _logger.info("PySide2.QtSvg not available")
- HAS_SVG = False
- else:
- HAS_SVG = True
-
- # Import loadUi wrapper for PySide2
- from ._pyside_dynamic import loadUi # noqa
-
- pyqtSignal = Signal
-
-else:
- raise ImportError('No Qt wrapper found. Install PyQt4, PyQt5, PySide2')
-
-
-# provide a exception handler but not implement it by default
-def exceptionHandler(type_, value, trace):
- """
- This exception handler prevents quitting to the command line when there is
- an unhandled exception while processing a Qt signal.
-
- The script/application willing to use it should implement code similar to:
-
- .. code-block:: python
-
- if __name__ == "__main__":
- sys.excepthook = qt.exceptionHandler
-
- """
- _logger.error("%s %s %s", type_, value, ''.join(traceback.format_tb(trace)))
- msg = QMessageBox()
- msg.setWindowTitle("Unhandled exception")
- msg.setIcon(QMessageBox.Critical)
- msg.setInformativeText("%s %s\nPlease report details" % (type_, value))
- msg.setDetailedText(("%s " % value) + ''.join(traceback.format_tb(trace)))
- msg.raise_()
- msg.exec_()
diff --git a/silx/gui/qt/_utils.py b/silx/gui/qt/_utils.py
deleted file mode 100644
index 4a7a1c0..0000000
--- a/silx/gui/qt/_utils.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2004-2019 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.
-#
-# ###########################################################################*/
-"""This module provides convenient functions related to Qt.
-"""
-
-__authors__ = ["V. Valls"]
-__license__ = "MIT"
-__date__ = "30/11/2016"
-
-
-import sys as _sys
-from . import _qt
-
-
-def supportedImageFormats():
- """Return a set of string of file format extensions supported by the
- Qt runtime."""
- if _sys.version_info[0] < 3 or _qt.BINDING == 'PySide':
- convert = str
- elif _qt.BINDING == 'PySide2':
- def convert(data):
- return str(data.data(), 'ascii')
- else:
- convert = lambda data: str(data, 'ascii')
- formats = _qt.QImageReader.supportedImageFormats()
- return set([convert(data) for data in formats])
-
-
-__globalThreadPoolInstance = None
-"""Store the own silx global thread pool"""
-
-
-def silxGlobalThreadPool():
- """"Manage an own QThreadPool to avoid issue on Qt5 Windows with the
- default Qt global thread pool.
-
- A thread pool is create in lazy loading. With a maximum of 4 threads.
- Else `qt.Thread.idealThreadCount()` is used.
-
- :rtype: qt.QThreadPool
- """
- global __globalThreadPoolInstance
- if __globalThreadPoolInstance is None:
- tp = _qt.QThreadPool()
- # Setting maxThreadCount fixes a segfault with PyQt 5.9.1 on Windows
- maxThreadCount = min(4, tp.maxThreadCount())
- tp.setMaxThreadCount(maxThreadCount)
- __globalThreadPoolInstance = tp
- return __globalThreadPoolInstance
diff --git a/silx/gui/qt/inspect.py b/silx/gui/qt/inspect.py
deleted file mode 100644
index 3c08835..0000000
--- a/silx/gui/qt/inspect.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2018-2019 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.
-#
-# ###########################################################################*/
-"""This module provides functions to access Qt C++ object state:
-
-- :func:`isValid` to check whether a QObject C++ pointer is valid.
-- :func:`createdByPython` to check if a QObject was created from Python.
-- :func:`ownedByPython` to check if a QObject is currently owned by Python.
-"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "08/10/2018"
-
-
-from . import _qt as qt
-
-
-if qt.BINDING in ('PyQt4', 'PyQt5'):
- if qt.BINDING == 'PyQt5':
- try:
- from PyQt5.sip import isdeleted as _isdeleted # noqa
- from PyQt5.sip import ispycreated as createdByPython # noqa
- from PyQt5.sip import ispyowned as ownedByPython # noqa
- except ImportError:
- from sip import isdeleted as _isdeleted # noqa
- from sip import ispycreated as createdByPython # noqa
- from sip import ispyowned as ownedByPython # noqa
-
- else: # PyQt4
- from sip import isdeleted as _isdeleted # noqa
- from sip import ispycreated as createdByPython # noqa
- from sip import ispyowned as ownedByPython # noqa
-
- def isValid(obj):
- """Returns True if underlying C++ object is valid.
-
- :param QObject obj:
- :rtype: bool
- """
- return not _isdeleted(obj)
-
-elif qt.BINDING == 'PySide2':
- try:
- from PySide2.shiboken2 import isValid # noqa
- from PySide2.shiboken2 import createdByPython # noqa
- from PySide2.shiboken2 import ownedByPython # noqa
- except ImportError:
- from shiboken2 import isValid # noqa
- from shiboken2 import createdByPython # noqa
- from shiboken2 import ownedByPython # noqa
-
-elif qt.BINDING == 'PySide':
- try: # Available through PySide
- from PySide.shiboken import isValid # noqa
- from PySide.shiboken import createdByPython # noqa
- from PySide.shiboken import ownedByPython # noqa
- except ImportError: # Available through standalone shiboken package
- from Shiboken.shiboken import isValid # noqa
- from Shiboken.shiboken import createdByPython # noqa
- from Shiboken.shiboken import ownedByPython # noqa
-
-else:
- raise ImportError("Unsupported Qt binding %s" % qt.BINDING)
-
-__all__ = ['isValid', 'createdByPython', 'ownedByPython']