Example #1
0
    def __init__(self, parent=None, statusBarService=None):
        """
        Creates a QProgressBar and adds it to the given status bar (for
        threads that can provide accurate progress information).

        Note: The status bar can either be a QStatusBar or the StatusBarService. In the default
        BioPARKIN use, it is the StatusBarService instance.

        @todo: A throbber is created and also added to the status bar (for
        threads that can only provide start/stop information).
        """
        #        super(ProgressBarService, self).__init__(parent)   # done in __new__

        if statusBarService is not None:
            self.statusBarService = statusBarService
            self.progressBar = QProgressBar(None)  # used for showing progress
            self.progressBarMutex = QMutex()
            self.progressBar.hide()
            self.statusBarService.addPermanentWidget(self.progressBar)
            self.progressRunning = False

            self.throbber = QLabel()
            self.throbberRunning = False
            self.throbberMutex = QMutex()
            self.statusBarService.addPermanentWidget(self.throbber)
            self.throbber.show()
            self.throbber.hide()

            throbberImage = QMovie(":/images/Spinning_wheel_throbber.gif",
                                   parent=self.throbber)
            throbberImage.setScaledSize(QSize(24, 24))
            throbberImage.setCacheMode(QMovie.CacheAll)
            throbberImage.start()
            self.throbber.setMovie(throbberImage)
            self.throbber.setFixedSize(24, 24)
Example #2
0
class Reduce(QObject):
    def __init__(self,reduce='../../bin/redcsl'):
        traceLogger.debug("######### reduce is %s", reduce)
        super(Reduce,self).__init__()
        self.__process = procNew(sys.path[0] + "/" + reduce)
        self.__processId = self.__process['processId']
        self.__process = self.__process['handle']
        self.__mutex = QMutex()

    def __del__(self):
        traceLogger.warning("about to delete Reduce process - this is good!")
        procDelete(self.__process)

    def compute(self,c):
        self.__mutex.lock()
        l = c.split('\n')
        for sc in l:
            a = self.__compute(sc)
        self.__mutex.unlock()
        return a

    def __compute(self,c):
        a = ansNew(self.__process,c)
        ansDelete(a['handle'])
        return a['data']

    def signal(self,c):
        signalLogger.debug("c=%s" % c)
        os.system('/bin/kill -' + c + ' ' + str(self.__processId))
Example #3
0
 def __init__(self,reduce='../../bin/redcsl'):
     traceLogger.debug("######### reduce is %s", reduce)
     super(Reduce,self).__init__()
     self.__process = procNew(sys.path[0] + "/" + reduce)
     self.__processId = self.__process['processId']
     self.__process = self.__process['handle']
     self.__mutex = QMutex()
Example #4
0
class SyncThread(QThread):
    """Sync notes with evernote thread"""
    force_sync_signal = Signal()
    sync_state_changed = Signal(int)

    def __init__(self, app, *args, **kwargs):
        QThread.__init__(self, *args, **kwargs)
        self.app = app
        self.status = STATUS_NONE
        self.last_sync = datetime.now()
        self.timer = QTimer()
        self.timer.timeout.connect(self.sync)
        self.update_timer()
        self.wait_condition = QWaitCondition()
        self.mutex = QMutex()

    def update_timer(self):
        self.timer.stop()
        delay = int(self.app.settings.value('sync_delay') or 0) or DEFAULT_SYNC_DELAY
        if delay != SYNC_MANUAL:
            self.timer.start(delay)

    def run(self):
        self.session = get_db_session()
        self.sq = self.session.query
        self.auth_token = get_auth_token()
        self.note_store = get_note_store(self.auth_token)
        self.perform()
        while True:
            self.mutex.lock()
            self.wait_condition.wait(self.mutex)
            self.perform()
            self.mutex.unlock()

    def force_sync(self):
        self.timer.stop()
        self.sync()
        self.update_timer()

    @Slot()
    def sync(self):
        self.wait_condition.wakeAll()

    def perform(self):
        """Perform all sync"""
        self.status = STATUS_SYNC
        self.last_sync = datetime.now()
        self.sync_state_changed.emit(SYNC_STATE_START)
        try:
            self.local_changes()
            self.remote_changes()
        except Exception, e:  # maybe log this
            self.session.rollback()
        finally:
Example #5
0
 def __init__(self, *args, **kwargs):
     QThread.__init__(self, *args, **kwargs)
     self.app = AppClass.instance()
     self.status = STATUS_NONE
     self.last_sync = datetime.now()
     self.update_count = 0
     self.timer = QTimer()
     self.timer.timeout.connect(self.sync)
     self.update_timer()
     self.wait_condition = QWaitCondition()
     self.mutex = QMutex()
Example #6
0
class WorkThread(QThread):
    def __init__(self, runnable):
        super(WorkThread, self).__init__()
        self.runnable = runnable
        self.stopped = False
        self.mutex = QMutex()

    def run(self, *args, **kwargs):
        self.runnable()
        self.stop()
        self.finished.connect(self.deleteLater)

    def stop(self):
        try:
            self.mutex.lock()
            self.stopped = False
        finally:
            self.mutex.unlock()

    def isStopped(self):
        try:
            self.mutex.lock()
            return self.stopped
        finally:
            self.mutex.unlock()
Example #7
0
    def __init__(self, widget):
        logging.Handler.__init__(self)

        self.widget = widget
        self.mutex = QMutex()

        self.formatter = logging.Formatter("%(levelname)s | %(message)s")
Example #8
0
	def __init__(self, theMainWindow, parent=None):
		global abnormalTermination
		global scanPath
		global homeDir
		global scanReportPath
		global scanReportFolder
		global infectionsList
		global infectedFiles
		super(manager, self).__init__(parent)
		
		# Opening Configuration File
		if config.debug:
			self.confileName = os.getcwd() + "/conf/config.ini"
		else:		
			self.confileName = os.path.expanduser("~") + "/.avgui/config.ini"
		#self.confileName = os.path.expanduser("~") + "/.avgui/config.ini"
		self.configparser = SafeConfigParser()
		self.configparser.read(self.confileName)
		self.mutexPrint = QMutex()
		
		self._theMainWindow = theMainWindow
		self.setupConnections(self._theMainWindow)
		self.theTimer = QTimer()
		abnormalTermination = 0
		self.scanReportStorageEnabled = 0
		scanReportPath = None
		scanReportFolder = None
		scanPath = None
		homeDir = expanduser("~")
Example #9
0
 def __init__(self, statusbar=None):
     """
     The constructor takes the QStatusBar that this service will wrap.
     """
     if statusbar:
         self.statusbar = statusbar  # needs to be provided when first (!) instantiated
     self.mutex = QMutex()
Example #10
0
    def __init__(self, video, user_id, parent=None):
        super(Buffer, self).__init__(parent)
        self.mutex = QMutex()
        self.video = video
        self.last_frame_accessed = (0, 0)
        self.displayed_frames_range = 1  # must be odd
        self.video_frame_count = self.video.frame_count
        self.video_frame_fps = self.video.fps
        self.user_id = user_id

        self.cache = {}
        self.cached_min_frame = 0
        self.cached_max_frame = 0
        self.cached_time = 10  # seconds
        self.cached_time_border = 0.25  # 25 percent from cached interval, where it starts to buffer new objects

        self.checkBufferState.connect(self.__checkBuffer)
Example #11
0
 def __init__(self, app, *args, **kwargs):
     QThread.__init__(self, *args, **kwargs)
     self.app = app
     self.status = STATUS_NONE
     self.last_sync = datetime.now()
     self.timer = QTimer()
     self.timer.timeout.connect(self.sync)
     self.update_timer()
     self.wait_condition = QWaitCondition()
     self.mutex = QMutex()
Example #12
0
 def __init__(self, controller, model):
     """
     This is the constructor of the class
     :param file: The json file where the packets are defined
     :param model: The model of the application
     """
     QThread.__init__(self)
     self.model = model
     self.controller = controller
     self.add_table_signal = AddTableSignal()
     self.add_table_signal.signal.connect(self.model.add)
     self.filter_table_signal = AddTableSignal()
     self.filter_table_signal.signal.connect(
         self.controller.open_filter_callback)
     self.json_file = None
     self.timer = QTimer(self)
     self.timer.timeout.connect(self.update_packets)
     self.json_file_loaded = QWaitCondition()
     self.mutex = QMutex()
Example #13
0
class _ShioriBean:
  def __init__(self):
    self.enabled = True
    self._renderMutex = QMutex()

  def renderKorean(self, text):
    """
    @param  text  unicode
    @return  unicode
    """
    ret = ""
    if self._renderMutex.tryLock():
      ret = dictman.manager().renderKorean(text)
      self._renderMutex.unlock()
    else:
      dwarn("ignore thread contention")
    return ret

  def renderJapanese(self, text):
    """
    @param  text  unicode
    @return  unicode
    """
    ret = ""
    feature = GrimoireBean.instance.lookupFeature(text)
    if self._renderMutex.tryLock():
      ret = skthreads.runsync(partial(
          dictman.manager().renderJapanese, text, exact=True,feature=feature)) # do exact match for speed
      self._renderMutex.unlock()
    else:
      dwarn("ignore thread contention")
    return ret

  def renderJson(self, data):
    """
    @param  data  unicode  json
    @return  unicode
    """
    ret = ""
    if self._renderMutex.tryLock():
      try:
        data = json.loads(data)
        ret = self._renderJson(**data) or ''
      except Exception, e:
        dwarn(e)
      self._renderMutex.unlock()
    else:
Example #14
0
    def __init__(self, q):
        _TermManager.instance = self

        #self.convertsChinese = False
        self.enabled = True  # bool
        self.hentai = False  # bool
        self.marked = False  # bool
        self.rubyEnabled = False  # bool
        self.chineseRubyEnabled = False  # bool
        self.koreanRubyEnabled = False  # bool
        self.vietnameseRubyEnabled = False  # bool
        #self.syntax = False # bool

        # For saving terms
        self.updateTime = 0  # float

        self.targetLanguage = 'ja'  # str  targetLanguage

        self.saveMutex = QMutex()

        self.scripts = {
        }  # {(str type, str fr, str to):TranslationScriptPerformer or ScriptCoder}
        self.scriptLocks = {}  #  {(str lang, str fr, str to):bool}
        self.scriptTimes = {}  # [(str lang, str fr, str to):float time]
        self.proxies = {}  # {(str fr, str to):TranslationProxy}

        #self.rbmt = {} # {str language:rbmt.api.Translator}
        #self.rbmtTimes = {} # [str language:float time]

        t = self.saveTimer = QTimer(q)
        t.setSingleShot(True)
        t.setInterval(2000)  # wait for 2 seconds for rebuilding
        t.timeout.connect(self.saveTerms)

        q.invalidateCacheRequested.connect(t.start, Qt.QueuedConnection)
        q.cacheChangedRequested.connect(q.cacheChanged, Qt.QueuedConnection)
Example #15
0
  def __init__(self, q):
    self.defaultEngineKey = '' # str
    self._online = True     # bool
    self._speakTask = None   # partial function object

    self._zunkoEngine = None  # _ttsman.ZunkoEngine
    self._zunkoMutex = QMutex()

    self._yukariEngine = None # _ttsman.YukariEngine
    self._sapiEngines = {}    # {str key:_ttsman.SapiEngine}
    self._onlineEngines = {}  # {str key:_ttsman.OnlineEngine}
    self._voiceroidEngines = {}  # {str key:_ttsman.VoiceroidEngine}
    self._voicetextEngines = {}  # {str key:_ttsman.VoiceTextEngine}

    #self.defaultEngineKey = 'wrong engine'
    #self.defaultEngineKey = 'VW Misaki'
    #self.defaultEngineKey = 'VW Show'
    #self.defaultEngineKey = 'zunko'
    #self.defaultEngineKey = 'yukari'
    #self.defaultEngineKey = 'google'

    t = self._speakTimer = QTimer(q)
    t.setSingleShot(True)
    t.timeout.connect(self._doSpeakTask)
Example #16
0
    def __init__(self, video, user_id, parent=None):
        super(Buffer, self).__init__(parent)
        self.mutex = QMutex()
        self.video = video
        self.last_frame_accessed = (0, 0)
        self.displayed_frames_range = 1     # must be odd
        self.video_frame_count = self.video.frame_count
        self.video_frame_fps = self.video.fps
        self.user_id = user_id

        self.cache = {}
        self.cached_min_frame = 0
        self.cached_max_frame = 0
        self.cached_time = 10               # seconds
        self.cached_time_border = 0.25      # 25 percent from cached interval, where it starts to buffer new objects

        self.checkBufferState.connect(self.__checkBuffer)
    def __init__(self, statusBar=None):
        """
        Constructor sets up a QMutex (for logging directly to
        a QStatusBar) and a logging.Formatter.

        If no statusBar is given, it *has to be* set later via
        .setStatusBar()!
        """
        logging.Handler.__init__(self)

        self.signaller = StatusBarLoggingSignaller()

        self.statusBar = statusBar
        self.mutex = QMutex()

        self.formatter = logging.Formatter("%(message)s")

        if self.statusBar:
            self.signaller.messageSignal.connect(self.statusBar.showMessage)
Example #18
0
# coding: utf8
# ocrutil.py
# 9/15/2014 jichi

from functools import partial
from sakurakit import skthreads
from sakurakit.skdebug import dwarn
from sakurakit.skwincom import SkCoInitializer
from modi import modi
import main

# Note: the read functions might raise if the image path does not exist on Windows XP

from PySide.QtCore import QMutex
READ_MUTEX = QMutex() # sync access would crash

class _ReadLocker():
  def __init__(self):
    self.locked = False
  def __enter__(self):
    self.locked = READ_MUTEX.tryLock()
    if self.locked:
      return self
    else:
      dwarn("failed to lock mutex due to contention")
      return
  def __exit__(self, *err):
    if self.locked:
      READ_MUTEX.unlock()

def readtext(path, lang, async=False):
Example #19
0
 def __init__(self, runnable):
     super(WorkThread, self).__init__()
     self.runnable = runnable
     self.stopped = False
     self.mutex = QMutex()
Example #20
0
#!/usr/bin/python
'''Test cases for QThread'''

import unittest
from PySide.QtCore import QThread, QCoreApplication, QObject, SIGNAL, QMutex, QTimer
from PySide.QtCore import QEventLoop

from helper import UsesQCoreApplication

mutex = QMutex()


class Dummy(QThread):
    '''Dummy thread'''
    def __init__(self, *args):
        super(Dummy, self).__init__(*args)
        self.called = False

    def run(self):
        #Start-quit sequence
        self.qobj = QObject()
        mutex.lock()
        self.called = True
        mutex.unlock()


class QThreadSimpleCase(UsesQCoreApplication):
    def setUp(self):
        UsesQCoreApplication.setUp(self)
        self.called = False
Example #21
0
 def __init__(self):
     super(AsyncResolver, self).__init__()
     self._task_queue = []
     self._mutex = QMutex()
     self._semaphore = QSemaphore()
     self.working = False
