[calligra] krita/plugins/extensions/gmic: Implement basic preview support for G'MIC for Krita
Lukáš Tvrdý
lukast.dev at gmail.com
Sat Nov 22 21:25:34 UTC 2014
Git commit 24eb6339c02e2cab495b183a652588845aa9a349 by Lukáš Tvrdý.
Committed on 22/11/2014 at 21:16.
Pushed by lukast into branch 'master'.
Implement basic preview support for G'MIC for Krita
- implement small preview window support
- implement extra feature: on-canvas preview mode (select Preview Size: On Canvas)
- a lot of small bug-fixes
Preview makes G'MIC for Krita much more usable
List of known issues is in source dir at
[calligra.git]/krita/plugins/extensions/gmic/TODO
Review it before reporting bugs, please
CCMAIL:kimageshop at kde.org
M +3 -2 krita/plugins/extensions/gmic/CMakeLists.txt
M +16 -1 krita/plugins/extensions/gmic/Command.cpp
M +1 -0 krita/plugins/extensions/gmic/Command.h
M +27 -8 krita/plugins/extensions/gmic/TODO
A +49 -0 krita/plugins/extensions/gmic/kis_filter_preview_widget.cpp [License: UNKNOWN] *
A +33 -0 krita/plugins/extensions/gmic/kis_filter_preview_widget.h [License: UNKNOWN] *
M +67 -11 krita/plugins/extensions/gmic/kis_gmic_applicator.cpp
M +9 -3 krita/plugins/extensions/gmic/kis_gmic_applicator.h
M +33 -3 krita/plugins/extensions/gmic/kis_gmic_filter_settings.cpp
M +47 -2 krita/plugins/extensions/gmic/kis_gmic_filter_settings.h
M +44 -19 krita/plugins/extensions/gmic/kis_gmic_input_output_widget.cpp
M +13 -2 krita/plugins/extensions/gmic/kis_gmic_input_output_widget.h
M +0 -1 krita/plugins/extensions/gmic/kis_gmic_parser.cpp
M +210 -54 krita/plugins/extensions/gmic/kis_gmic_plugin.cpp
M +22 -5 krita/plugins/extensions/gmic/kis_gmic_plugin.h
M +3 -3 krita/plugins/extensions/gmic/kis_gmic_settings_widget.cpp
M +23 -12 krita/plugins/extensions/gmic/kis_gmic_synchronize_layers_command.cpp
M +0 -18 krita/plugins/extensions/gmic/kis_gmic_updater.cpp
M +221 -91 krita/plugins/extensions/gmic/kis_gmic_widget.cpp
M +35 -12 krita/plugins/extensions/gmic/kis_gmic_widget.h
M +7 -1 krita/plugins/extensions/gmic/kis_import_gmic_processing_visitor.cpp
M +2 -0 krita/plugins/extensions/gmic/kis_input_output_mapper.cpp
M +2 -2 krita/plugins/extensions/gmic/tests/kis_gmic_tests.cpp
M +69 -26 krita/plugins/extensions/gmic/wdg_gmic.ui
A +128 -0 krita/plugins/extensions/gmic/wdg_gmic_input_output.ui
The files marked with a * at the end have a non valid license. Please read: http://techbase.kde.org/Policies/Licensing_Policy and use the headers which are listed at that page.
http://commits.kde.org/calligra/24eb6339c02e2cab495b183a652588845aa9a349
diff --git a/krita/plugins/extensions/gmic/CMakeLists.txt b/krita/plugins/extensions/gmic/CMakeLists.txt
index 736e103..3452d30 100644
--- a/krita/plugins/extensions/gmic/CMakeLists.txt
+++ b/krita/plugins/extensions/gmic/CMakeLists.txt
@@ -78,8 +78,11 @@ set(kritagmic_shared_PART_SRCS
kis_gmic_filter_proxy_model.cpp
kis_gmic_widget.cpp
kis_gmic_updater.cpp
+ kis_filter_preview_widget.cpp
)
+kde4_add_ui_files(kritagmic_shared_PART_SRCS wdg_gmic.ui wdg_gmic_input_output.ui)
+
set(kritagmic_PART_SRCS
kis_gmic_simple_convertor.cpp
kis_export_gmic_processing_visitor.cpp
@@ -92,8 +95,6 @@ set(kritagmic_PART_SRCS
set(gmicparser_PART_SRCS main.cpp ${kritagmic_shared_PART_SRCS})
-
-kde4_add_ui_files(kritagmic_PART_SRCS wdg_gmic.ui )
kde4_add_plugin(kritagmic ${kritagmic_PART_SRCS})
target_link_libraries(kritagmic kritaui gmic ${QT_QTXML_LIBRARY} ${ZLIB_LIBRARIES})
diff --git a/krita/plugins/extensions/gmic/Command.cpp b/krita/plugins/extensions/gmic/Command.cpp
index a35182f..b514627 100644
--- a/krita/plugins/extensions/gmic/Command.cpp
+++ b/krita/plugins/extensions/gmic/Command.cpp
@@ -59,6 +59,14 @@ void Command::processCommandName(const QString& line)
m_command = commands.at(0).trimmed();
m_commandPreview = commands.at(1).trimmed();
+ QStringList splitted = m_commandPreview.split("(");
+ if (splitted.size() == 2)
+ {
+ m_commandPreview = splitted.at(0);
+ m_commandPreviewZoom = splitted.at(1);
+ m_commandPreviewZoom.chop(1);
+ }
+
}
@@ -369,11 +377,13 @@ void Command::writeConfiguration(KisGmicFilterSetting* setting)
{
// example: -gimp_poster_edges 20,60,5,0,10,0,0
QString command = "-" + m_command + " ";
+ QString commandPreview = "-" + m_commandPreview + " ";
foreach(Parameter * p, m_parameters)
{
if (!p->value().isNull())
{
command.append(p->value() +",");
+ commandPreview.append(p->value() +",");
}
else
{
@@ -382,7 +392,6 @@ void Command::writeConfiguration(KisGmicFilterSetting* setting)
// implement for given parameter value()!
dbgPlugins << "UNHANDLED command parameter: " << p->m_name << p->toString();
}
-
}
}
@@ -391,7 +400,13 @@ void Command::writeConfiguration(KisGmicFilterSetting* setting)
command.chop(1);
}
+ if (commandPreview.endsWith(","))
+ {
+ commandPreview.chop(1);
+ }
+
setting->setGmicCommand(command);
+ setting->setPreviewGmicCommand(commandPreview);
}
QString Command::mergeBlockToLine(const QStringList& block)
diff --git a/krita/plugins/extensions/gmic/Command.h b/krita/plugins/extensions/gmic/Command.h
index ad4c10f..021da41 100644
--- a/krita/plugins/extensions/gmic/Command.h
+++ b/krita/plugins/extensions/gmic/Command.h
@@ -40,6 +40,7 @@ public:
QString m_command;
QString m_commandPreview;
+ QString m_commandPreviewZoom;
QList<Parameter*> m_parameters;
virtual void add(Component* c);
diff --git a/krita/plugins/extensions/gmic/TODO b/krita/plugins/extensions/gmic/TODO
index 7720fe8..9a01e45 100644
--- a/krita/plugins/extensions/gmic/TODO
+++ b/krita/plugins/extensions/gmic/TODO
@@ -1,10 +1,29 @@
-[DONE] * fix parser, there are still crazy cases where we do not parse notes and separators correctly (multi-line notes)
-[DONE] * add support for missing parameters (int, float, choice, note supported)
-* add support for layer modes: so far current layer is filtered
- * modes like current layer+above, all visible, etc.
-* UNDO does not work correctly sometimes
-* implement preview and it's modes
-* implement progress
-* figure out on-line updates for filter defintions
+List of known bugs:
+[done] * add ui for various preview sizes
+[done] * thumbnail preview (100%zoom only in first step?)
+[done] * finish full screen preview (ala Krita filters)
+[done] * aspect ratio in preview viewport has to be set correctly
+[done] * preview area has to support opacity
+[done] * selecting non-filter item in filter tree shows unchanged layer
+[done] * turning off preview: it shows non-filtered active layer
+[done] * preview is computed using gmic command, not using gmic preview command
+* add support for panning in preview viewport
+* implement progress bar for filters and preview
* separate included gmic code to stand-alone library and link dynamically
+* if the gmic filter outputs layer smaller than original, it supposed to be centered to canvas size, not bitblt(0,0,image->rect)
+* what to do with selections for small preview?
+* sometimes preview blocks the UI because it takes too long => progress bar
+* resizing the preview has to work (Small, Tiny, Large, ...)
+* resizing "input/output area/preview viewport" from filter settings tree
+* support all preview output modes
+* gmic debug output slows down filtering, make it optional
+* support for zooming/panning preview
+* preview area needs border and scrollbars
+* tiny, small, normal, large behaves exactly same for now
+* "Preview mode" only 1st ouput works
+* missing: Favorite presets group
+* missing: button for expanding all folders
+* missing: Available filters information
+* scrollbars for filter settings that are huge! currently text is horizontally downscaled and unreadable
+* gmic is located under Layer -> Apply Gmic action, it supposed to be in Filters
diff --git a/krita/plugins/extensions/gmic/kis_filter_preview_widget.cpp b/krita/plugins/extensions/gmic/kis_filter_preview_widget.cpp
new file mode 100644
index 0000000..5521902
--- /dev/null
+++ b/krita/plugins/extensions/gmic/kis_filter_preview_widget.cpp
@@ -0,0 +1,49 @@
+#include "kis_filter_preview_widget.h"
+#include <kis_canvas_widget_base.h>
+#include <kis_config.h>
+#include <QPaintEvent>
+#include <QPainter>
+#include <QWheelEvent>
+
+#include <QDebug>
+
+KisFilterPreviewWidget::KisFilterPreviewWidget(QWidget* parent): QWidget(parent)
+{
+ KisConfig cfg;
+ // for preview make it smaller than on canvas
+ qint32 checkSize = qMax(1,cfg.checkSize() / 2);
+ QImage checkImage = KisCanvasWidgetBase::createCheckersImage(checkSize);
+ m_checkBrush = QBrush(checkImage);
+ m_pixmap = QPixmap::fromImage(checkImage);
+}
+
+KisFilterPreviewWidget::~KisFilterPreviewWidget()
+{
+
+}
+
+void KisFilterPreviewWidget::paintEvent(QPaintEvent* event)
+{
+ Q_UNUSED(event);
+ QPainter gc(this);
+ gc.fillRect(m_pixmap.rect(), m_checkBrush);
+ gc.drawPixmap(0,0,m_pixmap);
+
+
+ QPen pen(Qt::black, 1, Qt::SolidLine);
+ gc.setPen(pen);
+ gc.drawRect(m_pixmap.rect().adjusted(0,0,-1,-1));
+
+}
+
+QSize KisFilterPreviewWidget::sizeHint() const
+{
+ return QSize(1, 1);
+}
+
+void KisFilterPreviewWidget::setImage(const QImage& img)
+{
+ m_pixmap = QPixmap::fromImage(img);
+ update();
+}
+
diff --git a/krita/plugins/extensions/gmic/kis_filter_preview_widget.h b/krita/plugins/extensions/gmic/kis_filter_preview_widget.h
new file mode 100644
index 0000000..0235036
--- /dev/null
+++ b/krita/plugins/extensions/gmic/kis_filter_preview_widget.h
@@ -0,0 +1,33 @@
+#ifndef KIS_FILTER_PREVIEW_WIDGET
+#define KIS_FILTER_PREVIEW_WIDGET
+
+#include <QWidget>
+
+class QWheelEvent;
+class QPaintEvent;
+
+class KisFilterPreviewWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ KisFilterPreviewWidget(QWidget * parent);
+ ~KisFilterPreviewWidget();
+
+ virtual QSize sizeHint() const;
+ virtual void paintEvent(QPaintEvent* event);
+
+ void setImage(const QImage &img);
+
+protected:
+
+
+
+
+
+private:
+ QPixmap m_pixmap;
+ QBrush m_checkBrush;
+
+};
+
+#endif
diff --git a/krita/plugins/extensions/gmic/kis_gmic_applicator.cpp b/krita/plugins/extensions/gmic/kis_gmic_applicator.cpp
index b5bfc49..6ca0983 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_applicator.cpp
+++ b/krita/plugins/extensions/gmic/kis_gmic_applicator.cpp
@@ -28,13 +28,15 @@
#include "kis_image.h"
#include <kis_selection.h>
-KisGmicApplicator::KisGmicApplicator()
+KisGmicApplicator::KisGmicApplicator():m_applicator(0),m_applicatorFinished(false)
{
}
KisGmicApplicator::~KisGmicApplicator()
{
+ dbgPlugins << "Destructor: " << m_applicator;
+ delete m_applicator;
}
void KisGmicApplicator::setProperties(KisImageWSP image, KisNodeSP node, const KUndo2MagicString &actionName, KisNodeListSP kritaNodes, const QString &gmicCommand, const QByteArray customCommands)
@@ -47,15 +49,21 @@ void KisGmicApplicator::setProperties(KisImageWSP image, KisNodeSP node, const K
m_customCommands = customCommands;
}
-void KisGmicApplicator::run()
+
+void KisGmicApplicator::preview()
{
+ // cancel previous preview if there is one
+ dbgPlugins << "Request for preview, cancelling any previous possible on-canvas preview";
+ cancel();
+
KisImageSignalVector emitSignals;
emitSignals << ModifiedSignal;
- KisProcessingApplicator applicator(m_image, m_node,
+ m_applicator = new KisProcessingApplicator(m_image, m_node,
KisProcessingApplicator::RECURSIVE,
emitSignals, m_actionName);
+ dbgPlugins << "Creating applicator " << m_applicator;
QSharedPointer< gmic_list<float> > gmicLayers(new gmic_list<float>);
gmicLayers->assign(m_kritaNodes->size());
@@ -71,21 +79,69 @@ void KisGmicApplicator::run()
{
layerSize = QRect(0,0,m_image->width(), m_image->height());
}
- KisProcessingVisitorSP visitor;
// convert krita layers to gmic layers
- visitor = new KisExportGmicProcessingVisitor(m_kritaNodes, gmicLayers, layerSize);
- applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT);
+ KisProcessingVisitorSP exportVisitor = new KisExportGmicProcessingVisitor(m_kritaNodes, gmicLayers, layerSize);
+ m_applicator->applyVisitor(exportVisitor, KisStrokeJobData::CONCURRENT);
// apply gmic filters to provided layers
const char * customCommands = m_customCommands.isNull() ? 0 : m_customCommands.constData();
- applicator.applyCommand(new KisGmicCommand(m_gmicCommand, gmicLayers, customCommands));
+ m_applicator->applyCommand(new KisGmicCommand(m_gmicCommand, gmicLayers, customCommands));
// synchronize layer count
- applicator.applyCommand(new KisGmicSynchronizeLayersCommand(m_kritaNodes, gmicLayers, m_image), KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE);
+ m_applicator->applyCommand(new KisGmicSynchronizeLayersCommand(m_kritaNodes, gmicLayers, m_image), KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE);
// would sleep(3) help here?
- visitor = new KisImportGmicProcessingVisitor(m_kritaNodes, gmicLayers, layerSize, selection);
- applicator.applyVisitor(visitor, KisStrokeJobData::SEQUENTIAL); // undo information is stored in this visitor
- applicator.end();
+ KisProcessingVisitorSP importVisitor = new KisImportGmicProcessingVisitor(m_kritaNodes, gmicLayers, layerSize, selection);
+ m_applicator->applyVisitor(importVisitor, KisStrokeJobData::SEQUENTIAL); // undo information is stored in this visitor
+ m_applicator->explicitlyEmitFinalSignals();
+}
+
+void KisGmicApplicator::cancel()
+{
+
+ if (m_applicator)
+ {
+
+ if (!m_applicatorFinished)
+ {
+ dbgPlugins << "Cancelling applicator: Yes!";
+ m_applicator->cancel();
+ }
+ else
+ {
+ dbgPlugins << "Cancelling applicator: No! Reason: Already finished!";
+ }
+
+
+ dbgPlugins << "deleting applicator: " << m_applicator;
+ delete m_applicator;
+ m_applicator = 0;
+
+
+ m_applicatorFinished = false;
+ dbgPlugins << ppVar(m_applicatorFinished);
+
+ }
+ else
+ {
+ dbgPlugins << "Cancelling applicator: No! Reason: Null applicator!";
+ }
+
+
+}
+
+void KisGmicApplicator::finish()
+{
+ dbgPlugins << "aplicator " << m_applicator << " finished";
+ if (m_applicator)
+ {
+ m_applicator->end();
+ m_applicatorFinished = true;
+ dbgPlugins << ppVar(m_applicatorFinished);
+ }
+ else
+ {
+ dbgPlugins << ppVar(m_applicatorFinished);
+ }
}
diff --git a/krita/plugins/extensions/gmic/kis_gmic_applicator.h b/krita/plugins/extensions/gmic/kis_gmic_applicator.h
index 389bf6b..bca1637 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_applicator.h
+++ b/krita/plugins/extensions/gmic/kis_gmic_applicator.h
@@ -24,22 +24,28 @@
#include <kis_types.h>
#include <QThread>
+class KisProcessingApplicator;
-class KisGmicApplicator : public QThread
+class KisGmicApplicator
{
public:
KisGmicApplicator();
~KisGmicApplicator();
void setProperties(KisImageWSP image, KisNodeSP node, const KUndo2MagicString &actionName, KisNodeListSP kritaNodes, const QString &gmicCommand, const QByteArray customCommands = QByteArray());
-protected:
- virtual void run();
+
+ void preview();
+ void cancel();
+ void finish();
+
private:
+ KisProcessingApplicator * m_applicator;
KisImageWSP m_image;
KisNodeSP m_node;
KUndo2MagicString m_actionName;
KisNodeListSP m_kritaNodes;
QString m_gmicCommand;
QByteArray m_customCommands;
+ bool m_applicatorFinished;
};
#endif
diff --git a/krita/plugins/extensions/gmic/kis_gmic_filter_settings.cpp b/krita/plugins/extensions/gmic/kis_gmic_filter_settings.cpp
index c122e21..d0f5666 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_filter_settings.cpp
+++ b/krita/plugins/extensions/gmic/kis_gmic_filter_settings.cpp
@@ -20,7 +20,7 @@
#include <kis_gmic_filter_settings.h>
-KisGmicFilterSetting::KisGmicFilterSetting():m_gmicCommand(),m_inputLayerMode(ACTIVE_LAYER),m_outputMode(IN_PLACE),m_isBlacklisted(false)
+KisGmicFilterSetting::KisGmicFilterSetting():m_gmicCommand(),m_previewGmicCommand(),m_inputLayerMode(ACTIVE_LAYER),m_outputMode(IN_PLACE),m_isBlacklisted(false)
{
}
@@ -40,7 +40,17 @@ void KisGmicFilterSetting::setGmicCommand(QString cmd)
m_gmicCommand = cmd;
}
-InputLayerMode KisGmicFilterSetting::inputLayerMode()
+const QString& KisGmicFilterSetting::previewGmicCommand() const
+{
+ return m_previewGmicCommand;
+}
+
+void KisGmicFilterSetting::setPreviewGmicCommand(QString cmd)
+{
+ m_previewGmicCommand = cmd;
+}
+
+InputLayerMode KisGmicFilterSetting::inputLayerMode() const
{
return m_inputLayerMode;
}
@@ -50,7 +60,7 @@ void KisGmicFilterSetting::setInputLayerMode(InputLayerMode mode)
m_inputLayerMode = mode;
}
-OutputMode KisGmicFilterSetting::outputMode()
+OutputMode KisGmicFilterSetting::outputMode() const
{
return m_outputMode;
}
@@ -59,3 +69,23 @@ void KisGmicFilterSetting::setOutputMode(OutputMode mode)
{
m_outputMode = mode;
}
+
+OutputPreviewMode KisGmicFilterSetting::previewMode() const
+{
+ return m_previewMode;
+}
+
+void KisGmicFilterSetting::setPreviewMode(OutputPreviewMode mode)
+{
+ m_previewMode = mode;
+}
+
+PreviewSize KisGmicFilterSetting::previewSize() const
+{
+ return m_previewSize;
+}
+
+void KisGmicFilterSetting::setPreviewSize(PreviewSize size)
+{
+ m_previewSize = size;
+}
diff --git a/krita/plugins/extensions/gmic/kis_gmic_filter_settings.h b/krita/plugins/extensions/gmic/kis_gmic_filter_settings.h
index 14ad26a..bdddb32 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_filter_settings.h
+++ b/krita/plugins/extensions/gmic/kis_gmic_filter_settings.h
@@ -33,6 +33,7 @@ static QStringList OUTPUT_MODE_STRINGS = QStringList() << "In place (default)"
<< "New active layer(s)"
<< "New image";
+
// this enum is also index in LAYER_MODE_STRINGS list
enum InputLayerMode { NONE = 0,
ACTIVE_LAYER,
@@ -57,6 +58,38 @@ static QStringList INPUT_MODE_STRINGS = QStringList() << "None"
<< "All invisibles (decr.)"
<< "All (decr.)";
+enum PreviewSize { TINY = 0,
+ SMALL,
+ NORMAL,
+ LARGE,
+ ON_CANVAS
+
+
+};
+
+static QStringList PREVIEW_SIZE = QStringList() << "Tiny" << "Small" << "Normal" << "Large" << "On Canvas";
+
+enum OutputPreviewMode { FIRST = 0,
+ SECOND,
+ THIRD,
+ FOURTH,
+ FIRST_TO_SECOND,
+ FIRST_TO_THIRD,
+ FIRST_TO_FOURTH,
+ ALL
+
+};
+
+static QStringList PREVIEW_MODE = QStringList() << "1st output"
+ << "2nd output"
+ << "3rd output"
+ << "4th output"
+ << "1st -> 2nd"
+ << "1st -> 3rd"
+ << "1st -> 4th"
+ << "All outputs";
+
+
class KisGmicFilterSetting
{
public:
@@ -66,18 +99,30 @@ public:
void setGmicCommand(QString cmd);
const QString& gmicCommand() const;
- InputLayerMode inputLayerMode();
+ void setPreviewGmicCommand(QString cmd);
+ const QString& previewGmicCommand() const;
+
+ InputLayerMode inputLayerMode() const;
void setInputLayerMode(InputLayerMode mode);
- OutputMode outputMode();
+ OutputMode outputMode() const;
void setOutputMode(OutputMode mode);
+ PreviewSize previewSize() const;
+ void setPreviewSize(PreviewSize size);
+
+ OutputPreviewMode previewMode() const;
+ void setPreviewMode(OutputPreviewMode mode);
+
void setBlacklisted(bool blacklist){ m_isBlacklisted = blacklist; }
bool isBlacklisted() const { return m_isBlacklisted; };
private:
QString m_gmicCommand;
+ QString m_previewGmicCommand;
InputLayerMode m_inputLayerMode;
OutputMode m_outputMode;
+ PreviewSize m_previewSize;
+ OutputPreviewMode m_previewMode;
bool m_isBlacklisted;
};
diff --git a/krita/plugins/extensions/gmic/kis_gmic_input_output_widget.cpp b/krita/plugins/extensions/gmic/kis_gmic_input_output_widget.cpp
index 6b6644e..b1e7d27 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_input_output_widget.cpp
+++ b/krita/plugins/extensions/gmic/kis_gmic_input_output_widget.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 Lukáš Tvrdý <lukast.dev at gmail.com>
+ * Copyright (c) 2013-2014 Lukáš Tvrdý <lukast.dev at gmail.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
@@ -15,6 +15,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+#include <KoIcon.h>
+
#include <kis_gmic_input_output_widget.h>
#include <kis_debug.h>
@@ -25,8 +27,14 @@
#include <QStringListModel>
#include <QLabel>
-KisGmicInputOutputWidget::KisGmicInputOutputWidget(): QWidget(), m_inputMode(ACTIVE_LAYER), m_outputMode(IN_PLACE)
+KisGmicInputOutputWidget::KisGmicInputOutputWidget(QWidget * parent):
+ QWidget(parent),
+ m_inputMode(ACTIVE_LAYER),
+ m_outputMode(IN_PLACE),
+ m_previewMode(FIRST),
+ m_previewSize(TINY)
{
+ setupUi(this);
createMainLayout();
}
@@ -35,44 +43,61 @@ KisGmicInputOutputWidget::~KisGmicInputOutputWidget()
}
+KisFilterPreviewWidget* KisGmicInputOutputWidget::previewWidget()
+{
+ return previewViewport;
+}
+
+
+
void KisGmicInputOutputWidget::createMainLayout()
{
- QComboBox * inputCombo = new QComboBox;
+ zoomInButton->setIcon(koIcon("zoom-in"));
+ zoomOutButton->setIcon(koIcon("zoom-out"));
+
QStringListModel * inputModel = new QStringListModel(INPUT_MODE_STRINGS);
inputCombo->setModel(inputModel);
QObject::connect(inputCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setIntputMode(int)));
inputCombo->setCurrentIndex(static_cast<int>(m_inputMode));
- QComboBox * outputCombo = new QComboBox;
QStringListModel * outputModel = new QStringListModel(OUTPUT_MODE_STRINGS);
outputCombo->setModel(outputModel);
QObject::connect(outputCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setOutputMode(int)));
outputCombo->setCurrentIndex(static_cast<int>(m_outputMode));
- QGridLayout * gridLayout = new QGridLayout;
- int row = 0;
- gridLayout->addWidget(new QLabel("Input"), row, 0);
- gridLayout->addWidget(inputCombo, row, 1, 1, 2);
- row++;
- gridLayout->addWidget(new QLabel("Output"), row, 0);
- gridLayout->addWidget(outputCombo, row, 1, 1, 2);
+ QStringListModel * previewModeModel = new QStringListModel(PREVIEW_MODE);
+ outputPreviewCombo->setModel(previewModeModel);
+ QObject::connect(outputPreviewCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setPreviewMode(int)));
+ outputPreviewCombo->setCurrentIndex(static_cast<int>(m_previewMode));
- setLayout(gridLayout);
+ QStringListModel * previewSizeModel = new QStringListModel(PREVIEW_SIZE);
+ previewSizeCombo->setModel(previewSizeModel);
+ QObject::connect(previewSizeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setPreviewSize(int)));
+ previewSizeCombo->setCurrentIndex(static_cast<int>(m_previewSize));
}
void KisGmicInputOutputWidget::setIntputMode(int index)
{
- m_inputMode = static_cast<InputLayerMode>(index);
- dbgPlugins << "Selecting " << INPUT_MODE_STRINGS.at(index);
- emit sigConfigurationChanged();
-
+ m_inputMode = static_cast<InputLayerMode>(index);
+ emit sigConfigurationChanged();
}
void KisGmicInputOutputWidget::setOutputMode(int index)
{
- m_outputMode = static_cast<OutputMode>(index);
- dbgPlugins << "Selecting " << OUTPUT_MODE_STRINGS.at(index);
- emit sigConfigurationChanged();
+ m_outputMode = static_cast<OutputMode>(index);
+ emit sigConfigurationChanged();
+}
+
+void KisGmicInputOutputWidget::setPreviewMode(int index)
+{
+ m_previewMode = static_cast<OutputPreviewMode>(index);
+ emit sigConfigurationChanged();
+}
+
+void KisGmicInputOutputWidget::setPreviewSize(int index)
+{
+ m_previewSize = static_cast<PreviewSize>(index);
+ emit sigConfigurationChanged();
}
diff --git a/krita/plugins/extensions/gmic/kis_gmic_input_output_widget.h b/krita/plugins/extensions/gmic/kis_gmic_input_output_widget.h
index 9fb5964..f9feb6f 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_input_output_widget.h
+++ b/krita/plugins/extensions/gmic/kis_gmic_input_output_widget.h
@@ -22,20 +22,27 @@
#include <QHash>
#include "kis_gmic_filter_settings.h"
+#include "ui_wdg_gmic_input_output.h"
+
/**
* creates GUI for Input/Output configuration
*/
-class KisGmicInputOutputWidget : public QWidget
+class KisGmicInputOutputWidget : public QWidget, public Ui::WdgGmicInputOutput
{
Q_OBJECT
public:
- KisGmicInputOutputWidget();
+ KisGmicInputOutputWidget(QWidget * parent);
~KisGmicInputOutputWidget();
InputLayerMode inputMode() const { return m_inputMode; };
OutputMode outputMode() const { return m_outputMode; };
+ OutputPreviewMode previewMode() const { return m_previewMode; };
+ PreviewSize previewSize() const { return m_previewSize; };
+
+ KisFilterPreviewWidget * previewWidget();
+
signals:
void sigConfigurationChanged();
@@ -45,10 +52,14 @@ private:
private slots:
void setIntputMode(int index);
void setOutputMode(int index);
+ void setPreviewMode(int index);
+ void setPreviewSize(int index);
private:
InputLayerMode m_inputMode;
OutputMode m_outputMode;
+ OutputPreviewMode m_previewMode;
+ PreviewSize m_previewSize;
};
diff --git a/krita/plugins/extensions/gmic/kis_gmic_parser.cpp b/krita/plugins/extensions/gmic/kis_gmic_parser.cpp
index 150673d..7c29ee5 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_parser.cpp
+++ b/krita/plugins/extensions/gmic/kis_gmic_parser.cpp
@@ -27,7 +27,6 @@
#include <Parameter.h>
#include <Command.h>
#include <Category.h>
-#include "kis_gmic_widget.h"
KisGmicParser::KisGmicParser(const QStringList& filePaths):m_filePaths(filePaths)
diff --git a/krita/plugins/extensions/gmic/kis_gmic_plugin.cpp b/krita/plugins/extensions/gmic/kis_gmic_plugin.cpp
index d5c732e..bf9f127 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_plugin.cpp
+++ b/krita/plugins/extensions/gmic/kis_gmic_plugin.cpp
@@ -1,7 +1,7 @@
/*
* This file is part of the KDE project
*
- * Copyright (c) 2013 Lukáš Tvrdý <lukast.dev at gmail.com>
+ * Copyright (c) 2013-2014 Lukáš Tvrdý <lukast.dev at gmail.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
@@ -37,6 +37,7 @@
#include <kis_image.h>
#include <kis_paint_device.h>
#include <kis_layer.h>
+#include <kis_selection.h>
#include <kis_paint_layer.h>
#include "kis_statusbar.h"
#include "widgets/kis_progress_widget.h"
@@ -51,24 +52,53 @@
#include "kis_input_output_mapper.h"
#include "kis_gmic_simple_convertor.h"
#include "kis_gmic_applicator.h"
+#include "kis_export_gmic_processing_visitor.h"
+#include "kis_gmic_command.h"
+#include "kis_import_gmic_processing_visitor.h"
+#include "kis_gmic_synchronize_layers_command.h"
+
+#include "KoColorSpaceConstants.h"
K_PLUGIN_FACTORY(KisGmicPluginFactory, registerPlugin<KisGmicPlugin>();)
K_EXPORT_PLUGIN(KisGmicPluginFactory("krita"))
const QString STANDARD_GMIC_DEFINITION = "gmic_def.gmic";
+class TemporaryFeedback
+{
+public:
+ TemporaryFeedback(QWidget * widget):m_widget(widget)
+ {
+ myTimer.start();
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ }
+
+ ~TemporaryFeedback()
+ {
+ QApplication::restoreOverrideCursor();
+ double seconds = myTimer.elapsed() * 0.001;
+ m_widget->setWindowTitle(QString("Filtering took ") + QString::number(seconds) + QString(" seconds"));
+ }
+
+private:
+ QWidget * m_widget;
+ QTime myTimer;
+};
+
+
KisGmicPlugin::KisGmicPlugin(QObject *parent, const QVariantList &)
- : KisViewPlugin(parent, "kritaplugins/gmic.rc"),m_gmicWidget(0)
+ : KisViewPlugin(parent, "kritaplugins/gmic.rc"),
+ m_gmicWidget(0),
+ m_previewFilter(true)
{
KisAction *action = new KisAction(i18n("Apply G'Mic Action..."), this);
action->setActivationFlags(KisAction::ACTIVE_LAYER);
action->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE);
+ connect(action, SIGNAL(triggered()), this, SLOT(slotShowGmicDialog()));
addAction("gmic", action);
KGlobal::dirs()->addResourceType("gmic_definitions", "data", "krita/gmic/");
m_blacklistPath = KGlobal::mainComponent().dirs()->findResource("gmic_definitions", STANDARD_GMIC_DEFINITION + ".blacklist");
-
- connect(action, SIGNAL(triggered()), this, SLOT(slotGmic()));
}
KisGmicPlugin::~KisGmicPlugin()
@@ -89,7 +119,7 @@ void KisGmicPlugin::setupDefinitionPaths()
}
}
- // if we don't have update, prepend gmic_def.gmic
+ // if we don't have updateXXXX.gmic, prepend standard gmic_def.gmic
int gmicVersion = gmic_version;
QString updateFileName = "update" + QString::number(gmicVersion) + ".gmic";
QString updatedGmicDefinitionFilePath = KGlobal::mainComponent().dirs()->findResource("gmic_definitions", updateFileName);
@@ -100,9 +130,9 @@ void KisGmicPlugin::setupDefinitionPaths()
}
}
-
-void KisGmicPlugin::slotGmic()
+void KisGmicPlugin::slotShowGmicDialog()
{
+ // init everything here
KisImageWSP image = m_view->image();
if (!image) return;
@@ -112,9 +142,11 @@ void KisGmicPlugin::slotGmic()
if (m_gmicWidget)
{
// restart here?
- slotClose();
+ slotCloseGmicDialog();
}
+ m_gmicApplicator = new KisGmicApplicator();
+
setupDefinitionPaths();
parseGmicCommandDefinitions(m_definitionFilePaths);
@@ -128,80 +160,111 @@ void KisGmicPlugin::slotGmic()
QString updateUrl = "http://gmic.sourceforge.net/" + QString("update") + QString::number(gmic_version) + ".gmic";
m_gmicWidget = new KisGmicWidget(model, updateUrl);
- m_gmicApplicator = new KisGmicApplicator();
-#ifdef Q_WS_WIN
- // On windows, gmic needs a humongous stack for its parser
- m_gmicApplicator->setStackSize(20 * 1024 * 1024);
-#endif
-
- // apply
- connect(m_gmicWidget, SIGNAL(sigApplyCommand(KisGmicFilterSetting*)),this, SLOT(slotApplyGmicCommand(KisGmicFilterSetting*)));
+ // preview filter
+ connect(m_gmicWidget, SIGNAL(sigPreviewFilterCommand(KisGmicFilterSetting*)),this, SLOT(slotPreviewGmicCommand(KisGmicFilterSetting*)));
+ // finish filter
+ connect(m_gmicWidget, SIGNAL(sigAcceptOnCanvasPreview()), this, SLOT(slotAcceptOnCanvasPreview()));
+ // cancel filter
+ connect(m_gmicWidget, SIGNAL(sigCancelOnCanvasPreview()), this, SLOT(slotCancelOnCanvasPreview()));
// cancel
- connect(m_gmicWidget, SIGNAL(sigClose()),this, SLOT(slotClose()));
-
+ connect(m_gmicWidget, SIGNAL(sigClose()),this, SLOT(slotCloseGmicDialog()));
+ // filter current image with current settings
+ connect(m_gmicWidget, SIGNAL(sigFilterCurrentImage(KisGmicFilterSetting*)), this, SLOT(slotFilterCurrentImage(KisGmicFilterSetting*)));
+ // show active layer in preview viewport
+ connect(m_gmicWidget, SIGNAL(sigPreviewActiveLayer()), this, SLOT(slotPreviewActiveLayer()));
+
+ QString version = QString("%0.%1.%2.%3").arg(gmic_version/1000).arg((gmic_version/100)%10).arg((gmic_version/10)%10).arg(gmic_version%10);
+ QString pluginName = i18n("G'MIC for Krita");
+ m_gmicWidget->setWindowTitle(QString("%0 %1").arg(pluginName).arg(version));
m_gmicWidget->show();
+ slotPreviewActiveLayer();
}
+void KisGmicPlugin::slotCloseGmicDialog()
+{
+ m_gmicWidget = 0;
+ if (m_gmicApplicator)
+ {
+ m_gmicApplicator->cancel();
+ }
+
+ delete m_gmicApplicator;
+ m_gmicApplicator = 0;
+}
-void KisGmicPlugin::slotApplyGmicCommand(KisGmicFilterSetting* setting)
+void KisGmicPlugin::slotPreviewGmicCommand(KisGmicFilterSetting* setting)
{
- KUndo2MagicString actionName;
- KisNodeSP node;
+ dbgPlugins << "Preview Request";
- if (setting->isBlacklisted())
+ KisInputOutputMapper mapper(m_view->image(), m_view->activeNode());
+ KisNodeListSP layers = mapper.inputNodes(setting->inputLayerMode());
+ if (!checkSettingsValidity(layers, setting))
{
- KMessageBox::sorry(m_gmicWidget, i18n("Sorry, this filter is crashing Krita and is turned off."), i18n("Krita"));
+ dbgPlugins << "Failed, some feature not implemented";
return;
}
- KisInputOutputMapper mapper(m_view->image(), m_view->activeNode());
- KisNodeListSP kritaNodes = mapper.inputNodes(setting->inputLayerMode());
- if (kritaNodes->isEmpty()) {
- KMessageBox::sorry(m_gmicWidget, i18n("Sorry, this input mode is not implemented"), i18n("Krita"));
- return;
+ if (setting->previewSize() != ON_CANVAS)
+ {
+ createViewportPreview(layers, setting);
+ }
+ else
+ {
+ startOnCanvasPreview(layers, setting);
}
+}
- actionName = kundo2_i18n("Gmic filter");
- node = m_view->image()->root();
- if (setting->outputMode() != IN_PLACE) {
- KMessageBox::sorry(m_gmicWidget,QString("Sorry, this output mode is not implemented"),"Krita");
- return;
- }
+void KisGmicPlugin::slotPreviewActiveLayer()
+{
+ showInPreviewViewport(m_view->activeNode()->paintDevice());
+}
+
+
+void KisGmicPlugin::showInPreviewViewport(KisPaintDeviceSP device)
+{
+ QRect deviceRect = device->exactBounds();
+ qreal aspectRatio = (qreal)deviceRect.width()/deviceRect.height();
+
+ int dstWidth = m_gmicWidget->previewWidget()->size().width();
+ int dstHeight = dstWidth / aspectRatio;
+
+ QImage previewImage = device->createThumbnail(dstWidth, dstHeight, deviceRect);
+ m_gmicWidget->previewWidget()->setImage(previewImage);
+}
- QTime myTimer;
- myTimer.start();
- QApplication::setOverrideCursor(Qt::WaitCursor);
- m_gmicApplicator->setProperties(m_view->image(), node, actionName, kritaNodes, setting->gmicCommand(), m_gmicCustomCommands);
- m_gmicApplicator->start();
- m_gmicApplicator->wait();
- m_view->image()->waitForDone();
- QApplication::restoreOverrideCursor();
+void KisGmicPlugin::slotAcceptOnCanvasPreview()
+{
+ m_gmicApplicator->finish();
+}
- double seconds = myTimer.elapsed() * 0.001;
- // temporary feedback
- m_gmicWidget->setWindowTitle(QString("Filtering took ") + QString::number(seconds) + QString(" seconds"));
+void KisGmicPlugin::slotCancelOnCanvasPreview()
+{
+ m_gmicApplicator->cancel();
}
-void KisGmicPlugin::slotClose()
+void KisGmicPlugin::slotFilterCurrentImage(KisGmicFilterSetting* setting)
{
- bool result = m_gmicWidget->close();
- if (!result)
+ dbgPlugins << "Filtering image on canvas!";
+
+ KisInputOutputMapper mapper(m_view->image(), m_view->activeNode());
+ KisNodeListSP layers = mapper.inputNodes(setting->inputLayerMode());
+ if (checkSettingsValidity(layers, setting))
{
- dbgPlugins << "Windows was not closed?";
+ TemporaryFeedback feedback(m_gmicWidget);
+ startOnCanvasPreview(layers, setting);
+ slotAcceptOnCanvasPreview();
+ // wait, so that next request to strokes for on-canvas preview is possible
+ m_view->image()->waitForDone();
}
else
{
- // close event deletes widget
- m_gmicWidget = 0;
- delete m_gmicApplicator;
- m_gmicApplicator = 0;
+ dbgPlugins << "Failed, some feature not implemented";
}
}
-
void KisGmicPlugin::parseGmicCommandDefinitions(const QStringList& gmicDefinitionFilePaths)
{
foreach (const QString filePath, gmicDefinitionFilePaths)
@@ -211,6 +274,99 @@ void KisGmicPlugin::parseGmicCommandDefinitions(const QStringList& gmicDefinitio
}
}
+KisNodeListSP KisGmicPlugin::createPreviewThumbnails(KisNodeListSP layers,const QSize &dstSize,const QRect &srcRect)
+{
+ KisNodeListSP previewKritaNodes(new QList< KisNodeSP >());
+ for (int i = 0; i < layers->size(); i++)
+ {
+ KisPaintDeviceSP thumbnail = layers->at(i)->paintDevice()->createThumbnailDevice(dstSize.width(), dstSize.height(), srcRect);
+ KisNodeSP node(new KisPaintLayer(0, "", OPACITY_OPAQUE_U8, thumbnail));
+ previewKritaNodes->append(node);
+ }
+ return previewKritaNodes;
+}
+
+
+void KisGmicPlugin::createViewportPreview(KisNodeListSP layers, KisGmicFilterSetting* setting)
+{
+ QRect canvasRect = m_view->image()->bounds();
+ qreal aspectRatio = (qreal)canvasRect.width() / canvasRect.height();
+
+ int previewWidth = m_gmicWidget->previewWidget()->size().width();
+ int previewHeight = qRound(previewWidth / aspectRatio);
+ QRect previewRect = QRect(QPoint(0,0), QSize(previewWidth, previewHeight));
+
+ KisNodeListSP previewKritaNodes = KisGmicPlugin::createPreviewThumbnails(layers, previewRect.size(), canvasRect);
+
+ QSharedPointer< gmic_list<float> > gmicLayers(new gmic_list<float>);
+ gmicLayers->assign(previewKritaNodes->size());
+
+ KisExportGmicProcessingVisitor exportVisitor(previewKritaNodes, gmicLayers, previewRect);
+ for (int i = 0; i < previewKritaNodes->size(); i++)
+ {
+ exportVisitor.visit( (KisPaintLayer *)(*previewKritaNodes)[i].data(), 0);
+ }
+
+ QString gmicCommand = setting->previewGmicCommand();
+ if (gmicCommand.isEmpty())
+ {
+ gmicCommand = setting->gmicCommand();
+ }
+
+ KisGmicCommand gmicCmd(gmicCommand, gmicLayers, m_gmicCustomCommands);
+ gmicCmd.redo();
+
+ KisGmicSynchronizeLayersCommand syncCmd(previewKritaNodes, gmicLayers, 0);
+ syncCmd.redo();
+
+ KisImportGmicProcessingVisitor importVisitor(previewKritaNodes, gmicLayers, previewRect, 0);
+ for (int i = 0; i < previewKritaNodes->size(); i++)
+ {
+ importVisitor.visit( (KisPaintLayer *)(*previewKritaNodes)[i].data(), 0 );
+ }
+
+ if (previewKritaNodes->size() > 0)
+ {
+ showInPreviewViewport(previewKritaNodes->at(0)->paintDevice());
+ }
+ else
+ {
+ // TODO: show error preview
+ }
+}
+
+
+void KisGmicPlugin::startOnCanvasPreview(KisNodeListSP layers, KisGmicFilterSetting* setting)
+{
+ KUndo2MagicString actionName = kundo2_i18n("Gmic filter");
+ KisNodeSP rootNode = m_view->image()->root();
+ m_gmicApplicator->setProperties(m_view->image(), rootNode, actionName, layers, setting->gmicCommand(), m_gmicCustomCommands);
+ m_gmicApplicator->preview();
+ // do not call KisImage::waitForDone(): strokes are not finished or cancelled, it's just preview!
+}
+
+
+bool KisGmicPlugin::checkSettingsValidity(KisNodeListSP layers, const KisGmicFilterSetting* setting)
+{
+ if (setting->isBlacklisted())
+ {
+ KMessageBox::sorry(m_gmicWidget, i18n("Sorry, this filter is crashing Krita and is turned off."), i18n("Krita"));
+ return false;
+ }
+
+ if (setting->outputMode() != IN_PLACE) {
+ KMessageBox::sorry(m_gmicWidget,QString("Sorry, this output mode is not implemented"),"Krita");
+ return false;
+ }
+
+ if (layers->isEmpty()) {
+ KMessageBox::sorry(m_gmicWidget, i18n("Sorry, this input mode is not implemented"), i18n("Krita"));
+ return false;
+ }
+
+ return true;
+}
#include "kis_gmic_plugin.moc"
+
diff --git a/krita/plugins/extensions/gmic/kis_gmic_plugin.h b/krita/plugins/extensions/gmic/kis_gmic_plugin.h
index aeb7e05..d9f62d2 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_plugin.h
+++ b/krita/plugins/extensions/gmic/kis_gmic_plugin.h
@@ -25,6 +25,8 @@
#include "kis_gmic_parser.h"
#include <kis_types.h>
+class QSize;
+class QRect;
class KisGmicApplicator;
class KisGmicWidget;
@@ -35,9 +37,28 @@ public:
KisGmicPlugin(QObject *parent, const QVariantList &);
virtual ~KisGmicPlugin();
+private slots:
+ // life cycle: show -> close
+ void slotShowGmicDialog();
+ void slotCloseGmicDialog();
+
+ void slotPreviewGmicCommand(KisGmicFilterSetting* setting);
+ void slotFilterCurrentImage(KisGmicFilterSetting* setting);
+ void slotCancelOnCanvasPreview();
+ void slotAcceptOnCanvasPreview();
+ void slotPreviewActiveLayer();
+
private:
void parseGmicCommandDefinitions(const QStringList &gmicDefinitionFilePaths);
void setupDefinitionPaths();
+ static KisNodeListSP createPreviewThumbnails(KisNodeListSP layers,const QSize &dstSize,const QRect &srcRect);
+ void createViewportPreview(KisNodeListSP layers, KisGmicFilterSetting* setting);
+ // has to be accepted or cancelled!
+ void startOnCanvasPreview(KisNodeListSP layers, KisGmicFilterSetting* setting);
+ bool checkSettingsValidity(KisNodeListSP layers, const KisGmicFilterSetting * setting);
+
+ // TODO: refactor into responsible classes
+ void showInPreviewViewport(KisPaintDeviceSP device);
private:
KisGmicWidget * m_gmicWidget;
@@ -45,11 +66,7 @@ private:
QStringList m_definitionFilePaths;
QString m_blacklistPath;
QByteArray m_gmicCustomCommands;
-
-private slots:
- void slotGmic();
- void slotApplyGmicCommand(KisGmicFilterSetting* setting);
- void slotClose();
+ bool m_previewFilter;
};
#endif
diff --git a/krita/plugins/extensions/gmic/kis_gmic_settings_widget.cpp b/krita/plugins/extensions/gmic/kis_gmic_settings_widget.cpp
index eb343c3..36a9a7e 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_settings_widget.cpp
+++ b/krita/plugins/extensions/gmic/kis_gmic_settings_widget.cpp
@@ -27,8 +27,9 @@
#include <kfiledialog.h> // For kurlrequester...
-KisGmicSettingsWidget::KisGmicSettingsWidget(Command * command):
- m_commandDefinition(command)
+KisGmicSettingsWidget::KisGmicSettingsWidget(Command * command)
+ : KisConfigWidget(0, 0, 250),
+ m_commandDefinition(command)
{
createSettingsWidget(CreateRole);
}
@@ -453,7 +454,6 @@ void KisGmicSettingsWidget::createSettingsWidget(ROLE role)
{
setLayout(gridLayout);
}
- setMinimumSize(sizeHint());
}
Command* KisGmicSettingsWidget::currentCommandSettings()
diff --git a/krita/plugins/extensions/gmic/kis_gmic_synchronize_layers_command.cpp b/krita/plugins/extensions/gmic/kis_gmic_synchronize_layers_command.cpp
index 5d8323a..33b91fe 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_synchronize_layers_command.cpp
+++ b/krita/plugins/extensions/gmic/kis_gmic_synchronize_layers_command.cpp
@@ -38,18 +38,30 @@ void KisGmicSynchronizeLayersCommand::redo()
// if gmic produces more layers
if (m_nodes->size() < int(m_images->_width))
{
- for (unsigned int i = m_nodes->size(); i < m_images->_width; i++)
- {
- KisPaintDevice * device = new KisPaintDevice(m_image->colorSpace());
- KisLayerSP paintLayer = new KisPaintLayer(m_image, "New layer from gmic filter", OPACITY_OPAQUE_U8, device);
- m_nodes->append(paintLayer);
- m_image->addNode(paintLayer, m_nodes->at(0)->parent());
- dbgPlugins << "Added new layer";
- }
+ if (m_image)
+ {
+ for (unsigned int i = m_nodes->size(); i < m_images->_width; i++)
+ {
+ KisPaintDevice * device = new KisPaintDevice(m_image->colorSpace());
+ KisLayerSP paintLayer = new KisPaintLayer(m_image, "New layer from gmic filter", OPACITY_OPAQUE_U8, device);
+ m_nodes->append(paintLayer);
- // would sleep(5) here help?
+ m_image->addNode(paintLayer, m_nodes->at(0)->parent());
+ dbgPlugins << "Added new layer";
+ }
+ }
+ else
+ {
+ Q_ASSERT(m_nodes->size() > 0);
+ for (unsigned int i = m_nodes->size(); i < m_images->_width; i++)
+ {
+ KisPaintDevice * device = new KisPaintDevice(m_nodes->at(0)->colorSpace());
+ KisLayerSP paintLayer = new KisPaintLayer(0, "New layer from gmic filter", OPACITY_OPAQUE_U8, device);
+ m_nodes->append(paintLayer);
+ }
+ }
} // if gmic produces less layers, we are going to drop some
else if (m_nodes->size() > int(m_images->_width))
{
@@ -58,13 +70,12 @@ void KisGmicSynchronizeLayersCommand::redo()
}
else
{
- // really?
- // KUndo2Command::undo();
- dbgPlugins << "Undo needed?";
+ dbgPlugins << "Redo again needed?";
}
}
void KisGmicSynchronizeLayersCommand::undo()
{
// do nothing?
+ dbgPlugins << "Not implemented";
}
diff --git a/krita/plugins/extensions/gmic/kis_gmic_updater.cpp b/krita/plugins/extensions/gmic/kis_gmic_updater.cpp
index 5353899..219295f 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_updater.cpp
+++ b/krita/plugins/extensions/gmic/kis_gmic_updater.cpp
@@ -22,7 +22,6 @@
#include <QFile>
#include <QNetworkRequest>
#include <qsslerror.h>
-#include <QDebug>
#include <QTimer>
#include <kis_debug.h>
@@ -77,23 +76,6 @@ void KisGmicUpdater::finishedDownload(QNetworkReply*reply)
QString path = KGlobal::mainComponent().dirs()->saveLocation("gmic_definitions");
QString fileName = reply->url().path().split("/").last();;
- /* TODO: optimize based on ETag, do not redownload if not necessery
- * also try to check Content-Type but so far cimgz report wrongly plain text
- if (reply->hasRawHeader("Content-Type"))
- {
- QString contentType = reply->rawHeader("Content-Type");
- }
-
- int i = 0;
- foreach (const QByteArray &array, reply->rawHeaderList())
- {
- ++i;
- qDebug() << i << " " << QString(array);
- }
-
- */
-
-
QByteArray data = reply->readAll();
QString tmpfilePath = path + fileName + QString(".cimgz");
diff --git a/krita/plugins/extensions/gmic/kis_gmic_widget.cpp b/krita/plugins/extensions/gmic/kis_gmic_widget.cpp
index 3703250..b285e86 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_widget.cpp
+++ b/krita/plugins/extensions/gmic/kis_gmic_widget.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 Lukáš Tvrdý <lukast.dev at gmail.com>
+ * Copyright (c) 2013-2014 Lukáš Tvrdý <lukast.dev at gmail.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
@@ -38,47 +38,49 @@
#include <kis_gmic_filter_proxy_model.h>
#include "kis_gmic_updater.h"
+
static const QString maximizeStr = i18n("Maximize");
+static const QString selectFilterStr = i18n("Select a filter...");
-KisGmicWidget::KisGmicWidget(KisGmicFilterModel * filters, const QString &updateUrl): QWidget(),m_filterModel(filters),m_updateUrl(updateUrl)
+KisGmicWidget::KisGmicWidget(KisGmicFilterModel * filters, const QString &updateUrl): m_filterModel(filters),m_updateUrl(updateUrl)
{
+ dbgPlugins << "Constructor:" << this;
+
+ setupUi(this);
createMainLayout();
setAttribute(Qt::WA_DeleteOnClose, true);
+
+ m_filterApplied = false;
+ m_onCanvasPreviewActivated = false;
+ m_onCanvasPreviewRequested = false;
}
KisGmicWidget::~KisGmicWidget()
{
- dbgPlugins << "I'm dying...";
+ dbgPlugins << "Destructor:" << this;
delete m_filterModel;
}
void KisGmicWidget::createMainLayout()
{
- m_filterConfigLayout = new QGridLayout;
- int column = 0;
- int row = 0;
- m_inputOutputOptions = new KisGmicInputOutputWidget();
- m_filterConfigLayout->addWidget(m_inputOutputOptions, row, column);
- column++;
- m_filterTree = new QTreeView();
+ connect(m_inputOutputOptions->previewCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotPreviewChanged(bool)));
+ connect(m_inputOutputOptions->previewSizeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(slotPreviewSizeChanged()));
+ connect(m_inputOutputOptions->previewSizeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(slotConfigurationChanged()));
+
+ connect(m_inputOutputOptions->zoomInButton, SIGNAL(clicked(bool)), this, SLOT(slotNotImplemented()));
+ connect(m_inputOutputOptions->zoomOutButton, SIGNAL(clicked(bool)), this, SLOT(slotNotImplemented()));
KisGmicFilterProxyModel *proxyModel = new KisGmicFilterProxyModel(this);
proxyModel->setSourceModel(m_filterModel);
proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
-
m_filterTree->setModel(proxyModel);
m_filterTree->setItemDelegate(new HtmlDelegate());
- QItemSelectionModel *selectionModel= m_filterTree->selectionModel();
- connect(selectionModel, SIGNAL(selectionChanged (const QItemSelection &, const QItemSelection &)),
- this, SLOT(selectionChangedSlot(const QItemSelection &, const QItemSelection &)));
-
- m_filterConfigLayout->addWidget(m_filterTree, row, column);
+ connect(m_filterTree->selectionModel(), SIGNAL(selectionChanged (const QItemSelection &, const QItemSelection &)),
+ this, SLOT(slotSelectedFilterChanged(const QItemSelection &, const QItemSelection &)));
- QPushButton * updateBtn = new QPushButton(this);
- updateBtn->setText("Update definitions");
if (!m_updateUrl.isEmpty())
{
updateBtn->setToolTip("Fetching definitions from : " + m_updateUrl);
@@ -87,50 +89,28 @@ void KisGmicWidget::createMainLayout()
{
updateBtn->setEnabled(false);
}
- connect(updateBtn, SIGNAL(clicked(bool)), this, SLOT(startUpdate()));
- m_filterConfigLayout->addWidget(updateBtn, row+1, column);
- QLineEdit * searchBox = new QLineEdit(this);
+ connect(updateBtn, SIGNAL(clicked(bool)), this, SLOT(startUpdate()));
connect(searchBox, SIGNAL(textChanged(QString)), proxyModel, SLOT(setFilterFixedString(QString)));
- m_filterConfigLayout->addWidget(searchBox, row+2, column);
- column++;
-
- m_filterOptions = new QWidget();
- m_filterConfigLayout->addWidget(m_filterOptions,row, column);
- m_filterConfigLayout->setColumnStretch(column, 1);
- m_filterOptionsRow = row;
- m_filterOptionsColumn = column;
-
- QDialogButtonBox * controlButtonBox = new QDialogButtonBox;
QPushButton * maximize = new QPushButton(maximizeStr);
- connect(maximize, SIGNAL(clicked(bool)), this, SLOT(maximizeSlot()));
-
- controlButtonBox->addButton(maximize, QDialogButtonBox::AcceptRole);
- controlButtonBox->addButton(QDialogButtonBox::Ok);
- QAbstractButton *okButton = controlButtonBox->button(QDialogButtonBox::Ok);
- connect(okButton, SIGNAL(clicked(bool)), this, SLOT(okFilterSlot()));
-
- controlButtonBox->addButton(QDialogButtonBox::Apply);
- QAbstractButton *applyButton = controlButtonBox->button(QDialogButtonBox::Apply);
- connect(applyButton, SIGNAL(clicked(bool)), this, SLOT(applyFilterSlot()));
-
- controlButtonBox->addButton(QDialogButtonBox::Cancel);
- QAbstractButton *cancelButton = controlButtonBox->button(QDialogButtonBox::Cancel);
- connect(cancelButton, SIGNAL(clicked(bool)), this, SLOT(cancelFilterSlot()));
-
- controlButtonBox->addButton(QDialogButtonBox::Reset);
- QAbstractButton *resetButton = controlButtonBox->button(QDialogButtonBox::Reset);
- connect(resetButton, SIGNAL(clicked(bool)), this, SLOT(resetFilterSlot()));
-
- m_filterConfigLayout->addWidget(controlButtonBox,row + 1, column, 1, 2);
- column++;
-
- setLayout(m_filterConfigLayout);
+ controlButtonBox->addButton(maximize, QDialogButtonBox::ActionRole);
+ connect(maximize, SIGNAL(clicked(bool)), this, SLOT(slotMaximizeClicked()));
+ connect(controlButtonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked(bool)), this, SLOT(slotOkClicked()));
+ connect(controlButtonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked(bool)), this, SLOT(slotApplyClicked()));
+ connect(controlButtonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked(bool)), this, SLOT(slotCancelClicked()));
+ connect(controlButtonBox->button(QDialogButtonBox::Reset), SIGNAL(clicked(bool)), this, SLOT(slotResetClicked()));
+
+ int indexOfFilterOptions = m_filterConfigLayout->indexOf(m_filterOptions);
+ Q_ASSERT(indexOfFilterOptions != -1);
+ int rowSpan = 0, colSpan = 0;
+ m_filterConfigLayout->getItemPosition(indexOfFilterOptions, &m_filterOptionsRow, &m_filterOptionsColumn, &rowSpan, &colSpan);
+
+ switchOptionsWidgetFor(new QLabel(selectFilterStr));
}
-void KisGmicWidget::selectionChangedSlot(const QItemSelection & /*newSelection*/, const QItemSelection & /*oldSelection*/)
+void KisGmicWidget::slotSelectedFilterChanged(const QItemSelection & /*newSelection*/, const QItemSelection & /*oldSelection*/)
{
//get the text of the selected item
const QModelIndex index = m_filterTree->selectionModel()->currentIndex();
@@ -150,78 +130,78 @@ void KisGmicWidget::selectionChangedSlot(const QItemSelection & /*newSelection*/
gmicCommand = var.value<Command *>();
}
- m_filterConfigLayout->removeWidget(m_filterOptions);
- delete m_filterOptions;
if (gmicCommand)
{
- m_filterOptions = new KisGmicSettingsWidget(gmicCommand);
+ KisGmicSettingsWidget * filterOptions = new KisGmicSettingsWidget(gmicCommand);
+ QObject::connect(filterOptions, SIGNAL(sigConfigurationUpdated()), this, SLOT(slotConfigurationChanged()));
+ switchOptionsWidgetFor(filterOptions);
}
else
{
- m_filterOptions = new QLabel("Select a filter...");
+ switchOptionsWidgetFor(new QLabel(selectFilterStr));
+ emit sigPreviewActiveLayer();
}
- m_filterConfigLayout->addWidget(m_filterOptions,m_filterOptionsRow,m_filterOptionsColumn);
- m_filterConfigLayout->update();
+
+#ifdef DEBUG_MODEL
//find out the hierarchy level of the selected item
- int hierarchyLevel=1;
+ int hierarchyLevel = 1;
QModelIndex seekRoot = index;
while(seekRoot.parent() != QModelIndex())
{
seekRoot = seekRoot.parent();
hierarchyLevel++;
}
+
QString showString = QString("%1, Level %2").arg(selectedText)
.arg(hierarchyLevel);
setWindowTitle(showString);
-
- resize(sizeHint());
+#endif
}
-void KisGmicWidget::applyFilterSlot()
+
+void KisGmicWidget::slotCancelClicked()
{
- const QModelIndex index = m_filterTree->selectionModel()->currentIndex();
- QVariant settings = index.data(FilterSettingsRole);
- if (settings.isValid())
+ if (m_inputOutputOptions->previewSize() == ON_CANVAS)
{
- KisGmicFilterSetting * filterSettings = settings.value<KisGmicFilterSetting * >();
- filterSettings->setInputLayerMode(m_inputOutputOptions->inputMode());
- filterSettings->setOutputMode(m_inputOutputOptions->outputMode());
+ emit sigCancelOnCanvasPreview();
+ }
+ close();
+}
- dbgPlugins << "Valid settings!";
- dbgPlugins << "GMIC command : " << filterSettings->gmicCommand();
- emit sigApplyCommand(filterSettings);
+void KisGmicWidget::slotOkClicked()
+{
+ if (m_inputOutputOptions->previewSize() == ON_CANVAS)
+ {
+ emit sigAcceptOnCanvasPreview();
}
else
{
- dbgPlugins << "Filter is not selected!";
+ if (!m_filterApplied)
+ {
+ KisGmicFilterSetting * filterSettings = currentFilterSettings();
+ if (filterSettings)
+ {
+ emit sigFilterCurrentImage(filterSettings);
+ }
+ m_filterApplied = true;
+ }
}
-}
-
-void KisGmicWidget::cancelFilterSlot()
-{
- emit sigClose();
-}
-
-
-void KisGmicWidget::okFilterSlot()
-{
- applyFilterSlot();
- emit sigClose();
+ close();
}
void KisGmicWidget::closeEvent(QCloseEvent *event)
{
- emit sigClose();
event->accept();
+ emit sigClose();
}
-void KisGmicWidget::resetFilterSlot()
+void KisGmicWidget::slotResetClicked()
{
const QModelIndex index = m_filterTree->selectionModel()->currentIndex();
QVariant var = index.data(CommandRole);
@@ -243,10 +223,10 @@ void KisGmicWidget::resetFilterSlot()
{
currentSettingsWidget->reload();
}
- resize(sizeHint());
+
}
-void KisGmicWidget::maximizeSlot()
+void KisGmicWidget::slotMaximizeClicked()
{
QPushButton * maximizeButton = qobject_cast<QPushButton *>(sender());
if (!maximizeButton)
@@ -283,3 +263,153 @@ void KisGmicWidget::finishUpdate()
"Restart G'MIC dialog to finish updating! ");
KMessageBox::information(this, msg, i18nc("@title:window", "Updated"));
}
+
+void KisGmicWidget::slotPreviewChanged(bool enabling)
+{
+ if (enabling)
+ {
+ requestComputePreview();
+ }
+ else
+ {
+ if (m_inputOutputOptions->previewSize() == ON_CANVAS)
+ {
+ emit sigCancelOnCanvasPreview();
+ m_onCanvasPreviewRequested = false; // cancelled
+ }
+ else
+ {
+ emit sigPreviewActiveLayer();
+ }
+ }
+
+}
+
+void KisGmicWidget::slotPreviewSizeChanged()
+{
+ if (m_inputOutputOptions->previewSize() == ON_CANVAS)
+ {
+ m_onCanvasPreviewActivated = true;
+ }
+ else
+ {
+ if (m_onCanvasPreviewActivated)
+ {
+ emit sigCancelOnCanvasPreview();
+ m_onCanvasPreviewActivated = false;
+ m_onCanvasPreviewRequested = false;
+ }
+ }
+}
+
+
+void KisGmicWidget::slotConfigurationChanged()
+{
+ if (m_inputOutputOptions->previewCheckBox->isChecked())
+ {
+ requestComputePreview();
+ }
+ else
+ {
+ emit sigPreviewActiveLayer();
+ }
+
+}
+
+void KisGmicWidget::slotApplyClicked()
+{
+ if (m_inputOutputOptions->previewSize() == ON_CANVAS)
+ {
+ KisGmicFilterSetting * filterSettings = currentFilterSettings();
+ if (!filterSettings)
+ {
+ return;
+ }
+
+ if (m_inputOutputOptions->previewCheckBox->isChecked())
+ {
+ emit sigAcceptOnCanvasPreview();
+ emit sigPreviewFilterCommand(filterSettings);
+ }
+ else
+ {
+ emit sigFilterCurrentImage(filterSettings);
+ m_filterApplied = true;
+ }
+
+
+ }
+ else // Tiny, Small, Medium, Large preview
+ {
+
+ KisGmicFilterSetting * filterSettings = currentFilterSettings();
+ if (filterSettings)
+ {
+ emit sigFilterCurrentImage(filterSettings);
+ m_filterApplied = true;
+ requestComputePreview();
+ }
+ }
+}
+
+KisGmicFilterSetting* KisGmicWidget::currentFilterSettings()
+{
+ KisGmicFilterSetting * filterSettings = 0;
+ QVariant settings = m_filterTree->selectionModel()->currentIndex().data(FilterSettingsRole);
+ if (settings.isValid())
+ {
+ dbgPlugins << "Valid settings!";
+ filterSettings = settings.value<KisGmicFilterSetting * >();
+ filterSettings->setInputLayerMode(m_inputOutputOptions->inputMode());
+ filterSettings->setOutputMode(m_inputOutputOptions->outputMode());
+ filterSettings->setPreviewMode(m_inputOutputOptions->previewMode());
+ filterSettings->setPreviewSize(m_inputOutputOptions->previewSize());
+ dbgPlugins << "GMIC command : " << filterSettings->gmicCommand();
+ dbgPlugins << "GMIC preview command : " << filterSettings->previewGmicCommand();
+ }
+ else
+ {
+ dbgPlugins << "Filter is not selected!";
+ }
+
+ return filterSettings;
+}
+
+void KisGmicWidget::requestComputePreview()
+{
+ KisGmicFilterSetting * filterSettings = currentFilterSettings();
+ if (filterSettings)
+ {
+ emit sigPreviewFilterCommand(filterSettings);
+ if (m_onCanvasPreviewActivated)
+ {
+ m_onCanvasPreviewRequested = true;
+ }
+ }
+ else
+ {
+ emit sigPreviewActiveLayer();
+ }
+}
+
+void KisGmicWidget::switchOptionsWidgetFor(QWidget* widget)
+{
+ m_filterConfigLayout->removeWidget(m_filterOptions);
+ delete m_filterOptions;
+
+ m_filterOptions = widget;
+
+ m_filterConfigLayout->addWidget(m_filterOptions, m_filterOptionsRow, m_filterOptionsColumn);
+ m_filterConfigLayout->update();
+
+}
+
+KisFilterPreviewWidget * KisGmicWidget::previewWidget()
+{
+ return m_inputOutputOptions->previewWidget();
+}
+
+void KisGmicWidget::slotNotImplemented()
+{
+ KMessageBox::sorry(this, i18n("Sorry, support not implemented yet."), i18n("Krita"));
+}
diff --git a/krita/plugins/extensions/gmic/kis_gmic_widget.h b/krita/plugins/extensions/gmic/kis_gmic_widget.h
index 73ebe42..1a87d69 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_widget.h
+++ b/krita/plugins/extensions/gmic/kis_gmic_widget.h
@@ -20,15 +20,18 @@
#include <QTreeView>
#include <QGridLayout>
+#include <QCheckBox>
#include "kis_gmic_filter_model.h"
#include "kis_gmic_filter_settings.h"
+#include "ui_wdg_gmic.h"
+
class KisGmicUpdater;
class QCloseEvent;
class KisGmicInputOutputWidget;
class QPushButton;
-class KisGmicWidget : public QWidget
+class KisGmicWidget : public QWidget, public Ui::WdgGmic
{
Q_OBJECT
@@ -37,30 +40,46 @@ public:
KisGmicWidget(KisGmicFilterModel * filters, const QString &updateUrl = QString());
~KisGmicWidget();
+ KisFilterPreviewWidget * previewWidget();
+
void createMainLayout();
virtual void closeEvent(QCloseEvent* );
signals:
- void sigApplyCommand(KisGmicFilterSetting * setting);
+ void sigFilterCurrentImage(KisGmicFilterSetting * setting); //TODO:const
+ void sigPreviewFilterCommand(KisGmicFilterSetting * setting); //TODO:const
+ void sigAcceptOnCanvasPreview();
+ void sigCancelOnCanvasPreview();
+ void sigPreviewActiveLayer();
void sigClose();
private slots:
- void selectionChangedSlot(const QItemSelection & newSelection, const QItemSelection & oldSelection);
- void applyFilterSlot();
- void resetFilterSlot();
- void okFilterSlot();
- void maximizeSlot();
- void cancelFilterSlot();
+ void slotSelectedFilterChanged(const QItemSelection & newSelection, const QItemSelection & oldSelection);
+ // buttons
+ void slotApplyClicked();
+ void slotOkClicked();
+ void slotCancelClicked();
+ void slotResetClicked();
+ void slotMaximizeClicked();
+
+ // internet updates slots
void startUpdate();
void finishUpdate();
+ // preview
+ void slotPreviewChanged(bool enabling);
+ void slotPreviewSizeChanged();
+ void slotConfigurationChanged();
+ void slotNotImplemented();
+
private:
- QGridLayout * m_filterConfigLayout;
+ KisGmicFilterSetting * currentFilterSettings();
+ void requestComputePreview();
+ void switchOptionsWidgetFor(QWidget * widget);
- QTreeView * m_filterTree;
- QWidget * m_filterOptions;
- KisGmicInputOutputWidget * m_inputOutputOptions;
+
+private:
KisGmicFilterModel * m_filterModel;
KisGmicUpdater * m_updater;
@@ -68,6 +87,10 @@ private:
int m_filterOptionsRow;
int m_filterOptionsColumn;
+
+ bool m_filterApplied;
+ bool m_onCanvasPreviewActivated;
+ bool m_onCanvasPreviewRequested;
};
#endif
diff --git a/krita/plugins/extensions/gmic/kis_import_gmic_processing_visitor.cpp b/krita/plugins/extensions/gmic/kis_import_gmic_processing_visitor.cpp
index a55e772..ddd14ed 100644
--- a/krita/plugins/extensions/gmic/kis_import_gmic_processing_visitor.cpp
+++ b/krita/plugins/extensions/gmic/kis_import_gmic_processing_visitor.cpp
@@ -62,7 +62,13 @@ void KisImportGmicProcessingVisitor::visitNodeWithPaintDevice(KisNode *node, Kis
{
KisGmicSimpleConvertor::convertFromGmicFast(m_images->_data[index], dst, 255.0f);
}
- transaction.commit(undoAdapter);
+
+ if (undoAdapter)
+ {
+ transaction.commit(undoAdapter);
+ node->setDirty(m_dstRect);
+ }
+
}
}
diff --git a/krita/plugins/extensions/gmic/kis_input_output_mapper.cpp b/krita/plugins/extensions/gmic/kis_input_output_mapper.cpp
index 5e9d9e4..3b9552e 100644
--- a/krita/plugins/extensions/gmic/kis_input_output_mapper.cpp
+++ b/krita/plugins/extensions/gmic/kis_input_output_mapper.cpp
@@ -61,6 +61,7 @@ KisNodeListSP KisInputOutputMapper::inputNodes(InputLayerMode inputMode)
result->append(m_activeNode->nextSibling());
break;
}
+ case NONE:
case ALL_VISIBLE_LAYERS:
case ALL_INVISIBLE_LAYERS:
case ALL_VISIBLE_LAYERS_DECR:
@@ -77,6 +78,7 @@ KisNodeListSP KisInputOutputMapper::inputNodes(InputLayerMode inputMode)
case ALL_DECR:
{
allInversedOrderedLayers(result);
+ break;
}
default:
{
diff --git a/krita/plugins/extensions/gmic/tests/kis_gmic_tests.cpp b/krita/plugins/extensions/gmic/tests/kis_gmic_tests.cpp
index 393d728..efd2df5 100644
--- a/krita/plugins/extensions/gmic/tests/kis_gmic_tests.cpp
+++ b/krita/plugins/extensions/gmic/tests/kis_gmic_tests.cpp
@@ -590,8 +590,8 @@ void KisGmicTests::testFilterOnlySelection()
KisGmicApplicator applicator;
applicator.setProperties(image, image->root(), kundo2_noi18n("Gmic filter"), kritaNodes, gmicCommand);
- applicator.start();
- applicator.wait();
+ applicator.preview();
+ applicator.finish();
image->waitForDone();
//image->convertToQImage(image->bounds(), 0).save("filteredSelection.png");
diff --git a/krita/plugins/extensions/gmic/wdg_gmic.ui b/krita/plugins/extensions/gmic/wdg_gmic.ui
index e8018d8..021955b 100644
--- a/krita/plugins/extensions/gmic/wdg_gmic.ui
+++ b/krita/plugins/extensions/gmic/wdg_gmic.ui
@@ -6,40 +6,83 @@
<rect>
<x>0</x>
<y>0</y>
- <width>503</width>
- <height>356</height>
+ <width>610</width>
+ <height>478</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>G'Mic string:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="txtGmic"/>
- </item>
- <item row="1" column="1">
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
+ <layout class="QGridLayout" name="m_filterConfigLayout" columnstretch="1,2,2,1">
+ <item row="0" column="0" rowspan="3" alignment="Qt::AlignLeft">
+ <widget class="KisGmicInputOutputWidget" name="m_inputOutputOptions" native="true"/>
+ </item>
+ <item row="0" column="1">
+ <widget class="QTreeView" name="m_filterTree">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="updateBtn">
+ <property name="text">
+ <string>Update definitions</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="searchLbl">
+ <property name="text">
+ <string>Search:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="searchBox"/>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="2" colspan="2">
+ <widget class="QDialogButtonBox" name="controlButtonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" colspan="2">
+ <widget class="QWidget" name="m_filterOptions" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
+ <customwidgets>
+ <customwidget>
+ <class>KisGmicInputOutputWidget</class>
+ <extends>QWidget</extends>
+ <header>kis_gmic_input_output_widget.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
<resources/>
<connections/>
</ui>
diff --git a/krita/plugins/extensions/gmic/wdg_gmic_input_output.ui b/krita/plugins/extensions/gmic/wdg_gmic_input_output.ui
new file mode 100644
index 0000000..22023fa
--- /dev/null
+++ b/krita/plugins/extensions/gmic/wdg_gmic_input_output.ui
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WdgGmicInputOutput</class>
+ <widget class="QWidget" name="WdgGmicInputOutput">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0" colspan="2">
+ <widget class="KisFilterPreviewWidget" name="previewViewport" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="previewCheckBox">
+ <property name="text">
+ <string>Preview</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="zoomInButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Zoom In</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="zoomOutButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip">
+ <string>Zoom Out</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="inputLayerLabel">
+ <property name="text">
+ <string>Input</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="inputCombo"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="outputLayerLabel">
+ <property name="text">
+ <string>Output</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="outputCombo"/>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="outputPreviewLabel">
+ <property name="text">
+ <string>Preview mode</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QComboBox" name="outputPreviewCombo"/>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="previewSizeLabel">
+ <property name="text">
+ <string>Preview size</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QComboBox" name="previewSizeCombo"/>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>KisFilterPreviewWidget</class>
+ <extends>QWidget</extends>
+ <header>kis_filter_preview_widget.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
More information about the kimageshop
mailing list