diff options
Diffstat (limited to 'lib/taurus/qt/qtgui')
91 files changed, 1409 insertions, 893 deletions
diff --git a/lib/taurus/qt/qtgui/__init__.py b/lib/taurus/qt/qtgui/__init__.py index 85e7ce55..d4fe4fe3 100644 --- a/lib/taurus/qt/qtgui/__init__.py +++ b/lib/taurus/qt/qtgui/__init__.py @@ -36,7 +36,8 @@ import sys import glob import pkg_resources from taurus import tauruscustomsettings as __S -from taurus import debug as __debug +from taurus import info as __info +from taurus import warning as __warning __docformat__ = 'restructuredtext' @@ -63,11 +64,12 @@ for __p in pkg_resources.iter_entry_points('taurus.qt.qtgui'): setattr(sys.modules[__name__], __p.name, __mod) # Add it to sys.modules sys.modules[__modname] = __mod - __debug('Plugin "%s" loaded as "%s"', __p.module_name, __modname) + __info('Plugin "%s" loaded as "%s"', __p.module_name, __modname) except Exception as e: - __debug('Could not load plugin "%s". Reason: %s', __p.module_name, e) + __warning('Could not load plugin "%s". Reason: %s', __p.module_name, e) # ------------------------------------------------------------------------ -del os, glob, __icon, icon_dir, pkg_resources, sys, __mod, __modname, __debug +del (os, glob, __icon, icon_dir, pkg_resources, sys, __mod, __modname, __info, + __warning) diff --git a/lib/taurus/qt/qtgui/application/taurusapplication.py b/lib/taurus/qt/qtgui/application/taurusapplication.py index 07a6c127..40eea105 100644 --- a/lib/taurus/qt/qtgui/application/taurusapplication.py +++ b/lib/taurus/qt/qtgui/application/taurusapplication.py @@ -37,7 +37,6 @@ import threading from taurus.external.qt import Qt from taurus.core.util.log import LogExceptHook, Logger -import taurus.core.util.argparse __all__ = ["TaurusApplication"] @@ -123,64 +122,45 @@ class STD(Logger): class TaurusApplication(Qt.QApplication, Logger): - """A QApplication that additionally parses the command line looking - for taurus options. This is done using the - :mod:`taurus.core.util.argparse`. - To create a TaurusApplication object you should use the same parameters - as in QApplication. + """A QApplication that performs some taurus-specific initializations + and (optionally but deprecated) also parses the command line for taurus + options. The optional keyword parameters: - app_name: (str) application name - app_version: (str) application version - org_name: (str) organization name - org_domain: (str) organization domain + - cmd_line_parser (None [or DEPRECATED :class:`optparse.OptionParser`]) - ...And at last the 'cmd_line_parser' which should be an instance of - :class:`optparse.OptionParser`. Simple example:: + If cmd_line_parser is explicitly set to None (recommended), no parsing will + be done at all. If a :class:`optparse.OptionParser` instance is passed as + cmd_line_parser (deprecated), it will be used for parsing the command line + arguments. If it is not explicitly passed (not recommended), a default + parser will be assumed with the default taurus options. - import sys - import taurus.qt.qtgui.application - import taurus.qt.qtgui.display - - app = taurus.qt.qtgui.application.TaurusApplication() - - w = taurus.qt.qtgui.display.TaurusLabel() - w.model = 'sys/tg_test/1/double_scalar' - w.show() - - sys.exit(app.exec_()) - - A more complex example showing how to add options and a usage help:: + Simple example:: import sys - import taurus.core.util.argparse - import taurus.qt.qtgui.application + from taurus.qt.qtgui.application import TaurusApplication import taurus.qt.qtgui.display - parser = taurus.core.util.argparse.get_taurus_parser() - parser.usage = "%prog [options] <model>" - parser.add_option("--hello") - - app = taurus.qt.qtgui.application.TaurusApplication(cmd_line_parser=parser) - args = app.get_command_line_args() - if len(args) < 1: - sys.stderr.write("Need to supply model attribute") - sys.exit(1) + app = TaurusApplication(cmd_line_parser=None) w = taurus.qt.qtgui.display.TaurusLabel() - w.model = args[1] + w.model = 'sys/tg_test/1/double_scalar' w.show() sys.exit(app.exec_()) - For more details on taurus command line parsing check - :mod:`taurus.core.util.argparse`. """ def __init__(self, *args, **kwargs): """The constructor. Parameters are the same as QApplication plus a - keyword parameter: 'cmd_line_parser' which should be an instance of - :class:`optparse.OptionParser`""" + keyword parameter: 'cmd_line_parser' which should be None or an + instance of :class:`optparse.OptionParser`. If cmd_line_parser is None + no command line parsing will be done () + """ # lock to safely get singleton elements (like IPython taurus # console app) @@ -189,18 +169,11 @@ class TaurusApplication(Qt.QApplication, Logger): if len(args) == 0: args = getattr(sys, 'argv', []), - parser = None - app_name, app_version, org_name, org_domain = None, None, None, None - if 'app_name' in kwargs: - app_name = kwargs.pop('app_name') - if 'app_version' in kwargs: - app_version = kwargs.pop('app_version') - if 'org_name' in kwargs: - org_name = kwargs.pop('org_name') - if 'org_domain' in kwargs: - org_domain = kwargs.pop('org_domain') - if 'cmd_line_parser' in kwargs: - parser = kwargs.pop('cmd_line_parser') + app_name = kwargs.pop('app_name', None) + app_version = kwargs.pop('app_version', None) + org_name = kwargs.pop('org_name', None) + org_domain = kwargs.pop('org_domain', None) + parser = kwargs.pop('cmd_line_parser', optparse.OptionParser()) ####################################################################### # Workaround for XInitThreads-related crash. @@ -235,21 +208,21 @@ class TaurusApplication(Qt.QApplication, Logger): if org_domain is not None: self.setOrganizationDomain(org_domain) - # if the constructor was called without a parser or with a parser that - # doesn't contain version information and with an application - # name and/or version, then add the --version capability - if (parser is None or parser.version is None) and app_version: - v = app_version - if app_name: - v = app_name + " " + app_version - if parser is None: - parser = optparse.OptionParser(version=v) - elif parser.version is None: + if parser is None: + p, opt, args = None, None, None + else: + if parser.version is None and app_version: + # if the parser does not contain version information + # but we have an application version, add the + # --version capability + v = app_version + if app_name: + v = app_name + " " + app_version parser.version = v parser._add_version_option() - p, opt, args = \ - taurus.core.util.argparse.init_taurus_args( + import taurus.core.util.argparse + p, opt, args = taurus.core.util.argparse.init_taurus_args( parser=parser, args=args[0][1:]) self._cmd_line_parser = p @@ -306,6 +279,7 @@ class TaurusApplication(Qt.QApplication, Logger): :return: the parser used in the command line :rtype: :class:`optparse.OptionParser`""" + # TODO: issue a warning if this is uninitialized (cmd_line_parser=None) return self._cmd_line_parser def get_command_line_options(self): @@ -314,6 +288,7 @@ class TaurusApplication(Qt.QApplication, Logger): :return: the command line options :rtype: :class:`optparse.Option`""" + # TODO: issue a warning if this is uninitialized (cmd_line_parser=None) return self._cmd_line_options def get_command_line_args(self): @@ -322,6 +297,7 @@ class TaurusApplication(Qt.QApplication, Logger): :return: the command line arguments :rtype: list of strings""" + # TODO: issue a warning if this is uninitialized (cmd_line_parser=None) return self._cmd_line_args def setTaurusStyle(self, styleName): diff --git a/lib/taurus/qt/qtgui/base/taurusbase.py b/lib/taurus/qt/qtgui/base/taurusbase.py index 931b6d60..8ffd6206 100644 --- a/lib/taurus/qt/qtgui/base/taurusbase.py +++ b/lib/taurus/qt/qtgui/base/taurusbase.py @@ -47,7 +47,7 @@ from taurus.core.tauruslistener import TaurusListener, TaurusExceptionListener from taurus.core.taurusoperation import WriteAttrOperation from taurus.core.util.eventfilters import filterEvent from taurus.core.util.log import deprecation_decorator -from taurus.qt.qtcore.util.signal import baseSignal +from taurus.qt.qtcore.util import baseSignal from taurus.qt.qtcore.configuration import BaseConfigurableClass from taurus.qt.qtcore.mimetypes import TAURUS_ATTR_MIME_TYPE from taurus.qt.qtcore.mimetypes import TAURUS_DEV_MIME_TYPE @@ -110,7 +110,7 @@ class TaurusBaseComponent(TaurusListener, BaseConfigurableClass): taurusEvent = baseSignal('taurusEvent', object, object, object) - def __init__(self, name='', parent=None, designMode=False): + def __init__(self, name='', parent=None, designMode=False, **kwargs): """Initialization of TaurusBaseComponent""" self.modelObj = None self.modelName = '' @@ -121,8 +121,12 @@ class TaurusBaseComponent(TaurusListener, BaseConfigurableClass): BaseConfigurableClass.__init__(self) - self.taurusMenu = None - self.taurusMenuData = '' + # -------------------------------------------------------------- + # Deprecated API for context menu + self.taurusMenu = None # deprecated since 4.5.3a. Do not use + self.taurusMenuData = '' # deprecated since 4.5.3a. Do not use + self.__explicitPopupMenu = False + # -------------------------------------------------------------- # attributes storing property values self._format = None @@ -165,6 +169,12 @@ class TaurusBaseComponent(TaurusListener, BaseConfigurableClass): 'formatter') self.resetModelInConfig() + # connect taurusEvent signal to filterEvent + try: + self.taurusEvent.connect(self.filterEvent) + except Exception as e: + self.warning('Could not connect taurusEvent signal: %r', e) + @deprecation_decorator(rel='4.0') def getSignaller(self): return self @@ -213,18 +223,39 @@ class TaurusBaseComponent(TaurusListener, BaseConfigurableClass): return taurus.Factory(scheme) #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- - # Popup menu behavior + # Context menu behavior #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- def contextMenuEvent(self, event): - """Handle the popup menu event + """ + DEPRECATED: + Until v4.5.3a, the default implementation of contextMenuEvent showed + the content of taurusMenu as a context menu. But this resulted in + unwanted behaviour when the widget already implemented its own context + menu (see https://github.com/taurus-org/taurus/issues/905 ) - :param event: the popup menu event + Therefore this feature was disabled in 4.5.3a. + + If you still want to show the contents of taurusMenu as a context menu, + you can explicitly reimplement the contextMenuEvent method as:: + + def contextMenuEvent(self, event): + self.taurusMenu.exec_(event.globalPos()) """ if self.taurusMenu is not None: - self.taurusMenu.exec_(event.globalPos()) - else: - event.ignore() + if self.__explicitPopupMenu: + # bck-compat: show taurusMenu as a contextMenu if it was + # explicitly created via the (deprecated) "setTaurusPopupMenu" + # API + self.taurusMenu.exec_(event.globalPos()) + return + else: + self.deprecated( + dep='taurusMenu context Menu API', + alt='custom contextMenuEvent to show taurusMenu', + rel='4.5.3a' + ) + event.ignore() #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- # Mandatory methods to be implemented in subclass implementation @@ -895,15 +926,11 @@ class TaurusBaseComponent(TaurusListener, BaseConfigurableClass): def preAttach(self): """Called inside self.attach() before actual attach is performed. - Default implementation just emits a signal. + Default implementation does nothing. Override when necessary. """ - try: - self.taurusEvent.connect(self.filterEvent) - except: - # self.error("In %s.preAttach() ... failed!" % str(type(self))) - pass + pass def postAttach(self): """Called inside self.attach() after actual attach is performed. @@ -915,15 +942,11 @@ class TaurusBaseComponent(TaurusListener, BaseConfigurableClass): def preDetach(self): """Called inside self.detach() before actual deattach is performed. - Default implementation just disconnects a signal. + Default implementation does nothing. Override when necessary. """ - try: - self.taurusEvent.disconnect(self.filterEvent) - except: - # self.error("In %s.preDetach() ... failed!" % str(type(self))) - pass + pass def postDetach(self): """Called inside self.detach() after actual deattach is performed. @@ -1238,14 +1261,18 @@ class TaurusBaseComponent(TaurusListener, BaseConfigurableClass): """Resets the showing of the display value to True""" self.setShowText(True) + @deprecation_decorator(rel='4.5.3a') def setTaurusPopupMenu(self, menuData): """Sets/unsets the taurus popup menu :param menuData: (str) an xml representing the popup menu""" self.taurusMenuData = str(menuData) + self.__explicitPopupMenu = True factory = ActionFactory() self.taurusMenu = factory.getNewMenu(self, self.taurusMenuData) + + @deprecation_decorator(rel='4.5.3a') def getTaurusPopupMenu(self): """Returns an xml string representing the current taurus popup menu @@ -1253,9 +1280,11 @@ class TaurusBaseComponent(TaurusListener, BaseConfigurableClass): """ return self.taurusMenuData + @deprecation_decorator(rel='4.5.3a') def resetTaurusPopupMenu(self): """Resets the taurus popup menu to empty""" self.taurusMenuData = '' + self.__explicitPopupMenu = False def isModifiableByUser(self): '''whether the user can change the contents of the widget @@ -1306,7 +1335,7 @@ class TaurusBaseWidget(TaurusBaseComponent): _dragEnabled = False - def __init__(self, name='', parent=None, designMode=False): + def __init__(self, name='', parent=None, designMode=False, **kwargs): self._disconnect_on_hide = False self._supportedMimeTypes = None self._autoTooltip = True @@ -1727,7 +1756,7 @@ class TaurusBaseWidget(TaurusBaseComponent): formats = mimeData.formats() for mtype in supported: if mtype in formats: - d = bytes(mimeData.data(mtype)) + d = bytes(mimeData.data(mtype)).decode('utf-8') if d is None: return None try: @@ -1910,7 +1939,8 @@ class TaurusBaseWritableWidget(TaurusBaseWidget): applied = baseSignal('applied') - def __init__(self, name='', taurus_parent=None, designMode=False): + def __init__(self, name='', taurus_parent=None, designMode=False, + **kwargs): self.call__init__(TaurusBaseWidget, name, parent=taurus_parent, designMode=designMode) diff --git a/lib/taurus/qt/qtgui/button/qbuttonbox.py b/lib/taurus/qt/qtgui/button/qbuttonbox.py index dc364620..4de8f98c 100644 --- a/lib/taurus/qt/qtgui/button/qbuttonbox.py +++ b/lib/taurus/qt/qtgui/button/qbuttonbox.py @@ -118,7 +118,7 @@ if __name__ == "__main__": from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) bb = QButtonBox() bb.okClicked.connect(on_ok) bb.cancelClicked.connect(on_cancel) diff --git a/lib/taurus/qt/qtgui/button/taurusbutton.py b/lib/taurus/qt/qtgui/button/taurusbutton.py index 9649065e..6489549d 100644 --- a/lib/taurus/qt/qtgui/button/taurusbutton.py +++ b/lib/taurus/qt/qtgui/button/taurusbutton.py @@ -31,7 +31,7 @@ from builtins import map from builtins import str from future.utils import string_types -from taurus.external.qt import Qt +from taurus.external.qt import Qt, compat from taurus.core.taurusbasetypes import LockStatus, TaurusLockInfo from taurus.core.taurusdevice import TaurusDevice from taurus.qt.qtgui.base import TaurusBaseWidget @@ -265,7 +265,7 @@ class TaurusCommandButton(Qt.QPushButton, TaurusBaseWidget): .. seealso:: :class:`TaurusCommandsForm` provides a good example of use of TaurusCommandButton (including managing the return value) ''' # TODO: tango-centric - commandExecuted = Qt.pyqtSignal(object) + commandExecuted = Qt.pyqtSignal(compat.PY_OBJECT) def __init__(self, parent=None, designMode=False, command=None, parameters=None, icon=None, text=None, @@ -659,7 +659,7 @@ def commandButtonMain(): import sys from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) form = TaurusCommandButton(parent=None, designMode=False, command='DevBoolean', parameters=[ 123], icon='logos:taurus.png', text='launch: DevBoolean 123') form.setModel('sys/tg_test/1') @@ -677,7 +677,7 @@ def launcherButtonMain(): import sys from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) # Creating button giving the widget # from taurus.qt.qtgui.plot import TaurusPlot diff --git a/lib/taurus/qt/qtgui/compact/abstractswitcher.py b/lib/taurus/qt/qtgui/compact/abstractswitcher.py index 610eea45..8459c29b 100644 --- a/lib/taurus/qt/qtgui/compact/abstractswitcher.py +++ b/lib/taurus/qt/qtgui/compact/abstractswitcher.py @@ -336,7 +336,7 @@ def demo1(): from taurus.qt.qtgui.display import TaurusLabel from taurus.qt.qtgui.input import TaurusValueLineEdit - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) w = TaurusReadWriteSwitcher(readWClass=TaurusLabel, writeWClass=TaurusValueLineEdit) @@ -359,7 +359,7 @@ def demo2(): writeWClass = TaurusValueLineEdit exitEditTriggers = ('editingFinished()', Qt.Qt.Key_Escape) - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) f = TaurusForm() f.model = ['sys/tg_test/1/long_scalar', 'sys/tg_test/1/long_scalar'] @@ -379,7 +379,7 @@ def demo3(): from taurus.qt.qtgui.display import TaurusLabel, TaurusLed from taurus.qt.qtgui.input import TaurusValueLineEdit, TaurusValueCheckBox - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) w1 = TaurusReadWriteSwitcher(readWClass=TaurusLabel, writeWClass=TaurusValueLineEdit) diff --git a/lib/taurus/qt/qtgui/compact/basicswitcher.py b/lib/taurus/qt/qtgui/compact/basicswitcher.py index b21f371f..3a029a54 100644 --- a/lib/taurus/qt/qtgui/compact/basicswitcher.py +++ b/lib/taurus/qt/qtgui/compact/basicswitcher.py @@ -59,7 +59,7 @@ def _demo(): from taurus.qt.qtgui.panel import TaurusForm from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) f = TaurusForm() f.model = ['sys/tg_test/1/long_scalar', 'sys/tg_test/1/long_scalar', diff --git a/lib/taurus/qt/qtgui/container/taurusmainwindow.py b/lib/taurus/qt/qtgui/container/taurusmainwindow.py index 8464dcd8..3bf50b9e 100644 --- a/lib/taurus/qt/qtgui/container/taurusmainwindow.py +++ b/lib/taurus/qt/qtgui/container/taurusmainwindow.py @@ -187,35 +187,62 @@ class TaurusMainWindow(Qt.QMainWindow, TaurusBaseContainer): perspectiveChanged = Qt.pyqtSignal('QString') # customization options: - # blinking semi-period in ms. Set to None for not showing the Heart beat - # LED - _heartbeat = 1500 - _showFileMenu = True - _showViewMenu = True - _showTaurusMenu = True - _showToolsMenu = True - _showHelpMenu = True - # Allows the user to change/create/delete perspectives - _supportUserPerspectives = True - _showLogger = True - # - # set to None for disabling splash screen - _splashLogo = "large:TaurusSplash.png" - _splashMessage = "Initializing Main window..." + #: Heartbeat LED blinking semi-period in ms. Set to None for not showing it + HEARTBEAT = 1500 + #: Whether to show the File menu + FILE_MENU_ENABLED = True + #: Whether to show the View menu + VIEW_MENU_ENABLED = True + #: Whether to show the Taurus menu + TAURUS_MENU_ENABLED = True + #: Whether to show the Tools menu + TOOLS_MENU_ENABLED = True + #: Whether to show the Help menu + HELP_MENU_ENABLED = True + #: Whether to show the Full Screen Toolbar + FULLSCREEN_TOOLBAR_ENABLED = True + #: Whether to show actions for user perspectives + USER_PERSPECTIVES_ENABLED = True + #: Whether add a dockwidget with the logger widget + LOGGER_WIDGET_ENABLED = True + #: Name of logo image for splash screen. Set to None for disabling splash + SPLASH_LOGO_NAME = "large:TaurusSplash.png" + #: Message for splash screen + SPLASH_MESSAGE = "Initializing Main window..." + + _old_options_api = { + '_heartbeat': 'HEARTBEAT', + '_showFileMenu': 'FILE_MENU_ENABLED', + '_showViewMenu': 'VIEW_MENU_ENABLED', + '_showTaurusMenu': 'TAURUS_MENU_ENABLED', + '_showToolsMenu': 'TOOLS_MENU_ENABLED', + '_showHelpMenu': 'HELP_MENU_ENABLED', + '_showLogger': 'LOGGER_WIDGET_ENABLED', + '_supportUserPerspectives': 'USER_PERSPECTIVES_ENABLED', + '_splashLogo': 'SPLASH_LOGO_NAME', + '_splashMessage': 'SPLASH_MESSAGE', + } def __init__(self, parent=None, designMode=False, splash=None): name = self.__class__.__name__ self.call__init__wo_kw(Qt.QMainWindow, parent) self.call__init__(TaurusBaseContainer, name, designMode=designMode) + + # Provide bck-compat with old options API + for old, new in self._old_options_api.items(): + if hasattr(self, old): + self.deprecated(dep=old, alt=new, rel='4.5.3a') + setattr(self, new, getattr(self, old)) + if splash is None: - splash = bool(self._splashLogo) + splash = bool(self.SPLASH_LOGO_NAME) self.__splashScreen = None if splash and not designMode: self.__splashScreen = Qt.QSplashScreen( - Qt.QPixmap(self._splashLogo)) + Qt.QPixmap(self.SPLASH_LOGO_NAME)) self.__splashScreen.show() - self.__splashScreen.showMessage(self._splashMessage) + self.__splashScreen.showMessage(self.SPLASH_MESSAGE) self.__tangoHost = "" self.__settings = None @@ -224,10 +251,12 @@ class TaurusMainWindow(Qt.QMainWindow, TaurusBaseContainer): self.helpManualDW = None self.helpManualBrowser = None - self.resetHelpManualURI() + + if self.HELP_MENU_ENABLED: + self.resetHelpManualURI() # Heartbeat - if self._heartbeat is not None: + if self.HEARTBEAT is not None: from taurus.qt.qtgui.display import QLed self.heartbeatLed = QLed() self.heartbeatLed.setToolTip( @@ -244,34 +273,49 @@ class TaurusMainWindow(Qt.QMainWindow, TaurusBaseContainer): self.__createActions() # logger dock widget - if self._showLogger: + if self.LOGGER_WIDGET_ENABLED: self.addLoggerWidget() # Create Menus - if self._showFileMenu: # File menu + if self.FILE_MENU_ENABLED: # File menu self.createFileMenu() - if self._showViewMenu: # View menu + if self.VIEW_MENU_ENABLED: # View menu self.createViewMenu() - if self._showTaurusMenu: # Taurus Menu + if self.TAURUS_MENU_ENABLED: # Taurus Menu self.createTaurusMenu() - if self._showToolsMenu: # Tools Menu + if self.TOOLS_MENU_ENABLED: # Tools Menu self.createToolsMenu() - if self._showHelpMenu: # Help Menu + if self.HELP_MENU_ENABLED: # Help Menu self.createHelpMenu() # View Toolbar - self.viewToolBar = self.addToolBar("View") - self.viewToolBar.setObjectName("viewToolBar") - self.viewToolBar.addAction(self.toggleFullScreenAction) + if self.FULLSCREEN_TOOLBAR_ENABLED: + self.viewToolBar = self.addToolBar("View") + self.viewToolBar.setObjectName("viewToolBar") + self.viewToolBar.addAction(self.toggleFullScreenAction) # Perspectives Toolbar - if self._supportUserPerspectives: + if self.USER_PERSPECTIVES_ENABLED: self.createPerspectivesToolBar() # disable the configuration action if there is nothing to configure self.configurationAction.setEnabled( self.configurationDialog._tabwidget.count()) + def __setattr__(self, key, value): + super(TaurusMainWindow, self).__setattr__(key, value) + if key in self._old_options_api: + new = self._old_options_api[key] + setattr(self, new, value) + self.deprecated(dep=key, alt=new, rel='4.5.3a') + + def contextMenuEvent(self, event): + """Reimplemented to avoid deprecation warning related to: + https://github.com/taurus-org/taurus/issues/905 + """ + # TODO: Remove this once the deprecation of the Popup menu is enforced + event.ignore() + def addLoggerWidget(self, hidden=True): '''adds a QLoggingWidget as a dockwidget of the main window (and hides it by default)''' from taurus.qt.qtgui.table import QLoggingWidget @@ -286,7 +330,7 @@ class TaurusMainWindow(Qt.QMainWindow, TaurusBaseContainer): def createFileMenu(self): '''adds a "File" Menu''' self.fileMenu = self.menuBar().addMenu("File") - if self._supportUserPerspectives: + if self.USER_PERSPECTIVES_ENABLED: self.fileMenu.addAction(self.importSettingsFileAction) self.fileMenu.addAction(self.exportSettingsFileAction) # self.fileMenu.addAction(self.resetSettingsAction) @@ -296,12 +340,12 @@ class TaurusMainWindow(Qt.QMainWindow, TaurusBaseContainer): def createViewMenu(self): '''adds a "View" Menu''' self.viewMenu = self.menuBar().addMenu("View") - if self._showLogger: + if self.LOGGER_WIDGET_ENABLED: self.viewMenu.addAction(self.__loggerDW.toggleViewAction()) self.viewToolBarsMenu = self.viewMenu.addMenu("Tool Bars") self.viewMenu.addSeparator() self.viewMenu.addAction(self.toggleFullScreenAction) - if self._supportUserPerspectives: + if self.USER_PERSPECTIVES_ENABLED: self.viewMenu.addSeparator() self.perspectivesMenu = Qt.QMenu("Load Perspectives", self) self.viewMenu.addMenu(self.perspectivesMenu) @@ -341,7 +385,7 @@ class TaurusMainWindow(Qt.QMainWindow, TaurusBaseContainer): pbutton.setMenu(self.perspectivesMenu) self.perspectivesToolBar.addWidget(pbutton) self.perspectivesToolBar.addAction(self.savePerspectiveAction) - if self._showViewMenu: + if self.VIEW_MENU_ENABLED: self.viewToolBarsMenu.addAction( self.perspectivesToolBar.toggleViewAction()) @@ -351,9 +395,10 @@ class TaurusMainWindow(Qt.QMainWindow, TaurusBaseContainer): .. note:: This method may need be called by derived classes at the end of their initialization. - :return: (QMenu) the updated perspectives menu (or None if self._supportUserPerspectives is False) + :return: (QMenu) the updated perspectives menu (or None if + self.USER_PERSPECTIVES_ENABLED is False) ''' - if not self._supportUserPerspectives: + if not self.USER_PERSPECTIVES_ENABLED: return None self.perspectivesMenu.clear() for pname in self.getPerspectivesList(): @@ -641,8 +686,10 @@ class TaurusMainWindow(Qt.QMainWindow, TaurusBaseContainer): ba = settings.value("TaurusConfig") or Qt.QByteArray() self.applyQConfig(ba) except Exception as e: - msg = 'Problem loading configuration from "%s". Some settings may not be restored.\n Details: %s' % ( - str(settings.fileName()), repr(e)) + msg = ('Problem loading configuration from "{}". ' + + 'Some settings may not be restored.\n' + + ' Reason: {}' + ).format(str(settings.fileName()), e) self.error(msg) Qt.QMessageBox.warning( self, 'Error Loading settings', msg, Qt.QMessageBox.Ok) @@ -673,6 +720,10 @@ class TaurusMainWindow(Qt.QMainWindow, TaurusBaseContainer): saved (no prefix by default) ''' settings = self.getQSettings() + if not settings.isWritable(): + self.info('Settings cannot be saved in "%s"', settings.fileName()) + return + if group is not None: settings.beginGroup(group) # main window geometry @@ -683,7 +734,7 @@ class TaurusMainWindow(Qt.QMainWindow, TaurusBaseContainer): settings.setValue("TaurusConfig", self.createQConfig()) if group is not None: settings.endGroup() - self.info('MainWindow settings saved in "%s"' % settings.fileName()) + self.info('Settings saved in "%s"' % settings.fileName()) @Qt.pyqtSlot() @Qt.pyqtSlot('QString') @@ -878,12 +929,12 @@ class TaurusMainWindow(Qt.QMainWindow, TaurusBaseContainer): self.extAppsBar.setObjectName("External Applications") self.extAppsBar.setToolButtonStyle( Qt.Qt.ToolButtonTextBesideIcon) - if self._showViewMenu: + if self.VIEW_MENU_ENABLED: self.viewToolBarsMenu.addAction( self.extAppsBar.toggleViewAction()) self.extAppsBar.addAction(extapp) - if toMenu and self._showToolsMenu: + if toMenu and self.TOOLS_MENU_ENABLED: if self.toolsMenu is None: self.createToolsMenu() self.externalAppsMenu.addAction(extapp) @@ -1059,7 +1110,7 @@ class TaurusMainWindow(Qt.QMainWindow, TaurusBaseContainer): def resetHeartbeat(self): '''resets the heartbeat interval''' - self.setHeartbeat(self.__class__._heartbeat) + self.setHeartbeat(self.__class__.HEARTBEAT) #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- # Public slots for apply/restore changes @@ -1106,24 +1157,24 @@ class TaurusMainWindow(Qt.QMainWindow, TaurusBaseContainer): if __name__ == "__main__": - import taurus.qt.qtgui.application - app = taurus.qt.qtgui.application.TaurusApplication() + from taurus.qt.qtgui.application import TaurusApplication + app = TaurusApplication(cmd_line_parser=None) app.setApplicationName('TaurusMainWindow-test') app.setOrganizationName('ALBA') app.basicConfig() class MyMainWindow(TaurusMainWindow): - _heartbeat = 300 # blinking semi-period in ms. Set to None for not showing the Heart beat LED - _showFileMenu = True - _showViewMenu = True - _showTaurusMenu = False - _showToolsMenu = True - _showHelpMenu = True + HEARTBEAT = 300 # blinking semi-period in ms. Set to None for not showing the Heart beat LED + FILE_MENU_ENABLED = True + VIEW_MENU_ENABLED = True + TAURUS_MENU_ENABLED = False + TOOLS_MENU_ENABLED = True + HELP_MENU_ENABLED = True # Allows the user to change/create/delete perspectives - _supportUserPerspectives = True - _showLogger = True + USER_PERSPECTIVES_ENABLED = True + LOGGER_WIDGET_ENABLED = True # set to None for disabling splash screen - _splashLogo = "large:TaurusSplash.png" + SPLASH_LOGO_NAME = "large:TaurusSplash.png" _splashMessage = "Initializing Main window..." def __init__(self): diff --git a/lib/taurus/qt/qtgui/display/qled.py b/lib/taurus/qt/qtgui/display/qled.py index 0cb1e040..799c3020 100644 --- a/lib/taurus/qt/qtgui/display/qled.py +++ b/lib/taurus/qt/qtgui/display/qled.py @@ -383,7 +383,7 @@ def main(): if owns_app: from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) w = Qt.QWidget() layout = Qt.QGridLayout() diff --git a/lib/taurus/qt/qtgui/display/qlogo.py b/lib/taurus/qt/qtgui/display/qlogo.py index d2664a0e..5510d29b 100644 --- a/lib/taurus/qt/qtgui/display/qlogo.py +++ b/lib/taurus/qt/qtgui/display/qlogo.py @@ -82,7 +82,7 @@ def main(): import sys from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) w = QLogo() w.show() sys.exit(app.exec_()) diff --git a/lib/taurus/qt/qtgui/display/test/test_tauruslabel.py b/lib/taurus/qt/qtgui/display/test/test_tauruslabel.py index bedc02be..e231faa3 100644 --- a/lib/taurus/qt/qtgui/display/test/test_tauruslabel.py +++ b/lib/taurus/qt/qtgui/display/test/test_tauruslabel.py @@ -34,6 +34,8 @@ from taurus.qt.qtgui.container import TaurusWidget from taurus.core.tango.test import TangoSchemeTestLauncher import functools from taurus.core.util.colors import ATTRIBUTE_QUALITY_DATA, DEVICE_STATE_DATA +from pint import UnitRegistry as ur +import numpy DEV_NAME = TangoSchemeTestLauncher.DEV_NAME @@ -102,7 +104,9 @@ testOldFgroles = functools.partial(insertTest, helper_name='text', maxdepr=1, # ------------------------------------------------------------------------------ @insertTest(helper_name='text', model='tango:' + DEV_NAME + '/double_image#rvalue[1,::2]', - expected='[ 1.23 1.23] mm') + expected='{:~}'.format(numpy.array([1.23,1.23])*ur().mm) + # expected is not explicit to support pint v<0.8 particularities + ) @insertTest(helper_name='text', model='tango:' + DEV_NAME + '/double_spectrum#rvalue[1]', expected='1.23 mm') diff --git a/lib/taurus/qt/qtgui/extra_guiqwt/cli.py b/lib/taurus/qt/qtgui/extra_guiqwt/cli.py new file mode 100644 index 00000000..1a00f8df --- /dev/null +++ b/lib/taurus/qt/qtgui/extra_guiqwt/cli.py @@ -0,0 +1,42 @@ +############################################################################# +## +# This file is part of Taurus +## +# http://taurus-scada.org +## +# Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain +## +# Taurus is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +## +# Taurus 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 Lesser General Public License for more details. +## +# You should have received a copy of the GNU Lesser General Public License +# along with Taurus. If not, see <http://www.gnu.org/licenses/>. +## +############################################################################# + +import click + + +from .plot import image_cmd +from .taurustrend2d import trend2d_cmd + + +@click.group('guiqwt') +def guiqwt(): + """guiqwt related commands (image, trend2d)""" + pass + + +guiqwt.add_command(image_cmd) +guiqwt.add_command(trend2d_cmd) + +if __name__ == '__main__': + guiqwt() + diff --git a/lib/taurus/qt/qtgui/extra_guiqwt/curve.py b/lib/taurus/qt/qtgui/extra_guiqwt/curve.py index 18f3d6bf..a4cf9df4 100644 --- a/lib/taurus/qt/qtgui/extra_guiqwt/curve.py +++ b/lib/taurus/qt/qtgui/extra_guiqwt/curve.py @@ -30,7 +30,7 @@ from builtins import next from taurus.external.qt import Qt from taurus.qt.qtgui.base import TaurusBaseComponent -from taurus.qt.qtcore.util.signal import baseSignal +from taurus.qt.qtcore.util import baseSignal import taurus from guiqwt.curve import CurveItem from taurus.qt.qtgui.extra_guiqwt.styles import TaurusCurveParam, TaurusTrendParam diff --git a/lib/taurus/qt/qtgui/extra_guiqwt/curvesmodel.py b/lib/taurus/qt/qtgui/extra_guiqwt/curvesmodel.py index 8dc49bde..2175a284 100644 --- a/lib/taurus/qt/qtgui/extra_guiqwt/curvesmodel.py +++ b/lib/taurus/qt/qtgui/extra_guiqwt/curvesmodel.py @@ -30,6 +30,7 @@ curvesmodel Model and view for new CurveItem configuration from __future__ import print_function from builtins import next from builtins import str +from builtins import bytes from builtins import range from builtins import object @@ -320,11 +321,12 @@ class TaurusCurveItemTableModel(Qt.QAbstractTableModel): else: column = parent.columnCount() if data.hasFormat(TAURUS_ATTR_MIME_TYPE): - self.setData(self.index(row, column), - value=str(data.data(TAURUS_ATTR_MIME_TYPE))) + model = bytes(data.data(TAURUS_ATTR_MIME_TYPE)).decode("utf-8") + self.setData(self.index(row, column), value=model) return True elif data.hasFormat(TAURUS_MODEL_LIST_MIME_TYPE): - models = str(data.data(TAURUS_MODEL_LIST_MIME_TYPE)).split() + d = bytes(data.data(TAURUS_MODEL_LIST_MIME_TYPE)) + models = d.decode("utf-8").split() if len(models) == 1: self.setData(self.index(row, column), value=models[0]) return True diff --git a/lib/taurus/qt/qtgui/extra_guiqwt/image.py b/lib/taurus/qt/qtgui/extra_guiqwt/image.py index 1781043f..885b19a9 100644 --- a/lib/taurus/qt/qtgui/extra_guiqwt/image.py +++ b/lib/taurus/qt/qtgui/extra_guiqwt/image.py @@ -33,7 +33,7 @@ __all__ = ["TaurusImageItem", "TaurusRGBImageItem", "TaurusTrend2DItem", from taurus.core.units import Quantity from taurus.external.qt import Qt from taurus.qt.qtgui.base import TaurusBaseComponent -from taurus.qt.qtcore.util.signal import baseSignal +from taurus.qt.qtcore.util import baseSignal import taurus.core from taurus.core.util.containers import ArrayBuffer @@ -601,7 +601,7 @@ def test1(): from guiqwt.plot import ImageDialog from taurus.qt.qtgui.extra_guiqwt.builder import make from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) # define a taurus image #model1 = 'sys/tg_test/1/short_image_ro' diff --git a/lib/taurus/qt/qtgui/extra_guiqwt/plot.py b/lib/taurus/qt/qtgui/extra_guiqwt/plot.py index 2ec85ac9..8ba2579b 100644 --- a/lib/taurus/qt/qtgui/extra_guiqwt/plot.py +++ b/lib/taurus/qt/qtgui/extra_guiqwt/plot.py @@ -29,6 +29,7 @@ Extension of :mod:`guiqwt.plot` from builtins import next from builtins import str +import click import copy from future.utils import string_types @@ -62,7 +63,7 @@ class TaurusCurveDialog(CurveDialog, TaurusBaseWidget): '''see :class:`guiqwt.plot.CurveDialog` for other valid initialization parameters''' CurveDialog.__init__(self, parent=parent, toolbar=toolbar, **kwargs) TaurusBaseWidget.__init__(self, 'TaurusCurveDialog') - self.deprecated(rel='4.1', dep='TaurusCurveDialog', alt='TaurusPlot / taurusplot launcher') + self.deprecated(rel='4.1', dep='TaurusCurveDialog', alt='TaurusPlot / taurus tpg plot launcher') self.setWindowFlags(Qt.Qt.Widget) self._designMode = designMode self._modelNames = CaselessList() @@ -209,7 +210,7 @@ class TaurusTrendDialog(CurveDialog, TaurusBaseWidget): '''see :class:`guiqwt.plot.CurveDialog` for other valid initialization parameters''' CurveDialog.__init__(self, parent=parent, toolbar=toolbar, **kwargs) TaurusBaseWidget.__init__(self, 'TaurusTrendDialog') - self.deprecated(rel='4.1', dep='TaurusTrendDialog', alt='TaurusTrend / taurustrend launcher') + self.deprecated(rel='4.1', dep='TaurusTrendDialog', alt='TaurusTrend / taurus tpg trend launcher') self.setWindowFlags(Qt.Qt.Widget) self._designMode = designMode self._modelNames = CaselessList() @@ -627,49 +628,48 @@ def taurusTrendDlgMain(): sys.exit(app.exec_()) -def taurusImageDlgMain(): +@click.command('image') +@click.argument('model', nargs=1, required=False) +@click.option('-c', '--color-mode', 'color_mode', + type=click.Choice(['gray', 'rgb']), + default='gray', + show_default=True, + help=('Color mode expected from the attribute') + ) +@click.option("--demo", is_flag=True, help="show a demo of the widget") +@click.option('--window-name', 'window_name', + default='TaurusPlot (qwt5)', + help='Name of the window') +def image_cmd(model, color_mode, demo, window_name): from taurus.qt.qtgui.application import TaurusApplication - import taurus.core import sys - # prepare options - parser = taurus.core.util.argparse.get_taurus_parser() - parser.set_usage("%prog [options] <model>") - parser.set_description( - 'a Taurus application for plotting Image Attributes') - parser.add_option("--demo", action="store_true", dest="demo", - default=False, help="show a demo of the widget") - parser.add_option("--rgb", action="store_true", dest="rgb_mode", - default=False, help="assume image is RGB") - parser.add_option("--window-name", dest="window_name", - default="Taurus Image", help="Name of the window") - app = TaurusApplication( - cmd_line_parser=parser, app_name="Taurus Image Dialog", app_version=taurus.Release.version) - args = app.get_command_line_args() - options = app.get_command_line_options() + app = TaurusApplication(cmd_line_parser=None, + app_name="Taurus Image Dialog") - # check & process options - if options.demo: - if options.rgb_mode: - args.append('eval:randint(0,256,(10,20,3))') + rgb_mode = (color_mode == 'rgb') + + # TODO: is "-c rgb --demo" doing the right thing?? Check it. + if demo: + if color_mode == 'rgb': + model = 'eval:randint(0,256,(10,20,3))' else: - args.append('eval:rand(256,128)') - w = TaurusImageDialog(wintitle=options.window_name) + model = 'eval:rand(256,128)' - w.setRGBmode(options.rgb_mode) + w = TaurusImageDialog(wintitle=window_name) + + w.setRGBmode(rgb_mode) # set model - if len(args) == 1: - w.setModel(args[0]) - else: - parser.print_help(sys.stderr) - sys.exit(1) + if model: + w.setModel(model) w.show() sys.exit(app.exec_()) if __name__ == "__main__": - taurusCurveDlgMain() + image_cmd() + # taurusCurveDlgMain() # taurusTrendDlgMain() -# taurusImageDlgMain() + # taurusImageDlgMain() diff --git a/lib/taurus/qt/qtgui/extra_guiqwt/taurustrend2d.py b/lib/taurus/qt/qtgui/extra_guiqwt/taurustrend2d.py index af564905..90090ff4 100644 --- a/lib/taurus/qt/qtgui/extra_guiqwt/taurustrend2d.py +++ b/lib/taurus/qt/qtgui/extra_guiqwt/taurustrend2d.py @@ -28,6 +28,8 @@ taurustrend.py: Generic trend widget for Taurus """ __all__ = ["TaurusTrend2DDialog"] +import click + from guiqwt.plot import ImageDialog from taurus.external.qt import Qt import taurus.core @@ -306,68 +308,46 @@ class TaurusTrend2DDialog(ImageDialog, TaurusBaseWidget): TaurusBaseWidget.resetModifiableByUser) -def taurusTrend2DMain(): +@click.command('trend2d') +@click.argument('model', nargs=1, required=False) +@click.option("-x", "--x-axis-mode", "x_axis_mode", + type=click.Choice(['t', 'd', 'e']), + default='d', + show_default=True, + help=("interpret X values as timestamps (t), " + + "time deltas (d) or event numbers (e). ") + ) +@click.option('-b', '--buffer', 'max_buffer_size', type=int, + default=512, + show_default=True, + help=("maximum number of values to be stacked " + + "(when reached, the oldest values will be " + + "discarded)") + ) +@click.option("--demo", is_flag=True, help="show a demo of the widget") +@click.option('--window-name', 'window_name', + default='TaurusPlot (qwt5)', + help='Name of the window') +def trend2d_cmd(model, x_axis_mode, max_buffer_size, + demo, window_name): from taurus.qt.qtgui.application import TaurusApplication - import taurus.core import sys - # prepare options - parser = taurus.core.util.argparse.get_taurus_parser() - parser.set_usage("%prog [options] <model>") - parser.set_description('a Taurus application for plotting trends of ' + - 'arrays (aka "spectrograms")') - parser.add_option("-x", "--x-axis-mode", dest="x_axis_mode", default='d', - metavar="t|d|e", - help=("interpret X values as timestamps (t), " + - "time deltas (d) or event numbers (e). " + - "Accepted values: t|d|e") - ) - parser.add_option("-b", "--buffer", dest="max_buffer_size", default='512', - help=("maximum number of values to be stacked " + - "(when reached, the oldest values will be " + - "discarded)") - ) - parser.add_option("-a", "--use-archiving", - action="store_true", dest="use_archiving", default=False) - parser.add_option("--demo", action="store_true", dest="demo", - default=False, help="show a demo of the widget") - parser.add_option("--window-name", dest="window_name", - default="Taurus Trend 2D", help="Name of the window") - - app = TaurusApplication(cmd_line_parser=parser, app_name="Taurus Trend 2D", - app_version=taurus.Release.version) - args = app.get_command_line_args() - options = app.get_command_line_options() - - # check & process options - stackModeMap = dict(t='datetime', d='deltatime', e='event') - if options.x_axis_mode.lower() not in stackModeMap: - parser.print_help(sys.stderr) - sys.exit(1) - - stackMode = stackModeMap[options.x_axis_mode.lower()] - - if options.demo: - args.append('eval:x=linspace(0,3,40);t=rand();sin(x+t)') - - w = TaurusTrend2DDialog(stackMode=stackMode, wintitle=options.window_name, - buffersize=int(options.max_buffer_size)) - - # set archiving - if options.use_archiving: - raise NotImplementedError('Archiving support is not yet implemented') - w.setUseArchiving(True) - - # set model - if len(args) == 1: - w.setModel(args[0]) - else: - parser.print_help(sys.stderr) - sys.exit(1) + if demo: + model = 'eval:x=linspace(0,3,40);t=rand();sin(x+t)' + + app = TaurusApplication(cmd_line_parser=None, app_name="Taurus Trend 2D") + + stackMode = dict(t='datetime', d='deltatime', e='event')[x_axis_mode] + + w = TaurusTrend2DDialog(stackMode=stackMode, wintitle=window_name, + buffersize=max_buffer_size) + if model: + w.setModel(model) w.show() sys.exit(app.exec_()) if __name__ == "__main__": - taurusTrend2DMain() + trend2d_cmd() diff --git a/lib/taurus/qt/qtgui/extra_guiqwt/tools.py b/lib/taurus/qt/qtgui/extra_guiqwt/tools.py index 25920c4f..fa752fb5 100644 --- a/lib/taurus/qt/qtgui/extra_guiqwt/tools.py +++ b/lib/taurus/qt/qtgui/extra_guiqwt/tools.py @@ -355,7 +355,7 @@ def testTool(tool): from taurus.qt.qtgui.application import TaurusApplication from guiqwt.plot import CurveDialog - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) win = CurveDialog(edit=False, toolbar=True) win.add_tool(tool) win.show() diff --git a/lib/taurus/qt/qtgui/extra_nexus/taurusnexuswidget.py b/lib/taurus/qt/qtgui/extra_nexus/taurusnexuswidget.py index c5715f19..570e41c1 100644 --- a/lib/taurus/qt/qtgui/extra_nexus/taurusnexuswidget.py +++ b/lib/taurus/qt/qtgui/extra_nexus/taurusnexuswidget.py @@ -203,7 +203,7 @@ if __name__ == "__main__": else: fname = None - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) w = TaurusNeXusBrowser() w.openFile(fname) w.show() diff --git a/lib/taurus/qt/qtgui/graphic/jdraw/jdraw.py b/lib/taurus/qt/qtgui/graphic/jdraw/jdraw.py index 5f99ead1..d20944ab 100644 --- a/lib/taurus/qt/qtgui/graphic/jdraw/jdraw.py +++ b/lib/taurus/qt/qtgui/graphic/jdraw/jdraw.py @@ -425,5 +425,5 @@ class TaurusJDrawGraphicsFactory(Singleton, TaurusBaseGraphicsFactory, Logger): return if __name__ == "__main__": - from . import jdraw_view + from taurus.qt.qtgui.graphic.jdraw import jdraw_view jdraw_view.jdraw_view_main() diff --git a/lib/taurus/qt/qtgui/graphic/jdraw/jdraw_view.py b/lib/taurus/qt/qtgui/graphic/jdraw/jdraw_view.py index f8dcd4c8..0e476a58 100644 --- a/lib/taurus/qt/qtgui/graphic/jdraw/jdraw_view.py +++ b/lib/taurus/qt/qtgui/graphic/jdraw/jdraw_view.py @@ -41,8 +41,7 @@ from taurus.qt.qtgui.graphic.taurusgraphic import parseTangoUri, TaurusGraphicsI from taurus.qt.qtcore.mimetypes import TAURUS_ATTR_MIME_TYPE, TAURUS_DEV_MIME_TYPE, TAURUS_MODEL_MIME_TYPE from taurus.qt.qtgui.base import TaurusBaseWidget -from . import jdraw_parser - +from taurus.qt.qtgui.graphic.jdraw.jdraw_parser import parse __all__ = ["TaurusJDrawSynopticsView"] @@ -389,7 +388,7 @@ class TaurusJDrawSynopticsView(Qt.QGraphicsView, TaurusBaseWidget): self.debug("Starting to parse %s" % filename) self.path = os.path.dirname(filename) factory = self.getGraphicsFactory(delayed=delayed) - scene = jdraw_parser.parse(filename, factory) + scene = parse(filename, factory) scene.setSelectionStyle(self._selectionStyle) self.debug("Obtained %s(%s)", type(scene).__name__, filename) if not scene: @@ -477,7 +476,7 @@ def jdraw_view_main(): taurus.setLogLevel(taurus.Info) from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) #form = Qt.QDialog() # ly=Qt.QVBoxLayout(form) diff --git a/lib/taurus/qt/qtgui/graphic/taurusgraphic.py b/lib/taurus/qt/qtgui/graphic/taurusgraphic.py index eb242535..e27fa7b1 100755..100644 --- a/lib/taurus/qt/qtgui/graphic/taurusgraphic.py +++ b/lib/taurus/qt/qtgui/graphic/taurusgraphic.py @@ -51,7 +51,7 @@ from taurus.core.util.log import Logger, deprecation_decorator from taurus.core.taurusdevice import TaurusDevice from taurus.core.taurusattribute import TaurusAttribute from taurus.core.util.enumeration import Enumeration -from taurus.external.qt import Qt +from taurus.external.qt import Qt, compat from taurus.qt.qtgui.base import TaurusBaseComponent from taurus.qt.qtgui.util import (QT_ATTRIBUTE_QUALITY_PALETTE, QT_DEVICE_STATE_PALETTE, ExternalAppAction, TaurusWidgetFactory) @@ -110,7 +110,7 @@ def parseTangoUri(name): class QEmitter(Qt.QObject): - updateView = Qt.pyqtSignal(object) + updateView = Qt.pyqtSignal(compat.PY_OBJECT) class TaurusGraphicsUpdateThread(Qt.QThread): @@ -867,12 +867,21 @@ class QGraphicsTextBoxing(Qt.QGraphicsItemGroup): _TEXT_RATIO = 0.8 def __init__(self, parent=None, scene=None): - Qt.QGraphicsItemGroup.__init__(self, parent, scene) - self._rect = Qt.QGraphicsRectItem(self, scene) + Qt.QGraphicsItemGroup.__init__(self, parent) + if scene is not None: + scene.addItem(self) + self._rect = Qt.QGraphicsRectItem(self) + if scene is not None: + scene.addItem(self._rect) self._rect.setBrush(Qt.QBrush(Qt.Qt.NoBrush)) self._rect.setPen(Qt.QPen(Qt.Qt.NoPen)) - self._text = Qt.QGraphicsTextItem(self, scene) - self._text.scale(self._TEXT_RATIO, self._TEXT_RATIO) + self._text = Qt.QGraphicsTextItem(self) + if scene is not None: + scene.addItem(self._text) + self._text.setTransform( + Qt.QTransform.fromScale(self._TEXT_RATIO, self._TEXT_RATIO), + True) + self._validBackground = None # using that like the previous code create a worst result self.__layoutValide = True @@ -1163,8 +1172,9 @@ class TaurusGraphicsAttributeItem(TaurusGraphicsItem): _frName = None else: _frName = 'rvalue.magnitude' - text = self._currText = self.getDisplayValue(fragmentName=_frName) - self._currText = text.decode('unicode-escape') + text = self.getDisplayValue(fragmentName=_frName) + + self._currText = text self._currHtmlText = None TaurusGraphicsItem.updateStyle(self) diff --git a/lib/taurus/qt/qtgui/icon/catalog.py b/lib/taurus/qt/qtgui/icon/catalog.py index 58cb7293..1e101691 100644 --- a/lib/taurus/qt/qtgui/icon/catalog.py +++ b/lib/taurus/qt/qtgui/icon/catalog.py @@ -30,6 +30,7 @@ from __future__ import print_function from builtins import str import os +import click import hashlib from taurus.qt.qtgui.application import TaurusApplication from taurus.qt.qtgui.input import GraphicalChoiceWidget @@ -38,7 +39,7 @@ from taurus.external.qt import Qt class QIconCatalogPage(GraphicalChoiceWidget): - """A widget that shows all icons available under a given searchPath preffix + """A widget that shows all icons available under a given searchPath prefix """ def __init__(self, prefix, iconSize=24, columns=10): @@ -139,6 +140,7 @@ class QIconCatalogPage(GraphicalChoiceWidget): dlg.setIconPixmap(getCachedPixmap(name, size=128)) dlg.exec_() + class QIconCatalog(Qt.QTabWidget): """ A widget that shows a tab for each registered search path prefix. @@ -166,11 +168,11 @@ class QIconCatalog(Qt.QTabWidget): progress.setValue(nprefix) -def main(): - """launcher of QIconCatalog""" +@click.command('icons') +def icons_cmd(): + """Show the Taurus icon catalog""" import sys - from taurus import Release - app = TaurusApplication(app_version=Release.version) + app = TaurusApplication(cmd_line_parser=None) w = QIconCatalog() w.setWindowTitle('Taurus Icon Catalog') w.show() @@ -178,4 +180,4 @@ def main(): if __name__ == "__main__": - main() + icons_cmd() diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_black_off.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_black_off.png Binary files differnew file mode 100644 index 00000000..1b7f04b0 --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_black_off.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_black_on.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_black_on.png Binary files differnew file mode 100644 index 00000000..1b7f04b0 --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_black_on.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_blue_off.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_blue_off.png Binary files differnew file mode 100644 index 00000000..ab5ae4e3 --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_blue_off.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_blue_on.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_blue_on.png Binary files differnew file mode 100644 index 00000000..ed0e0392 --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_blue_on.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_green_off.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_green_off.png Binary files differnew file mode 100644 index 00000000..a6d4ffac --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_green_off.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_green_on.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_green_on.png Binary files differnew file mode 100644 index 00000000..0e71615e --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_green_on.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_grenoble_off.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_grenoble_off.png Binary files differnew file mode 100644 index 00000000..5991ccd2 --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_grenoble_off.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_grenoble_on.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_grenoble_on.png Binary files differnew file mode 100644 index 00000000..61116762 --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_grenoble_on.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_magenta_off.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_magenta_off.png Binary files differnew file mode 100644 index 00000000..df2628ed --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_magenta_off.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_magenta_on.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_magenta_on.png Binary files differnew file mode 100644 index 00000000..f13784b7 --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_magenta_on.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_off.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_off.png Binary files differnew file mode 100644 index 00000000..1b7f04b0 --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_off.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_orange_off.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_orange_off.png Binary files differnew file mode 100644 index 00000000..e6ef7f64 --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_orange_off.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_orange_on.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_orange_on.png Binary files differnew file mode 100644 index 00000000..23839531 --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_orange_on.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_red_off.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_red_off.png Binary files differnew file mode 100644 index 00000000..33eecf62 --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_red_off.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_red_on.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_red_on.png Binary files differnew file mode 100644 index 00000000..8c444ae6 --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_red_on.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_white_off.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_white_off.png Binary files differnew file mode 100644 index 00000000..c702c33d --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_white_off.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_white_on.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_white_on.png Binary files differnew file mode 100644 index 00000000..efbc5d39 --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_white_on.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_yellow_off.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_yellow_off.png Binary files differnew file mode 100644 index 00000000..0d27b936 --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_yellow_off.png diff --git a/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_yellow_on.png b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_yellow_on.png Binary files differnew file mode 100644 index 00000000..92386b7f --- /dev/null +++ b/lib/taurus/qt/qtgui/icon/extra-icons/leds/images256icons/led_yellow_on.png diff --git a/lib/taurus/qt/qtgui/icon/icon.py b/lib/taurus/qt/qtgui/icon/icon.py index 0299849f..78c7ded4 100644 --- a/lib/taurus/qt/qtgui/icon/icon.py +++ b/lib/taurus/qt/qtgui/icon/icon.py @@ -327,7 +327,7 @@ def getDevStatePixmap(state, size=None): if __name__ == '__main__': from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) icons = [ # null because of non-existent path diff --git a/lib/taurus/qt/qtgui/input/choicedlg.py b/lib/taurus/qt/qtgui/input/choicedlg.py index b8f2cdfa..e32a235e 100644 --- a/lib/taurus/qt/qtgui/input/choicedlg.py +++ b/lib/taurus/qt/qtgui/input/choicedlg.py @@ -249,7 +249,7 @@ def testWidget(): import sys from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) w = GraphicalChoiceWidget(None, True) w.show() sys.exit(app.exec_()) @@ -260,7 +260,7 @@ def main(): from taurus.qt.qtgui.icon import getCachedPixmap from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) pixmaps = {} choices = [['TaurusForm', 'TaurusTrend'], ['TaurusPlot', 'Qub']] diff --git a/lib/taurus/qt/qtgui/input/qwheel.py b/lib/taurus/qt/qtgui/input/qwheel.py index 7965ea31..8b3ac6f0 100755..100644 --- a/lib/taurus/qt/qtgui/input/qwheel.py +++ b/lib/taurus/qt/qtgui/input/qwheel.py @@ -212,7 +212,9 @@ class QWheelEdit(Qt.QFrame): self._maxValue = numpy.finfo('d').max # inf self._editor = None self._editing = False + self._hideEditWidget = True self._showArrowButtons = True + self._forwardReturn = False self._setDigits(QWheelEdit.DefaultIntDigitCount, QWheelEdit.DefaultDecDigitCount) self._setValue(0) @@ -321,7 +323,7 @@ class QWheelEdit(Qt.QFrame): ed = _NumericEditor(self) ed.returnPressed.connect(self.editingFinished) - ed.editingFinished.connect(ed.hide) + ed.editingFinished.connect(self.hideEditWidget) rect = Qt.QRect(l.cellRect(1, 0).topLeft(), l.cellRect(1, l.columnCount() - 1).bottomRight()) ed.setGeometry(rect) @@ -504,7 +506,12 @@ class QWheelEdit(Qt.QFrame): return self._previous_value = self._value self._value = v - self._buildValueStr(v) + + str_value = self._buildValueStr(v) + ed = self.getEditWidget() + if ed is not None: + ed.setText(str_value) + def setWarning(self, msg): """setWarning(self, msg) -> None @@ -534,8 +541,11 @@ class QWheelEdit(Qt.QFrame): @param[in] b (_ArrowButton) the button which was pressed """ - self._setValue(self.getValue() + b._inc) - self._updateValue() + if self._editing: + self.hideEditWidget() + else: + self._setValue(self.getValue() + b._inc) + self._updateValue() def setDigitCount(self, int_nb, dec_nb): """setDigitCount(self, int_nb, dec_nb) -> None @@ -770,6 +780,7 @@ class QWheelEdit(Qt.QFrame): ed.selectAll() ed.setFocus() ed.setVisible(True) + self._editing = True def hideEditWidget(self): """hideEditWidget(self) -> None @@ -778,6 +789,7 @@ class QWheelEdit(Qt.QFrame): """ ed = self.getEditWidget() ed.setVisible(False) + self._editing = False self.setFocus() def wheelEvent(self, evt): @@ -803,7 +815,6 @@ class QWheelEdit(Qt.QFrame): widget when this happens """ self.showEditWidget() - self._editing = True def keyPressEvent(self, key_event): """keyPressEvent(self, key_event) -> None @@ -815,20 +826,16 @@ class QWheelEdit(Qt.QFrame): if k == Qt.Qt.Key_F2: if self._editing: self.hideEditWidget() - self._editing = False else: self.showEditWidget() - self._editing = True return elif k == Qt.Qt.Key_Escape: if self._editing: self.hideEditWidget() - self._editing = False return elif k in (Qt.Qt.Key_Return, Qt.Qt.Key_Enter): if self._editing: self.hideEditWidget() - self._editing = False else: self.returnPressed.emit() @@ -845,6 +852,63 @@ class QWheelEdit(Qt.QFrame): def resetShowArrowButtons(self): self.setShowArrowButtons(True) + def getHideEditWidget(self): + """getHideEditWidget(self) -> bool + + Gets the info if edition widget should be hidden when 'focusOut' event + occurs. + + @return (bool) + """ + return self._hideEditWidget + + def setHideEditWidget(self, focus_out=True): + """setFocusOut(self, focus_out=True) -> None + + Sets if edition widget should be hidden when 'focusOut' event occurs. + If set to False, edition widget is hidden only when 'F2', 'Esc', + 'Enter' and arrow button are pressed. Default set to True. + + @param[in] focus_out (bool) whether or not to hide edition widget + after 'focusOut' event. + """ + if focus_out and not self._hideEditWidget: + ed = self.getEditWidget() + ed.editingFinished.connect(self.hideEditWidget) + self._hideEditWidget = True + elif not focus_out and self._hideEditWidget: + ed = self.getEditWidget() + ed.editingFinished.disconnect(self.hideEditWidget) + self._hideEditWidget = False + + def isReturnForwarded(self): + """isReturnForwarded(self) -> bool + + Gets the info if returnPressed is forwarded. + + @return (bool) + """ + return self._forwardReturn + + def setReturnForwarded(self, forward_rtn=False): + """setReturnForwarded(self, forward_rtn=False) -> None + + Sets forwarding of returnPressed. If set to True, returnPressed from + edition widget emits returnPressed of 'QWheelEdit' widget. + + @param[in] forward_rtn (bool) whether or not to forward returnPressed + signal + """ + if forward_rtn and not self._forwardReturn: + ed = self.getEditWidget() + ed.returnPressed.connect(self.returnPressed) + self._forwardReturn = True + + elif not forward_rtn and self._forwardReturn: + ed = self.getEditWidget() + ed.returnPressed.disconnect(self.returnPressed) + self._forwardReturn = False + #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- # QT properties #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- @@ -893,6 +957,7 @@ def main(): def setNone(): arrowWidget.setValue(None) + a = Qt.QApplication([]) panel = Qt.QWidget() l = Qt.QFormLayout(panel) @@ -904,6 +969,8 @@ def main(): resetbutton.setDefault(True) nanbutton = Qt.QPushButton("Set NAN", panel) nonebutton = Qt.QPushButton("Set None", panel) + hideEditCB = Qt.QCheckBox() + hideEditCB.setChecked(True) showarrowbutton = Qt.QCheckBox("", panel) l.addRow("Value", arrowWidget) @@ -912,6 +979,7 @@ def main(): l.addRow("Minimum value:", minv) l.addRow("Maximum value:", maxv) l.addRow("Show arrows:", showarrowbutton) + l.addRow("hideEditCB", hideEditCB) l.addRow(button_layout) button_layout.addWidget(nanbutton) button_layout.addWidget(nonebutton) @@ -929,6 +997,7 @@ def main(): showarrowbutton.stateChanged.connect(arrowWidget.setShowArrowButtons) nanbutton.clicked.connect(setNAN) nonebutton.clicked.connect(setNone) + hideEditCB.toggled.connect(arrowWidget.setHideEditWidget) resetbutton.clicked.connect(resetAll) panel.setVisible(True) a.exec_() diff --git a/lib/taurus/qt/qtgui/input/tauruscombobox.py b/lib/taurus/qt/qtgui/input/tauruscombobox.py index d7ec3602..7b21557f 100644 --- a/lib/taurus/qt/qtgui/input/tauruscombobox.py +++ b/lib/taurus/qt/qtgui/input/tauruscombobox.py @@ -366,7 +366,7 @@ class TaurusAttrListComboBox(Qt.QComboBox, TaurusBaseWidget): def _taurusAttrListTest(): """tests taurusAttrList. Model: an attribute containing a list of strings""" from taurus.qt.qtgui.application import TaurusApplication - a = TaurusApplication() + a = TaurusApplication(cmd_line_parser=None) # model = sys.argv[1] # model = "eval:['foo','bar']" model = "sys/tg_test/1/string_spectrum" @@ -387,7 +387,7 @@ def _taurusValueComboboxTest(): ('name2', 2), ('name3', 3) ] - a = TaurusApplication() + a = TaurusApplication(cmd_line_parser=None) w = Qt.QWidget() w.setLayout(Qt.QVBoxLayout()) diff --git a/lib/taurus/qt/qtgui/input/tauruslineedit.py b/lib/taurus/qt/qtgui/input/tauruslineedit.py index 135460ae..4abeaf75 100755..100644 --- a/lib/taurus/qt/qtgui/input/tauruslineedit.py +++ b/lib/taurus/qt/qtgui/input/tauruslineedit.py @@ -89,7 +89,7 @@ class TaurusValueLineEdit(Qt.QLineEdit, TaurusBaseWritableWidget): def _updateValidator(self, value): """This method sets a validator depending on the data type""" val = None - if isinstance(value.wvalue, Quantity): + if value is not None and isinstance(value.wvalue, Quantity): val = self.validator() if not isinstance(val, PintValidator): val = PintValidator(self) diff --git a/lib/taurus/qt/qtgui/input/taurusspinbox.py b/lib/taurus/qt/qtgui/input/taurusspinbox.py index e7edf2cc..53d53b00 100644 --- a/lib/taurus/qt/qtgui/input/taurusspinbox.py +++ b/lib/taurus/qt/qtgui/input/taurusspinbox.py @@ -291,7 +291,7 @@ if __name__ == "__main__": main() # import sys # from taurus.qt.qtgui.application import TaurusApplication -# app = TaurusApplication() +# app = TaurusApplication(cmd_line_parser=None) # w = TaurusValueSpinBox() # w.setModel('sys/tg_test/1/double_scalar') diff --git a/lib/taurus/qt/qtgui/model/qbasemodel.py b/lib/taurus/qt/qtgui/model/qbasemodel.py index a43db539..99827359 100644 --- a/lib/taurus/qt/qtgui/model/qbasemodel.py +++ b/lib/taurus/qt/qtgui/model/qbasemodel.py @@ -32,7 +32,7 @@ __all__ = ["QBaseModelWidget", "TaurusBaseModelWidget", __docformat__ = 'restructuredtext' -from taurus.external.qt import Qt +from taurus.external.qt import Qt, compat from taurus.qt.qtgui.util import ActionFactory from taurus.qt.qtgui.base import TaurusBaseWidget @@ -221,7 +221,7 @@ class RefreshToolBar(BaseToolBar): class PerspectiveToolBar(BaseToolBar): - perspectiveChanged = Qt.pyqtSignal(str) + perspectiveChanged = Qt.pyqtSignal(compat.PY_OBJECT) def __init__(self, perspective, view=None, parent=None, designMode=False): BaseToolBar.__init__(self, name="Taurus refresh toolbar", view=view, @@ -275,10 +275,10 @@ class QBaseModelWidget(Qt.QMainWindow): KnownPerspectives = {} DftPerspective = None - itemClicked = Qt.pyqtSignal(object, int) - itemDoubleClicked = Qt.pyqtSignal(object, int) + itemClicked = Qt.pyqtSignal(compat.PY_OBJECT, int) + itemDoubleClicked = Qt.pyqtSignal(compat.PY_OBJECT, int) itemSelectionChanged = Qt.pyqtSignal() - currentItemChanged = Qt.pyqtSignal(object, object) + currentItemChanged = Qt.pyqtSignal(compat.PY_OBJECT, compat.PY_OBJECT) def __init__(self, parent=None, designMode=False, with_filter_widget=True, with_selection_widget=True, with_refresh_widget=True, diff --git a/lib/taurus/qt/qtgui/panel/qdataexportdialog.py b/lib/taurus/qt/qtgui/panel/qdataexportdialog.py index bdd5db54..5977be27 100755..100644 --- a/lib/taurus/qt/qtgui/panel/qdataexportdialog.py +++ b/lib/taurus/qt/qtgui/panel/qdataexportdialog.py @@ -28,6 +28,8 @@ one or more curves""" from __future__ import print_function +from future.utils import string_types + import os.path from datetime import datetime @@ -112,7 +114,7 @@ class QDataExportDialog(Qt.QDialog): if not ofile: return False try: - if not isinstance(ofile, file): + if isinstance(ofile, string_types): ofile = open(str(ofile), "w") if self.dataSetCB.currentText() == self.allInMultipleFiles: # 1 file per curve @@ -257,7 +259,7 @@ if __name__ == "__main__": import sys from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) form = QDataExportDialog() form.show() sys.exit(app.exec_()) diff --git a/lib/taurus/qt/qtgui/panel/qdoublelist.py b/lib/taurus/qt/qtgui/panel/qdoublelist.py index 5d7b69a5..51062cd2 100644 --- a/lib/taurus/qt/qtgui/panel/qdoublelist.py +++ b/lib/taurus/qt/qtgui/panel/qdoublelist.py @@ -132,7 +132,7 @@ class QDoubleListDlg(Qt.QDialog): def main(): from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) dlg = QDoubleListDlg(winTitle='foo', mainLabel='bla, bla', label1='1', label2='2', list1=['11', '22'], list2=['123', '33']) diff --git a/lib/taurus/qt/qtgui/panel/qrawdatachooser.py b/lib/taurus/qt/qtgui/panel/qrawdatachooser.py index 90fe1fb5..651e374e 100644 --- a/lib/taurus/qt/qtgui/panel/qrawdatachooser.py +++ b/lib/taurus/qt/qtgui/panel/qrawdatachooser.py @@ -85,7 +85,7 @@ if __name__ == "__main__": import sys from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) form = QRawDataWidget() form.show() sys.exit(app.exec_()) diff --git a/lib/taurus/qt/qtgui/panel/taurusconfigeditor.py b/lib/taurus/qt/qtgui/panel/taurusconfigeditor.py index 1f6b6660..d9362b61 100644 --- a/lib/taurus/qt/qtgui/panel/taurusconfigeditor.py +++ b/lib/taurus/qt/qtgui/panel/taurusconfigeditor.py @@ -33,10 +33,11 @@ standard_library.install_aliases() from taurus.external.qt import Qt, compat import pickle import os +import shutil import tempfile +import click from taurus.qt.qtcore.configuration import BaseConfigurableClass from taurus.qt.qtgui.container import TaurusWidget -import shutil __all__ = ["QConfigEditor"] @@ -80,10 +81,8 @@ class QConfigEditorModel(Qt.QStandardItemModel): :param iniFileName: (str) ''' - self.originalFile = str(iniFileName) - self._file = tempfile.NamedTemporaryFile() - self._temporaryFile = str(self._file.name) - + self.originalFile = iniFileName + self._temporaryFile = tempfile.NamedTemporaryFile(delete=False).name shutil.copyfile(self.originalFile, self._temporaryFile) self._settings = Qt.QSettings( @@ -346,7 +345,7 @@ class QConfigEditorModel(Qt.QStandardItemModel): ''' result = None qstate = self._settings.value(key) - if qstate is not None and not qstate.isNull(): + if qstate is not None: try: result = pickle.loads(qstate.data()) except Exception as e: @@ -366,6 +365,8 @@ class QConfigEditorModel(Qt.QStandardItemModel): ''' if self.markedItems == []: return + self._settings.sync() + shutil.copyfile(self._temporaryFile, self.originalFile) self.clearChanges() # self.reloadFile() @@ -395,7 +396,7 @@ class QConfigEditorModel(Qt.QStandardItemModel): ''' if self.markedItems == []: return - shutil.copyfile(self.originalFile, self._temporaryFile) + self.reloadFile() def clearChanges(self): @@ -493,26 +494,23 @@ class QConfigEditor(TaurusWidget): self.tree.restoreOriginal() -def main(): +@click.command('config') +@click.argument('config_file', type=click.Path(exists=True), required=False) +def config_cmd(config_file): + """Open the taurus configuration editor""" from taurus.qt.qtgui.application import TaurusApplication - from taurus.core.util import argparse - from taurus import Release import sys - parser = argparse.get_taurus_parser() - parser.set_usage("%prog [options] [INIFILENAME]") - parser.set_description("taurus configuration editor") - app = TaurusApplication(cmd_line_parser=parser, - app_name="taurusconfigeditor", - app_version=Release.version) - args = app.get_command_line_args() + app = TaurusApplication(cmd_line_parser=None) + w = QConfigEditor() w.setMinimumSize(500, 500) w.show() - if len(args) == 1: - w.loadFile(args[0]) + if config_file: + w.loadFile(config_file) sys.exit(app.exec_()) + if __name__ == '__main__': - main() + config_cmd() diff --git a/lib/taurus/qt/qtgui/panel/taurusconfigurationpanel.py b/lib/taurus/qt/qtgui/panel/taurusconfigurationpanel.py index 06c8226b..06c8226b 100755..100644 --- a/lib/taurus/qt/qtgui/panel/taurusconfigurationpanel.py +++ b/lib/taurus/qt/qtgui/panel/taurusconfigurationpanel.py diff --git a/lib/taurus/qt/qtgui/panel/taurusdemo.py b/lib/taurus/qt/qtgui/panel/taurusdemo.py index 405a76a6..b826077e 100644 --- a/lib/taurus/qt/qtgui/panel/taurusdemo.py +++ b/lib/taurus/qt/qtgui/panel/taurusdemo.py @@ -25,6 +25,7 @@ from __future__ import print_function import sys +import click import taurus.core.util import taurus.qt.qtgui.util @@ -122,17 +123,13 @@ class TaurusDemoPanel(Qt.QWidget): d.showMessage(str(e)) -def main(): - import taurus.core.util.argparse - parser = taurus.core.util.argparse.get_taurus_parser() - parser.set_description("A demo application for taurus") - app = taurus.qt.qtgui.application.TaurusApplication(cmd_line_parser=parser, - app_name="taurusdemo", - app_version="1.0", - org_domain="Taurus", - org_name="Tango community") +@click.command('demo') +def demo_cmd(): + """A demo application for taurus""" + from taurus.qt.qtgui.application import TaurusApplication + app = TaurusApplication(cmd_line_parser=None) gui = TaurusDemoPanel() - gui.setWindowTitle(app.applicationName()) + gui.setWindowTitle('Taurus demo') gui.show() sys.exit(app.exec_()) diff --git a/lib/taurus/qt/qtgui/panel/taurusdevicepanel.py b/lib/taurus/qt/qtgui/panel/taurusdevicepanel.py index 63dd4926..8fb0763e 100644 --- a/lib/taurus/qt/qtgui/panel/taurusdevicepanel.py +++ b/lib/taurus/qt/qtgui/panel/taurusdevicepanel.py @@ -28,10 +28,10 @@ TaurusDevicePanel.py: """ from builtins import str -from future.utils import string_types import re import traceback +import click from future.utils import string_types @@ -42,7 +42,8 @@ from taurus import tauruscustomsettings from taurus.core.taurusbasetypes import TaurusDevState, TaurusElementType from taurus.core.taurusattribute import TaurusAttribute from taurus.core.taurusdevice import TaurusDevice -from taurus.qt.qtgui.container import TaurusWidget, TaurusMainWindow +from taurus.qt.qtgui.container import TaurusWidget +from taurus.qt.qtgui.taurusgui import TaurusGui from taurus.qt.qtgui.display import TaurusLabel from taurus.qt.qtgui.panel.taurusform import TaurusForm from taurus.qt.qtgui.panel.taurusform import TaurusCommandsForm @@ -276,10 +277,8 @@ class TaurusDevicePanel(TaurusWidget): self.setModel(model) def loadConfigFile(self, ifile=None): - self.info('In TaurusDevicePanel.loadConfigFile(%s)' % ifile) - if isinstance(ifile, file) or isinstance(ifile, string_types) and not ifile.endswith('.py'): - TaurusWidget.loadConfigFile(self, ifile) - else: + self.debug('In TaurusDevicePanel.loadConfigFile(%s)' % ifile) + if isinstance(ifile, string_types) and ifile.endswith('.py'): from imp import load_source config_file = load_source('config_file', ifile) af, cf, im = [getattr(config_file, x, None) for x in ( @@ -290,6 +289,8 @@ class TaurusDevicePanel(TaurusWidget): self.setCommandFilters(cf) if im is not None: self.setIconMap(im) + else: + TaurusWidget.loadConfigFile(self, ifile) self.debug('AttributeFilters are:\n%s' % self.getAttributeFilters()) def duplicate(self): @@ -504,16 +505,17 @@ def filterNonExported(obj): @UILoadable(with_ui='_ui') -class TaurusDevPanel(TaurusMainWindow): - ''' +class TaurusDevPanel(TaurusGui): + """ TaurusDevPanel is a Taurus Application inspired in Jive and Atk Panel. It Provides a Device selector and several dockWidgets for interacting and displaying information from the selected device. - ''' + """ + HELP_MENU_ENABLED = False def __init__(self, parent=None, designMode=False): - TaurusMainWindow.__init__(self, parent, designMode=designMode) + TaurusGui.__init__(self, parent) self.loadUi() # setting up the device Tree. @@ -528,12 +530,6 @@ class TaurusDevPanel(TaurusMainWindow): # self.deviceTree.insertFilter(filterNonExported) self.setCentralWidget(self.deviceTree) - # needed because of a limitation in when using the useParentModel - # property from designer and taurus parents are not the same as Qt - # Parents - self._ui.taurusAttrForm.recheckTaurusParent() - self._ui.taurusCommandsForm.recheckTaurusParent() - # register subwidgets for configuration purposes # self.registerConfigDelegate(self.taurusAttrForm) # self.registerConfigDelegate(self.deviceTree) @@ -551,7 +547,7 @@ class TaurusDevPanel(TaurusMainWindow): self.splashScreen().finish(self) def createActions(self): - '''create actions ''' + """create actions""" # View Menu self.showAttrAction = self.viewMenu.addAction( self._ui.attrDW.toggleViewAction()) @@ -559,8 +555,8 @@ class TaurusDevPanel(TaurusMainWindow): self._ui.commandsDW.toggleViewAction()) def setTangoHost(self, host): - '''extended from :class:setTangoHost''' - TaurusMainWindow.setTangoHost(self, host) + """extended from :class:setTangoHost""" + TaurusGui.setTangoHost(self, host) self.deviceTree.setModel(host) # self.deviceTree.insertFilter(filterNonExported) @@ -586,28 +582,20 @@ class TaurusDevPanel(TaurusMainWindow): self.setDevice(devname) def setDevice(self, devname): - # try to connect with the device + """set the device to be shown by the commands and attr forms""" self.setModel(devname) - dev = self.getModelObj() - state = dev.state - # test the connection - if state == TaurusDevState.Ready: - msg = 'Connected to "%s"' % devname - self.statusBar().showMessage(msg) - self._ui.attrDW.setWindowTitle('Attributes - %s' % devname) - self._ui.commandsDW.setWindowTitle('Commands - %s' % devname) - else: - # reset the model if the connection failed - msg = 'Connection to "%s" failed (state = %s)' % (devname, - state.name) - self.statusBar().showMessage(msg) - self.info(msg) - Qt.QMessageBox.warning(self, "Device unreachable", msg) - self.setModel('') + self._ui.attrDW.setWindowTitle('Attributes - %s' % devname) + self._ui.commandsDW.setWindowTitle('Commands - %s' % devname) + + def setModel(self, name): + """Reimplemented to delegate model to the commands and attrs forms""" + TaurusGui.setModel(self, name) + self._ui.taurusAttrForm.setModel(name) + self._ui.taurusCommandsForm.setModel(name) @classmethod def getQtDesignerPluginInfo(cls): - ret = TaurusMainWindow.getQtDesignerPluginInfo() + ret = TaurusGui.getQtDesignerPluginInfo() ret['module'] = 'taurus.qt.qtgui.panel' return ret @@ -616,80 +604,89 @@ class TaurusDevPanel(TaurusMainWindow): #========================================================================= -def TaurusDevicePanelMain(): - '''A launcher for TaurusDevicePanel.''' +@click.command('device') +@click.argument('dev', nargs=1, default=None, required=False) +@click.option('-f', '--filter', + help=('regexp to filter for attributes to show ' + + '(it can be passed more than once)'), + multiple=True, + ) +@click.option('--config', 'config_file', type=click.File('rb'), + help='configuration file for initialization') +def device_cmd(dev, filter, config_file): + """Show a Device Panel""" import sys from taurus.qt.qtgui.application import TaurusApplication - from taurus.core.util import argparse - parser = argparse.get_taurus_parser() - parser.set_usage("%prog [options] [devname [attrs]]") - parser.set_description("Taurus Application inspired in Jive and Atk Panel") - parser.add_option("", "--config-file", dest="config_file", default=None, - help="load a config file (TODO: document this option)") - app = TaurusApplication(cmd_line_parser=parser, app_name="TaurusDevicePanel", - app_version=taurus.Release.version) - args = app.get_command_line_args() - options = app.get_command_line_options() + app = TaurusApplication(cmd_line_parser=None, app_name="TaurusDevicePanel") w = TaurusDevicePanel() w.show() - if len(args) == 0: + if dev is None: from taurus.qt.qtgui.panel import TaurusModelChooser - models, ok = TaurusModelChooser.modelChooserDlg(w, - selectables=[ - TaurusElementType.Member], - singleModel=True) - model = models[0] if ok and models else None - filters = '' - else: - model = args[0] - filters = args[1:] + models, ok = TaurusModelChooser.modelChooserDlg( + w, selectables=[TaurusElementType.Member], singleModel=True + ) + dev = models[0] if ok and models else None - if options.config_file is not None: - w.loadConfigFile(options.config_file) - elif model and filters: - w.setAttributeFilters({model: filters}) + if config_file is not None: + w.loadConfigFile(config_file) + elif dev and filter: + w.setAttributeFilters({dev: list(filter)}) - w.setModel(model) + w.setModel(dev) sys.exit(app.exec_()) -def TaurusPanelMain(): - '''A launcher for TaurusPanel.''' - # NOTE: DON'T PUT TEST CODE HERE. - # THIS IS CALLED FROM THE LAUNCHER SCRIPT (<taurus>/scripts/tauruspanel) +@click.command('panel') +@click.option('--tango-host', 'tango_host', + default=None, + help="Tango Host name (the system's default if not given)") +@click.option('-d', '--dev', default=None, + help='pre-selected device') +@click.option('-t', '--trend', is_flag=True, + help='Create a temporal trend widget') +def panel_cmd(tango_host, dev, trend): + """ + Show a TaurusPanel (a Taurus application inspired in Jive and Atk Panel) + """ from taurus.qt.qtgui.application import TaurusApplication - from taurus.core.util import argparse import sys - parser = argparse.get_taurus_parser() - parser.set_usage("%prog [options] [devname]") - parser.set_description("Taurus Application inspired in Jive and Atk Panel") - - app = TaurusApplication(cmd_line_parser=parser, app_name="tauruspanel", - app_version=taurus.Release.version) - args = app.get_command_line_args() - options = app.get_command_line_options() + app = TaurusApplication(cmd_line_parser=None, app_name="tauruspanel") w = TaurusDevPanel() - if options.tango_host is None: - options.tango_host = taurus.Authority().getNormalName() - w.setTangoHost(options.tango_host) + if tango_host is None: + from taurus import Factory + tango_host = Factory('tango').getAuthority().getFullName() + w.setTangoHost(tango_host) + + if dev is not None: + w.setDevice(dev) + + if trend is True: + # TODO: Allow to select TaurusTrend back-end + try: + from taurus.qt.qtgui.qwt5 import TaurusTrend + w.info('Using qwt5 back-end') + except: + try: + from taurus.qt.qtgui.tpg import TaurusTrend + w.info('Using tpg back-end') + except: + TaurusTrend = None + w.warning('TaurusTrend widget is not available') - if len(args) == 1: - w.setDevice(args[0]) + if TaurusTrend is not None: + plot = TaurusTrend() + w.createPanel(plot, 'TaurusTrend', permanent=False) w.show() sys.exit(app.exec_()) -############################################################################### - -if __name__ == "__main__": - TaurusDevicePanelMain() diff --git a/lib/taurus/qt/qtgui/panel/taurusform.py b/lib/taurus/qt/qtgui/panel/taurusform.py index 13572f4a..3fa02aaf 100644 --- a/lib/taurus/qt/qtgui/panel/taurusform.py +++ b/lib/taurus/qt/qtgui/panel/taurusform.py @@ -28,6 +28,7 @@ from __future__ import print_function from __future__ import absolute_import +import click from datetime import datetime from functools import partial @@ -865,21 +866,22 @@ class TaurusAttrForm(TaurusWidget): def _updateAttrWidgets(self): '''Populates the form with an item for each of the attributes shown ''' - dev = self.getModelObj() - if dev is None or dev.state != TaurusDevState.Ready: + try: + dev = self.getModelObj() + attrlist = sorted(dev.attribute_list_query(), key=self._sortKey) + for f in self.getViewFilters(): + attrlist = list(filter(f, attrlist)) + attrnames = [] + devname = self.getModelName() + for a in attrlist: + # ugly hack . But setUseParentModel does not work well + attrnames.append("%s/%s" % (devname, a.name)) + self.debug('Filling with attribute list: %s' + % ("; ".join(attrnames))) + self._form.setModel(attrnames) + except: self.debug('Cannot connect to device') self._form.setModel([]) - return - attrlist = sorted(dev.attribute_list_query(), key=self._sortKey) - for f in self.getViewFilters(): - attrlist = list(filter(f, attrlist)) - attrnames = [] - devname = self.getModelName() - for a in attrlist: - # ugly hack . But setUseParentModel does not work well - attrnames.append("%s/%s" % (devname, a.name)) - self.debug('Filling with attribute list: %s' % ("; ".join(attrnames))) - self._form.setModel(attrnames) def setViewFilters(self, filterlist): '''sets the filters to be applied when displaying the attributes @@ -948,7 +950,7 @@ def test1(): models = None from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) if models is None: models = ['sys/tg_test/1/state', 'sys/tg_test/1/float_scalar', @@ -980,7 +982,7 @@ def test2(): model = 'bl97/pc/dummy-01' from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) dialog = TaurusAttrForm() dialog.setModel(model) dialog.show() @@ -999,7 +1001,7 @@ def test3(): model = 'bl97/pc/dummy-01' from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) dialog = TaurusCommandsForm() dialog.setModel(model) dialog.show() @@ -1014,7 +1016,7 @@ def test4(): from taurus.qt.qtgui.display import TaurusLabel from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) from taurus.qt.qtgui.panel import TaurusValue @@ -1045,33 +1047,23 @@ def test4(): sys.exit(app.exec_()) -def taurusFormMain(): - '''A launcher for TaurusForm.''' - # NOTE: DON'T PUT TEST CODE HERE. - # THIS IS CALLED FROM THE LAUNCHER SCRIPT (<taurus>/scripts/taurusform) - # USE test1() instead. +@click.command('form') +@click.option('--window-name', 'window_name', + default='Taurus Form', + help='Name of the window') +@click.option('--config', 'config_file', type=click.File('rb'), + help='configuration file for initialization') +@click.argument('models', nargs=-1) +def form_cmd(window_name, config_file, models): + """Shows a Taurus form populated with the given model names""" from taurus.qt.qtgui.application import TaurusApplication - from taurus.core.util import argparse import sys - import os - - parser = argparse.get_taurus_parser() - parser.set_usage("%prog [options] [model1 [model2 ...]]") - parser.set_description("the taurus form panel application") - parser.add_option("--window-name", dest="window_name", - default="TaurusForm", help="Name of the window") - parser.add_option("--config", "--config-file", dest="config_file", default=None, - help="use the given config file for initialization") - app = TaurusApplication(cmd_line_parser=parser, - app_name="taurusform", - app_version=taurus.Release.version) - args = app.get_command_line_args() - options = app.get_command_line_options() - + app = TaurusApplication(cmd_line_parser=None) dialog = TaurusForm() dialog.setModifiableByUser(True) dialog.setModelInConfig(True) - dialog.setWindowTitle(options.window_name) + + dialog.setWindowTitle(window_name) # Make sure the window size and position are restored dialog.registerConfigProperty(dialog.saveGeometry, dialog.restoreGeometry, @@ -1099,16 +1091,14 @@ def taurusFormMain(): getattr(tauruscustomsettings, 'T_FORM_CUSTOM_WIDGET_MAP', {})) # set a model list from the command line or launch the chooser - if options.config_file is not None: - dialog.loadConfigFile(options.config_file) - elif len(args) > 0: - models = args + if config_file is not None: + dialog.loadConfigFile(config_file) + elif len(models) > 0: dialog.setModel(models) else: dialog.chooseModels() dialog.show() - sys.exit(app.exec_()) @@ -1117,7 +1107,7 @@ def main(): # test2() # test3() # test4() - taurusFormMain() + form_cmd() if __name__ == "__main__": main() diff --git a/lib/taurus/qt/qtgui/panel/taurusmodelchooser.py b/lib/taurus/qt/qtgui/panel/taurusmodelchooser.py index e505715e..552a168b 100644 --- a/lib/taurus/qt/qtgui/panel/taurusmodelchooser.py +++ b/lib/taurus/qt/qtgui/panel/taurusmodelchooser.py @@ -29,24 +29,124 @@ AttributeChooser.py: widget for choosing (a list of) attributes from a tango DB from __future__ import print_function from __future__ import absolute_import +from builtins import bytes, str + import sys -from taurus.external.qt import Qt +import pkg_resources + +import taurus +from taurus.external.qt import Qt, QtCore +from taurus.external.qt.compat import PY_OBJECT import taurus.core from taurus.qt.qtgui.container import TaurusWidget from taurus.qt.qtgui.tree import TaurusDbTreeWidget from taurus.core.util.containers import CaselessList from .taurusmodellist import TaurusModelList +__all__ = ["TaurusModelSelectorTree", "TaurusModelChooser", + "TaurusModelSelector", "TaurusModelSelectorItem"] + + +class TaurusModelSelector(Qt.QTabWidget): + """TaurusModelSelector is a QTabWidget container for + TaurusModelSelectorItem. + """ + # TODO add action to add new TaurusModelSelectorItem + # TODO add mechanism to allow manual plugin activation + # (instead of relying on installation) + modelsAdded = Qt.pyqtSignal(PY_OBJECT) + + def __init__(self, parent=None): + Qt.QTabWidget.__init__(self, parent=parent) + + self.currentChanged.connect(self.__setTabItemModel) + # --------------------------------------------------------------------- + # Note: this is an experimental feature + # It may be removed or changed in future releases + # Discover the taurus.modelselector plugins + ep_name = 'taurus.qt.qtgui.panel.TaurusModelSelector.items' + for ep in pkg_resources.iter_entry_points(ep_name): + try: + ms_class = ep.load() + ms_item = ms_class(parent=self) + self.__addItem(ms_item, ep.name) -__all__ = ["TaurusModelSelectorTree", "TaurusModelChooser"] - + except Exception as e: + err = 'Invalid TaurusModelSelectorItem plugin: {}\n{}'.format( + ep.module_name, e) + taurus.warning(err) + # --------------------------------------------------------------------- + + def __setTabItemModel(self): + w = self.currentWidget() + c = self.cursor() + try: + if not w.model: + self.setCursor(QtCore.Qt.WaitCursor) + w.setModel(w.default_model) + except Exception as e: + taurus.warning('Problem setting up selector: %r', e) + finally: + self.setCursor(c) + + def __addItem(self, widget, name, model=None): + if model is not None: + widget.default_model = model + + widget.modelsAdded.connect(self.modelsAdded) + self.addTab(widget, name) + + +class TaurusModelSelectorItem(TaurusWidget): + """Base class for ModelSelectorItem. + It defines the minimal API to be defined in the specialization + """ + modelsAdded = Qt.pyqtSignal(PY_OBJECT) + _dragEnabled = True + # TODO add action for setModel + + def __init__(self, parent=None, **kwargs): + TaurusWidget.__init__(self, parent) + self._default_model = None -class TaurusModelSelectorTree(TaurusWidget): + def getSelectedModels(self): + raise NotImplementedError(('getSelectedModels must be implemented' + + ' in TaurusModelSelectorItem subclass')) + + def getModelMimeData(self): + """ Reimplemented from TaurusBaseComponent + """ + models = self.getSelectedModels() + md = Qt.QMimeData() + md.setText(", ".join(models)) + models_bytes = [bytes(m, encoding='utf-8') for m in models] + md.setData(taurus.qt.qtcore.mimetypes.TAURUS_MODEL_LIST_MIME_TYPE, + b"\r\n".join(models_bytes)) + return md + + def _get_default_model(self): + """ + Reimplement to return a default model to initialize the widget + """ + raise NotImplementedError(('default_model must be implemented' + + ' in TaurusModelSelectorItem subclass')) + + def _set_default_model(self, model): + """ + Set default model to initialize the widget + """ + self._default_model = model + + # Reimplement this property + default_model = property(fget=_get_default_model, fset=_set_default_model) + + +class TaurusModelSelectorTree(TaurusModelSelectorItem): addModels = Qt.pyqtSignal('QStringList') def __init__(self, parent=None, selectables=None, buttonsPos=None, designMode=None): - TaurusWidget.__init__(self, parent) + TaurusModelSelectorItem.__init__(self, parent) if selectables is None: selectables = [taurus.core.taurusbasetypes.TaurusElementType.Attribute, taurus.core.taurusbasetypes.TaurusElementType.Member, taurus.core.taurusbasetypes.TaurusElementType.Device] @@ -138,6 +238,34 @@ class TaurusModelSelectorTree(TaurusWidget): return ret +class TangoModelSelectorItem(TaurusModelSelectorTree): + """A taurus model selector item for Tango models + """ + # TODO: Tango-centric (move to Taurus-Tango plugin) + def __init__(self, parent=None, selectables=None, + buttonsPos=Qt.Qt.RightToolBarArea, designMode=None): + TaurusModelSelectorTree.__init__( + self, parent=parent, selectables=selectables, + buttonsPos=buttonsPos, designMode=designMode) + + def onAddSelected(self): + """ + Reimplemented from TaurusModelSelectorTree to emit modelsAdded + signal instead of addModels + """ + self.modelsAdded.emit(self.getSelectedModels()) + + def _get_default_model(self): + """Reimplemented from TaurusModelSelectorItem""" + if self._default_model is None: + f = taurus.Factory('tango') + self._default_model = f.getAuthority().getFullName() + return self._default_model + + default_model = property(fget=_get_default_model, + fset=TaurusModelSelectorTree._set_default_model) + + class TaurusModelChooser(TaurusWidget): '''A widget that allows the user to select a list of models from a tree representing devices and attributes from a Tango server. diff --git a/lib/taurus/qt/qtgui/panel/taurusmodellist.py b/lib/taurus/qt/qtgui/panel/taurusmodellist.py index fef186b5..f9cf6b89 100644 --- a/lib/taurus/qt/qtgui/panel/taurusmodellist.py +++ b/lib/taurus/qt/qtgui/panel/taurusmodellist.py @@ -27,6 +27,7 @@ itemsmodel Model and view for new CurveItem configuration """ from builtins import object +from builtins import bytes #raise UnimplementedError('Under Construction!') import copy @@ -62,6 +63,16 @@ class TaurusModelItem(object): if display is not None: self.display = display + def __deepcopy__(self, memo): + cls = self.__class__ + result = cls.__new__(cls) + memo[id(self)] = result + result.icon = Qt.QIcon(self.icon) + result.ok = copy.deepcopy(self.ok, memo) + result._src = copy.deepcopy(self._src, memo) + result.display = copy.deepcopy(self.display, memo) + return result + def __repr__(self): ret = "TaurusModelItem('%s')" % (self.display) return ret @@ -236,11 +247,12 @@ class TaurusModelModel(Qt.QAbstractListModel): if row == -1 and parent.isValid(): row = parent.row() if data.hasFormat(TAURUS_ATTR_MIME_TYPE): - items = [str(data.data(TAURUS_ATTR_MIME_TYPE))] + items = [bytes(data.data(TAURUS_ATTR_MIME_TYPE)).decode("utf-8")] elif data.hasFormat(TAURUS_MODEL_MIME_TYPE): - items = [str(data.data(TAURUS_MODEL_MIME_TYPE))] + items = [bytes(data.data(TAURUS_MODEL_MIME_TYPE)).decode("utf-8")] elif data.hasFormat(TAURUS_MODEL_LIST_MIME_TYPE): - items = str(data.data(TAURUS_MODEL_LIST_MIME_TYPE)).split() + items = bytes( + data.data(TAURUS_MODEL_LIST_MIME_TYPE)).decode("utf-8").split() elif data.hasText(): items = [str(data.text())] else: @@ -442,7 +454,7 @@ class TaurusModelList(Qt.QListView): if __name__ == "__main__": from taurus.qt.qtgui.application import TaurusApplication import sys - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) w = TaurusModelList() w.addModels(["item%i" % i for i in range(3)] + [TaurusModelItem(src='src1', display='d1')] + [('src2', 'd2')]) diff --git a/lib/taurus/qt/qtgui/panel/taurusvalue.py b/lib/taurus/qt/qtgui/panel/taurusvalue.py index 81532828..2ef054ae 100644 --- a/lib/taurus/qt/qtgui/panel/taurusvalue.py +++ b/lib/taurus/qt/qtgui/panel/taurusvalue.py @@ -204,6 +204,15 @@ class CenteredLed(TaurusLed): DefaultAlignment = Qt.Qt.AlignHCenter | Qt.Qt.AlignVCenter +class UnitLessLineEdit(TaurusValueLineEdit): + """A customised TaurusValueLineEdit that always shows the magnitude""" + def setModel(self, model): + if model is None or model == '': + return TaurusValueLineEdit.setModel(self, None) + return TaurusValueLineEdit.setModel(self, model + "#wvalue.magnitude") + + + class DefaultUnitsWidget(TaurusLabel): FORMAT = "{}" @@ -380,7 +389,7 @@ class TaurusValue(Qt.QWidget, TaurusBaseWidget): itself. ''' if followCompact and self.isCompact(): - return self._readWidget.readWidget + return getattr(self._readWidget, 'readWidget', self._readWidget) return self._readWidget def writeWidget(self, followCompact=False): @@ -587,22 +596,24 @@ class TaurusValue(Qt.QWidget, TaurusBaseWidget): modelobj = self.getModelObj() if modelobj is None: if returnAll: - return [TaurusValueLineEdit] + return [UnitLessLineEdit] else: - return TaurusValueLineEdit + return UnitLessLineEdit modelType = modelobj.getType() if modelobj.data_format == DataFormat._0D: if modelType == DataType.Boolean: result = [DefaultTaurusValueCheckBox, TaurusValueLineEdit] else: - result = [TaurusValueLineEdit, + result = [UnitLessLineEdit, TaurusValueSpinBox, TaurusWheelEdit] elif modelobj.data_format == DataFormat._1D: + result = [TaurusValuesTableButton_W, TaurusValueLineEdit] if modelType in (DataType.Float, DataType.Integer): - result = [TaurusArrayEditorButton, - TaurusValuesTableButton_W, TaurusValueLineEdit] - else: - result = [TaurusValuesTableButton_W, TaurusValueLineEdit] + try: + import taurus.qt.qtgui.qwt5 + result.insert(0, TaurusArrayEditorButton) + except: + pass elif modelobj.data_format == DataFormat._2D: result = [TaurusValuesTableButton_W] else: @@ -1389,7 +1400,7 @@ if __name__ == "__main__": from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) form = Qt.QMainWindow() # ly=Qt.QVBoxLayout(form) # container=Qt.QWidget() diff --git a/lib/taurus/qt/qtgui/panel/test/test_taurusvalue.py b/lib/taurus/qt/qtgui/panel/test/test_taurusvalue.py index 7ec66e6e..d973560e 100644 --- a/lib/taurus/qt/qtgui/panel/test/test_taurusvalue.py +++ b/lib/taurus/qt/qtgui/panel/test/test_taurusvalue.py @@ -36,9 +36,7 @@ DEV_NAME = TangoSchemeTestLauncher.DEV_NAME @insertTest(helper_name="texts", model="tango:" + DEV_NAME + "/double_scalar", - expected=("double_scalar", "1.23", "0.00 mm", "mm"), - # expected=("double_scalar", "1.23", "0.0", "mm"), - # TODO: change taurusvalue's line edit to hide units + expected=("double_scalar", "1.23", "0.00", "mm") ) class TaurusValueTest(TangoSchemeTestLauncher, BaseWidgetTestCase, unittest.TestCase): diff --git a/lib/taurus/qt/qtgui/panel/ui/TaurusDevPanel.ui b/lib/taurus/qt/qtgui/panel/ui/TaurusDevPanel.ui index a155f1ba..22b7a03b 100644 --- a/lib/taurus/qt/qtgui/panel/ui/TaurusDevPanel.ui +++ b/lib/taurus/qt/qtgui/panel/ui/TaurusDevPanel.ui @@ -32,7 +32,7 @@ <item> <widget class="TaurusAttrForm" name="taurusAttrForm" native="true"> <property name="useParentModel" stdset="0"> - <bool>true</bool> + <bool>false</bool> </property> </widget> </item> @@ -54,7 +54,7 @@ <item> <widget class="TaurusCommandsForm" name="taurusCommandsForm" native="true"> <property name="useParentModel" stdset="0"> - <bool>true</bool> + <bool>false</bool> </property> </widget> </item> diff --git a/lib/taurus/qt/qtgui/plot/__init__.py b/lib/taurus/qt/qtgui/plot/__init__.py index 1d4326cb..1d4326cb 100755..100644 --- a/lib/taurus/qt/qtgui/plot/__init__.py +++ b/lib/taurus/qt/qtgui/plot/__init__.py diff --git a/lib/taurus/qt/qtgui/qwt5/arrayedit.py b/lib/taurus/qt/qtgui/qwt5/arrayedit.py index f3c36dfc..58069d12 100644 --- a/lib/taurus/qt/qtgui/qwt5/arrayedit.py +++ b/lib/taurus/qt/qtgui/qwt5/arrayedit.py @@ -537,7 +537,7 @@ if __name__ == "__main__": import sys from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) form = ArrayEditor() #x = numpy.arange(100)-20 #y = -(x-50)**2+50**2 diff --git a/lib/taurus/qt/qtgui/qwt5/cli.py b/lib/taurus/qt/qtgui/qwt5/cli.py new file mode 100644 index 00000000..6f1818ad --- /dev/null +++ b/lib/taurus/qt/qtgui/qwt5/cli.py @@ -0,0 +1,103 @@ +############################################################################# +## +# This file is part of Taurus +## +# http://taurus-scada.org +## +# Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain +## +# Taurus is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +## +# Taurus 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 Lesser General Public License for more details. +## +# You should have received a copy of the GNU Lesser General Public License +# along with Taurus. If not, see <http://www.gnu.org/licenses/>. +## +############################################################################# + +import click +from .taurustrend import TaurusTrend + + +@click.group('qwt5') +def qwt5(): + """Qwt5 related commands""" + pass + + +@qwt5.command('plot') +@click.argument('models', nargs=-1) +@click.option('--config', 'config_file', type=click.File('rb'), + help='configuration file for initialization') +@click.option("-x", "--x-axis-mode", "x_axis_mode", + type=click.Choice(['t', 'n']), + default='n', + show_default=True, + help=('X axis mode. "t" implies using a Date axis' + + '"n" uses the regular axis') + ) +@click.option("--demo", is_flag=True, help="show a demo of the widget") +@click.option('--window-name', 'window_name', + default='TaurusPlot (qwt5)', + help='Name of the window') +def plot_cmd(models, config_file, x_axis_mode, demo, window_name): + """Shows a plot for the given models""" + from .taurusplot import plot_main + return plot_main(models=models, + config_file=config_file, + x_axis_mode=x_axis_mode, + demo=demo, + window_name=window_name + ) + + +@qwt5.command('trend') +@click.argument('models', nargs=-1) +@click.option("-x", "--x-axis-mode", "x_axis_mode", + type=click.Choice(['t', 'n']), + default='n', + show_default=True, + help=('X axis mode. "t" implies using a Date axis' + + '"n" uses the regular axis') + ) +@click.option('-a', '--use-archiving', 'use_archiving', + is_flag=True, + default=False, + help='enable automatic archiving queries') +@click.option('-b', '--buffer', 'max_buffer_size', type=int, + default=TaurusTrend.DEFAULT_MAX_BUFFER_SIZE, + show_default=True, + help='maximum number of values per curve to be plotted') +@click.option('-r', '--forced-read', 'forced_read_period', type=int, + default=-1, + metavar="MILLISECONDS", + help="force re-reading of the attributes every MILLISECONDS ms") +@click.option('--config', 'config_file', type=click.File('rb'), + help='configuration file for initialization') +@click.option("--demo", is_flag=True, help="show a demo of the widget") +@click.option('--window-name', 'window_name', + default='TaurusPlot (qwt5)', + help='Name of the window') +def trend_cmd(models, x_axis_mode, use_archiving, max_buffer_size, + forced_read_period, config_file, demo, window_name): + """Shows a trend for the given models""" + from .taurustrend import trend_main + return trend_main(models=models, + config_file=config_file, + x_axis_mode=x_axis_mode, + use_archiving=use_archiving, + max_buffer_size=max_buffer_size, + forced_read_period=forced_read_period, + demo=demo, + window_name=window_name + ) + + +if __name__ == '__main__': + qwt5() diff --git a/lib/taurus/qt/qtgui/qwt5/curveprops.py b/lib/taurus/qt/qtgui/qwt5/curveprops.py index e5a4054f..a6dd35aa 100755..100644 --- a/lib/taurus/qt/qtgui/qwt5/curveprops.py +++ b/lib/taurus/qt/qtgui/qwt5/curveprops.py @@ -31,6 +31,7 @@ curveprops: Model and view for curve properties from __future__ import absolute_import from builtins import str +from builtins import bytes from builtins import object import copy @@ -294,11 +295,12 @@ class CurvesTableModel(Qt.QAbstractTableModel): else: column = parent.columnCount() if data.hasFormat(TAURUS_ATTR_MIME_TYPE): - self.setData(self.index(row, column), - value=str(data.data(TAURUS_ATTR_MIME_TYPE))) + model = bytes(data.data(TAURUS_ATTR_MIME_TYPE)).decode('utf-8') + self.setData(self.index(row, column), value=model) return True elif data.hasFormat(TAURUS_MODEL_LIST_MIME_TYPE): - models = str(data.data(TAURUS_MODEL_LIST_MIME_TYPE)).split() + d = bytes(data.data(TAURUS_MODEL_LIST_MIME_TYPE)) + models = d.decode('utf-8').split() if len(models) == 1: self.setData(self.index(row, column), value=models[0]) return True @@ -617,7 +619,7 @@ class CurvePropertiesView(Qt.QAbstractItemView): def main(): from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) curves = [CurveConf(xsrc='', ysrc='tango://host:1000/a/b/c/d', properties=None, title="tangocurve", vis=Qwt5.QwtPlot.yLeft), CurveConf(xsrc='=[1,2,3]', ysrc='=#2.x**2', diff --git a/lib/taurus/qt/qtgui/qwt5/curvesAppearanceChooserDlg.py b/lib/taurus/qt/qtgui/qwt5/curvesAppearanceChooserDlg.py index 724a058f..039d73e2 100644 --- a/lib/taurus/qt/qtgui/qwt5/curvesAppearanceChooserDlg.py +++ b/lib/taurus/qt/qtgui/qwt5/curvesAppearanceChooserDlg.py @@ -34,7 +34,7 @@ from __future__ import print_function from builtins import object import copy -from taurus.external.qt import Qt, Qwt5 +from taurus.external.qt import Qt, Qwt5, compat from taurus.core.util.containers import CaselessDict from taurus.qt.qtgui.util.ui import UILoadable @@ -106,7 +106,7 @@ class CurvesAppearanceChooser(Qt.QWidget): NAME_ROLE = Qt.Qt.UserRole controlChanged = Qt.pyqtSignal() - curveAppearanceChanged = Qt.pyqtSignal(object, list) + curveAppearanceChanged = Qt.pyqtSignal(compat.PY_OBJECT, list) CurveTitleEdited = Qt.pyqtSignal('QString', 'QString') def __init__(self, parent=None, curvePropDict={}, showButtons=False, autoApply=False, designMode=False): diff --git a/lib/taurus/qt/qtgui/qwt5/monitor.py b/lib/taurus/qt/qtgui/qwt5/monitor.py index deab6d7f..be6a8108 100644 --- a/lib/taurus/qt/qtgui/qwt5/monitor.py +++ b/lib/taurus/qt/qtgui/qwt5/monitor.py @@ -88,7 +88,7 @@ if __name__ == "__main__": import sys from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) args = sys.argv[1:] diff --git a/lib/taurus/qt/qtgui/qwt5/taurusplot.py b/lib/taurus/qt/qtgui/qwt5/taurusplot.py index 7680c93f..d562e634 100644 --- a/lib/taurus/qt/qtgui/qwt5/taurusplot.py +++ b/lib/taurus/qt/qtgui/qwt5/taurusplot.py @@ -52,7 +52,7 @@ from taurus.core.taurusbasetypes import DataFormat # TODO: Tango-centric from taurus.core.util.containers import LoopList, CaselessDict, CaselessList from taurus.core.util.safeeval import SafeEvaluator -from taurus.qt.qtcore.util.signal import baseSignal +from taurus.qt.qtcore.util import baseSignal from taurus.qt.qtcore.mimetypes import TAURUS_MODEL_LIST_MIME_TYPE, TAURUS_ATTR_MIME_TYPE from taurus.qt.qtgui.base import TaurusBaseComponent, TaurusBaseWidget from taurus.qt.qtgui.qwt5 import TaurusPlotConfigDialog, FancyScaleDraw,\ @@ -2513,8 +2513,8 @@ class TaurusPlot(Qwt5.QwtPlot, TaurusBaseWidget): ) if not ofile: return - if not isinstance(ofile, file): - ofile = open(ofile, 'w') + if isinstance(ofile, string_types): + ofile = open(ofile, 'wb') configdict = self.createConfig(curvenames=curvenames) self.info("Saving current settings in '%s'" % ofile.name) pickle.dump(configdict, ofile) @@ -2534,8 +2534,8 @@ class TaurusPlot(Qwt5.QwtPlot, TaurusBaseWidget): 'TaurusPlot Curve Properties File (*.pck)') if not ifile: return - if not isinstance(ifile, file): - ifile = open(ifile, 'r') + if isinstance(ifile, string_types): + ifile = open(ifile, 'rb') configdict = pickle.load(ifile) self.applyConfig(configdict) return ifile.name @@ -3709,79 +3709,37 @@ class TaurusPlot(Qwt5.QwtPlot, TaurusBaseWidget): "bool", isOptimizationEnabled, setOptimizationEnabled, resetOptimizationEnabled) -def main(): +def plot_main(models=(), config_file=None, x_axis_mode='n', demo=False, + window_name='TaurusPlot (qwt)'): import sys - import taurus.qt.qtgui.application - import taurus.core.util.argparse - - parser = taurus.core.util.argparse.get_taurus_parser() - parser.set_usage("%prog [options] [<model1> [<model2>] ...]") - parser.set_description("a taurus application for plotting 1D data sets") - parser.add_option("-x", "--x-axis-mode", dest="x_axis_mode", default='e', metavar="t|n", - help="interprete X values as either timestamps (t) or numbers (n). Accepted values: t|n (e is also accepted as a synonim of n)") - parser.add_option("--config", "--config-file", dest="config_file", default=None, - help="use the given config file for initialization") - parser.add_option("--import-ascii", dest="import_ascii", default=None, - help="import the given ascii file into the plot") - parser.add_option("--export", "--export-file", dest="export_file", default=None, - help="use the given file to as output instead of showing the plot") - parser.add_option("--window-name", dest="window_name", - default="TaurusPlot", help="Name of the window") - - app = taurus.qt.qtgui.application.TaurusApplication(cmd_line_parser=parser, - app_name="taurusplot", - app_version=taurus.Release.version) - args = app.get_command_line_args() - options = app.get_command_line_options() - if options.x_axis_mode.lower() not in ['t', 'e', 'n']: - parser.print_help(sys.stderr) - sys.exit(1) - - models = args + from taurus.qt.qtgui.application import TaurusApplication + + app = TaurusApplication(cmd_line_parser=None, app_name="taurusplot(qwt)") + w = TaurusPlot() - w.setWindowTitle(options.window_name) - w.setXIsTime(options.x_axis_mode.lower() == 't') - if options.config_file is not None: - w.loadConfig(options.config_file) + w.setWindowTitle(window_name) + + w.setXIsTime(x_axis_mode.lower() == 't') + + if demo: + models = list(models) + models.extend(['eval:rand(100)', 'eval:0.5*sqrt(arange(100))']) - if options.import_ascii is not None: - w.importAscii([options.import_ascii], xcol=0) + if config_file is not None: + w.loadConfigFile(config_file) if models: - w.setModel(models) - - if options.export_file is not None: - curves = dict.fromkeys(w.trendSets, 0) - - def exportIfAllCurves(curve, trend=w, counters=curves): - curve = str(curve) - print('*' * 10 + ' %s: Event received for %s ' % (datetime.now().isoformat(), curve) + '*' * 10) - if curve in counters: - counters[curve] += 1 - if all(counters.values()): - trend.exportPdf(options.export_file) - print('*' * 10 + ' %s: Exported to : %s ' % (datetime.now().isoformat(), options.export_file) + '*' * 10) - trend.close() - return - if not curves: - w.close() - else: - for ts in w.trendSets.values(): - ts.dataChanged.connect(exportIfAllCurves) - sys.exit(app.exec_()) # exit without showing the widget + w.setModel(list(models)) - # show the widget w.show() + # if no models are passed, show the data import dialog - if (len(models) == 0 - and options.config_file is None - and options.import_ascii is None - ): + if not models and config_file is None: w.showDataImportDlg() sys.exit(app.exec_()) if __name__ == "__main__": - main() + plot_main() diff --git a/lib/taurus/qt/qtgui/qwt5/taurusplotconf.py b/lib/taurus/qt/qtgui/qwt5/taurusplotconf.py index d6a8e509..cb15f5d1 100644 --- a/lib/taurus/qt/qtgui/qwt5/taurusplotconf.py +++ b/lib/taurus/qt/qtgui/qwt5/taurusplotconf.py @@ -209,7 +209,7 @@ class demo(Qt.QDialog): def main1(): from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) form = demo() form.show() sys.exit(app.exec_()) @@ -218,7 +218,7 @@ def main1(): def main2(): from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) curves = [curveprops.CurveConf(xsrc='', ysrc='tango://host:1000/a/b/c/d', properties=None, title="tangocurve", vis=Qwt5.QwtPlot.yLeft), curveprops.CurveConf( diff --git a/lib/taurus/qt/qtgui/qwt5/taurustrend.py b/lib/taurus/qt/qtgui/qwt5/taurustrend.py index df069d4d..26ab5d1d 100644 --- a/lib/taurus/qt/qtgui/qwt5/taurustrend.py +++ b/lib/taurus/qt/qtgui/qwt5/taurustrend.py @@ -1020,7 +1020,12 @@ class TaurusTrend(TaurusPlot): self._startingTime) # Set a range of 1 min else: self.setAxisScale(axis, 0, 10) # Set a range of 10 events - self.axisWidget(axis).scaleDivChanged.disconnect(self.rescheduleReplot) # disconnects the previous axis + w = self.axisWidget(axis) + try: + # disconnect the previous axis + w.scaleDivChanged.disconnect(self.rescheduleReplot) + except TypeError: + pass # ignore exception if signal was not previously connected # enable/disable the archiving action self._useArchivingAction.setEnabled(enable) # call the parent class method @@ -1869,8 +1874,8 @@ class TaurusTrend(TaurusPlot): def test(): import sys - import taurus.qt.qtgui.application - app = taurus.qt.qtgui.application.TaurusApplication() + from taurus.qt.qtgui.application import TaurusApplication + app = TaurusApplication(cmd_line_parser=None) w = Qt.QWidget() w.setLayout(Qt.QVBoxLayout()) s = Qt.QSplitter() @@ -1885,89 +1890,57 @@ def test(): sys.exit(app.exec_()) -def main(): +def trend_main(models=(), config_file=None, x_axis_mode='n', + use_archiving=False, + max_buffer_size=None, + forced_read_period=-1, + demo=False, + window_name='TaurusTrend (qwt5)'): import sys - import taurus.qt.qtgui.application - import taurus.core.util.argparse - - parser = taurus.core.util.argparse.get_taurus_parser() - parser.set_usage("%prog [options] [<model1> [<model2>] ...]") - parser.set_description("a taurus application for plotting trends") - parser.add_option("-x", "--x-axis-mode", dest="x_axis_mode", default='t', metavar="t|e", - help="interprete X values as either timestamps (t) or event numbers (e). Accepted values: t|e") - parser.add_option("-b", "--buffer", dest="max_buffer_size", default=TaurusTrend.DEFAULT_MAX_BUFFER_SIZE, - help="maximum number of values per curve to be plotted (default = %i) (when reached, the oldest values will be discarded)" % TaurusTrend.DEFAULT_MAX_BUFFER_SIZE) - parser.add_option("--config", "--config-file", dest="config_file", default=None, - help="use the given config file for initialization") - parser.add_option("--export", "--export-file", dest="export_file", default=None, - help="use the given file to as output instead of showing the plot") - parser.add_option("-r", "--forced-read", dest="forced_read_period", type="int", default=-1, metavar="MILLISECONDS", - help="force Taurustrend to re-read the attributes every MILLISECONDS ms") - parser.add_option("-a", "--use-archiving", - action="store_true", dest="use_archiving", default=False) - parser.add_option("--window-name", dest="window_name", - default="TaurusTrend", help="Name of the window") - - app = taurus.qt.qtgui.application.TaurusApplication(cmd_line_parser=parser, - app_name="taurustrend", - app_version=taurus.Release.version) - args = app.get_command_line_args() - options = app.get_command_line_options() - if options.x_axis_mode.lower() not in ['t', 'e']: - parser.print_help(sys.stderr) - sys.exit(1) - - models = args + from taurus.qt.qtgui.application import TaurusApplication + + app = TaurusApplication(cmd_line_parser=None, app_name="taurustrend(qwt5)") w = TaurusTrend() - w.setWindowTitle(options.window_name) + + w.setWindowTitle(window_name) + + # demo option + if demo: + models = list(models) + models.extend(['eval:rand()', 'eval:1+rand(2)']) # xistime option - w.setXIsTime(options.x_axis_mode.lower() == 't') + w.setXIsTime(x_axis_mode.lower() == 't') + # max buffer size option - w.setMaxDataBufferSize(int(options.max_buffer_size)) + if max_buffer_size is not None: + w.setMaxDataBufferSize(max_buffer_size) + # configuration file option - if options.config_file is not None: - w.loadConfig(options.config_file) + if config_file is not None: + w.loadConfig(config_file) + # set models if models: - w.setModel(models) - # export option - if options.export_file is not None: - curves = dict.fromkeys(w.trendSets, 0) - - def exportIfAllCurves(curve, trend=w, counters=curves): - curve = str(curve) - print('*' * 10 + ' %s: Event received for %s ' % (datetime.now().isoformat(), curve) + '*' * 10) - if curve in counters: - counters[curve] += 1 - if all(counters.values()): - trend.exportPdf(options.export_file) - print('*' * 10 + ' %s: Exported to : %s ' % (datetime.now().isoformat(), options.export_file) + '*' * 10) - trend.close() - return - if not curves: - w.close() - else: - for ts in w.trendSets.values(): - ts.dataChanged.connect(exportIfAllCurves) - sys.exit(app.exec_()) # exit without showing the widget + w.setModel(list(models)) # period option - if options.forced_read_period > 0: - w.setForcedReadingPeriod(options.forced_read_period) + if forced_read_period > 0: + w.setForcedReadingPeriod(forced_read_period) # archiving option - w.setUseArchiving(options.use_archiving) + w.setUseArchiving(use_archiving) # show the widget w.show() # if no models are passed, show the data import dialog - if len(models) == 0 and options.config_file is None: + if not models and config_file is None: w.showDataImportDlg() sys.exit(app.exec_()) + if __name__ == "__main__": - main() + trend_main() diff --git a/lib/taurus/qt/qtgui/resource/taurus_resource_utils.py b/lib/taurus/qt/qtgui/resource/taurus_resource_utils.py index b2fbee6a..d9fa73d0 100644 --- a/lib/taurus/qt/qtgui/resource/taurus_resource_utils.py +++ b/lib/taurus/qt/qtgui/resource/taurus_resource_utils.py @@ -166,7 +166,7 @@ if __name__ == '__main__': import sys from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) diff --git a/lib/taurus/qt/qtgui/table/qlogtable.py b/lib/taurus/qt/qtgui/table/qlogtable.py index 3c61cb8d..f0de1be3 100644 --- a/lib/taurus/qt/qtgui/table/qlogtable.py +++ b/lib/taurus/qt/qtgui/table/qlogtable.py @@ -36,6 +36,7 @@ import logging.handlers import datetime import threading import socket +import click import taurus from taurus.core.util.log import Logger @@ -597,5 +598,42 @@ def main(): app.exec_() w.stop_logging() + +@click.command('qlogmon') +@click.option('--port', 'port', type=int, + default=logging.handlers.DEFAULT_TCP_LOGGING_PORT, + show_default=True, + help='port where log server is running') +@click.option('--log-name', 'log_name', default=None, + help='filter specific log object') +@click.option('--log-level', 'log_level', + type=click.Choice(['critical', 'error', 'warning', 'info', + 'debug', 'trace']), + default='debug', show_default=True, + help='filter specific log level') +def qlogmon_cmd(port, log_name, log_level): + """Show the Taurus Remote Log Monitor""" + import taurus + host = socket.gethostname() + level = getattr(taurus, log_level.capitalize(), taurus.Trace) + + from taurus.qt.qtgui.application import TaurusApplication + app = TaurusApplication(cmd_line_parser=None, + app_name="Taurus remote logger") + w = QLoggingWidget(perspective="Remote") + w.setMinimumSize(1024, 600) + + filterbar = w.getFilterBar() + filterbar.setLogLevel(level) + if log_name is not None: + filterbar.setFilterText(log_name) + w.getPerspectiveBar().setEnabled(False) + w.getQModel().connect_logging(host, port) + w.show() + app.exec_() + w.getQModel().disconnect_logging() + + if __name__ == '__main__': main() + # qlogmon_cmd diff --git a/lib/taurus/qt/qtgui/table/taurusdevicepropertytable.py b/lib/taurus/qt/qtgui/table/taurusdevicepropertytable.py index 74f5565b..c256fcca 100755..100644 --- a/lib/taurus/qt/qtgui/table/taurusdevicepropertytable.py +++ b/lib/taurus/qt/qtgui/table/taurusdevicepropertytable.py @@ -436,7 +436,8 @@ class Delegate(QtGui.QItemDelegate): if __name__ == '__main__': import sys from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(app_name="TaurusDevice property table") + app = TaurusApplication(app_name="TaurusDevice property table", + cmd_line_parser=None) widget = TaurusPropTable() args = sys.argv if len(args) == 1: diff --git a/lib/taurus/qt/qtgui/table/taurusgrid.py b/lib/taurus/qt/qtgui/table/taurusgrid.py index a061968d..b9570a6c 100644 --- a/lib/taurus/qt/qtgui/table/taurusgrid.py +++ b/lib/taurus/qt/qtgui/table/taurusgrid.py @@ -299,7 +299,7 @@ class TaurusGrid(QtGui.QFrame, TaurusBaseWidget): 'labels': self._show_attr_labels, 'units': self._show_attr_units, 'others': self._show_others } - f = open(filename, 'w') + f = open(filename, 'wb') pickle.dump(d, f) f.close() @@ -308,7 +308,7 @@ class TaurusGrid(QtGui.QFrame, TaurusBaseWidget): if not isinstance(filename, dict): manual = False import pickle - f = open(filename) + f = open(filename, 'rb') d = pickle.load(f) f.close() else: @@ -1060,7 +1060,7 @@ if __name__ == '__main__': print('\t/usr/bin/python taurusgrid.py "model=lt.*/VC.*/.*/((C*)|(P*)|(I*))" cols=IP,CCG,PNV rows=LT01,LT02 others=False rowframe=True colframe=False') exit() - app = TaurusApplication(sys.argv[0:1]) + app = TaurusApplication(sys.argv[0:1], cmd_line_parser=None) gui = TaurusGrid() try: # first try if argument is a file to be opened diff --git a/lib/taurus/qt/qtgui/table/taurusvaluestable.py b/lib/taurus/qt/qtgui/table/taurusvaluestable.py index 567ea37c..567ea37c 100755..100644 --- a/lib/taurus/qt/qtgui/table/taurusvaluestable.py +++ b/lib/taurus/qt/qtgui/table/taurusvaluestable.py diff --git a/lib/taurus/qt/qtgui/taurusgui/__init__.py b/lib/taurus/qt/qtgui/taurusgui/__init__.py index 021658dd..efd300cd 100644 --- a/lib/taurus/qt/qtgui/taurusgui/__init__.py +++ b/lib/taurus/qt/qtgui/taurusgui/__init__.py @@ -35,7 +35,7 @@ The "new GUI wizard" and XML configuration files ------------------------------------------------ Note that the configuration files can either be written by hand or by -launching the "new GUI" wizard with `taurusgui --new-gui`, which will create +launching the "new GUI" wizard with `taurus newgui`, which will create a new directory containing configuration, resource and launcher files. The new GUI wizard stores all the options in xml format in a file called @@ -51,7 +51,6 @@ prevail). """ from __future__ import absolute_import -from . import utils from .paneldescriptionwizard import * from .taurusgui import * from .appsettingswizard import * diff --git a/lib/taurus/qt/qtgui/taurusgui/appsettingswizard.py b/lib/taurus/qt/qtgui/taurusgui/appsettingswizard.py index 066b6899..f3402909 100644 --- a/lib/taurus/qt/qtgui/taurusgui/appsettingswizard.py +++ b/lib/taurus/qt/qtgui/taurusgui/appsettingswizard.py @@ -45,12 +45,11 @@ import datetime import glob from lxml import etree -from taurus import tauruscustomsettings +from taurus import tauruscustomsettings, warning from taurus.external.qt import Qt, compat import taurus.qt.qtgui.panel import taurus.qt.qtgui.taurusgui.paneldescriptionwizard import taurus.qt.qtgui.input -from taurus.core.tango.tangovalidator import TangoDeviceNameValidator from taurus.core.util.enumeration import Enumeration from taurus.qt.qtgui.util import ExternalAppAction @@ -726,6 +725,12 @@ class MacroServerInfoPage(BasePage): def _getMacroServerName(self): if (self._macroGroupBox.isChecked()) and len(self._confWidget.macroServerComboBox.currentText()): + try: # TODO: tango-centric + from taurus.core.tango.tangovalidator import ( + TangoDeviceNameValidator) + except ImportError: + warning('Cannot import tango (needed for sardana integration)') + return None ms_name = str(self._confWidget.macroServerComboBox.currentText()) complete_name, _, _ = TangoDeviceNameValidator().getNames(ms_name) return complete_name @@ -735,6 +740,12 @@ class MacroServerInfoPage(BasePage): def _getDoorName(self): if (self._macroGroupBox.isChecked()) and len(self._confWidget.macroServerComboBox.currentText()): door_name = str(self._confWidget.doorComboBox.currentText()) + try: # TODO: tango-centric + from taurus.core.tango.tangovalidator import ( + TangoDeviceNameValidator) + except ImportError: + warning('Cannot import tango (needed for sardana integration)') + return None complete_name, _, _ = TangoDeviceNameValidator().getNames( door_name) return complete_name @@ -861,7 +872,8 @@ class PanelsPage(BasePage): name = AppSettingsWizard.getValueFromNode( child, "name", default=None) if name: - self._panels.append((name, etree.tostring(child))) + self._panels.append( + (name, etree.tostring(child, encoding='unicode'))) def _addPanel(self): paneldesc, ok = taurus.qt.qtgui.taurusgui.paneldescriptionwizard.PanelDescriptionWizard.getDialog( @@ -1057,7 +1069,7 @@ class ExternalAppEditor(Qt.QDialog): icon = etree.SubElement(root, "icon") icon.text = self._getIcon() - return etree.tostring(root) + return etree.tostring(root, encoding='unicode') @staticmethod def getDialog(): @@ -1131,7 +1143,9 @@ class ExternalAppPage(BasePage): name = AppSettingsWizard.getValueFromNode( child, "command", default=None) if name: - self._externalApps.append((name, etree.tostring(child))) + self._externalApps.append( + (name, etree.tostring(child, encoding='unicode')) + ) def _addApplication(self): name, xml, ok = ExternalAppEditor.getDialog() @@ -1673,7 +1687,8 @@ class AppSettingsWizard(Qt.QWizard): monitor = etree.SubElement(root, "MONITOR") monitor.text = self.__getitem__("monitor") - return etree.tostring(root, pretty_print=True), copy.copy(self._substitutions) + return (etree.tostring(root, pretty_print=True, encoding='unicode'), + copy.copy(self._substitutions)) def substitutionName(self, src, mod_dir): name = os.path.basename(src) diff --git a/lib/taurus/qt/qtgui/taurusgui/conf/gui_noconf.py b/lib/taurus/qt/qtgui/taurusgui/conf/gui_noconf.py index 21bca2a5..87e0e94b 100755..100644 --- a/lib/taurus/qt/qtgui/taurusgui/conf/gui_noconf.py +++ b/lib/taurus/qt/qtgui/taurusgui/conf/gui_noconf.py @@ -32,7 +32,7 @@ if __name__ == '__main__': from taurus.qt.qtgui.taurusgui import TaurusGui from taurus.external.qt import Qt # if app_name name not given, it uses the file name - app = TaurusApplication(app_name='MyGui') + app = TaurusApplication(app_name='MyGui', cmd_line_parser=None) gui = TaurusGui() panel = Qt.QWidget() gui.createPanel(panel, 'Foo') diff --git a/lib/taurus/qt/qtgui/taurusgui/conf/gui_selfconf.py b/lib/taurus/qt/qtgui/taurusgui/conf/gui_selfconf.py index d1b705f3..c2256413 100755..100644 --- a/lib/taurus/qt/qtgui/taurusgui/conf/gui_selfconf.py +++ b/lib/taurus/qt/qtgui/taurusgui/conf/gui_selfconf.py @@ -34,7 +34,7 @@ if __name__ == '__main__': from taurus.qt.qtgui.application import TaurusApplication from taurus.qt.qtgui.taurusgui import TaurusGui from taurus.external.qt import Qt - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) gui = TaurusGui(confname=__file__) panel = Qt.QWidget() gui.createPanel(panel, 'Foo') diff --git a/lib/taurus/qt/qtgui/taurusgui/conf/tgconf_macrogui/tgconf_macrogui.ini b/lib/taurus/qt/qtgui/taurusgui/conf/tgconf_macrogui/tgconf_macrogui.ini deleted file mode 100644 index 44905da4..00000000 --- a/lib/taurus/qt/qtgui/taurusgui/conf/tgconf_macrogui/tgconf_macrogui.ini +++ /dev/null @@ -1,11 +0,0 @@ -[Perspectives] -Default\MainWindow\State=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x1\0\0\0\x3\0\0\x3R\0\0\x2\xa6\xfc\x1\0\0\0\x2\xfb\0\0\0\x10\0l\0o\0g\0g\0\x65\0r\0\x44\0W\0\0\0\0\0\xff\xff\xff\xff\0\0\0M\x1\0\0\x5\xfc\0\0\0\0\0\0\x3R\0\0\x2\x1d\0\xff\xff\xff\xfc\x2\0\0\0\x2\xfc\0\0\0\x36\0\0\x1\xd3\0\0\x1N\0\xff\xff\xff\xfc\x1\0\0\0\x2\xfb\0\0\0\f\0M\0\x61\0\x63\0r\0o\0s\x1\0\0\0\0\0\0\x1\x86\0\0\0\xe8\x1\0\0\x5\xfc\0\0\x1\x89\0\0\x1\xc9\0\0\x1\x32\0\xff\xff\xff\xfc\x2\0\0\0\x2\xfb\0\0\0\x10\0\x31\0\x44\0 \0S\0\x63\0\x61\0n\0s\x1\0\0\0\x36\0\0\x1\x12\0\0\0\xe4\x1\0\0\x5\xfb\0\0\0 \0M\0\x61\0\x63\0r\0o\0\x44\0\x65\0s\0\x63\0r\0i\0p\0t\0i\0o\0n\x1\0\0\x1K\0\0\0\xbe\0\0\0_\x1\0\0\x5\xfc\0\0\x2\f\0\0\0\xd0\0\0\0|\x1\0\0\x1c\xfa\0\0\0\0\x1\0\0\0\x3\xfb\0\0\0\x14\0\x44\0o\0o\0r\0O\0u\0t\0p\0u\0t\x1\0\0\0\0\xff\xff\xff\xff\0\0\0M\x1\0\0\x5\xfb\0\0\0\x12\0\x44\0o\0o\0r\0\x44\0\x65\0\x62\0u\0g\x1\0\0\0\0\xff\xff\xff\xff\0\0\0M\x1\0\0\x5\xfb\0\0\0\x14\0\x44\0o\0o\0r\0R\0\x65\0s\0u\0l\0t\x1\0\0\0\0\xff\xff\xff\xff\0\0\0M\x1\0\0\x5\0\0\x3R\0\0\0\0\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x2\0\0\0\x1\0\0\0\x1\0\0\0\x18\0j\0o\0r\0g\0s\0T\0o\0o\0l\0\x42\0\x61\0r\x3\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x2\0\0\0\x3\0\0\0&\0p\0\x65\0r\0s\0p\0\x65\0\x63\0t\0i\0v\0\x65\0s\0T\0o\0o\0l\0\x42\0\x61\0r\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x1a\0P\0\x61\0n\0\x65\0l\0s\0T\0o\0o\0l\0\x62\0\x61\0r\x1\0\0\0\xb2\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0*\0\x45\0x\0t\0\x65\0r\0n\0\x61\0l\0 \0\x41\0p\0p\0l\0i\0\x63\0\x61\0t\0i\0o\0n\0s\x1\0\0\0\xd8\xff\xff\xff\xff\0\0\0\0\0\0\0\0) -Default\MainWindow\Geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\xf2\0\0\0\xbc\0\0\x4\x91\0\0\x3\xc6\0\0\0\xf6\0\0\0\xd3\0\0\x4\x8d\0\0\x3\xc2\0\0\0\0\0\0) -Default\TaurusConfig=@ByteArray((dp1\nS'__orderedConfigNames__'\np2\n(lp3\nS'modifiableByUser'\np4\naS'ModelInConfig'\np5\naS'permanentCustomPanels'\np6\naS'Macros'\np7\naS'MacroDescription'\np8\naS'1D Scans'\np9\naS'_extApp[pymca]'\np10\naS'_extApp[Spock]'\np11\nasS'__itemConfigurations__'\np12\n(dp13\ng7\n(dp14\ng2\n(lp15\ng4\nag5\nasS'widget'\np16\n(dp17\ng2\n(lp18\ng4\nag5\naS'aaaaa'\np19\nasg12\n(dp20\ng4\nI00\nsg19\n(dp21\ng2\n(lp22\ng4\nag5\naS'favourites'\np23\naS''\nasg12\n(dp24\ng4\nI00\nsS''\n(dp25\ng2\n(lp26\nsg12\n(dp27\nsS'ConfigVersion'\np28\nS'__UNVERSIONED__'\np29\nsS'__pickable__'\np30\nI01\nssg23\nS'<list/>'\np31\nsg5\nI00\nssg28\ng29\nsg30\nI01\nssg5\nI00\nssg28\ng29\nsg30\nI01\nssg30\nI01\nsg12\n(dp32\ng4\nI00\nsg5\nI00\nssg28\ng29\nsS'widgetClassName'\np33\nS'TaurusMacroExecutorWidget'\np34\nssg4\nI00\nsg8\n(dp35\ng2\n(lp36\ng4\nag5\nasg16\n(dp37\ng2\n(lp38\ng4\nag5\nasg12\n(dp39\ng4\nI00\nsg5\nI00\nssg28\ng29\nsg30\nI01\nssg30\nI01\nsg12\n(dp40\ng4\nI00\nsg5\nI00\nssg28\ng29\nsg33\nS'TaurusMacroDescriptionViewer'\np41\nssg9\n(dp42\ng2\n(lp43\ng4\nag5\nasg16\n(dp44\nS'CurveProp'\np45\n(dp46\nsS'TrendSets'\np47\nccopy_reg\n_reconstructor\np48\n(ctaurus.core.util.containers\nCaselessDict\np49\nc__builtin__\ndict\np50\n(dtRp51\nsS'Axes'\np52\n(dp53\nS'xIsTime'\np54\nI00\nsS'y1Max'\np55\nNsS'y1Min'\np56\nNsS'xMode'\np57\ncsip\n_unpickle_enum\np58\n(S'PyQt4.Qwt5.Qwt'\np59\nS'Type'\nI0\ntRp60\nsS'xMax'\np61\nNsS'y2Min'\np62\nNsS'y2Mode'\np63\ng58\n(g59\nS'Type'\nI0\ntRp64\nsS'y1Mode'\np65\ng58\n(g59\nS'Type'\nI0\ntRp66\nsS'y2Max'\np67\nNsS'xDyn'\np68\nI00\nsS'xMin'\np69\nNssS'Misc'\np70\n(dp71\nS'canvasBackground'\np72\ncsip\n_unpickle_type\np73\n(S'PyQt4.QtGui'\np74\nS'QColor'\n(I224\nI223\nI222\nI255\nttRp75\nsS'defaultCurvesTitle'\np76\nS'<label><[trend_index]>'\np77\nsS'plotTitle'\np78\nV\nsS'orderedCurveNames'\np79\n(lp80\nssS'RawData'\np81\ng48\n(g49\ng50\n(dtRp82\nsg28\nS'ttc-1'\np83\nssg30\nI01\nsg12\n(dp84\ng4\nI00\nsg5\nI00\nssg28\ng29\nsg33\nS'TaurusTrend'\np85\nssg10\n(dp86\ng2\n(lp87\nS'cmdArgs'\np88\nasg12\n(dp89\ng88\n(lp90\nS'pymca'\np91\nassg28\ng29\nsg30\nI01\nssg6\n(lp92\nsg5\nI00\nsg11\n(dp93\ng2\n(lp94\ng88\nasg12\n(dp95\ng88\n(lp96\nS'xterm'\np97\naS'spock'\np98\nassg28\ng29\nsg30\nI01\nsssg28\ng29\nsg30\nI01\ns.) - -[MainWindow] -State=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x1\0\0\0\x3\0\0\x3R\0\0\x2\xa6\xfc\x1\0\0\0\x2\xfb\0\0\0\x10\0l\0o\0g\0g\0\x65\0r\0\x44\0W\0\0\0\0\0\xff\xff\xff\xff\0\0\0M\x1\0\0\x5\xfc\0\0\0\0\0\0\x3R\0\0\x2\x1d\0\xff\xff\xff\xfc\x2\0\0\0\x2\xfc\0\0\0\x36\0\0\x1\xd3\0\0\x1N\0\xff\xff\xff\xfc\x1\0\0\0\x2\xfb\0\0\0\f\0M\0\x61\0\x63\0r\0o\0s\x1\0\0\0\0\0\0\x1\x86\0\0\0\xe8\x1\0\0\x5\xfc\0\0\x1\x89\0\0\x1\xc9\0\0\x1\x32\0\xff\xff\xff\xfc\x2\0\0\0\x2\xfb\0\0\0\x10\0\x31\0\x44\0 \0S\0\x63\0\x61\0n\0s\x1\0\0\0\x36\0\0\x1\x12\0\0\0\xe4\x1\0\0\x5\xfb\0\0\0 \0M\0\x61\0\x63\0r\0o\0\x44\0\x65\0s\0\x63\0r\0i\0p\0t\0i\0o\0n\x1\0\0\x1K\0\0\0\xbe\0\0\0_\x1\0\0\x5\xfc\0\0\x2\f\0\0\0\xd0\0\0\0|\x1\0\0\x1c\xfa\0\0\0\0\x1\0\0\0\x3\xfb\0\0\0\x14\0\x44\0o\0o\0r\0O\0u\0t\0p\0u\0t\x1\0\0\0\0\xff\xff\xff\xff\0\0\0M\x1\0\0\x5\xfb\0\0\0\x12\0\x44\0o\0o\0r\0\x44\0\x65\0\x62\0u\0g\x1\0\0\0\0\xff\xff\xff\xff\0\0\0M\x1\0\0\x5\xfb\0\0\0\x14\0\x44\0o\0o\0r\0R\0\x65\0s\0u\0l\0t\x1\0\0\0\0\xff\xff\xff\xff\0\0\0M\x1\0\0\x5\0\0\x3R\0\0\0\0\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x2\0\0\0\x1\0\0\0\x1\0\0\0\x18\0j\0o\0r\0g\0s\0T\0o\0o\0l\0\x42\0\x61\0r\x3\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x2\0\0\0\x3\0\0\0&\0p\0\x65\0r\0s\0p\0\x65\0\x63\0t\0i\0v\0\x65\0s\0T\0o\0o\0l\0\x42\0\x61\0r\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x1a\0P\0\x61\0n\0\x65\0l\0s\0T\0o\0o\0l\0\x62\0\x61\0r\x1\0\0\0\xb2\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0*\0\x45\0x\0t\0\x65\0r\0n\0\x61\0l\0 \0\x41\0p\0p\0l\0i\0\x63\0\x61\0t\0i\0o\0n\0s\x1\0\0\0\xd8\xff\xff\xff\xff\0\0\0\0\0\0\0\0) -Geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\xf2\0\0\0\xbc\0\0\x4\x91\0\0\x3\xc6\0\0\0\xf6\0\0\0\xd3\0\0\x4\x8d\0\0\x3\xc2\0\0\0\0\0\0) - -[General] -TaurusConfig=@ByteArray((dp1\nS'__orderedConfigNames__'\np2\n(lp3\nS'modifiableByUser'\np4\naS'ModelInConfig'\np5\naS'permanentCustomPanels'\np6\naS'Macros'\np7\naS'MacroDescription'\np8\naS'1D Scans'\np9\naS'_extApp[pymca]'\np10\naS'_extApp[Spock]'\np11\nasS'__itemConfigurations__'\np12\n(dp13\ng7\n(dp14\ng2\n(lp15\ng4\nag5\nasS'widget'\np16\n(dp17\ng2\n(lp18\ng4\nag5\naS'aaaaa'\np19\nasg12\n(dp20\ng4\nI00\nsg19\n(dp21\ng2\n(lp22\ng4\nag5\naS'favourites'\np23\naS''\nasg12\n(dp24\ng4\nI00\nsS''\n(dp25\ng2\n(lp26\nsg12\n(dp27\nsS'ConfigVersion'\np28\nS'__UNVERSIONED__'\np29\nsS'__pickable__'\np30\nI01\nssg23\nS'<list/>'\np31\nsg5\nI00\nssg28\ng29\nsg30\nI01\nssg5\nI00\nssg28\ng29\nsg30\nI01\nssg30\nI01\nsg12\n(dp32\ng4\nI00\nsg5\nI00\nssg28\ng29\nsS'widgetClassName'\np33\nS'TaurusMacroExecutorWidget'\np34\nssg4\nI00\nsg8\n(dp35\ng2\n(lp36\ng4\nag5\nasg16\n(dp37\ng2\n(lp38\ng4\nag5\nasg12\n(dp39\ng4\nI00\nsg5\nI00\nssg28\ng29\nsg30\nI01\nssg30\nI01\nsg12\n(dp40\ng4\nI00\nsg5\nI00\nssg28\ng29\nsg33\nS'TaurusMacroDescriptionViewer'\np41\nssg9\n(dp42\ng2\n(lp43\ng4\nag5\nasg16\n(dp44\nS'CurveProp'\np45\n(dp46\nsS'TrendSets'\np47\nccopy_reg\n_reconstructor\np48\n(ctaurus.core.util.containers\nCaselessDict\np49\nc__builtin__\ndict\np50\n(dtRp51\nsS'Axes'\np52\n(dp53\nS'xIsTime'\np54\nI00\nsS'y1Max'\np55\nNsS'y1Min'\np56\nNsS'xMode'\np57\ncsip\n_unpickle_enum\np58\n(S'PyQt4.Qwt5.Qwt'\np59\nS'Type'\nI0\ntRp60\nsS'xMax'\np61\nNsS'y2Min'\np62\nNsS'y2Mode'\np63\ng58\n(g59\nS'Type'\nI0\ntRp64\nsS'y1Mode'\np65\ng58\n(g59\nS'Type'\nI0\ntRp66\nsS'y2Max'\np67\nNsS'xDyn'\np68\nI00\nsS'xMin'\np69\nNssS'Misc'\np70\n(dp71\nS'canvasBackground'\np72\ncsip\n_unpickle_type\np73\n(S'PyQt4.QtGui'\np74\nS'QColor'\n(I224\nI223\nI222\nI255\nttRp75\nsS'defaultCurvesTitle'\np76\nS'<label><[trend_index]>'\np77\nsS'plotTitle'\np78\nV\nsS'orderedCurveNames'\np79\n(lp80\nssS'RawData'\np81\ng48\n(g49\ng50\n(dtRp82\nsg28\nS'ttc-1'\np83\nssg30\nI01\nsg12\n(dp84\ng4\nI00\nsg5\nI00\nssg28\ng29\nsg33\nS'TaurusTrend'\np85\nssg10\n(dp86\ng2\n(lp87\nS'cmdArgs'\np88\nasg12\n(dp89\ng88\n(lp90\nS'pymca'\np91\nassg28\ng29\nsg30\nI01\nssg6\n(lp92\nsg5\nI00\nsg11\n(dp93\ng2\n(lp94\ng88\nasg12\n(dp95\ng88\n(lp96\nS'xterm'\np97\naS'spock'\np98\nassg28\ng29\nsg30\nI01\nsssg28\ng29\nsg30\nI01\ns.) diff --git a/lib/taurus/qt/qtgui/taurusgui/paneldescriptionwizard.py b/lib/taurus/qt/qtgui/taurusgui/paneldescriptionwizard.py index a4fa08ca..0acf0029 100644 --- a/lib/taurus/qt/qtgui/taurusgui/paneldescriptionwizard.py +++ b/lib/taurus/qt/qtgui/taurusgui/paneldescriptionwizard.py @@ -35,7 +35,6 @@ import weakref from taurus.qt.qtgui.taurusgui.utils import PanelDescription from taurus.qt.qtgui.icon import getCachedPixmap from taurus.qt.qtgui.input import GraphicalChoiceWidget -from taurus.qt.qtgui.panel import TaurusModelChooser from taurus.qt.qtgui.base import TaurusBaseComponent, TaurusBaseWidget from taurus.qt.qtcore.communication import SharedDataManager from taurus.qt.qtcore.mimetypes import TAURUS_MODEL_LIST_MIME_TYPE @@ -429,6 +428,7 @@ class AdvSettingsPage(Qt.QWizardPage): self.commLV.setItemDelegate(self.itemDelegate) def showModelChooser(self): + from taurus.qt.qtgui.panel import TaurusModelChooser models, ok = TaurusModelChooser.modelChooserDlg( parent=self, asMimeData=True) if not ok: @@ -652,7 +652,7 @@ class PanelDescriptionWizard(Qt.QWizard, TaurusBaseWidget): def test(): from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) form = PanelDescriptionWizard() def kk(d): @@ -667,14 +667,14 @@ def test(): def test2(): from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) print(ExpertWidgetChooserDlg.getDialog()) sys.exit() def main(): from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication(sys.argv) + app = TaurusApplication(sys.argv, cmd_line_parser=None) from taurus.qt.qtgui.container import TaurusMainWindow form = Qt.QMainWindow() diff --git a/lib/taurus/qt/qtgui/taurusgui/res/init.template b/lib/taurus/qt/qtgui/taurusgui/res/init.template index 08f2543d..b14a87b6 100644 --- a/lib/taurus/qt/qtgui/taurusgui/res/init.template +++ b/lib/taurus/qt/qtgui/taurusgui/res/init.template @@ -2,9 +2,17 @@ This file was autogenerated by taurusgui --new-gui. """ -from config import * +from __future__ import absolute_import +import click +from .config import * -def run(): - from taurus.qt.qtgui.taurusgui.taurusgui import main - main(confname="tgconf_{name}") +@click.command("{name}") +@click.pass_context +@click.option('--safe-mode', 'safe_mode', is_flag=True, default=False, + help=('launch in safe mode (it prevents potentially problematic ' + 'configs from being loaded)') + ) +def run(ctx, safe_mode): + from taurus.qt.qtgui.taurusgui.taurusgui import gui_cmd + ctx.invoke(gui_cmd, confname="tgconf_{name}", safe_mode=safe_mode) diff --git a/lib/taurus/qt/qtgui/taurusgui/res/setup.template b/lib/taurus/qt/qtgui/taurusgui/res/setup.template index 00eba818..0b011fa3 100644 --- a/lib/taurus/qt/qtgui/taurusgui/res/setup.template +++ b/lib/taurus/qt/qtgui/taurusgui/res/setup.template @@ -13,11 +13,12 @@ classifiers = [ 'Intended Audience :: End Users/Desktop', 'Topic :: Scientific/Engineering', 'Environment :: X11 Applications :: Qt', - 'Programming Language :: Python :: 2.7' + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.5' ] _entry_points = {{ - "gui_scripts": ["{name}=tgconf_{name}:run"] + "console_scripts": ["{name}=tgconf_{name}:run"] }} setup( diff --git a/lib/taurus/qt/qtgui/taurusgui/taurusgui.py b/lib/taurus/qt/qtgui/taurusgui/taurusgui.py index 7228bc60..f46e5c86 100644 --- a/lib/taurus/qt/qtgui/taurusgui/taurusgui.py +++ b/lib/taurus/qt/qtgui/taurusgui/taurusgui.py @@ -25,10 +25,13 @@ """This package provides the TaurusGui class""" +from __future__ import absolute_import + from builtins import str import os import sys import copy +import click import weakref import inspect @@ -46,8 +49,6 @@ from taurus.qt.qtgui.container import TaurusMainWindow from taurus.qt.qtgui.taurusgui.utils import (ExternalApp, PanelDescription, ToolBarDescription, AppletDescription) -from taurus.qt.qtgui.taurusgui.appsettingswizard import ExternalAppEditor -from taurus.qt.qtgui.panel import QDoubleListDlg from taurus.qt.qtgui.util.ui import UILoadable from taurus.qt.qtgui.taurusgui.utils import ExternalAppAction @@ -214,7 +215,7 @@ class DockWidgetPanel(Qt.QDockWidget, TaurusBaseWidget): class TaurusGui(TaurusMainWindow): - ''' + """ This is main class for constructing the dynamic GUIs. TaurusGui is a specialised TaurusMainWindow which is able to handle "panels" and load configuration files. @@ -246,7 +247,7 @@ class TaurusGui(TaurusMainWindow): from taurus.qt.qtgui.application import TaurusApplication from taurus.qt.qtgui.taurusgui import TaurusGui from taurus.external.qt import Qt - app = TaurusApplication(app_name='MyGui') + app = TaurusApplication(cmd_line_parser=None, app_name='MyGui') gui = TaurusGui() panel = Qt.QWidget() gui.createPanel(panel, 'Foo') @@ -265,14 +266,14 @@ class TaurusGui(TaurusMainWindow): from taurus.qt.qtgui.application import TaurusApplication from taurus.qt.qtgui.taurusgui import TaurusGui from taurus.external.qt import Qt - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) gui = TaurusGui(confname=__file__) panel = Qt.QWidget() gui.createPanel(panel, 'Foo') # <-- programmatic! gui.show() app.exec_() - ''' + """ SelectedInstrument = Qt.pyqtSignal('QString') doorNameChanged = Qt.pyqtSignal('QString') @@ -281,7 +282,15 @@ class TaurusGui(TaurusMainWindow): IMPLICIT_ASSOCIATION = '__[IMPLICIT]__' - def __init__(self, parent=None, confname=None, configRecursionDepth=None): + #: Whether to show user actions related to shared data connections + PANELS_MENU_ENABLED = True + #: Whether to show the applets toolbar + APPLETS_TOOLBAR_ENABLED = True + #: wether to add the Quick access Toolbar (empty by default) + QUICK_ACCESS_TOOLBAR_ENABLED = True + + def __init__(self, parent=None, confname=None, configRecursionDepth=None, + settingsname=None): TaurusMainWindow.__init__(self, parent, False, True) if configRecursionDepth is not None: @@ -312,13 +321,34 @@ class TaurusGui(TaurusMainWindow): # Create a global SharedDataManager Qt.qApp.SDM = SharedDataManager(self) - self.__initPanelsMenu() - self.__initQuickAccessToolBar() - self.__initJorgBar() + # Initialize menus & toolbars + if self.PANELS_MENU_ENABLED: + self.__initPanelsMenu() + self.__initPanelsToolBar() + if self.QUICK_ACCESS_TOOLBAR_ENABLED: + self.__initQuickAccessToolBar() + if self.APPLETS_TOOLBAR_ENABLED: + self.__initJorgBar() + self.__initSharedDataConnections() - self.__initToolsMenu() - self.__initViewMenu() - self.__initPanelsToolBar() + + if self.TOOLS_MENU_ENABLED: + self.__initToolsMenu() + + # Create lockview actions + self._lockviewAction = Qt.QAction(Qt.QIcon.fromTheme( + "system-lock-screen"), "Lock View", self) + self._lockviewAction.setCheckable(True) + self._lockviewAction.toggled.connect(self.setLockView) + self._lockviewAction.setChecked(not self.isModifiableByUser()) + + if self.VIEW_MENU_ENABLED: + self.__initViewMenu() + + if settingsname: + self.resetQSettings() + _s = Qt.QSettings(settingsname, Qt.QSettings.IniFormat) + self.setQSettings(_s) self.loadConfiguration(confname) @@ -370,7 +400,11 @@ class TaurusGui(TaurusMainWindow): def __initPanelsMenu(self): # Panels menu self.__panelsMenu = Qt.QMenu('Panels', self) - self.menuBar().insertMenu(self.helpMenu.menuAction(), self.__panelsMenu) + try: # insert the panels menu before the help menu + self.menuBar().insertMenu(self.helpMenu.menuAction(), + self.__panelsMenu) + except AttributeError: # Or just add it if help menu is not shown + self.menuBar().addMenu(self.__panelsMenu) self.hideAllPanelsAction = self.__panelsMenu.addAction( Qt.QIcon('actions:hide.svg'), "Hide all panels", self.hideAllPanels) self.showAllPanelsAction = self.__panelsMenu.addAction( @@ -400,11 +434,6 @@ class TaurusGui(TaurusMainWindow): self.viewMenu.addSeparator() # view locking self.viewMenu.addSeparator() - self._lockviewAction = Qt.QAction(Qt.QIcon.fromTheme( - "system-lock-screen"), "Lock View", self) - self._lockviewAction.setCheckable(True) - self._lockviewAction.toggled.connect(self.setLockView) - self._lockviewAction.setChecked(not self.isModifiableByUser()) self.viewMenu.addAction(self._lockviewAction) def __initPanelsToolBar(self): @@ -412,15 +441,18 @@ class TaurusGui(TaurusMainWindow): self.panelsToolBar = self.addToolBar("Panels") self.panelsToolBar.setObjectName("PanelsToolbar") self.panelsToolBar.addAction(self.newPanelAction) - self.viewToolBarsMenu.addAction(self.panelsToolBar.toggleViewAction()) + if self.VIEW_MENU_ENABLED: + self.viewToolBarsMenu.addAction(self.panelsToolBar.toggleViewAction()) def __initQuickAccessToolBar(self): self.quickAccessToolBar = self.addToolBar("Quick Access") self.quickAccessToolBar.setObjectName("quickAccessToolbar") self.quickAccessToolBar.setToolButtonStyle( Qt.Qt.ToolButtonTextBesideIcon) - self.viewToolBarsMenu.addAction( - self.quickAccessToolBar.toggleViewAction()) + if self.VIEW_MENU_ENABLED: + self.viewToolBarsMenu.addAction( + self.quickAccessToolBar.toggleViewAction() + ) def __initJorgBar(self): # Fancy Stuff ToolBar (aka Jorg's Bar ;) ) @@ -473,6 +505,7 @@ class TaurusGui(TaurusMainWindow): def createExternalApp(self): '''Add a new external application on execution time''' + from .appsettingswizard import ExternalAppEditor app_editor = ExternalAppEditor(self) name, xml, ok = app_editor.getDialog() if name in self._external_app_names: @@ -734,6 +767,7 @@ class TaurusGui(TaurusMainWindow): temp = [n for n, p in self.__panels.items() if ( p.isCustom() and not p.isPermanent())] if len(temp) > 0 or showAlways: + from taurus.qt.qtgui.panel import QDoubleListDlg dlg = QDoubleListDlg(winTitle='Stored panels', mainLabel='Select which of the panels should be stored', label1='Temporary (to be discarded)', label2='Permanent (to be stored)', @@ -762,6 +796,7 @@ class TaurusGui(TaurusMainWindow): # be made permanent #permanet_ext_app = list(self._external_app_names) if len(self.__external_app) > 0 or showAlways: + from taurus.qt.qtgui.panel import QDoubleListDlg msg = 'Select which of the external applications should be stored' dlg = QDoubleListDlg(winTitle='Stored external applications', mainLabel=msg, @@ -850,8 +885,10 @@ class TaurusGui(TaurusMainWindow): synopticpanel = self.createPanel(synoptic, name, permanent=True, icon=Qt.QIcon.fromTheme( 'image-x-generic')) - toggleSynopticAction = synopticpanel.toggleViewAction() - self.quickAccessToolBar.addAction(toggleSynopticAction) + + if self.QUICK_ACCESS_TOOLBAR_ENABLED: + toggleSynopticAction = synopticpanel.toggleViewAction() + self.quickAccessToolBar.addAction(toggleSynopticAction) def createConsole(self, kernels): msg = ('createConsole() and the "CONSOLE" configuration key are ' + @@ -1000,20 +1037,47 @@ class TaurusGui(TaurusMainWindow): self, 'Initialization error', msg, Qt.QMessageBox.Abort) sys.exit() - # Get the xml root node from the xml configuration file - XML_CONFIG = getattr(conf, 'XML_CONFIG', None) - if XML_CONFIG is None: + xmlroot = self._loadXmlConfig(conf) + + self._loadAppName(conf, confname, xmlroot) + self._loadOrgName(conf, xmlroot) + self._loadCustomLogo(conf, xmlroot) + Qt.QApplication.instance().basicConfig() + self._loadOrgLogo(conf, xmlroot) + + self._loadSingleInstance(conf, xmlroot) + + self._loadExtraCatalogWidgets(conf, xmlroot) + self._loadManualUri(conf, xmlroot) + POOLINSTRUMENTS = self._loadSardanaOptions(conf, xmlroot) + self._loadSynoptic(conf, xmlroot) + # TODO: remove deprecated _loadConsole + self._loadConsole(conf, xmlroot) + + self._loadCustomPanels(conf, xmlroot, POOLINSTRUMENTS) + self._loadCustomToolBars(conf, xmlroot) + self._loadCustomApplets(conf, xmlroot) + self._loadExternalApps(conf, xmlroot) + self._loadIniFile(conf, xmlroot) + + def _loadXmlConfig(self, conf): + """ + Get the xml root node from the xml configuration file + """ + + xml_config = getattr(conf, 'XML_CONFIG', None) + if xml_config is None: self._xmlConfigFileName = None else: self._xmlConfigFileName = os.path.join( - self._confDirectory, XML_CONFIG) + self._confDirectory, xml_config) # default fallback (in case of I/O or parse errors) xmlroot = etree.fromstring('<root></root>') - if XML_CONFIG is not None: + if xml_config is not None: try: # If a relative name was given, the conf directory will be used # as base path - xmlfname = os.path.join(self._confDirectory, XML_CONFIG) + xmlfname = os.path.join(self._confDirectory, xml_config) xmlFile = open(xmlfname, 'r') xmlstring = xmlFile.read() xmlFile.close() @@ -1026,162 +1090,204 @@ class TaurusGui(TaurusMainWindow): msg, repr(e)), Qt.QMessageBox.Abort | Qt.QMessageBox.Ignore) if result == Qt.QMessageBox.Abort: sys.exit() + return xmlroot - # General Qt application settings and jorgs bar logos - APPNAME = getattr(conf, 'GUI_NAME', self.__getVarFromXML( + def _loadAppName(self, conf, confname, xmlroot): + appname = getattr(conf, 'GUI_NAME', self.__getVarFromXML( xmlroot, "GUI_NAME", confname)) - ORGNAME = getattr(conf, 'ORGANIZATION', self.__getVarFromXML( + Qt.qApp.setApplicationName(appname) + self.setWindowTitle(appname) + + def _loadOrgName(self, conf, xmlroot): + orgname = getattr(conf, 'ORGANIZATION', self.__getVarFromXML( xmlroot, "ORGANIZATION", str(Qt.qApp.organizationName()) or 'Taurus')) - CUSTOMLOGO = getattr(conf, 'CUSTOM_LOGO', getattr( + Qt.qApp.setOrganizationName(orgname) + + def _loadCustomLogo(self, conf, xmlroot): + custom_logo = getattr(conf, 'CUSTOM_LOGO', getattr( conf, 'LOGO', self.__getVarFromXML(xmlroot, "CUSTOM_LOGO", 'logos:taurus.png'))) - if Qt.QFile.exists(CUSTOMLOGO): - customIcon = Qt.QIcon(CUSTOMLOGO) + if Qt.QFile.exists(custom_logo): + custom_icon = Qt.QIcon(custom_logo) else: - customIcon = Qt.QIcon(os.path.join( - self._confDirectory, CUSTOMLOGO)) - Qt.qApp.setApplicationName(APPNAME) - Qt.qApp.setOrganizationName(ORGNAME) - Qt.QApplication.instance().basicConfig() - - logo = getattr(tauruscustomsettings, 'ORGANIZATION_LOGO', + custom_icon = Qt.QIcon(os.path.join( + self._confDirectory, custom_logo)) + self.setWindowIcon(custom_icon) + if self.APPLETS_TOOLBAR_ENABLED: + self.jorgsBar.addAction(custom_icon, Qt.qApp.applicationName()) + + def _loadOrgLogo(self, conf, xmlroot): + logo = getattr(tauruscustomsettings, + "ORGANIZATION_LOGO", "logos:taurus.png") - ORGANIZATIONLOGO = getattr(conf, 'ORGANIZATION_LOGO', - self.__getVarFromXML(xmlroot, - "ORGANIZATION_LOGO", - logo)) - ## - if Qt.QFile.exists(ORGANIZATIONLOGO): - organizationIcon = Qt.QIcon(ORGANIZATIONLOGO) + org_logo = getattr(conf, + "ORGANIZATION_LOGO", + self.__getVarFromXML(xmlroot, + "ORGANIZATION_LOGO", + logo)) + if Qt.QFile.exists(org_logo): + org_icon = Qt.QIcon(org_logo) else: - organizationIcon = Qt.QIcon(os.path.join( - self._confDirectory, ORGANIZATIONLOGO)) - - # if required, enforce that only one instance of this GUI can be run - SINGLEINSTANCE = getattr(conf, 'SINGLE_INSTANCE', (self.__getVarFromXML( + org_icon = Qt.QIcon(os.path.join( + self._confDirectory, org_logo)) + if self.APPLETS_TOOLBAR_ENABLED: + self.jorgsBar.addAction(org_icon, Qt.qApp.organizationName()) + + def _loadSingleInstance(self, conf, xmlroot): + """ + if required, enforce that only one instance of this GUI can be run + """ + single_inst = getattr(conf, 'SINGLE_INSTANCE', (self.__getVarFromXML( xmlroot, "SINGLE_INSTANCE", 'True').lower() == 'true')) - if SINGLEINSTANCE: + if single_inst: if not self.checkSingleInstance(): - msg = 'Only one istance of %s is allowed to run the same time' % ( - APPNAME) + msg = 'Only one instance of %s is allowed to run the same time' % ( + Qt.qApp.applicationName()) self.error(msg) Qt.QMessageBox.critical( self, 'Multiple copies', msg, Qt.QMessageBox.Abort) sys.exit(1) - # some initialization - self.resetQSettings() - self.setWindowTitle(APPNAME) - self.setWindowIcon(customIcon) - self.jorgsBar.addAction(organizationIcon, ORGNAME) - self.jorgsBar.addAction(customIcon, APPNAME) - - # get custom widget catalog entries + def _loadExtraCatalogWidgets(self, conf, xmlroot): + """ + get custom widget catalog entries + """ # @todo: support also loading from xml - EXTRA_CATALOG_WIDGETS = getattr(conf, 'EXTRA_CATALOG_WIDGETS', []) + extra_catalog_widgets = getattr(conf, 'EXTRA_CATALOG_WIDGETS', []) self._extraCatalogWidgets = [] - for classname, pixmapname in EXTRA_CATALOG_WIDGETS: + for class_name, pix_map_name in extra_catalog_widgets: # If a relative file name is given, the conf directory will be used # as base path - if pixmapname and not Qt.QFile.exists(pixmapname): - pixmapname = os.path.join(self._confDirectory, pixmapname) - self._extraCatalogWidgets.append((classname, pixmapname)) - - # manual panel - MANUAL_URI = getattr(conf, 'MANUAL_URI', + if pix_map_name and not Qt.QFile.exists(pix_map_name): + pix_map_name = os.path.join(self._confDirectory, pix_map_name) + self._extraCatalogWidgets.append((class_name, pix_map_name)) + + def _loadManualUri(self, conf, xmlroot): + """ + manual panel + """ + manual_uri = getattr(conf, 'MANUAL_URI', self.__getVarFromXML(xmlroot, "MANUAL_URI", taurus.Release.url)) - self.setHelpManualURI(MANUAL_URI) + self.setHelpManualURI(manual_uri) - self.createPanel(self.helpManualBrowser, 'Manual', permanent=True, - icon=Qt.QIcon.fromTheme('help-browser')) + if self.HELP_MENU_ENABLED: + self.createPanel(self.helpManualBrowser, 'Manual', permanent=True, + icon=Qt.QIcon.fromTheme('help-browser')) - # configure the macro infrastructure - MACROSERVER_NAME = getattr(conf, 'MACROSERVER_NAME', self.__getVarFromXML( - xmlroot, "MACROSERVER_NAME", None)) - MACRO_PANELS = getattr(conf, 'MACRO_PANELS', self.__getVarFromXML( - xmlroot, "MACRO_PANELS", True)) + ### SARDANA MACRO STUFF ON + def _loadSardanaOptions(self, conf, xmlroot): + """configure macro infrastructure""" + ms = self._loadMacroServerName(conf, xmlroot) + mp = self._loadMacroPanels(conf, xmlroot) # macro infrastructure will only be created if MACROSERVER_NAME is set - if MACRO_PANELS and MACROSERVER_NAME is not None: + if ms is not None and mp is True: from sardana.taurus.qt.qtgui.macrolistener import MacroBroker self.__macroBroker = MacroBroker(self) - if MACROSERVER_NAME: - self.macroserverNameChanged.emit(MACROSERVER_NAME) + self._loadDoorName(conf, xmlroot) + self._loadMacroEditorsPath(conf, xmlroot) + pool_instruments = self._loadInstrumentsFromPool(conf, xmlroot, ms) + return pool_instruments + + def _loadMacroServerName(self, conf, xmlroot): + macro_server_name = getattr(conf, "MACROSERVER_NAME", self.__getVarFromXML( + xmlroot, "MACROSERVER_NAME", None)) + if macro_server_name: + self.macroserverNameChanged.emit(macro_server_name) + return macro_server_name - DOOR_NAME = getattr(conf, 'DOOR_NAME', + def _loadMacroPanels(self, conf, xmlroot): + macro_panels = getattr(conf, "MACRO_PANELS", self.__getVarFromXML( + xmlroot, "MACRO_PANELS", True)) + return macro_panels + + def _loadDoorName(self, conf, xmlroot): + door_name = getattr(conf, "DOOR_NAME", self.__getVarFromXML(xmlroot, "DOOR_NAME", '')) - if DOOR_NAME: - self.doorNameChanged.emit(DOOR_NAME) - - MACROEDITORS_PATH = getattr(conf, 'MACROEDITORS_PATH', self.__getVarFromXML( - xmlroot, "MACROEDITORS_PATH", '')) - if MACROEDITORS_PATH: - from sardana.taurus.qt.qtgui.extra_macroexecutor.macroparameterseditor.macroparameterseditor import ParamEditorManager - ParamEditorManager().parsePaths(MACROEDITORS_PATH) + if door_name: + self.doorNameChanged.emit(door_name) + + def _loadMacroEditorsPath(self, conf, xmlroot): + macro_editors_path = getattr(conf, "MACROEDITORS_PATH", self.__getVarFromXML( + xmlroot, "MACROEDITORS_PATH", "")) + if macro_editors_path: + from sardana.taurus.qt.qtgui.extra_macroexecutor.macroparameterseditor.macroparameterseditor import \ + ParamEditorManager + ParamEditorManager().parsePaths(macro_editors_path) ParamEditorManager().browsePaths() + def _loadInstrumentsFromPool(self, conf, xmlroot, macro_server_name): + """ + Get panel descriptions from pool if required + """ + instruments_from_pool = getattr(conf, "INSTRUMENTS_FROM_POOL", (self.__getVarFromXML( + xmlroot, "INSTRUMENTS_FROM_POOL", "False").lower() == "true")) + if instruments_from_pool: + try: + self.splashScreen().showMessage("Gathering Instrument info from Pool") + except AttributeError: + pass + pool_instruments = self.createInstrumentsFromPool( + macro_server_name) # auto create instruments from pool + else: + pool_instruments = [] + return pool_instruments + ### SARDANA MACRO STUFF OFF + + def _loadSynoptic(self, conf, xmlroot): # Synoptics - SYNOPTIC = getattr(conf, 'SYNOPTIC', None) - if isinstance(SYNOPTIC, string_types): # old config file style + synoptic = getattr(conf, 'SYNOPTIC', None) + if isinstance(synoptic, string_types): # old config file style self.warning( - 'Deprecated usage of SYNOPTIC keyword (now it expects a list of paths). Please update your configuration file to: "SYNOPTIC=[\'%s\']".' % SYNOPTIC) - SYNOPTIC = [SYNOPTIC] - if SYNOPTIC is None: # we look in the xml config file if not present in the python config - SYNOPTIC = [] + 'Deprecated usage of synoptic keyword (now it expects a list of paths). Please update your configuration file to: "synoptic=[\'%s\']".' % synoptic) + synoptic = [synoptic] + if synoptic is None: # we look in the xml config file if not present in the python config + synoptic = [] node = xmlroot.find("SYNOPTIC") if (node is not None) and (node.text is not None): for child in node: s = child.get("str") # we do not append empty strings if s is not None and len(s): - SYNOPTIC.append(s) - for s in SYNOPTIC: + synoptic.append(s) + for s in synoptic: self.createMainSynoptic(s) - # Get panel descriptions from pool if required - INSTRUMENTS_FROM_POOL = getattr(conf, 'INSTRUMENTS_FROM_POOL', (self.__getVarFromXML( - xmlroot, "INSTRUMENTS_FROM_POOL", 'False').lower() == 'true')) - if INSTRUMENTS_FROM_POOL: - try: - self.splashScreen().showMessage("Gathering Instrument info from Pool") - except AttributeError: - pass - POOLINSTRUMENTS = self.createInstrumentsFromPool( - MACROSERVER_NAME) # auto create instruments from pool - else: - POOLINSTRUMENTS = [] - - ####################################################################### - # Deprecated CONSOLE command (if you need a IPython Console, just add a - # Panel with a `silx.gui.console.IPythonWidget` - # TODO: remove this block when deprecation grace time is due - CONSOLE = getattr(conf, 'CONSOLE', self.__getVarFromXML( + def _loadConsole(self, conf, xmlroot): + """ + Deprecated CONSOLE command (if you need a IPython Console, just add a + Panel with a `silx.gui.console.IPythonWidget` + """ + # TODO: remove this method when making deprecation efective + console = getattr(conf, 'CONSOLE', self.__getVarFromXML( xmlroot, "CONSOLE", [])) - if CONSOLE: + if console: self.createConsole([]) - ####################################################################### - # get custom panel descriptions from the python config file - CUSTOM_PANELS = [obj for name, obj in inspect.getmembers( + def _loadCustomPanels(self, conf, xmlroot, poolinstruments=None): + """ + get custom panel descriptions from the python config file, xml config and + create panels based on the panel descriptions + """ + custom_panels = [obj for name, obj in inspect.getmembers( conf) if isinstance(obj, PanelDescription)] - # add custom panel descriptions from xml config - panelDescriptions = xmlroot.find("PanelDescriptions") - if (panelDescriptions is not None): - for child in panelDescriptions: - if (child.tag == "PanelDescription"): - pd = PanelDescription.fromXml(etree.tostring(child)) + panel_descriptions = xmlroot.find("PanelDescriptions") + if panel_descriptions is not None: + for child in panel_descriptions: + if child.tag == "PanelDescription": + child_str = etree.tostring(child, encoding='unicode') + pd = PanelDescription.fromXml(child_str) if pd is not None: - CUSTOM_PANELS.append(pd) + custom_panels.append(pd) - # create panels based on the panel descriptions gathered before - for p in CUSTOM_PANELS + POOLINSTRUMENTS: + for p in custom_panels + poolinstruments: try: try: self.splashScreen().showMessage("Creating panel %s" % p.name) except AttributeError: pass w = p.getWidget(sdm=Qt.qApp.SDM, setModel=False) - if hasattr(w, 'setCustomWidgetMap'): + if hasattr(w, "setCustomWidgetMap"): w.setCustomWidgetMap(self.getCustomWidgetMap()) if p.model is not None: w.setModel(p.model) @@ -1189,35 +1295,38 @@ class TaurusGui(TaurusMainWindow): instrumentkey = self.IMPLICIT_ASSOCIATION # the pool instruments may change when the pool config changes, # so we do not store their config - registerconfig = p not in POOLINSTRUMENTS + registerconfig = p not in poolinstruments # create a panel self.createPanel(w, p.name, floating=p.floating, registerconfig=registerconfig, instrumentkey=instrumentkey, permanent=True) except Exception as e: - msg = 'Cannot create panel %s' % getattr( - p, 'name', '__Unknown__') + msg = "Cannot create panel %s" % getattr( + p, "name", "__Unknown__") self.error(msg) self.traceback(level=taurus.Info) - result = Qt.QMessageBox.critical(self, 'Initialization error', '%s\n\n%s' % ( + result = Qt.QMessageBox.critical(self, "Initialization error", "%s\n\n%s" % ( msg, repr(e)), Qt.QMessageBox.Abort | Qt.QMessageBox.Ignore) if result == Qt.QMessageBox.Abort: sys.exit() - # get custom toolbars descriptions from the python config file - CUSTOM_TOOLBARS = [obj for name, obj in inspect.getmembers( + def _loadCustomToolBars(self, conf, xmlroot): + """ + get custom toolbars descriptions from the python config file, xml config and + create toolbars based on the descriptions + """ + custom_toolbars = [obj for name, obj in inspect.getmembers( conf) if isinstance(obj, ToolBarDescription)] - # add custom toolbar descriptions from xml config - toolBarDescriptions = xmlroot.find("ToolBarDescriptions") - if (toolBarDescriptions is not None): - for child in toolBarDescriptions: - if (child.tag == "ToolBarDescription"): - d = ToolBarDescription.fromXml(etree.tostring(child)) + tool_bar_descriptions = xmlroot.find("ToolBarDescriptions") + if tool_bar_descriptions is not None: + for child in tool_bar_descriptions: + if child.tag == "ToolBarDescription": + child_str = etree.tostring(child, encoding='unicode') + d = ToolBarDescription.fromXml(child_str) if d is not None: - CUSTOM_TOOLBARS.append(d) + custom_toolbars.append(d) - # create toolbars based on the descriptions gathered before - for d in CUSTOM_TOOLBARS: + for d in custom_toolbars: try: try: self.splashScreen().showMessage("Creating Toolbar %s" % d.name) @@ -1236,38 +1345,41 @@ class TaurusGui(TaurusMainWindow): self.registerConfigDelegate(w, d.name) except Exception as e: - msg = 'Cannot add toolbar %s' % getattr( - d, 'name', '__Unknown__') + msg = "Cannot add toolbar %s" % getattr( + d, "name", "__Unknown__") self.error(msg) self.traceback(level=taurus.Info) - result = Qt.QMessageBox.critical(self, 'Initialization error', '%s\n\n%s' % ( + result = Qt.QMessageBox.critical(self, "Initialization error", "%s\n\n%s" % ( msg, repr(e)), Qt.QMessageBox.Abort | Qt.QMessageBox.Ignore) if result == Qt.QMessageBox.Abort: sys.exit() - CUSTOM_APPLETS = [] + def _loadCustomApplets(self, conf, xmlroot): + """ + get custom applet descriptions from the python config file, xml config and + create applet based on the descriptions + """ + custom_applets = [] # for backwards compatibility MONITOR = getattr( - conf, 'MONITOR', self.__getVarFromXML(xmlroot, "MONITOR", [])) + conf, "MONITOR", self.__getVarFromXML(xmlroot, "MONITOR", [])) if MONITOR: - CUSTOM_APPLETS.append(AppletDescription( - 'monitor', classname='TaurusMonitorTiny', model=MONITOR)) + custom_applets.append(AppletDescription( + "monitor", classname="TaurusMonitorTiny", model=MONITOR)) - # get custom applet descriptions from the python config file - CUSTOM_APPLETS += [obj for name, obj in inspect.getmembers( + custom_applets += [obj for name, obj in inspect.getmembers( conf) if isinstance(obj, AppletDescription)] - # add applet descriptions from xml config - appletDescriptions = xmlroot.find("AppletDescriptions") - if (appletDescriptions is not None): - for child in appletDescriptions: - if (child.tag == "AppletDescription"): - d = AppletDescription.fromXml(etree.tostring(child)) + applet_descriptions = xmlroot.find("AppletDescriptions") + if applet_descriptions is not None: + for child in applet_descriptions: + if child.tag == "AppletDescription": + child_str = etree.tostring(child, encoding='unicode') + d = AppletDescription.fromXml(child_str) if d is not None: - CUSTOM_APPLETS.append(d) + custom_applets.append(d) - # create applet based on the descriptions gathered before - for d in CUSTOM_APPLETS: + for d in custom_applets: try: try: self.splashScreen().showMessage("Creating applet %s" % d.name) @@ -1282,38 +1394,45 @@ class TaurusGui(TaurusMainWindow): if isinstance(w, BaseConfigurableClass): self.registerConfigDelegate(w, d.name) except Exception as e: - msg = 'Cannot add applet %s' % getattr( - d, 'name', '__Unknown__') + msg = "Cannot add applet %s" % getattr( + d, "name", "__Unknown__") self.error(msg) self.traceback(level=taurus.Info) - result = Qt.QMessageBox.critical(self, 'Initialization error', '%s\n\n%s' % ( + result = Qt.QMessageBox.critical(self, "Initialization error", "%s\n\n%s" % ( msg, repr(e)), Qt.QMessageBox.Abort | Qt.QMessageBox.Ignore) if result == Qt.QMessageBox.Abort: sys.exit() - # add external applications from both the python and the xml config - # files - EXTERNAL_APPS = [obj for name, obj in inspect.getmembers( + def _loadExternalApps(self, conf, xmlroot): + """ + add external applications from both the python and the xml config files + """ + external_apps = [obj for name, obj in inspect.getmembers( conf) if isinstance(obj, ExternalApp)] - externalAppsNode = xmlroot.find("ExternalApps") - if (externalAppsNode is not None): - for child in externalAppsNode: - if (child.tag == "ExternalApp"): - ea = ExternalApp.fromXml(etree.tostring(child)) + ext_apps_node = xmlroot.find("ExternalApps") + if ext_apps_node is not None: + for child in ext_apps_node: + if child.tag == "ExternalApp": + child_str = etree.tostring(child, encoding='unicode') + ea = ExternalApp.fromXml(child_str) if ea is not None: - EXTERNAL_APPS.append(ea) + external_apps.append(ea) - for a in EXTERNAL_APPS: + for a in external_apps: self._external_app_names.append(str(a.getAction().text())) self.addExternalAppLauncher(a.getAction()) - # get the "factory settings" filename. By default, it is called - # "default.ini" and resides in the configuration dir - INIFILE = getattr(conf, 'INIFILE', self.__getVarFromXML( + def _loadIniFile(self, conf, xmlroot): + """ + get the "factory settings" filename. By default, it is called + "default.ini" and resides in the configuration dir + """ + + ini_file = getattr(conf, 'INIFILE', self.__getVarFromXML( xmlroot, "INIFILE", "default.ini")) # if a relative name is given, the conf dir is used as the root path - iniFileName = os.path.join(self._confDirectory, INIFILE) + ini_file_name = os.path.join(self._confDirectory, ini_file) # read the settings (or the factory settings if the regular file is not # found) @@ -1324,7 +1443,7 @@ class TaurusGui(TaurusMainWindow): self.splashScreen().showMessage(msg) except AttributeError: pass - self.loadSettings(factorySettingsFileName=iniFileName) + self.loadSettings(factorySettingsFileName=ini_file_name) def setLockView(self, locked): self.setModifiableByUser(not locked) @@ -1337,14 +1456,21 @@ class TaurusGui(TaurusMainWindow): for panel in self.__panels.values(): panel.toggleViewAction().setEnabled(modifiable) panel.setFeatures(dwfeat) - for action in (self.newPanelAction, self.showAllPanelsAction, - self.hideAllPanelsAction, - self.addExternalApplicationAction, - self.removeExternalApplicationAction, - ): - action.setEnabled(modifiable) + + if self.PANELS_MENU_ENABLED: + for action in (self.newPanelAction, self.showAllPanelsAction, + self.hideAllPanelsAction, + ): + action.setEnabled(modifiable) + + if self.TOOLS_MENU_ENABLED: + for action in (self.addExternalApplicationAction, + self.removeExternalApplicationAction, + ): + action.setEnabled(modifiable) self._lockviewAction.setChecked(not modifiable) + TaurusMainWindow.setModifiableByUser(self, modifiable) def onShortMessage(self, msg): @@ -1529,6 +1655,7 @@ class TaurusGui(TaurusMainWindow): xmlroot, "PanelDescriptions") # Get all custom panels + from taurus.qt.qtgui.panel import QDoubleListDlg dlg = QDoubleListDlg(winTitle='Export Panels to XML', mainLabel='Select which of the custom panels you want to export as xml configuration', label1='Not Exported', label2='Exported', @@ -1547,7 +1674,7 @@ class TaurusGui(TaurusMainWindow): self.registerConfigDelegate(panel, name) panelxml = PanelDescription.fromPanel(panel).toXml() panelDescriptionsNode.append(etree.fromstring(panelxml)) - xml = etree.tostring(xmlroot, pretty_print=True) + xml = etree.tostring(xmlroot, pretty_print=True, encoding='unicode') # write to file while True: @@ -1605,52 +1732,34 @@ class TaurusGui(TaurusMainWindow): self.info(nfo) -#------------------------------------------------------------------------------ -def main(confname=None): +@click.command('gui') +@click.argument('confname', nargs=1, required=True) +@click.option('--safe-mode', 'safe_mode', is_flag=True, default=False, + help=('launch in safe mode (it prevents potentially problematic ' + + 'configs from being loaded)') + ) +@click.option('--ini', type=click.Path(exists=True), + metavar="INIFILE", + help=('settings file (.ini) to be loaded (defaults to ' + + '<user_config_dir>/<appname>.ini)'), + default=None + ) +def gui_cmd(confname, safe_mode, ini): + """Launch a TaurusGUI using the given CONF""" import sys import taurus - from taurus.core.util import argparse from taurus.qt.qtgui.application import TaurusApplication taurus.info('Starting execution of TaurusGui') - parser = argparse.get_taurus_parser() - parser.set_usage("%prog [options] confname") - parser.set_description("The taurus GUI application") - parser.add_option("", "--config-dir", dest="config_dir", default=None, - help="use the given configuration directory for initialization") - parser.add_option("", "--new-gui", action="store_true", dest="new_gui", default=None, - help="launch a wizard for creating a new TaurusGUI application") - parser.add_option("", "--fail-proof", action="store_true", dest="fail_proof", default=None, - help="launch in fail proof mode (it prevents potentially problematic configs from being loaded)") - - app = TaurusApplication(cmd_line_parser=parser, app_name="taurusgui", - app_version=taurus.Release.version) - args = app.get_command_line_args() - options = app.get_command_line_options() - - if options.new_gui: # launch app settings wizard instead of taurusgui - from taurus.qt.qtgui.taurusgui import AppSettingsWizard - wizard = AppSettingsWizard() - wizard.show() - sys.exit(app.exec_()) - - if confname is None: - confname = options.config_dir - - if confname is None: - if len(args) == 1: # for backwards compat, we allow to specify the confname without the "--config-dir" parameter - confname = args[0] - else: - parser.print_help(sys.stderr) - sys.exit(1) + app = TaurusApplication(cmd_line_parser=None, app_name="taurusgui") - if options.fail_proof: + if safe_mode: configRecursionDepth = 0 else: configRecursionDepth = None - gui = TaurusGui(None, confname=confname, + gui = TaurusGui(None, confname=confname, settingsname=ini, configRecursionDepth=configRecursionDepth) gui.show() @@ -1660,6 +1769,27 @@ def main(confname=None): sys.exit(ret) +@click.command('newgui') +# @click.option('--stub', 'stub_name', +# metavar="NAME", +# default=None, +# help='Create an empty stub of gui with the given NAME' +# ) +def newgui_cmd(): + """Create a new TaurusGui""" + import sys + from taurus.qt.qtgui.application import TaurusApplication + + app = TaurusApplication(cmd_line_parser=None, app_name="newgui") + + # if stub_name is not None: + # pass # TODO + + from taurus.qt.qtgui.taurusgui import AppSettingsWizard + wizard = AppSettingsWizard() + wizard.show() + sys.exit(app.exec_()) + + if __name__ == "__main__": - main() - # xmlTest() + gui_cmd() diff --git a/lib/taurus/qt/qtgui/taurusgui/utils.py b/lib/taurus/qt/qtgui/taurusgui/utils.py index 6812fd31..b224027c 100644 --- a/lib/taurus/qt/qtgui/taurusgui/utils.py +++ b/lib/taurus/qt/qtgui/taurusgui/utils.py @@ -264,7 +264,7 @@ class TaurusGuiComponentDescription(object): model = etree.SubElement(root, "model") model.text = self._model - return etree.tostring(root, pretty_print=True) + return etree.tostring(root, pretty_print=True, encoding='unicode') @staticmethod def fromXml(xmlstring): diff --git a/lib/taurus/qt/qtgui/test/base.py b/lib/taurus/qt/qtgui/test/base.py index 678e2762..7e8b4645 100644 --- a/lib/taurus/qt/qtgui/test/base.py +++ b/lib/taurus/qt/qtgui/test/base.py @@ -64,10 +64,9 @@ class BaseWidgetTestCase(object): from taurus.core.util.log import _DEPRECATION_COUNT self._depCounter = _DEPRECATION_COUNT self._depCounter.clear() - app = TaurusApplication.instance() if app is None: - app = TaurusApplication([]) + app = TaurusApplication([], cmd_line_parser=None) self._app = app if self._klass is not None: diff --git a/lib/taurus/qt/qtgui/util/qdraganddropdebug.py b/lib/taurus/qt/qtgui/util/qdraganddropdebug.py index 5d3d9ce7..90a462c5 100644 --- a/lib/taurus/qt/qtgui/util/qdraganddropdebug.py +++ b/lib/taurus/qt/qtgui/util/qdraganddropdebug.py @@ -59,7 +59,7 @@ if __name__ == '__main__': import sys from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) w = DropDebugger() w.show() sys.exit(app.exec_()) diff --git a/lib/taurus/qt/qtgui/util/tauruswidgettree.py b/lib/taurus/qt/qtgui/util/tauruswidgettree.py index 77948d8a..57517dd9 100644 --- a/lib/taurus/qt/qtgui/util/tauruswidgettree.py +++ b/lib/taurus/qt/qtgui/util/tauruswidgettree.py @@ -221,7 +221,7 @@ def build_gui(): def main(): from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication() + app = TaurusApplication(cmd_line_parser=None) w = build_gui() tree = TreeQObjectWidget(qobject_root=w) diff --git a/lib/taurus/qt/qtgui/util/ui.py b/lib/taurus/qt/qtgui/util/ui.py index b4bc93a2..31489759 100644 --- a/lib/taurus/qt/qtgui/util/ui.py +++ b/lib/taurus/qt/qtgui/util/ui.py @@ -176,7 +176,7 @@ def UILoadable(klass=None, with_ui=None): def main(): from taurus.qt.qtgui.application import TaurusApplication - app = TaurusApplication([]) + app = TaurusApplication([], cmd_line_parser=None) @UILoadable(with_ui="ui") class A(Qt.QWidget): diff --git a/lib/taurus/qt/qtgui/util/validator.py b/lib/taurus/qt/qtgui/util/validator.py index 92f875eb..92f875eb 100755..100644 --- a/lib/taurus/qt/qtgui/util/validator.py +++ b/lib/taurus/qt/qtgui/util/validator.py |