28#include <QReadWriteLock>
30#include <QWriteLocker>
62void KisSelection::Private::safeDeleteShapeSelection(T *
object,
KisSelection *selection)
65 ShapeSelectionReleaseStroke(T *
object)
77 ~ShapeSelectionReleaseStroke()
86 m_objectWrapper->deleteLater();
126 struct GuiStrokeWrapper
129 : m_image(image), m_object(object)
154 image = parentNode->
image();
252 if (!defaultBounds) {
263 m_d->pixelSelection->setParentNode(
m_d->parentNode);
277 if (!defaultBounds) {
283 m_d->pixelSelection->setParentSelection(
this);
284 m_d->pixelSelection->setParentNode(
m_d->parentNode);
285 m_d->pixelSelection->setDefaultBounds(defaultBounds);
298 m_d->isVisible = rhs.
m_d->isVisible;
299 m_d->resolutionProxy = rhs.
m_d->resolutionProxy;
302 Q_ASSERT(rhs.
m_d->pixelSelection);
304 m_d->pixelSelection->setParentSelection(
this);
306 QReadLocker l1(&rhs.
m_d->shapeSelectionPointerLock);
307 QWriteLocker l2(&
m_d->shapeSelectionPointerLock);
309 if (rhs.
m_d->shapeSelection && !rhs.
m_d->shapeSelection->isEmpty()) {
310 m_d->shapeSelection = rhs.
m_d->shapeSelection->clone(
this);
313 m_d->shapeSelection != rhs.
m_d->shapeSelection) {
314 m_d->shapeSelection = 0;
318 if (
m_d->shapeSelection) {
319 Private::safeDeleteShapeSelection(
m_d->shapeSelection,
this);
320 m_d->shapeSelection = 0;
327 delete m_d->shapeSelection;
333 m_d->parentNode = node;
334 m_d->pixelSelection->setParentNode(node);
339 m_d->updateCompressor->tryProcessStalledUpdate();
346 return m_d->parentNode;
351 QReadLocker l(&
m_d->shapeSelectionPointerLock);
352 return m_d->shapeSelection ||
353 m_d->pixelSelection->outlineCacheValid();
358 QReadLocker l(&
m_d->shapeSelectionPointerLock);
360 QPainterPath outline;
362 if (
m_d->shapeSelection) {
363 outline +=
m_d->shapeSelection->outlineCache();
364 }
else if (
m_d->pixelSelection->outlineCacheValid()) {
365 outline +=
m_d->pixelSelection->outlineCache();
373 QReadLocker l(&
m_d->shapeSelectionPointerLock);
375 Q_ASSERT(
m_d->pixelSelection);
377 if (
m_d->shapeSelection) {
378 m_d->shapeSelection->recalculateOutlineCache();
379 }
else if (!
m_d->pixelSelection->outlineCacheValid()) {
380 m_d->pixelSelection->recalculateOutlineCache();
386 return m_d->pixelSelection->thumbnailImageValid();
391 m_d->pixelSelection->recalculateThumbnailImage(maskColor);
396 return m_d->pixelSelection->thumbnailImage();
401 return m_d->pixelSelection->thumbnailImageTransform();
406 return m_d->pixelSelection && !
m_d->pixelSelection->isEmpty();
411 QReadLocker l(&
m_d->shapeSelectionPointerLock);
412 return m_d->shapeSelection && !
m_d->shapeSelection->isEmpty();
417 QReadLocker l(&
m_d->shapeSelectionPointerLock);
418 return m_d->shapeSelection;
423 return m_d->pixelSelection;
428 return m_d->shapeSelection;
450 return m_d->pixelSelection;
455 QReadLocker l(&
m_d->shapeSelectionPointerLock);
457 if(
m_d->shapeSelection) {
458 m_d->shapeSelection->renderToProjection(
m_d->pixelSelection, rc);
459 m_d->pixelSelection->setOutlineCache(
m_d->shapeSelection->outlineCache());
465 QReadLocker l(&
m_d->shapeSelectionPointerLock);
467 if(
m_d->shapeSelection) {
468 m_d->pixelSelection->clear();
469 m_d->shapeSelection->renderToProjection(
m_d->pixelSelection);
470 m_d->pixelSelection->setOutlineCache(
m_d->shapeSelection->outlineCache());
476 bool needsNotification = visible !=
m_d->isVisible;
478 m_d->isVisible = visible;
480 if (needsNotification) {
487 return m_d->isVisible;
492 return m_d->pixelSelection->isTotallyUnselected(r);
497 return m_d->pixelSelection->selectedRect();
502 return m_d->pixelSelection->selectedExactRect();
507 return m_d->pixelSelection->x();
512 return m_d->pixelSelection->y();
517 QReadLocker l(&
m_d->shapeSelectionPointerLock);
519 Q_ASSERT(
m_d->pixelSelection);
521 qint32 delta =
x -
m_d->pixelSelection->x();
522 m_d->pixelSelection->setX(
x);
523 if (
m_d->shapeSelection) {
524 m_d->shapeSelection->moveX(delta);
530 QReadLocker l(&
m_d->shapeSelectionPointerLock);
532 Q_ASSERT(
m_d->pixelSelection);
534 qint32 delta =
y -
m_d->pixelSelection->y();
535 m_d->pixelSelection->setY(
y);
536 if (
m_d->shapeSelection) {
537 m_d->shapeSelection->moveY(delta);
543 m_d->pixelSelection->setDefaultBounds(
bounds);
548 m_d->resolutionProxy = proxy;
549 if (
m_d->shapeSelection) {
550 m_d->shapeSelection->setResolutionProxy(proxy);
556 return m_d->resolutionProxy;
561 QReadLocker readLocker(&
m_d->shapeSelectionPointerLock);
563 if (
m_d->shapeSelection) {
565 QWriteLocker writeLocker(&
m_d->shapeSelectionPointerLock);
566 if (
m_d->shapeSelection) {
567 Private::safeDeleteShapeSelection(
m_d->shapeSelection,
this);
568 m_d->shapeSelection = 0;
572 m_d->pixelSelection->clear();
577 QReadLocker readLocker(&
m_d->shapeSelectionPointerLock);
581 if (
m_d->shapeSelection) {
582 command =
m_d->shapeSelection->resetToEmpty();
611 m_d->updateCompressor->requestUpdate(rc);
KisDeleteLaterWrapper< T > * makeKisDeleteLaterWrapper(T value)
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
virtual const quint8 * oldRawData() const =0
KisStrokeId startStroke(KisStrokeStrategy *strokeStrategy) override
void endStroke(KisStrokeId id) override
virtual void setResolutionProxy(KisImageResolutionProxySP)
void enableJob(JobType type, bool enable=true, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
virtual void cancelStrokeCallback()
KisSimpleStrokeStrategy(const QLatin1String &id, const KUndo2MagicString &name=KUndo2MagicString())
virtual void finishStrokeCallback()
void setClearsRedoOnStart(bool value)
void setRequestsOtherStrokesToEnd(bool value)
void setNeedsExplicitCancel(bool value)
#define KIS_SAFE_ASSERT_RECOVER(cond)
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
void addCommand(KUndo2Command *cmd)
virtual void notifySelectionChanged()
KisNodeGraphListener * graphListener
ChangeShapeSelectionCommand(KisSelectionWSP selection, KisSelectionComponent *shapeSelection)
KisSelectionWSP m_selection
KisSelectionComponent * m_shapeSelection
QScopedPointer< KUndo2Command > m_reincarnationCommand
~ChangeShapeSelectionCommand() override
KUndo2Command * convertToVectorSelection(KisSelectionComponent *shapeSelection)
converts shape selection into the vector state
KisSelection & operator=(const KisSelection &rhs)
void recalculateOutlineCache()
KisPixelSelectionSP projection() const
static void safeDeleteShapeSelection(T *object, KisSelection *selection)
void copyFrom(const KisSelection &rhs)
bool hasNonEmptyPixelSelection() const
bool thumbnailImageValid() const
void recalculateThumbnailImage(const QColor &maskColor)
QTransform thumbnailImageTransform() const
bool outlineCacheValid() const
bool isTotallyUnselected(const QRect &r) const
KisLazyStorage< KisSelectionUpdateCompressor, KisSelection * > updateCompressor
void setResolutionProxy(KisImageResolutionProxySP proxy)
void setParentNode(KisNodeWSP node)
KUndo2Command * flatten()
flatten creates a new pixel selection component from the shape selection and throws away the shape se...
QImage thumbnailImage() const
void notifySelectionChanged()
KisImageResolutionProxySP resolutionProxy
quint8 selected(qint32 x, qint32 y) const
KisPixelSelectionSP pixelSelection
bool hasNonEmptyShapeSelection() const
KisSelectionComponent * shapeSelection
QRect selectedRect() const
void setDefaultBounds(KisDefaultBoundsBaseSP bounds)
bool hasShapeSelection() const
void setVisible(bool visible)
void requestCompressedProjectionUpdate(const QRect &rc)
QReadWriteLock shapeSelectionPointerLock
QRect selectedExactRect() const
Slow, but exact way of determining the rectangle that encloses the selection.
void convertToVectorSelectionNoUndo(KisSelectionComponent *shapeSelection)
QPainterPath outlineCache() const