diff --git a/libs/ui/kis_canvas_resource_provider.h b/libs/ui/kis_canvas_resource_provider.h
index 7f14a06fd7..be3151e033 100644
--- a/libs/ui/kis_canvas_resource_provider.h
+++ b/libs/ui/kis_canvas_resource_provider.h
@@ -1,244 +1,245 @@
/*
* Copyright (c) 2006 Boudewijn Rempt
*
* 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.
*/
#ifndef KIS_CANVAS_RESOURCE_PROVIDER_H_
#define KIS_CANVAS_RESOURCE_PROVIDER_H_
#include
#include
#include
#include
#include "kis_types.h"
#include "kritaui_export.h"
class KisWorkspaceResource;
class KoColorProfile;
class KoAbstractGradient;
class KoResource;
class KoCanvasBase;
class KisViewManager;
class KoPattern;
class KisFilterConfiguration;
#include
/**
* KisCanvasResourceProvider contains the per-window current settings that
* influence painting, like paintop, color, gradients and so on.
*/
class KRITAUI_EXPORT KisCanvasResourceProvider : public QObject
{
Q_OBJECT
public:
enum Resources {
HdrExposure = KoCanvasResourceManager::KritaStart + 1,
CurrentPattern,
CurrentGradient,
CurrentDisplayProfile,
CurrentKritaNode,
CurrentPaintOpPreset,
CurrentGeneratorConfiguration,
CurrentCompositeOp,
CurrentEffectiveCompositeOp,
LodAvailability, ///<-user choice
LodSizeThreshold, ///<-user choice
LodSizeThresholdSupported, ///<-paintop property
+ EffectiveLodAvailablility, ///<- a superposition of user choice, threshold and paintop traits
EraserMode,
MirrorHorizontal,
MirrorVertical,
MirrorHorizontalLock,
MirrorVerticalLock,
MirrorVerticalHideDecorations,
MirrorHorizontalHideDecorations,
Opacity,
Flow,
Size,
HdrGamma,
GlobalAlphaLock,
DisablePressure,
PreviousPaintOpPreset,
EffectiveZoom, ///<-Used only by painting tools for non-displaying purposes
SelectionAction,
SelectionMode
};
KisCanvasResourceProvider(KisViewManager * view);
~KisCanvasResourceProvider() override;
void setResourceManager(KoCanvasResourceManager *resourceManager);
KoCanvasResourceManager* resourceManager();
KoCanvasBase * canvas() const;
KoColor bgColor() const;
void setBGColor(const KoColor& c);
KoColor fgColor() const;
void setFGColor(const KoColor& c);
float HDRExposure() const;
void setHDRExposure(float exposure);
float HDRGamma() const;
void setHDRGamma(float gamma);
bool eraserMode() const;
void setEraserMode(bool value);
KoPattern *currentPattern() const;
KoAbstractGradient *currentGradient() const;
KisImageWSP currentImage() const;
KisNodeSP currentNode() const;
KisPaintOpPresetSP currentPreset() const;
void setPaintOpPreset(const KisPaintOpPresetSP preset);
KisPaintOpPresetSP previousPreset() const;
void setPreviousPaintOpPreset(const KisPaintOpPresetSP preset);
void setCurrentCompositeOp(const QString& compositeOp);
QString currentCompositeOp() const;
QList > perspectiveGrids() const;
void addPerspectiveGrid(KisAbstractPerspectiveGrid*);
void removePerspectiveGrid(KisAbstractPerspectiveGrid*);
void clearPerspectiveGrids();
void setMirrorHorizontal(bool mirrorHorizontal);
bool mirrorHorizontal() const;
void setMirrorVertical(bool mirrorVertical);
bool mirrorVertical() const;
// options for horizontal and vertical mirror toolbar
void setMirrorHorizontalLock(bool isLocked);
bool mirrorHorizontalLock();
void setMirrorVerticalLock(bool isLocked);
bool mirrorVerticalLock();
void setMirrorVerticalHideDecorations(bool hide);
bool mirrorVerticalHideDecorations();
void setMirrorHorizontalHideDecorations(bool hide);
bool mirrorHorizontalHideDecorations();
void mirrorVerticalMoveCanvasToCenter();
void mirrorHorizontalMoveCanvasToCenter();
void setOpacity(qreal opacity);
qreal opacity() const;
void setFlow(qreal opacity);
qreal flow() const;
void setSize(qreal size);
qreal size() const;
void setGlobalAlphaLock(bool lock);
bool globalAlphaLock() const;
void setDisablePressure(bool value);
bool disablePressure() const;
///Notify that the workspace is saved and settings should be saved to it
void notifySavingWorkspace(KisWorkspaceResource* workspace);
///Notify that the workspace is loaded and settings can be read
void notifyLoadingWorkspace(KisWorkspaceResource* workspace);
int selectionAction();
void setSelectionAction(int action);
int selectionMode();
void setSelectionMode(int mode);
public Q_SLOTS:
void slotSetFGColor(const KoColor& c);
void slotSetBGColor(const KoColor& c);
void slotPatternActivated(KoResource *pattern);
void slotGradientActivated(KoResource *gradient);
void slotNodeActivated(const KisNodeSP node);
void slotPainting();
/**
* Set the image size in pixels. The resource provider will store
* the image size in postscript points.
*/
// FIXME: this slot doesn't catch the case when image resolution is changed
void slotImageSizeChanged();
void slotOnScreenResolutionChanged();
// This is a flag to handle a bug:
// If pop up palette is visible and a new colour is selected, the new colour
// will be added when the user clicks on the canvas to hide the palette
// In general, we want to be able to store recent color if the pop up palette
// is not visible
void slotResetEnableFGChange(bool);
private Q_SLOTS:
void slotCanvasResourceChanged(int key, const QVariant & res);
Q_SIGNALS:
void sigFGColorChanged(const KoColor &);
void sigBGColorChanged(const KoColor &);
void sigGradientChanged(KoAbstractGradient *);
void sigPatternChanged(KoPattern *);
void sigNodeChanged(const KisNodeSP);
void sigDisplayProfileChanged(const KoColorProfile *);
void sigFGColorUsed(const KoColor&);
void sigOnScreenResolutionChanged(qreal scaleX, qreal scaleY);
void sigOpacityChanged(qreal);
void sigSavingWorkspace(KisWorkspaceResource* workspace);
void sigLoadingWorkspace(KisWorkspaceResource* workspace);
void sigSelectionActionChanged(const int);
void sigSelectionModeChanged(const int);
void mirrorModeChanged();
void moveMirrorVerticalCenter();
void moveMirrorHorizontalCenter();
private:
KisViewManager * m_view;
KoCanvasResourceManager *m_resourceManager;
bool m_fGChanged;
QList > m_perspectiveGrids;
// This is a flag to handle a bug:
// If pop up palette is visible and a new colour is selected, the new colour
// will be added when the user clicks on the canvas to hide the palette
// In general, we want to be able to store recent color if the pop up palette
// is not visible
bool m_enablefGChange;
};
#endif
diff --git a/libs/ui/tool/kis_resources_snapshot.cpp b/libs/ui/tool/kis_resources_snapshot.cpp
index 71f73b32c1..733ef420a0 100644
--- a/libs/ui/tool/kis_resources_snapshot.cpp
+++ b/libs/ui/tool/kis_resources_snapshot.cpp
@@ -1,437 +1,429 @@
/*
* Copyright (c) 2011 Dmitry Kazakov
*
* 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_resources_snapshot.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_canvas_resource_provider.h"
#include "filter/kis_filter_configuration.h"
#include "kis_image.h"
#include "kis_paint_device.h"
#include "kis_paint_layer.h"
#include "recorder/kis_recorded_paint_action.h"
#include "kis_selection.h"
#include "kis_selection_mask.h"
#include "kis_algebra_2d.h"
struct KisResourcesSnapshot::Private {
Private()
: currentPattern(0)
, currentGradient(0)
, currentGenerator(0)
, compositeOp(0)
{
}
KisImageSP image;
KisDefaultBoundsBaseSP bounds;
KoColor currentFgColor;
KoColor currentBgColor;
KoPattern *currentPattern = 0;
KoAbstractGradient *currentGradient;
KisPaintOpPresetSP currentPaintOpPreset;
KisNodeSP currentNode;
qreal currentExposure;
KisFilterConfigurationSP currentGenerator;
QPointF axesCenter;
bool mirrorMaskHorizontal = false;
bool mirrorMaskVertical = false;
quint8 opacity = OPACITY_OPAQUE_U8;
QString compositeOpId = COMPOSITE_OVER;
const KoCompositeOp *compositeOp;
KisPainter::StrokeStyle strokeStyle = KisPainter::StrokeStyleBrush;
KisPainter::FillStyle fillStyle = KisPainter::FillStyleForegroundColor;
bool globalAlphaLock = false;
qreal effectiveZoom = 1.0;
bool presetAllowsLod = false;
KisSelectionSP selectionOverride;
};
KisResourcesSnapshot::KisResourcesSnapshot(KisImageSP image, KisNodeSP currentNode, KoCanvasResourceManager *resourceManager, KisDefaultBoundsBaseSP bounds)
: m_d(new Private())
{
m_d->image = image;
if (!bounds) {
bounds = new KisDefaultBounds(m_d->image);
}
m_d->bounds = bounds;
m_d->currentFgColor = resourceManager->resource(KoCanvasResourceManager::ForegroundColor).value();
m_d->currentBgColor = resourceManager->resource(KoCanvasResourceManager::BackgroundColor).value();
m_d->currentPattern = resourceManager->resource(KisCanvasResourceProvider::CurrentPattern).value();
m_d->currentGradient = resourceManager->resource(KisCanvasResourceProvider::CurrentGradient).value();
/**
* We should deep-copy the preset, so that long-runnign actions
* will have correct brush parameters. Theoretically this cloniong
* can be expensive, but according to measurements, it takes
* something like 0.1 ms for an average preset.
*/
m_d->currentPaintOpPreset = resourceManager->resource(KisCanvasResourceProvider::CurrentPaintOpPreset).value()->clone();
#ifdef HAVE_THREADED_TEXT_RENDERING_WORKAROUND
KisPaintOpRegistry::instance()->preinitializePaintOpIfNeeded(m_d->currentPaintOpPreset);
#endif /* HAVE_THREADED_TEXT_RENDERING_WORKAROUND */
m_d->currentExposure = resourceManager->resource(KisCanvasResourceProvider::HdrExposure).toDouble();
m_d->currentGenerator = resourceManager->resource(KisCanvasResourceProvider::CurrentGeneratorConfiguration).value();
QPointF relativeAxesCenter(0.5, 0.5);
if (m_d->image) {
relativeAxesCenter = m_d->image->mirrorAxesCenter();
}
m_d->axesCenter = KisAlgebra2D::relativeToAbsolute(relativeAxesCenter, m_d->bounds->bounds());
m_d->mirrorMaskHorizontal = resourceManager->resource(KisCanvasResourceProvider::MirrorHorizontal).toBool();
m_d->mirrorMaskVertical = resourceManager->resource(KisCanvasResourceProvider::MirrorVertical).toBool();
qreal normOpacity = resourceManager->resource(KisCanvasResourceProvider::Opacity).toDouble();
m_d->opacity = quint8(normOpacity * OPACITY_OPAQUE_U8);
m_d->compositeOpId = resourceManager->resource(KisCanvasResourceProvider::CurrentEffectiveCompositeOp).toString();
setCurrentNode(currentNode);
/**
* Fill and Stroke styles are not a part of the resource manager
* so the tools should set them manually
* TODO: port stroke and fill styles to be a part
* of the resource manager
*/
m_d->strokeStyle = KisPainter::StrokeStyleBrush;
m_d->fillStyle = KisPainter::FillStyleNone;
m_d->globalAlphaLock = resourceManager->resource(KisCanvasResourceProvider::GlobalAlphaLock).toBool();
m_d->effectiveZoom = resourceManager->resource(KisCanvasResourceProvider::EffectiveZoom).toDouble();
-
- m_d->presetAllowsLod = true;
-
- if (m_d->currentPaintOpPreset) {
- m_d->presetAllowsLod =
- KisPaintOpSettings::isLodUserAllowed(m_d->currentPaintOpPreset->settings()) &&
- (!m_d->currentPaintOpPreset->settings()->lodSizeThresholdSupported() ||
- m_d->currentPaintOpPreset->settings()->lodSizeThreshold() <= m_d->currentPaintOpPreset->settings()->paintOpSize());
- }
+ m_d->presetAllowsLod = resourceManager->resource(KisCanvasResourceProvider::EffectiveLodAvailablility).toBool();
}
KisResourcesSnapshot::KisResourcesSnapshot(KisImageSP image, KisNodeSP currentNode, KisDefaultBoundsBaseSP bounds)
: m_d(new Private())
{
m_d->image = image;
if (!bounds) {
bounds = new KisDefaultBounds(m_d->image);
}
m_d->bounds = bounds;
#ifdef HAVE_THREADED_TEXT_RENDERING_WORKAROUND
KisPaintOpRegistry::instance()->preinitializePaintOpIfNeeded(m_d->currentPaintOpPreset);
#endif /* HAVE_THREADED_TEXT_RENDERING_WORKAROUND */
QPointF relativeAxesCenter(0.5, 0.5);
if (m_d->image) {
relativeAxesCenter = m_d->image->mirrorAxesCenter();
}
m_d->axesCenter = KisAlgebra2D::relativeToAbsolute(relativeAxesCenter, m_d->bounds->bounds());
m_d->opacity = OPACITY_OPAQUE_U8;
setCurrentNode(currentNode);
/**
* Fill and Stroke styles are not a part of the resource manager
* so the tools should set them manually
* TODO: port stroke and fill styles to be a part
* of the resource manager
*/
m_d->strokeStyle = KisPainter::StrokeStyleBrush;
m_d->fillStyle = KisPainter::FillStyleNone;
}
KisResourcesSnapshot::~KisResourcesSnapshot()
{
delete m_d;
}
void KisResourcesSnapshot::setupPainter(KisPainter* painter)
{
painter->setPaintColor(m_d->currentFgColor);
painter->setBackgroundColor(m_d->currentBgColor);
painter->setGenerator(m_d->currentGenerator);
painter->setPattern(m_d->currentPattern);
painter->setGradient(m_d->currentGradient);
QBitArray lockflags = channelLockFlags();
if (lockflags.size() > 0) {
painter->setChannelFlags(lockflags);
}
painter->setOpacity(m_d->opacity);
painter->setCompositeOp(m_d->compositeOp);
painter->setMirrorInformation(m_d->axesCenter, m_d->mirrorMaskHorizontal, m_d->mirrorMaskVertical);
painter->setStrokeStyle(m_d->strokeStyle);
painter->setFillStyle(m_d->fillStyle);
/**
* The paintOp should be initialized the last, because it may
* ask the painter for some options while initialization
*/
painter->setPaintOpPreset(m_d->currentPaintOpPreset, m_d->currentNode, m_d->image);
}
void KisResourcesSnapshot::setupMaskingBrushPainter(KisPainter *painter)
{
KIS_SAFE_ASSERT_RECOVER_RETURN(painter->device());
KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->currentPaintOpPreset->hasMaskingPreset());
painter->setPaintColor(KoColor(Qt::white, painter->device()->colorSpace()));
painter->setBackgroundColor(KoColor(Qt::black, painter->device()->colorSpace()));
painter->setOpacity(OPACITY_OPAQUE_U8);
painter->setChannelFlags(QBitArray());
// masked brush always paints in indirect mode
painter->setCompositeOp(COMPOSITE_ALPHA_DARKEN);
painter->setMirrorInformation(m_d->axesCenter, m_d->mirrorMaskHorizontal, m_d->mirrorMaskVertical);
/**
* The paintOp should be initialized the last, because it may
* ask the painter for some options while initialization
*/
painter->setPaintOpPreset(m_d->currentPaintOpPreset->createMaskingPreset(),
m_d->currentNode, m_d->image);
}
void KisResourcesSnapshot::setupPaintAction(KisRecordedPaintAction *action)
{
action->setPaintOpPreset(m_d->currentPaintOpPreset);
action->setPaintIncremental(!needsIndirectPainting());
action->setPaintColor(m_d->currentFgColor);
action->setBackgroundColor(m_d->currentBgColor);
action->setGenerator(m_d->currentGenerator);
action->setGradient(m_d->currentGradient);
action->setPattern(m_d->currentPattern);
action->setOpacity(m_d->opacity / qreal(OPACITY_OPAQUE_U8));
action->setCompositeOp(m_d->compositeOp->id());
action->setStrokeStyle(m_d->strokeStyle);
action->setFillStyle(m_d->fillStyle);
}
KisPostExecutionUndoAdapter* KisResourcesSnapshot::postExecutionUndoAdapter() const
{
return m_d->image ? m_d->image->postExecutionUndoAdapter() : 0;
}
void KisResourcesSnapshot::setCurrentNode(KisNodeSP node)
{
m_d->currentNode = node;
KisPaintDeviceSP device;
if(m_d->currentNode && (device = m_d->currentNode->paintDevice())) {
m_d->compositeOp = device->colorSpace()->compositeOp(m_d->compositeOpId);
if(!m_d->compositeOp) {
m_d->compositeOp = device->colorSpace()->compositeOp(COMPOSITE_OVER);
}
}
}
void KisResourcesSnapshot::setStrokeStyle(KisPainter::StrokeStyle strokeStyle)
{
m_d->strokeStyle = strokeStyle;
}
void KisResourcesSnapshot::setFillStyle(KisPainter::FillStyle fillStyle)
{
m_d->fillStyle = fillStyle;
}
KisNodeSP KisResourcesSnapshot::currentNode() const
{
return m_d->currentNode;
}
KisImageSP KisResourcesSnapshot::image() const
{
return m_d->image;
}
bool KisResourcesSnapshot::needsIndirectPainting() const
{
return !m_d->currentPaintOpPreset->settings()->paintIncremental();
}
QString KisResourcesSnapshot::indirectPaintingCompositeOp() const
{
return m_d->currentPaintOpPreset->settings()->indirectPaintingCompositeOp();
}
bool KisResourcesSnapshot::needsMaskingBrushRendering() const
{
return m_d->currentPaintOpPreset && m_d->currentPaintOpPreset->hasMaskingPreset();
}
KisSelectionSP KisResourcesSnapshot::activeSelection() const
{
/**
* It is possible to have/use the snapshot without the image. Such
* usecase is present for example in the scratchpad.
*/
if (m_d->selectionOverride) {
return m_d->selectionOverride;
}
KisSelectionSP selection = m_d->image ? m_d->image->globalSelection() : 0;
KisLayerSP layer = qobject_cast(m_d->currentNode.data());
KisSelectionMaskSP mask;
if((layer = qobject_cast(m_d->currentNode.data()))) {
selection = layer->selection();
} else if ((mask = dynamic_cast(m_d->currentNode.data())) &&
mask->selection() == selection) {
selection = 0;
}
return selection;
}
bool KisResourcesSnapshot::needsAirbrushing() const
{
return m_d->currentPaintOpPreset->settings()->isAirbrushing();
}
qreal KisResourcesSnapshot::airbrushingInterval() const
{
return m_d->currentPaintOpPreset->settings()->airbrushInterval();
}
bool KisResourcesSnapshot::needsSpacingUpdates() const
{
return m_d->currentPaintOpPreset->settings()->useSpacingUpdates();
}
void KisResourcesSnapshot::setOpacity(qreal opacity)
{
m_d->opacity = opacity * OPACITY_OPAQUE_U8;
}
quint8 KisResourcesSnapshot::opacity() const
{
return m_d->opacity;
}
const KoCompositeOp* KisResourcesSnapshot::compositeOp() const
{
return m_d->compositeOp;
}
QString KisResourcesSnapshot::compositeOpId() const
{
return m_d->compositeOpId;
}
KoPattern* KisResourcesSnapshot::currentPattern() const
{
return m_d->currentPattern;
}
KoColor KisResourcesSnapshot::currentFgColor() const
{
return m_d->currentFgColor;
}
KoColor KisResourcesSnapshot::currentBgColor() const
{
return m_d->currentBgColor;
}
KisPaintOpPresetSP KisResourcesSnapshot::currentPaintOpPreset() const
{
return m_d->currentPaintOpPreset;
}
QBitArray KisResourcesSnapshot::channelLockFlags() const
{
QBitArray channelFlags;
KisPaintLayer *paintLayer;
if ((paintLayer = dynamic_cast(m_d->currentNode.data()))) {
channelFlags = paintLayer->channelLockFlags();
if (m_d->globalAlphaLock) {
if (channelFlags.isEmpty()) {
channelFlags = paintLayer->colorSpace()->channelFlags(true, true);
}
channelFlags &= paintLayer->colorSpace()->channelFlags(true, false);
}
}
return channelFlags;
}
qreal KisResourcesSnapshot::effectiveZoom() const
{
return m_d->effectiveZoom;
}
bool KisResourcesSnapshot::presetAllowsLod() const
{
return m_d->presetAllowsLod;
}
bool KisResourcesSnapshot::presetNeedsAsynchronousUpdates() const
{
return m_d->currentPaintOpPreset && m_d->currentPaintOpPreset->settings()->needsAsynchronousUpdates();
}
void KisResourcesSnapshot::setFGColorOverride(const KoColor &color)
{
m_d->currentFgColor = color;
}
void KisResourcesSnapshot::setBGColorOverride(const KoColor &color)
{
m_d->currentBgColor = color;
}
void KisResourcesSnapshot::setSelectionOverride(KisSelectionSP selection)
{
m_d->selectionOverride = selection;
}
void KisResourcesSnapshot::setBrush(const KisPaintOpPresetSP &brush)
{
m_d->currentPaintOpPreset = brush;
}
diff --git a/libs/ui/widgets/kis_lod_availability_widget.cpp b/libs/ui/widgets/kis_lod_availability_widget.cpp
index 7e7397a9e6..0e9c645bcf 100644
--- a/libs/ui/widgets/kis_lod_availability_widget.cpp
+++ b/libs/ui/widgets/kis_lod_availability_widget.cpp
@@ -1,233 +1,252 @@
/*
* Copyright (c) 2015 Dmitry Kazakov
*
* 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_lod_availability_widget.h"
#include
#include
#include
#include
#include
#include
#include "kis_config.h"
#include
#include
#include "kis_signals_blocker.h"
namespace {
/**
* These strings are added intentionally so we could relayout the threshold slider after
* the string freeze for 4.0. Please translate them :)
*/
static const QString stringForInstantPreviewThreshold1 = i18nc("@label:slider", "Threshold:");
static const QString stringForInstantPreviewThreshold2 = i18nc("@label:slider", "Instant preview threshold:");
}
struct KisLodAvailabilityWidget::Private
{
Private() : chkLod(0), resourceManager(0) {}
QCheckBox *chkLod;
QPushButton *btnLod;
QScopedPointer thresholdMenu;
KisDoubleSliderSpinBox *thresholdSlider = 0;
KoCanvasResourceManager *resourceManager;
KisPaintopLodLimitations limitations;
bool thresholdSupported = true;
bool sizeThresholdPassed();
};
KisLodAvailabilityWidget::KisLodAvailabilityWidget(QWidget *parent)
: QWidget(parent),
m_d(new Private)
{
m_d->chkLod = new QCheckBox(this);
m_d->btnLod = new QPushButton(this);
m_d->btnLod->setFlat(true);
connect(m_d->btnLod, SIGNAL(clicked()), SLOT(showLodToolTip()));
{
m_d->thresholdMenu.reset(new QMenu());
m_d->thresholdMenu->addSection(i18n("Enable after:"));
m_d->btnLod->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_d->btnLod, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(showLodThresholdWidget(QPoint)));
KisConfig cfg;
m_d->thresholdSlider = new KisDoubleSliderSpinBox(m_d->thresholdMenu.data());
m_d->thresholdSlider->setRange(0, cfg.readEntry("maximumBrushSize", 1000), 2);
m_d->thresholdSlider->setValue(100);
m_d->thresholdSlider->setSingleStep(1);
m_d->thresholdSlider->setExponentRatio(3.0);
m_d->thresholdSlider->setSuffix(i18n(" px"));
m_d->thresholdSlider->setBlockUpdateSignalOnDrag(true);
QWidgetAction *sliderAction = new QWidgetAction(this);
sliderAction->setDefaultWidget(m_d->thresholdSlider);
m_d->thresholdMenu->addAction(sliderAction);
}
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(m_d->chkLod);
layout->addWidget(m_d->btnLod);
layout->setSpacing(0);
setLayout(layout);
// set no limitations
setLimitations(m_d->limitations);
connect(m_d->chkLod, SIGNAL(toggled(bool)), SIGNAL(sigUserChangedLodAvailability(bool)));
connect(m_d->thresholdSlider, SIGNAL(valueChanged(qreal)), SIGNAL(sigUserChangedLodThreshold(qreal)));
}
KisLodAvailabilityWidget::~KisLodAvailabilityWidget()
{
}
void KisLodAvailabilityWidget::showLodToolTip()
{
QToolTip::showText(QCursor::pos(), m_d->btnLod->toolTip(), m_d->btnLod);
}
void KisLodAvailabilityWidget::showLodThresholdWidget(const QPoint &pos)
{
Q_UNUSED(pos);
if (m_d->thresholdSupported) {
m_d->thresholdMenu->popup(QCursor::pos());
}
}
void KisLodAvailabilityWidget::setLimitations(const KisPaintopLodLimitations &l)
{
QString limitationsText;
Q_FOREACH (const KoID &id, l.limitations) {
limitationsText.append("");
limitationsText.append(id.name());
limitationsText.append("");
}
QString blockersText;
Q_FOREACH (const KoID &id, l.blockers) {
blockersText.append("");
blockersText.append(id.name());
blockersText.append("");
}
bool isBlocked = !l.blockers.isEmpty();
bool isLimited = !l.limitations.isEmpty();
m_d->thresholdSupported =
m_d->resourceManager ?
m_d->resourceManager->resource(KisCanvasResourceProvider::LodSizeThresholdSupported).toBool() :
true;
bool isBlockedByThreshold = !m_d->sizeThresholdPassed() && m_d->thresholdSupported;
const QString text = !isBlocked && !isBlockedByThreshold && isLimited ?
i18n("(Instant Preview)*") : i18n("Instant Preview");
QString toolTip;
if (isBlocked) {
toolTip = i18nc("@info:tooltip",
"Instant Preview Mode is "
"disabled by the following options:"
"
", blockersText);
} else if (isBlockedByThreshold) {
const qreal lodThreshold = m_d->resourceManager->resource(KisCanvasResourceProvider::LodSizeThreshold).toDouble();
const qreal size = m_d->resourceManager->resource(KisCanvasResourceProvider::Size).toDouble();
toolTip = i18nc("@info:tooltip",
"Instant Preview Mode is "
"disabled by instant preview threshold. "
"Please right-click here to change the threshold"
"
- Brush size %1
"
"- Threshold: %2
",
size, lodThreshold);
} else if (isLimited) {
toolTip = i18nc("@info:tooltip",
"Instant Preview may look different "
"from the final result. In case of troubles "
"try disabling the following options:"
"
", limitationsText);
} else {
toolTip = i18nc("@info:tooltip", "Instant Preview Mode is available
");
}
{
QFont font;
font.setStrikeOut(isBlocked || isBlockedByThreshold);
m_d->chkLod->setEnabled(!isBlocked);
m_d->btnLod->setEnabled(!isBlocked);
m_d->btnLod->setFont(font);
m_d->btnLod->setText(text);
m_d->btnLod->setToolTip(toolTip);
+
+ if (isBlocked) {
+ /**
+ * If LoD is really blocked by some limitation we sneakly reset
+ * the checkbox to let the user know it is fully disabled.
+ */
+
+ KisSignalsBlocker b(m_d->chkLod);
+ m_d->chkLod->setChecked(false);
+ }
}
m_d->limitations = l;
+
+ if (m_d->resourceManager) {
+ const bool lodAvailableForUse =
+ !isBlocked && !isBlockedByThreshold &&
+ m_d->resourceManager->resource(KisCanvasResourceProvider::LodAvailability).toBool();
+
+ m_d->resourceManager->setResource(KisCanvasResourceProvider::EffectiveLodAvailablility, lodAvailableForUse);
+ }
+
}
void KisLodAvailabilityWidget::slotUserChangedLodAvailability(bool value)
{
KisSignalsBlocker b(m_d->chkLod);
m_d->chkLod->setChecked(value);
}
void KisLodAvailabilityWidget::slotUserChangedLodThreshold(qreal value)
{
KisSignalsBlocker b(m_d->thresholdSlider);
m_d->thresholdSlider->setValue(value);
setLimitations(m_d->limitations);
}
void KisLodAvailabilityWidget::slotUserChangedSize(qreal value)
{
Q_UNUSED(value);
setLimitations(m_d->limitations);
}
void KisLodAvailabilityWidget::setCanvasResourceManager(KoCanvasResourceManager *resourceManager)
{
m_d->resourceManager = resourceManager;
}
bool KisLodAvailabilityWidget::Private::sizeThresholdPassed()
{
if (!resourceManager) return true;
const qreal lodThreshold = resourceManager->resource(KisCanvasResourceProvider::LodSizeThreshold).toDouble();
const qreal size = resourceManager->resource(KisCanvasResourceProvider::Size).toDouble();
return size >= lodThreshold;
}