Source code for lavuelib.sourceTabWidget

# Copyright (C) 2017  DESY, Christoph Rosemann, Notkestr. 85, D-22607 Hamburg
#
# lavue is an image viewing program for photon science imaging detectors.
# Its usual application is as a live viewer using hidra as data source.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation in  version 2
# of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA  02110-1301, USA.
#
# Authors:
#     Christoph Rosemann <christoph.rosemann@desy.de>
#     Jan Kotanski <jan.kotanski@desy.de>
#

""" image source selection """

from .qtuic import uic
from pyqtgraph import QtCore, QtGui
import os
import json
from .sardanaUtils import debugmethod

from . import sourceWidget as swgm

_formclass, _baseclass = uic.loadUiType(
    os.path.join(os.path.dirname(os.path.abspath(__file__)),
                 "ui", "SourceTabWidget.ui"))

_sformclass, _sbaseclass = uic.loadUiType(
    os.path.join(os.path.dirname(os.path.abspath(__file__)),
                 "ui", "SourceForm.ui"))


[docs]class SourceForm(QtGui.QWidget): """ source form """ #: (:class:`pyqtgraph.QtCore.pyqtSignal`) source state signal sourceStateChanged = QtCore.pyqtSignal(int, int) #: (:class:`pyqtgraph.QtCore.pyqtSignal`) source state signal sourceChanged = QtCore.pyqtSignal(int) #: (:class:`pyqtgraph.QtCore.pyqtSignal`) source label name signal sourceLabelChanged = QtCore.pyqtSignal() #: (:class:`pyqtgraph.QtCore.pyqtSignal`) add Icon Clicked signal addIconClicked = QtCore.pyqtSignal(str, str) #: (:class:`pyqtgraph.QtCore.pyqtSignal`) remove Icon Clicked signal removeIconClicked = QtCore.pyqtSignal(str, str) #: (:class:`pyqtgraph.QtCore.pyqtSignal`) push button clicked signal pushButtonClicked = QtCore.pyqtSignal() #: (:class:`pyqtgraph.QtCore.pyqtSignal`) translation changed signal translationChanged = QtCore.pyqtSignal(str, int) #: (:class:`pyqtgraph.QtCore.pyqtSignal`) push button enabled signal buttonEnabled = QtCore.pyqtSignal(bool, int) @debugmethod def __init__(self, parent=None, sourceid=0, usersourcenames=None): """ constructor :param parent: parent object :type parent: :class:`pyqtgraph.QtCore.QObject` :param expertmode: expert mode flag :type expertmode: :obj:`bool` :param sourceid: source id :type sourceid: :obj:`int` :param usersourcenames: user source names :type usersourcenames: :obj:`list` < :obj:`str` > """ QtGui.QWidget.__init__(self, parent) #: (:obj:`bool`) if image source connected self.__connected = False #: (:class:`lavuelib.sourceWidget.SourceBaseWidget`) #: current source widget self.__currentSource = None #: (:obj:`str`) default datasource self.__defaultsource = "" #: (:obj:`list` < :obj:`str` > ) source names self.__sourcenames = [] #: (:obj:`list` < :obj:`str` > ) user source names self.__usersourcenames = usersourcenames or [] #: (:obj:`dict` < :obj:`str`, #: :class:`lavuelib.sourceWidget.SourceBaseWidget` >) #: source names self.__sourcewidgets = {} #: (:obj:`int`) source id self.__sourceid = sourceid # (:obj:`str`) error status self.__errorstatus = "" #: (:obj:`list` < :obj:`str` > ) source tab widgets self.__sourcetabs = [] #: (:obj:`list` < :class:`pyqtgraph.QtGui.QWidget` > ) datasource names self.__subwidgets = [] #: (:obj:`list` <:obj:`str`>) subwidget object names self.widgetnames = [ "sourceTypeLabel", "sourceTypeLabel", "translationLabel", "translationEditLine", "cStatusLabel", "cStatusLineEdit", "activeCheckBox", "pushButton", ] self._ui = _sformclass() self._ui.setupUi(self) if QtGui.QIcon.hasThemeIcon("video-display"): icon = QtGui.QIcon.fromTheme("video-display") self._ui.pushButton.setIcon(icon)
[docs] @debugmethod def init(self): """ initialize widget """ self._ui.sourceTypeComboBox.currentIndexChanged.connect( self.onSourceChanged) self.onSourceChanged()
[docs] @debugmethod def disconnectWidget(self): """ disconnect widget """ self._ui.cStatusLineEdit.setStyleSheet( "color: yellow;" "background-color: red;") self._ui.cStatusLineEdit.setText("Disconnected") if not self.__sourceid: self._ui.pushButton.setText("&Start") if QtGui.QIcon.hasThemeIcon("video-display"): icon = QtGui.QIcon.fromTheme("video-display") self._ui.pushButton.setIcon(icon) self.__connected = False self._ui.sourceTypeComboBox.setEnabled(True) if self.__currentSource is not None: self.__currentSource.disconnectWidget()
[docs] @debugmethod def connectWidget(self): """ connect widget """ self._ui.sourceTypeComboBox.setEnabled(False) if self.__currentSource is not None: self.__currentSource.connectWidget()
[docs] @debugmethod def currentDataSource(self): """ current data source :returns: current datasource class name :rtype: :obj:`str` """ if self.__currentSource is not None: return self.__currentSource.datasource
[docs] @debugmethod def currentDataSourceName(self): """ current data source name :returns: current datasource class name :rtype: :obj:`str` """ return self.__currentSource.name
[docs] @debugmethod def currentDataSourceAlias(self): """ current data source name :returns: current datasource class name alias :rtype: :obj:`str` """ return self.__currentSource.alias
[docs] @debugmethod def gridLayout(self): """ provide grid layout :returns: grid layout :rtype: :class:`PyQt5.QtGui.QGridLayout` """ return self._ui.formGridLayout
[docs] @debugmethod def pushButtonEnabled(self): """ provide status of push button :returns: if push button enabled :rtype: :obj:`bool` """ return self._ui.pushButton.isEnabled()
[docs] @debugmethod def removeCommonWidgets(self): """ remove common widgets """ layout = self.gridLayout() layout.removeWidget(self._ui.cStatusLabel) layout.removeWidget(self._ui.cStatusLineEdit) layout.removeWidget(self._ui.translationLabel) layout.removeWidget(self._ui.translationLineEdit) layout.removeWidget(self._ui.pushButton)
[docs] @debugmethod def addCommonWidgets(self, sln): """ add common widgets after given row in the grid layout :param sln: given row in the grid layout :type sln: :obj:`int` """ layout = self.gridLayout() layout.addWidget(self._ui.translationLabel, sln + 1, 0) layout.addWidget(self._ui.translationLineEdit, sln + 1, 1) layout.addWidget(self._ui.cStatusLabel, sln + 2, 0) layout.addWidget(self._ui.cStatusLineEdit, sln + 2, 1) if self.__sourceid: self._ui.pushButton.hide() else: layout.addWidget(self._ui.pushButton, sln + 3, 1) self._ui.pushButton.clicked.connect( self.toggleServerConnection) self._ui.translationLineEdit.textEdited.connect( self.emitTranslationChanged) self._ui.sourceTypeComboBox.setCurrentIndex(0)
[docs] @debugmethod def showItem(self, trans): """ show items of the widget :param trans: translation item show status :type trans: :obj:`bool` """ if trans: self._ui.translationLineEdit.show() self._ui.translationLabel.show() else: self._ui.translationLineEdit.hide() self._ui.translationLabel.hide()
[docs] @debugmethod def addWidgets(self, st, expertmode): """ add widgets :param st: source type class :type st: :class:`sourceWidget.SourceBaseWidget` :param expertmode: expert mode :type expertmode: :obj:`bool` """ layout = self.gridLayout() swg = getattr(swgm, st)(self.__sourceid) swg.expertmode = expertmode self.__sourcewidgets[swg.name] = swg if swg.name not in self.__sourcenames: self.__sourcenames.append(swg.name) self._ui.sourceTypeComboBox.addItem(swg.name) widgets = zip(swg.widgets[0::2], swg.widgets[1::2]) for wg1, wg2 in widgets: sln = len(self.__subwidgets) layout.addWidget(wg1, sln + 1, 0) layout.addWidget(wg2, sln + 1, 1) self.__subwidgets.append([wg1, wg2]) swg.updateComboBox() return len(self.__subwidgets)
[docs] @debugmethod def sourceStatus(self): """ source status :returns: source type id :rtype: :obj:`int` """ return self._ui.sourceTypeComboBox.currentIndex() + 1
[docs] @debugmethod def updateLayout(self): """ update source layout """ if hasattr(self.__currentSource, "name"): name = self.__currentSource.name else: name = None mst = None for stnm, st in self.__sourcewidgets.items(): if name == stnm: mst = st for wg in st.widgets: wg.show() else: for wg in st.widgets: wg.hide() if mst: mst.updateButton()
[docs] @debugmethod def updateSourceComboBox(self, sourcenames, name=None): """ set source by changing combobox :param sourcenames: source names :type sourcenames: :obj:`list` < :obj:`str` > :param index: combobox index :type index: :obj:`int` """ self.__usersourcenames = sourcenames self._ui.sourceTypeComboBox.currentIndexChanged.disconnect( self.onSourceChanged) if sourcenames and name and name not in sourcenames: sourcenames = list(sourcenames) sourcenames.append(name) sourcenames = [sr for sr in sourcenames if sr in self.__sourcenames] if not sourcenames: sourcenames = self.__sourcenames name = name or str(self._ui.sourceTypeComboBox.currentText()) self._ui.sourceTypeComboBox.clear() self._ui.sourceTypeComboBox.addItems(sourcenames) if self._ui.sourceTypeComboBox.count() == 0: self._ui.sourceTypeComboBox.addItems(self.__sourcenames) index = self._ui.sourceTypeComboBox.findText(name) if index == -1: index = 0 self._ui.sourceTypeComboBox.setCurrentIndex(index) self.onSourceChanged() self.updateLayout() self._ui.sourceTypeComboBox.currentIndexChanged.connect( self.onSourceChanged)
[docs] @debugmethod def setSource(self, name=None, disconnect=True): """ set source with the given name :param name: source name :type name: :obj:`str` :param disconnect: disconnect signals on update :type disconnect: :obj:`bool` """ if disconnect and self.__currentSource is not None: self.__currentSource.buttonEnabled.disconnect( self.emitButtonEnabled) self.__currentSource.sourceLabelChanged.disconnect( self._emitSourceLabelChanged) self.__currentSource.sourceStateChanged.disconnect( self._emitSourceStateChanged) self.__currentSource.addIconClicked.disconnect( self._emitAddIconClicked) self.__currentSource.removeIconClicked.disconnect( self._emitRemoveIconClicked) self.__currentSource.setActive(False) self.__currentSource.disconnectWidget() if name is not None and name in self.__sourcewidgets.keys(): self.__currentSource = self.__sourcewidgets[name] self.__currentSource.buttonEnabled.connect( self.emitButtonEnabled) self.__currentSource.sourceLabelChanged.connect( self._emitSourceLabelChanged) self.__currentSource.sourceStateChanged.connect( self._emitSourceStateChanged) self.__currentSource.addIconClicked.connect( self._emitAddIconClicked) self.__currentSource.removeIconClicked.connect( self._emitRemoveIconClicked) self.__currentSource.setActive(True) self.updateLayout() self.updateMetaData(disconnect=disconnect) self.emitSourceChanged()
[docs] @debugmethod def label(self): """ return a label of the current detector :return: label of the current detector :rtype: :obj:`str` """ return self.__currentSource.label()
[docs] @debugmethod def updateMetaData(self, **kargs): """ update source input parameters :param kargs: source widget input parameter dictionary :type kargs: :obj:`dict` < :obj:`str`, :obj:`any`> """ for wg in self.__sourcewidgets.values(): wg.updateMetaData(**kargs)
[docs] @debugmethod def setSourceComboBoxByName(self, name): """ set source by changing combobox by name :param name: combobox name :type name: :obj:`str` """ index = self._ui.sourceTypeComboBox.findText(name) if index != -1: self._ui.sourceTypeComboBox.setCurrentIndex(index)
[docs] @debugmethod def emitSourceChanged(self): """ emits sourceChanged signal """ status = self._ui.sourceTypeComboBox.currentIndex() + 1 self.sourceChanged.emit(status)
@debugmethod @QtCore.pyqtSlot(str, str) def _emitAddIconClicked(self, name, value): """ emits addIconClicked signal :param name: object name :type name: :obj:`str` :param value: text value :type value: :obj:`str` """ self.addIconClicked.emit(name, value) @debugmethod @QtCore.pyqtSlot(str, str) def _emitRemoveIconClicked(self, name, label): """ emits addIconClicked signal :param name: object name :type name: :obj:`str` :param value: text value label to remove :type value: :obj:`str` """ self.removeIconClicked.emit(name, label) @debugmethod @QtCore.pyqtSlot() def _emitSourceLabelChanged(self): """ emits sourceLabelChanged signal """ self.sourceLabelChanged.emit() @debugmethod @QtCore.pyqtSlot(int) def _emitSourceStateChanged(self, status): """ emits sourceStateChanged signal :param status: source state :type status: :obj:`int` """ self.sourceStateChanged.emit(status, self.__sourceid)
[docs] @debugmethod @QtCore.pyqtSlot(bool) def updateButton(self, status): """ update slot for source button :param status: button state :type status: :obj:`bool` """ self._ui.pushButton.setEnabled(status)
[docs] @debugmethod def isConnected(self): """ is datasource source connected :returns: if datasource source connected :rtype: :obj:`bool` """ return self.__connected
[docs] @debugmethod @QtCore.pyqtSlot() def toggleServerConnection(self): """ toggles server connection """ self.pushButtonClicked.emit()
[docs] @debugmethod @QtCore.pyqtSlot(str) def emitTranslationChanged(self, trans): """ emit translationChanged :param trans: x,y translation, e.g. 50,45 :type trans: :obj:`str` """ self.translationChanged.emit(trans, self.__sourceid)
[docs] @debugmethod @QtCore.pyqtSlot(bool) def emitButtonEnabled(self, status): """ emit buttonEnabled :param trans: enabled status of button :type trans: :obj:`bool` """ self.buttonEnabled.emit(status, self.__sourceid)
[docs] @debugmethod def setErrorStatus(self, status=""): """ set error status :param status: error status :type status: :obj:`str` """ if status: self._ui.cStatusLineEdit.setStyleSheet( "background-color: gray;") elif "emitting" in str(self._ui.cStatusLineEdit.text()): self._ui.cStatusLineEdit.setStyleSheet( "color: white;" "background-color: blue;") else: self._ui.cStatusLineEdit.setStyleSheet( "color: white;" "background-color: green;") self.__errorstatus = status
[docs] @debugmethod def connectSuccess(self, port=None): """ set connection status on and display connection status :param port: zmq port :type port: :obj: `str` """ self.__connected = True if port is not None: self._ui.cStatusLineEdit.setStyleSheet( "color: white;" "background-color: blue;") self._ui.cStatusLineEdit.setText( "Connected (emitting via %s)" % port) else: self._ui.cStatusLineEdit.setStyleSheet( "color: white;" "background-color: green;") self._ui.cStatusLineEdit.setText("Connected") self._ui.sourceTypeComboBox.setEnabled(False) if not self.__sourceid: self._ui.pushButton.setText("&Stop") if QtGui.QIcon.hasThemeIcon("process-stop"): icon = QtGui.QIcon.fromTheme("process-stop") self._ui.pushButton.setIcon(icon) if self.__currentSource is not None: self.__currentSource.connectWidget()
[docs] @debugmethod @QtCore.pyqtSlot() def onSourceChanged(self): """ update current source widgets """ name = str(self._ui.sourceTypeComboBox.currentText()) if self.__usersourcenames: us = [sr for sr in self.__usersourcenames if sr in self.__sourcenames] if name not in us and us: name = us[0] self.setSource(name)
[docs] @debugmethod def connectFailure(self): """ set connection status off and display connection status """ self.__connected = False self.sourceStateChanged.emit(0, self.__sourceid) self._ui.cStatusLineEdit.setText("Trouble connecting") self._ui.sourceTypeComboBox.setEnabled(True) if not self.__sourceid: self._ui.pushButton.setText("&Start") if QtGui.QIcon.hasThemeIcon("video-display"): icon = QtGui.QIcon.fromTheme("video-display") self._ui.pushButton.setIcon(icon) if self.__currentSource is not None: self.__currentSource.disconnectWidget()
# self.pushButton.setText("Retry connect")
[docs] @debugmethod def configure(self, configuration): """ set configuration for the current image source :param configuration: configuration string :type configuration: :obj:`str` """ if self.__currentSource is not None: self.__currentSource.configure(configuration)
[docs] @debugmethod def setTranslation(self, trans): """ stores translation of the given source :param: x,y tranlation, e.g. 2345,354 :type: :obj:`str` """ self._ui.translationLineEdit.setText(trans)
[docs] @debugmethod def configuration(self): """ provides configuration for the current image source :return: configuration string :rtype configuration: :obj:`str` """ if self.__currentSource is not None: return self.__currentSource.configuration()
[docs] @debugmethod def start(self): """ starts viewing if pushButton enable """ if self._ui.pushButton.isEnabled(): self.toggleServerConnection()
[docs]class SourceTabWidget(QtGui.QTabWidget): """ image source selection """ #: (:class:`pyqtgraph.QtCore.pyqtSignal`) source disconnected signal sourceDisconnected = QtCore.pyqtSignal() #: (:class:`pyqtgraph.QtCore.pyqtSignal`) source connected signal sourceConnected = QtCore.pyqtSignal(str) #: (:class:`pyqtgraph.QtCore.pyqtSignal`) source state signal sourceStateChanged = QtCore.pyqtSignal(int, int) #: (:class:`pyqtgraph.QtCore.pyqtSignal`) source state signal sourceChanged = QtCore.pyqtSignal(str) #: (:class:`pyqtgraph.QtCore.pyqtSignal`) source label name signal sourceLabelChanged = QtCore.pyqtSignal(str) #: (:class:`pyqtgraph.QtCore.pyqtSignal`) add Icon Clicked addIconClicked = QtCore.pyqtSignal(str, str) #: (:class:`pyqtgraph.QtCore.pyqtSignal`) remove Icon Clicked removeIconClicked = QtCore.pyqtSignal(str, str) #: (:class:`pyqtgraph.QtCore.pyqtSignal`) translation changed signal translationChanged = QtCore.pyqtSignal(str, int) @debugmethod def __init__(self, parent=None, sourcetypes=None, expertmode=False, nrsources=1): """ constructor :param parent: parent object :type parent: :class:`pyqtgraph.QtCore.QObject` :param sourcetypes: source type class names :type sourcetypes: :obj:`list` <:obj:`str`> :param expertmode: expert mode flag :type expertmode: :obj:`bool` :param nrsources: number of sources :type nrsources: :obj:`int` """ QtGui.QTabWidget.__init__(self, parent) #: (:class:`Ui_SourceTabWidget') ui_groupbox object from qtdesigner self._ui = _formclass() self._ui.setupUi(self) #: (:obj:`bool`) if image source connected self.__connected = False #: (:obj:`int`) number of image sources self.__nrsources = 0 #: (:obj:`list` < :obj:`str` > ) source class names self.__types = sourcetypes or [] #: (:obj:`str`) default datasource self.__defaultsource = "" #: (:obj:`bool`) expert mode flag self.__expertmode = expertmode #: (:obj:`list` < :obj:`str` > ) source names self.__sourcenames = [] #: (:obj:`list` < :obj:`str` > ) user source names self.__usersourcenames = [] # (:obj:`str`) error status self.__errorstatus = "" #: (:obj:`list` < :obj:`str` > ) source tab widgets self.__sourcetabs = [] #: (:obj:`list` < :obj:`str` > ) source tab widgets self.__buttonstatus = [False] #: (:obj:`list` < :class:`pyqtgraph.QtGui.QWidget` > ) # source tab checkbox widgets self.__tabcheckboxes = [] #: (:obj:`list` < :obj:`int` > ) source tab checkbox states self.__tabcheckboxstates = [] self.setNumberOfSources(nrsources) self.__sourcetabs[0].pushButtonClicked.connect( self.toggleServerConnection) self.__setSource(self.__defaultsource, disconnect=False) for st in self.__sourcetabs: st.init()
[docs] @debugmethod def addTab(self, widget, title): """ add tab widget :param widget: tab widget :type widget: :class:`pyqtgraph.QtGui.QWidget` :param title: tab title :type title: :obj:`str` """ QtGui.QTabWidget.addTab(self, widget, title) cb = QtGui.QCheckBox() self.__tabcheckboxes.append(cb) self.__tabcheckboxstates.append(2) self.tabBar().setTabButton(self.tabBar().count() - 1, QtGui.QTabBar.RightSide, cb) cb.setChecked(True) cb.stateChanged.connect( lambda state: self.__updateCheckBoxState(cb, state))
[docs] @debugmethod def removeTab(self, sid): """ remove tab widget :param sid: source id :type sid: :obj:`int` """ if sid < len(self.__tabcheckboxes): self.__tabcheckboxes.pop(sid) self.__tabcheckboxstates.pop(sid) QtGui.QTabWidget.removeTab(self, sid)
[docs] @debugmethod def isChecked(self, sid): """ check if tab is active :param sid: source id :type sid: :obj:`int` :returns: check state :rtype: :obj:`int` """ return self.tabBar().tabButton(sid, QtGui.QTabBar.RightSide).state()
[docs] @debugmethod def setCheckState(self, sid, state): """ set check status :param state: checkbox state :type state: :obj:`int` :param sid: source id :type sid: :obj:`int` """ self.tabBar().tabButton( sid, QtGui.QTabBar.RightSide).setCheckState(state)
@debugmethod def __updateCheckBoxState(self, cb, state): """ update checkbox state :param widget: checkbox widget :type widget: :class:`pyqtgraph.QtGui.QCheckBox` :param state: checkbox state :type state: :obj:`int` """ sid = self.__tabcheckboxes.index(cb) self.__tabcheckboxstates[sid] = state if 2 not in self.__tabcheckboxstates: for sid in range(len(self.__tabcheckboxstates)): self.setCheckState(sid, 2) if self.isConnected(): self.toggleServerConnection() self.toggleServerConnection()
[docs] @debugmethod def tabCheckBoxStates(self): """ provides checkbox states :returns: checkbox state :rtype: :obj:`list <`:obj:`int`> """ return tuple(self.__tabcheckboxstates)
[docs] @debugmethod def currentDataSources(self): """ current data source :returns: current datasource class name :rtype: :obj:`str` """ return [st.currentDataSource() for st in self.__sourcetabs][:self.count()]
[docs] @debugmethod def currentDataSourceNames(self): """ current data source name :returns: current datasource class name :rtype: :obj:`str` """ return [st.currentDataSourceName() for st in self.__sourcetabs][:self.count()]
[docs] @debugmethod def currentDataSourceAlias(self): """ current data source name alias :returns: current datasource class name alias :rtype: :obj:`str` """ return [st.currentDataSourceAlias() for st in self.__sourcetabs][:self.count()]
@debugmethod def __addSourceWidgets(self, wg=None): """ add source subwidgets into grid layout :param wg: source form object :type wg: :class:`SourceForm` """ wg = wg or self wg.removeCommonWidgets() sln = 0 for st in self.__types: sln = wg.addWidgets(st, self.__expertmode) swg = getattr(swgm, st) if swg.name not in self.__sourcenames: self.__sourcenames.append(swg.name) wg.addCommonWidgets(sln) wg.buttonEnabled.connect(self.updateButton) wg.sourceChanged.connect(self.emitSourceChanged) wg.sourceLabelChanged.connect(self._emitSourceLabelChanged) wg.sourceStateChanged.connect(self._emitSourceStateChanged) wg.addIconClicked.connect(self._emitAddIconClicked) wg.removeIconClicked.connect(self._emitRemoveIconClicked) wg.translationChanged.connect(self._emitTranslationChanged) self.__sourcetabs.append(wg) self.__buttonstatus.append(False)
[docs] @debugmethod def setNumberOfSources(self, nrsources): """ set a number of image sources :param nrsources: a number of image sources :type nrsources: :obj:`int` """ if not self.__sourcenames: for st in self.__types: swg = getattr(swgm, st) self.__sourcenames.append(swg.name) if self.__nrsources < nrsources: for i in range( self.count(), min(len(self.__sourcetabs), nrsources)): self.addTab(self.__sourcetabs[i], str(i + 1)) for i in range(len(self.__sourcetabs), nrsources): sf = SourceForm(self, sourceid=i, usersourcenames=self.__usersourcenames) self.__addSourceWidgets(sf) sf.init() self.addTab(sf, str(i + 1)) if nrsources > 1: self.setTabText(0, "Image Source 1") else: self.setTabText(0, "Image Source") self.__nrsources = nrsources elif self.__nrsources > nrsources: if nrsources == 1: self.setTabText(0, "Image Source") for i in reversed(range(nrsources, self.count())): self.removeTab(i) self.__nrsources = nrsources self.showItem(nrsources > 1) self.emitSourceChanged()
[docs] @debugmethod def setSourceComboBoxByName(self, sid, name): """ set source by changing combobox by name :param sid: source id :type sid: :obj:`int` :param name: combobox name :type name: :obj:`str` """ if len(self.__sourcetabs) > sid: self.__sourcetabs[sid].setSourceComboBoxByName(name)
[docs] @debugmethod def updateSourceComboBox(self, sourcenames, names=None): """ set source by changing combobox :param sourcenames: source names :type sourcenames: :obj:`list` < :obj:`str` > :param sourcenames: source names to set :type names: :obj:`list` < :obj:`str` > """ self.__usersourcenames = sourcenames for i, st in enumerate(self.__sourcetabs): if names and len(names) > i: st.updateSourceComboBox(sourcenames, names[i]) else: st.updateSourceComboBox(sourcenames)
[docs] @debugmethod @QtCore.pyqtSlot() def onSourceChanged(self): """ update current source widgets """ self.__setSource(str(self._ui.sourceTypeComboBox.currentText()))
[docs] @debugmethod def updateLayout(self): """ update source layout """ for st in self.__sourcetabs: st.updateLayout()
@debugmethod def __setSource(self, name=None, disconnect=True): """ set source with the given name :param name: source name :type name: :obj:`str` :param disconnect: disconnect signals on update :type disconnect: :obj:`bool` """ for st in self.__sourcetabs: st.setSource(name, disconnect)
[docs] @debugmethod @QtCore.pyqtSlot() def emitSourceChanged(self): """ emits sourceChanged signal """ status = json.dumps([st.sourceStatus() for st in self.__sourcetabs][:self.count()]) self.sourceChanged.emit(status)
@debugmethod @QtCore.pyqtSlot(str, str) def _emitAddIconClicked(self, name, value): """ emits addIconClicked signal :param name: object name :type name: :obj:`str` :param value: text value :type value: :obj:`str` """ self.addIconClicked.emit(name, value) @debugmethod @QtCore.pyqtSlot(str, str) def _emitRemoveIconClicked(self, name, label): """ emits addIconClicked signal :param name: object name :type name: :obj:`str` :param value: text value label to remove :type value: :obj:`str` """ self.removeIconClicked.emit(name, label) @debugmethod @QtCore.pyqtSlot() def _emitSourceLabelChanged(self): """ emits sourceLabelChanged signal with the given name """ status = "_".join([st.label() for st in self.__sourcetabs][:self.count()]) self.sourceLabelChanged.emit(status) @debugmethod @QtCore.pyqtSlot(int, int) def _emitSourceStateChanged(self, status, sid): """ emits sourceStateChanged signal with the current source id :param status: source id. -1 for take the current source :type status: :obj:`int` :param sid: source id :type sid: :obj:`int` """ if status == -1: status = json.dumps( [st.sourceStatus() for st in self.__sourcetabs][:self.count()]) self.sourceConnected.emit(status) else: self.sourceStateChanged.emit(status, sid) @debugmethod @QtCore.pyqtSlot(str, int) def _emitTranslationChanged(self, trans, sid): """ emits sourceStateChanged signal with the current source id :param trans: x,y translation e.g. '560,235' :type trans: :obj:`str` :param sid: source id :type sid: :obj:`int` """ self.translationChanged.emit(trans, sid)
[docs] @debugmethod @QtCore.pyqtSlot(bool, int) def updateButton(self, status, sid): """ update slot for image source :param status: button status :type status: :obj:`bool` :param sid: source id :type sid: :obj:`int` """ while len(self.__buttonstatus) <= sid: self.__buttonstatus.append(False) self.__sourcetabs[-1].updateLayout() self.__buttonstatus[sid] = status lstatus = self.__buttonstatus[:self.count()] fstatus = sum(lstatus) == len(lstatus) self.__sourcetabs[0].updateButton(fstatus)
[docs] @debugmethod def updateMetaData(self, **kargs): """ update source input parameters :param kargs: source widget input parameter dictionary :type kargs: :obj:`dict` < :obj:`str`, :obj:`any`> """ for st in self.__sourcetabs: st.updateMetaData(**kargs)
[docs] @debugmethod def updateSourceMetaData(self, sid, **kargs): """ update source input parameters :param sid: source id :type sid: :obj:`int` :param kargs: source widget input parameter dictionary :type kargs: :obj:`dict` < :obj:`str`, :obj:`any`> """ if len(self.__sourcetabs) > sid: self.__sourcetabs[sid].updateMetaData(**kargs)
[docs] @debugmethod def isConnected(self): """ is datasource source connected :returns: if datasource source connected :rtype: :obj:`bool` """ return self.__connected
[docs] @debugmethod @QtCore.pyqtSlot() def toggleServerConnection(self): """ toggles server connection """ if self.__errorstatus: self.setErrorStatus() if self.__connected: for st in self.__sourcetabs: st.disconnectWidget() self.__connected = False self.sourceDisconnected.emit() else: for st in self.__sourcetabs: st.connectWidget() status = json.dumps( [st.sourceStatus() for st in self.__sourcetabs][:self.count()]) self.sourceConnected.emit(status)
[docs] @debugmethod def setErrorStatus(self, status=""): """ set error status :param status: error status :type status: :obj:`str` """ for st in self.__sourcetabs: st.setErrorStatus(status) self.__errorstatus = status
[docs] @debugmethod def connectSuccess(self, port=None): """ set connection status on and display connection status :param port: zmq port :type port: :obj: `str` """ self.__connected = True for st in self.__sourcetabs: st.connectSuccess(port)
[docs] @debugmethod def connectFailure(self): """ set connection status off and display connection status """ self.__connected = False for i, st in enumerate(self.__sourcetabs): self.sourceStateChanged.emit(0, i) st.connectFailure()
[docs] @debugmethod def configure(self, sid, configuration): """ set configuration for the current image source :param sid: source id :type sid: :obj:`int` :param configuration: configuration string :type configuration: :obj:`str` """ if len(self.__sourcetabs) > sid: self.__sourcetabs[sid].configure(configuration)
[docs] @debugmethod def configuration(self): """ provides configuration for the current image source :return: configuration string :rtype configuration: :obj:`str` """ return [st.configuration() or "" for st in self.__sourcetabs][:self.count()]
[docs] @debugmethod def setTranslation(self, trans, sid): """ stores translation of the given source :param: x,y tranlation, e.g. 2345,354 :type: :obj:`str` :param sid: source id :type sid: :obj:`int` """ if len(self.__sourcetabs) > sid: self.__sourcetabs[sid].setTranslation(trans)
[docs] @debugmethod def showItem(self, trans): """ show items of the widget :param trans: translation item show status :type trans: :obj:`bool` """ for st in self.__sourcetabs: st.showItem(trans) for cb in self.__tabcheckboxes: if trans: cb.show() else: cb.hide()
[docs] @debugmethod def start(self): """ starts viewing if pushButton enable """ if self.__sourcetabs[0].pushButtonEnabled(): self.toggleServerConnection()