コード例 #1
0
 def _setRunning(self):
     '''update button'''
     self.btn_run_now.setChecked(True)
     self.btn_run_now.setText('Stop')
     self.display.workspace.gui.undoRedo.is_active = False
     # TODO: remove try... if .display if not a weakref.proxy any more
     try:
         d = self.display.__repr__.__self__
     except:
         d = self.display
     # SHOW RUN INDICATOR
     self._runIndicator = CircleWidget(d)
     self._runIndicator.move(2, 2)
     self._runIndicator.show()
コード例 #2
0
ファイル: Automation.py プロジェクト: comgram/dataArtist
 def _setRunning(self):
     '''update button'''
     self.btn_run_now.setChecked(True)
     self.btn_run_now.setText('Stop')
     self.display.workspace.gui.undoRedo.is_active = False
     #TODO: remove try... if .display if not a weakref.proxy any more
     try:
         d = self.display.__repr__.__self__
     except:
         d = self.display
     #SHOW RUN INDICATOR
     self._runIndicator = CircleWidget(d)
     self._runIndicator.move(2,2)
     self._runIndicator.show()
コード例 #3
0
ファイル: Automation.py プロジェクト: comgram/dataArtist
class Automation(QtGui.QWidget):
    '''
    Widget for easy automation within dataArtist, providing:
    
    * On/Of switch
    * 'Collect' button to grab the address of tool buttons and it's parameters
    * 'Import' list to load saved scripts
    * Multiple script editors listed as Tabs
    * 'Run on new input' - Activate active script as soon as the input has changed
    * 'Run' - run active script now 
    '''
    
    def __init__(self, display, splitter):
        QtGui.QWidget.__init__(self)
        
        self.display = display
        display.sigLayerChanged.connect(self.toggleDataChanged)
        display.sigNewLayer.connect(self.toggleNewData)

        self.splitter = splitter

        refreshR = 20
        
        self._collect = False
        self._activeWidgets = []
        #BUTTON: OF/OFF
        self.btn_show = QtGui.QRadioButton('Console')
        f=self.btn_show.font()
        f.setBold(True)
        self.btn_show.setFont(f)
        self.btn_show.clicked.connect(self._toggleShow)
        #COMBOBOX: IMPORT
        self.combo_import = QtGui.QComboBox()
        self.combo_import.addItems((
                    '<import>', 
                    'from file'))
        self.combo_import.addItems(
                #don't show '.py' and hide __init__.py
                [x[:-3] for x in SPRIPT_PATH.listdir() 
                    if (x[0] != '_' and x.endswith('.py'))]) 
        self.combo_import.currentIndexChanged.connect(self._importScript)
        #BUTTON: COLLECT
        self.btn_collect= QtGui.QPushButton('Collect')
        self.btn_collect.setToolTip('click on all tool parameters you want to change during the batch process')
        self.btn_collect.setCheckable(True)
        self.btn_collect.clicked.connect(self.collectWidgets)
        #TABWIDGET: SCRIPT 
        self.tabs = FwTabWidget()
        self.tabs.hide()
        self.tabs.setTabsAddable(True)
        self.tabs.setTabsClosable(True)
        self.tabs.setTabsRenamable(True)

        self.tabs.defaultTabWidget = lambda: ScriptTab(self, refreshR)
        self.tabs.addEmptyTab('New')
        #BUTTON: RUN AT NEW INPUT
        self.label_run_on = QtGui.QLabel('Activate on')
        self.cb_run_on = QtGui.QComboBox()
        self.cb_run_on.addItems(['-', 'New Data', 'Data Changed'])
        
        #SPINBOX REFRESHRATE
        self.label_refresh = QtGui.QLabel('Refresh rate:')
        self.sb_refreshrate = QtGui.QSpinBox()
        self.sb_refreshrate.setSuffix(" Hz")
        self.sb_refreshrate.setMinimum(0)
        self.sb_refreshrate.setMaximum(100)
        self.sb_refreshrate.setValue(refreshR)
        self.sb_refreshrate.valueChanged.connect(
            lambda hz: self.tabs.currentWidget().thread.setRefreshrate(hz))
        #BUTTON: RUN
        self.btn_run_now = QtGui.QPushButton('Run')
        self.btn_run_now.setCheckable(True)
        self.btn_run_now.clicked.connect(self.toggle)
        #LAYOUT
        layout = QtGui.QVBoxLayout()
        layout.setAlignment(QtCore.Qt.AlignTop)
        layout.setMargin(0)
        self.setLayout(layout)
            #top layout
        hl = QtGui.QHBoxLayout()
        hl.addWidget(self.btn_show)
        hl.addWidget(self.btn_collect)
            #fill layout
        layout.addLayout(hl)
        layout.addWidget(self.combo_import)
        layout.addWidget(self.tabs)
        
        hl2 = QtGui.QHBoxLayout()
        hl2.addWidget(self.label_run_on)
        hl2.addWidget(self.cb_run_on)
        hl2.addWidget(self.label_refresh)
        hl2.addWidget(self.sb_refreshrate)
        hl2.insertStretch(1,0)
        hl2.insertStretch(2,0)
        layout.addLayout(hl2)
        layout.addWidget(self.btn_run_now)

        self._toggleShow(False) #automation disabled by default


    def checkWidgetIsActive(self, widget):
        #bring widget into list of updated widgets
        #if not there already
        a = self._activeWidgets
        if widget not in a:
            a.append(widget)
        
        
    def saveState(self):
        state={}
        #BUTTONS
        state['active'] = self.btn_show.isChecked()
        state['collect'] = self.btn_collect.isChecked()
        #l['runOnNewInput'] = self.btn_run_new.isChecked()
        state['runOn'] = unicode(self.cb_run_on.currentText())
        state['tabTitles'] = [unicode(self.tabs.tabText(tab)) for tab in self.tabs]
        #SCRIPTS
        ss = state['scripts'] = []
        for tab in self.tabs:
            ss.append(tab.editor.toPlainText())
