Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_tool_crop.cc
Go to the documentation of this file.
1/*
2 * kis_tool_crop.cc -- part of Krita
3 *
4 * SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org>
5 * SPDX-FileCopyrightText: 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
6 * SPDX-FileCopyrightText: 2006 Cyrille Berger <cberger@cberger.net>
7 * SPDX-FileCopyrightText: 2007 Adrian Page <adrian@pagenet.plus.com>
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12#include "kis_tool_crop.h"
13
14
15#include <QCheckBox>
16#include <QObject>
17#include <QPainter>
18#include <QPen>
19#include <QRect>
20#include <QMenu>
21
22#include <kis_debug.h>
23#include <klocalizedstring.h>
24#include <ksharedconfig.h>
25
26#include <KoCanvasBase.h>
27#include <kis_global.h>
28#include <kis_painter.h>
29#include <kis_cursor.h>
30#include <kis_image.h>
31#include <kis_undo_adapter.h>
32#include <KoPointerEvent.h>
33#include <kis_selection.h>
34#include <kis_layer.h>
35#include <kis_canvas2.h>
36#include <KisViewManager.h>
38#include <kis_group_layer.h>
40
41#include <kundo2command.h>
43
44
61
63{
64 //thirds
69
70 //fifths
79
80 // Passport photo
81 {QPointF(0.0, 0.45/0.35),QPointF(1.0, 0.45/0.35), DecorationLine::Width, DecorationLine::Width, DecorationLine::Width, DecorationLine::Width},
82 {QPointF(0.2, 0.05/0.35),QPointF(0.8, 0.05/0.35), DecorationLine::Width, DecorationLine::Width, DecorationLine::Width, DecorationLine::Width},
83 {QPointF(0.2, 0.40/0.35),QPointF(0.8, 0.40/0.35), DecorationLine::Width, DecorationLine::Width, DecorationLine::Width, DecorationLine::Width},
84 {QPointF(0.25, 0.07/0.35),QPointF(0.75, 0.07/0.35), DecorationLine::Width, DecorationLine::Width, DecorationLine::Width, DecorationLine::Width},
85 {QPointF(0.25, 0.38/0.35),QPointF(0.75, 0.38/0.35), DecorationLine::Width, DecorationLine::Width, DecorationLine::Width, DecorationLine::Width},
86 {QPointF(0.35/0.45, 0.0),QPointF(0.35/0.45, 1.0), DecorationLine::Height, DecorationLine::Height, DecorationLine::Height, DecorationLine::Height},
87
88 //Crosshair
91};
92
93#define DECORATION_COUNT 5
94const int decorsIndex[DECORATION_COUNT] = {0,4,12,18,20};
95
97 : KisTool(canvas, KisCursor::load("tool_crop_cursor.png", 6, 6))
98{
99 setObjectName("tool_crop");
100 m_handleSize = 13;
101 m_haveCropSelection = false;
102 m_cropTypeSelectable = false;
104 m_decoration = 1;
105
106 connect(&m_finalRect, SIGNAL(sigValuesChanged()), SLOT(slotRectChanged()));
107 connect(&m_finalRect, SIGNAL(sigLockValuesChanged()), SLOT(slotRectChanged()));
108
109 // context menu options (mirrors tool options)
110 m_contextMenu.reset(new QMenu());
111 applyCrop = new KisAction(i18n("Crop"));
112
113 centerToggleOption = new KisAction(i18n("Center"));
114 centerToggleOption->setCheckable(true);
115
116 growToggleOption = new KisAction(i18nc("Grow as in crop tool", "Grow"));
117 growToggleOption->setCheckable(true);
118
119 lockWidthToggleOption = new KisAction(i18n("Lock Width"));
120 lockWidthToggleOption->setCheckable(true);
121
122 lockHeightToggleOption = new KisAction(i18n("Lock Height"));
123 lockHeightToggleOption->setCheckable(true);
124
125 lockRatioToggleOption = new KisAction(i18n("Lock Ratio"));
126 lockRatioToggleOption->setCheckable(true);
127}
128
130{
131 delete applyCrop;
132 delete centerToggleOption;
133 delete growToggleOption;
137}
138
139void KisToolCrop::activate(const QSet<KoShape*> &shapes)
140{
141
142 KisTool::activate(shapes);
143 configGroup = KSharedConfig::openConfig()->group(toolId()); // save settings to kritarc
144
145 KisResourcesSnapshotSP resources =
146 new KisResourcesSnapshot(image(), currentNode(), this->canvas()->resourceManager());
147
148
149 // load settings from configuration
150 setGrowCenter(configGroup.readEntry("growCenter", false));
151 setAllowGrow(configGroup.readEntry("allowGrow", true));
152
153 // Default: thirds decoration
154 setDecoration(configGroup.readEntry("decoration", 1));
155
156 // Default: crop the entire image
157 setCropType(CropToolType(configGroup.readEntry("cropType", 0)));
158
160
161 KisSelectionSP sel = resources->activeSelection();
162 if (sel) {
163 m_haveCropSelection = true;
165 }
166 useCursor(cursor());
167
168 //pixel layer
169 if(resources->currentNode() && resources->currentNode()->paintDevice()) {
171 }
172 //vector layer
173 else {
176 }
178 }
179 connect(&m_finalRect, SIGNAL(sigValuesChanged()), SLOT(showSizeOnCanvas()));
180}
181
188
194
199
204
209
214
215void KisToolCrop::canvasResourceChanged(int key, const QVariant &res)
216{
218
219 //pixel layer
220 if(currentNode() && currentNode()->paintDevice()) {
222 }
223 //vector layer
224 else {
227 }
229 }
230}
231
232void KisToolCrop::paint(QPainter &painter, const KoViewConverter &converter)
233{
234 Q_UNUSED(converter);
236}
237
239{
240 if (m_contextMenu) {
241 // Sync state of context menu toggles with state of Tool Options toggles
242 centerToggleOption->setChecked(growCenter());
243 growToggleOption->setChecked(allowGrow());
244 lockWidthToggleOption->setChecked(lockWidth());
245 lockHeightToggleOption->setChecked(lockHeight());
246 lockRatioToggleOption->setChecked(lockRatio());
247
248 m_contextMenu->clear();
249
250 m_contextMenu->addSection(i18n("Crop Tool Actions"));
251 m_contextMenu->addSeparator();
252
253 if (m_haveCropSelection) { // can't crop if there is no selection
254 m_contextMenu->addAction(applyCrop);
255 m_contextMenu->addSeparator();
256 }
257
260
261 m_contextMenu->addSeparator();
262
266 }
267
268 return m_contextMenu.data();
269}
270
272{
275
276 const QPointF imagePoint = convertToPixelCoord(event);
278
281 QPointF snapDocPoint = image()->pixelToDocument(snapPoint);
282 m_dragOffsetDoc = snapDocPoint - event->point;
283 } else {
284 m_dragOffsetDoc = QPointF();
285 }
286
287 QPointF snappedPoint = convertToPixelCoordAndSnap(event, m_dragOffsetDoc);
288
289 m_dragStart = snappedPoint.toPoint();
290 m_resettingStroke = false;
291
294 const int initialWidth = m_finalRect.widthLocked() ? m_finalRect.rect().width() : 1;
295 const int initialHeight = m_finalRect.heightLocked() ? m_finalRect.rect().height() : 1;
296 const QRect initialRect = QRect(m_dragStart, QSize(initialWidth, initialHeight));
297 m_finalRect.setRectInitial(initialRect);
298 m_initialDragRect = initialRect;
300 m_resettingStroke = true;
301 } else {
303 }
304}
305
315
317{
318 bool result = false;
319
320 const KUndo2Command *lastCommand = image()->undoAdapter()->presentCommand();
321 const KisCropSavedExtraData *data = 0;
322
323 if ((lastCommand = image()->undoAdapter()->presentCommand()) &&
324 (data = dynamic_cast<const KisCropSavedExtraData*>(lastCommand->extraData()))) {
325
326 bool cropImageConsistent =
330
331 bool cropLayerConsistent =
334 currentNode() == data->cropNode();
335
336
337 if (cropImageConsistent || cropLayerConsistent) {
339 image()->waitForDone();
340
342 m_haveCropSelection = true;
343
344 result = true;
345 }
346 }
347
348 return result;
349}
350
352{
355
356 QRectF viewCropRect = pixelToView(m_finalRect.rect());
357 const bool haveValidRect =
358 viewCropRect.width() > m_handleSize &&
359 viewCropRect.height() > m_handleSize;
360
361
362 if (!m_haveCropSelection && !haveValidRect) {
365 m_haveCropSelection = true;
366 }
367 } else if (m_resettingStroke && !haveValidRect) {
369 m_haveCropSelection = false;
370 } else {
371 m_haveCropSelection = true;
372 }
373
375
378}
379
381{
382 QPointF pos = convertToPixelCoordAndSnap(event);
383
384 if (m_haveCropSelection) { //if the crop selection is set
385 //set resize cursor if we are on one of the handles
386 if(mode() == KisTool::PAINT_MODE) {
387 //keep the same cursor as the one we clicked with
389 }else{
390 //hovering
391 qint32 type = mouseOnHandle(pixelToView(pos));
393 }
394 }
395}
396
398{
400
401 // this action will have no continuation
402 event->ignore();
403}
404
405
406#define BORDER_LINE_WIDTH 0
407#define HALF_BORDER_LINE_WIDTH 0
408#define HANDLE_BORDER_LINE_WIDTH 1
409
411{
412 QRectF borderRect = pixelToView(m_finalRect.rect());
413
414 // Draw the border line right next to the crop rectangle perimeter.
416
417 return borderRect;
418}
419
420#define OUTSIDE_CROP_ALPHA 200
421
423{
425 gc.save();
426
427 QRectF wholeImageRect = pixelToView(image()->bounds());
428 QRectF borderRect = borderLineRect();
429
430 QPainterPath path;
431
432 path.addRect(wholeImageRect);
433 path.addRect(borderRect);
434 gc.setPen(Qt::NoPen);
435 gc.setBrush(QColor(0, 0, 0, OUTSIDE_CROP_ALPHA));
436 gc.drawPath(path);
437
438 // Handles
439 QPen pen(Qt::SolidLine);
441 pen.setColor(Qt::black);
442 pen.setCosmetic(true);
443 gc.setPen(pen);
444 gc.setBrush(QColor(200, 200, 200, OUTSIDE_CROP_ALPHA));
445 gc.drawPath(handlesPath());
446
447 gc.setClipRect(borderRect, Qt::IntersectClip);
448
449 if (m_decoration > 0) {
450 for (int i = decorsIndex[m_decoration-1]; i<decorsIndex[m_decoration]; i++) {
451 drawDecorationLine(&gc, &(decors[i]), borderRect);
452 }
453 }
454 gc.restore();
455 }
456}
457
459{
461 if (m_finalRect.rect().isEmpty()) return;
462
463 const bool imageCrop = m_cropType == ImageCropType || m_cropType == CanvasCropType;
464
465 if (!imageCrop) {
466 //Cropping layer
467 if (!nodeEditable()) {
468 return;
469 }
470 }
471
472 m_haveCropSelection = false;
473 useCursor(cursor());
474
475 QRect cropRect = m_finalRect.rect();
476
477 // The visitor adds the undo steps to the macro
478 if (imageCrop || !currentNode()->paintDevice()) {
479 if (m_cropType == CanvasCropType) {
480 currentImage()->resizeImage(cropRect);
481 } else {
482 currentImage()->cropImage(cropRect);
483 }
484 } else {
486 }
487}
488
490{
492}
493
495{
496 if(m_cropType == cropType)
497 return;
499
500 configGroup.writeEntry("cropType", static_cast<int>(cropType));
501
503}
504
509
511{
512 if(selectable == m_cropTypeSelectable)
513 return;
514 m_cropTypeSelectable = selectable;
516}
517
519{
521}
522
524{
525 return m_decoration;
526}
527
529{
530 // This shouldn't happen, but safety first
531 if(i < 0 || i > DECORATION_COUNT)
532 return;
533 m_decoration = i;
536
537 configGroup.writeEntry("decoration", i);
538}
539
540void KisToolCrop::doCanvasUpdate(const QRect &updateRect)
541{
543 m_lastCanvasUpdateRect = updateRect;
544}
545
547{
549 Q_EMIT cropWidthChanged(cropWidth());
550 Q_EMIT cropXChanged(cropX());
551 Q_EMIT cropYChanged(cropY());
552 Q_EMIT ratioChanged(ratio());
554 Q_EMIT lockWidthChanged(lockWidth());
555 Q_EMIT lockRatioChanged(lockRatio());
556
557 Q_EMIT canGrowChanged(allowGrow());
559
560 doCanvasUpdate(boundingRect().toAlignedRect());
561}
562
564{
565 if(x == m_finalRect.rect().x())
566 return;
567
568 if (!m_haveCropSelection) {
569 m_haveCropSelection = true;
571 }
572
573 QPoint offset = m_finalRect.rect().topLeft();
574 offset.setX(x);
575 m_finalRect.setOffset(offset);
576}
577
579{
580 return m_finalRect.rect().x();
581}
582
584{
585 if(y == m_finalRect.rect().y())
586 return;
587
588 if (!m_haveCropSelection) {
589 m_haveCropSelection = true;
591 }
592
593 QPoint offset = m_finalRect.rect().topLeft();
594 offset.setY(y);
595 m_finalRect.setOffset(offset);
596}
597
599{
600 return m_finalRect.rect().y();
601}
602
604{
605 if(w == m_finalRect.rect().width())
606 return;
607
608 if (!m_haveCropSelection) {
609 m_haveCropSelection = true;
611 }
612
614}
615
617{
618 return m_finalRect.rect().width();
619}
620
622{
624}
625
627{
628 return m_finalRect.widthLocked();
629}
630
632{
633 if(h == m_finalRect.rect().height())
634 return;
635
636 if (!m_haveCropSelection) {
637 m_haveCropSelection = true;
639 }
640
642}
643
645{
646 return m_finalRect.rect().height();
647}
648
650{
652}
653
655{
656 return m_finalRect.heightLocked();
657}
658
660{
663 configGroup.writeEntry("allowGrow", g);
664
665 Q_EMIT canGrowChanged(g);
666}
667
669{
670 return m_finalRect.canGrow();
671}
672
674{
676
677
678 configGroup.writeEntry("growCenter", value);
679
680 Q_EMIT isCenteredChanged(value);
681}
682
684{
685 return m_finalRect.centered();
686}
687
688void KisToolCrop::setRatio(double ratio)
689{
690 if(ratio == m_finalRect.ratio())
691 return;
692
693 if (!m_haveCropSelection) {
694 m_haveCropSelection = true;
696 }
697
699}
700
701double KisToolCrop::ratio() const
702{
703 return m_finalRect.ratio();
704}
705
707{
709}
710
712{
713 return m_finalRect.ratioLocked();
714}
715
717{
718 KisCanvas2 *kisCanvas =dynamic_cast<KisCanvas2*>(canvas());
719 Q_ASSERT(kisCanvas);
720 if(m_mouseOnHandleType == 9) {
721 kisCanvas->viewManager()->showFloatingMessage(i18n("X: %1\nY: %2"
722 , optionsWidget->intX->text(), optionsWidget->intY->text())
723 , QIcon(), 1000, KisFloatingMessage::High, Qt::AlignLeft | Qt::TextWordWrap | Qt::AlignVCenter);
724 }
725 else {
726 kisCanvas->viewManager()->showFloatingMessage(i18n("Width: %1\nHeight: %2"
727 , optionsWidget->intWidth->text(), optionsWidget->intHeight->text())
728 , QIcon(), 1000, KisFloatingMessage::High, Qt::AlignLeft | Qt::TextWordWrap | Qt::AlignVCenter);
729 }
730}
731
733{
735 // See https://bugs.kde.org/show_bug.cgi?id=316896
736 QWidget *specialSpacer = new QWidget(optionsWidget);
737 specialSpacer->setObjectName("SpecialSpacer");
738 specialSpacer->setFixedSize(0, 0);
739 optionsWidget->layout()->addWidget(specialSpacer);
740
741 Q_CHECK_PTR(optionsWidget);
742 optionsWidget->setObjectName(toolId() + " option widget");
743
744 connect(optionsWidget->bnCrop, SIGNAL(clicked()), this, SLOT(crop()));
745
746 connect(optionsWidget, SIGNAL(cropTypeChanged(int)), this, SLOT(setCropTypeLegacy(int)));
747 connect(optionsWidget, SIGNAL(cropXChanged(int)), this, SLOT(setCropX(int)));
748 connect(optionsWidget, SIGNAL(cropYChanged(int)), this, SLOT(setCropY(int)));
749 connect(optionsWidget, SIGNAL(cropHeightChanged(int)), this, SLOT(setCropHeight(int)));
750 connect(optionsWidget, SIGNAL(lockHeightChanged(bool)), this, SLOT(setLockHeight(bool)));
751 connect(optionsWidget, SIGNAL(cropWidthChanged(int)), this, SLOT(setCropWidth(int)));
752 connect(optionsWidget, SIGNAL(lockWidthChanged(bool)), this, SLOT(setLockWidth(bool)));
753 connect(optionsWidget, SIGNAL(ratioChanged(double)), this, SLOT(setRatio(double)));
754 connect(optionsWidget, SIGNAL(lockRatioChanged(bool)), this, SLOT(setLockRatio(bool)));
755 connect(optionsWidget, SIGNAL(decorationChanged(int)), this, SLOT(setDecoration(int)));
756 connect(optionsWidget, SIGNAL(allowGrowChanged(bool)), this, SLOT(setAllowGrow(bool)));
757 connect(optionsWidget, SIGNAL(growCenterChanged(bool)), this, SLOT(setGrowCenter(bool)));
758
759 optionsWidget->setFixedHeight(optionsWidget->sizeHint().height());
760
761 connect(applyCrop, SIGNAL(triggered(bool)), this, SLOT(crop()));
762 connect(centerToggleOption, SIGNAL(triggered(bool)), this, SLOT(setGrowCenter(bool)));
763 connect(growToggleOption, SIGNAL(triggered(bool)), this, SLOT(setAllowGrow(bool)));
764 connect(lockWidthToggleOption, SIGNAL(triggered(bool)), this, SLOT(setLockWidth(bool)));
765 connect(lockHeightToggleOption, SIGNAL(triggered(bool)), this, SLOT(setLockHeight(bool)));
766 connect(lockRatioToggleOption, SIGNAL(triggered(bool)), this, SLOT(setLockRatio(bool)));
767
768 return optionsWidget;
769}
770
771QRectF KisToolCrop::lowerRightHandleRect(QRectF cropBorderRect)
772{
773 return QRectF(cropBorderRect.right() - m_handleSize / 2.0, cropBorderRect.bottom() - m_handleSize / 2.0, m_handleSize, m_handleSize);
774}
775
776QRectF KisToolCrop::upperRightHandleRect(QRectF cropBorderRect)
777{
778 return QRectF(cropBorderRect.right() - m_handleSize / 2.0 , cropBorderRect.top() - m_handleSize / 2.0, m_handleSize, m_handleSize);
779}
780
781QRectF KisToolCrop::lowerLeftHandleRect(QRectF cropBorderRect)
782{
783 return QRectF(cropBorderRect.left() - m_handleSize / 2.0 , cropBorderRect.bottom() - m_handleSize / 2.0, m_handleSize, m_handleSize);
784}
785
786QRectF KisToolCrop::upperLeftHandleRect(QRectF cropBorderRect)
787{
788 return QRectF(cropBorderRect.left() - m_handleSize / 2.0, cropBorderRect.top() - m_handleSize / 2.0, m_handleSize, m_handleSize);
789}
790
791QRectF KisToolCrop::lowerHandleRect(QRectF cropBorderRect)
792{
793 return QRectF(cropBorderRect.left() + (cropBorderRect.width() - m_handleSize) / 2.0 , cropBorderRect.bottom() - m_handleSize / 2.0, m_handleSize, m_handleSize);
794}
795
796QRectF KisToolCrop::rightHandleRect(QRectF cropBorderRect)
797{
798 return QRectF(cropBorderRect.right() - m_handleSize / 2.0 , cropBorderRect.top() + (cropBorderRect.height() - m_handleSize) / 2.0, m_handleSize, m_handleSize);
799}
800
801QRectF KisToolCrop::upperHandleRect(QRectF cropBorderRect)
802{
803 return QRectF(cropBorderRect.left() + (cropBorderRect.width() - m_handleSize) / 2.0 , cropBorderRect.top() - m_handleSize / 2.0, m_handleSize, m_handleSize);
804}
805
806QRectF KisToolCrop::leftHandleRect(QRectF cropBorderRect)
807{
808 return QRectF(cropBorderRect.left() - m_handleSize / 2.0, cropBorderRect.top() + (cropBorderRect.height() - m_handleSize) / 2.0, m_handleSize, m_handleSize);
809}
810
812{
813 QRectF cropBorderRect = borderLineRect();
814 QPainterPath path;
815
816 path.addRect(upperLeftHandleRect(cropBorderRect));
817 path.addRect(upperRightHandleRect(cropBorderRect));
818 path.addRect(lowerLeftHandleRect(cropBorderRect));
819 path.addRect(lowerRightHandleRect(cropBorderRect));
820 path.addRect(upperHandleRect(cropBorderRect));
821 path.addRect(lowerHandleRect(cropBorderRect));
822 path.addRect(leftHandleRect(cropBorderRect));
823 path.addRect(rightHandleRect(cropBorderRect));
824
825 return path;
826}
827
828qint32 KisToolCrop::mouseOnHandle(QPointF currentViewPoint)
829{
830 QRectF borderRect = borderLineRect();
831 qint32 handleType = None;
832
833 if (!m_haveCropSelection) {
834 return None;
835 }
836
837 if (upperLeftHandleRect(borderRect).contains(currentViewPoint)) {
839 } else if (lowerLeftHandleRect(borderRect).contains(currentViewPoint)) {
841 } else if (upperRightHandleRect(borderRect).contains(currentViewPoint)) {
843 } else if (lowerRightHandleRect(borderRect).contains(currentViewPoint)) {
845 } else if (upperHandleRect(borderRect).contains(currentViewPoint)) {
847 } else if (lowerHandleRect(borderRect).contains(currentViewPoint)) {
849 } else if (leftHandleRect(borderRect).contains(currentViewPoint)) {
851 } else if (rightHandleRect(borderRect).contains(currentViewPoint)) {
853 } else if (borderRect.contains(currentViewPoint)) {
855 }
856
857 return handleType;
858}
859
861{
862 QCursor cursorType;
863
864 switch (handle) {
865 case(UpperLeft):
866 case(LowerRight):
867 cursorType = KisCursor::sizeFDiagCursor();
868 break;
869 case(LowerLeft):
870 case(UpperRight):
871 cursorType = KisCursor::sizeBDiagCursor();
872 break;
873 case(Upper):
874 case(Lower):
875 cursorType = KisCursor::sizeVerCursor();
876 break;
877 case(Left):
878 case(Right):
879 cursorType = KisCursor::sizeHorCursor();
880 break;
881 case(Inside):
882 cursorType = KisCursor::sizeAllCursor();
883 break;
884 default:
886 cursorType = KisCursor::arrowCursor();
887 } else {
888 cursorType = cursor();
889 }
890 break;
891 }
892 useCursor(cursorType);
893}
894
901
902void KisToolCrop::drawDecorationLine(QPainter *p, DecorationLine *decorLine, const QRectF rect)
903{
904 QPointF start = rect.topLeft();
905 QPointF end = rect.topLeft();
906 qreal small = qMin(rect.width(), rect.height());
907 qreal large = qMax(rect.width(), rect.height());
908
909 switch (decorLine->startXRelation) {
911 start.setX(start.x() + decorLine->start.x() * rect.width());
912 break;
914 start.setX(start.x() + decorLine->start.x() * rect.height());
915 break;
917 start.setX(start.x() + decorLine->start.x() * small);
918 break;
920 start.setX(start.x() + decorLine->start.x() * large);
921 break;
922 }
923
924 switch (decorLine->startYRelation) {
926 start.setY(start.y() + decorLine->start.y() * rect.width());
927 break;
929 start.setY(start.y() + decorLine->start.y() * rect.height());
930 break;
932 start.setY(start.y() + decorLine->start.y() * small);
933 break;
935 start.setY(start.y() + decorLine->start.y() * large);
936 break;
937 }
938
939 switch (decorLine->endXRelation) {
941 end.setX(end.x() + decorLine->end.x() * rect.width());
942 break;
944 end.setX(end.x() + decorLine->end.x() * rect.height());
945 break;
947 end.setX(end.x() + decorLine->end.x() * small);
948 break;
950 end.setX(end.x() + decorLine->end.x() * large);
951 break;
952 }
953
954 switch (decorLine->endYRelation) {
956 end.setY(end.y() + decorLine->end.y() * rect.width());
957 break;
959 end.setY(end.y() + decorLine->end.y() * rect.height());
960 break;
962 end.setY(end.y() + decorLine->end.y() * small);
963 break;
965 end.setY(end.y() + decorLine->end.y() * large);
966 break;
967 }
968
969 p->drawLine(start, end);
970}
float value(const T *src, size_t ch)
const Params2D p
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
KUndo2CommandExtraData * extraData() const
KisViewManager * viewManager() const
void moveHandle(HandleType handle, const QPoint &offset, const QRect &oldRect)
void setRectInitial(const QRect &rect)
QPointF handleSnapPoint(HandleType handle, const QPointF &cursorPos)
void setCropRect(const QRect &cropRect)
void setCentered(bool value)
void setCanGrow(bool value)
void setOffset(const QPoint &offset)
void setHeightLocked(bool value)
void setRatioLocked(bool value)
void setWidthLocked(bool value)
static QCursor sizeBDiagCursor()
Definition kis_cursor.cc:74
static QCursor sizeAllCursor()
Definition kis_cursor.cc:84
static QCursor sizeHorCursor()
Definition kis_cursor.cc:69
static QCursor sizeFDiagCursor()
Definition kis_cursor.cc:79
static QCursor arrowCursor()
Definition kis_cursor.cc:24
static QCursor sizeVerCursor()
Definition kis_cursor.cc:64
void resizeImage(const QRect &newRect)
start asynchronous operation on resizing the image
Definition kis_image.cc:865
KisUndoAdapter * undoAdapter() const
void waitForDone()
void cropNode(KisNodeSP node, const QRect &newRect, const bool activeFrameOnly=false)
start asynchronous operation on cropping a subtree of nodes starting at node
Definition kis_image.cc:931
QPointF pixelToDocument(const QPointF &pixelCoord) const
void cropImage(const QRect &newRect)
start asynchronous operation on cropping the image
Definition kis_image.cc:870
QRect bounds() const override
The KisResourcesSnapshot class takes a snapshot of the various resources like colors and settings use...
KisSelectionSP activeSelection() const
void requestStrokeCancellation() override
void setAllowGrow(bool g)
KisAction * lockRatioToggleOption
bool m_resettingStroke
void requestUndoDuringStroke() override
void setGrowCenter(bool g)
void cropWidthChanged(int value)
bool tryContinueLastCropAction()
QRectF lowerRightHandleRect(QRectF cropBorderRect)
void requestRedoDuringStroke() override
QWidget * createOptionWidget() override
void paint(QPainter &painter, const KoViewConverter &converter) override
void slotRectChanged()
void requestStrokeEnd() override
QRect m_lastCanvasUpdateRect
bool m_cropTypeSelectable
void setLockHeight(bool lock)
void setCropHeight(int y)
KisAction * centerToggleOption
QRect m_initialDragRect
void decorationChanged(int value)
QRectF upperRightHandleRect(QRectF cropBorderRect)
void setCropX(int x)
KisToolCrop(KoCanvasBase *canvas)
void setCropType(CropToolType cropType)
KisAction * lockHeightToggleOption
void cropTypeChanged(int value)
void ratioChanged(double value)
void beginPrimaryAction(KoPointerEvent *event) override
bool growCenter() const
void setMoveResizeCursor(qint32 handle)
~KisToolCrop() override
void activate(const QSet< KoShape * > &shapes) override
void setCropTypeLegacy(int cropType)
void cropXChanged(int value)
CropToolType m_cropType
QRectF lowerLeftHandleRect(QRectF cropBorderRect)
QRectF upperHandleRect(QRectF cropBorderRect)
void doCanvasUpdate(const QRect &updateRect)
qint32 mouseOnHandle(const QPointF currentViewPoint)
QPoint m_dragStart
QMenu * popupActionsMenu() override
void deactivate() override
void canGrowChanged(bool value)
void canvasResourceChanged(int key, const QVariant &res) override
void setDecoration(int i)
void continuePrimaryAction(KoPointerEvent *event) override
qint32 m_handleSize
CropToolType cropType
KisToolCropConfigWidget * optionsWidget
QRectF leftHandleRect(QRectF cropBorderRect)
void mouseMoveEvent(KoPointerEvent *e) override
QRectF boundingRect()
void setRatio(double ratio)
QRectF borderLineRect()
void endPrimaryAction(KoPointerEvent *event) override
void lockRatioChanged(bool value)
qint32 m_mouseOnHandleType
KConfigGroup configGroup
void isCenteredChanged(bool value)
void cancelStroke()
QRectF rightHandleRect(QRectF cropBorderRect)
void drawDecorationLine(QPainter *p, DecorationLine *decorLine, QRectF rect)
void cropYChanged(int value)
void setCropWidth(int x)
bool m_haveCropSelection
QPointF m_dragOffsetDoc
bool cropTypeSelectable
void cropHeightChanged(int value)
void setCropY(int y)
KisAction * applyCrop
QRectF lowerHandleRect(QRectF cropBorderRect)
bool allowGrow() const
KisAction * growToggleOption
QScopedPointer< QMenu > m_contextMenu
KisAction * lockWidthToggleOption
void paintOutlineWithHandles(QPainter &gc)
QPainterPath handlesPath()
void cropTypeSelectableChanged()
void lockHeightChanged(bool value)
QRectF upperLeftHandleRect(QRectF cropBorderRect)
KisConstrainedRect m_finalRect
void showSizeOnCanvas()
void setLockWidth(bool lock)
void lockWidthChanged(bool value)
void setLockRatio(bool lock)
void setCropTypeSelectable(bool selectable)
void beginPrimaryDoubleClickAction(KoPointerEvent *event) override
virtual void undoLastCommand()=0
virtual const KUndo2Command * presentCommand()=0
void showFloatingMessage(const QString &message, const QIcon &icon, int timeout=4500, KisFloatingMessage::Priority priority=KisFloatingMessage::Medium, int alignment=Qt::AlignCenter|Qt::TextWordWrap)
shows a floating message in the top right corner of the canvas
Q_INVOKABLE QString toolId() const
void useCursor(const QCursor &cursor)
int decorationThickness() const
decorationThickness The minimum thickness for tool decoration lines, this is derived from the screen ...
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
#define bounds(x, a, b)
#define CHECK_MODE_SANITY_OR_RETURN(_mode)
Definition kis_tool.h:27
#define OUTSIDE_CROP_ALPHA
#define DECORATION_COUNT
#define HANDLE_BORDER_LINE_WIDTH
#define HALF_BORDER_LINE_WIDTH
DecorationLine decors[20]
const int decorsIndex[DECORATION_COUNT]
Relation endYRelation
Relation startXRelation
Relation endXRelation
Relation startYRelation
virtual KisPaintDeviceSP paintDevice() const =0
QRect selectedExactRect() const
Slow, but exact way of determining the rectangle that encloses the selection.
QPointF convertToPixelCoord(KoPointerEvent *e)
Definition kis_tool.cc:189
virtual ToolMode mode() const
Definition kis_tool.cc:407
KisImageWSP currentImage()
Definition kis_tool.cc:393
bool nodeEditable()
Checks checks if the current node is editable.
Definition kis_tool.cc:651
QPointF pixelToView(const QPoint &pixelCoord) const
Definition kis_tool.cc:269
KisNodeSP currentNode() const
Definition kis_tool.cc:370
void canvasResourceChanged(int key, const QVariant &res) override
Definition kis_tool.cc:139
void activate(const QSet< KoShape * > &shapes) override
Definition kis_tool.cc:93
void deactivate() override
Definition kis_tool.cc:131
KisImageWSP image() const
Definition kis_tool.cc:332
@ PAINT_MODE
Definition kis_tool.h:300
@ HOVER_MODE
Definition kis_tool.h:299
QPointF convertToPixelCoordAndSnap(KoPointerEvent *e, const QPointF &offset=QPointF(), bool useModifiers=true)
Definition kis_tool.cc:214
void updateCanvasViewRect(const QRectF &viewRect)
Update the canvas for the given rectangle in view coordinates.
Definition kis_tool.cc:327
QCursor cursor
Definition kis_tool.cc:64
virtual void setMode(ToolMode mode)
Definition kis_tool.cc:403
KisCanvas2 * canvas