summaryrefslogtreecommitdiffstats
path: root/src/libs/threadimageio/managedloadsavethread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/threadimageio/managedloadsavethread.cpp')
-rw-r--r--src/libs/threadimageio/managedloadsavethread.cpp362
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
+