Engine::Engine(QObject *parent) : QObject(parent), m_clipboardContainsCopy(false), m_progress(0) { m_fileWorker = new FileWorker; // update progress property when worker progresses connect(m_fileWorker, SIGNAL(progressChanged(int, QString)), this, SLOT(setProgress(int, QString))); // pass worker end signals to QML connect(m_fileWorker, SIGNAL(done()), this, SIGNAL(workerDone())); connect(m_fileWorker, SIGNAL(errorOccurred(QString, QString)), this, SIGNAL(workerErrorOccurred(QString, QString))); connect(m_fileWorker, SIGNAL(fileDeleted(QString)), this, SIGNAL(fileDeleted(QString))); }
/** * Creates a new instance of watcher thread. The watcher is not started but keeps the references * to the directory to be watched, and the associated filter. The lastPass member is used to * detect modification/creation of files between two passes. */ Watcher::Watcher(QString url, bool recursive, Filter *filterP) : QThread(), m_watchSem(1) { m_url = url; m_recursive = recursive; m_filterP = filterP; m_lastPass = QDateTime::currentDateTime(); // connect the activity signals/slots connect(this, SIGNAL(displayActivity(QString)), filterP, SIGNAL(displayActivity(QString))); connect(this, SIGNAL(displayProgress(int,int,int)), filterP, SIGNAL(displayProgress(int,int,int))); // connect the scan results signals/slots connect(this, SIGNAL(fileAdded(QString)), filterP, SLOT(fileAdded(QString))); connect(this, SIGNAL(fileDeleted(QString)), filterP, SLOT(fileDeleted(QString))); connect(this, SIGNAL(fileModified(QString)), filterP, SLOT(fileModified(QString))); connect(this, SIGNAL(directoryAdded(QString)), filterP, SLOT(directoryAdded(QString))); connect(this, SIGNAL(directoryDeleted(QString)), filterP, SLOT(directoryDeleted(QString))); connect(this, SIGNAL(directoryModified(QString)), filterP, SLOT(directoryModified(QString))); }
////////////////////////////////////////////////////////////////////////// /// Add a FileSystemWatcher to the directory /// /// Creates a FileSystemWatcher, connects all the signals, adds it to the /// list of watchers and starts it. ////////////////////////////////////////////////////////////////////////// void SyncSystem::slotStartNodeWatching(const QString& dir) { QString watchDir = joinPath(m_CurrentSourcePath, dir); qDebug() << "[SyncSystem.Debug] slotStartNodeWatching in dir " << watchDir; FileSystemWatcher* watcher = new FileSystemWatcher(); connect(watcher, SIGNAL(fileAdded(QString)), SLOT(slotFileAdded(QString))); connect(watcher, SIGNAL(fileDeleted(QString)), SLOT(slotFileDeleted(QString))); connect(watcher, SIGNAL(fileChanged(QString)), SLOT(slotFileChanged(QString))); connect(watcher, SIGNAL(fileRenamed(QString,QString)), SLOT(slotFileRenamed(QString,QString))); connect(watcher, SIGNAL(filewatchError(QString)), SLOT(slotFilewatchError(QString))); connect(watcher, SIGNAL(filewatchLostSync(QString)), SLOT(slotLostSync())); m_FileSystemWatchers.append(watcher); watcher->setWatchDir(watchDir); watcher->setRelativeDir(dir); watcher->start(); }
void Utils::deleteFinished() { //qDebug() << "Utils::deleteFinished"; int httpStatus = temp_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); QString httpStatusMessage = temp_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); QByteArray bytes = temp_reply->readAll(); //qDebug() << "status: " << httpStatus << " " << httpStatusMessage; //qDebug() << "bytes: " << bytes; if (temp_reply->error() == QNetworkReply::NoError) { emit fileDeleted(); } else { emit operationError(httpStatus); } temp_reply->close(); temp_reply->deleteLater(); }
void FileWatcher::checkFiles() { m_stateFlags |= AddRemoveBlocked; m_stateFlags |= FileCheckRunning; m_watchTimer->stop(); m_stateFlags |= TimerStopped; QDateTime time; QStringList toRemove; QMap<QString, fileMod>::Iterator it; // qDebug()<<files(); for ( it = m_watchedFiles.begin(); !(m_stateFlags & FileCheckMustStop) && it != m_watchedFiles.end(); ++it ) { it.value().info.refresh(); if (!it.value().info.exists()) { if (m_stateFlags & FileCheckMustStop) break; if (!it.value().pending) { if (it.value().fast) { if (it.value().isDir) emit dirDeleted(it.key()); else emit fileDeleted(it.key()); if (m_stateFlags & FileCheckMustStop) break; it.value().refCount--; if (it.value().refCount == 0) toRemove.append(it.key()); continue; } it.value().pendingCount = 5; it.value().pending = true; emit statePending(it.key()); continue; } if (it.value().pendingCount != 0) { it.value().pendingCount--; continue; } it.value().pending = false; if (it.value().isDir) emit dirDeleted(it.key()); else emit fileDeleted(it.key()); if (m_stateFlags & FileCheckMustStop) break; it.value().refCount--; if (it.value().refCount == 0) toRemove.append(it.key()); continue; } //qDebug()<<it.key(); it.value().pending = false; time = it.value().info.lastModified(); if (time != it.value().timeInfo) { // qDebug()<<"Times different: last modified:"<<time<<"\t recorded time:"<<it.value().timeInfo; if (it.value().isDir) { // qDebug()<<"dir, ignoring"<<it.key(); it.value().timeInfo = time; if (!(m_stateFlags & FileCheckMustStop)) emit dirChanged(it.key()); } else { qint64 sizeo = it.value().info.size(); std::this_thread::sleep_for(std::chrono::milliseconds(1)); it.value().info.refresh(); qint64 sizen = it.value().info.size(); // qDebug()<<"Size comparison"<<sizeo<<sizen<<it.key(); while (sizen != sizeo) { sizeo = sizen; std::this_thread::sleep_for(std::chrono::milliseconds(1)); it.value().info.refresh(); sizen = it.value().info.size(); } it.value().timeInfo = time; if (m_stateFlags & FileCheckMustStop) break; emit fileChanged(it.key()); } } } if (m_stateFlags & Dying) m_watchedFiles.clear(); else { for (int i=0; i<toRemove.count(); ++i) m_watchedFiles.remove(toRemove[i]); m_stateFlags &= ~AddRemoveBlocked; m_stateFlags &= ~TimerStopped; m_watchTimer->start(m_timeOut); } m_stateFlags &= ~FileCheckRunning; }
/** * This is the watcher thread main stuff. It iterates on watching its 'known' directories and * notifying the associated filter with the directories/files changes. */ void Watcher::run() { QTime passStart; int numEntries = 0; const QList<PathSegment *> *pathsP = NULL; // do nothing if no root url set if (m_url.isEmpty()) return; m_stop = false; m_numWatchedFiles = 0; // we'll start by scanning this one m_files.addPath(m_url, true); do { passStart.restart(); #ifdef _VERBOSE_WATCHER qDebug() << "(File)Watcher does a pass at " << passStart; #endif // now, don't let the filter play concurrently if (!tryAcquireWatchSemaphore()) goto nextPass; // check for new or modified files/directories pathsP = m_files.getPaths(true); numEntries = pathsP->count(); for (int i = 0; !m_stop && i < numEntries; i++) { QString filepath = pathsP->at(i)->getPath(); // show progress displayActivity(tr("Scanning directory %1").arg(filepath)); displayProgress(0, numEntries - 1, i); watchDirectory(filepath); } // add the new files and directories to the watch lists #ifdef _VERBOSE_PATH m_files.dump("dumping watched files before merging"); m_newFiles.dump("dumping new files before merging"); #endif m_files.merge(&m_newFiles); m_newFiles.deleteAll(); #ifdef _VERBOSE_PATH m_files.dump("dumping watched files after merging"); m_newFiles.dump("dumping new files after merging"); #endif // now check if any of the watched files have disappeared // check removed directories for (QList<PathSegment *>::const_iterator i = m_files.getPaths(true)->begin(); i != m_files.getPaths(true)->end(); i++) { QString filepath = (*i)->getPath(); QFileInfoExt entryInfo(filepath); if (!entryInfo.exists()) { // we DO NOT need to check the content and signal for everything... // because the content will be checked later on... #ifdef _VERBOSE_WATCHER qDebug() << "Detected deleted directory " << filepath; #endif directoryDeleted(filepath); m_removedFiles.addPath(filepath, true); } } // check removed files for (QList<PathSegment *>::const_iterator i = m_files.getPaths()->begin(); !m_stop && i != m_files.getPaths()->end(); i++) { QString filepath = (*i)->getPath(); QFileInfoExt entryInfo(filepath); if (!entryInfo.exists()) { #ifdef _VERBOSE_WATCHER qDebug() << "Detected deleted file " << filepath; #endif // fileDeleted(filepath); fileDeleted(entryInfo.absoluteFilePath()); m_removedFiles.addPath(filepath); --m_numWatchedFiles; } } // and remove // directories for (QList<PathSegment *>::const_iterator i = m_removedFiles.getPaths(true)->begin(); i != m_removedFiles.getPaths(true)->end(); i++) m_files.deletePath((*i)->getPath(), true); // files for (QList<PathSegment *>::const_iterator i = m_removedFiles.getPaths()->begin(); !m_stop && i != m_removedFiles.getPaths()->end(); i++) m_files.deletePath((*i)->getPath()); m_removedFiles.deleteAll(); // keep last pass time m_lastPass = QDateTime::currentDateTime(); // now, the filter can play releaseWatchSemaphore(); nextPass: #ifdef _VERBOSE_WATCHER qDebug() << "(File)Watcher ends pass at " << m_lastPass << " (duration: " << passStart.elapsed() << " ms)"; #endif QString duration; duration.sprintf("%d", passStart.elapsed()); displayActivity(tr("Scanning pass completed in (%1) milliseconds. Now sleeping.").arg(duration)); displayProgress(1, 100, 100); // a little break if (!m_stop) msleep(WATCH_PASS_INTERVAL); } while (!m_stop); #ifdef _VERBOSE_WATCHER qDebug() << "(File)Watcher now EXITING!"; #endif }
void FileWatcher::checkFiles() { m_stateFlags |= AddRemoveBlocked; m_stateFlags |= FileCheckRunning; watchTimer->stop(); m_stateFlags |= TimerStopped; QDateTime time; QStringList toRemove; QMap<QString, fileMod>::Iterator it; for ( it = watchedFiles.begin(); !(m_stateFlags & FileCheckMustStop) && it != watchedFiles.end(); ++it ) { it.value().info.refresh(); if (!it.value().info.exists()) { if (m_stateFlags & FileCheckMustStop) break; if (!it.value().pending) { if (it.value().fast) { if (it.value().isDir) emit dirDeleted(it.key()); else emit fileDeleted(it.key()); if (m_stateFlags & FileCheckMustStop) break; it.value().refCount--; if (it.value().refCount == 0) toRemove.append(it.key()); continue; } else { it.value().pendingCount = 5; it.value().pending = true; emit statePending(it.key()); continue; } } else { if (it.value().pendingCount != 0) { it.value().pendingCount--; continue; } else { it.value().pending = false; if (it.value().isDir) emit dirDeleted(it.key()); else emit fileDeleted(it.key()); if (m_stateFlags & FileCheckMustStop) break; it.value().refCount--; if (it.value().refCount == 0) toRemove.append(it.key()); continue; } } } else { it.value().pending = false; time = it.value().info.lastModified(); if (time != it.value().timeInfo) { if (it.value().isDir) { it.value().timeInfo = time; if (!(m_stateFlags & FileCheckMustStop)) emit dirChanged(it.key()); } else { uint sizeo = it.value().info.size(); usleep(100); it.value().info.refresh(); uint sizen = it.value().info.size(); while (sizen != sizeo) { sizeo = sizen; usleep(100); it.value().info.refresh(); sizen = it.value().info.size(); } it.value().timeInfo = time; if (m_stateFlags & FileCheckMustStop) break; emit fileChanged(it.key()); } } } } if (m_stateFlags & Dying) watchedFiles.clear(); else { for( int i=0; i<toRemove.count(); ++i) watchedFiles.remove(toRemove[i]); m_stateFlags &= ~AddRemoveBlocked; m_stateFlags &= ~TimerStopped; watchTimer->start(m_timeOut); } m_stateFlags &= ~FileCheckRunning; }