Example #22
0
class AsyncResolver(QThread):

    object_resolved = QtCore.Signal('object_resolved(QVariant)')

    def __init__(self):
        super(AsyncResolver, self).__init__()
        self._task_queue = []
        self._mutex = QMutex()
        self._semaphore = QSemaphore()
        self.working = False

    def synchronized(f):
        def wrap(self, *args, **kwargs):
            self._mutex.lock()
            try:
                return f(self, *args, **kwargs)
            finally:
                self._mutex.unlock()
        return wrap

    def add_task(self, dn):
        self._task_queue.append(dn)
        #print self._semaphore.available()
        self._semaphore.release()
        #print 'before release'

    @synchronized
    def _append_task(self, task):
        self._task_queue.append(task)

    @synchronized
    def _pop_task(self, task):
        return self._task_queue.pop()

    def consume_task(self):
        #print self._semaphore.available()
        self._semaphore.acquire()
        #print 'after acq'
        obj = self._task_queue.pop()
        return obj

    def stop_work(self):
        self.working = False
        if self._task_queue:
            self._append_task(None)
        self._semaphore.release()

    @synchronized
    def _do_task(self, task):
        return task()

    def run(self):
        self.working = True
        while self.working:
            task = self.consume_task()
            if task:
                try:
                    obj = self._do_task(task)
                except UcsmError:
                    pass
                else:
                    self.emit(SIGNAL('object_resolved(QVariant)'), obj)
            else:
                break
Example #23
0
class Buffer(QObject):
    """
    Class buffers annotation objects to cache from database for given frame or frame interval.
    :param video: reference to video object
    :type video: tovian.models.entity.Video
    :param parent: parent widget
    :type parent: PySide.QtCore.QObject
    """

    checkBufferState = Signal()
    buffering = Signal()
    buffered = Signal()
    initialized = Signal()

    MAX_MEMORY_USAGE = 52428800  # 50MB

    def __init__(self, video, user_id, parent=None):
        super(Buffer, self).__init__(parent)
        self.mutex = QMutex()
        self.video = video
        self.last_frame_accessed = (0, 0)
        self.displayed_frames_range = 1  # must be odd
        self.video_frame_count = self.video.frame_count
        self.video_frame_fps = self.video.fps
        self.user_id = user_id

        self.cache = {}
        self.cached_min_frame = 0
        self.cached_max_frame = 0
        self.cached_time = 10  # seconds
        self.cached_time_border = 0.25  # 25 percent from cached interval, where it starts to buffer new objects

        self.checkBufferState.connect(self.__checkBuffer)

    def initBuffer(self):
        """
        Called just first time after initializing buffed and moving to separated thread.
        """
        new_start = 0
        new_stop = int(self.cached_time * self.video_frame_fps)
        new_stop = new_stop if new_stop < self.video_frame_count else self.video_frame_count

        logger.debug("Filling buffer on interval [%s, %s]", new_start,
                     new_stop)
        self.__bufferObjects(new_start, new_stop)
        self.initialized.emit()

    def setDisplayedFrameRange(self, length):
        """
        Sets how long frame interval is displayed (non-vis annotations).
        i.e. 11 meas [currentframe-5, currentframe+5]
        :param length: range length
        :type length: int
        """
        logger.debug("Setting new displayed range value %s", length)
        self.mutex.lock()
        self.displayed_frames_range = length
        self.mutex.unlock()

    def getObjectsInFrame(self, frame):
        """
        Returns list of annotation objects for given frame. When accessing to cache, cached is locked for other access.
        :type frame: int
        :rtype: tuple of (tovian.models.entity.AnnotationObject, int, int)
        :raise AttributeError: if given frame number is out of range [0, video.frame_count]
        """
        logger.debug("Called get an_object from buffer for frame: %s", frame)

        if frame < 0 or frame > self.video_frame_count:
            raise AttributeError(
                "Given frame number %s is out of range [0, %s]" %
                (frame, self.video_frame_count))

        # --- locked ----
        self.mutex.lock()
        try:
            objects = self.cache[frame]
        except KeyError:
            logger.error("Buffer objects could not be found for frame: %s",
                         frame)
            models.repository.logs.insert(
                'gui.exception.get_obj_from_buffer_error',
                "Buffer objects could not be found for frame: %s" % frame,
                annotator_id=self.user_id)
            objects = self.video.annotation_objects_in_frame(frame)
        else:
            objects = objects.values()

        finally:
            self.last_frame_accessed = (frame, frame)
            self.mutex.unlock()  # don't forget to release lock
        # ---------------

        self.checkBufferState.emit()
        return tuple(objects)

    def getObjectsInFrameInterval(self, frame_from, frame_to):
        """
        Returns list of annotation objects for given frame interval.
        :type frame_from: int
        :type frame_to: int
        :rtype: tuple of (tovian.models.entity.AnnotationObject, int, int)
        :raise AttributeError: if given frame number interval is not in range [0, video.frame_count] or is invalid
        """
        logger.debug(
            "Called get an_object from buffer for frame interval [%s, %s]",
            frame_from, frame_to)

        if frame_from > frame_to:
            raise AttributeError(
                "frame_from '%s' is greater than frame_to '%s'" %
                (frame_from, frame_to))

        if frame_from < 0 or frame_to < 0 or frame_to > self.video_frame_count or frame_from > self.video_frame_count:
            raise AttributeError(
                "Given frame interval [%s, %s] is out of range [0, %s]" %
                (frame_from, frame_to, self.video_frame_count))

        if frame_from == frame_to:
            objects = self.getObjectsInFrame(frame_from)
            return objects

        objects = []
        self.mutex.lock()
        try:
            for frame in range(frame_from, frame_to + 1):
                try:
                    data = self.cache[frame]
                except KeyError:
                    logger.error(
                        "Buffer objects could not be found for frame: %s",
                        frame)
                    models.repository.logs.insert(
                        'gui.exception.get_obj_from_buffer_error',
                        "Buffer objects could not be found for frame: %s" %
                        frame,
                        annotator_id=self.user_id)
                    data = self.video.annotation_objects_in_frame(frame)
                else:
                    data = data.values()

                objects.extend(data)  # converts iterator to values
        finally:
            self.last_frame_accessed = (frame_from, frame_from)
            self.mutex.unlock()

        self.checkBufferState.emit()
        return tuple(set(objects))

    def resetBuffer(self, frame, clear_all=False, clear_object=None):
        """
        Reset buffer - loads new objects depending on given frame number (i.e. when seeking to new frame).
        Method requests lock when clearing cache!
        :param frame: target frame
        :type frame: int
        :param clear_all: manually clears buffer
        :type clear_all: bool
        :param clear_object:  object that has to be refreshed in buffer (object_id, old_start_frame, old_end_frame)
        :raise ValueError: if given frame number is out of range [0, video.frame_count] |
        when new min and max cached frame are equaled or invalid
        """
        #logger.debug("Locking thread")
        #self.mutex.lock()
        #self.last_frame_accessed = (min_frame_interval, max_frame_interval)
        #self.mutex.unlock()
        #logger.debug("Thread unlocked")

        if frame < 0 or frame > self.video_frame_count:
            raise ValueError("Given frame number %s is out of range [0, %s]" %
                             (frame, self.video_frame_count))

        if not clear_all and not clear_object:
            # if new frame has been already cached
            if frame in self.cache:
                min_frame = frame - ((self.displayed_frames_range - 1) / 2.0)
                max_frame = frame + ((self.displayed_frames_range - 1) / 2.0)

                min_frame = 0 if min_frame < 0 else min_frame
                max_frame = self.video_frame_count if max_frame > self.video_frame_count else max_frame

                # if new frame display frame range is also cached
                if self.cached_min_frame <= min_frame and self.cached_max_frame >= max_frame:
                    logger.debug(
                        "New frame and displayed frame interval is cached and no need to reset"
                    )
                    return
                else:
                    logger.debug(
                        "Target frame is cached, but displayed frame range isn't."
                    )
            else:
                logger.debug("Target frame is not cached.")
        # calculate new start_frame and stop_frame
        new_start_frame = frame - int(
            (self.cached_time / 2.0) * self.video_frame_fps)
        new_stop_frame = frame + int(
            (self.cached_time / 2.0) * self.video_frame_fps)
        new_start_frame = 0 if new_start_frame < 0 else new_start_frame
        new_stop_frame = self.video_frame_count if new_stop_frame > self.video_frame_count else new_stop_frame

        if new_stop_frame == new_start_frame or new_stop_frame < new_start_frame:
            logger.error(
                "New start_frame '%s' and stop_frame '%s' are equal or invalid.",
                new_start_frame, new_stop_frame)
            raise ValueError(
                "New start_frame '%s' and stop_frame '%s' are equal or invalid."
                % (new_start_frame, new_stop_frame))

        if clear_object:
            object_id, old_start, old_end = clear_object

            logger.debug("Deleting old object data from cache")
            self.mutex.lock()
            for i in range(old_start, old_end + 1):
                cache_data = self.cache[i]
                del cache_data[object_id]
            self.mutex.unlock()
            logger.debug("Thread unlocked")

            ## TODO DELETE !!!!!!!!!!!!!!!!!!!!!!!! FOR DEBUGGING PURPOSES
            #for key, value in self.cache.iteritems():
            #    if object_id in value:
            #        print key, value
            #        raise Exception()

            logger.debug(
                "Clearing object id '%s' from buffer and resetting for new frame: %s",
                object_id, frame)
            self.__bufferObjectByID(frame, object_id)

        else:
            logger.debug(
                "Resetting and clearing whole buffer for new frame: %s", frame)

            self.mutex.lock()
            self.cache = {}
            self.mutex.unlock()
            self.__bufferObjects(new_start_frame,
                                 new_stop_frame)  # manually invoked buffering

    def __bufferObjects(self, frame_from, frame_to):
        """
        Called to buffer new objects from database for given frame interval.
        Method requests lock when writing to cache!
        :type frame_from: int
        :type frame_to: int
        :raise ValueError: When frame_from or frame_to has invalid value (out of range, etc.)
        """
        logger.debug("Tries buffer new frame interval [%s, %s]...", frame_from,
                     frame_to)
        if frame_from > frame_to or frame_from < 0 or frame_to > self.video_frame_count:
            raise ValueError(
                "Invalid frame_from '%s' and frame_to values '%s'", frame_from,
                frame_to)

        self.mutex.lock()
        try:
            objectsTuples = self.video.annotation_objects_in_frame_intervals([
                (frame_from, frame_to)
            ])
        except Exception:
            # TODO display error to user
            logger.exception(
                "Error when buffering new objects from database on interval [%s, %s]",
                frame_from, frame_to)
            models.repository.logs.insert(
                'gui.exception.buffering_new_obj_error',
                "Error when buffering new objects from database on interval [%s, %s]"
                % (frame_from, frame_to),
                annotator_id=self.user_id)
            self.mutex.unlock()  # don't forget to release lock
            return

        cleared = not self.cache
        self.buffering.emit()

        #logger.debug("Locking thread -> adding new data to cache")
        #self.mutex.lock()               # request lock
        try:
            for frame in range(frame_from, frame_to + 1):
                try:
                    frame_dict = self.cache[frame]
                except KeyError:
                    self.cache[frame] = {}
                    frame_dict = self.cache[frame]

                # add record to cache
                for objectTuple in objectsTuples:
                    an_object, start_frame, end_frame = objectTuple
                    if start_frame <= frame <= end_frame:
                        frame_dict[an_object.id] = objectTuple

            # if cache has been cleared when method called, set min and max pointers as usually
            if cleared:
                self.cached_max_frame = frame_to
                self.cached_min_frame = frame_from

            # if don't, cache has been extended, so moves pointer a bit
            else:
                if frame_from < self.cached_min_frame:
                    self.cached_min_frame = frame_from
                if frame_to > self.cached_max_frame:
                    self.cached_max_frame = frame_to

        finally:
            self.mutex.unlock()  # don't forget to release lock

        self.buffered.emit()
        logger.debug("Buffered new time interval [%s, %s]", frame_from,
                     frame_to)

    def __bufferObjectByID(self, target_frame, object_id):
        """
        Buffer new object by given ID from database on given frame
        :type target_frame: int
        :type object_id: int
        :raise ValueError: When frame is out of range
        """
        logger.debug("Trying to buffer new object id '%s' on frame '%s'",
                     object_id, target_frame)
        if target_frame < 0 or target_frame > self.video_frame_count:
            raise ValueError(
                "Given frame number is out of video frame count range")

        try:
            objectTuples = self.video.annotation_objects_in_frame_intervals(
                [(target_frame, target_frame)], [
                    object_id,
                ])
        except Exception:
            # TODO display error to user
            logger.exception(
                "Error when buffering new object id '%s' from database on on frame '%s'",
                object_id, target_frame)
            models.repository.logs.insert(
                'gui.exception.buffering_new_obj_error',
                "Error when buffering new object id '%s' from database on on frame '%s'"
                % (object_id, target_frame),
                annotator_id=self.user_id)
            return

        if not objectTuples:
            logger.warning("No object id '%s' for frame '%s' in database!")
            return
        elif len(objectTuples) > 1:
            logger.warning(
                "Returned more than one object by id from database!")

        self.buffering.emit()

        logger.debug("Locking thread -> adding to cache new data")
        self.mutex.lock()
        try:
            an_object, start_frame, end_frame = objectTuples[0]

            for frame in range(start_frame, end_frame + 1):
                try:
                    frame_dict = self.cache[frame]
                except KeyError:
                    self.cache[frame] = {}
                    frame_dict = self.cache[frame]

                frame_dict[an_object.id] = objectTuples[0]

        finally:
            self.mutex.unlock()
            logger.debug("Thread unlocked")

        self.buffered.emit()
        logger.debug("Buffered new by id '%s' on frame '%s'", object_id,
                     target_frame)

    @Slot()
    def __checkBuffer(self):
        """
        Method called when some data in cache has been accessed to check,
        if needs to be loaded new objects from database.
        """
        memory_usage = sys.getsizeof(self.cache)

        if memory_usage > self.MAX_MEMORY_USAGE:
            logger.warning(
                "Reached maximum allowed memory usage '%s' bytes -> resetting buffer",
                self.MAX_MEMORY_USAGE)
            lower_accessed_frame, higher_accessed_frame = self.last_frame_accessed
            if lower_accessed_frame == higher_accessed_frame:
                frame = higher_accessed_frame
            else:
                frame = ((higher_accessed_frame - lower_accessed_frame) /
                         2) + lower_accessed_frame

            self.resetBuffer(frame, clear_all=True)
            return

        cached_min_border = self.cached_min_frame - self.last_frame_accessed[0]
        cached_max_border = self.cached_max_frame - self.last_frame_accessed[1]
        allowed_border = self.cached_time_border * self.cached_time * self.video_frame_fps

        # ----
        # If the last_accessed_frame pointer is between borders (typically between 25% and 75% cache), do nothing.
        # else cache new interval and merge cached data
        # i.e. cache status  =   |bottom|--------------0current0--|top|   => max border passed, cache new objects =>
        #      => new status =   |bottom|--------------0current0--(-----------------------------)|top|
        # ----

        # bottom border
        if cached_min_border > -allowed_border:
            new_stop = self.cached_min_frame - 1
            new_start = new_stop - int(self.cached_time * self.video_frame_fps)

            new_start = 0 if new_start < 0 else new_start
            new_start = self.video_frame_count if new_start > self.video_frame_count else new_start
            new_stop = 0 if new_stop < 0 else new_stop
            new_stop = self.video_frame_count if new_stop > self.video_frame_count else new_stop

            if new_start != new_stop:
                logger.debug(
                    "Check buffer - buffer needs to load new objects, direction down"
                )

                self.__bufferObjects(new_start, new_stop)

        # upper border
        elif cached_max_border < allowed_border:
            new_start = self.cached_max_frame + 1
            new_stop = new_start + int(self.cached_time * self.video_frame_fps)

            new_start = 0 if new_start < 0 else new_start
            new_start = self.video_frame_count if new_start > self.video_frame_count else new_start
            new_stop = 0 if new_stop < 0 else new_stop
            new_stop = self.video_frame_count if new_stop > self.video_frame_count else new_stop

            if new_start != new_stop:
                logger.debug(
                    "Check buffer - buffer needs to load new objects, direction up"
                )

                self.__bufferObjects(new_start, new_stop)

        else:
            logger.debug("Check buffer - status OK")

    @staticmethod
    def bufferFinished():
        """
        Called when buffer thread is finished (closed).
        """
        logger.debug("Buffer thread closed.")

    @staticmethod
    def bufferTerminated():
        """
        Called when buffer thread is terminated (forced to close).
        """
        logger.warning("Buffer thread terminated!")
