152 self.inputGroup.setEnabled(False) |
203 self.inputGroup.setEnabled(False) |
153 self.inputGroup.hide() |
204 self.inputGroup.hide() |
154 |
205 |
155 self.contents.clear() |
206 self.contents.clear() |
156 |
207 |
157 if not self.buf: |
208 if not self.logEntries: |
158 self.errors.append(self.trUtf8("No log available for '{0}'")\ |
209 self.errors.append(self.trUtf8("No log available for '{0}'")\ |
159 .format(self.filename)) |
210 .format(self.filename)) |
160 self.errorGroup.show() |
211 self.errorGroup.show() |
161 return |
212 return |
162 |
213 |
163 hasInitialText = 0 # three states flag (-1, 0, 1) |
214 if self.initialText: |
164 lvers = 1 |
215 self.contents.insertHtml(Utilities.html_encode(self.initialText.strip())) |
165 fileCopies = {} |
216 self.contents.insertHtml('<br />\n') |
166 for s in self.buf: |
217 self.contents.insertHtml('{0}<br/>\n'.format(80 * "=")) |
|
218 |
|
219 for entry in self.logEntries: |
|
220 fileCopies = {} |
|
221 for fentry in entry["file_copies"].split(", "): |
|
222 newName, oldName = entry[:-1].split(" (") |
|
223 fileCopies[newName] = oldName |
|
224 |
|
225 rev, hexRev = entry["change"].split(":") |
|
226 dstr = '<p><b>{0} {1}</b>'.format(self.revString, entry["change"]) |
|
227 parents = self.__getParents(rev) |
|
228 for parent in parents: |
|
229 url = QUrl() |
|
230 url.setScheme("file") |
|
231 url.setPath(self.filename) |
|
232 query = QByteArray() |
|
233 query.append(parent.split(":")[0]).append('_').append(rev) |
|
234 url.setEncodedQuery(query) |
|
235 dstr += ' [<a href="{0}" name="{1}" id="{1}">{2}</a>]'.format( |
|
236 url.toString(), |
|
237 str(query, encoding="ascii"), |
|
238 self.trUtf8('diff to {0}').format(parent), |
|
239 ) |
|
240 dstr += '<br />\n' |
|
241 self.contents.insertHtml(dstr) |
|
242 |
|
243 self.contents.insertHtml(self.trUtf8("Branches: {0}<br />\n")\ |
|
244 .format(entry["branches"])) |
|
245 |
|
246 self.contents.insertHtml(self.trUtf8("Tags: {0}<br />\n")\ |
|
247 .format(entry["tags"])) |
|
248 |
|
249 self.contents.insertHtml(self.trUtf8("Parents: {0}<br />\n")\ |
|
250 .format(entry["parents"])) |
|
251 |
|
252 self.contents.insertHtml(self.trUtf8('<i>Author: {0}</i><br />\n')\ |
|
253 .format(entry["user"])) |
|
254 |
|
255 date, time = entry["date"].split()[:2] |
|
256 self.contents.insertHtml(self.trUtf8('<i>Date: {0}, {1}</i><br />\n')\ |
|
257 .format(date, time)) |
|
258 |
|
259 for line in entry["description"]: |
|
260 self.contents.insertHtml(Utilities.html_encode(line.strip())) |
|
261 self.contents.insertHtml('<br />\n') |
|
262 |
|
263 if entry["file_adds"]: |
|
264 self.contents.insertHtml('<br />\n') |
|
265 for f in entry["file_adds"].strip().split(", "): |
|
266 if f in fileCopies: |
|
267 self.contents.insertHtml( |
|
268 self.trUtf8('Added {0} (copied from {1})<br />\n')\ |
|
269 .format(Utilities.html_encode(f), |
|
270 Utilities.html_encode(fileCopies[f]))) |
|
271 else: |
|
272 self.contents.insertHtml( |
|
273 self.trUtf8('Added {0}<br />\n')\ |
|
274 .format(Utilities.html_encode(f))) |
|
275 |
|
276 if entry["files_mods"]: |
|
277 self.contents.insertHtml('<br />\n') |
|
278 for f in entry["files_mods"].strip().split(", "): |
|
279 self.contents.insertHtml( |
|
280 self.trUtf8('Modified {0}<br />\n')\ |
|
281 .format(Utilities.html_encode(f))) |
|
282 |
|
283 if entry["file_dels"]: |
|
284 self.contents.insertHtml('<br />\n') |
|
285 for f in entry["file_dels"].strip().split(", "): |
|
286 self.contents.insertHtml( |
|
287 self.trUtf8('Deleted {0}<br />\n')\ |
|
288 .format(Utilities.html_encode(f))) |
|
289 |
|
290 self.contents.insertHtml('</p>{0}<br/>\n'.format(80 * "=")) |
|
291 |
|
292 tc = self.contents.textCursor() |
|
293 tc.movePosition(QTextCursor.Start) |
|
294 self.contents.setTextCursor(tc) |
|
295 self.contents.ensureCursorVisible() |
|
296 |
|
297 def __readStdout(self): |
|
298 """ |
|
299 Private slot to handle the readyReadStandardOutput signal. |
|
300 |
|
301 It reads the output of the process and inserts it into a buffer. |
|
302 """ |
|
303 self.process.setReadChannel(QProcess.StandardOutput) |
|
304 |
|
305 while self.process.canReadLine(): |
|
306 s = str(self.process.readLine(), |
|
307 Preferences.getSystem("IOEncoding"), |
|
308 'replace') |
|
309 ## self.buf.append(line) |
|
310 ## |
|
311 ## if line.startswith("change|"): |
|
312 ## ver = line[7:] |
|
313 ## # save revision number for later use |
|
314 ## self.revisions.append(ver) |
|
315 |
167 if s == "@@@\n": |
316 if s == "@@@\n": |
168 self.contents.insertHtml('</p>{0}<br/>\n'.format(80 * "=")) |
317 self.logEntries.append(self.lastLogEntry) |
169 fileCopies = {} |
318 self.lastLogEntry = {} |
|
319 self.fileCopies = {} |
170 else: |
320 else: |
171 try: |
321 try: |
172 key, value = s.split("|", 1) |
322 key, value = s.split("|", 1) |
173 except ValueError: |
323 except ValueError: |
174 key = "" |
324 key = "" |
175 value = s |
325 value = s |
176 if key == "change": |
326 if key == "change": |
177 if hasInitialText == 1: |
327 self.endInitialText = True |
178 self.contents.insertHtml('{0}<br/>\n'.format(80 * "=")) |
328 if key in ("change", "branches", "tags", "parents", "user", |
179 hasInitialText = -1 |
329 "date", "file_copies", "file_adds", "files_mods", |
180 rev, hexRev = value.split(":") |
330 "file_dels"): |
181 dstr = '<p><b>{0} {1}</b>'.format(self.revString, value) |
331 self.lastLogEntry[key] = value.strip() |
182 try: |
|
183 lv = self.revisions[lvers] |
|
184 lvers += 1 |
|
185 except IndexError: |
|
186 lv = str(int(rev) - 1) |
|
187 if rev != "0": |
|
188 url = QUrl() |
|
189 url.setScheme("file") |
|
190 url.setPath(self.filename) |
|
191 query = QByteArray() |
|
192 query.append(lv.split(":")[0]).append('_').append(rev) |
|
193 url.setEncodedQuery(query) |
|
194 dstr += ' [<a href="{0}" name="{1}" id="{1}">{2}</a>]'.format( |
|
195 url.toString(), |
|
196 str(query, encoding="ascii"), |
|
197 self.trUtf8('diff to {0}').format(lv), |
|
198 ) |
|
199 dstr += '<br />\n' |
|
200 self.contents.insertHtml(dstr) |
|
201 elif key == "branches": |
|
202 if value.strip(): |
|
203 self.contents.insertHtml(self.trUtf8("Branches: {0}<br />\n")\ |
|
204 .format(value.strip())) |
|
205 elif key == "tags": |
|
206 if value.strip(): |
|
207 self.contents.insertHtml(self.trUtf8("Tags: {0}<br />\n")\ |
|
208 .format(value.strip())) |
|
209 elif key == "parents": |
|
210 if value.strip(): |
|
211 self.contents.insertHtml(self.trUtf8("Parents: {0}<br />\n")\ |
|
212 .format(value.strip())) |
|
213 elif key == "user": |
|
214 dstr = self.contents.insertHtml( |
|
215 self.trUtf8('<i>Author: {0}</i><br />\n').format(value.strip())) |
|
216 elif key == "date": |
|
217 date, time = value.strip().split()[:2] |
|
218 dstr = self.contents.insertHtml( |
|
219 self.trUtf8('<i>Date: {0}, {1}</i><br />\n')\ |
|
220 .format(date, time)) |
|
221 elif key == "description": |
332 elif key == "description": |
222 self.contents.insertHtml(Utilities.html_encode(value.strip())) |
333 self.lastLogEntry[key] = [value.strip()] |
223 self.contents.insertHtml('<br />\n') |
|
224 elif key == "file_copies": |
|
225 if value.strip(): |
|
226 for entry in value.strip().split(", "): |
|
227 newName, oldName = entry[:-1].split(" (") |
|
228 fileCopies[newName] = oldName |
|
229 elif key == "file_adds": |
|
230 if value.strip(): |
|
231 self.contents.insertHtml('<br />\n') |
|
232 for f in value.strip().split(", "): |
|
233 if f in fileCopies: |
|
234 self.contents.insertHtml( |
|
235 self.trUtf8('Added {0} (copied from {1})<br />\n')\ |
|
236 .format(Utilities.html_encode(f), |
|
237 Utilities.html_encode(fileCopies[f]))) |
|
238 else: |
|
239 self.contents.insertHtml( |
|
240 self.trUtf8('Added {0}<br />\n')\ |
|
241 .format(Utilities.html_encode(f))) |
|
242 elif key == "files_mods": |
|
243 if value.strip(): |
|
244 self.contents.insertHtml('<br />\n') |
|
245 for f in value.strip().split(", "): |
|
246 self.contents.insertHtml( |
|
247 self.trUtf8('Modified {0}<br />\n')\ |
|
248 .format(Utilities.html_encode(f))) |
|
249 elif key == "file_dels": |
|
250 if value.strip(): |
|
251 self.contents.insertHtml('<br />\n') |
|
252 for f in value.strip().split(", "): |
|
253 self.contents.insertHtml( |
|
254 self.trUtf8('Deleted {0}<br />\n')\ |
|
255 .format(Utilities.html_encode(f))) |
|
256 else: |
334 else: |
257 if value.strip(): |
335 if self.endInitialText: |
258 self.contents.insertHtml(Utilities.html_encode(value.strip())) |
336 self.lastLogEntry["description"].append(value.strip()) |
259 self.contents.insertHtml('<br />\n') |
337 else: |
260 if hasInitialText == 0: |
338 self.initialText.append(value) |
261 hasInitialText = 1 |
|
262 |
|
263 tc = self.contents.textCursor() |
|
264 tc.movePosition(QTextCursor.Start) |
|
265 self.contents.setTextCursor(tc) |
|
266 self.contents.ensureCursorVisible() |
|
267 |
|
268 def __readStdout(self): |
|
269 """ |
|
270 Private slot to handle the readyReadStandardOutput signal. |
|
271 |
|
272 It reads the output of the process and inserts it into a buffer. |
|
273 """ |
|
274 self.process.setReadChannel(QProcess.StandardOutput) |
|
275 |
|
276 while self.process.canReadLine(): |
|
277 line = str(self.process.readLine(), |
|
278 Preferences.getSystem("IOEncoding"), |
|
279 'replace') |
|
280 self.buf.append(line) |
|
281 |
|
282 if line.startswith("change|"): |
|
283 ver = line[7:] |
|
284 # save revision number for later use |
|
285 self.revisions.append(ver) |
|
286 |
339 |
287 def __readStderr(self): |
340 def __readStderr(self): |
288 """ |
341 """ |
289 Private slot to handle the readyReadStandardError signal. |
342 Private slot to handle the readyReadStandardError signal. |
290 |
343 |