Commit dcd1fe5f authored by Gilles Caulier's avatar Gilles Caulier 🗼
Browse files

Batch Queue Manager improvement : add Queue settings included Assigned Batch...

Batch Queue Manager improvement : add Queue settings included Assigned Batch Tools list save and restore feature. Concept is named Workflow in GUI.
By this way, end users is able to apply prefered and fully customized settings already used in previous queues processed in BQM. A control panel dedicated
to manage worflow list have been add to main BQM window. Workflow settings are saved in dedicated xml files from your home directory (into KDE config dir)
BUGS: 251126
FIXED-IN: 3.0.0
parent a303129c
This diff is collapsed.
......@@ -31,6 +31,7 @@
#include <QList>
#include <QMetaType>
#include <QPolygon>
#include <QDomElement>
// LibKDcraw includes
......@@ -88,6 +89,11 @@ public:
static DRawDecoding fromFilterAction(const FilterAction& action, const QString& prefix = QString());
/** Used by BQM to read/store Queue Raw decoding settings from/to configuration file
*/
static void decodingSettingsToXml(const RawDecodingSettings& prm, QDomElement& elm);
static void decodingSettingsFromXml(const QDomElement& elm, RawDecodingSettings& prm);
public:
/** All Raw decoding settings provided by libkdcraw.
......
......@@ -36,6 +36,8 @@ SET(libqueuemanager_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/manager/batchtool.cpp
${CMAKE_CURRENT_SOURCE_DIR}/manager/batchtoolutils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/manager/batchtoolsmanager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/manager/workflowmanager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/manager/workflowdlg.cpp
${CMAKE_CURRENT_SOURCE_DIR}/views/assignedlist.cpp
${CMAKE_CURRENT_SOURCE_DIR}/views/queuelist.cpp
${CMAKE_CURRENT_SOURCE_DIR}/views/queuepool.cpp
......@@ -44,6 +46,7 @@ SET(libqueuemanager_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/views/toolsettingsview.cpp
${CMAKE_CURRENT_SOURCE_DIR}/views/toolslistview.cpp
${CMAKE_CURRENT_SOURCE_DIR}/views/toolsview.cpp
${CMAKE_CURRENT_SOURCE_DIR}/views/workflowlist.cpp
${CMAKE_CURRENT_SOURCE_DIR}/main/queuemgrwindow.cpp
)
......
......@@ -36,8 +36,8 @@
// Local includes
#include "dimg.h"
#include "bcgfilter.h"
#include "bcgsettings.h"
#include "bcgfilter.h"
namespace Digikam
{
......
......@@ -70,6 +70,7 @@
#include "batchtoolsmanager.h"
#include "actionthread.h"
#include "queuepool.h"
#include "workflowmanager.h"
#include "queuelist.h"
#include "queuesettings.h"
#include "queuesettingsview.h"
......@@ -131,6 +132,7 @@ QueueMgrWindow::QueueMgrWindow()
m_instance = this;
BatchToolsManager::instance(); // Create first instance here
WorkflowManager::instance(); // Create first instance here
d->thread = new ActionThread(this);
setWindowFlags(Qt::Window);
......@@ -216,7 +218,7 @@ void QueueMgrWindow::setupUserArea()
// ------------------------------------------------------------------------------
QGroupBox* toolsBox = new QGroupBox(i18n("Batch Tools Available / History"), mainW);
QGroupBox* toolsBox = new QGroupBox(i18n("Control Panel"), mainW);
QVBoxLayout* vlay3 = new QVBoxLayout(toolsBox);
d->toolsView = new ToolsView(toolsBox);
vlay3->addWidget(d->toolsView);
......@@ -334,8 +336,11 @@ void QueueMgrWindow::setupConnections()
// -- GUI connections ---------------------------------------------------
connect(d->toolsView, SIGNAL(signalHistoryEntryClicked(int,qlonglong)),
this, SLOT(slotHistoryEntryClicked(int,qlonglong)));
connect(d->toolsView, SIGNAL(signalHistoryEntryClicked(int, qlonglong)),
this, SLOT(slotHistoryEntryClicked(int, qlonglong)));
connect(d->toolsView, SIGNAL(signalAssignQueueSettings(QString)),
this, SLOT(slotAssignQueueSettings(QString)));
}
void QueueMgrWindow::setupActions()
......@@ -362,6 +367,10 @@ void QueueMgrWindow::setupActions()
connect(d->removeQueueAction, SIGNAL(triggered()), d->queuePool, SLOT(slotRemoveCurrentQueue()));
actionCollection()->addAction("queuemgr_removequeue", d->removeQueueAction);
d->saveQueueAction = new KAction(KIcon("document-save"), i18n("Save Workflow"), this);
connect(d->saveQueueAction, SIGNAL(triggered()), this, SLOT(slotSaveWorkflow()));
actionCollection()->addAction("queuemgr_savequeue", d->saveQueueAction);
d->removeItemsSelAction = new KAction(KIcon("list-remove"), i18n("Remove items"), this);
d->removeItemsSelAction->setShortcut(KShortcut(Qt::CTRL + Qt::Key_K));
d->removeItemsSelAction->setEnabled(false);
......@@ -830,7 +839,7 @@ void QueueMgrWindow::slotRun()
d->statusProgressBar->setProgressTotalSteps(d->queuePool->totalPendingTasks());
d->statusProgressBar->setProgressValue(0);
d->statusProgressBar->progressBarMode(StatusProgressBar::ProgressBarMode);
d->toolsView->showHistory();
d->toolsView->showTab(ToolsView::HISTORY);
busy(true);
processOneQueue();
......@@ -881,6 +890,7 @@ void QueueMgrWindow::busy(bool busy)
d->busy = busy;
d->runAction->setEnabled(!d->busy);
d->newQueueAction->setEnabled(!d->busy);
d->saveQueueAction->setEnabled(!d->busy);
d->removeQueueAction->setEnabled(!d->busy);
d->removeItemsSelAction->setEnabled(!d->busy);
d->removeItemsDoneAction->setEnabled(!d->busy);
......@@ -1117,4 +1127,29 @@ void QueueMgrWindow::slotQueueProcessed()
}
}
void QueueMgrWindow::slotAssignQueueSettings(const QString& title)
{
if (!title.isEmpty())
{
Workflow q = WorkflowManager::instance()->findByTitle(title);
QueueListView* const queue = d->queuePool->currentQueue();
if (queue)
{
queue->setSettings(q.qSettings);
AssignedBatchTools tools;
tools.m_toolsList = q.aTools;
queue->setAssignedTools(tools);
d->queuePool->slotQueueSelected(d->queuePool->currentIndex());
}
}
}
void QueueMgrWindow::slotSaveWorkflow()
{
if (d->queuePool->saveWorkflow())
{
d->toolsView->showTab(ToolsView::WORKFLOW);
}
}
} // namespace Digikam
......@@ -129,10 +129,12 @@ private Q_SLOTS:
void slotDBStat();
void slotAction(const Digikam::ActionData&);
void slotHistoryEntryClicked(int, qlonglong);
void slotAssignQueueSettings(const QString&);
void slotAssignedToolsChanged(const AssignedBatchTools&);
void slotQueueContentsChanged();
void slotItemSelectionChanged();
void slotQueueProcessed();
void slotSaveWorkflow();
private:
......
......@@ -84,6 +84,7 @@ public:
stopAction = 0;
removeQueueAction = 0;
newQueueAction = 0;
saveQueueAction = 0;
rawCameraListAction = 0;
libsInfoAction = 0;
dbStatAction = 0;
......@@ -126,6 +127,7 @@ public:
KAction* stopAction;
KAction* removeQueueAction;
KAction* newQueueAction;
KAction* saveQueueAction;
KAction* donateMoneyAction;
KAction* contributeAction;
KAction* rawCameraListAction;
......
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
<gui version="201" name="queuemgrwindow" >
<gui version="202" name="queuemgrwindow" >
<MenuBar>
......@@ -9,6 +9,7 @@
<Separator/>
<Action name="queuemgr_newqueue" />
<Action name="queuemgr_removequeue" />
<Action name="queuemgr_savequeue" />
<Separator/>
<Action name="queuemgr_removeitemssel" />
<Action name="queuemgr_removeitemsdone" />
......
......@@ -191,6 +191,10 @@ public:
*/
bool apply();
/** Return version of tool. By default, ID is 1. Re-implement this method and increase this ID when tool settings change.
*/
virtual int toolVersion() const { return 1; };
/** Re-implement this method is you want customize cancelization of tool, for ex. to call
a dedicated method to kill sub-threads parented to this tool instance.
Unforget to call parent BatchTool::cancel() method in you customized implementation.
......
......@@ -36,7 +36,8 @@ namespace Digikam
BatchToolSet::BatchToolSet()
{
index = -1;
index = -1;
version = 0;
}
BatchToolSet::~BatchToolSet()
......@@ -45,9 +46,10 @@ BatchToolSet::~BatchToolSet()
bool BatchToolSet::operator==(const BatchToolSet& set) const
{
return ( (index == set.index) &&
(name == set.name ) &&
(group == set.group)
return ( (index == set.index) &&
(version == set.version) &&
(name == set.name ) &&
(group == set.group)
);
}
......
......@@ -58,12 +58,13 @@ public:
virtual ~BatchToolSet();
/** Equality operator which check index, name, and group data. Settings member is ignored.
/** Equality operator which check index, version, name, and group data. Settings member is ignored.
*/
bool operator==(const BatchToolSet& set) const;
/// Tool identifier data. Index is tool ID from assigned list.
int index;
int version;
QString name;
BatchTool::BatchToolGroup group;
......
......@@ -4,7 +4,7 @@
* http://www.digikam.org
*
* Date : 2009-02-21
* Description : Queue settings container.
* Description : Queue common settings container.
*
* Copyright (C) 2009-2012 Gilles Caulier <caulier dot gilles at gmail dot com>
*
......@@ -36,7 +36,8 @@ using namespace KDcrawIface;
namespace Digikam
{
/** This container host all common settings used by a queue, not including assigned batch tools
*/
class QueueSettings
{
public:
......@@ -70,6 +71,9 @@ public:
rawLoadingRule = DEMOSAICING;
};
public:
/// Setting managed through Metadata control panel.
bool exifSetOrientation;
QString renamingParser;
......
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2012-12-19
* Description : Workflow properties dialog.
*
* Copyright (C) 2012 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.
*
* ============================================================ */
#include "workflowdlg.moc"
// Qt includes
#include <QGridLayout>
#include <QGroupBox>
#include <QLabel>
#include <QRegExp>
#include <QValidator>
// KDE includes
#include <khbox.h>
#include <kiconloader.h>
#include <klineedit.h>
#include <kstandarddirs.h>
#include <kseparator.h>
#include <klocale.h>
namespace Digikam
{
class WorkflowDlg::Private
{
public:
Private() :
titleEdit(0),
descEdit(0)
{
}
KLineEdit* titleEdit;
KLineEdit* descEdit;
};
WorkflowDlg::WorkflowDlg(const Workflow& wf, bool create)
: KDialog(0), d(new Private)
{
setCaption(create ? i18n("New Workflow") : i18n("Edit Workflow"));
setButtons(Help|Ok|Cancel);
setDefaultButton(Ok);
setModal(true);
setHelp("workflowdlg.anchor", "digikam");
QWidget* page = new QWidget(this);
QLabel* logo = new QLabel(page);
logo->setPixmap(QPixmap(KStandardDirs::locate("data", "digikam/data/logo-digikam.png"))
.scaled(48, 48, Qt::KeepAspectRatio, Qt::SmoothTransformation));
QLabel* topLabel = new QLabel(page);
if (create)
{
topLabel->setText(i18n("<qt><b>Create new Workflow</b></qt>"));
}
else
{
topLabel->setText(i18n("<qt><b>Workflow Properties</b></qt>"));
}
topLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
topLabel->setWordWrap(false);
KSeparator* topLine = new KSeparator(Qt::Horizontal);
// --------------------------------------------------------
QRegExp reg("[^/]+");
QValidator* const validator = new QRegExpValidator(reg, this);
QLabel* const titleLabel = new QLabel(page);
titleLabel->setText(i18n("&Title:"));
d->titleEdit = new KLineEdit(page);
d->titleEdit->setClearButtonShown(true);
d->titleEdit->setValidator(validator);
d->titleEdit->selectAll();
d->titleEdit->setFocus();
titleLabel->setBuddy(d->titleEdit);
// --------------------------------------------------------
QLabel* const descLabel = new QLabel(page);
descLabel->setText(i18n("Description:"));
d->descEdit = new KLineEdit(page);
d->titleEdit->setClearButtonShown(true);
d->descEdit->setValidator(validator);
descLabel->setBuddy(d->descEdit);
// --------------------------------------------------------
QGridLayout* const grid = new QGridLayout();
grid->addWidget(logo, 0, 0, 1, 1);
grid->addWidget(topLabel, 0, 1, 1, 1);
grid->addWidget(topLine, 1, 0, 1, 2);
grid->addWidget(titleLabel, 2, 0, 1, 1);
grid->addWidget(d->titleEdit, 2, 1, 1, 1);
grid->addWidget(descLabel, 3, 0, 1, 1, Qt::AlignLeft | Qt::AlignTop);
grid->addWidget(d->descEdit, 3, 1, 1, 1);
grid->setMargin(0);
grid->setSpacing(KDialog::spacingHint());
page->setLayout(grid);
if (create)
{
d->titleEdit->setText(i18n("New Workflow"));
}
else
{
d->titleEdit->setText(wf.title);
d->descEdit->setText(wf.desc);
}
// -- slots connections -------------------------------------------
connect(d->titleEdit, SIGNAL(textChanged(QString)),
this, SLOT(slotTitleChanged(QString)));
// --------------------------------------------------------
setMainWidget(page);
}
WorkflowDlg::~WorkflowDlg()
{
delete d;
}
QString WorkflowDlg::title() const
{
return d->titleEdit->text();
}
QString WorkflowDlg::description() const
{
return d->descEdit->text();
}
bool WorkflowDlg::editProps(Workflow& wf)
{
QPointer<WorkflowDlg> dlg = new WorkflowDlg(wf);
bool ok = (dlg->exec() == QDialog::Accepted);
if (ok)
{
wf.title = dlg->title();
wf.desc = dlg->description();
}
delete dlg;
return ok;
}
bool WorkflowDlg::createNew(Workflow& wf)
{
QPointer<WorkflowDlg> dlg = new WorkflowDlg(wf, true);
bool ok = (dlg->exec() == QDialog::Accepted);
if (ok)
{
wf.title = dlg->title();
wf.desc = dlg->description();
}
delete dlg;
return ok;
}
void WorkflowDlg::slotTitleChanged(const QString& text)
{
Workflow wf = WorkflowManager::instance()->findByTitle(text);
bool enable = (wf.title.isEmpty() && !text.isEmpty());
enableButtonOk(enable);
}
} // namespace Digikam
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2012-12-19
* Description : Workflow properties dialog.
*
* Copyright (C) 2012 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.
*
* ============================================================ */
#ifndef WORKFLOW_DLG_H
#define WORKFLOW_DLG_H
// Qt includes
#include <QDateTime>
#include <QString>
#include <QStringList>
// KDE includes
#include <kdialog.h>
// Locale includes
#include "workflowmanager.h"
namespace Digikam
{
class WorkflowDlg : public KDialog
{
Q_OBJECT
public:
explicit WorkflowDlg(const Workflow& wf, bool create=false);
~WorkflowDlg();
QString title() const;
QString description() const;
public:
static bool editProps(Workflow& wf);
static bool createNew(Workflow& wf);
private Q_SLOTS:
void slotTitleChanged(const QString& text);
private:
class Private;
Private* const d;
};
} // namespace Digikam
#endif /* WORKFLOW_DLG_H */
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2012-12-17
* Description : workflow manager.
*
* Copyright (C) 2012 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.
*
* ============================================================ */
#include "workflowmanager.moc"
// Qt includes
#include <QMutex>
#include <QFile>
#include <QDomDocument>
#include <QDomElement>
#include <QTextStream>
#include <QTextCodec>
// KDE includes
#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>
#include <kstandarddirs.h>
// Local includes
#include "queuesettings.h"
#include "batchtoolsmanager.h"
namespace Digikam
{
class WorkflowManager::Private
{
public:
Private()
:mutex(QMutex::Recursive)
{
modified = false;
}
bool modified;