Example #24
0
class manager(QObject):

	_scanParams = []
	_scanRunning = 0
	# _storageEnabled = 0
	#_folderStorage = None
	#_fileStorage = None
	#_storagePath = None
	_resultsToPrint = []

	

	def __init__(self, theMainWindow, parent=None):
		global abnormalTermination
		global scanPath
		global homeDir
		global scanReportPath
		global scanReportFolder
		global infectionsList
		global infectedFiles
		super(manager, self).__init__(parent)
		
		# Opening Configuration File
		if config.debug:
			self.confileName = os.getcwd() + "/conf/config.ini"
		else:		
			self.confileName = os.path.expanduser("~") + "/.avgui/config.ini"
		#self.confileName = os.path.expanduser("~") + "/.avgui/config.ini"
		self.configparser = SafeConfigParser()
		self.configparser.read(self.confileName)
		self.mutexPrint = QMutex()
		
		self._theMainWindow = theMainWindow
		self.setupConnections(self._theMainWindow)
		self.theTimer = QTimer()
		abnormalTermination = 0
		self.scanReportStorageEnabled = 0
		scanReportPath = None
		scanReportFolder = None
		scanPath = None
		homeDir = expanduser("~")
	
	def displayAVGinfo(self):
		self._theMainWindow.theavgavInfo.show()

	def displayAVGuiinfo(self):
		self._theMainWindow.theavguiInfo	.show()

				
	def setupConnections(self, theMainWindow):
		# Main Window
		self._theMainWindow.btnHistory.clicked.connect(self.emitHistory)
		self._theMainWindow.btnScan.clicked.connect(self.emitScan)
		self._theMainWindow.btnUpdate.clicked.connect(self.emitUpdate)
		self._theMainWindow.sigMainSent.connect(self.handleMainWindowEmits)
		self._theMainWindow.btnStatus.clicked.connect(self.showStatus)
		self._theMainWindow.comLangsel.currentIndexChanged.connect(self.setLanguage)
		self._theMainWindow.action_AVG.triggered.connect(self.displayAVGinfo)
		self._theMainWindow.action_AVGui.triggered.connect(self.displayAVGuiinfo)
		
		# Scan Dialog
		self._theMainWindow.theScan.btnSelectF.clicked.connect(self.selectWhatToScan)
		self._theMainWindow.theScan.btnBeginScan.clicked.connect(self.beginScan)
		self._theMainWindow.theScan.btnScanSettings.clicked.connect(self.setScanSettings)
		self._theMainWindow.theScan.sigCleanScanDialog.connect(self.cleanUpScanSettings)
		
		# Scan Select Dialog
		# self._theMainWindow.theScan.theSelect.sigSelectType.connect(self.handleSelectScanTypeEmits)
		self._theMainWindow.theScan.theSelect.radioFile.clicked.connect(self.emitFileSelected)
		self._theMainWindow.theScan.theSelect.radioFolder.clicked.connect(self.emitFolderSelected)
		
		# Scan Settings Dialog
		self._theMainWindow.theScan.theScanSettings.btnOK.clicked.connect(self.getScanSettings)
		self._theMainWindow.theScan.theScanSettings.chkbFileStore.stateChanged.connect(self.enableStorage)
		self._theMainWindow.theScan.theScanSettings.btnSelectFolder.clicked.connect(self.selectScanReportFolder)
		
		# Scan Progress Dialog
		self._theMainWindow.theScan.theScanProgress.btnExitScan.clicked.connect(self.terminateScan)
		self._theMainWindow.theScan.theScanProgress.sigCloseEvent.connect(self.terminateScan)
		
		# Scan History Dialog
		self._theMainWindow.theHistory.btnExecute.clicked.connect(self.execSearch)
		self._theMainWindow.theHistory.btnHistoryDB.clicked.connect(self.retrieveDBHistory)
		self._theMainWindow.theHistory.theResults.btnExtractTxt.clicked.connect(self.extractToText)
		self._theMainWindow.theHistory.theResults.sigCloseEvent.connect(self.clearResults)

		# Update Dialog
		self._theMainWindow.theUpdate.btnUpdateCheck.clicked.connect(self.checkUpdates)
		self._theMainWindow.theUpdate.btnUpdate.clicked.connect(self.performUpdate)		   
		self._theMainWindow.theUpdate.btnUpdateSet.clicked.connect(self.setUpdateSettings)
		self._theMainWindow.theUpdate.theUpdateSettings.btnOK.clicked.connect(self.setUpdateSettings)
		self._theMainWindow.theUpdate.theUpdateSettings.btnCancel.clicked.connect(self.setUpdateSettings)
		
				
	def emitScan(self):
		self._theMainWindow.sigMainSent.emit("SCAN")
		
		
	def emitHistory(self):
		self._theMainWindow.sigMainSent.emit("HISTORY")

		
	def emitUpdate(self):
		self._theMainWindow.sigMainSent.emit("UPDATE")
		
		
	def handleMainWindowEmits(self, param):
		#print(param)
		if param == "SCAN":
			self._theMainWindow.theScan.clear()
			self._theMainWindow.theScan.theSelect.clear()
			self._theMainWindow.theScan.show()
		elif param == "UPDATE":
			self._theMainWindow.theUpdate.show()
		elif param == "HISTORY":
			self._theMainWindow.theHistory.show()
			# populating combo boxes
			availMal = utilities.populateMalware()
			modelMalware = utilities.malwareModel(availMal)
			self._theMainWindow.theHistory.comMalware.setModel(modelMalware)
			availDBs = utilities.populateVirusDBs()
			modelDBs = utilities.virusDBModel(availDBs)
			
			#populating date fields
			self.curDateList = date.today().isoformat().split('-')
			self.curQDate = QDate(int(self.curDateList[0]), int(self.curDateList[1]), int(self.curDateList[2]))
			self._theMainWindow.theHistory.comStartDate.setDate(self.curQDate )
			self._theMainWindow.theHistory.comEndDate.setDate(self.curQDate )
			
			self._theMainWindow.theHistory.comDatabase.setModel(modelDBs)
			
		else:
			QMessageBox.critical(None, langmodule.attention, langmodule.applicationError, 
								 QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton)
	
	def selectWhatToScan(self):
		self._theMainWindow.theScan.theSelect.clear()
		self._theMainWindow.theScan.theSelect.show()
		
	def emitFileSelected(self):
		global scanPath
		options = QFileDialog.DontResolveSymlinks 
		scanPath = QFileDialog.getOpenFileName(self._theMainWindow.theScan.theSelect, langmodule.chooseFileToScan, '/home', 'All files (*.*)', "",  options)[0]
		print("scan path is: " + scanPath)
		if scanPath == "":
			scanPath=None
			return
		else:
			self._theMainWindow.theScan.infoLabel.setText(langmodule.scanFileTitle)
			self._theMainWindow.theScan.fileToScanLabel.setText(str(scanPath))
		self._theMainWindow.theScan.theSelect.close()
		
	def emitFolderSelected(self):
		global scanPath
		options = QFileDialog.DontResolveSymlinks | QFileDialog.ShowDirsOnly
		scanPath = QFileDialog.getExistingDirectory(self._theMainWindow.theScan.theSelect, langmodule.chooseFolderToScan, '/home', options)
		print("scan path is: " + scanPath)
		if scanPath == "":
			scanPath=None
			return
		else:
			self._theMainWindow.theScan.infoLabel.setText(langmodule.scanFolderTitle)
			self._theMainWindow.theScan.fileToScanLabel.setText(str(scanPath))
		self._theMainWindow.theScan.theSelect.close()
		
############################################ Setting Language #############################################################

	def setLanguage(self):
		
		oldLang = self.configparser.get('Language', 'lang')
		print("oldLang: " + oldLang)
		newLang = self._theMainWindow.comLangsel.currentText()
		self.configparser.set('Language', 'lang', newLang)
		print("newLang: " + newLang)
		if oldLang != newLang:
			QMessageBox.information(None, langmodule.attention, langmodule.needRestartTitle, 
									QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton)
			self.configparser.set('Language', 'lang', newLang)
			with open(self.confileName, 'r+') as confile:
				self.configparser.write(confile)


################################### Methods related to setting the Scan Settings ##########################################

	def setScanSettings(self):
		self._theMainWindow.theScan.theScanSettings.show()
		
	
	def getScanSettings(self):
		global scanParameters
		global scanReportFolder
		global scanReportFile
		global scanReportPath
		#global scanReportStorageEnabled
		
		closeWidget = True
		
		#print("Setting up scan settings...")
		scanParams = []
		# scan for specific file extensions
		if self._theMainWindow.theScan.theScanSettings.chkbIfType.isChecked():
			#print("Getting file extension")
			filesToScan = self._theMainWindow.theScan.theScanSettings.textIfType.toPlainText()
			print("files to scan BEFORE: " + str(filesToScan))
			if (utilities.checkIsExtension(filesToScan)):
				scanParams.append("--ext")
				scanParams.append(filesToScan)
				#print("files to scan AFTER: " + str(filesToScan))
				#print("Just after setting file extensions: " + str(scanParams))
		fileStorageOK = self.validateFileStorage()
		if (self.scanReportStorageEnabled == 1) & (fileStorageOK):
			scanParams.append("--report")
			scanParams.append(scanReportPath)
			#print(scanParams)
		if self._theMainWindow.theScan.theScanSettings.chkbBackUpFiles.isChecked():
			scanParams.append("--vv-backup")
		if self._theMainWindow.theScan.theScanSettings.chkbArchive.isChecked():
			scanParams.append("--arc")
		if self._theMainWindow.theScan.theScanSettings.chkbBootSec.isChecked():
			scanParams.append("--boot-sector")
		if self._theMainWindow.theScan.theScanSettings.chkbCookies.isChecked():
			scanParams.append("--coo")
		if self._theMainWindow.theScan.theScanSettings.chkbMultimedia.isChecked():
			scanParams.append("--media")
		# check which radio button is set 
			# and create parameter
		if self._theMainWindow.theScan.theScanSettings.radioDelete.isChecked():
			scanParams.append("--delete")
		elif self._theMainWindow.theScan.theScanSettings.radioHeal.isChecked():
			scanParams.append("--heal")
		elif self._theMainWindow.theScan.theScanSettings.radioVault.isChecked():
			scanParams.append("--vv-move")
		
		#print("Inside function the scanParams are: " + str(scanParams))
		scanParameters = scanParams
		#print("Just set manager._scanParams: " + str(manager._scanParams))
		#scanParameters = scanParams
		print("Just set scanParameters: " + str(scanParameters))
		
		#print("Clicked OK_1: " + "self.validateFileStorage: " + str(self.validateFileStorage()) + " scanReportStorageEnabled: " + str(self.scanReportStorageEnabled) )
		if self.scanReportStorageEnabled == 1:
			print("Level 1")
			if fileStorageOK:
				print("Level 2")
				self._theMainWindow.theScan.theScanSettings.close()
				print("just closed")
		elif self.scanReportStorageEnabled == 0:
			self._theMainWindow.theScan.theScanSettings.close()
		#print("Clicked OK_2: " + "self.validateFileStorage: " + str(self.validateFileStorage()) + " scanReportStorageEnabled: " + str(self.scanReportStorageEnabled) )
		#self._theMainWindow.theScan.theScanSettings.close()
		
	def selectScanReportFolder(self):
		global scanReportFolder
		#global scanReportStorageEnabled
		result = False
		#if self._theMainWindow.theScan.theScanSettings.chkbFileStore.isChecked():
		if self.scanReportStorageEnabled == 1:
			reportDir = ""
			while not result:
				self._theMainWindow.theScan.theScanSettings.theStoreFileDialog.ShowDirsOnly
				self._theMainWindow.theScan.theSelect.selectDialog.setFileMode(QFileDialog.Directory)
				reportDir = self._theMainWindow.theScan.theSelect.selectDialog.getExistingDirectory()
				if reportDir == "":
					return
				result = utilities.checkFolderPermissions(reportDir)
				if not result:
					QMessageBox.information(None, langmodule.attention, langmodule.noAccessRights, 
									QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton)
				else:					
					scanReportFolder = reportDir
					self._theMainWindow.theScan.theScanSettings.btnSelectFolder.setText(scanReportFolder)
			
	
	def validateFileStorage(self):
		global scanReportFolder
		global scanReportPath
		storagePathOK = True
		
		if (self._theMainWindow.theScan.theScanSettings.textStoreFile.toPlainText() == "") & (self.scanReportStorageEnabled == 1):
			print("here...")
			QMessageBox.information(None, langmodule.attention, langmodule.noFileNameProvided, 
								 QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton)
			storagePathOK = False
		elif (self._theMainWindow.theScan.theScanSettings.textStoreFile.toPlainText() != "") & (self.scanReportStorageEnabled == 1):
			print("scanReportFolder is: " + str(scanReportFolder))
			scanReportFile = self._theMainWindow.theScan.theScanSettings.textStoreFile.toPlainText()
			if scanReportFolder != None:
				scanReportPath = scanReportFolder + "/" + scanReportFile
			else:
				scanReportPath = scanReportFile
			storagePathOK = True
		return storagePathOK
		#print("scanReportPath is: " + str(scanReportPath))
		
		return storagePathOK
			 
	def enableStorage(self):
		#global scanReportStorageEnabled
			   
		if self.scanReportStorageEnabled == 0:
			self._theMainWindow.theScan.theScanSettings.btnSelectFolder.setEnabled(True)
			self._theMainWindow.theScan.theScanSettings.textStoreFile.setEnabled(True)
			#print("setting to 1")
			#print("sender: " + str(self.sender().objectName()))
			self.scanReportStorageEnabled = 1
		else:
			self._theMainWindow.theScan.theScanSettings.btnSelectFolder.setDisabled(True)
			self._theMainWindow.theScan.theScanSettings.textStoreFile.setDisabled(True)
			#print("Setting to 0")
			#print("sender: " + str(self.sender().objectName()))
			self.scanReportStorageEnabled = 0

