eric7/VCS/StatusMonitorThread.py

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

eric ide

mercurial