diff options
Diffstat (limited to 'src/libs/threadimageio/managedloadsavethread.cpp')
-rw-r--r-- | src/libs/threadimageio/managedloadsavethread.cpp | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/src/libs/threadimageio/managedloadsavethread.cpp b/src/libs/threadimageio/managedloadsavethread.cpp new file mode 100644 index 00000000..51d9f1b7 --- /dev/null +++ b/src/libs/threadimageio/managedloadsavethread.cpp @@ -0,0 +1,362 @@ +/* ============================================================ + * + * 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 + |