################################################################################
############################### DB Updates History #############################
################################################################################

	def retrieveDBHistory(self):
		self.thedbHistoryWorker = utilities.dbHistoryWorker()
		#self.thedbHistoryWorker.finished.connect(self.showdbHistoryResults)
		self.thedbHistoryWorker.sigHistoryRetrieved.connect(self.showdbHistoryResults)
		self.thedbHistoryWorker.start()
		
	def showdbHistoryResults(self, theResults):
		if theResults:
			print("theResults = " + str(theResults))
			modelHisDBRes = utilities.dbHistoryTableModel(theResults)
			self._theMainWindow.theHistory.theHistdbResults.tblViewHistoryDB.setModel(modelHisDBRes)
			self._theMainWindow.theHistory.theHistdbResults.tblViewHistoryDB.resizeColumnsToContents()
			self._theMainWindow.theHistory.theHistdbResults.show()
			self.thedbHistoryWorker.exit()
		else:
			QMessageBox.information(None, langmodule.noResults, langmodule.noUpdatesYes, 
								 QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton)

################################################################################
################################### SCAN #######################################
################################################################################

	def beginScan(self):
		global infectionsList
		global infectedFiles
		global infectionsList
		self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.clear()
		self.isCleanScan = False
		global scanPath
		global abnormalTermination
		global scanParameters
		self.getScanSettings()
		infectedFiles = []
		infectionsList = []
		abnormalTermination = 0
		self._theMainWindow.theScan.theScanProgress.btnExitScan.setText(langmodule.terminateScan)
		#print("Scan path is: " + str(scanPath))
		if scanPath == None:
			QMessageBox.information(None, langmodule.attention, langmodule.noFilesChosen, 
								 QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton)
			return -1
		
		# preparing to start scan in a new thread
		self.theScanWorker = utilities.scanWorker(scanPath, scanParameters)
		#self.theScanWorker.finished.connect(self.onScanFinish)
		self.theScanWorker.sigWriteScan.connect(self.printToWidget)
		self.theScanWorker.sigScanTerminated.connect(self.onScanFinish)
		
		self._theMainWindow.theScan.theScanProgress.textScanProg.clear()
		self._theMainWindow.theScan.theScanProgress.show()
		self.theScanWorker.start()
			
		#preparing to store scan event in a new thread
		self.theSQLITEWorker = utilities.sqliteWorker()
		self.theSQLITEWorker.finished.connect(self.onSQLiteFinish)

	def onSQLiteFinish(self):
		pass
		#print("Data Insertion Completed!!!!")

	def printToWidget(self, linetoappend):
		self.mutexPrint.lock()
		global infectionsList
		global infectedFiles
		lineList = (linetoappend.split())
		if ("Trojan" in lineList):
			position = lineList.index('Trojan')
			infectedFiles.append(lineList[position - 1])
			infectionsList.append(lineList[position +2])
		if ("Virus" in lineList):
			if ("identified" in lineList):
				position = lineList.index('Virus')
				infectedFiles.append(lineList[position - 1])
				infectionsList.append(lineList[position +2])
		if ("Could" in lineList):
			position = lineList.index('Could')
			infectedFiles.append(lineList[position - 1])
			infectionsList.append(lineList[position +3])
		print("Infected Files: " + str(infectedFiles))
		print("List of Infections: " + str(infectionsList))
		for i,j in langmodule.translationDict.items(): 
			linetoappend = linetoappend.replace(i,j)
		# curDateTime = datetime.now().isoformat(' ')[:19]
		self._theMainWindow.theScan.theScanProgress.textScanProg.appendPlainText(linetoappend)
		self.mutexPrint.unlock()

	def terminateScan(self):
		global infectionsList
		
		infectionsList = []
		
		if not self.isCleanScan:
			global abnormalTermination
			print("Entering terminateScan from signalManager")
			if hasattr(self, 'theScanWorker'):
				if (self.theScanWorker.getScanState() == QProcess.ProcessState.Running) | (self.theScanWorker.getScanState() == QProcess.ProcessState.Starting):
					print("Seems it was running, calling killScan method")
					self.theScanWorker.killScan()
			self.isCleanScan = True
			self._theMainWindow.theScan.theScanProgress.hide()
			manager._scanParams = []
		

	def onScanFinish(self, normalTermination):
		global infectionsList
		self.theScanWorker.sigWriteScan.disconnect()
		# infectionsList = []
		
		print("Entering onScanFinish, from signalManager, normalTermination = " + str(normalTermination))
		if hasattr(self, 'theScanWorker'):
			self.theScanWorker.exit()
			while not self.theScanWorker.wait():
				print("Waiting for scan worker to finish")
		self._theMainWindow.theScan.theScanProgress.btnExitScan.setText(langmodule.btnExitUpdateProgTitle)
		
		if hasattr(self, 'theScanWorker'):
			del self.theScanWorker
			print("The Scan Worker is being Deleted")
		else:
			print("The Scan Worker Was Already Deleted")
		try:
			lockerFinish = QMutexLocker(mutexTermination)		   
			if normalTermination=="True":
				if infectionsList:
					header1 = QTableWidgetItem("Threats")
					header2 = QTableWidgetItem(("Files"))
					self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.setColumnCount(2)
					self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.setRowCount(len(infectionsList))
					self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.setHorizontalHeaderItem(0, header1)
					self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.setHorizontalHeaderItem(1, header2)
					self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.horizontalHeader().setStretchLastSection(True)
					for i in range(1, len(infectionsList) + 1):
							newItem0 = QTableWidgetItem(infectionsList[i-1])
							newItem1 = QTableWidgetItem(infectedFiles[i-1])
							print("line " + str(i) + ": " + newItem0.text())
							print("line " + str(i) + ": " + newItem1.text())
							self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.setItem(i-1, 0, newItem0)
							self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.setItem(i-1, 1, newItem1)
							self._theMainWindow.theScan.theScanProgress.theShowScanResults.tableWidget.resizeColumnsToContents()
					self._theMainWindow.theScan.theScanProgress.theShowScanResults.show()
				self.theSQLITEWorker.start() 
		except Exception as errmut2:
			print(str(errmut2))
			exit(-1)

		gc.collect()
	

	def cleanUpScanSettings(self):
		global scanPath
		print("Running cleanup")
		scanPath = None
		manager._scanParams = []
		
######################################################## END OF SCAN ###############################################
	
	def execSearch(self):
		flag = 0
		
		if (self._theMainWindow.theHistory.comStartDate.date() > self._theMainWindow.theHistory.comEndDate.date()):
			QMessageBox.information(None, langmodule.wrongDates1, langmodule.wrongDates2, 
								 QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton)
			return
		
		dateFrom = self._theMainWindow.theHistory.comStartDate.date().toString('yyyy-MM-dd')
		dateTo = self._theMainWindow.theHistory.comEndDate.date().toString('yyyy-MM-dd')
		#dateFrom = self._theMainWindow.theHistory.comStartDate.date().toString('yyyy-MM-dd') + ' 23:59:59'
		#dateTo = self._theMainWindow.theHistory.comEndDate.date().toString('yyyy-MM-dd') + ' 23:59:59'
		if dateFrom == dateTo:
			dateFrom = dateFrom + ' 00:00:00'
		dateTo = dateTo + ' 23:59:59'
		
		malware = self._theMainWindow.theHistory.comMalware.currentText()
		virusDB = self._theMainWindow.theHistory.comDatabase.currentText()
		results = utilities.scanSearchQuery(dateFrom, dateTo, malware, virusDB)
		if not results:
			QMessageBox.information(None, langmodule.noResults, langmodule.noResultsCriteria, 
								 QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton)
		else:
			
			if (malware == '') & (virusDB == ''):
				flag = 0
			elif (malware =='') & (virusDB != ''):
				flag = 1
			elif (malware != '') & (virusDB == ''):
				flag = 2
			else:
				flag = 3
		
			nestedResults = []
			for item in results:
				tempList = []
				for i in item:
					tempList.append(str(i))
				nestedResults.append(tempList)
			manager._resultsToPrint = nestedResults
			modelResults = utilities.scanResultsTableModel(nestedResults, flag)
			# print("Nested Results: " + str(nestedResults))
			self._theMainWindow.theHistory.theResults.tblVscanResults.setModel(modelResults)
			#self._theMainWindow.theHistory.theResults.tblVscanResults.resizeColumnsToContents()
			if flag == 0:
				for i in range(3):
					self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(i, 300)
			if flag == 2:
				self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(0, 170)
				self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(1, 180)
				self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(2, 200)
									  
			if flag == 3:
				self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(0, 150)
				self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(1, 170)
				self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(2, 190)
				self._theMainWindow.theHistory.theResults.tblVscanResults.setColumnWidth(3, 170)
			#print("flag = " + str(flag))
			#qsize = QSize(2000, 2000)
			#self._theMainWindow.theHistory.theResults.tblVscanResults.resize(qsize)
			self._theMainWindow.theHistory.theResults.show()

	def extractToText(self):
		try:
			now = datetime.now().isoformat().split('T')
			filename='scanLog_' + now[0][0:10] + '_' + now[1][0:8] + '.txt'
			flags = QFileDialog.DontResolveSymlinks | QFileDialog.ShowDirsOnly
			folder = QFileDialog.getExistingDirectory(self._theMainWindow.theHistory.theResults, langmodule.chooseFolderToStoreText, homeDir, flags)
			print(filename)
			print(manager._resultsToPrint)
			path = folder + '/' + filename
			with open(path, 'w') as file:
				file.write(langmodule.userTitle + '\t\t\t' + langmodule.noOfResultsTitle  + '\t\t' + langmodule.scanDateTimeTitle + '\n') # linux specific newline - not portable!
				file.write("----------------------------------------------------------------------------------" + '\n') # linux specific newline - not portable!
				for inlist in manager._resultsToPrint:
					file.write(inlist[0] + '\t\t\t')
					file.write(inlist[1] + '\t\t\t\t\t')
					file.write(inlist[2] + '\n') # linux specific newline - not portable!
				file.close()	
		except IOError as error:
			print(str(error)[0:13])
			if "Permission denied" in str(error):
				QMessageBox.critical(None, langmodule.attention, langmodule.noAccessRightsInFolder, 
								 QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton)
		except Exception:
			QMessageBox.critical(None, langmodule.attention, langmodule.errorStoringFile, 
								 QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton)
	def clearResults(self):
		manager._resultsToPrint = []
		#print("Test")
	
			
################################################## UPDATES ###########################################################

################################################## Check Updates #####################################################

	def checkUpdates(self):
		self.abnormalTermination = False
		self.isCleanCheck = False
		self._theMainWindow.theUpdate.theCheckPanel.txtCheck.clear()
		self._theMainWindow.theUpdate.theCountDown.countDownLCD.display(30)
		self.theChecker = utilities.chkUpdateWorker()
		self.theChecker.sigFailed.connect(self.handleCheckTermination)
		self.theChecker.sigCheckFinished.connect(self.handleCheckTermination)
		self.theChecker.started.connect(self.beginDaemonChecker)
		self._theMainWindow.theUpdate.theCountDown.sigCloseEvent.connect(self.closeCounterWidget)
		self.theDaemonChecker = utilities.checkDaemonD()
		self.theDaemonChecker.sigDstarted.connect(self.startTimer)
		self._theMainWindow.theUpdate.theCountDown.show()
		self.theChecker.start()
		while not self.theChecker.isRunning():
			print("Waiting for checker to start")


	def beginDaemonChecker(self):
		#print("beginning daemon checker")
		self.theDaemonChecker.start()
		while not self.theDaemonChecker.isRunning():
			print("Waiting for daemon checker to start")

		
	def startTimer(self, result):
		try:
			self.theTimer.timeout.disconnect()
		except Exception as err:
			print("Error disconnecting timeout signal from timer")
		if result == 1: # process failed to start
			QMessageBox.critical(None, langmodule.attention, langmodule.restartUpdate, 
				QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton)
			self._theMainWindow.theUpdate.theCountDown.close()
		if result == 2:
			self._theMainWindow.theUpdate.theCountDown.close()
			return # user cancelled the operation
		else: # normal process initiation
			#print("starting timer...")
			self.theTimer.timeout.connect(self.decrementLCD)
			self.theTimer.start(1000)

	def decrementLCD(self):
		currentValue = self._theMainWindow.theUpdate.theCountDown.countDownLCD.intValue()
		#print("decrementing: current value is: " + str(currentValue))
		self._theMainWindow.theUpdate.theCountDown.countDownLCD.display(currentValue - 1)
		
	def closeCounterWidget(self):
		if not self.isCleanCheck:
			print("In Close Counter Widget")
			if hasattr(self, 'theChecker'):
				print("it has!")
				self.theChecker.cleanUp()
			self.isCleanCheck = True
		else:
			pass
	
	def handleCheckTermination(self, abnormalTermination, theOutput):
		self.abnormalTermination = abnormalTermination
		if self._theMainWindow.theUpdate.theCountDown.isVisible():
			print("was visible")
			self._theMainWindow.theUpdate.theCountDown.close()
		print("inside with abnormalTermination: " + str(self.abnormalTermination))
		self.theTimer.stop()
		if hasattr(self, 'theChecker'):
			if self.theChecker.isRunning():
				self.theChecker.exit()
		if hasattr(self, 'theDaemonChecker'):
			if self.theDaemonChecker.isRunning():
				self.theDaemonChecker.exit()
			while not self.theDaemonChecker.wait():
				print("Waiting for daemon checker to exit")
		if hasattr(self, 'theDaemonChecker'):
			del self.theDaemonChecker
		if hasattr(self, 'theChecker'):
			#self.theChecker.exit()
			print("Trying to delete the checker")
			del self.theChecker
		gc.collect()
		#if hasattr(self, 'theChecker'):
		#	 print("Failed to delete the checker")
		#self._theMainWindow.theUpdate.theCountDown.close()
		if not self.abnormalTermination:
			self._theMainWindow.theUpdate.theCheckPanel.txtCheck.appendPlainText(theOutput)
			self._theMainWindow.theUpdate.theCheckPanel.show()
		gc.collect()

