Changeset View
Changeset View
Standalone View
Standalone View
krusader/Synchronizer/synchronizer.cpp
Show All 13 Lines | |||||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
15 | * GNU General Public License for more details. * | 15 | * GNU General Public License for more details. * | ||
16 | * * | 16 | * * | ||
17 | * You should have received a copy of the GNU General Public License * | 17 | * You should have received a copy of the GNU General Public License * | ||
18 | * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * | 18 | * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * | ||
19 | *****************************************************************************/ | 19 | *****************************************************************************/ | ||
20 | 20 | | |||
21 | #include "synchronizer.h" | 21 | #include "synchronizer.h" | ||
22 | | ||||
22 | #include "synchronizerdirlist.h" | 23 | #include "synchronizerdirlist.h" | ||
23 | #include "../krglobal.h" | | |||
24 | #include "../krservices.h" | | |||
25 | #include "../FileSystem/filesystem.h" | 24 | #include "../FileSystem/filesystem.h" | ||
26 | #include "../FileSystem/krquery.h" | 25 | #include "../FileSystem/krquery.h" | ||
26 | #include "../krglobal.h" | ||||
27 | #include "../krservices.h" | ||||
27 | 28 | | |||
28 | #include <utime.h> | 29 | #include <utime.h> | ||
29 | 30 | | |||
30 | // QtCore | 31 | // QtCore | ||
31 | #include <QRegExp> | 32 | #include <QDateTime> | ||
33 | #include <QDebug> | ||||
32 | #include <QDir> | 34 | #include <QDir> | ||
33 | #include <QEventLoop> | 35 | #include <QEventLoop> | ||
34 | #include <QTimer> | 36 | #include <QRegExp> | ||
35 | #include <QTime> | 37 | #include <QTime> | ||
36 | #include <QDateTime> | 38 | #include <QTimer> | ||
37 | #include <QUrl> | 39 | #include <QUrl> | ||
38 | // QtWidgets | 40 | // QtWidgets | ||
39 | #include <QApplication> | 41 | #include <QApplication> | ||
40 | #include <QDialogButtonBox> | 42 | #include <QDialogButtonBox> | ||
41 | #include <QFrame> | 43 | #include <QFrame> | ||
42 | #include <QVBoxLayout> | 44 | #include <QLabel> | ||
43 | #include <QLayout> | 45 | #include <QLayout> | ||
44 | #include <QProgressBar> | 46 | #include <QProgressBar> | ||
45 | #include <QPushButton> | 47 | #include <QPushButton> | ||
46 | #include <QLabel> | 48 | #include <QVBoxLayout> | ||
47 | 49 | | |||
50 | #include <KCoreAddons/KProcess> | ||||
48 | #include <KI18n/KLocalizedString> | 51 | #include <KI18n/KLocalizedString> | ||
49 | #include <KIO/DeleteJob> | 52 | #include <KIO/DeleteJob> | ||
50 | #include <KIO/JobUiDelegate> | 53 | #include <KIO/JobUiDelegate> | ||
51 | #include <KIO/SkipDialog> | 54 | #include <KIO/SkipDialog> | ||
52 | #include <KCoreAddons/KProcess> | | |||
53 | #include <KIOWidgets/KUrlCompletion> | 55 | #include <KIOWidgets/KUrlCompletion> | ||
54 | #include <KWidgetsAddons/KMessageBox> | 56 | #include <KWidgetsAddons/KMessageBox> | ||
55 | 57 | | |||
56 | | ||||
57 | #ifdef HAVE_POSIX_ACL | 58 | #ifdef HAVE_POSIX_ACL | ||
58 | #include <sys/acl.h> | 59 | #include <sys/acl.h> | ||
59 | #ifdef HAVE_NON_POSIX_ACL_EXTENSIONS | 60 | #ifdef HAVE_NON_POSIX_ACL_EXTENSIONS | ||
60 | #include <acl/libacl.h> | 61 | #include <acl/libacl.h> | ||
61 | #endif | 62 | #endif | ||
62 | #endif | 63 | #endif | ||
63 | 64 | | |||
64 | | ||||
65 | #define DISPLAY_UPDATE_PERIOD 2 | 65 | #define DISPLAY_UPDATE_PERIOD 2 | ||
66 | 66 | | |||
67 | Synchronizer::Synchronizer() : displayUpdateCount(0), markEquals(true), | 67 | Synchronizer::Synchronizer() | ||
68 | markDiffers(true), markCopyToLeft(true), markCopyToRight(true), markDeletable(true), | 68 | : displayUpdateCount(0), markEquals(true), markDiffers(true), markCopyToLeft(true), | ||
69 | stack(), jobMap(), receivedMap(), parentWidget(0), resultListIt(resultList) | 69 | markCopyToRight(true), markDeletable(true), stack(), jobMap(), receivedMap(), parentWidget(0), | ||
70 | resultListIt(resultList) | ||||
70 | { | 71 | { | ||
71 | } | 72 | } | ||
72 | 73 | | |||
73 | Synchronizer::~Synchronizer() | 74 | Synchronizer::~Synchronizer() { clearLists(); } | ||
74 | { | | |||
75 | clearLists(); | | |||
76 | } | | |||
77 | | ||||
78 | QUrl Synchronizer::fsUrl(QString strUrl) | | |||
79 | { | | |||
80 | QUrl result = QUrl::fromUserInput(strUrl, QString(), QUrl::AssumeLocalFile); | | |||
81 | return KrServices::escapeFileUrl(result); | | |||
82 | } | | |||
83 | 75 | | |||
84 | void Synchronizer::clearLists() | 76 | void Synchronizer::clearLists() | ||
85 | { | 77 | { | ||
86 | QListIterator<SynchronizerFileItem *> i1(resultList); | 78 | QListIterator<SynchronizerFileItem *> i1(resultList); | ||
87 | while (i1.hasNext()) | 79 | while (i1.hasNext()) | ||
88 | delete i1.next(); | 80 | delete i1.next(); | ||
89 | resultList.clear(); | 81 | resultList.clear(); | ||
90 | 82 | | |||
91 | QListIterator<SynchronizerTask *> i2(stack); | 83 | QListIterator<SynchronizerTask *> i2(stack); | ||
92 | while (i2.hasNext()) | 84 | while (i2.hasNext()) | ||
93 | delete i2.next(); | 85 | delete i2.next(); | ||
94 | stack.clear(); | 86 | stack.clear(); | ||
95 | 87 | | |||
96 | temporaryList.clear(); | 88 | temporaryList.clear(); | ||
97 | } | 89 | } | ||
98 | 90 | | |||
99 | void Synchronizer::reset() | 91 | void Synchronizer::reset() | ||
100 | { | 92 | { | ||
101 | displayUpdateCount = 0; | 93 | displayUpdateCount = 0; | ||
102 | markEquals = markDiffers = markCopyToLeft = markCopyToRight = markDeletable = true; | 94 | markEquals = markDiffers = markCopyToLeft = markCopyToRight = markDeletable = true; | ||
103 | stopped = false; | 95 | stopped = false; | ||
104 | recurseSubDirs = followSymLinks = ignoreDate = asymmetric = cmpByContent = ignoreCase = autoScroll = false; | 96 | recurseSubDirs = followSymLinks = ignoreDate = asymmetric = cmpByContent = ignoreCase = | ||
105 | markEquals = markDiffers = markCopyToLeft = markCopyToRight = markDeletable = markDuplicates = markSingles = false; | 97 | autoScroll = false; | ||
98 | markEquals = markDiffers = markCopyToLeft = markCopyToRight = markDeletable = markDuplicates = | ||||
99 | markSingles = false; | ||||
106 | leftCopyEnabled = rightCopyEnabled = deleteEnabled = overWrite = autoSkip = paused = false; | 100 | leftCopyEnabled = rightCopyEnabled = deleteEnabled = overWrite = autoSkip = paused = false; | ||
107 | leftCopyNr = rightCopyNr = deleteNr = 0; | 101 | leftCopyNr = rightCopyNr = deleteNr = 0; | ||
108 | leftCopySize = rightCopySize = deleteSize = 0; | 102 | leftCopySize = rightCopySize = deleteSize = 0; | ||
109 | comparedDirs = fileCount = 0; | 103 | comparedDirs = fileCount = 0; | ||
110 | leftBaseDir.clear(); | 104 | leftBaseDir.clear(); | ||
111 | rightBaseDir.clear(); | 105 | rightBaseDir.clear(); | ||
112 | clearLists(); | 106 | clearLists(); | ||
113 | } | 107 | } | ||
114 | 108 | | |||
115 | int Synchronizer::compare(QString leftURL, QString rightURL, KRQuery *query, bool subDirs, | 109 | int Synchronizer::compare(const QUrl &left, const QUrl &right, KRQuery *query, bool subDirs, | ||
116 | bool symLinks, bool igDate, bool asymm, bool cmpByCnt, bool igCase, | 110 | bool symLinks, bool igDate, bool asymm, bool cmpByCnt, bool igCase, | ||
117 | bool autoSc, QStringList &selFiles, int equThres, int timeOffs, int parThreads, bool hiddenFiles) | 111 | bool autoSc, QStringList &selFiles, int equThres, int timeOffs, | ||
112 | int parThreads, bool hiddenFiles) | ||||
118 | { | 113 | { | ||
119 | clearLists(); | 114 | clearLists(); | ||
120 | 115 | | |||
121 | recurseSubDirs = subDirs; | 116 | recurseSubDirs = subDirs; | ||
122 | followSymLinks = symLinks; | 117 | followSymLinks = symLinks; | ||
123 | ignoreDate = igDate; | 118 | ignoreDate = igDate; | ||
124 | asymmetric = asymm; | 119 | asymmetric = asymm; | ||
125 | cmpByContent = cmpByCnt; | 120 | cmpByContent = cmpByCnt; | ||
126 | autoScroll = autoSc; | 121 | autoScroll = autoSc; | ||
127 | ignoreCase = igCase; | 122 | ignoreCase = igCase; | ||
128 | selectedFiles = selFiles; | 123 | selectedFiles = selFiles; | ||
129 | equalsThreshold = equThres; | 124 | equalsThreshold = equThres; | ||
130 | timeOffset = timeOffs; | 125 | timeOffset = timeOffs; | ||
131 | parallelThreads = parThreads; | 126 | parallelThreads = parThreads; | ||
132 | ignoreHidden = hiddenFiles; | 127 | ignoreHidden = hiddenFiles; | ||
133 | 128 | | |||
134 | stopped = false; | 129 | stopped = false; | ||
135 | 130 | | |||
136 | this->query = query; | 131 | this->query = query; | ||
137 | 132 | | |||
138 | leftURL = KUrlCompletion::replacedPath(leftURL, true, true); | | |||
139 | rightURL = KUrlCompletion::replacedPath(rightURL, true, true); | | |||
140 | | ||||
141 | if (!leftURL.endsWith('/')) leftURL += '/'; | | |||
142 | if (!rightURL.endsWith('/')) rightURL += '/'; | | |||
143 | | ||||
144 | excludedPaths = KrServices::toStringList(query->dontSearchInDirs()); | 133 | excludedPaths = KrServices::toStringList(query->dontSearchInDirs()); | ||
145 | for (int i = 0; i != excludedPaths.count(); i++) | 134 | for (int i = 0; i != excludedPaths.count(); i++) | ||
146 | if (excludedPaths[ i ].endsWith('/')) | 135 | if (excludedPaths[i].endsWith('/')) | ||
147 | excludedPaths[ i ].truncate(excludedPaths[ i ].length() - 1); | 136 | excludedPaths[i].truncate(excludedPaths[i].length() - 1); | ||
148 | 137 | | |||
149 | comparedDirs = fileCount = 0; | 138 | comparedDirs = fileCount = 0; | ||
150 | 139 | | |||
151 | stack.append(new CompareTask(0, leftBaseDir = leftURL, rightBaseDir = rightURL, "", "", ignoreHidden)); | 140 | stack.append(new CompareTask(0, leftBaseDir = left, rightBaseDir = right, QString(), QString(), | ||
141 | ignoreHidden)); | ||||
152 | compareLoop(); | 142 | compareLoop(); | ||
153 | 143 | | |||
154 | QListIterator<SynchronizerFileItem *> it(temporaryList); | 144 | QListIterator<SynchronizerFileItem *> it(temporaryList); | ||
155 | while (it.hasNext()) { | 145 | while (it.hasNext()) { | ||
156 | SynchronizerFileItem * item = it.next(); | 146 | SynchronizerFileItem *item = it.next(); | ||
157 | 147 | | |||
158 | if (item->isTemporary()) | 148 | if (item->isTemporary()) | ||
159 | delete item; | 149 | delete item; | ||
160 | } | 150 | } | ||
161 | temporaryList.clear(); | 151 | temporaryList.clear(); | ||
162 | 152 | | |||
163 | | ||||
164 | if (!autoScroll) | 153 | if (!autoScroll) | ||
165 | refresh(true); | 154 | refresh(true); | ||
166 | 155 | | |||
167 | emit statusInfo(i18n("Number of files: %1", fileCount)); | 156 | emit statusInfo(i18n("Number of files: %1", fileCount)); | ||
168 | return fileCount; | 157 | return fileCount; | ||
169 | } | 158 | } | ||
170 | 159 | | |||
171 | void Synchronizer::compareLoop() | 160 | void Synchronizer::compareLoop() | ||
172 | { | 161 | { | ||
173 | while (!stopped && !stack.isEmpty()) { | 162 | while (!stopped && !stack.isEmpty()) { | ||
174 | for (int thread = 0; thread < (int)stack.count() && thread < parallelThreads; thread++) { | 163 | for (int thread = 0; thread < (int)stack.count() && thread < parallelThreads; thread++) { | ||
175 | SynchronizerTask * entry = stack.at(thread); | 164 | SynchronizerTask *entry = stack.at(thread); | ||
176 | 165 | | |||
177 | if (entry->state() == ST_STATE_NEW) | 166 | if (entry->state() == ST_STATE_NEW) | ||
178 | entry->start(parentWidget); | 167 | entry->start(parentWidget); | ||
179 | 168 | | |||
180 | if (entry->inherits("CompareTask")) { | 169 | if (entry->inherits("CompareTask")) { | ||
181 | if (entry->state() == ST_STATE_READY) { | 170 | if (entry->state() == ST_STATE_READY) { | ||
182 | CompareTask *ctentry = (CompareTask *) entry; | 171 | CompareTask *ctentry = (CompareTask *)entry; | ||
183 | if (ctentry->isDuplicate()) | 172 | if (ctentry->isDuplicate()) | ||
184 | compareDirectory(ctentry->parent(), ctentry->leftDirList(), ctentry->rightDirList(), | 173 | compareDirectory(ctentry->parent(), ctentry->leftDirList(), | ||
185 | ctentry->leftDir(), ctentry->rightDir()); | 174 | ctentry->rightDirList(), ctentry->leftDir(), | ||
175 | ctentry->rightDir()); | ||||
186 | else | 176 | else | ||
187 | addSingleDirectory(ctentry->parent(), ctentry->dirList(), ctentry->dir(), | 177 | addSingleDirectory(ctentry->parent(), ctentry->dirList(), ctentry->dir(), | ||
188 | ctentry->isLeft()); | 178 | ctentry->isLeft()); | ||
189 | } | 179 | } | ||
190 | if (entry->state() == ST_STATE_READY || entry->state() == ST_STATE_ERROR) | 180 | if (entry->state() == ST_STATE_READY || entry->state() == ST_STATE_ERROR) | ||
191 | comparedDirs++; | 181 | comparedDirs++; | ||
192 | } | 182 | } | ||
193 | switch (entry->state()) { | 183 | switch (entry->state()) { | ||
Show All 15 Lines | |||||
209 | } | 199 | } | ||
210 | 200 | | |||
211 | QListIterator<SynchronizerTask *> it(stack); | 201 | QListIterator<SynchronizerTask *> it(stack); | ||
212 | while (it.hasNext()) | 202 | while (it.hasNext()) | ||
213 | delete it.next(); | 203 | delete it.next(); | ||
214 | stack.clear(); | 204 | stack.clear(); | ||
215 | } | 205 | } | ||
216 | 206 | | |||
217 | void Synchronizer::compareDirectory(SynchronizerFileItem *parent, SynchronizerDirList * left_directory, | 207 | void Synchronizer::compareDirectory(SynchronizerFileItem *parent, | ||
218 | SynchronizerDirList * right_directory, const QString &leftDir, | 208 | SynchronizerDirList *left_directory, | ||
219 | const QString &rightDir) | 209 | SynchronizerDirList *right_directory, | ||
220 | { | 210 | const QString &leftDir, const QString &rightDir) | ||
221 | const QString &leftURL = left_directory->url(); | 211 | { | ||
222 | const QString &rightURL = right_directory->url(); | 212 | const QUrl leftDirectoryPath = left_directory->url(); | ||
213 | const QUrl rightDirectoryPath = right_directory->url(); | ||||
214 | const bool checkIfSelected = leftDir.isEmpty() && rightDir.isEmpty() && selectedFiles.count(); | ||||
215 | | ||||
223 | FileItem *left_file; | 216 | FileItem *left_file; | ||
224 | FileItem *right_file; | 217 | FileItem *right_file; | ||
225 | | ||||
226 | QString file_name; | 218 | QString file_name; | ||
227 | bool checkIfSelected = false; | | |||
228 | | ||||
229 | if (leftDir.isEmpty() && rightDir.isEmpty() && selectedFiles.count()) | | |||
230 | checkIfSelected = true; | | |||
231 | 219 | | |||
232 | /* walking through in the left directory */ | 220 | /* walking through in the left directory */ | ||
233 | for (left_file = left_directory->first(); left_file != 0 && !stopped; | 221 | for (left_file = left_directory->first(); left_file != 0 && !stopped; | ||
234 | left_file = left_directory->next()) { | 222 | left_file = left_directory->next()) { | ||
223 | | ||||
235 | if (isDir(left_file)) | 224 | if (isDir(left_file)) | ||
236 | continue; | 225 | continue; | ||
237 | 226 | | |||
238 | file_name = left_file->getName(); | 227 | file_name = left_file->getName(); | ||
239 | 228 | | |||
240 | if (checkIfSelected && !selectedFiles.contains(file_name)) | 229 | if (checkIfSelected && !selectedFiles.contains(file_name)) | ||
241 | continue; | 230 | continue; | ||
242 | 231 | | |||
243 | if (!query->match(left_file)) | 232 | if (!query->match(left_file)) | ||
244 | continue; | 233 | continue; | ||
245 | 234 | | |||
246 | if ((right_file = right_directory->search(file_name, ignoreCase)) == 0) | 235 | if ((right_file = right_directory->search(file_name, ignoreCase)) == 0) | ||
247 | addLeftOnlyItem(parent, file_name, leftDir, left_file->getSize(), left_file->getTime_t(), | 236 | addLeftOnlyItem(left_file, parent, leftDir); | ||
248 | readLink(left_file), left_file->getOwner(), left_file->getGroup(), | | |||
249 | left_file->getMode(), left_file->getACL()); | | |||
250 | else { | 237 | else { | ||
251 | if (isDir(right_file)) | 238 | if (isDir(right_file)) | ||
252 | continue; | 239 | continue; | ||
253 | 240 | | |||
254 | addDuplicateItem(parent, file_name, right_file->getName(), leftDir, rightDir, left_file->getSize(), right_file->getSize(), | 241 | addDuplicateItem(left_file, right_file, parent, leftDir, rightDir); | ||
255 | left_file->getTime_t(), right_file->getTime_t(), readLink(left_file), | | |||
256 | readLink(right_file), left_file->getOwner(), right_file->getOwner(), | | |||
257 | left_file->getGroup(), right_file->getGroup(), | | |||
258 | left_file->getMode(), right_file->getMode(), | | |||
259 | left_file->getACL(), right_file->getACL()); | | |||
260 | } | 242 | } | ||
261 | } | 243 | } | ||
262 | 244 | | |||
263 | /* walking through in the right directory */ | 245 | /* walking through in the right directory */ | ||
264 | for (right_file = right_directory->first(); right_file != 0 && !stopped; | 246 | for (right_file = right_directory->first(); right_file != 0 && !stopped; | ||
265 | right_file = right_directory->next()) { | 247 | right_file = right_directory->next()) { | ||
266 | if (isDir(right_file)) | 248 | if (isDir(right_file)) | ||
267 | continue; | 249 | continue; | ||
268 | 250 | | |||
269 | file_name = right_file->getName(); | 251 | file_name = right_file->getName(); | ||
270 | 252 | | |||
271 | if (checkIfSelected && !selectedFiles.contains(file_name)) | 253 | if (checkIfSelected && !selectedFiles.contains(file_name)) | ||
272 | continue; | 254 | continue; | ||
273 | 255 | | |||
274 | if (!query->match(right_file)) | 256 | if (!query->match(right_file)) | ||
275 | continue; | 257 | continue; | ||
276 | 258 | | |||
277 | if (left_directory->search(file_name, ignoreCase) == 0) | 259 | if (left_directory->search(file_name, ignoreCase) == 0) | ||
278 | addRightOnlyItem(parent, file_name, rightDir, right_file->getSize(), right_file->getTime_t(), | 260 | addRightOnlyItem(right_file, parent, rightDir); | ||
279 | readLink(right_file), right_file->getOwner(), right_file->getGroup(), | | |||
280 | right_file->getMode(), right_file->getACL()); | | |||
281 | } | 261 | } | ||
282 | 262 | | |||
283 | /* walking through the subdirectories */ | | |||
284 | if (recurseSubDirs) { | 263 | if (recurseSubDirs) { | ||
264 | | ||||
265 | /* walking through the left side subdirectories */ | ||||
285 | for (left_file = left_directory->first(); left_file != 0 && !stopped; | 266 | for (left_file = left_directory->first(); left_file != 0 && !stopped; | ||
286 | left_file = left_directory->next()) { | 267 | left_file = left_directory->next()) { | ||
287 | if (left_file->isDir() && (followSymLinks || !left_file->isSymLink())) { | 268 | | ||
288 | QString left_file_name = left_file->getName(); | 269 | if (!left_file->isDir() || !(followSymLinks || !left_file->isSymLink())) | ||
270 | continue; | ||||
271 | | ||||
272 | const QString left_file_name = left_file->getName(); | ||||
289 | 273 | | |||
290 | if (checkIfSelected && !selectedFiles.contains(left_file_name)) | 274 | if (checkIfSelected && !selectedFiles.contains(left_file_name)) | ||
291 | continue; | 275 | continue; | ||
292 | 276 | | |||
293 | if (excludedPaths.contains(leftDir.isEmpty() ? left_file_name : leftDir + '/' + left_file_name)) | 277 | if (excludedPaths.contains(leftDir.isEmpty() ? left_file_name : | ||
278 | leftDir + '/' + left_file_name)) | ||||
294 | continue; | 279 | continue; | ||
295 | 280 | | |||
296 | if (!query->matchDirName(left_file_name)) | 281 | if (!query->matchDirName(left_file_name)) | ||
297 | continue; | 282 | continue; | ||
298 | 283 | | |||
284 | const QUrl leftFilePath = pathAppend(leftDirectoryPath, left_file_name); | ||||
285 | const QString leftRelativeDir = | ||||
286 | leftDir.isEmpty() ? left_file_name : leftDir + '/' + left_file_name; | ||||
287 | | ||||
299 | if ((right_file = right_directory->search(left_file_name, ignoreCase)) == 0) { | 288 | if ((right_file = right_directory->search(left_file_name, ignoreCase)) == 0) { | ||
300 | SynchronizerFileItem *me = addLeftOnlyItem(parent, left_file_name, leftDir, 0, | 289 | // no right file dir | ||
301 | left_file->getTime_t(), readLink(left_file), | 290 | SynchronizerFileItem *me = | ||
302 | left_file->getOwner(), left_file->getGroup(), | 291 | addLeftOnlyItem(left_file, parent, leftDir, !query->match(left_file)); | ||
303 | left_file->getMode(), left_file->getACL(), | 292 | stack.append( | ||
304 | true, !query->match(left_file)); | 293 | new CompareTask(me, leftFilePath, leftRelativeDir, true, ignoreHidden)); | ||
305 | stack.append(new CompareTask(me, leftURL + left_file_name + '/', | | |||
306 | leftDir.isEmpty() ? left_file_name : leftDir + '/' + left_file_name, true, ignoreHidden)); | | |||
307 | } else { | 294 | } else { | ||
308 | QString right_file_name = right_file->getName(); | 295 | // compare left file dir with right file | ||
309 | SynchronizerFileItem *me = addDuplicateItem(parent, left_file_name, right_file_name, | 296 | const QString right_file_name = right_file->getName(); | ||
310 | leftDir, rightDir, 0, 0, | 297 | const QUrl rightFilePath = pathAppend(rightDirectoryPath, right_file_name); | ||
311 | left_file->getTime_t(), right_file->getTime_t(), | 298 | const QString rightRelativeDir = | ||
312 | readLink(left_file), readLink(right_file), | 299 | rightDir.isEmpty() ? right_file_name : rightDir + '/' + right_file_name; | ||
313 | left_file->getOwner(), right_file->getOwner(), | 300 | | ||
314 | left_file->getGroup(), right_file->getGroup(), | 301 | SynchronizerFileItem *me = addDuplicateItem(left_file, right_file, parent, leftDir, | ||
315 | left_file->getMode(), right_file->getMode(), | 302 | rightDir, !query->match(left_file)); | ||
316 | left_file->getACL(), right_file->getACL(), | 303 | | ||
317 | true, !query->match(left_file)); | 304 | stack.append(new CompareTask(me, leftFilePath, rightFilePath, leftRelativeDir, | ||
318 | stack.append(new CompareTask(me, leftURL + left_file_name + '/', rightURL + right_file_name + '/', | 305 | rightRelativeDir, ignoreHidden)); | ||
319 | leftDir.isEmpty() ? left_file_name : leftDir + '/' + left_file_name, | | |||
320 | rightDir.isEmpty() ? right_file_name : rightDir + '/' + right_file_name, ignoreHidden)); | | |||
321 | } | | |||
322 | } | 306 | } | ||
323 | } | 307 | } | ||
324 | 308 | | |||
325 | /* walking through the right side subdirectories */ | 309 | /* walking through the right side subdirectories */ | ||
326 | for (right_file = right_directory->first(); right_file != 0 && !stopped; | 310 | for (right_file = right_directory->first(); right_file != 0 && !stopped; | ||
327 | right_file = right_directory->next()) { | 311 | right_file = right_directory->next()) { | ||
328 | if (right_file->isDir() && (followSymLinks || !right_file->isSymLink())) { | 312 | | ||
313 | if (!right_file->isDir() || !(followSymLinks || !right_file->isSymLink())) | ||||
314 | continue; | ||||
315 | | ||||
329 | file_name = right_file->getName(); | 316 | file_name = right_file->getName(); | ||
330 | 317 | | |||
331 | if (checkIfSelected && !selectedFiles.contains(file_name)) | 318 | if (checkIfSelected && !selectedFiles.contains(file_name)) | ||
332 | continue; | 319 | continue; | ||
333 | 320 | | |||
334 | if (excludedPaths.contains(rightDir.isEmpty() ? file_name : rightDir + '/' + file_name)) | 321 | const QString rightRelativePath = | ||
322 | rightDir.isEmpty() ? file_name : rightDir + '/' + file_name; | ||||
323 | if (excludedPaths.contains(rightRelativePath)) | ||||
335 | continue; | 324 | continue; | ||
336 | 325 | | |||
337 | if (!query->matchDirName(file_name)) | 326 | if (!query->matchDirName(file_name)) | ||
338 | continue; | 327 | continue; | ||
339 | 328 | | |||
340 | if (left_directory->search(file_name, ignoreCase) == 0) { | 329 | if (left_directory->search(file_name, ignoreCase) == 0) { | ||
341 | SynchronizerFileItem *me = addRightOnlyItem(parent, file_name, rightDir, 0, | 330 | // no left exists | ||
342 | right_file->getTime_t(), readLink(right_file), | 331 | SynchronizerFileItem *me = | ||
343 | right_file->getOwner(), right_file->getGroup(), | 332 | addRightOnlyItem(right_file, parent, rightDir, !query->match(right_file)); | ||
344 | right_file->getMode(), right_file->getACL(), | 333 | stack.append(new CompareTask(me, pathAppend(rightDirectoryPath, file_name), | ||
345 | true, !query->match(right_file)); | 334 | rightRelativePath, false, ignoreHidden)); | ||
346 | stack.append(new CompareTask(me, rightURL + file_name + '/', | | |||
347 | rightDir.isEmpty() ? file_name : rightDir + '/' + file_name, false, ignoreHidden)); | | |||
348 | } | | |||
349 | } | 335 | } | ||
350 | } | 336 | } | ||
337 | | ||||
351 | } | 338 | } | ||
352 | } | 339 | } | ||
353 | 340 | | |||
354 | QString Synchronizer::getTaskTypeName(TaskType taskType) | 341 | QString Synchronizer::getTaskTypeName(TaskType taskType) | ||
355 | { | 342 | { | ||
356 | static QString names[] = {"=", "!=", "<-", "->", "DEL", "?", "?", "?", "?", "?"}; | 343 | static QString names[] = {"=", "!=", "<-", "->", "DEL", "?", "?", "?", "?", "?"}; | ||
357 | 344 | | |||
358 | return names[taskType]; | 345 | return names[taskType]; | ||
359 | } | 346 | } | ||
360 | 347 | | |||
361 | SynchronizerFileItem * Synchronizer::addItem(SynchronizerFileItem *parent, const QString &leftFile, | 348 | SynchronizerFileItem *Synchronizer::addItem(FileItem *leftFile, FileItem *rightFile, | ||
362 | const QString &rightFile, const QString &leftDir, | 349 | SynchronizerFileItem *parent, | ||
363 | const QString &rightDir, bool existsLeft, bool existsRight, | 350 | const QString &leftDir, const QString &rightDir, | ||
364 | KIO::filesize_t leftSize, KIO::filesize_t rightSize, | 351 | TaskType tsk, bool isTemp) | ||
365 | time_t leftDate, time_t rightDate, const QString &leftLink, | 352 | { | ||
366 | const QString &rightLink, const QString &leftOwner, | 353 | const bool existsLeft = leftFile != nullptr; | ||
367 | const QString &rightOwner, const QString &leftGroup, | 354 | const bool existsRight = rightFile != nullptr; | ||
368 | const QString &rightGroup, mode_t leftMode, mode_t rightMode, | 355 | const bool marked = autoScroll ? !isTemp && isMarked(tsk, existsLeft && existsRight) : false; | ||
369 | const QString &leftACL, const QString &rightACL, TaskType tsk, | 356 | const FileItem left = existsLeft ? FileItem(*leftFile) : FileItem(); | ||
370 | bool isDir, bool isTemp) | 357 | const FileItem right = existsRight ? FileItem(*rightFile) : FileItem(); | ||
371 | { | 358 | SynchronizerFileItem *item = new SynchronizerFileItem(left, right, leftDir, rightDir, | ||
372 | bool marked = autoScroll ? !isTemp && isMarked(tsk, existsLeft && existsRight) : false; | 359 | marked, tsk, isTemp, parent); | ||
373 | SynchronizerFileItem *item = new SynchronizerFileItem(leftFile, rightFile, leftDir, rightDir, marked, | | |||
374 | existsLeft, existsRight, leftSize, rightSize, leftDate, rightDate, leftLink, rightLink, | | |||
375 | leftOwner, rightOwner, leftGroup, rightGroup, leftMode, rightMode, leftACL, rightACL, tsk, isDir, | | |||
376 | isTemp, parent); | | |||
377 | 360 | | |||
378 | if (!isTemp) { | 361 | if (!isTemp) { | ||
379 | while (parent && parent->isTemporary()) | 362 | while (parent && parent->isTemporary()) | ||
380 | setPermanent(parent); | 363 | setPermanent(parent); | ||
381 | 364 | | |||
382 | bool doRefresh = false; | 365 | bool doRefresh = false; | ||
383 | 366 | | |||
384 | if (marked) { | 367 | if (marked) { | ||
Show All 11 Lines | |||||
396 | if (marked && (displayUpdateCount++ % DISPLAY_UPDATE_PERIOD == (DISPLAY_UPDATE_PERIOD - 1))) | 379 | if (marked && (displayUpdateCount++ % DISPLAY_UPDATE_PERIOD == (DISPLAY_UPDATE_PERIOD - 1))) | ||
397 | qApp->processEvents(); | 380 | qApp->processEvents(); | ||
398 | } else | 381 | } else | ||
399 | temporaryList.append(item); | 382 | temporaryList.append(item); | ||
400 | 383 | | |||
401 | return item; | 384 | return item; | ||
402 | } | 385 | } | ||
403 | 386 | | |||
404 | void Synchronizer::compareContentResult(SynchronizerFileItem * item, bool res) | 387 | SynchronizerFileItem *Synchronizer::addLeftOnlyItem(FileItem *leftFile, SynchronizerFileItem *parent, | ||
388 | const QString &dir, bool isTemp) | ||||
405 | { | 389 | { | ||
406 | item->compareContentResult(res); | 390 | return addItem(leftFile, nullptr, parent, dir, dir, asymmetric ? TT_DELETE : TT_COPY_TO_RIGHT, | ||
407 | bool marked = autoScroll ? isMarked(item->task(), item->existsInLeft() && item->existsInRight()) : false; | 391 | isTemp); | ||
408 | item->setMarked(marked); | | |||
409 | if (marked) { | | |||
410 | markParentDirectories(item); | | |||
411 | fileCount++; | | |||
412 | emit markChanged(item, true); | | |||
413 | } | | |||
414 | } | 392 | } | ||
415 | 393 | | |||
416 | void Synchronizer::setPermanent(SynchronizerFileItem *item) | 394 | SynchronizerFileItem *Synchronizer::addRightOnlyItem(FileItem *rightFile, SynchronizerFileItem *parent, | ||
395 | const QString &dir, bool isTemp) | ||||
417 | { | 396 | { | ||
418 | if (item->parent() && item->parent()->isTemporary()) | 397 | return addItem(nullptr, rightFile, parent, dir, dir, TT_COPY_TO_LEFT, isTemp); | ||
419 | setPermanent(item->parent()); | | |||
420 | | ||||
421 | item->setPermanent(); | | |||
422 | resultList.append(item); | | |||
423 | emit comparedFileData(item); | | |||
424 | } | | |||
425 | | ||||
426 | SynchronizerFileItem * Synchronizer::addLeftOnlyItem(SynchronizerFileItem *parent, | | |||
427 | const QString &file_name, const QString &dir, KIO::filesize_t size, | | |||
428 | time_t date, const QString &link, const QString &owner, | | |||
429 | const QString &group, mode_t mode, const QString &acl, bool isDir, | | |||
430 | bool isTemp) | | |||
431 | { | | |||
432 | return addItem(parent, file_name, file_name, dir, dir, true, false, size, 0, date, 0, link, QString(), | | |||
433 | owner, QString(), group, QString(), mode, (mode_t) - 1, acl, QString(), | | |||
434 | asymmetric ? TT_DELETE : TT_COPY_TO_RIGHT, isDir, isTemp); | | |||
435 | } | | |||
436 | | ||||
437 | SynchronizerFileItem * Synchronizer::addRightOnlyItem(SynchronizerFileItem *parent, | | |||
438 | const QString &file_name, const QString &dir, KIO::filesize_t size, | | |||
439 | time_t date, const QString &link, const QString &owner, | | |||
440 | const QString &group, mode_t mode, const QString &acl, bool isDir, | | |||
441 | bool isTemp) | | |||
442 | { | | |||
443 | return addItem(parent, file_name, file_name, dir, dir, false, true, 0, size, 0, date, QString(), link, | | |||
444 | QString(), owner, QString(), group, (mode_t) - 1, mode, QString(), acl, | | |||
445 | TT_COPY_TO_LEFT, isDir, isTemp); | | |||
446 | } | 398 | } | ||
447 | 399 | | |||
448 | SynchronizerFileItem * Synchronizer::addDuplicateItem(SynchronizerFileItem *parent, | 400 | SynchronizerFileItem *Synchronizer::addDuplicateItem(FileItem *leftFile, FileItem *rightFile, | ||
449 | const QString &leftName, const QString &rightName, | 401 | SynchronizerFileItem *parent, const QString &leftDir, const QString &rightDir, bool isTemp) | ||
450 | const QString &leftDir, const QString &rightDir, | | |||
451 | KIO::filesize_t leftSize, KIO::filesize_t rightSize, time_t leftDate, time_t rightDate, | | |||
452 | const QString &leftLink, const QString &rightLink, | | |||
453 | const QString &leftOwner, const QString &rightOwner, | | |||
454 | const QString &leftGroup, const QString &rightGroup, | | |||
455 | mode_t leftMode, mode_t rightMode, | | |||
456 | const QString &leftACL, const QString &rightACL, | | |||
457 | bool isDir, bool isTemp) | | |||
458 | { | 402 | { | ||
459 | TaskType task; | 403 | TaskType task; | ||
460 | 404 | | |||
461 | int checkedRightDate = rightDate - timeOffset; | 405 | Q_ASSERT(leftFile->isDir() == rightFile->isDir()); | ||
406 | const bool isDir = leftFile->isDir(); | ||||
407 | const int checkedRightDate = rightFile->getTime_t() - timeOffset; | ||||
408 | const time_t leftDate = leftFile->getTime_t(); | ||||
462 | int uncertain = 0; | 409 | int uncertain = 0; | ||
463 | 410 | | |||
464 | do { | 411 | do { | ||
465 | if (isDir) { | 412 | if (isDir) { | ||
466 | task = TT_EQUALS; | 413 | task = TT_EQUALS; | ||
467 | break; | 414 | break; | ||
468 | } | 415 | } | ||
469 | if (leftSize == rightSize) { | 416 | | ||
470 | if (!leftLink.isNull() || !rightLink.isNull()) { | 417 | if (leftFile->getSize() == rightFile->getSize()) { | ||
471 | if (leftLink == rightLink) { | 418 | if (leftFile->isSymLink() == rightFile->isSymLink() && | ||
419 | rightFile->getSymDest() == rightFile->getSymDest()) { | ||||
472 | task = TT_EQUALS; | 420 | task = TT_EQUALS; | ||
473 | break; | 421 | break; | ||
474 | } | 422 | } else if (cmpByContent) { | ||
475 | } else if (cmpByContent) | | |||
476 | uncertain = TT_UNKNOWN; | 423 | uncertain = TT_UNKNOWN; | ||
477 | else { | 424 | } else { | ||
478 | if (ignoreDate || leftDate == checkedRightDate) { | 425 | if (ignoreDate || leftDate == checkedRightDate) { | ||
479 | task = TT_EQUALS; | 426 | task = TT_EQUALS; | ||
480 | break; | 427 | break; | ||
481 | } | 428 | } | ||
482 | time_t diff = (leftDate > checkedRightDate) ? leftDate - checkedRightDate : checkedRightDate - leftDate; | 429 | time_t diff = (leftDate > checkedRightDate) ? leftDate - checkedRightDate : | ||
430 | checkedRightDate - leftDate; | ||||
483 | if (diff <= equalsThreshold) { | 431 | if (diff <= equalsThreshold) { | ||
484 | task = TT_EQUALS; | 432 | task = TT_EQUALS; | ||
485 | break; | 433 | break; | ||
486 | } | 434 | } | ||
487 | } | 435 | } | ||
488 | } | 436 | } | ||
489 | 437 | | |||
490 | if (asymmetric) | 438 | if (asymmetric) | ||
491 | task = TT_COPY_TO_LEFT; | 439 | task = TT_COPY_TO_LEFT; | ||
492 | else if (ignoreDate) | 440 | else if (ignoreDate) | ||
493 | task = TT_DIFFERS; | 441 | task = TT_DIFFERS; | ||
494 | else if (leftDate > checkedRightDate) | 442 | else if (leftDate > checkedRightDate) | ||
495 | task = TT_COPY_TO_RIGHT; | 443 | task = TT_COPY_TO_RIGHT; | ||
496 | else if (leftDate < checkedRightDate) | 444 | else if (leftDate < checkedRightDate) | ||
497 | task = TT_COPY_TO_LEFT; | 445 | task = TT_COPY_TO_LEFT; | ||
498 | else | 446 | else | ||
499 | task = TT_DIFFERS; | 447 | task = TT_DIFFERS; | ||
500 | 448 | | |||
501 | } while (false); | 449 | } while (false); | ||
502 | 450 | | |||
503 | SynchronizerFileItem * item = addItem(parent, leftName, rightName, leftDir, rightDir, true, true, | 451 | SynchronizerFileItem *item = addItem(leftFile, rightFile, | ||
504 | leftSize, rightSize, leftDate, rightDate, leftLink, rightLink, | 452 | parent, leftDir, rightDir, (TaskType)(task + uncertain), isTemp); | ||
505 | leftOwner, rightOwner, leftGroup, rightGroup, | | |||
506 | leftMode, rightMode, leftACL, rightACL, | | |||
507 | (TaskType)(task + uncertain), isDir, isTemp); | | |||
508 | 453 | | |||
509 | if (uncertain == TT_UNKNOWN) { | 454 | if (uncertain == TT_UNKNOWN) { | ||
510 | QUrl leftURL = Synchronizer::fsUrl(leftDir.isEmpty() ? leftBaseDir + leftName : leftBaseDir + leftDir + '/' + leftName); | 455 | const QUrl leftURL = pathAppend(leftBaseDir, leftDir, leftFile->getName()); | ||
511 | QUrl rightURL = Synchronizer::fsUrl(rightDir.isEmpty() ? rightBaseDir + rightName : rightBaseDir + rightDir + '/' + rightName); | 456 | const QUrl rightURL = pathAppend(rightBaseDir, rightDir, rightFile->getName()); | ||
512 | stack.append(new CompareContentTask(this, item, leftURL, rightURL, leftSize)); | 457 | stack.append(new CompareContentTask(this, item, leftURL, rightURL, leftFile->getSize())); | ||
513 | } | 458 | } | ||
514 | 459 | | |||
515 | return item; | 460 | return item; | ||
516 | } | 461 | } | ||
517 | 462 | | |||
518 | void Synchronizer::addSingleDirectory(SynchronizerFileItem *parent, SynchronizerDirList *directory, | 463 | void Synchronizer::addSingleDirectory(SynchronizerFileItem *parent, SynchronizerDirList *directory, | ||
519 | const QString &dirName, bool isLeft) | 464 | const QString &dirName, bool isLeft) | ||
520 | { | 465 | { | ||
521 | const QString &url = directory->url(); | 466 | const QUrl &url = directory->url(); | ||
522 | FileItem *file; | 467 | FileItem *file; | ||
523 | QString file_name; | 468 | QString file_name; | ||
524 | 469 | | |||
525 | /* walking through the directory files */ | 470 | /* walking through the directory files */ | ||
526 | for (file = directory->first(); file != 0 && !stopped; file = directory->next()) { | 471 | for (file = directory->first(); file != 0 && !stopped; file = directory->next()) { | ||
527 | if (isDir(file)) | 472 | if (isDir(file)) | ||
528 | continue; | 473 | continue; | ||
529 | 474 | | |||
530 | file_name = file->getName(); | 475 | file_name = file->getName(); | ||
531 | 476 | | |||
532 | if (!query->match(file)) | 477 | if (!query->match(file)) | ||
533 | continue; | 478 | continue; | ||
534 | 479 | | |||
535 | if (isLeft) | 480 | if (isLeft) | ||
536 | addLeftOnlyItem(parent, file_name, dirName, file->getSize(), file->getTime_t(), readLink(file), | 481 | addLeftOnlyItem(file, parent, dirName); | ||
537 | file->getOwner(), file->getGroup(), file->getMode(), file->getACL()); | | |||
538 | else | 482 | else | ||
539 | addRightOnlyItem(parent, file_name, dirName, file->getSize(), file->getTime_t(), readLink(file), | 483 | addRightOnlyItem(file, parent, dirName); | ||
540 | file->getOwner(), file->getGroup(), file->getMode(), file->getACL()); | | |||
541 | } | 484 | } | ||
542 | 485 | | |||
543 | /* walking through the subdirectories */ | 486 | /* walking through the subdirectories */ | ||
544 | for (file = directory->first(); file != 0 && !stopped; file = directory->next()) { | 487 | for (file = directory->first(); file != 0 && !stopped; file = directory->next()) { | ||
545 | if (file->isDir() && (followSymLinks || !file->isSymLink())) { | 488 | if (file->isDir() && (followSymLinks || !file->isSymLink())) { | ||
546 | file_name = file->getName(); | 489 | file_name = file->getName(); | ||
547 | 490 | | |||
548 | if (excludedPaths.contains(dirName.isEmpty() ? file_name : dirName + '/' + file_name)) | 491 | if (excludedPaths.contains(dirName.isEmpty() ? file_name : dirName + '/' + file_name)) | ||
549 | continue; | 492 | continue; | ||
550 | 493 | | |||
551 | if (!query->matchDirName(file_name)) | 494 | if (!query->matchDirName(file_name)) | ||
552 | continue; | 495 | continue; | ||
553 | 496 | | |||
554 | SynchronizerFileItem *me; | 497 | SynchronizerFileItem *me = | ||
498 | isLeft ? addLeftOnlyItem(file, parent, dirName, !query->match(file)) : | ||||
499 | addRightOnlyItem(file, parent, dirName, !query->match(file)); | ||||
500 | | ||||
501 | stack.append(new CompareTask(me, pathAppend(url, file_name), | ||||
502 | dirName.isEmpty() ? file_name : dirName + '/' + file_name, | ||||
503 | isLeft, ignoreHidden)); | ||||
504 | } | ||||
505 | } | ||||
506 | } | ||||
555 | 507 | | |||
556 | if (isLeft) | 508 | void Synchronizer::compareContentResult(SynchronizerFileItem *item, bool res) | ||
557 | me = addLeftOnlyItem(parent, file_name, dirName, 0, file->getTime_t(), readLink(file), | 509 | { | ||
558 | file->getOwner(), file->getGroup(), file->getMode(), | 510 | item->compareContentResult(res); | ||
559 | file->getACL(), true, !query->match(file)); | 511 | bool marked = | ||
560 | else | 512 | autoScroll ? isMarked(item->task(), item->existsLeft() && item->existsRight()) : false; | ||
561 | me = addRightOnlyItem(parent, file_name, dirName, 0, file->getTime_t(), readLink(file), | 513 | item->setMarked(marked); | ||
562 | file->getOwner(), file->getGroup(), file->getMode(), | 514 | if (marked) { | ||
563 | file->getACL(), true, !query->match(file)); | 515 | markParentDirectories(item); | ||
564 | stack.append(new CompareTask(me, url + file_name + '/', | 516 | fileCount++; | ||
565 | dirName.isEmpty() ? file_name : dirName + '/' + file_name, isLeft, ignoreHidden)); | 517 | emit markChanged(item, true); | ||
566 | } | 518 | } | ||
567 | } | 519 | } | ||
520 | | ||||
521 | void Synchronizer::setPermanent(SynchronizerFileItem *item) | ||||
522 | { | ||||
523 | if (item->parent() && item->parent()->isTemporary()) | ||||
524 | setPermanent(item->parent()); | ||||
525 | | ||||
526 | item->setPermanent(); | ||||
527 | resultList.append(item); | ||||
528 | emit comparedFileData(item); | ||||
568 | } | 529 | } | ||
569 | 530 | | |||
570 | void Synchronizer::setMarkFlags(bool left, bool equal, bool differs, bool right, bool dup, bool sing, | 531 | void Synchronizer::setMarkFlags(bool left, bool equal, bool differs, bool right, bool dup, | ||
571 | bool del) | 532 | bool sing, bool del) | ||
572 | { | 533 | { | ||
573 | markEquals = equal; | 534 | markEquals = equal; | ||
574 | markDiffers = differs; | 535 | markDiffers = differs; | ||
575 | markCopyToLeft = left; | 536 | markCopyToLeft = left; | ||
576 | markCopyToRight = right; | 537 | markCopyToRight = right; | ||
577 | markDeletable = del; | 538 | markDeletable = del; | ||
578 | markDuplicates = dup; | 539 | markDuplicates = dup; | ||
579 | markSingles = sing; | 540 | markSingles = sing; | ||
580 | } | 541 | } | ||
581 | 542 | | |||
582 | bool Synchronizer::isMarked(TaskType task, bool isDuplicate) | 543 | bool Synchronizer::isMarked(TaskType task, bool isDuplicate) | ||
583 | { | 544 | { | ||
584 | if ((isDuplicate && !markDuplicates) || (!isDuplicate && !markSingles)) | 545 | if ((isDuplicate && !markDuplicates) || (!isDuplicate && !markSingles)) | ||
585 | return false; | 546 | return false; | ||
586 | 547 | | |||
587 | switch (task) { | 548 | switch (task) { | ||
Show All 27 Lines | |||||
615 | } | 576 | } | ||
616 | 577 | | |||
617 | int Synchronizer::refresh(bool nostatus) | 578 | int Synchronizer::refresh(bool nostatus) | ||
618 | { | 579 | { | ||
619 | fileCount = 0; | 580 | fileCount = 0; | ||
620 | 581 | | |||
621 | QListIterator<SynchronizerFileItem *> it(resultList); | 582 | QListIterator<SynchronizerFileItem *> it(resultList); | ||
622 | while (it.hasNext()) { | 583 | while (it.hasNext()) { | ||
623 | SynchronizerFileItem * item = it.next(); | 584 | SynchronizerFileItem *item = it.next(); | ||
624 | 585 | | |||
625 | bool marked = isMarked(item->task(), item->existsInLeft() && item->existsInRight()); | 586 | bool marked = isMarked(item->task(), item->existsLeft() && item->existsRight()); | ||
626 | item->setMarked(marked); | 587 | item->setMarked(marked); | ||
627 | 588 | | |||
628 | if (marked) { | 589 | if (marked) { | ||
629 | markParentDirectories(item); | 590 | markParentDirectories(item); | ||
630 | fileCount++; | 591 | fileCount++; | ||
631 | } | 592 | } | ||
632 | } | 593 | } | ||
633 | 594 | | |||
634 | it.toFront(); | 595 | it.toFront(); | ||
635 | while (it.hasNext()) { | 596 | while (it.hasNext()) { | ||
636 | SynchronizerFileItem * item = it.next(); | 597 | SynchronizerFileItem *item = it.next(); | ||
637 | emit markChanged(item, false); | 598 | emit markChanged(item, false); | ||
638 | } | 599 | } | ||
639 | 600 | | |||
640 | if (!nostatus) | 601 | if (!nostatus) | ||
641 | emit statusInfo(i18n("Number of files: %1", fileCount)); | 602 | emit statusInfo(i18n("Number of files: %1", fileCount)); | ||
642 | 603 | | |||
643 | return fileCount; | 604 | return fileCount; | ||
644 | } | 605 | } | ||
645 | 606 | | |||
646 | void Synchronizer::operate(SynchronizerFileItem *item, | 607 | void Synchronizer::operate(SynchronizerFileItem *item, | ||
647 | void (*executeOperation)(SynchronizerFileItem *)) | 608 | void (*executeOperation)(SynchronizerFileItem *)) | ||
648 | { | 609 | { | ||
649 | executeOperation(item); | 610 | executeOperation(item); | ||
650 | 611 | | |||
651 | if (item->isDir()) { | 612 | if (item->isDir()) { | ||
652 | QString leftDirName = (item->leftDirectory().isEmpty()) ? | 613 | const QString leftDirName = (item->leftDirectory().isEmpty()) ? | ||
653 | item->leftName() : item->leftDirectory() + '/' + item->leftName(); | 614 | item->leftName() : | ||
654 | QString rightDirName = (item->rightDirectory().isEmpty()) ? | 615 | item->leftDirectory() + '/' + item->leftName(); | ||
655 | item->rightName() : item->rightDirectory() + '/' + item->rightName(); | 616 | const QString rightDirName = (item->rightDirectory().isEmpty()) ? | ||
617 | item->rightName() : | ||||
618 | item->rightDirectory() + '/' + item->rightName(); | ||||
656 | 619 | | |||
657 | QListIterator<SynchronizerFileItem *> it(resultList); | 620 | QListIterator<SynchronizerFileItem *> it(resultList); | ||
658 | while (it.hasNext()) { | 621 | while (it.hasNext()) { | ||
659 | SynchronizerFileItem * item = it.next(); | 622 | SynchronizerFileItem *item = it.next(); | ||
660 | 623 | | |||
661 | if (item->leftDirectory() == leftDirName || item->leftDirectory().startsWith(leftDirName + '/') || | 624 | if (item->leftDirectory() == leftDirName || | ||
662 | item->rightDirectory() == rightDirName || item->rightDirectory().startsWith(rightDirName + '/')) | 625 | item->leftDirectory().startsWith(leftDirName + '/') || | ||
626 | item->rightDirectory() == rightDirName || | ||||
627 | item->rightDirectory().startsWith(rightDirName + '/')) | ||||
663 | executeOperation(item); | 628 | executeOperation(item); | ||
664 | } | 629 | } | ||
665 | } | 630 | } | ||
666 | } | 631 | } | ||
667 | 632 | | |||
668 | void Synchronizer::excludeOperation(SynchronizerFileItem *item) | 633 | void Synchronizer::excludeOperation(SynchronizerFileItem *item) { item->setTask(TT_DIFFERS); } | ||
669 | { | | |||
670 | item->setTask(TT_DIFFERS); | | |||
671 | } | | |||
672 | 634 | | |||
673 | void Synchronizer::exclude(SynchronizerFileItem *item) | 635 | void Synchronizer::exclude(SynchronizerFileItem *item) | ||
674 | { | 636 | { | ||
675 | if (!item->parent() || item->parent()->task() != TT_DELETE) | 637 | if (!item->parent() || item->parent()->task() != TT_DELETE) | ||
676 | operate(item, excludeOperation); /* exclude only if the parent task is not DEL */ | 638 | operate(item, excludeOperation); /* exclude only if the parent task is not DEL */ | ||
677 | } | 639 | } | ||
678 | 640 | | |||
679 | void Synchronizer::restoreOperation(SynchronizerFileItem *item) | 641 | void Synchronizer::restoreOperation(SynchronizerFileItem *item) { item->restoreOriginalTask(); } | ||
680 | { | | |||
681 | item->restoreOriginalTask(); | | |||
682 | } | | |||
683 | 642 | | |||
684 | void Synchronizer::restore(SynchronizerFileItem *item) | 643 | void Synchronizer::restore(SynchronizerFileItem *item) | ||
685 | { | 644 | { | ||
686 | operate(item, restoreOperation); | 645 | operate(item, restoreOperation); | ||
687 | 646 | | |||
688 | while ((item = item->parent()) != 0) /* in case of restore, the parent directories */ | 647 | while ((item = item->parent()) != 0) /* in case of restore, the parent directories */ | ||
689 | { /* must be changed for being consistent */ | 648 | { /* must be changed for being consistent */ | ||
690 | if (item->task() != TT_DIFFERS) | 649 | if (item->task() != TT_DIFFERS) | ||
691 | break; | 650 | break; | ||
692 | 651 | | |||
693 | if (item->originalTask() == TT_DELETE) /* if the parent original task is delete */ | 652 | if (item->originalTask() == TT_DELETE) /* if the parent original task is delete */ | ||
694 | break; /* don't touch it */ | 653 | break; /* don't touch it */ | ||
695 | 654 | | |||
696 | item->restoreOriginalTask(); /* restore */ | 655 | item->restoreOriginalTask(); /* restore */ | ||
697 | } | 656 | } | ||
698 | } | 657 | } | ||
699 | 658 | | |||
700 | void Synchronizer::reverseDirectionOperation(SynchronizerFileItem *item) | 659 | void Synchronizer::reverseDirectionOperation(SynchronizerFileItem *item) | ||
701 | { | 660 | { | ||
702 | if (item->existsInRight() && item->existsInLeft()) { | 661 | if (item->existsRight() && item->existsLeft()) { | ||
703 | if (item->task() == TT_COPY_TO_LEFT) | 662 | if (item->task() == TT_COPY_TO_LEFT) | ||
704 | item->setTask(TT_COPY_TO_RIGHT); | 663 | item->setTask(TT_COPY_TO_RIGHT); | ||
705 | else if (item->task() == TT_COPY_TO_RIGHT) | 664 | else if (item->task() == TT_COPY_TO_RIGHT) | ||
706 | item->setTask(TT_COPY_TO_LEFT); | 665 | item->setTask(TT_COPY_TO_LEFT); | ||
707 | } | 666 | } | ||
708 | } | 667 | } | ||
709 | 668 | | |||
710 | void Synchronizer::reverseDirection(SynchronizerFileItem *item) | 669 | void Synchronizer::reverseDirection(SynchronizerFileItem *item) | ||
711 | { | 670 | { | ||
712 | operate(item, reverseDirectionOperation); | 671 | operate(item, reverseDirectionOperation); | ||
713 | } | 672 | } | ||
714 | 673 | | |||
715 | void Synchronizer::deleteLeftOperation(SynchronizerFileItem *item) | 674 | void Synchronizer::deleteLeftOperation(SynchronizerFileItem *item) | ||
716 | { | 675 | { | ||
717 | if (!item->existsInRight() && item->existsInLeft()) | 676 | if (!item->existsRight() && item->existsLeft()) | ||
718 | item->setTask(TT_DELETE); | 677 | item->setTask(TT_DELETE); | ||
719 | } | 678 | } | ||
720 | 679 | | |||
721 | void Synchronizer::deleteLeft(SynchronizerFileItem *item) | 680 | QUrl Synchronizer::pathAppend(const QUrl &url, const QString &fileName) | ||
681 | { | ||||
682 | QUrl newUrl = QUrl(url); | ||||
683 | newUrl.setPath(QDir(url.path()).filePath(fileName)); | ||||
684 | return newUrl; | ||||
685 | } | ||||
686 | | ||||
687 | QUrl Synchronizer::pathAppend(const QUrl &url, const QString &dirName, const QString &fileName) | ||||
722 | { | 688 | { | ||
723 | operate(item, deleteLeftOperation); | 689 | QUrl newUrl = QUrl(url); | ||
690 | newUrl.setPath(QDir(QDir(url.path()).filePath(dirName)).filePath(fileName)); | ||||
691 | return newUrl; | ||||
724 | } | 692 | } | ||
725 | 693 | | |||
694 | void Synchronizer::deleteLeft(SynchronizerFileItem *item) { operate(item, deleteLeftOperation); } | ||||
695 | | ||||
726 | void Synchronizer::copyToLeftOperation(SynchronizerFileItem *item) | 696 | void Synchronizer::copyToLeftOperation(SynchronizerFileItem *item) | ||
727 | { | 697 | { | ||
728 | if (item->existsInRight()) { | 698 | if (item->existsRight()) { | ||
729 | if (!item->isDir()) | 699 | if (!item->isDir()) | ||
730 | item->setTask(TT_COPY_TO_LEFT); | 700 | item->setTask(TT_COPY_TO_LEFT); | ||
731 | else { | 701 | else { | ||
732 | if (item->existsInLeft() && item->existsInRight()) | 702 | if (item->existsLeft() && item->existsRight()) | ||
733 | item->setTask(TT_EQUALS); | 703 | item->setTask(TT_EQUALS); | ||
734 | else if (!item->existsInLeft() && item->existsInRight()) | 704 | else if (!item->existsLeft() && item->existsRight()) | ||
735 | item->setTask(TT_COPY_TO_LEFT); | 705 | item->setTask(TT_COPY_TO_LEFT); | ||
736 | } | 706 | } | ||
737 | } | 707 | } | ||
738 | } | 708 | } | ||
739 | 709 | | |||
740 | void Synchronizer::copyToLeft(SynchronizerFileItem *item) | 710 | void Synchronizer::copyToLeft(SynchronizerFileItem *item) | ||
741 | { | 711 | { | ||
742 | operate(item, copyToLeftOperation); | 712 | operate(item, copyToLeftOperation); | ||
743 | 713 | | |||
744 | while ((item = item->parent()) != 0) { | 714 | while ((item = item->parent()) != 0) { | ||
745 | if (item->task() != TT_DIFFERS) | 715 | if (item->task() != TT_DIFFERS) | ||
746 | break; | 716 | break; | ||
747 | 717 | | |||
748 | if (item->existsInLeft() && item->existsInRight()) | 718 | if (item->existsLeft() && item->existsRight()) | ||
749 | item->setTask(TT_EQUALS); | 719 | item->setTask(TT_EQUALS); | ||
750 | else if (!item->existsInLeft() && item->existsInRight()) | 720 | else if (!item->existsLeft() && item->existsRight()) | ||
751 | item->setTask(TT_COPY_TO_LEFT); | 721 | item->setTask(TT_COPY_TO_LEFT); | ||
752 | } | 722 | } | ||
753 | } | 723 | } | ||
754 | 724 | | |||
755 | void Synchronizer::copyToRightOperation(SynchronizerFileItem *item) | 725 | void Synchronizer::copyToRightOperation(SynchronizerFileItem *item) | ||
756 | { | 726 | { | ||
757 | if (item->existsInLeft()) { | 727 | if (item->existsLeft()) { | ||
758 | if (!item->isDir()) | 728 | if (!item->isDir()) | ||
759 | item->setTask(TT_COPY_TO_RIGHT); | 729 | item->setTask(TT_COPY_TO_RIGHT); | ||
760 | else { | 730 | else { | ||
761 | if (item->existsInLeft() && item->existsInRight()) | 731 | if (item->existsLeft() && item->existsRight()) | ||
762 | item->setTask(TT_EQUALS); | 732 | item->setTask(TT_EQUALS); | ||
763 | else if (item->existsInLeft() && !item->existsInRight()) | 733 | else if (item->existsLeft() && !item->existsRight()) | ||
764 | item->setTask(TT_COPY_TO_RIGHT); | 734 | item->setTask(TT_COPY_TO_RIGHT); | ||
765 | } | 735 | } | ||
766 | } | 736 | } | ||
767 | } | 737 | } | ||
768 | 738 | | |||
769 | void Synchronizer::copyToRight(SynchronizerFileItem *item) | 739 | void Synchronizer::copyToRight(SynchronizerFileItem *item) | ||
770 | { | 740 | { | ||
771 | operate(item, copyToRightOperation); | 741 | operate(item, copyToRightOperation); | ||
772 | 742 | | |||
773 | while ((item = item->parent()) != 0) { | 743 | while ((item = item->parent()) != 0) { | ||
774 | if (item->task() != TT_DIFFERS && item->task() != TT_DELETE) | 744 | if (item->task() != TT_DIFFERS && item->task() != TT_DELETE) | ||
775 | break; | 745 | break; | ||
776 | 746 | | |||
777 | if (item->existsInLeft() && item->existsInRight()) | 747 | if (item->existsLeft() && item->existsRight()) | ||
778 | item->setTask(TT_EQUALS); | 748 | item->setTask(TT_EQUALS); | ||
779 | else if (item->existsInLeft() && !item->existsInRight()) | 749 | else if (item->existsLeft() && !item->existsRight()) | ||
780 | item->setTask(TT_COPY_TO_RIGHT); | 750 | item->setTask(TT_COPY_TO_RIGHT); | ||
781 | } | 751 | } | ||
782 | } | 752 | } | ||
783 | 753 | | |||
784 | bool Synchronizer::totalSizes(int * leftCopyNr, KIO::filesize_t *leftCopySize, int * rightCopyNr, | 754 | bool Synchronizer::totalSizes(int *leftCopyNr, KIO::filesize_t *leftCopySize, int *rightCopyNr, | ||
785 | KIO::filesize_t *rightCopySize, int *deleteNr, KIO::filesize_t *deletableSize) | 755 | KIO::filesize_t *rightCopySize, int *deleteNr, | ||
756 | KIO::filesize_t *deletableSize) | ||||
786 | { | 757 | { | ||
787 | bool hasAnythingToDo = false; | 758 | bool hasAnythingToDo = false; | ||
788 | 759 | | |||
789 | *leftCopySize = *rightCopySize = *deletableSize = 0; | 760 | *leftCopySize = *rightCopySize = *deletableSize = 0; | ||
790 | *leftCopyNr = *rightCopyNr = *deleteNr = 0; | 761 | *leftCopyNr = *rightCopyNr = *deleteNr = 0; | ||
791 | 762 | | |||
792 | QListIterator<SynchronizerFileItem *> it(resultList); | 763 | QListIterator<SynchronizerFileItem *> it(resultList); | ||
793 | while (it.hasNext()) { | 764 | while (it.hasNext()) { | ||
794 | SynchronizerFileItem * item = it.next(); | 765 | SynchronizerFileItem *item = it.next(); | ||
795 | 766 | | |||
796 | if (item->isMarked()) { | 767 | if (item->isMarked()) { | ||
797 | switch (item->task()) { | 768 | switch (item->task()) { | ||
798 | case TT_COPY_TO_LEFT: | 769 | case TT_COPY_TO_LEFT: | ||
799 | *leftCopySize += item->rightSize(); | 770 | *leftCopySize += item->rightSize(); | ||
800 | (*leftCopyNr)++; | 771 | (*leftCopyNr)++; | ||
801 | hasAnythingToDo = true; | 772 | hasAnythingToDo = true; | ||
802 | break; | 773 | break; | ||
Show All 13 Lines | |||||
816 | } | 787 | } | ||
817 | } | 788 | } | ||
818 | 789 | | |||
819 | return hasAnythingToDo; | 790 | return hasAnythingToDo; | ||
820 | } | 791 | } | ||
821 | 792 | | |||
822 | void Synchronizer::swapSides() | 793 | void Synchronizer::swapSides() | ||
823 | { | 794 | { | ||
824 | QString leftTmp = leftBaseDir; | 795 | const QUrl leftTmp = leftBaseDir; | ||
825 | leftBaseDir = rightBaseDir; | 796 | leftBaseDir = rightBaseDir; | ||
826 | rightBaseDir = leftTmp; | 797 | rightBaseDir = leftTmp; | ||
827 | 798 | | |||
828 | QListIterator<SynchronizerFileItem *> it(resultList); | 799 | QListIterator<SynchronizerFileItem *> it(resultList); | ||
829 | while (it.hasNext()) { | 800 | while (it.hasNext()) { | ||
830 | SynchronizerFileItem * item = it.next(); | 801 | SynchronizerFileItem *item = it.next(); | ||
831 | 802 | | |||
832 | item->swap(asymmetric); | 803 | item->swap(asymmetric); | ||
833 | } | 804 | } | ||
834 | } | 805 | } | ||
835 | 806 | | |||
836 | void Synchronizer::setScrolling(bool scroll) | 807 | void Synchronizer::setScrolling(bool scroll) | ||
837 | { | 808 | { | ||
838 | autoScroll = scroll; | 809 | autoScroll = scroll; | ||
839 | if (autoScroll) { | 810 | if (autoScroll) { | ||
840 | int oldFileCount = fileCount; | 811 | int oldFileCount = fileCount; | ||
841 | refresh(true); | 812 | refresh(true); | ||
842 | fileCount = oldFileCount; | 813 | fileCount = oldFileCount; | ||
843 | } | 814 | } | ||
844 | } | 815 | } | ||
845 | 816 | | |||
846 | void Synchronizer::synchronize(QWidget *syncWdg, bool leftCopyEnabled, bool rightCopyEnabled, | 817 | void Synchronizer::synchronize(QWidget *syncDialog, bool leftCopyEnabled, bool rightCopyEnabled, | ||
847 | bool deleteEnabled, bool overWrite, int parThreads) | 818 | bool deleteEnabled, bool overWrite, int parThreads) | ||
848 | { | 819 | { | ||
849 | this->leftCopyEnabled = leftCopyEnabled; | 820 | this->leftCopyEnabled = leftCopyEnabled; | ||
850 | this->rightCopyEnabled = rightCopyEnabled; | 821 | this->rightCopyEnabled = rightCopyEnabled; | ||
851 | this->deleteEnabled = deleteEnabled; | 822 | this->deleteEnabled = deleteEnabled; | ||
852 | this->overWrite = overWrite; | 823 | this->overWrite = overWrite; | ||
853 | this->parallelThreads = parThreads; | 824 | this->parallelThreads = parThreads; | ||
854 | this->syncDlgWidget = syncWdg; | 825 | this->syncDlgWidget = syncDialog; | ||
855 | 826 | | |||
856 | autoSkip = paused = disableNewTasks = false; | 827 | autoSkip = paused = disableNewTasks = false; | ||
857 | 828 | | |||
858 | leftCopyNr = rightCopyNr = deleteNr = 0; | 829 | leftCopyNr = rightCopyNr = deleteNr = 0; | ||
859 | leftCopySize = rightCopySize = deleteSize = 0; | 830 | leftCopySize = rightCopySize = deleteSize = 0; | ||
860 | 831 | | |||
861 | inTaskFinished = 0; | 832 | inTaskFinished = 0; | ||
862 | lastTask = 0; | 833 | lastTask = 0; | ||
Show All 21 Lines | 852 | if (task == 0) { | |||
884 | return; | 855 | return; | ||
885 | } | 856 | } | ||
886 | executeTask(task); | 857 | executeTask(task); | ||
887 | if (disableNewTasks) | 858 | if (disableNewTasks) | ||
888 | break; | 859 | break; | ||
889 | } | 860 | } | ||
890 | } | 861 | } | ||
891 | 862 | | |||
892 | SynchronizerFileItem * Synchronizer::getNextTask() | 863 | SynchronizerFileItem *Synchronizer::getNextTask() | ||
893 | { | 864 | { | ||
894 | TaskType task; | 865 | TaskType task; | ||
895 | SynchronizerFileItem * currentTask; | 866 | SynchronizerFileItem *currentTask; | ||
896 | 867 | | |||
897 | do { | 868 | do { | ||
898 | if (!resultListIt.hasNext()) | 869 | if (!resultListIt.hasNext()) | ||
899 | return 0; | 870 | return 0; | ||
900 | 871 | | |||
901 | currentTask = resultListIt.next(); | 872 | currentTask = resultListIt.next(); | ||
902 | 873 | | |||
903 | if (currentTask->isMarked()) { | 874 | if (currentTask->isMarked()) { | ||
904 | task = currentTask->task(); | 875 | task = currentTask->task(); | ||
905 | 876 | | |||
906 | if (leftCopyEnabled && task == TT_COPY_TO_LEFT) | 877 | if (leftCopyEnabled && task == TT_COPY_TO_LEFT) | ||
907 | break; | 878 | break; | ||
908 | else if (rightCopyEnabled && task == TT_COPY_TO_RIGHT) | 879 | else if (rightCopyEnabled && task == TT_COPY_TO_RIGHT) | ||
909 | break; | 880 | break; | ||
910 | else if (deleteEnabled && task == TT_DELETE) | 881 | else if (deleteEnabled && task == TT_DELETE) | ||
911 | break; | 882 | break; | ||
912 | } | 883 | } | ||
913 | } while (true); | 884 | } while (true); | ||
914 | 885 | | |||
915 | return lastTask = currentTask; | 886 | return lastTask = currentTask; | ||
916 | } | 887 | } | ||
917 | 888 | | |||
918 | | ||||
919 | void Synchronizer::executeTask(SynchronizerFileItem * task) | 889 | void Synchronizer::executeTask(SynchronizerFileItem *task) | ||
920 | { | 890 | { | ||
921 | QString leftDirName = task->leftDirectory(); | 891 | const QUrl leftURL = pathAppend(leftBaseDir, task->leftDirectory(), task->leftName()); | ||
922 | if (!leftDirName.isEmpty()) | 892 | const QUrl rightURL = pathAppend(rightBaseDir, task->rightDirectory(), task->rightName()); | ||
923 | leftDirName += '/'; | | |||
924 | QString rightDirName = task->rightDirectory(); | | |||
925 | if (!rightDirName.isEmpty()) | | |||
926 | rightDirName += '/'; | | |||
927 | 893 | | |||
928 | QUrl leftURL = Synchronizer::fsUrl(leftBaseDir + leftDirName + task->leftName()); | 894 | KJob *job = nullptr; | ||
929 | QUrl rightURL = Synchronizer::fsUrl(rightBaseDir + rightDirName + task->rightName()); | | |||
930 | 895 | | |||
931 | switch (task->task()) { | 896 | switch (task->task()) { | ||
932 | case TT_COPY_TO_LEFT: | 897 | case TT_COPY_TO_LEFT: | ||
933 | if (task->isDir()) { | 898 | job = createJob(task, rightURL, leftURL, task->rightLink()); | ||
934 | KIO::SimpleJob *job = KIO::mkdir(leftURL); | 899 | break; | ||
935 | connect(job, SIGNAL(result(KJob*)), this, SLOT(slotTaskFinished(KJob*))); | 900 | case TT_COPY_TO_RIGHT: | ||
936 | jobMap[ job ] = task; | 901 | job = createJob(task, leftURL, rightURL, task->leftLink()); | ||
937 | disableNewTasks = true; | 902 | break; | ||
938 | } else { | 903 | case TT_DELETE: | ||
939 | QUrl destURL(leftURL); | 904 | job = KIO::del(leftURL, KIO::DefaultFlags); | ||
940 | if (!task->destination().isNull()) | 905 | break; | ||
941 | destURL = Synchronizer::fsUrl(task->destination()); | 906 | default: | ||
942 | 907 | return; | |||
943 | if (task->rightLink().isNull()) { | 908 | } | ||
944 | KIO::FileCopyJob *job = KIO::file_copy(rightURL, destURL, -1, | 909 | | ||
945 | ((overWrite || task->overWrite()) ? KIO::Overwrite : KIO::DefaultFlags) | KIO::HideProgressInfo); | 910 | if (job) { | ||
946 | connect(job, SIGNAL(processedSize(KJob*,qulonglong)), this, | 911 | connect(job, &KIO::FileCopyJob::result, this, &Synchronizer::slotTaskFinished); | ||
947 | SLOT(slotProcessedSize(KJob*,qulonglong))); | | |||
948 | connect(job, SIGNAL(result(KJob*)), this, SLOT(slotTaskFinished(KJob*))); | | |||
949 | jobMap[ job ] = task; | | |||
950 | } else { | | |||
951 | KIO::SimpleJob *job = KIO::symlink(task->rightLink(), destURL, | | |||
952 | ((overWrite || task->overWrite()) ? KIO::Overwrite : KIO::DefaultFlags) | KIO::HideProgressInfo); | | |||
953 | connect(job, SIGNAL(result(KJob*)), this, SLOT(slotTaskFinished(KJob*))); | | |||
954 | jobMap[ job ] = task; | 912 | jobMap[job] = task; | ||
955 | } | 913 | } | ||
956 | } | 914 | } | ||
957 | break; | 915 | | ||
958 | case TT_COPY_TO_RIGHT: | 916 | KJob *Synchronizer::createJob(SynchronizerFileItem *task, const QUrl &src, const QUrl &dest, | ||
917 | const QString &link) | ||||
918 | { | ||||
919 | KJob *job; | ||||
959 | if (task->isDir()) { | 920 | if (task->isDir()) { | ||
960 | KIO::SimpleJob *job = KIO::mkdir(rightURL); | 921 | job = KIO::mkdir(dest); | ||
961 | connect(job, SIGNAL(result(KJob*)), this, SLOT(slotTaskFinished(KJob*))); | | |||
962 | jobMap[ job ] = task; | | |||
963 | disableNewTasks = true; | 922 | disableNewTasks = true; | ||
964 | } else { | 923 | } else { | ||
965 | QUrl destURL(rightURL); | 924 | const QUrl destURL = task->destination().isEmpty() ? dest : task->destination(); | ||
966 | if (!task->destination().isNull()) | 925 | const KIO::JobFlags flags = | ||
967 | destURL = Synchronizer::fsUrl(task->destination()); | 926 | ((overWrite || task->overWrite()) ? KIO::Overwrite : KIO::DefaultFlags) | | ||
968 | 927 | KIO::HideProgressInfo; | |||
969 | if (task->leftLink().isNull()) { | 928 | | ||
970 | KIO::FileCopyJob *job = KIO::file_copy(leftURL, destURL, -1, | 929 | if (link.isNull()) { | ||
971 | ((overWrite || task->overWrite()) ? KIO::Overwrite : KIO::DefaultFlags) | KIO::HideProgressInfo); | 930 | job = KIO::file_copy(src, destURL, -1, flags); | ||
972 | connect(job, SIGNAL(processedSize(KJob*,qulonglong)), this, | 931 | connect(job, SIGNAL(processedSize(KJob *, qulonglong)), this, | ||
973 | SLOT(slotProcessedSize(KJob*,qulonglong))); | 932 | SLOT(slotProcessedSize(KJob *, qulonglong))); | ||
974 | connect(job, SIGNAL(result(KJob*)), this, SLOT(slotTaskFinished(KJob*))); | | |||
975 | jobMap[ job ] = task; | | |||
976 | } else { | 933 | } else { | ||
977 | KIO::SimpleJob *job = KIO::symlink(task->leftLink(), destURL, | 934 | job = KIO::symlink(link, destURL, flags); | ||
978 | ((overWrite || task->overWrite()) ? KIO::Overwrite : KIO::DefaultFlags) | KIO::HideProgressInfo); | | |||
979 | connect(job, SIGNAL(result(KJob*)), this, SLOT(slotTaskFinished(KJob*))); | | |||
980 | jobMap[ job ] = task; | | |||
981 | } | 935 | } | ||
982 | } | 936 | } | ||
983 | break; | 937 | | ||
984 | case TT_DELETE: { | 938 | return job; | ||
985 | KIO::DeleteJob *job = KIO::del(leftURL, KIO::DefaultFlags); | | |||
986 | connect(job, SIGNAL(result(KJob*)), this, SLOT(slotTaskFinished(KJob*))); | | |||
987 | jobMap[ job ] = task; | | |||
988 | } | | |||
989 | break; | | |||
990 | default: | | |||
991 | break; | | |||
992 | } | | |||
993 | } | 939 | } | ||
994 | 940 | | |||
995 | void Synchronizer::slotTaskFinished(KJob *job) | 941 | void Synchronizer::slotTaskFinished(KJob *job) | ||
996 | { | 942 | { | ||
997 | inTaskFinished++; | 943 | inTaskFinished++; | ||
998 | 944 | | |||
999 | SynchronizerFileItem * item = jobMap[ job ]; | 945 | SynchronizerFileItem *item = jobMap[job]; | ||
1000 | jobMap.remove(job); | 946 | jobMap.remove(job); | ||
1001 | 947 | | |||
1002 | KIO::filesize_t receivedSize = 0; | 948 | KIO::filesize_t receivedSize = 0; | ||
1003 | 949 | | |||
1004 | if (receivedMap.contains(job)) { | 950 | if (receivedMap.contains(job)) { | ||
1005 | receivedSize = receivedMap[ job ]; | 951 | receivedSize = receivedMap[job]; | ||
1006 | receivedMap.remove(job); | 952 | receivedMap.remove(job); | ||
1007 | } | 953 | } | ||
1008 | 954 | | |||
1009 | if (disableNewTasks && item == lastTask) | 955 | if (disableNewTasks && item == lastTask) | ||
1010 | disableNewTasks = false; // the blocker task finished | 956 | disableNewTasks = false; // the blocker task finished | ||
1011 | 957 | | |||
1012 | QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + '/'; | 958 | const QUrl leftURL = pathAppend(leftBaseDir, item->leftDirectory() , item->leftName()); | ||
1013 | QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + '/'; | 959 | const QUrl rightURL = pathAppend(rightBaseDir, item->rightDirectory(), item->rightName()); | ||
1014 | QUrl leftURL = Synchronizer::fsUrl(leftBaseDir + leftDirName + item->leftName()); | | |||
1015 | QUrl rightURL = Synchronizer::fsUrl(rightBaseDir + rightDirName + item->rightName()); | | |||
1016 | 960 | | |||
1017 | do { | 961 | do { | ||
1018 | if (!job->error()) { | 962 | if (!job->error()) { | ||
1019 | switch (item->task()) { | 963 | switch (item->task()) { | ||
1020 | case TT_COPY_TO_LEFT: | 964 | case TT_COPY_TO_LEFT: | ||
1021 | if (leftURL.isLocalFile()) { | 965 | if (leftURL.isLocalFile()) { | ||
1022 | struct utimbuf timestamp; | 966 | struct utimbuf timestamp; | ||
1023 | 967 | | |||
1024 | timestamp.actime = time(0); | 968 | timestamp.actime = time(0); | ||
1025 | timestamp.modtime = item->rightDate() - timeOffset; | 969 | timestamp.modtime = item->rightDate() - timeOffset; | ||
1026 | 970 | | |||
1027 | utime((const char *)(leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), ×tamp); | 971 | utime((const char | ||
972 | *)(leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), | ||||
973 | ×tamp); | ||||
1028 | 974 | | |||
1029 | uid_t newOwnerID = (uid_t) - 1; // chown(2) : -1 means no change | 975 | uid_t newOwnerID = (uid_t)-1; // chown(2) : -1 means no change | ||
1030 | if (!item->rightOwner().isEmpty()) { | 976 | if (!item->rightOwner().isEmpty()) { | ||
1031 | struct passwd* pw = getpwnam(QFile::encodeName(item->rightOwner())); | 977 | struct passwd *pw = getpwnam(QFile::encodeName(item->rightOwner())); | ||
1032 | if (pw != 0L) | 978 | if (pw != 0L) | ||
1033 | newOwnerID = pw->pw_uid; | 979 | newOwnerID = pw->pw_uid; | ||
1034 | } | 980 | } | ||
1035 | gid_t newGroupID = (gid_t) - 1; // chown(2) : -1 means no change | 981 | gid_t newGroupID = (gid_t)-1; // chown(2) : -1 means no change | ||
1036 | if (!item->rightGroup().isEmpty()) { | 982 | if (!item->rightGroup().isEmpty()) { | ||
1037 | struct group* g = getgrnam(QFile::encodeName(item->rightGroup())); | 983 | struct group *g = getgrnam(QFile::encodeName(item->rightGroup())); | ||
1038 | if (g != 0L) | 984 | if (g != 0L) | ||
1039 | newGroupID = g->gr_gid; | 985 | newGroupID = g->gr_gid; | ||
1040 | } | 986 | } | ||
1041 | int status1 = chown((const char *)(leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), newOwnerID, (gid_t) - 1); | 987 | chown((const char | ||
1042 | int status2 = chown((const char *)(leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), (uid_t) - 1, newGroupID); | 988 | *)(leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), | ||
1043 | if (status1 < 0 || status2 < 0) { | 989 | newOwnerID, (gid_t)-1); | ||
1044 | // synchronizer currently ignores chown errors | 990 | chown((const char | ||
1045 | } | 991 | *)(leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), | ||
1046 | 992 | (uid_t)-1, newGroupID); | |||
1047 | chmod((const char *)(leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), item->rightMode() & 07777); | 993 | | ||
994 | chmod((const char | ||||
995 | *)(leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), | ||||
996 | item->rightMode() & 07777); | ||||
1048 | 997 | | |||
1049 | #ifdef HAVE_POSIX_ACL | 998 | #ifdef HAVE_POSIX_ACL | ||
1050 | if (!item->rightACL().isNull()) { | 999 | if (!item->rightACL().isNull()) { | ||
1051 | acl_t acl = acl_from_text(item->rightACL().toLatin1()); | 1000 | acl_t acl = acl_from_text(item->rightACL().toLatin1()); | ||
1052 | if (acl && !acl_valid(acl)) | 1001 | if (acl && !acl_valid(acl)) | ||
1053 | acl_set_file(leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit(), ACL_TYPE_ACCESS, acl); | 1002 | acl_set_file( | ||
1003 | leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit(), | ||||
1004 | ACL_TYPE_ACCESS, acl); | ||||
1054 | if (acl) | 1005 | if (acl) | ||
1055 | acl_free(acl); | 1006 | acl_free(acl); | ||
1056 | } | 1007 | } | ||
1057 | #endif | 1008 | #endif | ||
1058 | } | 1009 | } | ||
1059 | break; | 1010 | break; | ||
1060 | case TT_COPY_TO_RIGHT: | 1011 | case TT_COPY_TO_RIGHT: | ||
1061 | if (rightURL.isLocalFile()) { | 1012 | if (rightURL.isLocalFile()) { | ||
1062 | struct utimbuf timestamp; | 1013 | struct utimbuf timestamp; | ||
1063 | 1014 | | |||
1064 | timestamp.actime = time(0); | 1015 | timestamp.actime = time(0); | ||
1065 | timestamp.modtime = item->leftDate() + timeOffset; | 1016 | timestamp.modtime = item->leftDate() + timeOffset; | ||
1066 | 1017 | | |||
1067 | utime((const char *)(rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), ×tamp); | 1018 | utime((const char | ||
1019 | *)(rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), | ||||
1020 | ×tamp); | ||||
1068 | 1021 | | |||
1069 | uid_t newOwnerID = (uid_t) - 1; // chown(2) : -1 means no change | 1022 | uid_t newOwnerID = (uid_t)-1; // chown(2) : -1 means no change | ||
1070 | if (!item->leftOwner().isEmpty()) { | 1023 | if (!item->leftOwner().isEmpty()) { | ||
1071 | struct passwd* pw = getpwnam(QFile::encodeName(item->leftOwner())); | 1024 | struct passwd *pw = getpwnam(QFile::encodeName(item->leftOwner())); | ||
1072 | if (pw != 0L) | 1025 | if (pw != 0L) | ||
1073 | newOwnerID = pw->pw_uid; | 1026 | newOwnerID = pw->pw_uid; | ||
1074 | } | 1027 | } | ||
1075 | gid_t newGroupID = (gid_t) - 1; // chown(2) : -1 means no change | 1028 | gid_t newGroupID = (gid_t)-1; // chown(2) : -1 means no change | ||
1076 | if (!item->leftGroup().isEmpty()) { | 1029 | if (!item->leftGroup().isEmpty()) { | ||
1077 | struct group* g = getgrnam(QFile::encodeName(item->leftGroup())); | 1030 | struct group *g = getgrnam(QFile::encodeName(item->leftGroup())); | ||
1078 | if (g != 0L) | 1031 | if (g != 0L) | ||
1079 | newGroupID = g->gr_gid; | 1032 | newGroupID = g->gr_gid; | ||
1080 | } | 1033 | } | ||
1081 | int status1 = chown((const char *)(rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), newOwnerID, (uid_t) - 1); | 1034 | chown((const char | ||
1082 | int status2 = chown((const char *)(rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), (uid_t) - 1, newGroupID); | 1035 | *)(rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), | ||
1083 | if (status1 < 0 || status2 < 0) { | 1036 | newOwnerID, (uid_t)-1); | ||
1084 | // synchronizer currently ignores chown errors | 1037 | chown((const char | ||
1085 | } | 1038 | *)(rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), | ||
1086 | 1039 | (uid_t)-1, newGroupID); | |||
1087 | chmod((const char *)(rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), item->leftMode() & 07777); | 1040 | | ||
1041 | chmod((const char | ||||
1042 | *)(rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), | ||||
1043 | item->leftMode() & 07777); | ||||
1088 | 1044 | | |||
1089 | #ifdef HAVE_POSIX_ACL | 1045 | #ifdef HAVE_POSIX_ACL | ||
1090 | if (!item->leftACL().isNull()) { | 1046 | if (!item->leftACL().isNull()) { | ||
1091 | acl_t acl = acl_from_text(item->leftACL().toLatin1()); | 1047 | acl_t acl = acl_from_text(item->leftACL().toLatin1()); | ||
1092 | if (acl && !acl_valid(acl)) | 1048 | if (acl && !acl_valid(acl)) | ||
1093 | acl_set_file(rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit(), ACL_TYPE_ACCESS, acl); | 1049 | acl_set_file( | ||
1050 | rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit(), | ||||
1051 | ACL_TYPE_ACCESS, acl); | ||||
1094 | if (acl) | 1052 | if (acl) | ||
1095 | acl_free(acl); | 1053 | acl_free(acl); | ||
1096 | } | 1054 | } | ||
1097 | #endif | 1055 | #endif | ||
1098 | } | 1056 | } | ||
1099 | break; | 1057 | break; | ||
1100 | default: | 1058 | default: | ||
1101 | break; | 1059 | break; | ||
1102 | } | 1060 | } | ||
1103 | } else { | 1061 | } else { | ||
1104 | if (job->error() == KIO::ERR_FILE_ALREADY_EXIST && item->task() != TT_DELETE) { | | |||
1105 | KIO::RenameDialog_Result result; | | |||
1106 | QString newDest; | | |||
1107 | 1062 | | |||
1063 | if (job->error() == KIO::ERR_FILE_ALREADY_EXIST && item->task() != TT_DELETE) { | ||||
1108 | if (autoSkip) | 1064 | if (autoSkip) | ||
1109 | break; | 1065 | break; | ||
1110 | 1066 | | |||
1111 | KIO::JobUiDelegate *ui = static_cast<KIO::JobUiDelegate*>(job->uiDelegate()); | 1067 | KIO::JobUiDelegate *ui = static_cast<KIO::JobUiDelegate *>(job->uiDelegate()); | ||
1112 | ui->setWindow(syncDlgWidget); | 1068 | ui->setWindow(syncDlgWidget); | ||
1113 | 1069 | | |||
1114 | if (item->task() == TT_COPY_TO_LEFT) { | 1070 | const bool fromRightToLeft = item->task() == TT_COPY_TO_LEFT; | ||
1115 | result = | 1071 | const QUrl source = fromRightToLeft ? rightURL : leftURL; | ||
1116 | ui->askFileRename(job, i18n("File Already Exists"), rightURL, leftURL, | 1072 | const QUrl destination = fromRightToLeft ? leftURL : rightURL; | ||
1117 | KIO::RenameDialog_Overwrite | KIO::RenameDialog_Skip | | 1073 | KIO::filesize_t sizeSrc = fromRightToLeft ? item->rightSize() : item->leftSize(); | ||
1118 | KIO::RenameDialog_MultipleItems, | 1074 | KIO::filesize_t sizeDest = fromRightToLeft ? item->leftSize() : item->rightSize(); | ||
1119 | newDest, item->rightSize(), item->leftSize(), QDateTime(), | 1075 | time_t mTimeSrc = fromRightToLeft ? item->rightDate() : item->leftDate(); | ||
1120 | QDateTime(), QDateTime::fromTime_t(item->rightDate()), | 1076 | time_t mTimeDest = fromRightToLeft ? item->leftDate() : item->rightDate(); | ||
1121 | QDateTime::fromTime_t(item->leftDate())); | 1077 | | ||
1122 | } else { | 1078 | QString newDest; | ||
1123 | result = | 1079 | KIO::RenameDialog_Result result = ui->askFileRename( | ||
1124 | ui->askFileRename(job, i18n("File Already Exists"), leftURL, rightURL, | 1080 | job, i18n("File Already Exists"), source, destination, | ||
1125 | KIO::RenameDialog_Overwrite | KIO::RenameDialog_Skip | | 1081 | KIO::RenameDialog_Overwrite | KIO::RenameDialog_Skip | | ||
1126 | KIO::RenameDialog_MultipleItems, | 1082 | KIO::RenameDialog_MultipleItems, | ||
1127 | newDest, item->leftSize(), item->rightSize(), QDateTime(), | 1083 | newDest, sizeSrc, sizeDest, QDateTime(), QDateTime(), | ||
1128 | QDateTime(), QDateTime::fromTime_t(item->leftDate()), | 1084 | QDateTime::fromTime_t(mTimeSrc), QDateTime::fromTime_t(mTimeDest)); | ||
1129 | QDateTime::fromTime_t(item->rightDate())); | | |||
1130 | } | | |||
1131 | 1085 | | |||
1132 | switch (result) { | 1086 | switch (result) { | ||
1133 | case KIO::R_RENAME: | 1087 | case KIO::R_RENAME: { | ||
1134 | item->setDestination(newDest); | 1088 | QUrl newDestUrl = QUrl(destination); | ||
1089 | newDestUrl.setPath(newDest); // new destination does not contain scheme | ||||
1090 | item->setDestination(newDestUrl); | ||||
1135 | executeTask(item); | 1091 | executeTask(item); | ||
1136 | inTaskFinished--; | 1092 | inTaskFinished--; | ||
1137 | return; | 1093 | return; | ||
1094 | } | ||||
1138 | case KIO::R_OVERWRITE: | 1095 | case KIO::R_OVERWRITE: | ||
1139 | item->setOverWrite(); | 1096 | item->setOverWrite(); | ||
1140 | executeTask(item); | 1097 | executeTask(item); | ||
1141 | inTaskFinished--; | 1098 | inTaskFinished--; | ||
1142 | return; | 1099 | return; | ||
1143 | case KIO::R_OVERWRITE_ALL: | 1100 | case KIO::R_OVERWRITE_ALL: | ||
1144 | overWrite = true; | 1101 | overWrite = true; | ||
1145 | executeTask(item); | 1102 | executeTask(item); | ||
Show All 11 Lines | |||||
1157 | if (job->error() != KIO::ERR_DOES_NOT_EXIST || item->task() != TT_DELETE) { | 1114 | if (job->error() != KIO::ERR_DOES_NOT_EXIST || item->task() != TT_DELETE) { | ||
1158 | if (autoSkip) | 1115 | if (autoSkip) | ||
1159 | break; | 1116 | break; | ||
1160 | 1117 | | |||
1161 | QString error; | 1118 | QString error; | ||
1162 | 1119 | | |||
1163 | switch (item->task()) { | 1120 | switch (item->task()) { | ||
1164 | case TT_COPY_TO_LEFT: | 1121 | case TT_COPY_TO_LEFT: | ||
1165 | error = i18n("Error at copying file %1 to %2.", | 1122 | error = i18n("Error at copying file %1 to %2:\n%3", | ||
1166 | rightURL.toDisplayString(QUrl::PreferLocalFile), | 1123 | rightURL.toDisplayString(QUrl::PreferLocalFile), | ||
1167 | leftURL.toDisplayString(QUrl::PreferLocalFile)); | 1124 | leftURL.toDisplayString(QUrl::PreferLocalFile), | ||
1125 | job->errorString()); | ||||
1168 | break; | 1126 | break; | ||
1169 | case TT_COPY_TO_RIGHT: | 1127 | case TT_COPY_TO_RIGHT: | ||
1170 | error = i18n("Error at copying file %1 to %2.", | 1128 | error = i18n("Error at copying file %1 to %2:\n%3", | ||
1171 | leftURL.toDisplayString(QUrl::PreferLocalFile), | 1129 | leftURL.toDisplayString(QUrl::PreferLocalFile), | ||
1172 | rightURL.toDisplayString(QUrl::PreferLocalFile)); | 1130 | rightURL.toDisplayString(QUrl::PreferLocalFile), | ||
1131 | job->errorString()); | ||||
1173 | break; | 1132 | break; | ||
1174 | case TT_DELETE: | 1133 | case TT_DELETE: | ||
1175 | error = i18n("Error at deleting file %1.", leftURL.toDisplayString(QUrl::PreferLocalFile)); | 1134 | error = i18n("Error at deleting file %1:\n%2", | ||
1135 | leftURL.toDisplayString(QUrl::PreferLocalFile), | ||||
1136 | job->errorString()); | ||||
1176 | break; | 1137 | break; | ||
1177 | default: | 1138 | default: | ||
1178 | break; | 1139 | break; | ||
1179 | } | 1140 | } | ||
1180 | 1141 | | |||
1181 | KIO::JobUiDelegate *ui = static_cast<KIO::JobUiDelegate*>(job->uiDelegate()); | 1142 | KIO::JobUiDelegate *ui = static_cast<KIO::JobUiDelegate *>(job->uiDelegate()); | ||
1182 | ui->setWindow(syncDlgWidget); | 1143 | ui->setWindow(syncDlgWidget); | ||
1183 | 1144 | | |||
1184 | KIO::SkipDialog_Result result = ui->askSkip(job, KIO::SkipDialog_MultipleItems, error); | 1145 | KIO::SkipDialog_Result result = | ||
1146 | ui->askSkip(job, KIO::SkipDialog_MultipleItems, error); | ||||
1185 | 1147 | | |||
1186 | switch (result) { | 1148 | switch (result) { | ||
1187 | case KIO::S_CANCEL: | 1149 | case KIO::S_CANCEL: | ||
1188 | executeTask(item); /* simply retry */ | 1150 | executeTask(item); /* simply retry */ | ||
1189 | inTaskFinished--; | 1151 | inTaskFinished--; | ||
1190 | return; | 1152 | return; | ||
1191 | case KIO::S_AUTO_SKIP: | 1153 | case KIO::S_AUTO_SKIP: | ||
1192 | autoSkip = true; | 1154 | autoSkip = true; | ||
1193 | default: | 1155 | default: | ||
1194 | break; | 1156 | break; | ||
1195 | } | 1157 | } | ||
1196 | } | 1158 | } | ||
Show All 22 Lines | |||||
1219 | if (--inTaskFinished == 0) { | 1181 | if (--inTaskFinished == 0) { | ||
1220 | if (paused) | 1182 | if (paused) | ||
1221 | emit pauseAccepted(); | 1183 | emit pauseAccepted(); | ||
1222 | else | 1184 | else | ||
1223 | synchronizeLoop(); | 1185 | synchronizeLoop(); | ||
1224 | } | 1186 | } | ||
1225 | } | 1187 | } | ||
1226 | 1188 | | |||
1227 | void Synchronizer::slotProcessedSize(KJob * job , qulonglong size) | 1189 | void Synchronizer::slotProcessedSize(KJob *job, qulonglong size) | ||
1228 | { | 1190 | { | ||
1229 | KIO::filesize_t dl = 0, dr = 0, dd = 0; | 1191 | KIO::filesize_t dl = 0, dr = 0, dd = 0; | ||
1230 | SynchronizerFileItem * item = jobMap[ job ]; | 1192 | SynchronizerFileItem *item = jobMap[job]; | ||
1231 | 1193 | | |||
1232 | KIO::filesize_t lastProcessedSize = 0; | 1194 | KIO::filesize_t lastProcessedSize = 0; | ||
1233 | if (receivedMap.contains(job)) | 1195 | if (receivedMap.contains(job)) | ||
1234 | lastProcessedSize = receivedMap[ job ]; | 1196 | lastProcessedSize = receivedMap[job]; | ||
1235 | 1197 | | |||
1236 | receivedMap[ job ] = size; | 1198 | receivedMap[job] = size; | ||
1237 | 1199 | | |||
1238 | switch (item->task()) { | 1200 | switch (item->task()) { | ||
1239 | case TT_COPY_TO_LEFT: | 1201 | case TT_COPY_TO_LEFT: | ||
1240 | dl = size - lastProcessedSize; | 1202 | dl = size - lastProcessedSize; | ||
1241 | break; | 1203 | break; | ||
1242 | case TT_COPY_TO_RIGHT: | 1204 | case TT_COPY_TO_RIGHT: | ||
1243 | dr = size - lastProcessedSize; | 1205 | dr = size - lastProcessedSize; | ||
1244 | break; | 1206 | break; | ||
1245 | case TT_DELETE: | 1207 | case TT_DELETE: | ||
1246 | dd = size - lastProcessedSize; | 1208 | dd = size - lastProcessedSize; | ||
1247 | break; | 1209 | break; | ||
1248 | default: | 1210 | default: | ||
1249 | break; | 1211 | break; | ||
1250 | } | 1212 | } | ||
1251 | 1213 | | |||
1252 | emit processedSizes(leftCopyNr, leftCopySize += dl, rightCopyNr, rightCopySize += dr, deleteNr, deleteSize += dd); | 1214 | emit processedSizes(leftCopyNr, leftCopySize += dl, rightCopyNr, rightCopySize += dr, deleteNr, | ||
1215 | deleteSize += dd); | ||||
1253 | } | 1216 | } | ||
1254 | 1217 | | |||
1255 | void Synchronizer::pause() | 1218 | void Synchronizer::pause() { paused = true; } | ||
1256 | { | | |||
1257 | paused = true; | | |||
1258 | } | | |||
1259 | 1219 | | |||
1260 | void Synchronizer::resume() | 1220 | void Synchronizer::resume() | ||
1261 | { | 1221 | { | ||
1262 | paused = false; | 1222 | paused = false; | ||
1263 | synchronizeLoop(); | 1223 | synchronizeLoop(); | ||
1264 | } | 1224 | } | ||
1265 | 1225 | | |||
1266 | QString Synchronizer::leftBaseDirectory() | 1226 | KgetProgressDialog::KgetProgressDialog(QWidget *parent, const QString &caption, const QString &text, | ||
1267 | { | 1227 | bool modal) | ||
1268 | return leftBaseDir; | 1228 | : QDialog(parent) | ||
1269 | } | | |||
1270 | | ||||
1271 | QString Synchronizer::rightBaseDirectory() | | |||
1272 | { | | |||
1273 | return rightBaseDir; | | |||
1274 | } | | |||
1275 | | ||||
1276 | KgetProgressDialog::KgetProgressDialog(QWidget *parent, const QString &caption, | | |||
1277 | const QString &text, bool modal) : QDialog(parent) | | |||
1278 | { | 1229 | { | ||
1279 | if (caption.isEmpty()) | 1230 | if (caption.isEmpty()) | ||
1280 | setWindowTitle(caption); | 1231 | setWindowTitle(caption); | ||
1281 | setModal(modal); | 1232 | setModal(modal); | ||
1282 | 1233 | | |||
1283 | QVBoxLayout *mainLayout = new QVBoxLayout; | 1234 | QVBoxLayout *mainLayout = new QVBoxLayout; | ||
1284 | setLayout(mainLayout); | 1235 | setLayout(mainLayout); | ||
1285 | 1236 | | |||
Show All 24 Lines | |||||
1310 | } | 1261 | } | ||
1311 | 1262 | | |||
1312 | void KgetProgressDialog::slotCancel() | 1263 | void KgetProgressDialog::slotCancel() | ||
1313 | { | 1264 | { | ||
1314 | mCancelled = true; | 1265 | mCancelled = true; | ||
1315 | reject(); | 1266 | reject(); | ||
1316 | } | 1267 | } | ||
1317 | 1268 | | |||
1318 | | ||||
1319 | void Synchronizer::synchronizeWithKGet() | 1269 | void Synchronizer::synchronizeWithKGet() | ||
1320 | { | 1270 | { | ||
1321 | bool isLeftLocal = QUrl::fromUserInput(leftBaseDirectory(), QString(), QUrl::AssumeLocalFile).isLocalFile(); | 1271 | const bool isLeftLocal = leftBaseDirectory().isLocalFile(); | ||
1272 | | ||||
1273 | if (isLeftLocal == rightBaseDirectory().isLocalFile()) { | ||||
1274 | qDebug() << "one side must be local, the other remote"; | ||||
1275 | return; | ||||
1276 | } | ||||
1277 | | ||||
1322 | KgetProgressDialog *progDlg = 0; | 1278 | KgetProgressDialog *progDlg = 0; | ||
1323 | int processedCount = 0, totalCount = 0; | 1279 | int processedCount = 0, totalCount = 0; | ||
1324 | 1280 | | |||
1325 | QListIterator<SynchronizerFileItem *> it(resultList); | 1281 | QListIterator<SynchronizerFileItem *> it(resultList); | ||
1326 | while (it.hasNext()) | 1282 | while (it.hasNext()) | ||
1327 | if (it.next()->isMarked()) | 1283 | if (it.next()->isMarked()) | ||
1328 | totalCount++; | 1284 | totalCount++; | ||
1329 | 1285 | | |||
1330 | it.toFront(); | 1286 | it.toFront(); | ||
1331 | while (it.hasNext()) { | 1287 | while (it.hasNext()) { | ||
1332 | SynchronizerFileItem * item = it.next(); | 1288 | SynchronizerFileItem *item = it.next(); | ||
1333 | 1289 | | |||
1334 | if (item->isMarked()) { | 1290 | if (item->isMarked()) { | ||
1335 | QUrl downloadURL; | 1291 | QUrl downloadURL; | ||
1336 | QUrl destURL; | 1292 | QUrl destURL; | ||
1337 | QString destDir; | 1293 | QUrl destDir; | ||
1338 | QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + '/'; | | |||
1339 | QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + '/'; | | |||
1340 | 1294 | | |||
1341 | if (progDlg == 0) { | 1295 | if (progDlg == 0) { | ||
1342 | progDlg = new KgetProgressDialog(krMainWindow, i18n("Krusader::Synchronizer"), | 1296 | progDlg = new KgetProgressDialog(krMainWindow, i18n("Krusader::Synchronizer"), | ||
1343 | i18n("Feeding the URLs to KGet"), true); | 1297 | i18n("Feeding the URLs to KGet"), true); | ||
1344 | progDlg->progressBar()->setMaximum(totalCount); | 1298 | progDlg->progressBar()->setMaximum(totalCount); | ||
1345 | progDlg->show(); | 1299 | progDlg->show(); | ||
1346 | qApp->processEvents(); | 1300 | qApp->processEvents(); | ||
1347 | } | 1301 | } | ||
1348 | 1302 | | |||
1349 | if (item->task() == TT_COPY_TO_RIGHT && !isLeftLocal) { | 1303 | if (item->task() == TT_COPY_TO_RIGHT && !isLeftLocal) { | ||
1350 | downloadURL = Synchronizer::fsUrl(leftBaseDirectory() + leftDirName + item->leftName()); | 1304 | downloadURL = pathAppend(leftBaseDirectory(), item->leftDirectory(), item->leftName()); | ||
1351 | destDir = rightBaseDirectory() + rightDirName; | 1305 | destDir = pathAppend(rightBaseDirectory(), item->rightDirectory()); | ||
1352 | destURL = Synchronizer::fsUrl(destDir + item->rightName()); | 1306 | destURL = pathAppend(destDir, item->rightName()); | ||
1353 | 1307 | | |||
1354 | if (item->isDir()) | 1308 | if (item->isDir()) | ||
1355 | destDir += item->leftName(); | 1309 | destDir = pathAppend(destDir, item->leftName()); | ||
1356 | } | 1310 | } | ||
1357 | if (item->task() == TT_COPY_TO_LEFT && isLeftLocal) { | 1311 | else if (item->task() == TT_COPY_TO_LEFT && isLeftLocal) { | ||
1358 | downloadURL = Synchronizer::fsUrl(rightBaseDirectory() + rightDirName + item->rightName()); | 1312 | downloadURL = pathAppend(rightBaseDirectory(), item->rightDirectory(), item->rightName()); | ||
1359 | destDir = leftBaseDirectory() + leftDirName; | 1313 | destDir = pathAppend(leftBaseDirectory(), item->leftDirectory()); | ||
1360 | destURL = Synchronizer::fsUrl(destDir + item->leftName()); | 1314 | destURL = pathAppend(destDir, item->leftName()); | ||
1361 | 1315 | | |||
1362 | if (item->isDir()) | 1316 | if (item->isDir()) | ||
1363 | destDir += item->rightName(); | 1317 | destDir = pathAppend(destDir, item->rightName()); | ||
1318 | } else { | ||||
1319 | qDebug() << "KGet can only download from remote to local"; | ||||
1320 | continue; | ||||
1364 | } | 1321 | } | ||
1365 | 1322 | | |||
1323 | const QString destLocalDir = destDir.toLocalFile(); | ||||
1324 | | ||||
1366 | // creating the directory system | 1325 | // creating the directory system | ||
1367 | for (int i = 0; i >= 0 ; i = destDir.indexOf('/', i + 1)) | 1326 | for (int i = 0; i >= 0; i = destLocalDir.indexOf('/', i + 1)) { | ||
1368 | if (!QDir(destDir.left(i)).exists()) | 1327 | if (!QDir(destLocalDir.left(i)).exists()) | ||
1369 | QDir().mkdir(destDir.left(i)); | 1328 | QDir().mkdir(destLocalDir.left(i)); | ||
1329 | } | ||||
1370 | 1330 | | |||
1371 | if (!item->isDir() && !downloadURL.isEmpty()) { | 1331 | if (!item->isDir() && !downloadURL.isEmpty()) { | ||
1372 | if (QFile(destURL.path()).exists()) | 1332 | // ovewrite destination | ||
1333 | if (QFile(destURL.path()).exists()) { | ||||
1373 | QFile(destURL.path()).remove(); | 1334 | QFile(destURL.path()).remove(); | ||
1335 | } | ||||
1374 | 1336 | | |||
1375 | QString source = downloadURL.toDisplayString(); | 1337 | QString source = downloadURL.toDisplayString(); | ||
1376 | if (source.indexOf('@') >= 2) { /* is this an ftp proxy URL? */ | 1338 | if (source.indexOf('@') >= 2) { /* is this an ftp proxy URL? */ | ||
1377 | int lastAt = source.lastIndexOf('@'); | 1339 | const int lastAt = source.lastIndexOf('@'); | ||
1378 | QString startString = source.left(lastAt); | 1340 | QString startString = source.left(lastAt); | ||
1379 | QString endString = source.mid(lastAt); | | |||
1380 | startString.replace('@', "%40"); | 1341 | startString.replace('@', "%40"); | ||
1342 | const QString endString = source.mid(lastAt); | ||||
1381 | source = startString + endString; | 1343 | source = startString + endString; | ||
1382 | } | 1344 | } | ||
1383 | 1345 | | |||
1384 | KProcess p; | 1346 | KProcess p; | ||
1385 | 1347 | | |||
1386 | p << KrServices::fullPathName("kget") << source << destURL.path(); | 1348 | const QString kgetPath = KrServices::fullPathName("kget"); | ||
1387 | if (!p.startDetached()) | 1349 | p << kgetPath << source << destURL.path(); | ||
1388 | KMessageBox::error(parentWidget, i18n("Error executing %1.", KrServices::fullPathName("kget"))); | 1350 | | ||
1351 | if (!p.startDetached()) { | ||||
1352 | KMessageBox::error(parentWidget, i18n("Error executing %1.", kgetPath)); | ||||
1353 | } | ||||
1389 | } | 1354 | } | ||
1390 | 1355 | | |||
1391 | progDlg->progressBar()->setValue(++processedCount); | 1356 | progDlg->progressBar()->setValue(++processedCount); | ||
1392 | 1357 | | |||
1393 | QTime t; | 1358 | QTime t; | ||
1394 | t.start(); | 1359 | t.start(); | ||
1395 | bool canExit = false; | 1360 | bool canExit = false; | ||
1396 | 1361 | | |||
1397 | do { | 1362 | do { | ||
1398 | qApp->processEvents(); | 1363 | qApp->processEvents(); | ||
1399 | 1364 | | |||
1400 | if (progDlg->wasCancelled()) | 1365 | if (progDlg->wasCancelled()) | ||
1401 | break; | 1366 | break; | ||
1402 | 1367 | | |||
1403 | canExit = (t.elapsed() > 100); | 1368 | canExit = (t.elapsed() > 100); | ||
1404 | 1369 | | |||
1405 | if (progDlg->isPaused() || !canExit) | 1370 | if (progDlg->isPaused() || !canExit) | ||
1406 | usleep(10000); | 1371 | usleep(10 * 1000); // wait 10 seconds for some reason | ||
1407 | 1372 | | |||
1408 | } while (progDlg->isPaused() || !canExit); | 1373 | } while (progDlg->isPaused() || !canExit); | ||
1409 | 1374 | | |||
1410 | if (progDlg->wasCancelled()) | 1375 | if (progDlg->wasCancelled()) | ||
1411 | break; | 1376 | break; | ||
1412 | } | 1377 | } | ||
1413 | } | 1378 | } | ||
1414 | 1379 | | |||
1415 | if (progDlg) | 1380 | if (progDlg) | ||
1416 | delete progDlg; | 1381 | delete progDlg; | ||
1417 | } | 1382 | } | ||
1418 | 1383 | | |||
1419 | bool Synchronizer::isDir(const FileItem *file) | 1384 | bool Synchronizer::isDir(const FileItem *file) | ||
1420 | { | 1385 | { | ||
1421 | if (followSymLinks) { | 1386 | return file->isDir() && (followSymLinks || !file->isSymLink()); | ||
1422 | return file->isDir(); | | |||
1423 | } else { | | |||
1424 | return file->isDir() && !file->isSymLink(); | | |||
1425 | } | | |||
1426 | } | | |||
1427 | | ||||
1428 | QString Synchronizer::readLink(const FileItem *file) | | |||
1429 | { | | |||
1430 | if (file->isSymLink()) | | |||
1431 | return file->getSymDest(); | | |||
1432 | else | | |||
1433 | return QString(); | | |||
1434 | } | 1387 | } | ||
1435 | 1388 | | |||
1436 | SynchronizerFileItem *Synchronizer::getItemAt(unsigned ndx) | 1389 | SynchronizerFileItem *Synchronizer::getItemAt(unsigned ndx) | ||
1437 | { | 1390 | { | ||
1438 | if (ndx < (unsigned)resultList.count()) | 1391 | if (ndx < (unsigned)resultList.count()) | ||
1439 | return resultList.at(ndx); | 1392 | return resultList.at(ndx); | ||
1440 | else | 1393 | else | ||
1441 | return 0; | 1394 | return 0; | ||
1442 | } | 1395 | } | ||
1443 | |