Helpviewer/Sync/FtpSyncHandler.py

changeset 1680
28e57079dab5
parent 1638
cd2f9e526710
child 1681
34c774fb57b5
equal deleted inserted replaced
1679:422cc500eef9 1680:28e57079dab5
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
40 @param parent reference to the parent object (QObject) 42 @param parent reference to the parent object (QObject)
41 """ 43 """
42 super().__init__(parent) 44 super().__init__(parent)
43 45
44 self.__state = "idle" 46 self.__state = "idle"
47 self.__forceUpload = False
45 48
46 self.__remoteFiles = { 49 self.__remoteFiles = {
47 "bookmarks": "Bookmarks", 50 "bookmarks": "Bookmarks",
48 "history": "History", 51 "history": "History",
49 "passwords": "Logins", 52 "passwords": "Logins",
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 """

eric ide

mercurial