28 |
39 |
29 class HistoryEntry: |
40 class HistoryEntry: |
30 """ |
41 """ |
31 Class implementing a history entry. |
42 Class implementing a history entry. |
32 """ |
43 """ |
|
44 |
33 def __init__(self, url=None, dateTime=None, title=None, visitCount=None): |
45 def __init__(self, url=None, dateTime=None, title=None, visitCount=None): |
34 """ |
46 """ |
35 Constructor |
47 Constructor |
36 |
48 |
37 @param url URL of the history entry (string) |
49 @param url URL of the history entry (string) |
38 @param dateTime date and time this entry was created (QDateTime) |
50 @param dateTime date and time this entry was created (QDateTime) |
39 @param title title string for the history entry (string) |
51 @param title title string for the history entry (string) |
40 @param visitCount number of visits of this URL (int) |
52 @param visitCount number of visits of this URL (int) |
41 """ |
53 """ |
42 self.url = url and url or "" |
54 self.url = url and url or "" |
43 self.dateTime = dateTime and dateTime or QDateTime() |
55 self.dateTime = dateTime and dateTime or QDateTime() |
44 self.title = title and title or "" |
56 self.title = title and title or "" |
45 self.visitCount = visitCount and visitCount or 0 |
57 self.visitCount = visitCount and visitCount or 0 |
46 |
58 |
47 def __eq__(self, other): |
59 def __eq__(self, other): |
48 """ |
60 """ |
49 Special method determining equality. |
61 Special method determining equality. |
50 |
62 |
51 @param other reference to the history entry to compare against |
63 @param other reference to the history entry to compare against |
52 (HistoryEntry) |
64 (HistoryEntry) |
53 @return flag indicating equality (boolean) |
65 @return flag indicating equality (boolean) |
54 """ |
66 """ |
55 return ( |
67 return ( |
56 other.title == self.title and |
68 other.title == self.title |
57 other.url == self.url and |
69 and other.url == self.url |
58 other.dateTime == self.dateTime |
70 and other.dateTime == self.dateTime |
59 ) |
71 ) |
60 |
72 |
61 def __lt__(self, other): |
73 def __lt__(self, other): |
62 """ |
74 """ |
63 Special method determining less relation. |
75 Special method determining less relation. |
64 |
76 |
65 Note: History is sorted in reverse order by date and time |
77 Note: History is sorted in reverse order by date and time |
66 |
78 |
67 @param other reference to the history entry to compare against |
79 @param other reference to the history entry to compare against |
68 (HistoryEntry) |
80 (HistoryEntry) |
69 @return flag indicating less (boolean) |
81 @return flag indicating less (boolean) |
70 """ |
82 """ |
71 return self.dateTime > other.dateTime |
83 return self.dateTime > other.dateTime |
72 |
84 |
73 def userTitle(self): |
85 def userTitle(self): |
74 """ |
86 """ |
75 Public method to get the title of the history entry. |
87 Public method to get the title of the history entry. |
76 |
88 |
77 @return title of the entry (string) |
89 @return title of the entry (string) |
78 """ |
90 """ |
79 if not self.title: |
91 if not self.title: |
80 page = pathlib.Path(QUrl(self.url).path()).name |
92 page = pathlib.Path(QUrl(self.url).path()).name |
81 if page: |
93 if page: |
82 return page |
94 return page |
83 return self.url |
95 return self.url |
84 return self.title |
96 return self.title |
85 |
97 |
86 def isValid(self): |
98 def isValid(self): |
87 """ |
99 """ |
88 Public method to determine validity. |
100 Public method to determine validity. |
89 |
101 |
90 @return flag indicating validity |
102 @return flag indicating validity |
91 @rtype bool |
103 @rtype bool |
92 """ |
104 """ |
93 return bool(self.url) and self.dateTime.isValid() |
105 return bool(self.url) and self.dateTime.isValid() |
94 |
106 |
95 |
107 |
96 class HistoryManager(QObject): |
108 class HistoryManager(QObject): |
97 """ |
109 """ |
98 Class implementing the history manager. |
110 Class implementing the history manager. |
99 |
111 |
100 @signal historyCleared() emitted after the history has been cleared |
112 @signal historyCleared() emitted after the history has been cleared |
101 @signal historyReset() emitted after the history has been reset |
113 @signal historyReset() emitted after the history has been reset |
102 @signal entryAdded(HistoryEntry) emitted after a history entry has been |
114 @signal entryAdded(HistoryEntry) emitted after a history entry has been |
103 added |
115 added |
104 @signal entryRemoved(HistoryEntry) emitted after a history entry has been |
116 @signal entryRemoved(HistoryEntry) emitted after a history entry has been |
105 removed |
117 removed |
106 @signal entryUpdated(int) emitted after a history entry has been updated |
118 @signal entryUpdated(int) emitted after a history entry has been updated |
107 @signal historySaved() emitted after the history was saved |
119 @signal historySaved() emitted after the history was saved |
108 """ |
120 """ |
|
121 |
109 historyCleared = pyqtSignal() |
122 historyCleared = pyqtSignal() |
110 historyReset = pyqtSignal() |
123 historyReset = pyqtSignal() |
111 entryAdded = pyqtSignal(HistoryEntry) |
124 entryAdded = pyqtSignal(HistoryEntry) |
112 entryRemoved = pyqtSignal(HistoryEntry) |
125 entryRemoved = pyqtSignal(HistoryEntry) |
113 entryUpdated = pyqtSignal(int) |
126 entryUpdated = pyqtSignal(int) |
114 historySaved = pyqtSignal() |
127 historySaved = pyqtSignal() |
115 |
128 |
116 def __init__(self, parent=None): |
129 def __init__(self, parent=None): |
117 """ |
130 """ |
118 Constructor |
131 Constructor |
119 |
132 |
120 @param parent reference to the parent object (QObject) |
133 @param parent reference to the parent object (QObject) |
121 """ |
134 """ |
122 super().__init__(parent) |
135 super().__init__(parent) |
123 |
136 |
124 self.__saveTimer = AutoSaver(self, self.save) |
137 self.__saveTimer = AutoSaver(self, self.save) |
125 self.__daysToExpire = Preferences.getWebBrowser("HistoryLimit") |
138 self.__daysToExpire = Preferences.getWebBrowser("HistoryLimit") |
126 self.__history = [] |
139 self.__history = [] |
127 self.__lastSavedUrl = "" |
140 self.__lastSavedUrl = "" |
128 |
141 |
129 self.__expiredTimer = QTimer(self) |
142 self.__expiredTimer = QTimer(self) |
130 self.__expiredTimer.setSingleShot(True) |
143 self.__expiredTimer.setSingleShot(True) |
131 self.__expiredTimer.timeout.connect(self.__checkForExpired) |
144 self.__expiredTimer.timeout.connect(self.__checkForExpired) |
132 |
145 |
133 self.__frequencyTimer = QTimer(self) |
146 self.__frequencyTimer = QTimer(self) |
134 self.__frequencyTimer.setSingleShot(True) |
147 self.__frequencyTimer.setSingleShot(True) |
135 self.__frequencyTimer.timeout.connect(self.__refreshFrequencies) |
148 self.__frequencyTimer.timeout.connect(self.__refreshFrequencies) |
136 |
149 |
137 self.entryAdded.connect(self.__saveTimer.changeOccurred) |
150 self.entryAdded.connect(self.__saveTimer.changeOccurred) |
138 self.entryRemoved.connect(self.__saveTimer.changeOccurred) |
151 self.entryRemoved.connect(self.__saveTimer.changeOccurred) |
139 |
152 |
140 self.__load() |
153 self.__load() |
141 |
154 |
142 from .HistoryModel import HistoryModel |
155 from .HistoryModel import HistoryModel |
143 from .HistoryFilterModel import HistoryFilterModel |
156 from .HistoryFilterModel import HistoryFilterModel |
144 from .HistoryTreeModel import HistoryTreeModel |
157 from .HistoryTreeModel import HistoryTreeModel |
145 |
158 |
146 self.__historyModel = HistoryModel(self, self) |
159 self.__historyModel = HistoryModel(self, self) |
147 self.__historyFilterModel = HistoryFilterModel( |
160 self.__historyFilterModel = HistoryFilterModel(self.__historyModel, self) |
148 self.__historyModel, self) |
161 self.__historyTreeModel = HistoryTreeModel(self.__historyFilterModel, self) |
149 self.__historyTreeModel = HistoryTreeModel( |
162 |
150 self.__historyFilterModel, self) |
|
151 |
|
152 self.__startFrequencyTimer() |
163 self.__startFrequencyTimer() |
153 |
164 |
154 def close(self): |
165 def close(self): |
155 """ |
166 """ |
156 Public method to close the history manager. |
167 Public method to close the history manager. |
157 """ |
168 """ |
158 # remove history items on application exit |
169 # remove history items on application exit |
159 if self.__daysToExpire == -2: |
170 if self.__daysToExpire == -2: |
160 self.clear() |
171 self.clear() |
161 self.__saveTimer.saveIfNeccessary() |
172 self.__saveTimer.saveIfNeccessary() |
162 |
173 |
163 def history(self): |
174 def history(self): |
164 """ |
175 """ |
165 Public method to return the history. |
176 Public method to return the history. |
166 |
177 |
167 @return reference to the list of history entries (list of HistoryEntry) |
178 @return reference to the list of history entries (list of HistoryEntry) |
168 """ |
179 """ |
169 return self.__history[:] |
180 return self.__history[:] |
170 |
181 |
171 def setHistory(self, history, loadedAndSorted=False): |
182 def setHistory(self, history, loadedAndSorted=False): |
172 """ |
183 """ |
173 Public method to set a new history. |
184 Public method to set a new history. |
174 |
185 |
175 @param history reference to the list of history entries to be set |
186 @param history reference to the list of history entries to be set |
176 (list of HistoryEntry) |
187 (list of HistoryEntry) |
177 @param loadedAndSorted flag indicating that the list is sorted |
188 @param loadedAndSorted flag indicating that the list is sorted |
178 (boolean) |
189 (boolean) |
179 """ |
190 """ |
180 self.__history = history[:] |
191 self.__history = history[:] |
181 if not loadedAndSorted: |
192 if not loadedAndSorted: |
182 self.__history.sort() |
193 self.__history.sort() |
183 |
194 |
184 self.__checkForExpired() |
195 self.__checkForExpired() |
185 |
196 |
186 if loadedAndSorted: |
197 if loadedAndSorted: |
187 try: |
198 try: |
188 self.__lastSavedUrl = self.__history[0].url |
199 self.__lastSavedUrl = self.__history[0].url |
189 except IndexError: |
200 except IndexError: |
190 self.__lastSavedUrl = "" |
201 self.__lastSavedUrl = "" |
191 else: |
202 else: |
192 self.__lastSavedUrl = "" |
203 self.__lastSavedUrl = "" |
193 self.__saveTimer.changeOccurred() |
204 self.__saveTimer.changeOccurred() |
194 self.historyReset.emit() |
205 self.historyReset.emit() |
195 |
206 |
196 def __findFirstHistoryEntry(self, url): |
207 def __findFirstHistoryEntry(self, url): |
197 """ |
208 """ |
198 Private method to find the first entry for the given URL. |
209 Private method to find the first entry for the given URL. |
199 |
210 |
200 @param url URL to search for |
211 @param url URL to search for |
201 @type str |
212 @type str |
202 @return first entry for the given URL |
213 @return first entry for the given URL |
203 @rtype HistoryEntry |
214 @rtype HistoryEntry |
204 """ |
215 """ |
205 for index in range(len(self.__history)): |
216 for index in range(len(self.__history)): |
206 if url == self.__history[index].url: |
217 if url == self.__history[index].url: |
207 return self.__history[index] |
218 return self.__history[index] |
208 |
219 |
209 # not found, return an empty entry |
220 # not found, return an empty entry |
210 return HistoryEntry() |
221 return HistoryEntry() |
211 |
222 |
212 def __updateVisitCount(self, url, count): |
223 def __updateVisitCount(self, url, count): |
213 """ |
224 """ |
214 Private method to update the visit count for all entries of the |
225 Private method to update the visit count for all entries of the |
215 given URL. |
226 given URL. |
216 |
227 |
217 @param url URL to be updated |
228 @param url URL to be updated |
218 @type str |
229 @type str |
219 @param count new visit count |
230 @param count new visit count |
220 @type int |
231 @type int |
221 """ |
232 """ |
222 for index in range(len(self.__history)): |
233 for index in range(len(self.__history)): |
223 if url == self.__history[index].url: |
234 if url == self.__history[index].url: |
224 self.__history[index].visitCount = count |
235 self.__history[index].visitCount = count |
225 |
236 |
226 def addHistoryEntry(self, view): |
237 def addHistoryEntry(self, view): |
227 """ |
238 """ |
228 Public method to add a history entry. |
239 Public method to add a history entry. |
229 |
240 |
230 @param view reference to the view to add an entry for |
241 @param view reference to the view to add an entry for |
231 @type WebBrowserView |
242 @type WebBrowserView |
232 """ |
243 """ |
233 import WebBrowser.WebBrowserWindow |
244 import WebBrowser.WebBrowserWindow |
|
245 |
234 if WebBrowser.WebBrowserWindow.WebBrowserWindow.isPrivate(): |
246 if WebBrowser.WebBrowserWindow.WebBrowserWindow.isPrivate(): |
235 return |
247 return |
236 |
248 |
237 url = view.url() |
249 url = view.url() |
238 title = view.title() |
250 title = view.title() |
239 |
251 |
240 if url.scheme() not in ["eric", "about", "data", "chrome"]: |
252 if url.scheme() not in ["eric", "about", "data", "chrome"]: |
241 cleanUrlStr = self.__cleanUrlStr(url) |
253 cleanUrlStr = self.__cleanUrlStr(url) |
242 firstEntry = self.__findFirstHistoryEntry(cleanUrlStr) |
254 firstEntry = self.__findFirstHistoryEntry(cleanUrlStr) |
243 if firstEntry.isValid(): |
255 if firstEntry.isValid(): |
244 visitCount = firstEntry.visitCount + 1 |
256 visitCount = firstEntry.visitCount + 1 |
245 self.__updateVisitCount(cleanUrlStr, visitCount) |
257 self.__updateVisitCount(cleanUrlStr, visitCount) |
246 else: |
258 else: |
247 visitCount = 1 |
259 visitCount = 1 |
248 itm = HistoryEntry(cleanUrlStr, |
260 itm = HistoryEntry( |
249 QDateTime.currentDateTime(), |
261 cleanUrlStr, QDateTime.currentDateTime(), title, visitCount |
250 title, |
262 ) |
251 visitCount) |
|
252 self.__history.insert(0, itm) |
263 self.__history.insert(0, itm) |
253 self.entryAdded.emit(itm) |
264 self.entryAdded.emit(itm) |
254 if len(self.__history) == 1: |
265 if len(self.__history) == 1: |
255 self.__checkForExpired() |
266 self.__checkForExpired() |
256 |
267 |
257 def updateHistoryEntry(self, url, title): |
268 def updateHistoryEntry(self, url, title): |
258 """ |
269 """ |
259 Public method to update a history entry. |
270 Public method to update a history entry. |
260 |
271 |
261 @param url URL of the entry to update (string) |
272 @param url URL of the entry to update (string) |
262 @param title title of the entry to update (string) |
273 @param title title of the entry to update (string) |
263 """ |
274 """ |
264 if QUrl(url).scheme() not in ["eric", "about", "data", "chrome"]: |
275 if QUrl(url).scheme() not in ["eric", "about", "data", "chrome"]: |
265 cleanUrlStr = self.__cleanUrlStr(QUrl(url)) |
276 cleanUrlStr = self.__cleanUrlStr(QUrl(url)) |
306 # don't save the password in the history |
316 # don't save the password in the history |
307 cleanurl.setPassword("") |
317 cleanurl.setPassword("") |
308 if cleanurl.host(): |
318 if cleanurl.host(): |
309 # convert host to lower case |
319 # convert host to lower case |
310 cleanurl.setHost(url.host().lower()) |
320 cleanurl.setHost(url.host().lower()) |
311 |
321 |
312 return cleanurl |
322 return cleanurl |
313 |
323 |
314 def __cleanUrlStr(self, url): |
324 def __cleanUrlStr(self, url): |
315 """ |
325 """ |
316 Private method to generate a clean URL usable for the history entry. |
326 Private method to generate a clean URL usable for the history entry. |
317 |
327 |
318 @param url original URL |
328 @param url original URL |
319 @type QUrl |
329 @type QUrl |
320 @return cleaned URL |
330 @return cleaned URL |
321 @rtype str |
331 @rtype str |
322 """ |
332 """ |
323 cleanurl = self.__cleanUrl(url) |
333 cleanurl = self.__cleanUrl(url) |
324 return cleanurl.toString() |
334 return cleanurl.toString() |
325 |
335 |
326 def historyModel(self): |
336 def historyModel(self): |
327 """ |
337 """ |
328 Public method to get a reference to the history model. |
338 Public method to get a reference to the history model. |
329 |
339 |
330 @return reference to the history model (HistoryModel) |
340 @return reference to the history model (HistoryModel) |
331 """ |
341 """ |
332 return self.__historyModel |
342 return self.__historyModel |
333 |
343 |
334 def historyFilterModel(self): |
344 def historyFilterModel(self): |
335 """ |
345 """ |
336 Public method to get a reference to the history filter model. |
346 Public method to get a reference to the history filter model. |
337 |
347 |
338 @return reference to the history filter model (HistoryFilterModel) |
348 @return reference to the history filter model (HistoryFilterModel) |
339 """ |
349 """ |
340 return self.__historyFilterModel |
350 return self.__historyFilterModel |
341 |
351 |
342 def historyTreeModel(self): |
352 def historyTreeModel(self): |
343 """ |
353 """ |
344 Public method to get a reference to the history tree model. |
354 Public method to get a reference to the history tree model. |
345 |
355 |
346 @return reference to the history tree model (HistoryTreeModel) |
356 @return reference to the history tree model (HistoryTreeModel) |
347 """ |
357 """ |
348 return self.__historyTreeModel |
358 return self.__historyTreeModel |
349 |
359 |
350 def __checkForExpired(self): |
360 def __checkForExpired(self): |
351 """ |
361 """ |
352 Private slot to check entries for expiration. |
362 Private slot to check entries for expiration. |
353 """ |
363 """ |
354 if self.__daysToExpire < 0 or len(self.__history) == 0: |
364 if self.__daysToExpire < 0 or len(self.__history) == 0: |
355 return |
365 return |
356 |
366 |
357 now = QDateTime.currentDateTime() |
367 now = QDateTime.currentDateTime() |
358 nextTimeout = 0 |
368 nextTimeout = 0 |
359 |
369 |
360 while self.__history: |
370 while self.__history: |
361 checkForExpired = QDateTime(self.__history[-1].dateTime) |
371 checkForExpired = QDateTime(self.__history[-1].dateTime) |
362 checkForExpired.setDate( |
372 checkForExpired.setDate(checkForExpired.date().addDays(self.__daysToExpire)) |
363 checkForExpired.date().addDays(self.__daysToExpire)) |
|
364 nextTimeout = ( |
373 nextTimeout = ( |
365 7 * 86400 |
374 7 * 86400 |
366 if now.daysTo(checkForExpired) > 7 else |
375 if now.daysTo(checkForExpired) > 7 |
367 now.secsTo(checkForExpired) |
376 else now.secsTo(checkForExpired) |
368 ) |
377 ) |
369 if nextTimeout > 0: |
378 if nextTimeout > 0: |
370 break |
379 break |
371 |
380 |
372 itm = self.__history.pop(-1) |
381 itm = self.__history.pop(-1) |
373 self.__lastSavedUrl = "" |
382 self.__lastSavedUrl = "" |
374 self.entryRemoved.emit(itm) |
383 self.entryRemoved.emit(itm) |
375 self.__saveTimer.saveIfNeccessary() |
384 self.__saveTimer.saveIfNeccessary() |
376 |
385 |
377 if nextTimeout > 0: |
386 if nextTimeout > 0: |
378 self.__expiredTimer.start(nextTimeout * 1000) |
387 self.__expiredTimer.start(nextTimeout * 1000) |
379 |
388 |
380 def daysToExpire(self): |
389 def daysToExpire(self): |
381 """ |
390 """ |
382 Public method to get the days for entry expiration. |
391 Public method to get the days for entry expiration. |
383 |
392 |
384 @return days for entry expiration (integer) |
393 @return days for entry expiration (integer) |
385 """ |
394 """ |
386 return self.__daysToExpire |
395 return self.__daysToExpire |
387 |
396 |
388 def setDaysToExpire(self, limit): |
397 def setDaysToExpire(self, limit): |
389 """ |
398 """ |
390 Public method to set the days for entry expiration. |
399 Public method to set the days for entry expiration. |
391 |
400 |
392 @param limit days for entry expiration (integer) |
401 @param limit days for entry expiration (integer) |
393 """ |
402 """ |
394 if self.__daysToExpire == limit: |
403 if self.__daysToExpire == limit: |
395 return |
404 return |
396 |
405 |
397 self.__daysToExpire = limit |
406 self.__daysToExpire = limit |
398 self.__checkForExpired() |
407 self.__checkForExpired() |
399 self.__saveTimer.changeOccurred() |
408 self.__saveTimer.changeOccurred() |
400 |
409 |
401 def preferencesChanged(self): |
410 def preferencesChanged(self): |
402 """ |
411 """ |
403 Public method to indicate a change of preferences. |
412 Public method to indicate a change of preferences. |
404 """ |
413 """ |
405 self.setDaysToExpire(Preferences.getWebBrowser("HistoryLimit")) |
414 self.setDaysToExpire(Preferences.getWebBrowser("HistoryLimit")) |
406 |
415 |
407 @pyqtSlot() |
416 @pyqtSlot() |
408 def clear(self, period=0): |
417 def clear(self, period=0): |
409 """ |
418 """ |
410 Public slot to clear the complete history. |
419 Public slot to clear the complete history. |
411 |
420 |
412 @param period history period in milliseconds to be cleared (integer) |
421 @param period history period in milliseconds to be cleared (integer) |
413 """ |
422 """ |
414 if period == 0: |
423 if period == 0: |
415 self.__history = [] |
424 self.__history = [] |
416 self.historyReset.emit() |
425 self.historyReset.emit() |
417 else: |
426 else: |
418 breakMS = QDateTime.currentMSecsSinceEpoch() - period |
427 breakMS = QDateTime.currentMSecsSinceEpoch() - period |
419 while ( |
428 while self.__history and ( |
420 self.__history and |
429 QDateTime(self.__history[0].dateTime).toMSecsSinceEpoch() > breakMS |
421 (QDateTime(self.__history[0].dateTime).toMSecsSinceEpoch() > |
|
422 breakMS) |
|
423 ): |
430 ): |
424 itm = self.__history.pop(0) |
431 itm = self.__history.pop(0) |
425 self.entryRemoved.emit(itm) |
432 self.entryRemoved.emit(itm) |
426 self.__lastSavedUrl = "" |
433 self.__lastSavedUrl = "" |
427 self.__saveTimer.changeOccurred() |
434 self.__saveTimer.changeOccurred() |
428 self.__saveTimer.saveIfNeccessary() |
435 self.__saveTimer.saveIfNeccessary() |
429 self.historyCleared.emit() |
436 self.historyCleared.emit() |
430 |
437 |
431 def getFileName(self): |
438 def getFileName(self): |
432 """ |
439 """ |
433 Public method to get the file name of the history file. |
440 Public method to get the file name of the history file. |
434 |
441 |
435 @return name of the history file (string) |
442 @return name of the history file (string) |
436 """ |
443 """ |
437 return os.path.join(Utilities.getConfigDir(), "web_browser", "history") |
444 return os.path.join(Utilities.getConfigDir(), "web_browser", "history") |
438 |
445 |
439 def reload(self): |
446 def reload(self): |
440 """ |
447 """ |
441 Public method to reload the history. |
448 Public method to reload the history. |
442 """ |
449 """ |
443 self.__load() |
450 self.__load() |
444 |
451 |
445 def __load(self): |
452 def __load(self): |
446 """ |
453 """ |
447 Private method to load the saved history entries from disk. |
454 Private method to load the saved history entries from disk. |
448 """ |
455 """ |
449 historyFile = QFile(self.getFileName()) |
456 historyFile = QFile(self.getFileName()) |
475 itm.url = Utilities.readStringFromStream(stream) |
483 itm.url = Utilities.readStringFromStream(stream) |
476 stream >> itm.dateTime |
484 stream >> itm.dateTime |
477 itm.title = Utilities.readStringFromStream(stream) |
485 itm.title = Utilities.readStringFromStream(stream) |
478 if ver == HISTORY_VERSION_60: |
486 if ver == HISTORY_VERSION_60: |
479 itm.visitCount = stream.readUInt32() |
487 itm.visitCount = stream.readUInt32() |
480 |
488 |
481 if not itm.dateTime.isValid(): |
489 if not itm.dateTime.isValid(): |
482 continue |
490 continue |
483 |
491 |
484 if itm == lastInsertedItem: |
492 if itm == lastInsertedItem: |
485 if not lastInsertedItem.title and len(history) > 0: |
493 if not lastInsertedItem.title and len(history) > 0: |
486 history[0].title = itm.title |
494 history[0].title = itm.title |
487 continue |
495 continue |
488 |
496 |
489 if ver == HISTORY_VERSION_42: |
497 if ver == HISTORY_VERSION_42: |
490 firstEntry = self.__findFirstHistoryEntry(itm.url) |
498 firstEntry = self.__findFirstHistoryEntry(itm.url) |
491 if firstEntry.isValid(): |
499 if firstEntry.isValid(): |
492 visitCount = firstEntry.visitCount + 1 |
500 visitCount = firstEntry.visitCount + 1 |
493 self.__updateVisitCount(itm.url, visitCount) |
501 self.__updateVisitCount(itm.url, visitCount) |
494 else: |
502 else: |
495 visitCount = 1 |
503 visitCount = 1 |
496 itm.visitCount = visitCount |
504 itm.visitCount = visitCount |
497 |
505 |
498 if not needToSort and history and lastInsertedItem < itm: |
506 if not needToSort and history and lastInsertedItem < itm: |
499 needToSort = True |
507 needToSort = True |
500 |
508 |
501 history.insert(0, itm) |
509 history.insert(0, itm) |
502 lastInsertedItem = itm |
510 lastInsertedItem = itm |
503 historyFile.close() |
511 historyFile.close() |
504 |
512 |
505 if needToSort: |
513 if needToSort: |
506 history.sort() |
514 history.sort() |
507 |
515 |
508 self.setHistory(history, True) |
516 self.setHistory(history, True) |
509 |
517 |
510 # if the history had to be sorted, rewrite the history sorted |
518 # if the history had to be sorted, rewrite the history sorted |
511 if needToSort: |
519 if needToSort: |
512 self.__lastSavedUrl = "" |
520 self.__lastSavedUrl = "" |
513 self.__saveTimer.changeOccurred() |
521 self.__saveTimer.changeOccurred() |
514 |
522 |
515 def save(self): |
523 def save(self): |
516 """ |
524 """ |
517 Public slot to save the history entries to disk. |
525 Public slot to save the history entries to disk. |
518 """ |
526 """ |
519 historyFile = QFile(self.getFileName()) |
527 historyFile = QFile(self.getFileName()) |
520 if not historyFile.exists(): |
528 if not historyFile.exists(): |
521 self.__lastSavedUrl = "" |
529 self.__lastSavedUrl = "" |
522 |
530 |
523 saveAll = self.__lastSavedUrl == "" |
531 saveAll = self.__lastSavedUrl == "" |
524 first = len(self.__history) - 1 |
532 first = len(self.__history) - 1 |
525 if not saveAll: |
533 if not saveAll: |
526 # find the first one to save |
534 # find the first one to save |
527 for index in range(len(self.__history)): |
535 for index in range(len(self.__history)): |
528 if self.__history[index].url == self.__lastSavedUrl: |
536 if self.__history[index].url == self.__lastSavedUrl: |
529 first = index - 1 |
537 first = index - 1 |
530 break |
538 break |
531 if first == len(self.__history) - 1: |
539 if first == len(self.__history) - 1: |
532 saveAll = True |
540 saveAll = True |
533 |
541 |
534 if saveAll: |
542 if saveAll: |
535 # use a temporary file when saving everything |
543 # use a temporary file when saving everything |
536 f = QTemporaryFile() |
544 f = QTemporaryFile() |
537 f.setAutoRemove(False) |
545 f.setAutoRemove(False) |
538 opened = f.open() |
546 opened = f.open() |
539 else: |
547 else: |
540 f = historyFile |
548 f = historyFile |
541 opened = f.open(QIODevice.OpenModeFlag.Append) |
549 opened = f.open(QIODevice.OpenModeFlag.Append) |
542 |
550 |
543 if not opened: |
551 if not opened: |
544 EricMessageBox.warning( |
552 EricMessageBox.warning( |
545 None, |
553 None, |
546 self.tr("Saving History"), |
554 self.tr("Saving History"), |
547 self.tr( |
555 self.tr( |
548 """<p>Unable to open history file <b>{0}</b>.<br/>""" |
556 """<p>Unable to open history file <b>{0}</b>.<br/>""" |
549 """Reason: {1}</p>""") |
557 """Reason: {1}</p>""" |
550 .format(f.fileName(), f.errorString())) |
558 ).format(f.fileName(), f.errorString()), |
|
559 ) |
551 return |
560 return |
552 |
561 |
553 for index in range(first, -1, -1): |
562 for index in range(first, -1, -1): |
554 data = QByteArray() |
563 data = QByteArray() |
555 stream = QDataStream(data, QIODevice.OpenModeFlag.WriteOnly) |
564 stream = QDataStream(data, QIODevice.OpenModeFlag.WriteOnly) |
556 stream.setVersion(QDataStream.Version.Qt_4_6) |
565 stream.setVersion(QDataStream.Version.Qt_4_6) |
557 itm = self.__history[index] |
566 itm = self.__history[index] |
558 stream.writeUInt32(HISTORY_VERSION_60) |
567 stream.writeUInt32(HISTORY_VERSION_60) |
559 stream.writeString(itm.url.encode("utf-8")) |
568 stream.writeString(itm.url.encode("utf-8")) |
560 stream << itm.dateTime |
569 stream << itm.dateTime |
561 stream.writeString(itm.title.encode('utf-8')) |
570 stream.writeString(itm.title.encode("utf-8")) |
562 stream.writeUInt32(itm.visitCount) |
571 stream.writeUInt32(itm.visitCount) |
563 f.write(data) |
572 f.write(data) |
564 |
573 |
565 f.close() |
574 f.close() |
566 if saveAll: |
575 if saveAll: |
567 if historyFile.exists() and not historyFile.remove(): |
576 if historyFile.exists() and not historyFile.remove(): |
568 EricMessageBox.warning( |
577 EricMessageBox.warning( |
569 None, |
578 None, |
570 self.tr("Saving History"), |
579 self.tr("Saving History"), |
571 self.tr( |
580 self.tr( |
572 """<p>Error removing old history file <b>{0}</b>.""" |
581 """<p>Error removing old history file <b>{0}</b>.""" |
573 """<br/>Reason: {1}</p>""") |
582 """<br/>Reason: {1}</p>""" |
574 .format(historyFile.fileName(), |
583 ).format(historyFile.fileName(), historyFile.errorString()), |
575 historyFile.errorString())) |
584 ) |
576 if not f.copy(historyFile.fileName()): |
585 if not f.copy(historyFile.fileName()): |
577 EricMessageBox.warning( |
586 EricMessageBox.warning( |
578 None, |
587 None, |
579 self.tr("Saving History"), |
588 self.tr("Saving History"), |
580 self.tr( |
589 self.tr( |
581 """<p>Error moving new history file over old one """ |
590 """<p>Error moving new history file over old one """ |
582 """(<b>{0}</b>).<br/>Reason: {1}</p>""") |
591 """(<b>{0}</b>).<br/>Reason: {1}</p>""" |
583 .format(historyFile.fileName(), f.errorString())) |
592 ).format(historyFile.fileName(), f.errorString()), |
|
593 ) |
584 f.remove() # get rid of the temporary file |
594 f.remove() # get rid of the temporary file |
585 self.historySaved.emit() |
595 self.historySaved.emit() |
586 try: |
596 try: |
587 self.__lastSavedUrl = self.__history[0].url |
597 self.__lastSavedUrl = self.__history[0].url |
588 except IndexError: |
598 except IndexError: |
589 self.__lastSavedUrl = "" |
599 self.__lastSavedUrl = "" |
590 |
600 |
591 def __refreshFrequencies(self): |
601 def __refreshFrequencies(self): |
592 """ |
602 """ |
593 Private slot to recalculate the refresh frequencies. |
603 Private slot to recalculate the refresh frequencies. |
594 """ |
604 """ |
595 self.__historyFilterModel.recalculateFrequencies() |
605 self.__historyFilterModel.recalculateFrequencies() |
596 self.__startFrequencyTimer() |
606 self.__startFrequencyTimer() |
597 |
607 |
598 def __startFrequencyTimer(self): |
608 def __startFrequencyTimer(self): |
599 """ |
609 """ |
600 Private method to start the timer to recalculate the frequencies. |
610 Private method to start the timer to recalculate the frequencies. |
601 """ |
611 """ |
602 tomorrow = QDateTime(QDate.currentDate().addDays(1), QTime(3, 0)) |
612 tomorrow = QDateTime(QDate.currentDate().addDays(1), QTime(3, 0)) |
603 self.__frequencyTimer.start( |
613 self.__frequencyTimer.start(QDateTime.currentDateTime().secsTo(tomorrow) * 1000) |
604 QDateTime.currentDateTime().secsTo(tomorrow) * 1000) |
614 |
605 |
|
606 def siteVisitsCount(self, scheme, host): |
615 def siteVisitsCount(self, scheme, host): |
607 """ |
616 """ |
608 Public method to get the visit count for a web site using the given |
617 Public method to get the visit count for a web site using the given |
609 scheme. |
618 scheme. |
610 |
619 |
611 @param scheme scheme to look for |
620 @param scheme scheme to look for |
612 @type str |
621 @type str |
613 @param host host to look for |
622 @param host host to look for |
614 @type str |
623 @type str |
615 @return number of visits to this site |
624 @return number of visits to this site |
616 @rtype int |
625 @rtype int |
617 """ |
626 """ |
618 count = 0 |
627 count = 0 |
619 url = "{0}://{1}".format(scheme.lower(), host.lower()) |
628 url = "{0}://{1}".format(scheme.lower(), host.lower()) |
620 |
629 |
621 seenUrls = [] |
630 seenUrls = [] |
622 |
631 |
623 for index in range(len(self.__history)): |
632 for index in range(len(self.__history)): |
624 historyUrl = self.__history[index].url |
633 historyUrl = self.__history[index].url |
625 if historyUrl.startswith(url) and historyUrl not in seenUrls: |
634 if historyUrl.startswith(url) and historyUrl not in seenUrls: |
626 count += self.__history[index].visitCount |
635 count += self.__history[index].visitCount |
627 seenUrls.append(historyUrl) |
636 seenUrls.append(historyUrl) |
628 |
637 |
629 return count |
638 return count |