# Source code for taurus.qt.qtgui.util.taurusaction

    #!/usr/bin/env python

    # ###########################################################################
    #
    # 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/>.
    #
    # ###########################################################################

    """This module is designed to provide a library of taurus Qt actions
    """

    import os
    import xml.dom.minidom

    from functools import partial

    from taurus import getSchemeFromName
    from taurus.external.qt import Qt
    from taurus.qt.qtcore.configuration import BaseConfigurableClass

    __docformat__ = "restructuredtext"

    class ExternalAppAction(Qt.QAction, BaseConfigurableClass):
        """An specialized QAction for launching external applications

        Signals: apart of those from QAction, it emits a  "cmdArgsChanged" signal
        with the current cmdArgs list as its argument.
        """

        DEFAULT_ICON_NAME = "application-x-executable"

        cmdArgsChanged = Qt.pyqtSignal(list)

        def __init__(
            self, cmdargs, text=None, icon=None, parent=None, interactive=True
        ):
            """creator

            :param cmdargs: A list of strings to be passed to
                :meth:`subprocess.Popen` for launching the external application. It
                can also be a single string containing a command. See
                :meth:`setCmdArgs`
            :type cmdargs: list<str> or str
            :param text: see :class:`Qt.QAction`
            :type text: str
            :param icon: see :class:`Qt.QAction`
            :type icon: QIcon or any other object that can be passed to QIcon
                creator
            :param parent: The parent object
            :type parent: QObject
            """
            if isinstance(cmdargs, str):
                import shlex

                cmdargs = shlex.split(str(cmdargs))
            self.path = os.path.realpath(cmdargs and cmdargs[0] or "")
            if text is None:
                text = os.path.basename(cmdargs and cmdargs[0] or "")
            if icon is None:
                icon = Qt.QIcon.fromTheme(self.DEFAULT_ICON_NAME)
            elif isinstance(icon, str):
                tmp = Qt.QIcon.fromTheme(icon)
                if not tmp.isNull():
                    icon = tmp

            Qt.QAction.__init__(self, Qt.QIcon(icon), text, parent)
            BaseConfigurableClass.__init__(self)
            self.interactive = interactive
            self._process = []
            self.setCmdArgs(cmdargs)
            self.triggered.connect(partial(self.actionTriggered, args=None))
            self.setToolTip("Launches %s (external application)" % text)
            self.registerConfigProperty(self.cmdArgs, self.setCmdArgs, "cmdArgs")

        def setCmdArgs(self, cmdargs, emitsignal=True):
            """Sets the command args for executing this external application.

            It emits the "cmdArgsChanged" signal with the new cmdArgs list

            :param cmdargs: A list of strings to be passed to
                :meth:`subprocess.Popen` for launching the external application. It
                can also be a string containing a command, which will be
                automatically converted to a list
            :type cmdargs: list<str> or str
            """
            if isinstance(cmdargs, str):
                import shlex

                cmdargs = shlex.split(str(cmdargs))
            self.__cmdargs = cmdargs
            if emitsignal:
                self.cmdArgsChanged.emit(self.__cmdargs)

        def cmdArgs(self):
            return self.__cmdargs

        @Qt.pyqtSlot(name="triggered", result=bool)
        def actionTriggered(self, args=None):
            """launches the external application as a subprocess"""
            import subprocess

            try:
                if args is not None:
                    if isinstance(args, str):
                        import shlex

                        args = shlex.split(str(args))
                    args = self.cmdArgs() + args
                else:
                    args = self.cmdArgs()
                if any(args):
                    self._process.append(subprocess.Popen(args))
                    self._process = [p for p in self._process if p.poll() is None]
                    return True
                else:
                    return False
            except OSError:
                err = "Error launching %s" % str(self.text())
                msg = (
                    "Cannot launch application:\n"
                    + " ".join(self.__cmdargs)
                    + "\nHint: Check that %s is installed and in the path"
                    % str(self.text())
                )
                if self.interactive:
                    Qt.QMessageBox.warning(self.parentWidget(), err, msg)
                from taurus.core.util.log import Logger

                Logger().warning("%s:\n%s" % (err, msg))
                return False

        def kill(self):
            # Kills all processes opened by this application
            [p.kill() for p in self._process]

        def check(self):
            """Returns True if the application is available for executing

            :return:
            :rtype: bool
            """
            # raise NotImplementedError  #@todo: implement a checker (check if
            # self.cmdargs[0] is in the execution path and is executable
            path = os.path.realpath(self.cmdArgs()[0])
            try:
                os.stat(path)
                return True
            except Exception:
                return False

    class TaurusAction(Qt.QAction):
        """Base class for Taurus Actions"""

        def __init__(self, parent):
            import taurus.qt.qtgui.base

            if (
                (parent is None)
                or (not isinstance(parent, Qt.QWidget))
                or (
                    not isinstance(
                        parent, taurus.qt.qtgui.base.TaurusBaseComponent
                    )
                )
            ):
                raise RuntimeError(
                    "Invalid parent. Must be a valid Taurus widget."
                )

            Qt.QAction.__init__(self, parent)

            parent.modelChanged.connect(self.modelChanged)
            self.triggered.connect(self.actionTriggered)

            self.update()

        def update(self):
            model = self.parent().getModelObj()
            self.setDisabled(model is None)

        @Qt.pyqtSlot("QString")
        def modelChanged(self, modelName):
            self.update()

        @Qt.pyqtSlot(name="triggered")
        def actionTriggered(self):
            pass

    class SeparatorAction(TaurusAction):

        menuID = "_Separator_"

        def __init__(self, parent=None):
            Qt.QAction.__init__(self, parent)
            self.setSeparator(True)

    class AttributeHistoryAction(TaurusAction):

        menuID = "AttrHistory"

        def __init__(self, parent=None):
            TaurusAction.__init__(self, parent)
            self.setText("Show history...")

        def actionTriggered(self):
            dialog = Qt.QDialog()
            dialog.exec_()

    class AttributeAllConfigAction(TaurusAction):

        menuID = "AttrConfig"

        def __init__(self, parent=None):
            TaurusAction.__init__(self, parent)
            self.setText("All...")

        def actionTriggered(self):
            taurus_widget = self.parent()
            from taurus.qt.qtgui.dialog.taurusconfigurationdialog import (
                TaurusConfigurationDialog,
            )

            d = TaurusConfigurationDialog(taurus_widget)
            d.setModel(taurus_widget.getModelName())
            d.exec_()

    class AttributeMonitorDeviceAction(TaurusAction):

        menuID = "MonitorDevice"

        def __init__(self, parent=None):
            TaurusAction.__init__(self, parent)
            self.setText("&Monitor device ...")

        def actionTriggered(self):
            taurus_widget = self.parent()
            model_name = taurus_widget.getModelName()
            w = model_name.split("/")
            if len(w) == 3:
                dev_name = model_name
            elif len(w) == 4:
                dev_name = w[0] + "/" + w[1] + "/" + w[2]
            elif len(w) == 5:  # FB: If the first parameter is the database
                dev_name = w[1] + "/" + w[2] + "/" + w[3]
            else:
                return

            cmd = "atkpanel " + dev_name + " &"
            os.system(cmd)

    class AttributeImageDisplayAction(TaurusAction):

        menuID = "ImageDisplay"

        def __init__(self, parent=None):
            TaurusAction.__init__(self, parent)
            self.setText("&Image Display ...")

        def actionTriggered(self):
            taurus_widget = self.parent()
            model_name = taurus_widget.getModelName()
            w = model_name.split("/")
            if len(w) == 3:
                dev_name = model_name
            elif len(w) == 4:
                dev_name = w[0] + "/" + w[1] + "/" + w[2]
            else:
                return

            attr_name = dev_name + "/Image"

            import qub

            im = qub._TaurusQubDataImageDisplay(data=attr_name)
            im.show()