licence={}
licence['en']="""\
processes.py version %s:

definition of processes which can interact with a sequenceApplication
see sequenceApp.py

Copyright (C)2014 Georges Khaznadar <georgesk@debian.org>

This program is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 2 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see
<http://www.gnu.org/licenses/>.
"""

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import re, collections

class bashProcess(QProcess):
    """
    class to implement abstract processes to be run in a sequence by
    a sequenceApplication
    """
    defaultCmd="""\
echo "This is the default bashProcess command, it should be redefined."
"""
    def __init__(self, sqApp, cmd = None, message = None, expect=None):
        """
        Constructor.
        @parameter sqApp a sequenceApplication to hook to
        @param cmd a command line which will be interpreted by bash
        @param message a string to summarize the command lines
        @param expect can be an integer (then it states the number of
        expected lines in the output) or a regexp (then it states a
        filter to extract the progress from lines) or a function of a
        string (which will be called to find the progress from lines
        contents)
        @param lines if notNOne, it is the number of expected lines from
        stdout and stderr streams. It is taken in account to manage the
        progress bar when the number of output lines matters.
        @param percentRe a regular expression which can be used to filter
        an integer from the stdout stream. It is taken in account to
        manage the progress bar when not None.
        """
        QProcess.__init__(self, parent=None)
        self.sqApp = sqApp
        if message:
            self.message=message
        else:
            self.message="no message"
        self.outBrowser=self.sqApp.outBrowser()
        self.errBrowser=self.sqApp.errBrowser()
        self.oldLines=0
        self.lines=None
        self.percentRe=None
        self.function=None
        if type(expect) is int:
            self.lines=expect
        if type(expect) is re.Pattern
            self.percentRe=expect
        if isinstance(expect, collections.Callable):
            self.function=expect
        if cmd:
            self.cmd=cmd
        else:
            self.cmd=bashProcess.defaultCmd
        self.readyReadStandardOutput.connect(self.stdout)
        self.readyReadStandardError.connect(self.stderr)
        self.finished.connect(self.finish)
        self.timer=QTimer(self)
        self.timer.timeout.connect(self.stdout)
        self.timer.setInterval( 100 )
        self.timer.start()
        return

    def start(self):
        return QProcess.start(self,"bash", ["-c", self.cmd])
        
    def stdout(self):
        s=self.readAllStandardOutput()
        stream=bytes(s).decode("utf-8")
        if self.percentRe:
            numbers=self.regexp.findall(s)
            if len(numbers)==0:
                return
            n=int(numbers[-1])
            if 0 <= n <= 100:
                # send a signal to the application
                self.sqApp.idleDetailProgress.emit(n)
        if self.lines:
            self.oldLines=self.oldLines+len(s.split('\n'))
            n=int(100*self.oldLines/self.lines)
            if 0 <= n <= 100:
                # send a signal to the application
                self.sqApp.idleDetailProgress.emit(n)
        if self.function:
            for l in s.split('\n'):
                n=self.function(l)
                if type(n) is int:
                    if 0 <= n <= 100:
                        # send a signal to the application
                        self.sqApp.idleDetailProgress.emit(n)                    
        if len(stream)>0:
          t=self.outBrowser.toPlainText()           
          self.outBrowser.clear()
          self.outBrowser.insertPlainText(t+stream)
          sb=self.outBrowser.verticalScrollBar();
          sb.setValue(sb.maximum());
        return

    def stderr(self):
        stream=bytes(self.readAllStandardError()).decode("utf-8")
        t=self.errBrowser.toPlainText()           
        self.errBrowser.clear()
        self.errBrowser.insertPlainText(t+stream)
        sb=self.errBrowser.verticalScrollBar();
        sb.setValue(sb.maximum());
        return

    def finish(self):
        # don't need to raise a signal as it is finished ?
        self.sqApp.nextProcess(finished=self.cmd)
        return