############################################### Run Update #######################################################

	def performUpdate(self):
		self.isClean = False
		self._theMainWindow.theUpdate.theUpdateProgress.sigCloseEvent.connect(self.closeUpdateProgress)
		self.theUpdater = utilities.updateWorker()
		self.theUpdater.sigWriteUpdate.connect(self.printToUpdateWidget)
		self.theUpdater.sigUpdateTerminated.connect(self.onUpdateFinish)
		self.theUpdater.started.connect(self.startChecker)
		self.theUpdateChecker = utilities.checkDaemonD()
		self.theUpdateChecker.sigDstarted.connect(self.showProgress)
		self.theUpdater.start()
	
	def closeUpdateProgress(self):
		print("is clean: " + str(self.isClean))
		if self.isClean:
			pass
		else:
			if hasattr(self, "theUpdater"):
				self.theUpdater.cleanUp()
			self.isClean = True

	def startChecker(self):
		self.theUpdateChecker.start()
		while not self.theUpdateChecker.isRunning():
			print("Waiting for checker to start")		 

	def showProgress(self, result):
		print("result is: " + str(result))
		self._theMainWindow.theUpdate.theUpdateProgress.textUpdateProg.clear()
		if result == 0:
			self._theMainWindow.theUpdate.theUpdateProgress.show()
			self._theMainWindow.theUpdate.theUpdateProgress.btnExit.setEnabled(False)
		else:
			pass
	
	def printToUpdateWidget(self, theInput):
		 self._theMainWindow.theUpdate.theUpdateProgress.textUpdateProg.appendPlainText(theInput)

	def onUpdateFinish(self, exitCode):
		print("EXIT CODE IS: " + str(exitCode))
		if exitCode == 1: # process did not start
			QMessageBox.critical(None, langmodule.attention, langmodule.restartUpdate, 
								 QMessageBox.Ok | QMessageBox.Default, QMessageBox.NoButton)
			if hasattr(self, 'theUpdateChecker'):
				self.theUpdateChecker.exit()
			if hasattr(self, 'theUpdater'):
				self.theUpdater.exit()
		elif exitCode == 0 | exitCode == 255: # nornal process termination
			# print(str(self.theUpdater.isRunning()))
			# signals need to be disconnected in both cases
			self.theUpdater.started.disconnect()
			self.theUpdater.sigUpdateTerminated.disconnect()
			self.theUpdater.sigWriteUpdate.disconnect()
			self.theUpdateChecker.sigDstarted.disconnect()
		if exitCode == 0:
			self._theMainWindow.theUpdate.theUpdateProgress.btnExit.setEnabled(True)
		if exitCode == 299: # abnormalTermination
			if self._theMainWindow.theUpdate.theUpdateProgress.isVisible():
				self._theMainWindow.theUpdate.theUpdateProgress.hide

		###	 cleanup code, always runs	###
		if hasattr(self, 'theUpdateChecker'):
			print("here 1")
			self.theUpdateChecker.exit()
			while self.theUpdateChecker.isRunning():
				print("here 2")
				self.theUpdateChecker.exit()
				QApplication.processEvents()
		if hasattr(self, 'theUpdateChecker'):
			del self.theUpdateChecker
		if hasattr(self, 'theUpdater'):
			while self.theUpdater.isRunning():
				print("now waiting updater...")
				self.theUpdater.exit()
				QApplication.processEvents()
		if hasattr(self, 'theUpdater'):
			print("trying to delete the updater")
			del self.theUpdater
			#if self._theMainWindow.theUpdate.theUpdateProgress.isVisible():
			#print("set it")
		gc.collect()

###################################################### Update Settings ##############################################
	
	#@QtCore.Slot()
	def setUpdateSettings(self):
		self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyMode.currentIndexChanged.connect(self.updateProxyModeSettings)			
		self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.stateChanged.connect(self.updateProxyModeSettings)			
		self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.currentIndexChanged.connect(self.updateProxyModeSettings)
		if self.sender().objectName() == "btnUpdateSet":
			self.getSettings()
			print("getting settings")
			if self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyMode.currentIndex() == 0:
				self._theMainWindow.theUpdate.theUpdateSettings.leditProxyName.setEnabled(False)
				self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPort.setEnabled(False)
				if (self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.isEnabled()):
					self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.setEnabled(False)
				self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.setEnabled(False)
				self._theMainWindow.theUpdate.theUpdateSettings.leditProxyUsername.setEnabled(False)
				self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPass.setEnabled(False)
			self._theMainWindow.theUpdate.theUpdateSettings.show()
		elif self.sender().objectName() == "btnOK":
			try:
				print("test")
				self.setSettings()
				self._theMainWindow.theUpdate.theUpdateSettings.close()
			except Exception as err:
				raise err
		elif self.sender().objectName() == "btnCancel":
			self._theMainWindow.theUpdate.theUpdateSettings.close()

	def updateProxyModeSettings(self):
		if (str(self.sender().objectName())) == "cmbBoxProxyMode":
			print("sender was cmbBoxProxyMode")
			if self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyMode.currentIndex() == 0:
				self._theMainWindow.theUpdate.theUpdateSettings.leditProxyName.setEnabled(False)
				self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPort.setEnabled(False)
				if (self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.isEnabled()):
					self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.setEnabled(False)
				self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.setEnabled(False)
				self._theMainWindow.theUpdate.theUpdateSettings.leditProxyUsername.setEnabled(False)
				self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPass.setEnabled(False)
			else:
				self._theMainWindow.theUpdate.theUpdateSettings.leditProxyName.setEnabled(True)
				self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPort.setEnabled(True)
				self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.setEnabled(True)
				if	self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.isChecked():
					self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.setEnabled(True)
					self._theMainWindow.theUpdate.theUpdateSettings.leditProxyUsername.setEnabled(True)
					self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPass.setEnabled(True)
		elif (str(self.sender().objectName())) == "chkUseLogin":
			if self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.isChecked():
				self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.setEnabled(True)
				self._theMainWindow.theUpdate.theUpdateSettings.leditProxyUsername.setEnabled(True)
				self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPass.setEnabled(True)
			else:
				self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.setEnabled(False)
				self._theMainWindow.theUpdate.theUpdateSettings.leditProxyUsername.setEnabled(False)
				self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPass.setEnabled(False)

	def showStatus(self):
		# !!!! NOT PORTABLE !!!! #
		statusList = subprocess.check_output(["avgctl", "--stat-all"]).decode("utf").split('\n')
		
			
		avgVersion = statusList[5].split()[-1]
		self._theMainWindow.theCurrentStatus.lblAVGtitle.setStyleSheet("QLabel { font-weight : bold; }");
		self._theMainWindow.theCurrentStatus.lblAVGvalue.setText(avgVersion)
		
		if ("-" not in statusList[8]): # checking if at least one update has taken place
			lastUpdate = statusList[8].split()[4] + "/" + statusList[8].split()[5] + "/" + statusList[8].split()[6] + ", " + statusList[8].split()[7]
			self._theMainWindow.theCurrentStatus.lblLastUpdateTitle.setStyleSheet("QLabel { font-weight : bold; }");
			self._theMainWindow.theCurrentStatus.lblLastUpdateValue.setText(lastUpdate)
		
		licence = statusList[11].split()[-1]
		licenceNo = statusList[12].split()[-1]
		self._theMainWindow.theCurrentStatus.lblLicenceTitle.setStyleSheet("QLabel { font-weight : bold; }");
		self._theMainWindow.theCurrentStatus.lblLicenceValue.setText(licence + " / " + licenceNo)
		
		aviVersion = statusList[45].split()[-1]
		self._theMainWindow.theCurrentStatus.lblDatabaseTitle.setStyleSheet("QLabel { font-weight : bold; }");
		self._theMainWindow.theCurrentStatus.lblDatabaseValue.setText(aviVersion)
		
		aviDate = statusList[46].split()[6] + "/" + statusList[46].split()[7] + "/" + statusList[46].split()[8] + ", " + statusList[46].split()[9]
		self._theMainWindow.theCurrentStatus.lblDBDateTitle.setStyleSheet("QLabel { font-weight : bold; }");
		self._theMainWindow.theCurrentStatus.lblDBDateValue.setText(aviDate)
		
		oadStatus1 = statusList[21].split('\t')[2]
		self._theMainWindow.theCurrentStatus.lblOADTitle.setStyleSheet("QLabel { font-weight : bold; }");
		if oadStatus1 == "running":
			self._theMainWindow.theCurrentStatus.lblOADValue.setStyleSheet("QLabel { color : green; }");
			oadStatus = langmodule.genericON
			# perhaps add background color
		else:
			self._theMainWindow.theCurrentStatus.lblOADValue.setStyleSheet("QLabel { color : red; }");
			oadStatus = langmodule.genericOFF
		self._theMainWindow.theCurrentStatus.lblOADValue.setText(oadStatus)
		
		schedStatus1 = statusList[22].split('\t')[2]
		self._theMainWindow.theCurrentStatus.lblSchedTitle.setStyleSheet("QLabel { font-weight : bold; }");
		if schedStatus1 == "running":
			self._theMainWindow.theCurrentStatus.lblSchedValue.setStyleSheet("QLabel { color : green; }");
			schedStatus = langmodule.genericON
			# perhaps add background color
		else:
			self._theMainWindow.theCurrentStatus.lblSchedValue.setStyleSheet("QLabel { color : red; }");
			schedStatus = langmodule.genericOFF
		self._theMainWindow.theCurrentStatus.lblSchedValue.setText(schedStatus)

		if ("-" not in statusList[29]): # checking if at least one virus update has taken place
			lastVirUpdate = statusList[29].split()[3] + "/" + statusList[29].split()[4] + "/" + statusList[29].split()[5] + ", " + statusList[29].split()[6]
			self._theMainWindow.theCurrentStatus.lblNextVUpdateTitle.setStyleSheet("QLabel { font-weight : bold; }");
			self._theMainWindow.theCurrentStatus.lblNextVUpdateValue.setText(lastVirUpdate)
		else: 
			self._theMainWindow.theCurrentStatus.lblNextVUpdateValue.setText(" ")
		
		if ("-" not in statusList[30]): # checking if at least one program update has taken place
			lastProgUpdate = statusList[30].split()[3] + "/" + statusList[30].split()[4] + "/" + statusList[30].split()[5] + ", " + statusList[30].split()[6]
			self._theMainWindow.theCurrentStatus.lblNextPUpdateTitle.setStyleSheet("QLabel { font-weight : bold; }");
			self._theMainWindow.theCurrentStatus.lblNextPUpdateValue.setText(lastProgUpdate)
		else:
			self._theMainWindow.theCurrentStatus.lblNextPUpdateTitle.setStyleSheet("QLabel { font-weight : bold; }");
			self._theMainWindow.theCurrentStatus.lblNextPUpdateValue.setText(" ")
		
		self._theMainWindow.theCurrentStatus.show()

	def getSettings(self):
		# Automatic Program Update
		self.autoProgUpdateOut = subprocess.check_output(["avgcfgctl", "UpdateProgram.sched.Task.Disabled"])
		self.tmp_autoProgUpdate = self.autoProgUpdateOut.decode("utf").rstrip().split("=",1)[-1].capitalize()
		if self.tmp_autoProgUpdate == "False":
			self.autoProgUpdate = True
		else:
			self.autoProgUpdate = False
		self._theMainWindow.theUpdate.theUpdateSettings.chkAutoUpdateProg.setChecked(self.autoProgUpdate)
		# Automatic Virus Database Update
		self.autoVirUpdateOut = subprocess.check_output(["avgcfgctl", "UpdateVir.sched.Task.Disabled"])
		self.tmp_autoVirUpdate = self.autoVirUpdateOut.decode("utf").rstrip().split("=",1)[-1].capitalize()
		if self.tmp_autoVirUpdate == "False":
			self.autoVirUpdate = True
		else:
			self.autoVirUpdate = False
		self._theMainWindow.theUpdate.theUpdateSettings.chkAutoUpdateVir.setChecked(self.autoVirUpdate)
		# Minimum Speed 
		self.minSpeedOut = subprocess.check_output(["avgcfgctl", "Default.update.Inet.disconnect_speed_limit"])
		self.minSpeed = int(str(self.minSpeedOut.decode("utf")).split("=",1)[-1])
		self._theMainWindow.theUpdate.theUpdateSettings.leditMinSpeed.setText(str(self.minSpeed))
		# Maximum Time
		self.maxTimeOut = subprocess.check_output(["avgcfgctl", "Default.update.Inet.disconnect_time_limit"])
		self.maxTime = int(str(self.maxTimeOut.decode("utf")).split("=",1)[-1])
		self._theMainWindow.theUpdate.theUpdateSettings.leditMaxTime.setText(str(self.maxTime))
		# Proxy Name
		self.proxyNameOut = subprocess.check_output(["avgcfgctl", "Default.update.Options.Proxy.Server"])
		self.proxyName = str(self.proxyNameOut.decode("utf")).split("=",1)[-1]
		self._theMainWindow.theUpdate.theUpdateSettings.leditProxyName.setText(str(self.proxyName))
		# Proxy Username
		self.proxyUsernameOut = subprocess.check_output(["avgcfgctl", "Default.update.Options.Proxy.Login"])
		self.proxyUsername = str(self.proxyUsernameOut.decode("utf")).split("=",1)[-1]
		self._theMainWindow.theUpdate.theUpdateSettings.leditProxyUsername.setText(str(self.proxyUsername))
		# Proxy Password
		self.proxyPassOut = subprocess.check_output(["avgcfgctl", "Default.update.Options.Proxy.Password"])
		self.proxyPass = str(self.proxyPassOut.decode("utf")).split("=",1)[-1]
		self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPass.setText(str(self.proxyPass))
		# Proxy Port
		self.proxyPortOut = subprocess.check_output(["avgcfgctl", "Default.update.Options.Proxy.Port"])
		self.proxyPort = int(str(self.proxyPortOut.decode("utf")).split("=",1)[-1])
		self._theMainWindow.theUpdate.theUpdateSettings.leditProxyPort.setText(str(self.proxyPort))
		# Proxy Set up
		self.proxyModeOut = subprocess.check_output(["avgcfgctl", "Default.update.Options.Proxy.Mode"])
		self.proxyMode = int(str(self.proxyModeOut.decode("utf")).split("=",1)[-1])
		self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyMode.setCurrentIndex(self.proxyMode)
		# Proxy Auth Type
		self.proxyAuthTypeOut = subprocess.check_output(["avgcfgctl", "Default.update.Options.Proxy.AuthenticationType"])
		self.proxyAuthType = int(str(self.proxyModeOut.decode("utf")).split("=",1)[-1])
		self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.setCurrentIndex(self.proxyAuthType)
		# Proxy Log In Required
		self.proxyLoginRequiredOut = subprocess.check_output(["avgcfgctl", "Default.update.Options.Proxy.UseLogin"])
		self.tmp_proxyLoginRequired = self.proxyLoginRequiredOut.decode("utf").rstrip().split("=",1)[-1].capitalize()
		if self.tmp_proxyLoginRequired == 'False':
			self.proxyLoginRequired = False
		else:
			self.proxyLoginRequired = True
		self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.setChecked(self.proxyLoginRequired)

	def setSettings(self):
		self.command = ""
		# Automatic Program Update
		self.newAutoProgUpdate = self._theMainWindow.theUpdate.theUpdateSettings.chkAutoUpdateProg.isChecked()
		if (self.newAutoProgUpdate != self.autoProgUpdate):
			self.command = self.command + " UpdateProgram.sched.Task.Disabled=" + str(not self.newAutoProgUpdate)
		# Automatic Virus Database Update
		self.newAutoVirUpdate = self._theMainWindow.theUpdate.theUpdateSettings.chkAutoUpdateVir.isChecked()
		if (self.newAutoVirUpdate != self.autoVirUpdate):
			self.command = self.command + " UpdateVir.sched.Task.Disabled=" + str(not self.newAutoVirUpdate)		
		# Minimum Speed
		self.newMinSpeed = int(self._theMainWindow.theUpdate.theUpdateSettings.leditMinSpeed.text())
		if (self.newMinSpeed != self.minSpeed):
			self.command = self.command + "Default.update.Inet.disconnect_speed_limit=" + str(self.newMinSpeed)
		# Maximum Time
		self.newMaxTime = int(self._theMainWindow.theUpdate.theUpdateSettings.leditMaxTime.text())
		if (self.newMaxTime != self.maxTime):
			self.command = self.command + " Default.update.Inet.disconnect_time_limit=" + str(self.newMaxTime)
		# Proxy Name
		self.newProxyName = self._theMainWindow.theUpdate.theUpdateSettings.leditProxyName.text()
		if (self.newProxyName != self.proxyName):
			self.command = self.command + " Default.update.Options.Proxy.Server="+self.newProxyName.replace(" ", "")
		# Proxy Username
		self.newProxyUsername = self._theMainWindow.theUpdate.theUpdateSettings.leditProxyUsername.text()
		if (self.newProxyUsername != self.proxyUsername):
			self.command = self.command + " Default.update.Options.Proxy.Login="******" Default.update.Options.Proxy.Password="******" Default.update.Options.Proxy.Port=" + str(self.newProxyPort)
		# Proxy Set up
		self.newProxyMode = int(self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyMode.currentIndex())
		if (self.newProxyMode != self.proxyMode):
			self.command = self.command + " Default.update.Options.Proxy.Mode=" + str(self.newProxyMode)
		# Proxy Auth Type
		self.newProxyAuthType = int(self._theMainWindow.theUpdate.theUpdateSettings.cmbBoxProxyAuthType.currentIndex())
		if (self.newProxyAuthType != self.proxyAuthType):
			self.command = self.command + " Default.update.Options.Proxy.AuthenticationType=" + str(self.newProxyAuthType)
		# Proxy Log in Required
		self.newProxyLoginRequired = self._theMainWindow.theUpdate.theUpdateSettings.chkUseLogin.isChecked()
		print(self.newProxyLoginRequired)
		print(self.proxyLoginRequired)
		if (self.newProxyLoginRequired != self.proxyLoginRequired):
			self.command = self.command + " Default.update.Options.Proxy.UseLogin="******"command is: " + self.command)
		self.command = " ".join(self.command.split()) 
		print("new command is: " + self.command)
		if self.command != "":
			try:
				subprocess.call(["gksu", "avgcfgctl -w " + self.command])
			except Exception as err:
				print("Error setting new update settings")
				raise err