#             session.addContentToSave(tab.editor.toPlainText(), 
#                             *path+('scripts', '%s.txt' %n))
        #-->
#         session.addContentToSave(l, *path+('automation.txt',))
        return state

        
    def restoreState(self, state):
#         l =  eval(session.getSavedContent(*path +('automation.txt',) ) )
        #BUTTONS
        self.btn_show.setChecked(state['active'])
        self._toggleShow(state['active'])
        self.btn_collect.setChecked(state['collect'])
        #self.btn_run_new.setChecked(l['runOnNewInput'])
        self.cb_run_on.setCurrentIndex([self.cb_run_on.itemText(i) 
                for i in range(self.cb_run_on.count())].index(
                    state['runOn']))
        #SCRIPTS
        self.tabs.clear()
        ss = state['scripts']
        for n, title in enumerate(state['tabTitles']):
            tab = self.tabs.addEmptyTab(title)
#             txt = ss[n]#session.getSavedContent(*path+('scripts', '%s.txt' %n))
            tab.editor.setPlainText(ss[n])
    
        
    def collectWidgets(self):
        '''
        Get a Tool button or a parameter within the tools menu
        and add it to the active script
        '''
        #TOGGLE BETWEEN NORMAL- AND PointingHandCursor
        self._collect = not self._collect
        if self._collect:
            QtGui.QApplication.setOverrideCursor(QtGui.QCursor(
                                                        QtCore.Qt.PointingHandCursor))
        else:
            QtGui.QApplication.restoreOverrideCursor()
        #TOGGLE BUTTON
        self.btn_collect.setChecked(self._collect)
        #add chosen widget to active script:  
        fn = lambda widget: self.tabs.currentWidget().addTool(widget)
        for tool in self.display.widget.tools.itervalues():
            #TOOLS:
            tool.returnToolOnClick(self._collect, fn)
            #TOOL-PARAMETERS:
            if isinstance(tool.menu(), ParameterMenu):
                tool.menu().pTree.returnParameterOnKlick(self._collect, fn)


    def _importScript(self, index):
        '''
        Open a file, read it's content and add it to the active script tab
        '''
        self.combo_import.setCurrentIndex(0)
        if index == 0:# '<import>' placeholder within the comboBox
            return
        if index == 1: # import from file
            f = self.display.workspace.gui.dialogs.getOpenFileName()
            if f is not None and f.isfile():
                tab = self.tabs.addEmptyTab('file')
                with open(f, 'r') as r:
                    tab.editor.appendPlainText(r.read()) 
        else:
            # import one of the examples scripts
            tab = self.tabs.addEmptyTab('ex%s' %str(index-1))
            tab.editor.appendPlainText(
                        open(SPRIPT_PATH.join(
                             str(self.combo_import.itemText(index)))+'.py','r').read())


    def _updateWidget(self):
        '''
        update all active display widgets
        '''
        for widget in self._activeWidgets:
            try:
                widget.updateView(force=True)
            except Exception:
                traceback.print_exc() 


    def _toggleShow(self, show):
        '''
        Show/hide all widgets within Automation except of the on/off switch
        And move the horizontal splitter according to the space needed
        '''
        s = self.splitter
        l = s.sizes()
        minSize = 7.0
        i = s.indexOf(self)
        
        if show:
            self.tabs.show() 
            self.btn_run_now.show()
            self.btn_collect.show()
            self.label_run_on.show()
            self.cb_run_on.show()
            self.combo_import.show()
            self.label_refresh.show()
            self.sb_refreshrate.show()
            # move splitter:
                # assume equal sizes for all to calc the splitter size
            s.setSizes(np.ones(len(l))*np.mean(l))
        else:
            self.tabs.hide()
            self.btn_run_now.hide()
            self.btn_collect.hide()
            self.label_run_on.hide()
            self.cb_run_on.hide()
            self.combo_import.hide()
            self.label_refresh.hide()
            self.sb_refreshrate.hide()
            # move splitter:
                # smallest possible size of batchTab 
            if l:
                a = (l[i] - minSize) / len(l)
                for n,y in enumerate(l):
                    if n != i:
                        l[n] = y+a
                    else:
                        l[n] = minSize
                s.setSizes(l)

      
    def _setRunning(self):
        '''update button'''
        self.btn_run_now.setChecked(True)
        self.btn_run_now.setText('Stop')
        self.display.workspace.gui.undoRedo.is_active = False
        #TODO: remove try... if .display if not a weakref.proxy any more
        try:
            d = self.display.__repr__.__self__
        except:
            d = self.display
        #SHOW RUN INDICATOR
        self._runIndicator = CircleWidget(d)
        self._runIndicator.move(2,2)
        self._runIndicator.show()

       
    def _setDone(self):
        '''update button'''
        self.btn_run_now.setChecked(False)
        self.btn_run_now.setText('Start')
        self.display.workspace.gui.undoRedo.is_active = True
        if hasattr(self, '_runIndicator'):
            self._runIndicator.close()
            del self._runIndicator


    def toggle(self):
        '''
        Start/Stop the active script
        '''
        tab = self.tabs.currentWidget()
        #STOP
        if self.btn_run_now.text() == 'Stop':
            tab.thread.kill()
            return
        #START 
        self.display.backupChangedLayer(changes='Script <%s>' %self.tabs.tabText(tab))
        self._activeWidgets = [self.display.widget]

        tab.thread.start()


    def toggleNewData(self):
        '''
        toggle run settings allow running for new data
        '''
        if self.btn_show.isChecked() and self.cb_run_on.currentIndex() == 1:#=new data
            self.toggle()


    def toggleDataChanged(self):
        '''
        toggle run settings allow running for data changed
        '''
        if self.btn_show.isChecked() and self.cb_run_on.currentIndex() == 2:#=data changed
            self.toggle()
