5 |
5 |
6 """ |
6 """ |
7 Module implementing a synchronization handler using FTP. |
7 Module implementing a synchronization handler using FTP. |
8 """ |
8 """ |
9 |
9 |
10 from PyQt4.QtCore import pyqtSignal, QUrl, QFile, QIODevice, QTime, QThread, QTimer |
10 from PyQt4.QtCore import pyqtSignal, QUrl, QIODevice, QTime, QThread, QTimer, QBuffer |
11 from PyQt4.QtNetwork import QFtp, QNetworkProxyQuery, QNetworkProxy, QNetworkProxyFactory |
11 from PyQt4.QtNetwork import QFtp, QNetworkProxyQuery, QNetworkProxy, QNetworkProxyFactory |
12 |
12 |
13 from .SyncHandler import SyncHandler |
13 from .SyncHandler import SyncHandler |
14 |
14 |
15 import Helpviewer.HelpWindow |
15 import Helpviewer.HelpWindow |
23 |
23 |
24 @signal syncStatus(type_, done, message) emitted to indicate the synchronization |
24 @signal syncStatus(type_, done, message) emitted to indicate the synchronization |
25 status (string one of "bookmarks", "history", "passwords" or "useragents", |
25 status (string one of "bookmarks", "history", "passwords" or "useragents", |
26 boolean, string) |
26 boolean, string) |
27 @signal syncError(message) emitted for a general error with the error message (string) |
27 @signal syncError(message) emitted for a general error with the error message (string) |
|
28 @signal syncMessage(message) emitted to send a message about synchronization (string) |
28 @signal syncFinished(type_, done, download) emitted after a synchronization has |
29 @signal syncFinished(type_, done, download) emitted after a synchronization has |
29 finished (string one of "bookmarks", "history", "passwords" or "useragents", |
30 finished (string one of "bookmarks", "history", "passwords" or "useragents", |
30 boolean, boolean) |
31 boolean, boolean) |
31 """ |
32 """ |
32 syncStatus = pyqtSignal(str, bool, str) |
33 syncStatus = pyqtSignal(str, bool, str) |
33 syncError = pyqtSignal(str) |
34 syncError = pyqtSignal(str) |
|
35 syncMessage = pyqtSignal(str) |
34 syncFinished = pyqtSignal(str, bool, bool) |
36 syncFinished = pyqtSignal(str, bool, bool) |
35 |
37 |
36 def __init__(self, parent=None): |
38 def __init__(self, parent=None): |
37 """ |
39 """ |
38 Constructor |
40 Constructor |
57 "Remote bookmarks file exists! Syncing local copy..."), |
60 "Remote bookmarks file exists! Syncing local copy..."), |
58 "RemoteMissing": self.trUtf8( |
61 "RemoteMissing": self.trUtf8( |
59 "Remote bookmarks file does NOT exists. Exporting local copy..."), |
62 "Remote bookmarks file does NOT exists. Exporting local copy..."), |
60 "LocalMissing": self.trUtf8( |
63 "LocalMissing": self.trUtf8( |
61 "Local bookmarks file does NOT exist. Skipping synchronization!"), |
64 "Local bookmarks file does NOT exist. Skipping synchronization!"), |
|
65 "Uploading": self.trUtf8("Uploading local bookmarks file..."), |
62 }, |
66 }, |
63 "history": { |
67 "history": { |
64 "RemoteExists": self.trUtf8( |
68 "RemoteExists": self.trUtf8( |
65 "Remote history file exists! Syncing local copy..."), |
69 "Remote history file exists! Syncing local copy..."), |
66 "RemoteMissing": self.trUtf8( |
70 "RemoteMissing": self.trUtf8( |
67 "Remote history file does NOT exists. Exporting local copy..."), |
71 "Remote history file does NOT exists. Exporting local copy..."), |
68 "LocalMissing": self.trUtf8( |
72 "LocalMissing": self.trUtf8( |
69 "Local history file does NOT exist. Skipping synchronization!"), |
73 "Local history file does NOT exist. Skipping synchronization!"), |
|
74 "Uploading": self.trUtf8("Uploading local history file..."), |
70 }, |
75 }, |
71 "passwords": { |
76 "passwords": { |
72 "RemoteExists": self.trUtf8( |
77 "RemoteExists": self.trUtf8( |
73 "Remote logins file exists! Syncing local copy..."), |
78 "Remote logins file exists! Syncing local copy..."), |
74 "RemoteMissing": self.trUtf8( |
79 "RemoteMissing": self.trUtf8( |
75 "Remote logins file does NOT exists. Exporting local copy..."), |
80 "Remote logins file does NOT exists. Exporting local copy..."), |
76 "LocalMissing": self.trUtf8( |
81 "LocalMissing": self.trUtf8( |
77 "Local logins file does NOT exist. Skipping synchronization!"), |
82 "Local logins file does NOT exist. Skipping synchronization!"), |
|
83 "Uploading": self.trUtf8("Uploading local logins file..."), |
78 }, |
84 }, |
79 "useragents": { |
85 "useragents": { |
80 "RemoteExists": self.trUtf8( |
86 "RemoteExists": self.trUtf8( |
81 "Remote user agent settings file exists! Syncing local copy..."), |
87 "Remote user agent settings file exists! Syncing local copy..."), |
82 "RemoteMissing": self.trUtf8( |
88 "RemoteMissing": self.trUtf8( |
83 "Remote user agent settings file does NOT exists." |
89 "Remote user agent settings file does NOT exists." |
84 " Exporting local copy..."), |
90 " Exporting local copy..."), |
85 "LocalMissing": self.trUtf8( |
91 "LocalMissing": self.trUtf8( |
86 "Local user agent settings file does NOT exist." |
92 "Local user agent settings file does NOT exist." |
87 " Skipping synchronization!"), |
93 " Skipping synchronization!"), |
|
94 "Uploading": self.trUtf8("Uploading local user agent settings file..."), |
88 }, |
95 }, |
89 } |
96 } |
90 |
97 |
91 def initialLoadAndCheck(self): |
98 def initialLoadAndCheck(self, forceUpload): |
92 """ |
99 """ |
93 Public method to do the initial check. |
100 Public method to do the initial check. |
|
101 |
|
102 @keyparam forceUpload flag indicating a forced upload of the files (boolean) |
94 """ |
103 """ |
95 if not Preferences.getHelp("SyncEnabled"): |
104 if not Preferences.getHelp("SyncEnabled"): |
96 return |
105 return |
97 |
106 |
98 self.__state = "initializing" |
107 self.__state = "initializing" |
|
108 self.__forceUpload = forceUpload |
99 |
109 |
100 self.__remoteFilesFound = [] |
110 self.__remoteFilesFound = [] |
101 self.__syncIDs = {} |
111 self.__syncIDs = {} |
102 |
112 |
103 self.__idleTimer = QTimer(self) |
113 self.__idleTimer = QTimer(self) |
158 elif self.__ftp.currentCommand() == QFtp.Cd: |
168 elif self.__ftp.currentCommand() == QFtp.Cd: |
159 self.__ftp.mkdir(self.__storePathList[0]) |
169 self.__ftp.mkdir(self.__storePathList[0]) |
160 self.__ftp.cd(self.__storePathList[0]) |
170 self.__ftp.cd(self.__storePathList[0]) |
161 else: |
171 else: |
162 if id in self.__syncIDs: |
172 if id in self.__syncIDs: |
|
173 # TODO: change this like below |
163 self.__syncIDs[id][1].close() |
174 self.__syncIDs[id][1].close() |
164 self.syncStatus.emit(self.__syncIDs[id][0], False, |
175 self.syncStatus.emit(self.__syncIDs[id][0], False, |
165 self.__ftp.errorString()) |
176 self.__ftp.errorString()) |
166 self.syncFinished.emit(self.__syncIDs[id][0], False, |
177 self.syncFinished.emit(self.__syncIDs[id][0], False, |
167 self.__syncIDs[id][2]) |
178 self.__syncIDs[id][2]) |
168 del self.__syncIDs[id] |
179 del self.__syncIDs[id] |
|
180 if not self.__syncIDs: |
|
181 self.__state = "idle" |
|
182 self.syncMessage.emit(self.trUtf8("Synchronization finished")) |
169 else: |
183 else: |
170 if self.__ftp.currentCommand() == QFtp.Login: |
184 if self.__ftp.currentCommand() == QFtp.Login: |
171 self.__changeToStore() |
185 self.__changeToStore() |
172 elif self.__ftp.currentCommand() == QFtp.Cd: |
186 elif self.__ftp.currentCommand() == QFtp.Cd: |
173 del self.__storePathList[0] |
187 del self.__storePathList[0] |
177 self.__storeReached() |
191 self.__storeReached() |
178 elif self.__ftp.currentCommand() == QFtp.List: |
192 elif self.__ftp.currentCommand() == QFtp.List: |
179 self.__initialSync() |
193 self.__initialSync() |
180 else: |
194 else: |
181 if id in self.__syncIDs: |
195 if id in self.__syncIDs: |
182 self.__syncIDs[id][1].close() |
196 if self.__ftp.currentCommand() == QFtp.Get: |
|
197 self.__syncIDs[id][1].close() |
|
198 ok, error = self.writeFile(self.__syncIDs[id][1].buffer(), |
|
199 self.__syncIDs[id][3]) |
|
200 if ok: |
|
201 self.syncStatus.emit(self.__syncIDs[id][0], True, |
|
202 self.__messages[self.__syncIDs[id][0]]["RemoteExists"]) |
|
203 else: |
|
204 self.syncStatus.emit(self.__syncIDs[id][0], False, |
|
205 error) |
183 self.syncFinished.emit(self.__syncIDs[id][0], True, |
206 self.syncFinished.emit(self.__syncIDs[id][0], True, |
184 self.__syncIDs[id][2]) |
207 self.__syncIDs[id][2]) |
185 del self.__syncIDs[id] |
208 del self.__syncIDs[id] |
|
209 if not self.__syncIDs: |
|
210 self.__state = "idle" |
|
211 self.syncMessage.emit(self.trUtf8("Synchronization finished")) |
186 |
212 |
187 def __storeReached(self): |
213 def __storeReached(self): |
188 """ |
214 """ |
189 Private slot executed, when the storage directory was reached. |
215 Private slot executed, when the storage directory was reached. |
190 """ |
216 """ |
200 """ |
226 """ |
201 if info.isValid() and info.isFile(): |
227 if info.isValid() and info.isFile(): |
202 if info.name() in self.__remoteFiles.values(): |
228 if info.name() in self.__remoteFiles.values(): |
203 self.__remoteFilesFound.append(info.name()) |
229 self.__remoteFilesFound.append(info.name()) |
204 |
230 |
|
231 def __downloadFile(self, type_, fileName): |
|
232 """ |
|
233 Private method to downlaod the given file. |
|
234 |
|
235 @param type_ type of the synchronization event (string one |
|
236 of "bookmarks", "history", "passwords" or "useragents") |
|
237 @param fileName name of the file to be downloaded (string) |
|
238 """ |
|
239 buffer = QBuffer(self) |
|
240 buffer.open(QIODevice.WriteOnly) |
|
241 id = self.__ftp.get(self.__remoteFiles[type_], buffer) |
|
242 self.__syncIDs[id] = (type_, buffer, True, fileName) |
|
243 |
|
244 def __uploadFile(self, type_, fileName): |
|
245 """ |
|
246 Private method to upload the given file. |
|
247 |
|
248 @param type_ type of the synchronization event (string one |
|
249 of "bookmarks", "history", "passwords" or "useragents") |
|
250 @param fileName name of the file to be uploaded (string) |
|
251 """ |
|
252 data = self.readFile(fileName) |
|
253 if data.isEmpty(): |
|
254 self.syncStatus.emit(type_, True, |
|
255 self.__messages[type_]["LocalMissing"]) |
|
256 else: |
|
257 id = self.__ftp.put(data, self.__remoteFiles[type_]) |
|
258 self.__syncIDs[id] = (type_, data, False) |
|
259 |
205 def __initialSyncFile(self, type_, fileName): |
260 def __initialSyncFile(self, type_, fileName): |
206 """ |
261 """ |
207 Private method to do the initial synchronization of the given file. |
262 Private method to do the initial synchronization of the given file. |
208 |
263 |
209 @param type_ type of the synchronization event (string one |
264 @param type_ type of the synchronization event (string one |
210 of "bookmarks", "history", "passwords" or "useragents") |
265 of "bookmarks", "history", "passwords" or "useragents") |
211 @param fileName name of the file to be synchronized (string) |
266 @param fileName name of the file to be synchronized (string) |
212 """ |
267 """ |
213 f = QFile(fileName) |
268 if not self.__forceUpload and \ |
214 if self.__remoteFiles[type_] in self.__remoteFilesFound: |
269 self.__remoteFiles[type_] in self.__remoteFilesFound: |
|
270 self.__downloadFile(type_, fileName) |
|
271 else: |
215 self.syncStatus.emit(type_, True, |
272 self.syncStatus.emit(type_, True, |
216 self.__messages[type_]["RemoteExists"]) |
273 self.__messages[type_]["RemoteMissing"]) |
217 f.open(QIODevice.WriteOnly) |
274 self.__uploadFile(type_, fileName) |
218 id = self.__ftp.get(self.__remoteFiles[type_], f) |
|
219 self.__syncIDs[id] = (type_, f, True) |
|
220 else: |
|
221 if f.exists(): |
|
222 self.syncStatus.emit(type_, True, |
|
223 self.__messages[type_]["RemoteMissing"]) |
|
224 f.open(QIODevice.ReadOnly) |
|
225 id = self.__ftp.put(f, self.__remoteFiles[type_]) |
|
226 self.__syncIDs[id] = (type_, f, False) |
|
227 else: |
|
228 self.syncStatus.emit(type_, True, |
|
229 self.__messages[type_]["LocalMissing"]) |
|
230 |
275 |
231 def __initialSync(self): |
276 def __initialSync(self): |
232 """ |
277 """ |
233 Private slot to do the initial synchronization. |
278 Private slot to do the initial synchronization. |
234 """ |
279 """ |
249 |
294 |
250 # User Agent Settings |
295 # User Agent Settings |
251 if Preferences.getHelp("SyncUserAgents"): |
296 if Preferences.getHelp("SyncUserAgents"): |
252 self.__initialSyncFile("useragents", |
297 self.__initialSyncFile("useragents", |
253 Helpviewer.HelpWindow.HelpWindow.userAgentsManager().getFileName()) |
298 Helpviewer.HelpWindow.HelpWindow.userAgentsManager().getFileName()) |
|
299 |
|
300 self.__forceUpload = False |
254 |
301 |
255 def __syncFile(self, type_, fileName): |
302 def __syncFile(self, type_, fileName): |
256 """ |
303 """ |
257 Private method to synchronize the given file. |
304 Private method to synchronize the given file. |
258 |
305 |
259 @param type_ type of the synchronization event (string one |
306 @param type_ type of the synchronization event (string one |
260 of "bookmarks", "history", "passwords" or "useragents") |
307 of "bookmarks", "history", "passwords" or "useragents") |
261 @param fileName name of the file to be synchronized (string) |
308 @param fileName name of the file to be synchronized (string) |
262 """ |
309 """ |
|
310 if self.__state == "initializing": |
|
311 return |
|
312 |
263 self.__state = "uploading" |
313 self.__state = "uploading" |
264 f = QFile(fileName) |
314 self.syncStatus.emit(type_, True, self.__messages[type_]["Uploading"]) |
265 if f.exists(): |
315 self.__uploadFile(type_, fileName) |
266 f.open(QIODevice.ReadOnly) |
|
267 id = self.__ftp.put(f, self.__remoteFiles[type_]) |
|
268 self.__syncIDs[id] = (type_, f, False) |
|
269 |
316 |
270 def syncBookmarks(self): |
317 def syncBookmarks(self): |
271 """ |
318 """ |
272 Public method to synchronize the bookmarks. |
319 Public method to synchronize the bookmarks. |
273 """ |
320 """ |