You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
363 lines
13 KiB
363 lines
13 KiB
/* ============================================================
|
|
*
|
|
* This file is a part of digiKam project
|
|
* http://www.digikam.org
|
|
*
|
|
* Date : 2006-01-20
|
|
* Description : image file IO threaded interface.
|
|
*
|
|
* Copyright (C) 2005-2007 by Marcel Wiesweg <marcel.wiesweg@gmx.de>
|
|
* Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
|
|
*
|
|
* This program is free software; you can redistribute it
|
|
* and/or modify it under the terms of the GNU General
|
|
* Public License as published by the Free Software Foundation;
|
|
* either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* ============================================================ */
|
|
|
|
// Local includes.
|
|
|
|
#include "ddebug.h"
|
|
#include "managedloadsavethread.h"
|
|
#include "loadsavetask.h"
|
|
#include "previewtask.h"
|
|
|
|
namespace Digikam
|
|
{
|
|
|
|
ManagedLoadSaveThread::ManagedLoadSaveThread()
|
|
{
|
|
m_terminationPolicy = TerminationPolicyTerminateLoading;
|
|
}
|
|
|
|
ManagedLoadSaveThread::~ManagedLoadSaveThread()
|
|
{
|
|
LoadingTask *loadingTask;
|
|
switch (m_terminationPolicy)
|
|
{
|
|
case TerminationPolicyTerminateLoading:
|
|
{
|
|
TQMutexLocker lock(&m_mutex);
|
|
if ( (loadingTask = checkLoadingTask(m_currentTask, LoadingTaskFilterAll)) )
|
|
loadingTask->setStatus(LoadingTask::LoadingTaskStatusStopping);
|
|
removeLoadingTasks(LoadingDescription(TQString()), LoadingTaskFilterAll);
|
|
break;
|
|
}
|
|
case TerminationPolicyTerminatePreloading:
|
|
{
|
|
TQMutexLocker lock(&m_mutex);
|
|
if ( (loadingTask = checkLoadingTask(m_currentTask, LoadingTaskFilterPreloading)) )
|
|
loadingTask->setStatus(LoadingTask::LoadingTaskStatusStopping);
|
|
removeLoadingTasks(LoadingDescription(TQString()), LoadingTaskFilterPreloading);
|
|
break;
|
|
}
|
|
case TerminationPolicyWait:
|
|
break;
|
|
}
|
|
}
|
|
|
|
LoadingTask *ManagedLoadSaveThread::checkLoadingTask(LoadSaveTask *task, LoadingTaskFilter filter)
|
|
{
|
|
if (task && task->type() == LoadSaveTask::TaskTypeLoading)
|
|
{
|
|
LoadingTask *loadingTask = (LoadingTask *)task;
|
|
if (filter == LoadingTaskFilterAll)
|
|
return loadingTask;
|
|
else if (filter == LoadingTaskFilterPreloading)
|
|
if (loadingTask->status() == LoadingTask::LoadingTaskStatusPreloading)
|
|
return loadingTask;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
LoadingTask *ManagedLoadSaveThread::findExistingTask(const LoadingDescription &loadingDescription)
|
|
{
|
|
LoadingTask *loadingTask;
|
|
if (m_currentTask)
|
|
{
|
|
if (m_currentTask->type() == LoadSaveTask::TaskTypeLoading)
|
|
{
|
|
loadingTask = (LoadingTask *)m_currentTask;
|
|
LoadingDescription taskDescription = loadingTask->loadingDescription();
|
|
if (taskDescription == loadingDescription)
|
|
return loadingTask;
|
|
}
|
|
}
|
|
for (LoadSaveTask *task = m_todo.first(); task; task = m_todo.next())
|
|
{
|
|
if (task->type() == LoadSaveTask::TaskTypeLoading)
|
|
{
|
|
loadingTask = (LoadingTask *)task;
|
|
if (loadingTask->loadingDescription() == loadingDescription)
|
|
return loadingTask;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void ManagedLoadSaveThread::setTerminationPolicy(TerminationPolicy terminationPolicy)
|
|
{
|
|
m_terminationPolicy = terminationPolicy;
|
|
}
|
|
|
|
void ManagedLoadSaveThread::load(LoadingDescription description, LoadingPolicy policy)
|
|
{
|
|
load(description, LoadingModeNormal, policy);
|
|
}
|
|
|
|
void ManagedLoadSaveThread::load(LoadingDescription description, LoadingMode loadingMode, LoadingPolicy policy, AccessMode accessMode)
|
|
{
|
|
TQMutexLocker lock(&m_mutex);
|
|
LoadingTask *loadingTask = 0;
|
|
LoadingTask *existingTask = findExistingTask(description);
|
|
|
|
//DDebug() << "ManagedLoadSaveThread::load " << description.filePath << ", policy " << policy << endl;
|
|
switch(policy)
|
|
{
|
|
case LoadingPolicyFirstRemovePrevious:
|
|
// reuse task if it exists
|
|
if (existingTask)
|
|
{
|
|
existingTask->setStatus(LoadingTask::LoadingTaskStatusLoading);
|
|
}
|
|
// stop current task
|
|
if (m_currentTask && m_currentTask != existingTask)
|
|
{
|
|
if ( (loadingTask = checkLoadingTask(m_currentTask, LoadingTaskFilterAll)) )
|
|
loadingTask->setStatus(LoadingTask::LoadingTaskStatusStopping);
|
|
}
|
|
//DDebug() << "LoadingPolicyFirstRemovePrevious, Existing task " << existingTask <<
|
|
//", m_currentTask " << m_currentTask << ", loadingTask " << loadingTask << endl;
|
|
// remove all loading tasks
|
|
for (LoadSaveTask *task = m_todo.first(); task; task = m_todo.next())
|
|
{
|
|
if (task != existingTask && checkLoadingTask(task, LoadingTaskFilterAll))
|
|
{
|
|
//DDebug() << "Removing task " << task << " from list" << endl;
|
|
m_todo.remove();
|
|
m_todo.prev();
|
|
}
|
|
}
|
|
// append new, exclusive loading task
|
|
if (existingTask)
|
|
break;
|
|
m_todo.append(createLoadingTask(description, false, loadingMode, accessMode));
|
|
break;
|
|
case LoadingPolicyPrepend:
|
|
if (existingTask)
|
|
{
|
|
existingTask->setStatus(LoadingTask::LoadingTaskStatusLoading);
|
|
}
|
|
// stop and postpone current task if it is a preloading task
|
|
if (m_currentTask)
|
|
{
|
|
if ( (loadingTask = checkLoadingTask(m_currentTask, LoadingTaskFilterPreloading)) )
|
|
{
|
|
loadingTask->setStatus(LoadingTask::LoadingTaskStatusStopping);
|
|
load(loadingTask->filePath(), LoadingPolicyPreload);
|
|
}
|
|
}
|
|
//DDebug() << "LoadingPolicyPrepend, Existing task " << existingTask << ", m_currentTask " << m_currentTask << endl;
|
|
// prepend new loading task
|
|
if (existingTask)
|
|
break;
|
|
m_todo.prepend(createLoadingTask(description, false, loadingMode, accessMode));
|
|
break;
|
|
case LoadingPolicyAppend:
|
|
if (existingTask)
|
|
{
|
|
existingTask->setStatus(LoadingTask::LoadingTaskStatusLoading);
|
|
}
|
|
// stop and postpone current task if it is a preloading task
|
|
if (m_currentTask)
|
|
{
|
|
if ( (loadingTask = checkLoadingTask(m_currentTask, LoadingTaskFilterPreloading)) )
|
|
{
|
|
loadingTask->setStatus(LoadingTask::LoadingTaskStatusStopping);
|
|
load(loadingTask->filePath(), LoadingPolicyPreload);
|
|
}
|
|
}
|
|
if (existingTask)
|
|
break;
|
|
//DDebug() << "LoadingPolicyAppend, Existing task " << existingTask << ", m_currentTask " << m_currentTask << endl;
|
|
// append new loading task, put it in front of preloading tasks
|
|
for (uint i = 0; i<m_todo.count(); i++)
|
|
{
|
|
LoadSaveTask *task = m_todo.at(i);
|
|
if ( (loadingTask = checkLoadingTask(task, LoadingTaskFilterPreloading)) )
|
|
{
|
|
m_todo.insert(i, createLoadingTask(description, false, loadingMode, accessMode));
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case LoadingPolicyPreload:
|
|
// append to the very end of the list
|
|
//DDebug() << "LoadingPolicyPreload, Existing task " << existingTask << endl;
|
|
if (existingTask)
|
|
break;
|
|
m_todo.append(createLoadingTask(description, true, loadingMode, accessMode));
|
|
break;
|
|
}
|
|
m_condVar.wakeAll();
|
|
}
|
|
|
|
void ManagedLoadSaveThread::loadPreview(LoadingDescription description)
|
|
{
|
|
// This is similar to the LoadingPolicyFirstRemovePrevious policy with normal loading tasks.
|
|
// Preview threads typically only support preview tasks,
|
|
// so no need to differentiate with normal loading tasks.
|
|
|
|
TQMutexLocker lock(&m_mutex);
|
|
LoadingTask *loadingTask = 0;
|
|
LoadingTask *existingTask = findExistingTask(description);
|
|
|
|
// reuse task if it exists
|
|
if (existingTask)
|
|
{
|
|
existingTask->setStatus(LoadingTask::LoadingTaskStatusLoading);
|
|
}
|
|
// stop current task
|
|
if (m_currentTask && m_currentTask != existingTask)
|
|
{
|
|
if ( (loadingTask = checkLoadingTask(m_currentTask, LoadingTaskFilterAll)) )
|
|
loadingTask->setStatus(LoadingTask::LoadingTaskStatusStopping);
|
|
}
|
|
// remove all loading tasks
|
|
for (LoadSaveTask *task = m_todo.first(); task; task = m_todo.next())
|
|
{
|
|
if (task != existingTask && checkLoadingTask(task, LoadingTaskFilterAll))
|
|
{
|
|
m_todo.remove();
|
|
m_todo.prev();
|
|
}
|
|
}
|
|
//DDebug()<<"loadPreview for " << description.filePath << " existingTask " << existingTask << " currentTask " << m_currentTask << endl;
|
|
// append new loading task
|
|
if (existingTask)
|
|
return;
|
|
m_todo.append(new PreviewLoadingTask(this, description));
|
|
m_condVar.wakeAll();
|
|
}
|
|
|
|
|
|
LoadingTask *ManagedLoadSaveThread::createLoadingTask(const LoadingDescription &description,
|
|
bool preloading, LoadingMode loadingMode, AccessMode accessMode)
|
|
{
|
|
if (loadingMode == LoadingModeShared)
|
|
{
|
|
if (preloading)
|
|
return new SharedLoadingTask(this, description, accessMode, LoadingTask::LoadingTaskStatusPreloading);
|
|
else
|
|
return new SharedLoadingTask(this, description, accessMode);
|
|
}
|
|
else
|
|
{
|
|
if (preloading)
|
|
return new LoadingTask(this, description, LoadingTask::LoadingTaskStatusPreloading);
|
|
else
|
|
return new LoadingTask(this, description);
|
|
}
|
|
}
|
|
|
|
void ManagedLoadSaveThread::stopLoading(const TQString& filePath, LoadingTaskFilter filter)
|
|
{
|
|
TQMutexLocker lock(&m_mutex);
|
|
removeLoadingTasks(LoadingDescription(filePath), filter);
|
|
}
|
|
|
|
void ManagedLoadSaveThread::stopLoading(const LoadingDescription& desc, LoadingTaskFilter filter)
|
|
{
|
|
TQMutexLocker lock(&m_mutex);
|
|
removeLoadingTasks(desc, filter);
|
|
}
|
|
|
|
void ManagedLoadSaveThread::stopSaving(const TQString& filePath)
|
|
{
|
|
TQMutexLocker lock(&m_mutex);
|
|
|
|
// stop current task if it is matching the criteria
|
|
if (m_currentTask && m_currentTask->type() == LoadSaveTask::TaskTypeSaving)
|
|
{
|
|
SavingTask *savingTask = (SavingTask *)m_currentTask;
|
|
if (filePath.isNull() || savingTask->filePath() == filePath)
|
|
{
|
|
savingTask->setStatus(SavingTask::SavingTaskStatusStopping);
|
|
}
|
|
}
|
|
|
|
// remove relevant tasks from list
|
|
for (LoadSaveTask *task = m_todo.first(); task; task = m_todo.next())
|
|
{
|
|
if (task->type() == LoadSaveTask::TaskTypeSaving)
|
|
{
|
|
SavingTask *savingTask = (SavingTask *)m_currentTask;
|
|
if (filePath.isNull() || savingTask->filePath() == filePath)
|
|
{
|
|
m_todo.remove();
|
|
m_todo.prev();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ManagedLoadSaveThread::removeLoadingTasks(const LoadingDescription &description, LoadingTaskFilter filter)
|
|
{
|
|
LoadingTask *loadingTask;
|
|
|
|
// stop current task if it is matching the criteria
|
|
if ( (loadingTask = checkLoadingTask(m_currentTask, filter)) )
|
|
{
|
|
if (description.filePath.isNull() || loadingTask->loadingDescription() == description)
|
|
{
|
|
loadingTask->setStatus(LoadingTask::LoadingTaskStatusStopping);
|
|
}
|
|
}
|
|
|
|
// remove relevant tasks from list
|
|
for (LoadSaveTask *task = m_todo.first(); task; task = m_todo.next())
|
|
{
|
|
if ( (loadingTask = checkLoadingTask(task, filter)) )
|
|
{
|
|
if (description.filePath.isNull() || loadingTask->loadingDescription() == description)
|
|
{
|
|
m_todo.remove();
|
|
m_todo.prev();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ManagedLoadSaveThread::save(DImg &image, const TQString& filePath, const TQString &format)
|
|
{
|
|
TQMutexLocker lock(&m_mutex);
|
|
LoadingTask *loadingTask;
|
|
|
|
// stop and postpone current task if it is a preloading task
|
|
if (m_currentTask && (loadingTask = checkLoadingTask(m_currentTask, LoadingTaskFilterPreloading)))
|
|
{
|
|
loadingTask->setStatus(LoadingTask::LoadingTaskStatusStopping);
|
|
load(loadingTask->filePath(), LoadingPolicyPreload);
|
|
}
|
|
// append new loading task, put it in front of preloading tasks
|
|
uint i;
|
|
for (i = 0; i<m_todo.count(); i++)
|
|
{
|
|
LoadSaveTask *task = m_todo.at(i);
|
|
if ( (loadingTask = checkLoadingTask(task, LoadingTaskFilterPreloading)) )
|
|
break;
|
|
}
|
|
m_todo.insert(i, new SavingTask(this, image, filePath, format));
|
|
}
|
|
|
|
} // namespace Digikam
|
|
|