Example #25
0
 def __init__(self, **kwargs):
     super(FastAITTranslator, self).__init__(**kwargs)
     self._warned = False  # bool
     self._mutex = QMutex()
Example #26
0
class SyncThread(QThread):
    """Sync notes with evernote thread"""
    force_sync_signal = Signal()
    sync_state_changed = Signal(int)
    data_changed = Signal()

    def __init__(self, app, *args, **kwargs):
        QThread.__init__(self, *args, **kwargs)
        self.app = app
        self.status = STATUS_NONE
        self.last_sync = datetime.now()
        self.update_count = 0
        self.timer = QTimer()
        self.timer.timeout.connect(self.sync)
        self.update_timer()
        self.wait_condition = QWaitCondition()
        self.mutex = QMutex()

    def update_timer(self):
        self.timer.stop()
        delay = int(self.app.settings.value('sync_delay') or 0) or DEFAULT_SYNC_DELAY
        if delay != SYNC_MANUAL:
            self.timer.start(delay)

    def run(self):
        self.init_db()
        self.init_network()
        while True:
            self.mutex.lock()
            self.wait_condition.wait(self.mutex)
            self.perform()
            self.mutex.unlock()
            time.sleep(1)  # prevent cpu eating

    def init_db(self):
        self.session = get_db_session()
        self.sq = self.session.query

    def init_network(self):
        while True:
            try:
                self.auth_token = get_auth_token()
                self.note_store = get_note_store(self.auth_token)
                break
            except socket.error:
                time.sleep(30)

    def force_sync(self):
        self.timer.stop()
        self.sync()
        self.update_timer()

    @Slot()
    def sync(self):
        self.wait_condition.wakeAll()

    def perform(self):
        """Perform all sync"""
        self.status = STATUS_SYNC
        self.last_sync = datetime.now()
        self.sync_state_changed.emit(SYNC_STATE_START)
        if self._need_to_update():
            self.need_to_update = True
            self.all_notes = list(self._iter_all_notes())
        try:
            if self.need_to_update:
                self.remote_changes()
            self.local_changes()
        except Exception, e:  # maybe log this
            self.session.rollback()
            self.init_db()
            self.app.log(e)
        finally:
Example #27
0
class PusThread(QThread):
    """
    This class overrides a QThread object to be able to
    define custom safe threads with custom signals. This
    class is used to be able to make a simulation of a connection
    with the robot where the packets arrives with an interval
    between them without blocking the rest of the functionality
    of the application. The simulation is done by reading the
    packets from a json file.

    """
    def __init__(self, controller, model):
        """
        This is the constructor of the class
        :param file: The json file where the packets are defined
        :param model: The model of the application
        """
        QThread.__init__(self)
        self.model = model
        self.controller = controller
        self.add_table_signal = AddTableSignal()
        self.add_table_signal.signal.connect(self.model.add)
        self.filter_table_signal = AddTableSignal()
        self.filter_table_signal.signal.connect(
            self.controller.open_filter_callback)
        self.json_file = None
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_packets)
        self.json_file_loaded = QWaitCondition()
        self.mutex = QMutex()

    def run(self):
        """
        This method runs the thread reading from
        the json defined and making an sleep of T
        seconds between packet and packet according
        to the interval defined in the json file.
        """

        self.timer.start(1000)

        while True:
            self.mutex.lock()
            self.json_file_loaded.wait(self.mutex)
            file = self.json_file
            self.mutex.unlock()

            pt = PacketTranslator()
            mt = MakoTranslate()
            if file is not None:
                with open(file) as jfile:
                    jsondata = mt.replace(jfile.read())
                    activities = json.loads(jsondata)[TestTags.ACTIVITIES_TAG]
                    for activity in activities:
                        interval = activity[TestTags.INTERVAL_TAG]
                        self.sleep(interval)
                        if TestTags.PACKET_TAG in activity:
                            packet = pt.json2packet(
                                activity[TestTags.PACKET_TAG])
                            pb.pus_notify_sendPacket(packet)
                            self.add_table_signal.throw(packet)
                        elif TestTags.ACTIONS_TAG in activity:
                            if activity[TestTags.
                                        ACTIONS_TAG] == TestTags.SAVEDB_TAG:
                                file = activity[TestTags.PARAMS_TAG]

                                d = Database(file)
                                d.create_dump_table()
                                packages = [
                                    tuple(e[1:-1]) for e in self.model.table
                                ]

                                d.insert_db(
                                    "INSERT INTO packages VALUES(?,?,?,?,?,?,?,?,?,?)",
                                    packages)

                            elif activity[
                                    TestTags.
                                    ACTIONS_TAG] == TestTags.SETFILTER_TAG:
                                filter_ = FilterModel()
                                type_ = activity[TestTags.PARAMS_TAG]["type"]
                                svc = activity[TestTags.PARAMS_TAG]["svc"]
                                msg = activity[TestTags.PARAMS_TAG]["msg"]
                                filter_.set_filter_options(type_, svc, msg)
                                filter_index = self.model.set_filter(
                                    filter_.get_filter_options())
                                self.filter_table_signal.throw(filter_index)
            self.mutex.lock()
            self.json_file = None
            self.mutex.unlock()

    def update_packets(self):
        for _ in range(10):
            packet = pb.pusPacket_t()
            if pb.pusError_t.PUS_NO_ERROR == pb.pus_notify_readTm(
                    packet):  # Comprobar si null
                self.add_table_signal.throw(packet)

    def load_test(self, json_file):
        self.mutex.lock()
        self.json_file = json_file
        if json_file is not None:
            self.json_file_loaded.wakeAll()
        self.mutex.unlock()
Example #28
0
class _TermManager:

    instance = None  # _TermManager  needed for updateTime

    def __init__(self, q):
        _TermManager.instance = self

        #self.convertsChinese = False
        self.enabled = True  # bool
        self.hentai = False  # bool
        self.marked = False  # bool
        self.rubyEnabled = False  # bool
        self.chineseRubyEnabled = False  # bool
        self.koreanRubyEnabled = False  # bool
        self.vietnameseRubyEnabled = False  # bool
        #self.syntax = False # bool

        # For saving terms
        self.updateTime = 0  # float

        self.targetLanguage = 'ja'  # str  targetLanguage

        self.saveMutex = QMutex()

        self.scripts = {
        }  # {(str type, str fr, str to):TranslationScriptPerformer or ScriptCoder}
        self.scriptLocks = {}  #  {(str lang, str fr, str to):bool}
        self.scriptTimes = {}  # [(str lang, str fr, str to):float time]
        self.proxies = {}  # {(str fr, str to):TranslationProxy}

        #self.rbmt = {} # {str language:rbmt.api.Translator}
        #self.rbmtTimes = {} # [str language:float time]

        t = self.saveTimer = QTimer(q)
        t.setSingleShot(True)
        t.setInterval(2000)  # wait for 2 seconds for rebuilding
        t.timeout.connect(self.saveTerms)

        q.invalidateCacheRequested.connect(t.start, Qt.QueuedConnection)
        q.cacheChangedRequested.connect(q.cacheChanged, Qt.QueuedConnection)

    def rebuildCacheLater(self, queued=False):
        if queued:
            self.q.invalidateCacheRequested.emit()
        else:
            self.saveTimer.start()

    def saveTerms(self):
        if not self.scriptTimes:
            return
        if not self.saveMutex.tryLock():
            dwarn("retry later due to thread contention")
            self.rebuildCacheLater(queued=True)
            return

        saveTime = time()
        skthreads.runsync(partial(self._saveTerms, saveTime))
        self.saveMutex.unlock()

    def _saveTerms(self, createTime):
        """Invoked async
    @param  createTime  float
    """
        #for lang,ts in self.targetLanguages.iteritems():
        scriptTimes = self.scriptTimes
        #rbmtTimes = self.rbmtTimes
        if not scriptTimes or createTime < self.updateTime:
            return

        dprint("enter")

        if scriptTimes and createTime >= self.updateTime:
            self._saveScriptTerms(createTime=createTime, times=scriptTimes)

        if createTime >= self.updateTime:
            dprint("cache changed")
            self.q.cacheChangedRequested.emit()
        dprint("leave")

    def _saveScriptTerms(self, createTime, times):
        """
    @param  createTime  float
    @param  times  {str key:float time}
    """
        dprint("enter")

        dm = dataman.manager()
        gameIds = dm.currentGameIds()
        dprint("current series gameIds = %s" % gameIds)
        if gameIds:
            gameIds = set(gameIds)  # in case it is changed during iteration

        l = [
            t.d for t in dm.terms()
            if not t.d.disabled and not t.d.deleted and t.d.pattern
        ]  # filtered
        _termman.sort_terms(l)
        w = _termman.TermWriter(
            termData=l,
            gameIds=gameIds,
            hentai=self.hentai,
            createTime=createTime,
            parent=self,
            rubyEnabled=self.rubyEnabled,
            chineseRubyEnabled=self.rubyEnabled and self.chineseRubyEnabled,
            koreanRubyEnabled=self.rubyEnabled and self.koreanRubyEnabled,
            vietnameseRubyEnabled=self.rubyEnabled
            and self.vietnameseRubyEnabled,
        )

        #for scriptKey,ts in times.iteritems():
        for scriptKey, ts in times.items():  # back up items
            if ts < self.updateTime:  # skip language that does not out of date
                type, to, fr = scriptKey
                macros = w.queryMacros(to, fr)

                if w.isOutdated():
                    dwarn("leave: cancel saving out-of-date terms")
                    return

                path = rc.term_path(type, to=to, fr=fr)  # unicode
                dir = os.path.dirname(path)  # unicode path
                if not os.path.exists(dir):
                    skfileio.makedirs(dir)

                scriptKey = type, to, fr
                if self.scriptLocks.get(scriptKey):
                    raise Exception("cancel saving locked terms")
                self.scriptLocks[scriptKey] = True

                man = self.scripts.get(scriptKey)
                if not man:
                    man = self.scripts[scriptKey] = _make_script_interpreter(
                        type)
                #elif not man.isEmpty():
                #  man.clear()
                else:
                    #man.mutex.lock()
                    if not man.isEmpty():
                        man.clear()
                    #man.mutex.unlock()
                try:
                    if type == 'trans':
                        proxies = self.proxies.get((to, fr))
                        if proxies:
                            del proxies[:]

                    if w.saveTerms(path, type, to, fr, macros):
                        #man.mutex.lock()
                        ok = man.loadScript(path)
                        #man.mutex.unlock()
                        if ok and type == 'trans':
                            self.proxies[(to, fr)] = w.queryProxies(to, fr)
                        dprint("type = %s, to = %s, fr = %s, count = %s" %
                               (type, to, fr, man.size()))
                except:
                    self.scriptLocks[scriptKey] = False
                    raise

                self.scriptLocks[scriptKey] = False
                times[scriptKey] = createTime
        dprint("leave")

    def applyTerms(self,
                   text,
                   type,
                   to,
                   fr,
                   context='',
                   host='',
                   mark=False,
                   ignoreIfNotReady=False):
        """
    @param  text  unicode
    @param  type  str
    @param  to  str  language
    @param* fr  str  language
    @param* context  str
    @param* host  str
    @param* mark  bool or None
    @param* ignoreIfNotReady  bool
    """
        if mark is None:
            mark = self.marked
        if type in ('encode', 'decode'):
            key = 'trans', to, fr  # share the same manager
        else:
            key = type, to, fr
        man = self.scripts.get(key)
        if man is None:
            self.scriptTimes[key] = 0
            self.rebuildCacheLater()
            if ignoreIfNotReady:
                dwarn("ignore text while processing shared dictionary")
                growl.notify(my.tr("Processing Shared Dictionary") + "...")
                return ''
        if self.scriptLocks.get(key):
            dwarn("skip applying locked script")
            if ignoreIfNotReady:
                dwarn("ignore text while processing shared dictionary")
                growl.notify(my.tr("Processing Shared Dictionary") + "...")
                return ''
            return text

        if not man:  #or man.isEmpty():
            return text

        #if not man.mutex.tryLock(TERM_TRYLOCK_INTERVAL):
        #  dwarn("try lock timeout")
        #  return text

        ret = text
        if not man.isEmpty():
            category = _termman.make_category(context=context, host=host)
            if type == 'encode':
                ret = man.encode(text, category)
            elif type == 'decode':
                ret = man.decode(text, category, mark)
            else:
                ret = man.transform(text, category, mark)
        #man.mutex.unlock()
        return ret

    def warmupTerms(self, type, to, fr):
        """
    @param  type  str
    @param  to  str  language
    @param* fr  str  language
    """
        if type in ('encode', 'decode'):
            key = 'trans', to, fr  # share the same manager
        else:
            key = type, to, fr
        if key not in self.scripts:
            self.scriptTimes[key] = 0
            self.rebuildCacheLater()

    _rx_delegate = re.compile(r"{{"
                              r"([a-zA-Z0-9,_$]+)"  # TR_RE_TOKEN
                              r"<[-0-9<>]+>"
                              r"}}")

    def delegateTranslation(self, text, to, fr, context, host, proxies,
                            proxyDigit):
        """
    @param  text  unicode
    @param  to  str  language
    @param  fr  str  language
    @param  context  str
    @param  host  str
    @param  proxies  {unicode input:unicode output}
    @param  proxyDigit  proxy using letters or digits
    @return  unicode
    """
        if '{{' not in text or '}}' not in text:
            return text

        if to in DELEGATE_DISABLED_LANGUAGES:
            unused_proxies = None  # disabled
        else:
            unused_proxies = self.proxies.get((to, fr))  # [TranslationProxy]

        used_proxy_input = set()  # [unicode]
        used_proxy_output = set()  # [unicode]

        category = _termman.make_category(context=context, host=host)

        def fn(m):  # re.match -> unicode
            matched_text = m.group()
            role = m.group(1)
            ret = None
            if unused_proxies:
                for proxy in unused_proxies:
                    if (proxy.match_category(category)
                            and proxy.match_role(role)
                            and proxy.input not in used_proxy_input
                            and proxy.output not in used_proxy_output
                            and proxy.input not in text
                            and proxy.output not in text):
                        used_proxy_input.add(proxy.input)
                        used_proxy_output.add(proxy.output)
                        proxies[proxy.output] = matched_text
                        return proxy.input
            index = len(proxies)
            ret = defs.term_role_proxy(role, index, proxyDigit=proxyDigit)
            proxies[ret] = matched_text
            return ret

        return self._rx_delegate.sub(fn, text)

    _rx_undelegate_latin = re.compile(r"Z[A-Y]+Z")
    _rx_undelegate_digit = re.compile(r"9[0-8]+9")

    def undelegateTranslation(self, text, to, fr, proxies, proxyDigit=False):
        """
    @param  text  unicode
    @param  to  str  language
    @param  fr  str  language
    @param* proxies  {unicode input:unicode output}
    @param* proxyDigit  proxy using letters or digits
    @return  unicode
    """
        if not proxies:
            return text
        rx = None
        if proxyDigit:
            if '9' in text:
                rx = self._rx_undelegate_digit
        else:
            if 'Z' in text:
                rx = self._rx_undelegate_latin
        if rx:

            def fn(m):  # re.match -> unicode
                matched_text = m.group()
                try:
                    return proxies.pop(matched_text)
                except KeyError:
                    return matched_text

            text = rx.sub(fn, text)
        if proxies:
            #to_latin = config.is_latin_language(to)
            for k, v in proxies.iteritems():
                text = text.replace(k, v)
        return text
