Here is the original code I had in the slot
void FileDatabase::taskFinished(WorkerTask* worktask)
{
switch (worktask->id())
{
...
case DBTASK_DELETE:
{
// Double Check for accidental fallthroughs
if (worktask->id() != DBTASK_DELETE) break;
if (d
->deleteConfirmation
== QMessageBox::Cancel) break;
FileModifiedTask* task = static_cast<FileModifiedTask*>(worktask);
FileNode* fn = task->file();
if (task->isModified()) {
Log(LOG_WARN) << tr("File has been modified; won't delete (%1)")
.arg(fileRelativePath(fn)) << Log::ENDL;
break;
}
{
app, tr("File About to be Deleted"),
tr("Are you sure you want to delete %1 file '%2' ?\n\n"
"WARNING: File will be removed from filesystem and it "
"can't be restored!\n")
.arg(FileAttributeString(fn), fileRelativePath(fn)),
}
if (d->deleteConfirmation&
{
if (file.remove())
removeFile(fn);
else {
Log(LOG_ERROR) <<
tr("Can't delete file (%1)")
.arg(fileRelativePath(fn)) << Log::ENDL;
}
}
}
break;
}
delete worktask;
}
void FileDatabase::taskFinished(WorkerTask* worktask)
{
switch (worktask->id())
{
...
case DBTASK_DELETE:
{
// Double Check for accidental fallthroughs
if (worktask->id() != DBTASK_DELETE) break;
if (d->deleteConfirmation == QMessageBox::Cancel) break;
FileModifiedTask* task = static_cast<FileModifiedTask*>(worktask);
FileNode* fn = task->file();
if (task->isModified()) {
Log(LOG_WARN) << tr("File has been modified; won't delete (%1)")
.arg(fileRelativePath(fn)) << Log::ENDL;
break;
}
if (d->deleteConfirmation != QMessageBox::YesToAll)
{
d->deleteConfirmation = QMessageBox::question(
app, tr("File About to be Deleted"),
tr("Are you sure you want to delete %1 file '%2' ?\n\n"
"WARNING: File will be removed from filesystem and it "
"can't be restored!\n")
.arg(FileAttributeString(fn), fileRelativePath(fn)),
QMessageBox::Yes|QMessageBox::No|
QMessageBox::YesToAll|QMessageBox::Cancel,
QMessageBox::No);
}
if (d->deleteConfirmation&
(QMessageBox::Yes|QMessageBox::YesAll))
{
QFile file(fn->path());
if (file.remove())
removeFile(fn);
else {
Log(LOG_ERROR) <<
tr("Can't delete file (%1)")
.arg(fileRelativePath(fn)) << Log::ENDL;
}
}
}
break;
}
delete worktask;
}
To copy to clipboard, switch view to plain text mode
Worker thread computes hash of file content and the result is stored in FileModifiedTask and then emitted to the slot. In the slot I check if the file has been modified and confirm the file delete, unless it's been canceled or YesToAlled.
So I thought about your suggestion to use mutex. In this case wouldn't simple bool variable be enough? I would assume this happens in single thread ? But then the problem becomes what to do with those tasks that can't get the lock ?
So I thought it a bit more and then realised I need to store those finished tasks and process them later
QObject::connect(taskTimer,
SIGNAL(timeout
()),
db, SLOT(processQueuedTasks()));
void FileDatabase::taskFinished(WorkerTask* task)
{
d->taskQueue.enqueue(task);
if (!(d->taskTimer->isActive() || d->processingTasks))
d->taskTimer->start();
}
void FileDatabase::processQueuedTasks()
{
d->processingTasks = true;
time.start();
int n = d->taskQueue.size();
while (d->taskQueue.size() && time.elapsed() < 10) {
processTask(d->taskQueue.dequeue()); // same code as in original taskFinished(..)
}
emit progressAdvanced(n - d->taskQueue.size());
if (d->taskQueue.size())
d->taskTimer->start();
if (d->batchFinished && d->taskQueue.isEmpty())
unlock();
d->processingTasks = false;
}
QObject::connect(taskTimer, SIGNAL(timeout()),
db, SLOT(processQueuedTasks()));
void FileDatabase::taskFinished(WorkerTask* task)
{
d->taskQueue.enqueue(task);
if (!(d->taskTimer->isActive() || d->processingTasks))
d->taskTimer->start();
}
void FileDatabase::processQueuedTasks()
{
d->processingTasks = true;
QTime time;
time.start();
int n = d->taskQueue.size();
while (d->taskQueue.size() && time.elapsed() < 10) {
processTask(d->taskQueue.dequeue()); // same code as in original taskFinished(..)
}
emit progressAdvanced(n - d->taskQueue.size());
if (d->taskQueue.size())
d->taskTimer->start();
if (d->batchFinished && d->taskQueue.isEmpty())
unlock();
d->processingTasks = false;
}
To copy to clipboard, switch view to plain text mode
Not very pretty but but at least it seems to work...
Btw am I correct when I think that each time QMessageBox::question() is called a new EventLoop is pushed on stack that now handles the gui events and all the other event that the previous "main" EventLoop did ? That in a sense there are then multiple EventLoops on stack, but only top one is "active"? I hope I'm not too off the mark here
Bookmarks