コード例 #4
0
class Automation(QtWidgets.QWidget):
    '''
    Widget for easy automation within dataArtist, providing:

    * On/Of switch
    * 'Collect' button to grab the address of tool buttons and it's parameters
    * 'Import' list to load saved scripts
    * Multiple script editors listed as Tabs
    * 'Run on new input'
        - Activate active script as soon as the input has changed
    * 'Run' - run active script now
    '''
    def __init__(self, display, splitter):
        QtWidgets.QWidget.__init__(self)

        self.display = display
        display.sigLayerChanged.connect(self.toggleDataChanged)
        display.sigNewLayer.connect(self.toggleNewData)
        self.setMinimumHeight(30)

        self.splitter = splitter

        self._collect = False
        self._activeWidgets = []

        # LAYOUT
        layout = QtWidgets.QVBoxLayout()
        layout.setAlignment(QtCore.Qt.AlignTop)
        # setMargin removed. obsolete, doesn't do anything, not even in PyQt4
        self.setLayout(layout)
        self._hl = QtWidgets.QHBoxLayout()
        layout.addLayout(self._hl)

        # BUTTON: show/hide 'Scripts'
        self.btn_scripts = QtWidgets.QRadioButton('Scripts')
        f = self.btn_scripts.font()
        f.setBold(True)
        self.btn_scripts.setFont(f)
        self.btn_scripts.clicked.connect(self._uncheckConsole)
        self.btn_scripts.clicked.connect(self._toggleScriptsFirstTime)
        self.btn_scripts.clicked.connect(self.updateSize)
        self._hl.addWidget(self.btn_scripts)

        # BUTTON: show/hide 'Console'
        self.btn_console = QtWidgets.QRadioButton('Console')
        f = self.btn_console.font()
        f.setBold(True)
        self.btn_console.setFont(f)
        self.btn_console.clicked.connect(self._uncheckScripts)
        self.btn_console.clicked.connect(self._toggleConsoleFirstTime)
        self.btn_console.clicked.connect(self.updateSize)

        self._hl.addWidget(self.btn_console)

        g = QtWidgets.QButtonGroup(self)
        g.setExclusive(False)
        g.addButton(self.btn_scripts)
        g.addButton(self.btn_console)

        self.splitter.setStretchFactor(0, 0)

        self.cb_run_on = QtWidgets.QComboBox()
        self.cb_run_on.addItems(['-', 'New Data', 'Data Changed'])

        self.tabs = FwTabWidget()
        self.tabs.hide()
        self.tabs.setTabsAddable(True)
        self.tabs.setTabsClosable(True)
        self.tabs.setTabsRenamable(True)

    def _uncheckScripts(self, show):
        if show and self.btn_scripts.isChecked():
            self._toggleScripts(False)
            self.btn_scripts.setChecked(False)

    def _uncheckConsole(self, show):
        if show and self.btn_console.isChecked():
            self._toggleConsole(False)
            self.btn_console.setChecked(False)

    def _toggleConsoleFirstTime(self):

        txt = '''This is a Python {} console.
        it accepts ...
        * all built-in functions, like 'dir'
        * already imported modules, like 'np', for numpy
        * special dataArtist functions, like d', d.l, d.l0,...
        '''.format(platform.python_version())

        namespace = _ExecGlobalsDict(self.display)

        self.console = console.ConsoleWidget(namespace=namespace, text=txt)
        self.console.ui.exceptionBtn.hide()
        self.console.input.sigExecuteCmd.connect(
            self.display.widget.updateView)
        self.layout().addWidget(self.console)

        # update connections:
        self.btn_console.clicked.disconnect(self._toggleConsoleFirstTime)
        self.btn_console.clicked.connect(self._toggleConsole)

    def _toggleConsole(self, show):
        self.console.setVisible(show)

    def _toggleScriptsFirstTime(self):
        # build scripts layout
        refreshR = 20

        # COMBOBOX: IMPORT
        self.combo_import = QtWidgets.QComboBox()
        self.combo_import.addItems(('<import>', 'from file'))
        self.combo_import.addItems(
            # don't show '.py' and hide __init__.py
            [
                x[:-3] for x in SPRIPT_PATH.listdir()
                if (x[0] != '_' and x.endswith('.py'))
            ])
        self.combo_import.currentIndexChanged.connect(self._importScript)
        # BUTTON: COLLECT
        self.btn_collect = QtWidgets.QPushButton('Collect')
        self.btn_collect.setToolTip(
            'click on all tool parameters you want to change during the batch process'
        )
        self.btn_collect.setCheckable(True)
        self.btn_collect.clicked.connect(self.collectTools)
        # TABWIDGET: SCRIPT
        self.tabs.defaultTabWidget = lambda: ScriptTab(self, refreshR)
        self.tabs.addEmptyTab('New')
        # BUTTON: RUN AT NEW INPUT
        self.label_run_on = QtWidgets.QLabel('Activate on')

        # SPINBOX REFRESHRATE
        self.label_refresh = QtWidgets.QLabel('Refresh rate:')
        self.sb_refreshrate = QtWidgets.QSpinBox()
        self.sb_refreshrate.setSuffix(" Hz")
        self.sb_refreshrate.setMinimum(0)
        self.sb_refreshrate.setMaximum(100)
        self.sb_refreshrate.setValue(refreshR)
        self.sb_refreshrate.valueChanged.connect(
            lambda hz: self.tabs.currentWidget().thread.setRefreshrate(hz))
        # BUTTON: RUN
        self.btn_run_now = QtWidgets.QPushButton('Run')
        self.btn_run_now.setCheckable(True)
        self.btn_run_now.clicked.connect(self.toggle)

        self._hl.addWidget(self.btn_collect)
        l = self.layout()
        l.addWidget(self.combo_import)
        l.addWidget(self.tabs)

        self.tabs.show()

        hl2 = QtWidgets.QHBoxLayout()
        hl2.addWidget(self.label_run_on)
        hl2.addWidget(self.cb_run_on)
        hl2.addWidget(self.label_refresh)
        hl2.addWidget(self.sb_refreshrate)
        hl2.insertStretch(1, 0)
        hl2.insertStretch(2, 0)
        l.addLayout(hl2)
        l.addWidget(self.btn_run_now)

        # update connections:
        self.btn_scripts.clicked.disconnect(self._toggleScriptsFirstTime)
        self.btn_scripts.clicked.connect(self._toggleScripts)

    def checkWidgetIsActive(self, widget):
        # bring widget into list of updated widgets
        # if not there already
        a = self._activeWidgets
        if widget not in a:
            a.append(widget)

    def saveState(self):
        state = {
            'scriptOn': self.btn_scripts.isChecked(),
            'consoleOn': self.btn_console.isChecked(),
            'runOn': str(self.cb_run_on.currentText()),
            'tabTitles': [str(self.tabs.tabText(tab)) for tab in self.tabs],
            'curTab': self.tabs.currentIndex()
        }
        # SCRIPTS
        ss = state['scripts'] = []
        for tab in self.tabs:
            ss.append(tab.editor.toPlainText())
        return state

    def restoreState(self, state):
        # BUTTONS
        self.btn_scripts.setChecked(state['scriptOn'])
        #         self._toggleScripts(state['active'])
        self.btn_console.setChecked(state['consoleOn'])
        # self.btn_run_new.setChecked(l['runOnNewInput'])
        self.cb_run_on.setCurrentIndex([
            self.cb_run_on.itemText(i) for i in range(self.cb_run_on.count())
        ].index(state['runOn']))
        # SCRIPTS
        ss = state['scripts']
        if ss and not hasattr(self, 'combo_import'):
            self._toggleScriptsFirstTime()
        self.tabs.clear()
        for n, title in enumerate(state['tabTitles']):
            tab = self.tabs.addEmptyTab(title)
            tab.editor.setPlainText(ss[n])
        self.tabs.setCurrentIndex(state['curTab'])

    def collectTools(self):
        '''
        Get a Tool button or a parameter within the tools menu
        and add it to the active script
        '''
        # TOGGLE BETWEEN NORMAL- AND PointingHandCursor
        self._collect = not self._collect
        if self._collect:
            QtWidgets.QApplication.setOverrideCursor(
                QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        else:
            QtWidgets.QApplication.restoreOverrideCursor()
        # TOGGLE BUTTON
        self.btn_collect.setChecked(self._collect)

        # add chosen widget to active script:
        def fn(tool):
            return self.tabs.currentWidget().addTool(tool)

        for tool in self.display.widget.tools.values():
            # TOOLS:
            tool.returnToolOnClick(self._collect, fn)
            # TOOL-PARAMETERS:
            if isinstance(tool.menu(), ParameterMenu):
                tool.menu().pTree.returnParameterOnClick(self._collect, fn)

    def _importScript(self, index):
        '''
        Open a file, read it's content and add it to the active script tab
        '''
        self.combo_import.setCurrentIndex(0)
        if index == 0:  # '<import>' placeholder within the comboBox
            return
        if index == 1:  # import from file
            f = self.display.workspace.gui.dialogs.getOpenFileName()
            if f is not None and f.isfile():
                tab = self.tabs.addEmptyTab('file')
                with open(f, 'r') as r:
                    tab.editor.appendPlainText(r.read())
        else:
            # import one of the examples scripts
            tab = self.tabs.addEmptyTab('ex%s' % str(index - 1))
            tab.editor.appendPlainText(
                open(
                    SPRIPT_PATH.join(str(self.combo_import.itemText(index))) +
                    '.py', 'r').read())

    def _updateWidget(self):
        '''
        update all active display widgets
        '''
        for widget in self._activeWidgets:
            try:
                widget.updateView(force=True)
            except Exception:
                traceback.print_exc()

    def minimumHeight(self):
        return QtWidgets.QWidget.minimumHeight(self) + 10

    def updateSize(self):
        s = self.splitter
        l = s.sizes()
        if self.btn_scripts.isChecked() or self.btn_console.isChecked():
            # resize to 50%
            s.setSizes(np.ones(len(l)) * np.mean(l))
            self.splitter.setStretchFactor(0, 1)
        else:
            minSize = self.minimumHeight()
            l[1] = max(0, np.sum(l) - minSize)
            l[0] = minSize

            s.setSizes(l)
            self.splitter.setStretchFactor(0, 0)

    def _toggleScripts(self, show):
        '''
        Show/hide all widgets within Automation except of the on/off switch
        And move the horizontal splitter according to the space needed
        '''
        if show:
            self.tabs.show()
            self.btn_run_now.show()
            self.btn_collect.show()
            self.label_run_on.show()
            self.cb_run_on.show()
            self.combo_import.show()
            self.label_refresh.show()
            self.sb_refreshrate.show()
        else:
            self.tabs.hide()
            self.btn_run_now.hide()
            self.btn_collect.hide()
            self.label_run_on.hide()
            self.cb_run_on.hide()
            self.combo_import.hide()
            self.label_refresh.hide()
            self.sb_refreshrate.hide()

    def _setRunning(self):
        '''update button'''
        self.btn_run_now.setChecked(True)
        self.btn_run_now.setText('Stop')
        self.display.workspace.gui.undoRedo.is_active = False
        # TODO: remove try... if .display if not a weakref.proxy any more
        try:
            d = self.display.__repr__.__self__
        except:
            d = self.display
        # SHOW RUN INDICATOR
        self._runIndicator = CircleWidget(d)
        self._runIndicator.move(2, 2)
        self._runIndicator.show()

    def _setDone(self):
        '''update button'''
        self.btn_run_now.setChecked(False)
        self.btn_run_now.setText('Start')
        self.display.workspace.gui.undoRedo.is_active = True
        if hasattr(self, '_runIndicator'):
            self._runIndicator.close()
            del self._runIndicator

    def toggle(self):
        '''
        Start/Stop the active script
        '''
        tab = self.tabs.currentWidget()
        # STOP
        if self.btn_run_now.text() == 'Stop':
            tab.thread.kill()
            return
        # START
        self.display.backupChangedLayer(changes='Script <%s>' %
                                        self.tabs.tabText(tab))
        self._activeWidgets = [self.display.widget]

        tab.thread.start()

    def toggleNewData(self):
        '''
        toggle run settings allow running for new data
        '''
        if self.btn_scripts.isChecked() and self.cb_run_on.currentIndex() == 1:
            self.toggle()

    def toggleDataChanged(self):
        '''
        toggle run settings allow running for data changed
        '''
        if self.btn_scripts.isChecked() and self.cb_run_on.currentIndex() == 2:
            self.toggle()
コード例 #5
0
class Automation(QtGui.QWidget):
    '''
    Widget for easy automation within dataArtist, providing:
    
    * On/Of switch
    * 'Collect' button to grab the address of tool buttons and it's parameters
    * 'Import' list to load saved scripts
    * Multiple script editors listed as Tabs
    * 'Run on new input' - Activate active script as soon as the input has changed
    * 'Run' - run active script now 
    '''
    def __init__(self, display, splitter):
        QtGui.QWidget.__init__(self)

        self.display = display
        display.sigLayerChanged.connect(self.toggleDataChanged)
        display.sigNewLayer.connect(self.toggleNewData)

        self.splitter = splitter

        refreshR = 20

        self._collect = False
        self._activeWidgets = []
        #BUTTON: OF/OFF
        self.btn_show = QtGui.QRadioButton('Console')
        f = self.btn_show.font()
        f.setBold(True)
        self.btn_show.setFont(f)
        self.btn_show.clicked.connect(self._toggleShow)
        #COMBOBOX: IMPORT
        self.combo_import = QtGui.QComboBox()
        self.combo_import.addItems(('<import>', 'from file'))
        self.combo_import.addItems(
            #don't show '.py' and hide __init__.py
            [
                x[:-3] for x in SPRIPT_PATH.listdir()
                if (x[0] != '_' and x.endswith('.py'))
            ])
        self.combo_import.currentIndexChanged.connect(self._importScript)
        #BUTTON: COLLECT
        self.btn_collect = QtGui.QPushButton('Collect')
        self.btn_collect.setToolTip(
            'click on all tool parameters you want to change during the batch process'
        )
        self.btn_collect.setCheckable(True)
        self.btn_collect.clicked.connect(self.collectWidgets)
        #TABWIDGET: SCRIPT
        self.tabs = FwTabWidget()
        self.tabs.hide()
        self.tabs.setTabsAddable(True)
        self.tabs.setTabsClosable(True)
        self.tabs.setTabsRenamable(True)

        self.tabs.defaultTabWidget = lambda: ScriptTab(self, refreshR)
        self.tabs.addEmptyTab('New')
        #BUTTON: RUN AT NEW INPUT
        self.label_run_on = QtGui.QLabel('Activate on')
        self.cb_run_on = QtGui.QComboBox()
        self.cb_run_on.addItems(['-', 'New Data', 'Data Changed'])

        #SPINBOX REFRESHRATE
        self.label_refresh = QtGui.QLabel('Refresh rate:')
        self.sb_refreshrate = QtGui.QSpinBox()
        self.sb_refreshrate.setSuffix(" Hz")
        self.sb_refreshrate.setMinimum(0)
        self.sb_refreshrate.setMaximum(100)
        self.sb_refreshrate.setValue(refreshR)
        self.sb_refreshrate.valueChanged.connect(
            lambda hz: self.tabs.currentWidget().thread.setRefreshrate(hz))
        #BUTTON: RUN
        self.btn_run_now = QtGui.QPushButton('Run')
        self.btn_run_now.setCheckable(True)
        self.btn_run_now.clicked.connect(self.toggle)
        #LAYOUT
        layout = QtGui.QVBoxLayout()
        layout.setAlignment(QtCore.Qt.AlignTop)
        layout.setMargin(0)
        self.setLayout(layout)
        #top layout
        hl = QtGui.QHBoxLayout()
        hl.addWidget(self.btn_show)
        hl.addWidget(self.btn_collect)
        #fill layout
        layout.addLayout(hl)
        layout.addWidget(self.combo_import)
        layout.addWidget(self.tabs)

        hl2 = QtGui.QHBoxLayout()
        hl2.addWidget(self.label_run_on)
        hl2.addWidget(self.cb_run_on)
        hl2.addWidget(self.label_refresh)
        hl2.addWidget(self.sb_refreshrate)
        hl2.insertStretch(1, 0)
        hl2.insertStretch(2, 0)
        layout.addLayout(hl2)
        layout.addWidget(self.btn_run_now)

        self._toggleShow(False)  #automation disabled by default

    def checkWidgetIsActive(self, widget):
        #bring widget into list of updated widgets
        #if not there already
        a = self._activeWidgets
        if widget not in a:
            a.append(widget)

    def saveState(self):
        state = {}
        #BUTTONS
        state['active'] = self.btn_show.isChecked()
        state['collect'] = self.btn_collect.isChecked()
        #l['runOnNewInput'] = self.btn_run_new.isChecked()
        state['runOn'] = unicode(self.cb_run_on.currentText())
        state['tabTitles'] = [
            unicode(self.tabs.tabText(tab)) for tab in self.tabs
        ]
        #SCRIPTS
        ss = state['scripts'] = []
        for tab in self.tabs:
            ss.append(tab.editor.toPlainText())


#             session.addContentToSave(tab.editor.toPlainText(),
#                             *path+('scripts', '%s.txt' %n))
#-->
#         session.addContentToSave(l, *path+('automation.txt',))
        return state

    def restoreState(self, state):
        #         l =  eval(session.getSavedContent(*path +('automation.txt',) ) )
        #BUTTONS
        self.btn_show.setChecked(state['active'])
        self._toggleShow(state['active'])
        self.btn_collect.setChecked(state['collect'])
        #self.btn_run_new.setChecked(l['runOnNewInput'])
        self.cb_run_on.setCurrentIndex([
            self.cb_run_on.itemText(i) for i in range(self.cb_run_on.count())
        ].index(state['runOn']))
        #SCRIPTS
        self.tabs.clear()
        ss = state['scripts']
        for n, title in enumerate(state['tabTitles']):
            tab = self.tabs.addEmptyTab(title)
            #             txt = ss[n]#session.getSavedContent(*path+('scripts', '%s.txt' %n))
            tab.editor.setPlainText(ss[n])

    def collectWidgets(self):
        '''
        Get a Tool button or a parameter within the tools menu
        and add it to the active script
        '''
        #TOGGLE BETWEEN NORMAL- AND PointingHandCursor
        self._collect = not self._collect
        if self._collect:
            QtGui.QApplication.setOverrideCursor(
                QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        else:
            QtGui.QApplication.restoreOverrideCursor()
        #TOGGLE BUTTON
        self.btn_collect.setChecked(self._collect)
        #add chosen widget to active script:
        fn = lambda widget: self.tabs.currentWidget().addTool(widget)
        for tool in self.display.widget.tools.itervalues():
            #TOOLS:
            tool.returnToolOnClick(self._collect, fn)
            #TOOL-PARAMETERS:
            if isinstance(tool.menu(), ParameterMenu):
                tool.menu().pTree.returnParameterOnKlick(self._collect, fn)

    def _importScript(self, index):
        '''
        Open a file, read it's content and add it to the active script tab
        '''
        self.combo_import.setCurrentIndex(0)
        if index == 0:  # '<import>' placeholder within the comboBox
            return
        if index == 1:  # import from file
            f = self.display.workspace.gui.dialogs.getOpenFileName()
            if f is not None and f.isfile():
                tab = self.tabs.addEmptyTab('file')
                with open(f, 'r') as r:
                    tab.editor.appendPlainText(r.read())
        else:
            # import one of the examples scripts
            tab = self.tabs.addEmptyTab('ex%s' % str(index - 1))
            tab.editor.appendPlainText(
                open(
                    SPRIPT_PATH.join(str(self.combo_import.itemText(index))) +
                    '.py', 'r').read())

    def _updateWidget(self):
        '''
        update all active display widgets
        '''
        for widget in self._activeWidgets:
            try:
                widget.updateView(force=True)
            except Exception:
                traceback.print_exc()

    def _toggleShow(self, show):
        '''
        Show/hide all widgets within Automation except of the on/off switch
        And move the horizontal splitter according to the space needed
        '''
        s = self.splitter
        l = s.sizes()
        minSize = 7.0
        i = s.indexOf(self)

        if show:
            self.tabs.show()
            self.btn_run_now.show()
            self.btn_collect.show()
            self.label_run_on.show()
            self.cb_run_on.show()
            self.combo_import.show()
            self.label_refresh.show()
            self.sb_refreshrate.show()
            # move splitter:
            # assume equal sizes for all to calc the splitter size
            s.setSizes(np.ones(len(l)) * np.mean(l))
        else:
            self.tabs.hide()
            self.btn_run_now.hide()
            self.btn_collect.hide()
            self.label_run_on.hide()
            self.cb_run_on.hide()
            self.combo_import.hide()
            self.label_refresh.hide()
            self.sb_refreshrate.hide()
            # move splitter:
            # smallest possible size of batchTab
            if l:
                a = (l[i] - minSize) / len(l)
                for n, y in enumerate(l):
                    if n != i:
                        l[n] = y + a
                    else:
                        l[n] = minSize
                s.setSizes(l)

    def _setRunning(self):
        '''update button'''
        self.btn_run_now.setChecked(True)
        self.btn_run_now.setText('Stop')
        self.display.workspace.gui.undoRedo.is_active = False
        #TODO: remove try... if .display if not a weakref.proxy any more
        try:
            d = self.display.__repr__.__self__
        except:
            d = self.display
        #SHOW RUN INDICATOR
        self._runIndicator = CircleWidget(d)
        self._runIndicator.move(2, 2)
        self._runIndicator.show()

    def _setDone(self):
        '''update button'''
        self.btn_run_now.setChecked(False)
        self.btn_run_now.setText('Start')
        self.display.workspace.gui.undoRedo.is_active = True
        if hasattr(self, '_runIndicator'):
            self._runIndicator.close()
            del self._runIndicator

    def toggle(self):
        '''
        Start/Stop the active script
        '''
        tab = self.tabs.currentWidget()
        #STOP
        if self.btn_run_now.text() == 'Stop':
            tab.thread.kill()
            return
        #START
        self.display.backupChangedLayer(changes='Script <%s>' %
                                        self.tabs.tabText(tab))
        self._activeWidgets = [self.display.widget]

        tab.thread.start()

    def toggleNewData(self):
        '''
        toggle run settings allow running for new data
        '''
        if self.btn_show.isChecked() and self.cb_run_on.currentIndex(
        ) == 1:  #=new data
            self.toggle()

    def toggleDataChanged(self):
        '''
        toggle run settings allow running for data changed
        '''
        if self.btn_show.isChecked() and self.cb_run_on.currentIndex(
        ) == 2:  #=data changed
            self.toggle()