Tasks/TaskViewer.py

changeset 5117
1faa0780ae1d
parent 5114
ad158c12d744
child 5389
9b1c800daff3
diff -r ed2f37c1f6b6 -r 1faa0780ae1d Tasks/TaskViewer.py
--- a/Tasks/TaskViewer.py	Tue Aug 30 20:13:21 2016 +0200
+++ b/Tasks/TaskViewer.py	Wed Aug 31 18:20:40 2016 +0200
@@ -15,8 +15,9 @@
 
 import os
 import fnmatch
+import threading
 
-from PyQt5.QtCore import pyqtSignal, Qt
+from PyQt5.QtCore import pyqtSignal, Qt, QThread
 from PyQt5.QtWidgets import QHeaderView, QLineEdit, QTreeWidget, QDialog, \
     QInputDialog, QApplication, QMenu, QAbstractItemView, QTreeWidgetItem
 
@@ -77,6 +78,8 @@
         self.taskFilter.setActive(False)
         
         self.__projectTasksSaveTimer = AutoSaver(self, self.saveProjectTasks)
+        self.__projectTaskExtractionThread = ProjectTaskExtractionThread()
+        self.__projectTaskExtractionThread.taskFound.connect(self.addFileTask)
         
         self.__projectTasksMenu = QMenu(
             self.tr("P&roject Tasks"), self)
@@ -690,56 +693,56 @@
         self.clearProjectTasks(fileOnly=True)
         
         # now process them
-        if not quiet:
+        if quiet:
+            ppath = self.project.getProjectPath()
+            self.__projectTaskExtractionThread.scan(
+                markers, [os.path.join(ppath, f) for f in files])
+        else:
             progress = E5ProgressDialog(
                 self.tr("Extracting project tasks..."),
                 self.tr("Abort"), 0, len(files), self.tr("%v/%m Files"))
             progress.setMinimumDuration(0)
             progress.setWindowTitle(self.tr("Tasks"))
-        count = 0
-        
-        for file in files:
-            if not quiet:
+            count = 0
+            
+            ppath = self.project.getProjectPath()
+            for file in files:
                 progress.setLabelText(
                     self.tr("Extracting project tasks...\n{0}").format(file))
                 progress.setValue(count)
                 QApplication.processEvents()
                 if progress.wasCanceled():
                     break
-            
-            QApplication.processEvents()
-            
-            fn = os.path.join(self.project.ppath, file)
-            # read the file and split it into textlines
-            try:
-                text, encoding = Utilities.readEncodedFile(fn)
-                lines = text.splitlines()
-            except (UnicodeError, IOError):
+                
+                fn = os.path.join(ppath, file)
+                # read the file and split it into textlines
+                try:
+                    text, encoding = Utilities.readEncodedFile(fn)
+                    lines = text.splitlines()
+                except (UnicodeError, IOError):
+                    count += 1
+                    progress.setValue(count)
+                    continue
+                
+                # now search tasks and record them
+                lineIndex = 0
+                for line in lines:
+                    lineIndex += 1
+                    shouldBreak = False
+                    
+                    for taskType, taskMarkers in markers.items():
+                        for taskMarker in taskMarkers:
+                            index = line.find(taskMarker)
+                            if index > -1:
+                                task = line[index:]
+                                self.addFileTask(task, fn, lineIndex, taskType)
+                                shouldBreak = True
+                                break
+                        if shouldBreak:
+                            break
+                
                 count += 1
-                if not quiet:
-                    progress.setValue(count)
-                continue
             
-            # now search tasks and record them
-            lineIndex = 0
-            for line in lines:
-                lineIndex += 1
-                shouldBreak = False
-                
-                for taskType, taskMarkers in markers.items():
-                    for taskMarker in taskMarkers:
-                        index = line.find(taskMarker)
-                        if index > -1:
-                            task = line[index:]
-                            self.addFileTask(task, fn, lineIndex, taskType)
-                            shouldBreak = True
-                            break
-                    if shouldBreak:
-                        break
-            
-            count += 1
-        
-        if not quiet:
             progress.setValue(len(files))
     
     def __configure(self):
@@ -754,3 +757,101 @@
         """
         if self.projectOpen and Preferences.getProject("TasksProjectAutoSave"):
             self.project.writeTasks()
+    
+    def stopProjectTaskExtraction(self):
+        """
+        Public method to stop the project task extraction thread.
+        """
+        self.__projectTaskExtractionThread.requestInterrupt()
+        self.__projectTaskExtractionThread.wait()
+
+
+class ProjectTaskExtractionThread(QThread):
+    """
+    Class implementing a thread to extract tasks related to a project.
+    
+    @signal taskFound(str, str, int, int) emitted with the task description,
+        the file name, the line number and task type to signal the presence of
+        a task
+    """
+    taskFound = pyqtSignal(str, str, int, int)
+    
+    def __init__(self, parent=None):
+        """
+        Constructor
+        
+        @param parent reference to the parent object (QObject)
+        """
+        super(ProjectTaskExtractionThread, self).__init__()
+        
+        self.__lock = threading.Lock()
+        self.__interrupt = False
+    
+    def requestInterrupt(self):
+        """
+        Public method to request iterruption of the thread.
+        """
+        if self.isRunning():
+            self.__interrupt = True
+    
+    def scan(self, markers, files):
+        """
+        Public method to scan the given list of files for tasks.
+        
+        @param markers dictionary of defined task markers
+        @type dict of lists of str
+        @param files list of file names to be scanned
+        @type list of str
+        """
+        with self.__lock:
+            self.__interrupt = False
+            self.__files = files[:]
+            self.__markers = {}
+            for markerType in markers:
+                self.__markers[markerType] = markers[markerType][:]
+            
+            if not self.isRunning():
+                self.start(QThread.LowPriority)
+    
+    def run(self):
+        """
+        Public thread method to scan the given files.
+        """
+        with self.__lock:
+            files = self.__files[:]
+            markers = {}
+            for markerType in self.__markers:
+                markers[markerType] = self.__markers[markerType][:]
+        
+        for fn in files:
+            if self.__interrupt:
+                break
+            
+            # read the file and split it into textlines
+            try:
+                text, encoding = Utilities.readEncodedFile(fn)
+                lines = text.splitlines()
+            except (UnicodeError, IOError):
+                continue
+            
+            # now search tasks and record them
+            lineIndex = 0
+            for line in lines:
+                if self.__interrupt:
+                    break
+                
+                lineIndex += 1
+                found = False
+                
+                for taskType, taskMarkers in markers.items():
+                    for taskMarker in taskMarkers:
+                        index = line.find(taskMarker)
+                        if index > -1:
+                            task = line[index:]
+                            with self.__lock:
+                                self.taskFound.emit(task, fn, lineIndex,
+                                                    taskType)
+                            found = True
+                            break
+                    if found:
+                        break

eric ide

mercurial