688 |
691 |
689 # remove all project tasks |
692 # remove all project tasks |
690 self.clearProjectTasks(fileOnly=True) |
693 self.clearProjectTasks(fileOnly=True) |
691 |
694 |
692 # now process them |
695 # now process them |
693 if not quiet: |
696 if quiet: |
|
697 ppath = self.project.getProjectPath() |
|
698 self.__projectTaskExtractionThread.scan( |
|
699 markers, [os.path.join(ppath, f) for f in files]) |
|
700 else: |
694 progress = E5ProgressDialog( |
701 progress = E5ProgressDialog( |
695 self.tr("Extracting project tasks..."), |
702 self.tr("Extracting project tasks..."), |
696 self.tr("Abort"), 0, len(files), self.tr("%v/%m Files")) |
703 self.tr("Abort"), 0, len(files), self.tr("%v/%m Files")) |
697 progress.setMinimumDuration(0) |
704 progress.setMinimumDuration(0) |
698 progress.setWindowTitle(self.tr("Tasks")) |
705 progress.setWindowTitle(self.tr("Tasks")) |
699 count = 0 |
706 count = 0 |
700 |
707 |
701 for file in files: |
708 ppath = self.project.getProjectPath() |
702 if not quiet: |
709 for file in files: |
703 progress.setLabelText( |
710 progress.setLabelText( |
704 self.tr("Extracting project tasks...\n{0}").format(file)) |
711 self.tr("Extracting project tasks...\n{0}").format(file)) |
705 progress.setValue(count) |
712 progress.setValue(count) |
706 QApplication.processEvents() |
713 QApplication.processEvents() |
707 if progress.wasCanceled(): |
714 if progress.wasCanceled(): |
708 break |
715 break |
|
716 |
|
717 fn = os.path.join(ppath, file) |
|
718 # read the file and split it into textlines |
|
719 try: |
|
720 text, encoding = Utilities.readEncodedFile(fn) |
|
721 lines = text.splitlines() |
|
722 except (UnicodeError, IOError): |
|
723 count += 1 |
|
724 progress.setValue(count) |
|
725 continue |
|
726 |
|
727 # now search tasks and record them |
|
728 lineIndex = 0 |
|
729 for line in lines: |
|
730 lineIndex += 1 |
|
731 shouldBreak = False |
|
732 |
|
733 for taskType, taskMarkers in markers.items(): |
|
734 for taskMarker in taskMarkers: |
|
735 index = line.find(taskMarker) |
|
736 if index > -1: |
|
737 task = line[index:] |
|
738 self.addFileTask(task, fn, lineIndex, taskType) |
|
739 shouldBreak = True |
|
740 break |
|
741 if shouldBreak: |
|
742 break |
|
743 |
|
744 count += 1 |
709 |
745 |
710 QApplication.processEvents() |
746 progress.setValue(len(files)) |
|
747 |
|
748 def __configure(self): |
|
749 """ |
|
750 Private method to open the configuration dialog. |
|
751 """ |
|
752 e5App().getObject("UserInterface").showPreferences("tasksPage") |
|
753 |
|
754 def saveProjectTasks(self): |
|
755 """ |
|
756 Public method to write the project tasks. |
|
757 """ |
|
758 if self.projectOpen and Preferences.getProject("TasksProjectAutoSave"): |
|
759 self.project.writeTasks() |
|
760 |
|
761 def stopProjectTaskExtraction(self): |
|
762 """ |
|
763 Public method to stop the project task extraction thread. |
|
764 """ |
|
765 self.__projectTaskExtractionThread.requestInterrupt() |
|
766 self.__projectTaskExtractionThread.wait() |
|
767 |
|
768 |
|
769 class ProjectTaskExtractionThread(QThread): |
|
770 """ |
|
771 Class implementing a thread to extract tasks related to a project. |
|
772 |
|
773 @signal taskFound(str, str, int, int) emitted with the task description, |
|
774 the file name, the line number and task type to signal the presence of |
|
775 a task |
|
776 """ |
|
777 taskFound = pyqtSignal(str, str, int, int) |
|
778 |
|
779 def __init__(self, parent=None): |
|
780 """ |
|
781 Constructor |
|
782 |
|
783 @param parent reference to the parent object (QObject) |
|
784 """ |
|
785 super(ProjectTaskExtractionThread, self).__init__() |
|
786 |
|
787 self.__lock = threading.Lock() |
|
788 self.__interrupt = False |
|
789 |
|
790 def requestInterrupt(self): |
|
791 """ |
|
792 Public method to request iterruption of the thread. |
|
793 """ |
|
794 if self.isRunning(): |
|
795 self.__interrupt = True |
|
796 |
|
797 def scan(self, markers, files): |
|
798 """ |
|
799 Public method to scan the given list of files for tasks. |
|
800 |
|
801 @param markers dictionary of defined task markers |
|
802 @type dict of lists of str |
|
803 @param files list of file names to be scanned |
|
804 @type list of str |
|
805 """ |
|
806 with self.__lock: |
|
807 self.__interrupt = False |
|
808 self.__files = files[:] |
|
809 self.__markers = {} |
|
810 for markerType in markers: |
|
811 self.__markers[markerType] = markers[markerType][:] |
711 |
812 |
712 fn = os.path.join(self.project.ppath, file) |
813 if not self.isRunning(): |
|
814 self.start(QThread.LowPriority) |
|
815 |
|
816 def run(self): |
|
817 """ |
|
818 Public thread method to scan the given files. |
|
819 """ |
|
820 with self.__lock: |
|
821 files = self.__files[:] |
|
822 markers = {} |
|
823 for markerType in self.__markers: |
|
824 markers[markerType] = self.__markers[markerType][:] |
|
825 |
|
826 for fn in files: |
|
827 if self.__interrupt: |
|
828 break |
|
829 |
713 # read the file and split it into textlines |
830 # read the file and split it into textlines |
714 try: |
831 try: |
715 text, encoding = Utilities.readEncodedFile(fn) |
832 text, encoding = Utilities.readEncodedFile(fn) |
716 lines = text.splitlines() |
833 lines = text.splitlines() |
717 except (UnicodeError, IOError): |
834 except (UnicodeError, IOError): |
718 count += 1 |
|
719 if not quiet: |
|
720 progress.setValue(count) |
|
721 continue |
835 continue |
722 |
836 |
723 # now search tasks and record them |
837 # now search tasks and record them |
724 lineIndex = 0 |
838 lineIndex = 0 |
725 for line in lines: |
839 for line in lines: |
|
840 if self.__interrupt: |
|
841 break |
|
842 |
726 lineIndex += 1 |
843 lineIndex += 1 |
727 shouldBreak = False |
844 found = False |
728 |
845 |
729 for taskType, taskMarkers in markers.items(): |
846 for taskType, taskMarkers in markers.items(): |
730 for taskMarker in taskMarkers: |
847 for taskMarker in taskMarkers: |
731 index = line.find(taskMarker) |
848 index = line.find(taskMarker) |
732 if index > -1: |
849 if index > -1: |
733 task = line[index:] |
850 task = line[index:] |
734 self.addFileTask(task, fn, lineIndex, taskType) |
851 with self.__lock: |
735 shouldBreak = True |
852 self.taskFound.emit(task, fn, lineIndex, |
|
853 taskType) |
|
854 found = True |
736 break |
855 break |
737 if shouldBreak: |
856 if found: |
738 break |
857 break |
739 |
|
740 count += 1 |
|
741 |
|
742 if not quiet: |
|
743 progress.setValue(len(files)) |
|
744 |
|
745 def __configure(self): |
|
746 """ |
|
747 Private method to open the configuration dialog. |
|
748 """ |
|
749 e5App().getObject("UserInterface").showPreferences("tasksPage") |
|
750 |
|
751 def saveProjectTasks(self): |
|
752 """ |
|
753 Public method to write the project tasks. |
|
754 """ |
|
755 if self.projectOpen and Preferences.getProject("TasksProjectAutoSave"): |
|
756 self.project.writeTasks() |
|