diff --git a/libs/libqml/plugins/kritasketchplugin/models/CompositeOpModel.cpp b/libs/libqml/plugins/kritasketchplugin/models/CompositeOpModel.cpp index 9ad9f70f2e..c0f8cb65ab 100644 --- a/libs/libqml/plugins/kritasketchplugin/models/CompositeOpModel.cpp +++ b/libs/libqml/plugins/kritasketchplugin/models/CompositeOpModel.cpp @@ -1,482 +1,482 @@ /* Copyright (C) 2012 Dan Leinir Turthra Jensen 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 of the License, 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "CompositeOpModel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class CompositeOpModel::Private { public: Private(CompositeOpModel* qq) : q(qq) , model(KisCompositeOpListModel::sharedInstance()) , view(0) , eraserMode(0) , opacity(0) , opacityEnabled(false) , flow(0) , flowEnabled(false) , size(0) , sizeEnabled(false) , presetsEnabled(true) {}; CompositeOpModel* q; KisCompositeOpListModel* model; KisViewManager* view; QString currentCompositeOpID; QString prevCompositeOpID; bool eraserMode; QMap settingsWidgets; qreal opacity; bool opacityEnabled; qreal flow; bool flowEnabled; qreal size; bool sizeEnabled; bool presetsEnabled; KisPaintOpPresetSP currentPreset; void updateCompositeOp(QString compositeOpID) { if (!view) return; KisNodeSP node = view->resourceProvider()->currentNode(); if (node && node->paintDevice()) { if (!node->paintDevice()->colorSpace()->hasCompositeOp(compositeOpID)) compositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id(); if (compositeOpID != currentCompositeOpID) { q->setEraserMode(compositeOpID == COMPOSITE_ERASE); currentPreset->settings()->setProperty("CompositeOp", compositeOpID); //m_optionWidget->setConfiguration(m_activePreset->settings().data()); view->resourceProvider()->setCurrentCompositeOp(compositeOpID); prevCompositeOpID = currentCompositeOpID; currentCompositeOpID = compositeOpID; } } emit q->currentCompositeOpIDChanged(); } void ofsChanged() { if (presetsEnabled && !currentPreset.isNull() && !currentPreset->settings().isNull()) { // IMPORTANT: set the PaintOp size before setting the other properties // it wont work the other way - qreal sizeDiff = size - currentPreset->settings()->paintOpSize(); + //qreal sizeDiff = size - currentPreset->settings()->paintOpSize(); //currentPreset->settings()->changePaintOpSize(sizeDiff, 0); if (currentPreset->settings()->hasProperty("OpacityValue")) currentPreset->settings()->setProperty("OpacityValue", opacity); if (currentPreset->settings()->hasProperty("FlowValue")) currentPreset->settings()->setProperty("FlowValue", flow); //m_optionWidget->setConfiguration(d->currentPreset->settings().data()); } if (view) { view->resourceProvider()->setOpacity(opacity); } } }; CompositeOpModel::CompositeOpModel(QObject* parent) : QAbstractListModel(parent) , d(new Private(this)) { connect(KoToolManager::instance(), SIGNAL(changedTool(KoCanvasController*,int)), this, SLOT(slotToolChanged(KoCanvasController*,int))); } CompositeOpModel::~CompositeOpModel() { delete d; } QHash CompositeOpModel::roleNames() const { QHash roles; roles[TextRole] = "text"; roles[IsCategoryRole] = "isCategory"; return roles; } QVariant CompositeOpModel::data(const QModelIndex& index, int role) const { QVariant data; if (index.isValid()) { QModelIndex otherIndex = d->model->index(index.row(), index.column(), QModelIndex()); switch(role) { case TextRole: data = d->model->data(otherIndex, Qt::DisplayRole); break; case IsCategoryRole: data = d->model->data(otherIndex, __CategorizedListModelBase::IsHeaderRole); break; default: break; } } return data; } int CompositeOpModel::rowCount(const QModelIndex& parent) const { if (parent.isValid()) return 0; return d->model->rowCount(QModelIndex()); } void CompositeOpModel::activateItem(int index) { if (index > -1 && index < d->model->rowCount(QModelIndex())) { KoID compositeOp; if (d->model->entryAt(compositeOp, d->model->index(index))) d->updateCompositeOp(compositeOp.id()); } } QObject* CompositeOpModel::view() const { return d->view; } void CompositeOpModel::setView(QObject* newView) { if (d->view) { d->view->canvasBase()->disconnect(this); d->view->canvasBase()->globalInputManager()->disconnect(this); d->view->nodeManager()->disconnect(this); } d->view = qobject_cast( newView ); if (d->view) { if (d->view->canvasBase() && d->view->canvasBase()->resourceManager()) { connect(d->view->canvasBase()->resourceManager(), SIGNAL(canvasResourceChanged(int, const QVariant&)), this, SLOT(resourceChanged(int, const QVariant&))); } if (d->view->nodeManager()) { connect(d->view->nodeManager(), SIGNAL(sigLayerActivated(KisLayerSP)), this, SLOT(currentNodeChanged(KisLayerSP))); } slotToolChanged(0, 0); } emit viewChanged(); } bool CompositeOpModel::eraserMode() const { return d->eraserMode; } void CompositeOpModel::setEraserMode(bool newEraserMode) { if (d->eraserMode != newEraserMode) { d->eraserMode = newEraserMode; if (d->eraserMode) d->updateCompositeOp(COMPOSITE_ERASE); else d->updateCompositeOp(d->prevCompositeOpID); emit eraserModeChanged(); } } qreal CompositeOpModel::flow() const { return d->flow; } void CompositeOpModel::setFlow(qreal newFlow) { if (d->flow != newFlow) { d->flow = newFlow; d->ofsChanged(); emit flowChanged(); } } bool CompositeOpModel::flowEnabled() const { return d->flowEnabled; } void CompositeOpModel::setFlowEnabled(bool newFlowEnabled) { d->flowEnabled = newFlowEnabled; emit flowEnabledChanged(); } qreal CompositeOpModel::opacity() const { return d->opacity; } void CompositeOpModel::setOpacity(qreal newOpacity) { if (d->opacity != newOpacity) { d->opacity = newOpacity; d->ofsChanged(); emit opacityChanged(); } } bool CompositeOpModel::opacityEnabled() const { return d->opacityEnabled; } void CompositeOpModel::setOpacityEnabled(bool newOpacityEnabled) { d->opacityEnabled = newOpacityEnabled; emit opacityEnabledChanged(); } qreal CompositeOpModel::size() const { return d->size; } void CompositeOpModel::setSize(qreal newSize) { if (d->size != newSize) { d->size = newSize; d->ofsChanged(); emit sizeChanged(); } } bool CompositeOpModel::sizeEnabled() const { return d->sizeEnabled; } void CompositeOpModel::setSizeEnabled(bool newSizeEnabled) { d->sizeEnabled = newSizeEnabled; emit sizeEnabledChanged(); } void CompositeOpModel::changePaintopValue(QString propertyName, QVariant value) { if (propertyName == "size" && value.toReal() != d->size) setSize(value.toReal()); else if (propertyName == "opacity" && value.toReal() != d->opacity) setOpacity(value.toReal()); else if (propertyName == "flow" && value.toReal() != d->flow) setFlow(value.toReal()); } bool CompositeOpModel::mirrorHorizontally() const { if (d->view) return d->view->resourceProvider()->mirrorHorizontal(); return false; } void CompositeOpModel::setMirrorHorizontally(bool newMirrorHorizontally) { if (d->view && d->view->resourceProvider()->mirrorHorizontal() != newMirrorHorizontally) { d->view->resourceProvider()->setMirrorHorizontal(newMirrorHorizontally); emit mirrorHorizontallyChanged(); } } bool CompositeOpModel::mirrorVertically() const { if (d->view) return d->view->resourceProvider()->mirrorVertical(); return false; } void CompositeOpModel::setMirrorVertically(bool newMirrorVertically) { if (d->view && d->view->resourceProvider()->mirrorVertical() != newMirrorVertically) { d->view->resourceProvider()->setMirrorVertical(newMirrorVertically); emit mirrorVerticallyChanged(); } } void CompositeOpModel::slotToolChanged(KoCanvasController* canvas, int toolId) { Q_UNUSED(canvas); Q_UNUSED(toolId); if (!d->view) return; if (!d->view->canvasBase()) return; QString id = KoToolManager::instance()->activeToolId(); KisTool* tool = dynamic_cast(KoToolManager::instance()->toolById(d->view->canvasBase(), id)); if (tool) { int flags = tool->flags(); if (flags & KisTool::FLAG_USES_CUSTOM_COMPOSITEOP) { //setWidgetState(ENABLE_COMPOSITEOP|ENABLE_OPACITY); d->opacityEnabled = true; } else { //setWidgetState(DISABLE_COMPOSITEOP|DISABLE_OPACITY); d->opacityEnabled = false; } if (flags & KisTool::FLAG_USES_CUSTOM_PRESET) { d->flowEnabled = true; d->sizeEnabled = true; d->presetsEnabled = true; } else { d->flowEnabled = false; d->sizeEnabled = false; d->presetsEnabled = false; } } else { d->opacityEnabled = false; d->flowEnabled = false; d->sizeEnabled = false; } emit opacityEnabledChanged(); emit flowEnabledChanged(); emit sizeEnabledChanged(); } void CompositeOpModel::resourceChanged(int key, const QVariant& /*v*/) { if (d->view && d->view->canvasBase() && d->view->canvasBase()->resourceManager() && d->view->resourceProvider()) { if (key == KisCanvasResourceProvider::MirrorHorizontal) { emit mirrorHorizontallyChanged(); return; } else if(key == KisCanvasResourceProvider::MirrorVertical) { emit mirrorVerticallyChanged(); return; } KisPaintOpPresetSP preset = d->view->canvasBase()->resourceManager()->resource(KisCanvasResourceProvider::CurrentPaintOpPreset).value(); if (preset && d->currentPreset.data() != preset.data()) { d->currentPreset = preset; if (!d->settingsWidgets.contains(preset.data())) { d->settingsWidgets[preset.data()] = KisPaintOpRegistry::instance()->get(preset->paintOp().id())->createConfigWidget(0); d->settingsWidgets[preset.data()]->setImage(d->view->image()); d->settingsWidgets[preset.data()]->setConfiguration(preset->settings()); } if (d->settingsWidgets[preset.data()]) { preset->settings()->setOptionsWidget(d->settingsWidgets[preset.data()]); } d->size = preset->settings()->paintOpSize(); emit sizeChanged(); if (preset->settings()->hasProperty("OpacityValue")) { d->opacityEnabled = true; d->opacity = preset->settings()->getProperty("OpacityValue").toReal(); } else { d->opacityEnabled = false; d->opacity = 1; } d->view->resourceProvider()->setOpacity(d->opacity); emit opacityChanged(); emit opacityEnabledChanged(); if (preset->settings()->hasProperty("FlowValue")) { d->flowEnabled = true; d->flow = preset->settings()->getProperty("FlowValue").toReal(); } else { d->flowEnabled = false; d->flow = 1; } emit flowChanged(); emit flowEnabledChanged(); QString compositeOp = preset->settings()->getString("CompositeOp"); // This is a little odd, but the logic here is that the opposite of an eraser is a normal composite op (so we just select over, aka normal) // This means that you can switch your eraser over to being a painting tool by turning off the eraser again. if (compositeOp == COMPOSITE_ERASE) { d->currentCompositeOpID = COMPOSITE_OVER; d->eraserMode = true; } else { d->eraserMode = false; } emit eraserModeChanged(); d->updateCompositeOp(compositeOp); } } } void CompositeOpModel::currentNodeChanged(KisLayerSP newNode) { Q_UNUSED(newNode); if (d->eraserMode) { d->eraserMode = false; d->updateCompositeOp(d->prevCompositeOpID); emit eraserModeChanged(); } } int CompositeOpModel::indexOf(QString compositeOpId) { return d->model->indexOf(KoID(compositeOpId)).row(); } QString CompositeOpModel::currentCompositeOpID() const { return d->currentCompositeOpID; } diff --git a/libs/ui/input/KisQtWidgetsTweaker.cpp b/libs/ui/input/KisQtWidgetsTweaker.cpp index ed323d3b7f..5e1153504e 100644 --- a/libs/ui/input/KisQtWidgetsTweaker.cpp +++ b/libs/ui/input/KisQtWidgetsTweaker.cpp @@ -1,333 +1,339 @@ /* This file is part of the KDE project Copyright (C) 2017 Nikita Vertikov This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisQtWidgetsTweaker.h" #include #include #include #include #include #include #include #include #include #include "opengl/kis_opengl_canvas2.h" #include "canvas/kis_qpainter_canvas.h" #include "KisMainWindow.h" Q_GLOBAL_STATIC(KisQtWidgetsTweaker, kqwt_instance) namespace { class ShortcutOverriderBase { public: enum class DecisionOnShortcutOverride { overrideShortcut, askNext, dontOverrideShortcut }; constexpr ShortcutOverriderBase() = default; virtual ~ShortcutOverriderBase() {} virtual bool interestedInEvent(QKeyEvent *event) = 0; virtual DecisionOnShortcutOverride handleEvent(QObject *receiver, QKeyEvent *event) = 0; virtual DecisionOnShortcutOverride finishedPhysicalKeyPressHandling() { return DecisionOnShortcutOverride::askNext; } }; class LineTextEditingShortcutOverrider : public ShortcutOverriderBase { public: constexpr LineTextEditingShortcutOverrider() = default; virtual bool interestedInEvent(QKeyEvent *event) override { static constexpr QKeySequence::StandardKey actionsForQLineEdit[]{ QKeySequence::MoveToNextChar ,QKeySequence::MoveToPreviousChar ,QKeySequence::MoveToStartOfLine ,QKeySequence::MoveToEndOfLine ,QKeySequence::MoveToPreviousWord ,QKeySequence::MoveToNextWord ,QKeySequence::SelectPreviousChar ,QKeySequence::SelectNextChar ,QKeySequence::SelectNextWord ,QKeySequence::SelectPreviousWord ,QKeySequence::SelectStartOfLine ,QKeySequence::SelectEndOfLine ,QKeySequence::SelectAll ,QKeySequence::Deselect ,QKeySequence::Backspace ,QKeySequence::DeleteStartOfWord ,QKeySequence::Delete ,QKeySequence::DeleteEndOfWord ,QKeySequence::DeleteEndOfLine ,QKeySequence::Copy ,QKeySequence::Paste ,QKeySequence::Cut ,QKeySequence::Undo ,QKeySequence::Redo }; for (QKeySequence::StandardKey sk : actionsForQLineEdit) { if (event->matches(sk)) { event->accept(); return true; } } return false; } virtual DecisionOnShortcutOverride handleEvent(QObject *receiver, QKeyEvent *event) override { + Q_UNUSED(event); + if ((qobject_cast (receiver) != nullptr)|| (qobject_cast (receiver) != nullptr)|| (qobject_cast(receiver) != nullptr)) { return DecisionOnShortcutOverride::overrideShortcut; } else { return DecisionOnShortcutOverride::askNext; } } }; class SpingboxShortcutOverrider : public ShortcutOverriderBase { public: constexpr SpingboxShortcutOverrider() = default; virtual bool interestedInEvent(QKeyEvent *event) override { if (event->modifiers() != Qt::NoModifier) { return false; } switch (event->key()) { case Qt::Key_Down: case Qt::Key_Up: case Qt::Key_PageDown: case Qt::Key_PageUp: event->accept(); return true; default: return false; } } virtual DecisionOnShortcutOverride handleEvent(QObject *receiver, QKeyEvent *event) override { + Q_UNUSED(event); + if (qobject_cast (receiver) != nullptr|| qobject_cast(receiver) != nullptr) { return DecisionOnShortcutOverride::overrideShortcut; } else { return DecisionOnShortcutOverride::askNext; } } }; class TabShortcutOverrider : public ShortcutOverriderBase { public: constexpr TabShortcutOverrider() = default; virtual bool interestedInEvent(QKeyEvent *event) override { bool tab = event->modifiers() == Qt::NoModifier && ( event->key() == Qt::Key_Tab || event->key() == Qt::Key_Backtab); bool shiftTab = event->modifiers() == Qt::ShiftModifier && event->key() == Qt::Key_Backtab; if (tab || shiftTab) { return true; }else{ return false; } } virtual DecisionOnShortcutOverride handleEvent(QObject *receiver, QKeyEvent *event) override { + Q_UNUSED(event); + if (qobject_cast(receiver) != nullptr|| qobject_cast (receiver) != nullptr) { return DecisionOnShortcutOverride::dontOverrideShortcut; } else { m_nooverride = true; return DecisionOnShortcutOverride::askNext; } } virtual DecisionOnShortcutOverride finishedPhysicalKeyPressHandling() override { if (m_nooverride){ m_nooverride = false; return DecisionOnShortcutOverride::overrideShortcut; } return DecisionOnShortcutOverride::askNext; } private: bool m_nooverride = false; }; //for some reason I can't just populate constexpr //pointer array using "new" LineTextEditingShortcutOverrider overrider0; SpingboxShortcutOverrider overrider1; TabShortcutOverrider overrider2; constexpr ShortcutOverriderBase *allShortcutOverriders[] = { &overrider0, &overrider1, &overrider2 }; -constexpr size_t numOfShortcutOverriders = +constexpr int numOfShortcutOverriders = sizeof(allShortcutOverriders)/ sizeof(allShortcutOverriders[0]); } //namespace struct KisQtWidgetsTweaker::Private { public: Private(KisQtWidgetsTweaker *parent) : q(parent) + , interestedHandlers(numOfShortcutOverriders) , lastKeyPressProcessingComplete(true) , decision(ShortcutOverriderBase::DecisionOnShortcutOverride::askNext) - , interestedHandlers(numOfShortcutOverriders) { } const KisQtWidgetsTweaker *q; QBitArray interestedHandlers = QBitArray(numOfShortcutOverriders); ShortcutOverriderBase::DecisionOnShortcutOverride decision = ShortcutOverriderBase::DecisionOnShortcutOverride::askNext; //unsigned long lastEventTimestamp=0; bool lastKeyPressProcessingComplete = true; void newPhysicalKeyPressed(QKeyEvent *event) { for (int i=0; i < numOfShortcutOverriders; ++i) { if (allShortcutOverriders[i]->interestedInEvent(event)) { interestedHandlers.setBit(i); }else{ interestedHandlers.clearBit(i); } } decision = ShortcutOverriderBase::DecisionOnShortcutOverride::askNext; lastKeyPressProcessingComplete = false; } }; KisQtWidgetsTweaker::KisQtWidgetsTweaker(QObject *parent) :QObject(parent) , d(new KisQtWidgetsTweaker::Private(this)) { } KisQtWidgetsTweaker::~KisQtWidgetsTweaker() { delete d; } bool KisQtWidgetsTweaker::eventFilter(QObject *receiver, QEvent *event) { switch(event->type()) { case QEvent::ShortcutOverride:{ //QLineEdit and other widgets lets qt's shortcut system take away it's keyboard events //even is it knows them, such as ctrl+backspace //if there is application-wide shortcut, assigned to it. //The following code fixes it //by accepting ShortcutOverride events. //if you press key 'a' and then 'b', qt at first call //all handlers for 'a' key press event, and only after that //for 'b' QKeyEvent *key = static_cast(event); if (d->lastKeyPressProcessingComplete) { d->newPhysicalKeyPressed(key); } for(int i = 0; i < numOfShortcutOverriders; ++i) { if (d->decision != ShortcutOverriderBase::DecisionOnShortcutOverride::askNext) { break; } if (d->interestedHandlers.at(i)) { d->decision = allShortcutOverriders[i]->handleEvent(receiver, key); } } //if nothing said wether shortcutoverride to be accepted //last widget that qt will ask will be kismainwindow or docker if (qobject_cast(receiver)!=nullptr|| receiver->inherits(QDockWidget::staticMetaObject.className())) { for (int i = 0; i < numOfShortcutOverriders; ++i) { if (d->decision != ShortcutOverriderBase::DecisionOnShortcutOverride::askNext) { break; } if (d->interestedHandlers.at(i)) { d->decision = allShortcutOverriders[i]->finishedPhysicalKeyPressHandling(); } } d->lastKeyPressProcessingComplete = true; } bool retval = false; switch (d->decision) { case ShortcutOverriderBase::DecisionOnShortcutOverride::askNext: event->ignore(); retval = false; break; case ShortcutOverriderBase::DecisionOnShortcutOverride::dontOverrideShortcut: event->ignore(); retval = true; break; case ShortcutOverriderBase::DecisionOnShortcutOverride::overrideShortcut: event->accept(); //once shortcutoverride acepted, qt stop asking everyone //about it and proceed to handling next event d->lastKeyPressProcessingComplete = true; retval = true; break; } return retval || QObject::eventFilter(receiver, event); }break; //other event types default: break; } //code for tweaking the behavior of other qt elements will go here return QObject::eventFilter(receiver, event); } KisQtWidgetsTweaker *KisQtWidgetsTweaker::instance() { return kqwt_instance; } diff --git a/plugins/filters/edgedetection/kis_edge_detection_filter.cpp b/plugins/filters/edgedetection/kis_edge_detection_filter.cpp index 79b594a016..5775d1d166 100644 --- a/plugins/filters/edgedetection/kis_edge_detection_filter.cpp +++ b/plugins/filters/edgedetection/kis_edge_detection_filter.cpp @@ -1,157 +1,158 @@ /* * Copyright (c) 2017 Wolthera van Hövell tot Westerflier * * 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 of the License, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_edge_detection_filter.h" #include "kis_wdg_edge_detection.h" #include #include #include #include #include #include #include #include #include #include "kis_lod_transform.h" #include #include #include K_PLUGIN_FACTORY_WITH_JSON(KritaEdgeDetectionFilterFactory, "kritaedgedetection.json", registerPlugin();) KritaEdgeDetectionFilter::KritaEdgeDetectionFilter(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(KisFilterSP(new KisEdgeDetectionFilter())); } KritaEdgeDetectionFilter::~KritaEdgeDetectionFilter() { } KisEdgeDetectionFilter::KisEdgeDetectionFilter(): KisFilter(id(), categoryEdgeDetection(), i18n("&Edge Detection...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); setShowConfigurationWidget(true); } void KisEdgeDetectionFilter::processImpl(KisPaintDeviceSP device, const QRect &rect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const { Q_ASSERT(device != 0); KisFilterConfigurationSP configuration = config ? config : new KisFilterConfiguration(id().id(), 1); KisLodTransformScalar t(device); QVariant value; configuration->getProperty("horizRadius", value); float horizontalRadius = t.scale(value.toFloat()); configuration->getProperty("vertRadius", value); float verticalRadius = t.scale(value.toFloat()); QBitArray channelFlags; if (configuration) { channelFlags = configuration->channelFlags(); } if (channelFlags.isEmpty() || !configuration) { channelFlags = device->colorSpace()->channelFlags(); } KisEdgeDetectionKernel::FilterType type = KisEdgeDetectionKernel::SobolVector; if (config->getString("type") == "prewitt") { type = KisEdgeDetectionKernel::Prewit; } else if (config->getString("type") == "simple") { type = KisEdgeDetectionKernel::Simple; } KisEdgeDetectionKernel::FilterOutput output = KisEdgeDetectionKernel::pythagorean; if (config->getString("output") == "xGrowth") { output = KisEdgeDetectionKernel::xGrowth; } else if (config->getString("output") == "xFall") { output = KisEdgeDetectionKernel::xFall; } else if (config->getString("output") == "yGrowth") { output = KisEdgeDetectionKernel::yGrowth; } else if (config->getString("output") == "yFall") { output = KisEdgeDetectionKernel::yFall; } else if (config->getString("output") == "radian") { output = KisEdgeDetectionKernel::radian; } KisEdgeDetectionKernel::applyEdgeDetection(device, rect, horizontalRadius, verticalRadius, type, channelFlags, progressUpdater, output, config->getBool("transparency", false)); } KisFilterConfigurationSP KisEdgeDetectionFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); config->setProperty("horizRadius", 1); config->setProperty("vertRadius", 1); config->setProperty("type", "prewitt"); config->setProperty("output", "pythagorean"); config->setProperty("lockAspect", true); config->setProperty("transparency", false); return config; } KisConfigWidget *KisEdgeDetectionFilter::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const { + Q_UNUSED(dev); return new KisWdgEdgeDetection(parent); } QRect KisEdgeDetectionFilter::neededRect(const QRect &rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; /** * NOTE: integer devision by two is done on purpose, * because the kernel size is always odd */ const int halfWidth = _config->getProperty("horizRadius", value) ? KisEdgeDetectionKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; const int halfHeight = _config->getProperty("vertRadius", value) ? KisEdgeDetectionKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; return rect.adjusted(-halfWidth * 2, -halfHeight * 2, halfWidth * 2, halfHeight * 2); } QRect KisEdgeDetectionFilter::changedRect(const QRect &rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const int halfWidth = _config->getProperty("horizRadius", value) ? KisEdgeDetectionKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; const int halfHeight = _config->getProperty("vertRadius", value) ? KisEdgeDetectionKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; return rect.adjusted( -halfWidth, -halfHeight, halfWidth, halfHeight); } #include "kis_edge_detection_filter.moc"