Tasks/TaskViewer.py

changeset 0
de9c2efb9d02
child 12
1d8dd9706f46
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tasks/TaskViewer.py	Mon Dec 28 16:03:33 2009 +0000
@@ -0,0 +1,816 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2005 - 2009 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a task viewer and associated classes.
+
+Tasks can be defined manually or automatically. Automatically
+generated tasks are derived from a comment with a special
+introductory text. This text is configurable.
+"""
+
+import os
+import sys
+import time
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from E4Gui.E4Application import e4App
+
+from TaskPropertiesDialog import TaskPropertiesDialog
+from TaskFilterConfigDialog import TaskFilterConfigDialog
+
+import UI.PixmapCache
+
+import Preferences
+import Utilities
+
+class Task(QTreeWidgetItem):
+    """
+    Class implementing the task data structure.
+    """
+    def __init__(self, description, priority = 1, filename = "", lineno = 0, 
+                 completed = False, _time = 0, isProjectTask = False, 
+                 isBugfixTask = False, ppath = "", longtext = ""):
+        """
+        Constructor
+        
+        @param parent parent widget of the task (QWidget)
+        @param description descriptive text of the task (string)
+        @param priority priority of the task (0=high, 1=normal, 2=low)
+        @param filename filename containing the task (string)
+        @param lineno line number containing the task (integer)
+        @param completed flag indicating completion status (boolean)
+        @param _time creation time of the task (float, if 0 use current time)
+        @param isProjectTask flag indicating a task related to the current project
+            (boolean)
+        @param isBugfixTask flag indicating a bugfix task (boolean)
+        @param ppath the project path (string)
+        @param longtext explanatory text of the task (string)
+        """
+        self.description = description
+        self.longtext = longtext
+        if priority in [0, 1, 2]:
+            self.priority = priority 
+        else:
+            self.priority = 1
+        self.filename = filename
+        self.lineno = lineno
+        self.completed = completed
+        self.created = _time and _time or time.time()
+        self._isProjectTask = isProjectTask
+        self.isBugfixTask = isBugfixTask
+        self.ppath = ppath
+        
+        if isProjectTask:
+            self.filename = self.filename.replace(self.ppath + os.sep, "")
+            
+        QTreeWidgetItem.__init__(self, ["", "", self.description, self.filename, 
+            (self.lineno and "%6d" % self.lineno or "")])
+        
+        if self.completed:
+            self.setIcon(0, UI.PixmapCache.getIcon("taskCompleted.png"))
+        else:
+            self.setIcon(0, UI.PixmapCache.getIcon("empty.png"))
+        
+        if self.priority == 1:
+            self.setIcon(1, UI.PixmapCache.getIcon("empty.png"))
+        elif self.priority == 0:
+            self.setIcon(1, UI.PixmapCache.getIcon("taskPrioHigh.png"))
+        elif self.priority == 2:
+            self.setIcon(1, UI.PixmapCache.getIcon("taskPrioLow.png"))
+        else:
+            self.setIcon(1, UI.PixmapCache.getIcon("empty.png"))
+        
+        self.colorizeTask()
+        self.setTextAlignment(4, Qt.AlignRight)
+    
+    def colorizeTask(self):
+        """
+        Public slot to set the colors of the task item.
+        """
+        for col in range(5):
+            if self.isBugfixTask:
+                self.setTextColor(col, Preferences.getTasks("TasksBugfixColour"))
+            else:
+                self.setTextColor(col, Preferences.getTasks("TasksColour"))
+            if self._isProjectTask:
+                self.setBackgroundColor(col, Preferences.getTasks("TasksProjectBgColour"))
+            else:
+                self.setBackgroundColor(col, Preferences.getTasks("TasksBgColour"))
+    
+    def setDescription(self, description):
+        """
+        Public slot to update the description.
+        
+        @param longtext explanatory text of the task (string)
+        """
+        self.description = description
+        self.setText(2, self.description)
+    
+    def setLongText(self, longtext):
+        """
+        Public slot to update the longtext field.
+        
+        @param longtext descriptive text of the task (string)
+        """
+        self.longtext = longtext
+    
+    def setPriority(self, priority):
+        """
+        Public slot to update the priority.
+        
+        @param priority priority of the task (0=high, 1=normal, 2=low)
+        """
+        if priority in [0, 1, 2]:
+            self.priority = priority 
+        else:
+            self.priority = 1
+        
+        if self.priority == 1:
+            self.setIcon(1, UI.PixmapCache.getIcon("empty.png"))
+        elif self.priority == 0:
+            self.setIcon(1, UI.PixmapCache.getIcon("taskPrioHigh.png"))
+        elif self.priority == 2:
+            self.setIcon(1, UI.PixmapCache.getIcon("taskPrioLow.png"))
+        else:
+            self.setIcon(1, UI.PixmapCache.getIcon("empty.png"))
+    
+    def setCompleted(self, completed):
+        """
+        Public slot to update the completed flag.
+        
+        @param completed flag indicating completion status (boolean)
+        """
+        self.completed = completed
+        if self.completed:
+            self.setIcon(0, UI.PixmapCache.getIcon("taskCompleted.png"))
+        else:
+            self.setIcon(0, UI.PixmapCache.getIcon("empty.png"))
+    
+    def isCompleted(self):
+        """
+        Public slot to return the completion status.
+        
+        @return flag indicating the completion status (boolean)
+        """
+        return self.completed
+    
+    def getFilename(self):
+        """
+        Public method to retrieve the tasks filename.
+        
+        @return filename (string)
+        """
+        if self._isProjectTask and self.filename:
+            return os.path.join(self.ppath, self.filename)
+        else:
+            return self.filename
+    
+    def getLineno(self):
+        """
+        Public method to retrieve the tasks linenumber.
+        
+        @return linenumber (integer)
+        """
+        return self.lineno
+    
+    def setProjectTask(self, pt):
+        """
+        Public method to set the project relation flag.
+        
+        @param pt flag indicating a project task (boolean)
+        """
+        self._isProjectTask = pt
+        self.colorizeTask()
+    
+    def isProjectTask(self):
+        """
+        Public slot to return the project relation status.
+        
+        @return flag indicating the project relation status (boolean)
+        """
+        return self._isProjectTask
+
+class TaskFilter(object):
+    """
+    Class implementing a filter for tasks.
+    """
+    def __init__(self):
+        """
+        Constructor
+        """
+        self.active = False
+        
+        self.descriptionFilter = None
+        self.filenameFilter = None
+        self.typeFilter = None        # standard (False) or bugfix (True)
+        self.scopeFilter = None       # global (False) or project (True)
+        self.statusFilter = None      # uncompleted (False) or completed (True)
+        self.prioritiesFilter = None  # list of priorities [0 (high), 1 (normal), 2 (low)]
+    
+    def setActive(self, enabled):
+        """
+        Public method to activate the filter.
+        
+        @param enabled flag indicating the activation state (boolean)
+        """
+        self.active = enabled
+    
+    def setDescriptionFilter(self, filter):
+        """
+        Public method to set the description filter.
+        
+        @param filter a regular expression for the description filter 
+            to set (string) or None
+        """
+        if not filter:
+            self.descriptionFilter = None
+        else:
+            self.descriptionFilter = QRegExp(filter)
+    
+    def setFileNameFilter(self, filter):
+        """
+        Public method to set the filename filter.
+        
+        @param filter a wildcard expression for the filename filter 
+            to set (string) or None
+        """
+        if not filter:
+            self.filenameFilter = None
+        else:
+            self.filenameFilter = QRegExp(filter)
+            self.filenameFilter.setPatternSyntax(QRegExp.Wildcard)
+    
+    def setTypeFilter(self, type_):
+        """
+        Public method to set the type filter.
+        
+        @param type_ flag indicating a bugfix task (boolean) or None
+        """
+        self.typeFilter = type_
+        
+    def setScopeFilter(self, scope):
+        """
+        Public method to set the scope filter.
+        
+        @param scope flag indicating a project task (boolean) or None
+        """
+        self.scopeFilter = scope
+        
+    def setStatusFilter(self, status):
+        """
+        Public method to set the status filter.
+        
+        @param status flag indicating a completed task (boolean) or None
+        """
+        self.statusFilter = status
+        
+    def setPrioritiesFilter(self, priorities):
+        """
+        Public method to set the priorities filter.
+        
+        @param priorities list of task priorities (list of integer) or None
+        """
+        self.prioritiesFilter = priorities
+        
+    def hasActiveFilter(self):
+        """
+        Public method to check for active filters.
+        
+        @return flag indicating an active filter was found (boolean)
+        """
+        return self.descriptionFilter is not None or \
+               self.filenameFilter is not None or \
+               self.typeFilter is not None or \
+               self.scopeFilter is not None or \
+               self.statusFilter is not None or \
+               self.prioritiesFilter is not None
+        
+    def showTask(self, task):
+        """
+        Public method to check, if a task should be shown.
+        
+        @param task reference to the task object to check (Task)
+        @return flag indicating whether the task should be shown (boolean)
+        """
+        if not self.active:
+            return True
+        
+        if self.descriptionFilter and \
+           self.descriptionFilter.indexIn(task.description) == -1:
+            return False
+        
+        if self.filenameFilter and \
+           not self.filenameFilter.exactMatch(task.filename):
+            return False
+        
+        if self.typeFilter is not None and \
+           self.typeFilter != task.isBugfixTask:
+            return False
+        
+        if self.scopeFilter is not None and \
+           self.scopeFilter != task._isProjectTask:
+            return False
+        
+        if self.statusFilter is not None and \
+           self.statusFilter != task.completed:
+            return False
+        
+        if self.prioritiesFilter is not None and \
+           not task.priority in self.prioritiesFilter:
+            return False
+        
+        return True
+    
+class TaskViewer(QTreeWidget):
+    """
+    Class implementing the task viewer.
+    
+    @signal displayFile(string, integer) emitted to go to a file task
+    """
+    def __init__(self, parent, project):
+        """
+        Constructor
+        
+        @param parent the parent (QWidget)
+        @param project reference to the project object
+        """
+        QTreeWidget.__init__(self, parent)
+        
+        self.setRootIsDecorated(False)
+        self.setItemsExpandable(False)
+        self.setSortingEnabled(True)
+        
+        self.__headerItem = QTreeWidgetItem(["", "", self.trUtf8("Summary"), 
+            self.trUtf8("Filename"), self.trUtf8("Line"), ""])
+        self.__headerItem.setIcon(0, UI.PixmapCache.getIcon("taskCompleted.png"))
+        self.__headerItem.setIcon(1, UI.PixmapCache.getIcon("taskPriority.png"))
+        self.setHeaderItem(self.__headerItem)
+        
+        self.header().setSortIndicator(2, Qt.AscendingOrder)
+        self.__resizeColumns()
+        
+        self.tasks = []
+        self.copyTask = None
+        self.projectOpen = False
+        self.project = project
+        
+        self.taskFilter = TaskFilter()
+        self.taskFilter.setActive(False)
+        
+        self.__menu = QMenu(self)
+        self.__menu.addAction(self.trUtf8("&New Task..."), self.__newTask)
+        self.__menu.addSeparator()
+        self.regenerateProjectTasksItem = \
+            self.__menu.addAction(self.trUtf8("&Regenerate project tasks"),
+                                  self.__regenerateProjectTasks)
+        self.__menu.addSeparator()
+        self.gotoItem = self.__menu.addAction(self.trUtf8("&Go To"), self.__goToTask)
+        self.__menu.addSeparator()
+        self.copyItem = self.__menu.addAction(self.trUtf8("&Copy"), self.__copyTask)
+        self.pasteItem = self.__menu.addAction(self.trUtf8("&Paste"), self.__pasteTask)
+        self.deleteItem = self.__menu.addAction(self.trUtf8("&Delete"), self.__deleteTask)
+        self.__menu.addSeparator()
+        self.markCompletedItem = self.__menu.addAction(self.trUtf8("&Mark Completed"),
+                                                       self.__markCompleted)
+        self.__menu.addAction(self.trUtf8("Delete Completed &Tasks"),
+                              self.__deleteCompleted)
+        self.__menu.addSeparator()
+        self.__menu.addAction(self.trUtf8("P&roperties..."), self.__editTaskProperties)
+        self.__menu.addSeparator()
+        self.__menuFilteredAct = self.__menu.addAction(self.trUtf8("&Filtered display")) 
+        self.__menuFilteredAct.setCheckable(True)
+        self.__menuFilteredAct.setChecked(False)
+        self.connect(self.__menuFilteredAct, SIGNAL("triggered(bool)"), 
+                     self.__activateFilter)
+        self.__menu.addAction(self.trUtf8("Filter c&onfiguration..."), 
+                              self.__configureFilter)
+        self.__menu.addSeparator()
+        self.__menu.addAction(self.trUtf8("Resi&ze columns"), self.__resizeColumns)
+        self.__menu.addSeparator()
+        self.__menu.addAction(self.trUtf8("Configure..."), self.__configure)
+        
+        self.__backMenu = QMenu(self)
+        self.__backMenu.addAction(self.trUtf8("&New Task..."), self.__newTask)
+        self.__backMenu.addSeparator()
+        self.backRegenerateProjectTasksItem = \
+            self.__backMenu.addAction(self.trUtf8("&Regenerate project tasks"),
+                                      self.__regenerateProjectTasks)
+        self.__backMenu.addSeparator()
+        self.backPasteItem = self.__backMenu.addAction(self.trUtf8("&Paste"), 
+                                                       self.__pasteTask)
+        self.__backMenu.addSeparator()
+        self.__backMenu.addAction(self.trUtf8("Delete Completed &Tasks"),
+                                  self.__deleteCompleted)
+        self.__backMenu.addSeparator()
+        self.__backMenuFilteredAct = \
+            self.__backMenu.addAction(self.trUtf8("&Filtered display")) 
+        self.__backMenuFilteredAct.setCheckable(True)
+        self.__backMenuFilteredAct.setChecked(False)
+        self.connect(self.__backMenuFilteredAct, SIGNAL("triggered(bool)"), 
+                     self.__activateFilter)
+        self.__backMenu.addAction(self.trUtf8("Filter c&onfiguration..."), 
+                              self.__configureFilter)
+        self.__backMenu.addSeparator()
+        self.__backMenu.addAction(self.trUtf8("Resi&ze columns"), self.__resizeColumns)
+        self.__backMenu.addSeparator()
+        self.__backMenu.addAction(self.trUtf8("Configure..."), self.__configure)
+        
+        self.setContextMenuPolicy(Qt.CustomContextMenu)
+        self.connect(self, SIGNAL("customContextMenuRequested(const QPoint &)"),
+                     self.__showContextMenu)
+        self.connect(self, SIGNAL("itemActivated(QTreeWidgetItem *, int)"),
+                     self.__taskItemActivated)
+        
+        self.setWindowIcon(UI.PixmapCache.getIcon("eric.png"))
+    
+    def __resort(self):
+        """
+        Private method to resort the tree.
+        """
+        self.sortItems(self.sortColumn(), self.header().sortIndicatorOrder())
+        
+    def __resizeColumns(self):
+        """
+        Private method to resize the list columns.
+        """
+        self.header().resizeSections(QHeaderView.ResizeToContents)
+        self.header().setStretchLastSection(True)
+        
+    def __refreshDisplay(self):
+        """
+        Private method to refresh the display.
+        """
+        for task in self.tasks:
+            index = self.indexOfTopLevelItem(task)
+            if self.taskFilter.showTask(task):
+                # show the task
+                if index == -1:
+                    self.addTopLevelItem(task)
+            else:
+                # hide the task
+                if index != -1:
+                    self.takeTopLevelItem(index)
+        self.__resort()
+        self.__resizeColumns()
+        
+    def __taskItemActivated(self, itm, col):
+        """
+        Private slot to handle the activation of an item. 
+        
+        @param itm reference to the activated item (QTreeWidgetItem)
+        @param col column the item was activated in (integer)
+        """
+        fn = itm.getFilename()
+        if fn:
+            self.emit(SIGNAL("displayFile"), fn, itm.getLineno())
+        else:
+            self.__editTaskProperties()
+
+    def __showContextMenu(self, coord):
+        """
+        Private slot to show the context menu of the list.
+        
+        @param coord the position of the mouse pointer (QPoint)
+        """
+        itm = self.itemAt(coord)
+        coord = self.mapToGlobal(coord)
+        if itm is None:
+            self.backRegenerateProjectTasksItem.setEnabled(self.projectOpen)
+            if self.copyTask:
+                self.backPasteItem.setEnabled(True)
+            else:
+                self.backPasteItem.setEnabled(False)
+            self.__backMenu.popup(coord)
+        else:
+            self.regenerateProjectTasksItem.setEnabled(self.projectOpen)
+            if itm.getFilename():
+                self.gotoItem.setEnabled(True)
+                self.deleteItem.setEnabled(True)
+                self.markCompletedItem.setEnabled(False)
+                self.copyItem.setEnabled(False)
+            else:
+                self.gotoItem.setEnabled(False)
+                self.deleteItem.setEnabled(True)
+                self.markCompletedItem.setEnabled(True)
+                self.copyItem.setEnabled(True)
+            if self.copyTask:
+                self.pasteItem.setEnabled(True)
+            else:
+                self.pasteItem.setEnabled(False)
+            
+            self.__menu.popup(coord)
+    
+    def setProjectOpen(self, o = False):
+        """
+        Public slot to set the project status.
+        
+        @param o flag indicating the project status
+        """
+        self.projectOpen = o
+    
+    def addTask(self, description, priority = 1, filename = "", lineno = 0, 
+                completed = False, _time = 0, isProjectTask = False, 
+                isBugfixTask = False, longtext = ""):
+        """
+        Public slot to add a task.
+        
+        @param description descriptive text of the task (string)
+        @param priority priority of the task (0=high, 1=normal, 2=low)
+        @param filename filename containing the task (string)
+        @param lineno line number containing the task (integer)
+        @param completed flag indicating completion status (boolean)
+        @param _time creation time of the task (float, if 0 use current time)
+        @param isProjectTask flag indicating a task related to the current 
+            project (boolean)
+        @param isBugfixTask flag indicating a bugfix task (boolean)
+        @param longtext explanatory text of the task (string)
+        """
+        task = Task(description, priority, filename, lineno, completed, 
+                   _time, isProjectTask, isBugfixTask, 
+                   self.project and self.project.ppath or "", 
+                   longtext)
+        self.tasks.append(task)
+        if self.taskFilter.showTask(task):
+            self.addTopLevelItem(task)
+            self.__resort()
+            self.__resizeColumns()
+    
+    def addFileTask(self, description, filename, lineno, isBugfixTask = False, 
+                    longtext = ""):
+        """
+        Public slot to add a file related task.
+        
+        @param description descriptive text of the task (string)
+        @param filename filename containing the task (string)
+        @param lineno line number containing the task (integer)
+        @param isBugfixTask flag indicating a bugfix task (boolean)
+        @param longtext explanatory text of the task (string)
+        """
+        self.addTask(description, filename = filename, lineno = lineno,
+                     isProjectTask = \
+                        self.project and self.project.isProjectSource(filename),
+                     isBugfixTask = isBugfixTask, longtext = longtext)
+        
+    def getProjectTasks(self):
+        """
+        Public method to retrieve all project related tasks.
+        
+        @return copy of tasks (list of Task)
+        """
+        tasks = [task for task in self.tasks if task.isProjectTask()]
+        return tasks[:]
+        
+    def getGlobalTasks(self):
+        """
+        Public method to retrieve all non project related tasks.
+        
+        @return copy of tasks (list of Task)
+        """
+        tasks = [task for task in self.tasks if not task.isProjectTask()]
+        return tasks[:]
+        
+    def clearTasks(self):
+        """
+        Public slot to clear all tasks from display.
+        """
+        self.tasks = []
+        self.clear()
+        
+    def clearProjectTasks(self):
+        """
+        Public slot to clear project related tasks.
+        """
+        for task in self.tasks[:]:
+            if task.isProjectTask():
+                if self.copyTask == task:
+                    self.copyTask = None
+                index = self.indexOfTopLevelItem(task)
+                self.takeTopLevelItem(index)
+                self.tasks.remove(task)
+                del task
+        
+    def clearFileTasks(self, filename):
+        """
+        Public slot to clear all tasks related to a file.
+        
+        @param filename name of the file (string)
+        """
+        for task in self.tasks[:]:
+            if task.getFilename() == filename:
+                if self.copyTask == task:
+                    self.copyTask = None
+                index = self.indexOfTopLevelItem(task)
+                self.takeTopLevelItem(index)
+                self.tasks.remove(task)
+                del task
+        
+    def __editTaskProperties(self):
+        """
+        Private slot to handle the "Properties" context menu entry
+        """
+        task = self.currentItem()
+        dlg = TaskPropertiesDialog(task, self, self.projectOpen)
+        ro = task.getFilename() != ""
+        if ro:
+            dlg.setReadOnly()
+        if dlg.exec_() == QDialog.Accepted and not ro:
+            data = dlg.getData()
+            task.setDescription(data[0])
+            task.setPriority(data[1])
+            task.setCompleted(data[2])
+            task.setProjectTask(data[3])
+            task.setLongText(data[4])
+    
+    def __newTask(self):
+        """
+        Private slot to handle the "New Task" context menu entry.
+        """
+        dlg = TaskPropertiesDialog(None, self, self.projectOpen)
+        if dlg.exec_() == QDialog.Accepted:
+            data = dlg.getData()
+            self.addTask(data[0], data[1], completed =  data[2], isProjectTask = data[3], 
+                longtext = data[4])
+    
+    def __markCompleted(self):
+        """
+        Private slot to handle the "Mark Completed" context menu entry.
+        """
+        task = self.currentItem()
+        task.setCompleted(True)
+    
+    def __deleteCompleted(self):
+        """
+        Private slot to handle the "Delete Completed Tasks" context menu entry.
+        """
+        for task in self.tasks[:]:
+            if task.isCompleted():
+                if self.copyTask == task:
+                    self.copyTask = None
+                index = self.indexOfTopLevelItem(task)
+                self.takeTopLevelItem(index)
+                self.tasks.remove(task)
+                del task
+        ci = self.currentItem()
+        if ci:
+            ind = self.indexFromItem(ci, self.currentColumn())
+            self.scrollTo(ind, QAbstractItemView.PositionAtCenter)
+    
+    def __copyTask(self):
+        """
+        Private slot to handle the "Copy" context menu entry.
+        """
+        task = self.currentItem()
+        self.copyTask = task
+    
+    def __pasteTask(self):
+        """
+        Private slot to handle the "Paste" context menu entry.
+        """
+        if self.copyTask:
+            self.addTask(self.copyTask.description,
+                         priority = self.copyTask.priority,
+                         completed = self.copyTask.completed, 
+                         longtext = self.copyTask.longtext, 
+                         isProjectTask = self.copyTask._isProjectTask)
+    
+    def __deleteTask(self):
+        """
+        Private slot to handle the "Delete Task" context menu entry.
+        """
+        task = self.currentItem()
+        if self.copyTask == task:
+            self.copyTask = None
+        index = self.indexOfTopLevelItem(task)
+        self.takeTopLevelItem(index)
+        self.tasks.remove(task)
+        del task
+        ci = self.currentItem()
+        if ci:
+            ind = self.indexFromItem(ci, self.currentColumn())
+            self.scrollTo(ind, QAbstractItemView.PositionAtCenter)
+    
+    def __goToTask(self):
+        """
+        Private slot to handle the "Go To" context menu entry.
+        """
+        task = self.currentItem()
+        self.emit(SIGNAL('displayFile'), task.getFilename(), task.getLineno())
+
+    def handlePreferencesChanged(self):
+        """
+        Public slot to react to changes of the preferences.
+        """
+        for task in self.tasks:
+            task.colorizeTask()
+
+    def __activateFilter(self, on):
+        """
+        Private slot to handle the "Filtered display" context menu entry.
+        
+        @param on flag indicating the filter state (boolean)
+        """
+        if on and not self.taskFilter.hasActiveFilter():
+            res = QMessageBox.information(None,
+                self.trUtf8("Activate task filter"),
+                self.trUtf8("""The task filter doesn't have any active filters."""
+                            """ Do you want to configure the filter settings?"""),
+                QMessageBox.StandardButtons(\
+                    QMessageBox.No | \
+                    QMessageBox.Yes),
+                QMessageBox.Yes)
+            if res != QMessageBox.Yes:
+                on = False
+            else:
+                self.__configureFilter()
+                on = self.taskFilter.hasActiveFilter()
+        
+        self.taskFilter.setActive(on)
+        self.__menuFilteredAct.setChecked(on)
+        self.__backMenuFilteredAct.setChecked(on)
+        self.__refreshDisplay()
+    
+    def __configureFilter(self):
+        """
+        Private slot to handle the "Configure filter" context menu entry.
+        """
+        dlg = TaskFilterConfigDialog(self.taskFilter)
+        if dlg.exec_() == QDialog.Accepted:
+            dlg.configureTaskFilter(self.taskFilter)
+            self.__refreshDisplay()
+
+    def __regenerateProjectTasks(self):
+        """
+        Private slot to handle the "Regenerated project tasks" context menu entry.
+        """
+        todoMarkers = Preferences.getTasks("TasksMarkers").split()
+        bugfixMarkers = Preferences.getTasks("TasksMarkersBugfix").split()
+        files = self.project.pdata["SOURCES"]
+        
+        # remove all project tasks
+        self.clearProjectTasks()
+        
+        # now process them
+        progress = QProgressDialog(self.trUtf8("Extracting project tasks..."), 
+            self.trUtf8("Abort"), 0, len(files))
+        progress.setMinimumDuration(0)
+        count = 0
+        
+        for file in files:
+            progress.setLabelText(\
+                self.trUtf8("Extracting project tasks...\n{0}").format(file))
+            progress.setValue(count)
+            QApplication.processEvents()
+            if progress.wasCanceled():
+                break
+            
+            fn = os.path.join(self.project.ppath, file)
+            # read the file and split it into textlines
+            try:
+                f = open(fn, 'rb')
+                text, encoding = Utilities.decode(f.read())
+                lines = text.splitlines()
+                f.close()
+            except IOError:
+                count += 1
+                self.progress.setValue(count)
+                continue
+            
+            # now search tasks and record them
+            lineIndex = 0
+            for line in lines:
+                lineIndex += 1
+                shouldContinue = False
+                # normal tasks first
+                for tasksMarker in todoMarkers:
+                    index = line.find(tasksMarker)
+                    if index > -1:
+                        task = line[index:]
+                        self.addFileTask(task, fn, lineIndex, False)
+                        shouldContinue = True
+                        break
+                if shouldContinue:
+                    continue
+                
+                # bugfix tasks second
+                for tasksMarker in bugfixMarkers:
+                    index = line.find(tasksMarker)
+                    if index > -1:
+                        task = line[index:]
+                        self.addFileTask(task, fn, lineIndex, True)
+                        shouldContinue = True
+                        break
+            
+            count += 1
+            
+        progress.setValue(len(files))
+    
+    def __configure(self):
+        """
+        Private method to open the configuration dialog.
+        """
+        e4App().getObject("UserInterface").showPreferences("tasksPage")

eric ide

mercurial