src/eric7/VCS/StatusMonitorThread.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2006 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the VCS status monitor thread base class.
8 """
9
10 import contextlib
11
12 from PyQt6.QtCore import (
13 QThread, QMutex, QWaitCondition, pyqtSignal, QCoreApplication
14 )
15
16
17 class VcsStatusMonitorThread(QThread):
18 """
19 Class implementing the VCS status monitor thread base class.
20
21 @signal vcsStatusMonitorData(list of str) emitted to update the VCS status
22 @signal vcsStatusMonitorAllData(dict) emitted to signal all VCS status
23 (key is project relative file name, value is status)
24 @signal vcsStatusMonitorStatus(str, str) emitted to signal the status of
25 the monitoring thread (ok, nok, op) and a status message
26 @signal vcsStatusMonitorInfo(str) emitted to signal some info of the
27 monitoring thread
28 """
29 vcsStatusMonitorData = pyqtSignal(list)
30 vcsStatusMonitorAllData = pyqtSignal(dict)
31 vcsStatusMonitorStatus = pyqtSignal(str, str)
32 vcsStatusMonitorInfo = pyqtSignal(str)
33
34 def __init__(self, interval, project, vcs, parent=None):
35 """
36 Constructor
37
38 @param interval new interval in seconds (integer)
39 @param project reference to the project object (Project)
40 @param vcs reference to the version control object
41 @param parent reference to the parent object (QObject)
42 """
43 super().__init__(parent)
44 self.setObjectName("VcsStatusMonitorThread")
45
46 self.setTerminationEnabled(True)
47
48 self.projectDir = project.getProjectPath()
49 self.project = project
50 self.vcs = vcs
51
52 self.interval = interval
53 self.autoUpdate = False
54
55 self.statusList = []
56 self.reportedStates = {}
57 self.shouldUpdate = False
58
59 self.monitorMutex = QMutex()
60 self.monitorCondition = QWaitCondition()
61 self.__stopIt = False
62
63 def run(self):
64 """
65 Public method implementing the tasks action.
66 """
67 while not self.__stopIt:
68 # perform the checking task
69 self.statusList = []
70 self.vcsStatusMonitorStatus.emit(
71 "wait", QCoreApplication.translate(
72 "VcsStatusMonitorThread", "Waiting for lock"))
73 try:
74 locked = self.vcs.vcsExecutionMutex.tryLock(5000)
75 except TypeError:
76 locked = self.vcs.vcsExecutionMutex.tryLock()
77 if locked:
78 try:
79 self.vcsStatusMonitorStatus.emit(
80 "op", QCoreApplication.translate(
81 "VcsStatusMonitorThread",
82 "Checking repository status"))
83 res, statusMsg = self._performMonitor()
84 infoMsg = self._getInfo()
85 finally:
86 self.vcs.vcsExecutionMutex.unlock()
87 if res:
88 status = "ok"
89 else:
90 status = "nok"
91 self.vcsStatusMonitorStatus.emit(
92 "send", QCoreApplication.translate(
93 "VcsStatusMonitorThread", "Sending data"))
94 self.vcsStatusMonitorData.emit(self.statusList)
95 self.vcsStatusMonitorAllData.emit(self.reportedStates)
96 self.vcsStatusMonitorStatus.emit(status, statusMsg)
97 self.vcsStatusMonitorInfo.emit(infoMsg)
98 else:
99 self.vcsStatusMonitorStatus.emit(
100 "timeout", QCoreApplication.translate(
101 "VcsStatusMonitorThread",
102 "Timed out waiting for lock"))
103 self.vcsStatusMonitorInfo.emit("")
104
105 if self.autoUpdate and self.shouldUpdate:
106 self.vcs.vcsUpdate(self.projectDir, True)
107 continue # check again
108 self.shouldUpdate = False
109
110 # wait until interval has expired checking for a stop condition
111 self.monitorMutex.lock()
112 if not self.__stopIt:
113 self.monitorCondition.wait(
114 self.monitorMutex, self.interval * 1000)
115 self.monitorMutex.unlock()
116
117 self._shutdown()
118 self.exit()
119
120 def setInterval(self, interval):
121 """
122 Public method to change the monitor interval.
123
124 @param interval new interval in seconds (integer)
125 """
126 locked = self.monitorMutex.tryLock()
127 self.interval = interval
128 self.monitorCondition.wakeAll()
129 if locked:
130 self.monitorMutex.unlock()
131
132 def getInterval(self):
133 """
134 Public method to get the monitor interval.
135
136 @return interval in seconds (integer)
137 """
138 return self.interval
139
140 def setAutoUpdate(self, auto):
141 """
142 Public method to enable the auto update function.
143
144 @param auto status of the auto update function (boolean)
145 """
146 self.autoUpdate = auto
147
148 def getAutoUpdate(self):
149 """
150 Public method to retrieve the status of the auto update function.
151
152 @return status of the auto update function (boolean)
153 """
154 return self.autoUpdate
155
156 def checkStatus(self):
157 """
158 Public method to wake up the status monitor thread.
159 """
160 locked = self.monitorMutex.tryLock()
161 self.monitorCondition.wakeAll()
162 if locked:
163 self.monitorMutex.unlock()
164
165 def stop(self):
166 """
167 Public method to stop the monitor thread.
168 """
169 locked = self.monitorMutex.tryLock()
170 self.__stopIt = True
171 self.monitorCondition.wakeAll()
172 if locked:
173 self.monitorMutex.unlock()
174
175 def clearCachedState(self, name):
176 """
177 Public method to clear the cached VCS state of a file/directory.
178
179 @param name name of the entry to be cleared (string)
180 """
181 key = self.project.getRelativePath(name)
182 with contextlib.suppress(KeyError):
183 del self.reportedStates[key]
184
185 def _performMonitor(self):
186 """
187 Protected method implementing the real monitoring action.
188
189 This method must be overridden and populate the statusList member
190 variable with a list of strings giving the status in the first column
191 and the path relative to the project directory starting with the
192 third column. The allowed status flags are:
193 <ul>
194 <li>"A" path was added but not yet committed</li>
195 <li>"M" path has local changes</li>
196 <li>"O" path was removed</li>
197 <li>"R" path was deleted and then re-added</li>
198 <li>"U" path needs an update</li>
199 <li>"Z" path contains a conflict</li>
200 <li>"?" path is not tracked</li>
201 <li>"!" path is missing</li>
202 <li>" " path is back at normal</li>
203 </ul>
204
205 @return tuple of flag indicating successful operation (boolean) and
206 a status message in case of non successful operation (string)
207 @exception RuntimeError to indicate that this method must be
208 implemented by a subclass
209 """
210 raise RuntimeError('Not implemented')
211
212 return ()
213
214 def _getInfo(self):
215 """
216 Protected method implementing the real info action.
217
218 This method should be overridden and create a short info message to be
219 shown in the main window status bar right next to the status indicator.
220
221 @return short info message
222 @rtype str
223 """
224 return ""
225
226 def _shutdown(self):
227 """
228 Protected method performing shutdown actions.
229
230 The default implementation does nothing.
231 """
232 pass

eric ide

mercurial