Example #29
0
 def __init__(self, volume=100, mutex=None):
     self.engine = self.createengine(volume / 100.0)
     self.mutex = mutex or QMutex()  # speak mutex
Example #30
0
class Buffer(QObject):
    """
    Class buffers annotation objects to cache from database for given frame or frame interval.
    :param video: reference to video object
    :type video: tovian.models.entity.Video
    :param parent: parent widget
    :type parent: PySide.QtCore.QObject
    """

    checkBufferState = Signal()
    buffering = Signal()
    buffered = Signal()
    initialized = Signal()

    MAX_MEMORY_USAGE = 52428800     # 50MB

    def __init__(self, video, user_id, parent=None):
        super(Buffer, self).__init__(parent)
        self.mutex = QMutex()
        self.video = video
        self.last_frame_accessed = (0, 0)
        self.displayed_frames_range = 1     # must be odd
        self.video_frame_count = self.video.frame_count
        self.video_frame_fps = self.video.fps
        self.user_id = user_id

        self.cache = {}
        self.cached_min_frame = 0
        self.cached_max_frame = 0
        self.cached_time = 10               # seconds
        self.cached_time_border = 0.25      # 25 percent from cached interval, where it starts to buffer new objects

        self.checkBufferState.connect(self.__checkBuffer)

    def initBuffer(self):
        """
        Called just first time after initializing buffed and moving to separated thread.
        """
        new_start = 0
        new_stop = int(self.cached_time * self.video_frame_fps)
        new_stop = new_stop if new_stop < self.video_frame_count else self.video_frame_count

        logger.debug("Filling buffer on interval [%s, %s]", new_start, new_stop)
        self.__bufferObjects(new_start, new_stop)
        self.initialized.emit()

    def setDisplayedFrameRange(self, length):
        """
        Sets how long frame interval is displayed (non-vis annotations).
        i.e. 11 meas [currentframe-5, currentframe+5]
        :param length: range length
        :type length: int
        """
        logger.debug("Setting new displayed range value %s", length)
        self.mutex.lock()
        self.displayed_frames_range = length
        self.mutex.unlock()

    def getObjectsInFrame(self, frame):
        """
        Returns list of annotation objects for given frame. When accessing to cache, cached is locked for other access.
        :type frame: int
        :rtype: tuple of (tovian.models.entity.AnnotationObject, int, int)
        :raise AttributeError: if given frame number is out of range [0, video.frame_count]
        """
        logger.debug("Called get an_object from buffer for frame: %s", frame)

        if frame < 0 or frame > self.video_frame_count:
            raise AttributeError("Given frame number %s is out of range [0, %s]" % (frame, self.video_frame_count))

        # --- locked ----
        self.mutex.lock()
        try:
            objects = self.cache[frame]
        except KeyError:
            logger.error("Buffer objects could not be found for frame: %s", frame)
            models.repository.logs.insert('gui.exception.get_obj_from_buffer_error',
                                          "Buffer objects could not be found for frame: %s" % frame,
                                          annotator_id=self.user_id)
            objects = self.video.annotation_objects_in_frame(frame)
        else:
            objects = objects.values()

        finally:
            self.last_frame_accessed = (frame, frame)
            self.mutex.unlock()                 # don't forget to release lock
        # ---------------

        self.checkBufferState.emit()
        return tuple(objects)

    def getObjectsInFrameInterval(self, frame_from, frame_to):
        """
        Returns list of annotation objects for given frame interval.
        :type frame_from: int
        :type frame_to: int
        :rtype: tuple of (tovian.models.entity.AnnotationObject, int, int)
        :raise AttributeError: if given frame number interval is not in range [0, video.frame_count] or is invalid
        """
        logger.debug("Called get an_object from buffer for frame interval [%s, %s]", frame_from, frame_to)

        if frame_from > frame_to:
            raise AttributeError("frame_from '%s' is greater than frame_to '%s'" % (frame_from, frame_to))

        if frame_from < 0 or frame_to < 0 or frame_to > self.video_frame_count or frame_from > self.video_frame_count:
            raise AttributeError("Given frame interval [%s, %s] is out of range [0, %s]"
                                 % (frame_from, frame_to, self.video_frame_count))

        if frame_from == frame_to:
            objects = self.getObjectsInFrame(frame_from)
            return objects

        objects = []
        self.mutex.lock()
        try:
            for frame in range(frame_from, frame_to + 1):
                try:
                    data = self.cache[frame]
                except KeyError:
                    logger.error("Buffer objects could not be found for frame: %s", frame)
                    models.repository.logs.insert('gui.exception.get_obj_from_buffer_error',
                                                  "Buffer objects could not be found for frame: %s" % frame,
                                                  annotator_id=self.user_id)
                    data = self.video.annotation_objects_in_frame(frame)
                else:
                    data = data.values()

                objects.extend(data)       # converts iterator to values
        finally:
            self.last_frame_accessed = (frame_from, frame_from)
            self.mutex.unlock()

        self.checkBufferState.emit()
        return tuple(set(objects))

    def resetBuffer(self, frame, clear_all=False, clear_object=None):
        """
        Reset buffer - loads new objects depending on given frame number (i.e. when seeking to new frame).
        Method requests lock when clearing cache!
        :param frame: target frame
        :type frame: int
        :param clear_all: manually clears buffer
        :type clear_all: bool
        :param clear_object:  object that has to be refreshed in buffer (object_id, old_start_frame, old_end_frame)
        :raise ValueError: if given frame number is out of range [0, video.frame_count] |
        when new min and max cached frame are equaled or invalid
        """
        #logger.debug("Locking thread")
        #self.mutex.lock()
        #self.last_frame_accessed = (min_frame_interval, max_frame_interval)
        #self.mutex.unlock()
        #logger.debug("Thread unlocked")

        if frame < 0 or frame > self.video_frame_count:
            raise ValueError("Given frame number %s is out of range [0, %s]" % (frame, self.video_frame_count))

        if not clear_all and not clear_object:
            # if new frame has been already cached
            if frame in self.cache:
                min_frame = frame - ((self.displayed_frames_range - 1) / 2.0)
                max_frame = frame + ((self.displayed_frames_range - 1) / 2.0)

                min_frame = 0 if min_frame < 0 else min_frame
                max_frame = self.video_frame_count if max_frame > self.video_frame_count else max_frame

                # if new frame display frame range is also cached
                if self.cached_min_frame <= min_frame and self.cached_max_frame >= max_frame:
                    logger.debug("New frame and displayed frame interval is cached and no need to reset")
                    return
                else:
                    logger.debug("Target frame is cached, but displayed frame range isn't.")
            else:
                logger.debug("Target frame is not cached.")
        # calculate new start_frame and stop_frame
        new_start_frame = frame - int((self.cached_time / 2.0) * self.video_frame_fps)
        new_stop_frame = frame + int((self.cached_time / 2.0) * self.video_frame_fps)
        new_start_frame = 0 if new_start_frame < 0 else new_start_frame
        new_stop_frame = self.video_frame_count if new_stop_frame > self.video_frame_count else new_stop_frame

        if new_stop_frame == new_start_frame or new_stop_frame < new_start_frame:
            logger.error("New start_frame '%s' and stop_frame '%s' are equal or invalid.",
                         new_start_frame, new_stop_frame)
            raise ValueError("New start_frame '%s' and stop_frame '%s' are equal or invalid."
                             % (new_start_frame, new_stop_frame))

        if clear_object:
            object_id, old_start, old_end = clear_object

            logger.debug("Deleting old object data from cache")
            self.mutex.lock()
            for i in range(old_start, old_end + 1):
                cache_data = self.cache[i]
                del cache_data[object_id]
            self.mutex.unlock()
            logger.debug("Thread unlocked")

            ## TODO DELETE !!!!!!!!!!!!!!!!!!!!!!!! FOR DEBUGGING PURPOSES
            #for key, value in self.cache.iteritems():
            #    if object_id in value:
            #        print key, value
            #        raise Exception()

            logger.debug("Clearing object id '%s' from buffer and resetting for new frame: %s", object_id, frame)
            self.__bufferObjectByID(frame, object_id)

        else:
            logger.debug("Resetting and clearing whole buffer for new frame: %s", frame)

            self.mutex.lock()
            self.cache = {}
            self.mutex.unlock()
            self.__bufferObjects(new_start_frame, new_stop_frame)       # manually invoked buffering

    def __bufferObjects(self, frame_from, frame_to):
        """
        Called to buffer new objects from database for given frame interval.
        Method requests lock when writing to cache!
        :type frame_from: int
        :type frame_to: int
        :raise ValueError: When frame_from or frame_to has invalid value (out of range, etc.)
        """
        logger.debug("Tries buffer new frame interval [%s, %s]...", frame_from, frame_to)
        if frame_from > frame_to or frame_from < 0 or frame_to > self.video_frame_count:
            raise ValueError("Invalid frame_from '%s' and frame_to values '%s'", frame_from, frame_to)

        self.mutex.lock()
        try:
            objectsTuples = self.video.annotation_objects_in_frame_intervals([(frame_from, frame_to)])
        except Exception:
            # TODO display error to user
            logger.exception("Error when buffering new objects from database on interval [%s, %s]", frame_from, frame_to)
            models.repository.logs.insert('gui.exception.buffering_new_obj_error',
                                          "Error when buffering new objects from database on interval [%s, %s]" %
                                          (frame_from, frame_to),
                                          annotator_id=self.user_id)
            self.mutex.unlock()         # don't forget to release lock
            return

        cleared = not self.cache
        self.buffering.emit()

        #logger.debug("Locking thread -> adding new data to cache")
        #self.mutex.lock()               # request lock
        try:
            for frame in range(frame_from, frame_to + 1):
                try:
                    frame_dict = self.cache[frame]
                except KeyError:
                    self.cache[frame] = {}
                    frame_dict = self.cache[frame]

                # add record to cache
                for objectTuple in objectsTuples:
                    an_object, start_frame, end_frame = objectTuple
                    if start_frame <= frame <= end_frame:
                        frame_dict[an_object.id] = objectTuple

            # if cache has been cleared when method called, set min and max pointers as usually
            if cleared:
                self.cached_max_frame = frame_to
                self.cached_min_frame = frame_from

            # if don't, cache has been extended, so moves pointer a bit
            else:
                if frame_from < self.cached_min_frame:
                    self.cached_min_frame = frame_from
                if frame_to > self.cached_max_frame:
                    self.cached_max_frame = frame_to

        finally:
            self.mutex.unlock()         # don't forget to release lock

        self.buffered.emit()
        logger.debug("Buffered new time interval [%s, %s]", frame_from, frame_to)

    def __bufferObjectByID(self, target_frame, object_id):
        """
        Buffer new object by given ID from database on given frame
        :type target_frame: int
        :type object_id: int
        :raise ValueError: When frame is out of range
        """
        logger.debug("Trying to buffer new object id '%s' on frame '%s'", object_id, target_frame)
        if target_frame < 0 or target_frame > self.video_frame_count:
            raise ValueError("Given frame number is out of video frame count range")

        try:
            objectTuples = self.video.annotation_objects_in_frame_intervals([(target_frame, target_frame)],
                                                                            [object_id, ])
        except Exception:
            # TODO display error to user
            logger.exception("Error when buffering new object id '%s' from database on on frame '%s'",
                             object_id, target_frame)
            models.repository.logs.insert('gui.exception.buffering_new_obj_error',
                                          "Error when buffering new object id '%s' from database on on frame '%s'" %
                                          (object_id, target_frame),
                                          annotator_id=self.user_id)
            return

        if not objectTuples:
            logger.warning("No object id '%s' for frame '%s' in database!")
            return
        elif len(objectTuples) > 1:
            logger.warning("Returned more than one object by id from database!")

        self.buffering.emit()

        logger.debug("Locking thread -> adding to cache new data")
        self.mutex.lock()
        try:
            an_object, start_frame, end_frame = objectTuples[0]

            for frame in range(start_frame, end_frame + 1):
                try:
                    frame_dict = self.cache[frame]
                except KeyError:
                    self.cache[frame] = {}
                    frame_dict = self.cache[frame]

                frame_dict[an_object.id] = objectTuples[0]

        finally:
            self.mutex.unlock()
            logger.debug("Thread unlocked")

        self.buffered.emit()
        logger.debug("Buffered new by id '%s' on frame '%s'", object_id, target_frame)

    @Slot()
    def __checkBuffer(self):
        """
        Method called when some data in cache has been accessed to check,
        if needs to be loaded new objects from database.
        """
        memory_usage = sys.getsizeof(self.cache)

        if memory_usage > self.MAX_MEMORY_USAGE:
            logger.warning("Reached maximum allowed memory usage '%s' bytes -> resetting buffer", self.MAX_MEMORY_USAGE)
            lower_accessed_frame, higher_accessed_frame = self.last_frame_accessed
            if lower_accessed_frame == higher_accessed_frame:
                frame = higher_accessed_frame
            else:
                frame = ((higher_accessed_frame - lower_accessed_frame) / 2) + lower_accessed_frame

            self.resetBuffer(frame, clear_all=True)
            return

        cached_min_border = self.cached_min_frame - self.last_frame_accessed[0]
        cached_max_border = self.cached_max_frame - self.last_frame_accessed[1]
        allowed_border = self.cached_time_border * self.cached_time * self.video_frame_fps

        # ----
        # If the last_accessed_frame pointer is between borders (typically between 25% and 75% cache), do nothing.
        # else cache new interval and merge cached data
        # i.e. cache status  =   |bottom|--------------0current0--|top|   => max border passed, cache new objects =>
        #      => new status =   |bottom|--------------0current0--(-----------------------------)|top|
        # ----

        # bottom border
        if cached_min_border > -allowed_border:
            new_stop = self.cached_min_frame - 1
            new_start = new_stop - int(self.cached_time * self.video_frame_fps)

            new_start = 0 if new_start < 0 else new_start
            new_start = self.video_frame_count if new_start > self.video_frame_count else new_start
            new_stop = 0 if new_stop < 0 else new_stop
            new_stop = self.video_frame_count if new_stop > self.video_frame_count else new_stop

            if new_start != new_stop:
                logger.debug("Check buffer - buffer needs to load new objects, direction down")

                self.__bufferObjects(new_start, new_stop)

        # upper border
        elif cached_max_border < allowed_border:
            new_start = self.cached_max_frame + 1
            new_stop = new_start + int(self.cached_time * self.video_frame_fps)

            new_start = 0 if new_start < 0 else new_start
            new_start = self.video_frame_count if new_start > self.video_frame_count else new_start
            new_stop = 0 if new_stop < 0 else new_stop
            new_stop = self.video_frame_count if new_stop > self.video_frame_count else new_stop

            if new_start != new_stop:
                logger.debug("Check buffer - buffer needs to load new objects, direction up")

                self.__bufferObjects(new_start, new_stop)

        else:
            logger.debug("Check buffer - status OK")

    @staticmethod
    def bufferFinished():
        """
        Called when buffer thread is finished (closed).
        """
        logger.debug("Buffer thread closed.")

    @staticmethod
    def bufferTerminated():
        """
        Called when buffer thread is terminated (forced to close).
        """
        logger.warning("Buffer thread terminated!")
Example #31
0
 def __init__(self):
   self.enabled = True
   self._renderMutex = QMutex()
Example #32
0
 def __init__(self, lock, parent=None):
     super(LayoutThread, self).__init__(parent)
     self.lock = lock
     self.stopped = False
     self.mutex = QMutex()
     self.completed = False
Example #33
0
class SyncThread(QThread, SyncAgent):
    """Sync notes with evernote thread"""
    force_sync_signal = Signal()
    sync_state_changed = Signal(int)
    data_changed = Signal()

    def __init__(self, *args, **kwargs):
        QThread.__init__(self, *args, **kwargs)
        self.app = AppClass.instance()
        self.status = STATUS_NONE
        self.last_sync = datetime.now()
        self.update_count = 0
        self.timer = QTimer()
        self.timer.timeout.connect(self.sync)
        self.update_timer()
        self.wait_condition = QWaitCondition()
        self.mutex = QMutex()

    def update_timer(self):
        self.timer.stop()
        delay = int(self.app.settings.value('sync_delay')
                    or 0) or DEFAULT_SYNC_DELAY
        if delay != SYNC_MANUAL:
            self.timer.start(delay)

    def run(self):
        self.init_db()
        self.init_network()
        while True:
            self.mutex.lock()
            self.wait_condition.wait(self.mutex)
            self.perform()
            self.mutex.unlock()
            time.sleep(1)  # prevent cpu eating

    def init_db(self):
        self.session = get_db_session()
        self.sq = self.session.query

    def init_network(self):
        while True:
            try:
                self.auth_token = get_auth_token()
                self.note_store = get_note_store(self.auth_token)
                break
            except socket.error:
                time.sleep(30)

    def force_sync(self):
        self.timer.stop()
        self.sync()
        self.update_timer()

    @Slot()
    def sync(self):
        self.wait_condition.wakeAll()

    def perform(self):
        """Perform all sync"""
        self.status = STATUS_SYNC
        self.last_sync = datetime.now()
        self.sync_state_changed.emit(SYNC_STATE_START)
        if self._need_to_update():
            self.need_to_update = True
            self.all_notes = list(self._iter_all_notes())
        try:
            if self.need_to_update:
                self.remote_changes()
            self.local_changes()
            self.sharing_changes()
        except Exception, e:  # maybe log this
            self.session.rollback()
            self.init_db()
            self.app.log(e)
        finally:
Example #34
0
 def __init__(self, parent):
     super(QtLoggingView, self).__init__(parent)
     #self.setEnabled(False)
     self.setReadOnly(True)
     self.mutex = QMutex()
Example #35
0
class _TtsManager(object):

  def __init__(self, q):
    self.defaultEngineKey = '' # str
    self._online = True     # bool
    self._speakTask = None   # partial function object

    self._zunkoEngine = None  # _ttsman.ZunkoEngine
    self._zunkoMutex = QMutex()

    self._yukariEngine = None # _ttsman.YukariEngine
    self._sapiEngines = {}    # {str key:_ttsman.SapiEngine}
    self._onlineEngines = {}  # {str key:_ttsman.OnlineEngine}
    self._voiceroidEngines = {}  # {str key:_ttsman.VoiceroidEngine}
    self._voicetextEngines = {}  # {str key:_ttsman.VoiceTextEngine}

    #self.defaultEngineKey = 'wrong engine'
    #self.defaultEngineKey = 'VW Misaki'
    #self.defaultEngineKey = 'VW Show'
    #self.defaultEngineKey = 'zunko'
    #self.defaultEngineKey = 'yukari'
    #self.defaultEngineKey = 'google'

    t = self._speakTimer = QTimer(q)
    t.setSingleShot(True)
    t.timeout.connect(self._doSpeakTask)

  @staticmethod
  def _repairText(text, key=''):
    """
    @param  text  unicode
    @param* key  str  engine key
    @return  unicode
    """
    ret = text.replace(u'…', '.') # てんてんてん
    #if key == 'zunko.offline':
    #  ret = textutil.repair_zunko_text(ret)
    return ret

  def iterActiveEngines(self):
    """
    @yield  engine
    """
    if self._online:
      for it in self._onlineEngines.itervalues():
        if it.isValid():
          yield it
      for it in self._voiceroidEngines.itervalues():
        if it.isValid():
          yield it
      for it in self._voicetextEngines.itervalues():
        if it.isValid():
          yield it
    for it in self._zunkoEngine, self._yukariEngine:
      if it and it.isValid():
        yield it
    for it in self._sapiEngines.itervalues():
      if it.isValid():
        yield it

  def stop(self):
    for it in self.iterActiveEngines():
      #if it.type != 'sapi': # do not disable sapi TTS to make it faster
      it.stop()

  def speakLater(self, text, interval, **kwargs): # unicode, long ->
    self._speakTask = partial(self.speak, text, **kwargs)
    self._speakTimer.start(interval)

  def speak(self, text, engine='', termEnabled=False, language='', gender='', verbose=True):
    """
    @param  text  unicode
    @param* engine  str
    @param* termEnabled  bool  whether apply game-specific terms
    @param* language  str
    @param* gender  str
    @param* verbose  bool  whether warn on error
    """
    #if not features.TEXT_TO_SPEECH:
    if not text or jpchars.allpunct(text):
      #self.stop() # stop is not needed for games
      return

    eng = self.getEngine(engine)
    if not eng and self.defaultEngineKey and self.defaultEngineKey != engine:
      eng = self.getEngine(self.defaultEngineKey)

    if not eng:
      if verbose:
        growl.warn(my.tr("TTS is not available in Preferences"))
      dprint("missing engine: %s" % (engine or self.defaultEngineKey))
      return
    if not eng.isValid():
      #if verbose:
      # Always warn
      growl.warn('<br/>'.join((
        my.tr("TTS is not available"),
        eng.name,
      )))
      dprint("invalid engine: %s" % eng.key)
      return

    if eng.online and not self._online:
      dprint("ignore when offline: %s" % eng.key)
      return

    if language == '?': #
      language = unilang.guess_language(text) or 'ja'

    if language and eng.language and eng.language != '*' and language[:2] != eng.language[:2]:
      #if verbose:
      #  growl.notify("<br/>".join((
      #      my.tr("TTS languages mismatch"),
      #      "%s: %s != %s" % (eng.key, language, eng.language))))
      dprint("language mismatch: %s != %s" % (language, eng.language))
      eng = self.getAvailableEngine(language)
      if not eng:
        return

    if termEnabled: #and (not language or language == 'ja'):
      text = termman.manager().applyTtsTerms(text, language)
    # Even if text is empty, trigger stop tts
    #if not text:
    #  return
    text = self._repairText(text, eng.key) # always apply no matter terms are enabled or not

    #if eng.type == 'sapi':
    #  eng.speak(text, async=True)
    #else:
    #with SkProfiler():
    if text:
      eng.speak(text, language, gender) # 0.007 ~ 0.009 seconds for SAPI
    else:
      eng.stop()

    #skevents.runlater(partial(eng.speak, text))

  def getAvailableEngine(self, language):
    """
    @param  language  str
    @return  _ttsman.VoiceEngine or None
    """
    if not self.online:
      dprint("ignore when offline")
      return None
    key = 'naver' if language == 'ja' else 'baidu' if language.startswith('zh') else 'google'
    return self.getEngine(key)

  @property
  def online(self): return self._online
  @online.setter
  def online(self, v):
    if v != self._online:
      self._online = v

  # Voiceroid

  @property
  def yukariEngine(self):
    if not self._yukariEngine:
      ss = settings.global_()
      eng = self._yukariEngine = _ttsman.YukariEngine(path=ss.yukariLocation())
      ss.yukariLocationChanged.connect(eng.setPath)
      growl.msg(' '.join((
        my.tr("Load TTS"),
        eng.name,
      )))
    return self._yukariEngine

  @property
  def zunkoEngine(self):
    if not self._zunkoEngine:
      if self._zunkoMutex.tryLock():
        eng = self._zunkoEngine = _ttsman.ZunkoEngine(
            mutex = self._zunkoMutex,
            volume=self.getVolume(_ttsman.ZunkoEngine.key))
        settings.global_().zunkoLocationChanged.connect(eng.setPath)
        #growl.msg(' '.join((
        #  my.tr("Load TTS"),
        #  eng.name,
        #)))
        self._zunkoMutex.unlock()
      else:
        dwarn("ignored due to thread contention")
    return self._zunkoEngine

  # Online

  def getOnlineEngine(self, key):
    ret = self._onlineEngines.get(key)
    if not ret and key in _ttsman.ONLINE_ENGINES:
      ret = _ttsman.OnlineEngine.create(key)
      if ret:
        ret.speed = self.getSpeed(key)
        ret.pitch = self.getPitch(key)
        ret.volume = self.getVolume(key)
        ret.gender = self.getGender(key)
      if ret and ret.isValid():
        self._onlineEngines[key] = ret
        growl.msg(' '.join((
          my.tr("Load TTS"),
          ret.name,
        )))
      else:
        ret = None
        growl.warn(' '.join((
          my.tr("Failed to load TTS"),
          key,
        )))
    return ret

  # SAPI

  def getSapiEngine(self, key):
    ret = self._sapiEngines.get(key)
    if not ret:
      ret = _ttsman.SapiEngine(key=key,
        speed=self.getSpeed(key),
        pitch=self.getPitch(key),
        volume=self.getVolume(key),
        #gender=self.getGender(key),
      )
      if ret.isValid():
        self._sapiEngines[key] = ret
        growl.msg(' '.join((
          my.tr("Load TTS"),
          ret.name,
        )))
      else:
        ret = None
        growl.warn(' '.join((
          my.tr("Failed to load TTS"),
          key,
        )))
    return ret

  def getPitch(self, key):
    """
    @param  key  str
    @return  int
    """
    try: return int(settings.global_().ttsPitches().get(key) or 0)
    except (ValueError, TypeError): return 0

  def setPitch(self, key, v):
    """
    @param  key  str
    @param  v  int
    """
    ss = settings.global_()
    m = ss.ttsPitches()
    if v != m.get(key):
      m[key] = v
      ss.setTtsPitches(m)
      eng = self.getCreatedEngine(key)
      if eng:
        eng.setPitch(v)

  def getVolume(self, key):
    """
    @param  key  str
    @return  int
    """
    try: return int(settings.global_().ttsVolumes().get(key) or 100)
    except (ValueError, TypeError): return 100

  def setVolume(self, key, v):
    """
    @param  key  str
    @param  v  int
    """
    ss = settings.global_()
    m = ss.ttsVolumes()
    if v != m.get(key):
      m[key] = v
      ss.setTtsVolumes(m)
      eng = self.getCreatedEngine(key)
      if eng:
        eng.setVolume(v)

  def getSpeed(self, key):
    """
    @param  key  str
    @return  int
    """
    try: return int(settings.global_().ttsSpeeds().get(key) or 0)
    except (ValueError, TypeError): return 0

  def setSpeed(self, key, v):
    """
    @param  key  str
    @param  v  int
    """
    ss = settings.global_()
    m = ss.ttsSpeeds()
    if v != m.get(key):
      m[key] = v
      ss.setTtsSpeeds(m)
      eng = self.getCreatedEngine(key)
      if eng:
        eng.setSpeed(v)

  def getGender(self, key):
    """
    @param  key  str
    @return  str
    """
    try: return settings.global_().ttsGenders().get(key) or 'f'
    except (ValueError, TypeError): return 'f'

  def setGender(self, key, v):
    """
    @param  key  str
    @param  v  str
    """
    ss = settings.global_()
    m = ss.ttsGenders()
    if v != m.get(key):
      m[key] = v
      ss.setTtsGenders(m)
      eng = self.getCreatedEngine(key)
      if eng:
        eng.setGender(v)

  # Actions

  def getEngine(self, key):
    """
    @return  _ttsman.VoiceEngine or None
    """
    if not key:
      return None
    if key == 'zunkooffline':
      return self.zunkoEngine
    if key == 'yukarioffline':
      return self.yukariEngine
    return self.getOnlineEngine(key) or self.getSapiEngine(key)

  def getCreatedEngine(self, key):
    """
    @return  _ttsman.VoiceEngine or None
    """
    if not key:
      return None
    if key == 'zunkooffline':
      return self._zunkoEngine
    if key == 'yukarioffline':
      return self._yukariEngine
    return self._onlineEngines.get(key) or self._voiceroidEngines.get(key) or self._voicetextEngines.get(key) or self._sapiEngines.get(key)

  #@memoizedproperty
  #def speakTimer(self):
  #  ret = QTimer(self.q)
  #  ret.setSingleShot(True)
  #  ret.timeout.connect(self._doSpeakTask)
  #  return ret

  def _doSpeakTask(self):
    if self._speakTask:
      try: self._speakTask()
      except Exception, e: dwarn(e)
      self._speakTask = None