Krita Source Code Documentation
Loading...
Searching...
No Matches
KisAssistantTool Class Reference

#include <kis_assistant_tool.h>

+ Inheritance diagram for KisAssistantTool:

Public Slots

void activate (const QSet< KoShape * > &shapes) override
 
void deactivate () override
 
void slotChangeFixedLength (double value)
 
void slotChangeMinorSubdivisions (int value)
 
void slotChangeSubdivisions (int value)
 
void slotChangeTwoPointDensity (double value)
 
void slotChangeTwoPointUseVertical (int value)
 
void slotChangeVanishingPointAngle (double value)
 
void slotEnableFixedLength (int enabled)
 
- Public Slots inherited from KisTool
void activate (const QSet< KoShape * > &shapes) override
 
void canvasResourceChanged (int key, const QVariant &res) override
 
void deactivate () override
 
virtual void updateSettingsViews ()
 
- Public Slots inherited from KoToolBase
virtual void activate (const QSet< KoShape * > &shapes)
 
virtual void canvasResourceChanged (int key, const QVariant &res)
 
virtual void deactivate ()
 
virtual void documentResourceChanged (int key, const QVariant &res)
 
virtual void repaintDecorations ()
 
virtual void requestRedoDuringStroke ()
 
virtual void requestStrokeCancellation ()
 
virtual void requestStrokeEnd ()
 
virtual void requestUndoDuringStroke ()
 
void setStatusText (const QString &statusText)
 
void updateOptionsWidgetIcons ()
 

Public Member Functions

void beginAlternateAction (KoPointerEvent *event, KisTool::AlternateAction action) override
 
void beginPrimaryAction (KoPointerEvent *event) override
 
void continueAlternateAction (KoPointerEvent *event, AlternateAction action) override
 
void continuePrimaryAction (KoPointerEvent *event) override
 
QWidget * createOptionWidget () override
 
void endAlternateAction (KoPointerEvent *event, AlternateAction action) override
 
void endPrimaryAction (KoPointerEvent *event) override
 
void keyPressEvent (QKeyEvent *event) override
 
 KisAssistantTool (KoCanvasBase *canvas)
 
void mouseMoveEvent (KoPointerEvent *event) override
 
virtual quint32 priority ()
 
 ~KisAssistantTool () override
 
- Public Member Functions inherited from KisTool
virtual void activateAlternateAction (AlternateAction action)
 
virtual void activatePrimaryAction ()
 
virtual bool alternateActionSupportsHiResEvents (AlternateAction action) const
 
virtual void beginAlternateDoubleClickAction (KoPointerEvent *event, AlternateAction action)
 
virtual void beginPrimaryDoubleClickAction (KoPointerEvent *event)
 
virtual void deactivateAlternateAction (AlternateAction action)
 
virtual void deactivatePrimaryAction ()
 
void deleteSelection () override
 
virtual int flags () const
 
bool isActive () const
 
 KisTool (KoCanvasBase *canvas, const QCursor &cursor)
 
void mouseDoubleClickEvent (KoPointerEvent *event) override
 
void mouseMoveEvent (KoPointerEvent *event) override
 
void mousePressEvent (KoPointerEvent *event) override
 
void mouseReleaseEvent (KoPointerEvent *event) override
 
void mouseTripleClickEvent (KoPointerEvent *event) override
 
virtual void newActivationWithExternalSource (KisPaintDeviceSP externalSource)
 newActivationWithExternalSource Makes sure that the tool is active and starts a new stroke, which will be able to access the pixels from the specified external source.
 
KisTool::NodePaintAbility nodePaintAbility ()
 
virtual bool primaryActionSupportsHiResEvents () const
 
virtual bool supportsPaintingAssistants () const
 
 ~KisTool () override
 
- Public Member Functions inherited from Private
 Private (KisCanvas2 *c)
 
- Public Member Functions inherited from KoToolBase
QAction * action (const QString &name) const
 
KoCanvasBasecanvas () const
 Returns the canvas the tool is working on.
 
virtual void copy () const
 
QCursor cursor () const
 return the last emitted cursor
 
virtual void customMoveEvent (KoPointerEvent *event)
 
virtual void customPressEvent (KoPointerEvent *event)
 
virtual void customReleaseEvent (KoPointerEvent *event)
 
virtual void cut ()
 
virtual QRectF decorationsRect () const
 
int decorationThickness () const
 decorationThickness The minimum thickness for tool decoration lines, this is derived from the screen magnification, thus the HiDPI settings. Note: to use this effectively, also set the pen to isCosmetic(true);
 
virtual void deselect ()
 deselect the tool should clear the selection if it has one.
 
virtual void dragLeaveEvent (QDragLeaveEvent *event)
 
virtual void dragMoveEvent (QDragMoveEvent *event, const QPointF &point)
 
virtual void dropEvent (QDropEvent *event, const QPointF &point)
 
virtual void explicitUserStrokeEndRequest ()
 explicitUserStrokeEndRequest is called by the input manager when the user presses the Enter key or any equivalent key. This callback comes before requestStrokeEnd(), which comes from a different source.
 
KoToolFactoryBasefactory () const
 
virtual void focusInEvent (QFocusEvent *event)
 
virtual void focusOutEvent (QFocusEvent *event)
 
virtual bool hasSelection ()
 
virtual void inputMethodEvent (QInputMethodEvent *event)
 
virtual QVariant inputMethodQuery (Qt::InputMethodQuery query) const
 
bool isInTextMode () const
 
bool isOpacityPresetMode () const
 
virtual void keyReleaseEvent (QKeyEvent *event)
 
 KoToolBase (KoCanvasBase *canvas)
 
bool maskSyntheticEvents () const
 
QList< QPointer< QWidget > > optionWidgets ()
 
virtual bool paste ()
 
virtual QMenu * popupActionsMenu ()
 
virtual KisPopupWidgetInterfacepopupWidget ()
 
virtual bool selectAll ()
 selectAll select all data the tool can select.
 
virtual KoToolSelectionselection ()
 
Q_INVOKABLE QString toolId () const
 
virtual bool wantsAutoScroll () const
 
 ~KoToolBase () override
 

Protected Member Functions

void paint (QPainter &gc, const KoViewConverter &converter) override
 
- Protected Member Functions inherited from KisTool
bool blockUntilOperationsFinished ()
 
void blockUntilOperationsFinishedForced ()
 
QPointF convertDocumentToWidget (const QPointF &pt)
 
QPoint convertToImagePixelCoordFloored (KoPointerEvent *e)
 
QPointF convertToPixelCoord (const QPointF &pt)
 
QPointF convertToPixelCoord (KoPointerEvent *e)
 
QPointF convertToPixelCoordAndAlignOnWidget (const QPointF &pt)
 
QPointF convertToPixelCoordAndSnap (const QPointF &pt, const QPointF &offset=QPointF())
 
QPointF convertToPixelCoordAndSnap (KoPointerEvent *e, const QPointF &offset=QPointF(), bool useModifiers=true)
 
QRectF convertToPt (const QRectF &rect)
 
qreal convertToPt (qreal value)
 
QWidget * createOptionWidget () override
 
KoColor currentBgColor ()
 
KoColor currentFgColor ()
 
KisFilterConfigurationSP currentGenerator ()
 
KoAbstractGradientSP currentGradient ()
 
KisImageWSP currentImage ()
 
KisNodeSP currentNode () const
 
KisPaintOpPresetSP currentPaintOpPreset ()
 
KoPatternSP currentPattern ()
 
QCursor cursor () const
 
KisImageWSP image () const
 
virtual bool listeningToModifiers ()
 
virtual void listenToModifiers (bool listen)
 
virtual ToolMode mode () const
 
bool nodeEditable ()
 Checks checks if the current node is editable.
 
bool overrideCursorIfNotEditable ()
 Override the cursor appropriately if current node is not editable.
 
void paintToolOutline (QPainter *painter, const KisOptimizedBrushOutline &path)
 
KisOptimizedBrushOutline pixelToView (const KisOptimizedBrushOutline &path) const
 
QPainterPath pixelToView (const QPainterPath &pixelPath) const
 Convert a pixel path into a view path.
 
QPointF pixelToView (const QPoint &pixelCoord) const
 
QPointF pixelToView (const QPointF &pixelCoord) const
 Convert a floating point pixel coordinate into a view coordinate.
 
QPolygonF pixelToView (const QPolygonF &pixelPolygon) const
 Convert a pixel polygon into a view path.
 
QRectF pixelToView (const QRectF &pixelRect) const
 Convert a pixel rectangle into a view rectangle.
 
KisNodeList selectedNodes () const
 
bool selectionEditable ()
 Checks checks if the selection is editable, only applies to local selection as global selection is always editable.
 
void setCursor (const QCursor &cursor)
 
virtual void setMode (ToolMode mode)
 
void updateCanvasPixelRect (const QRectF &pixelRect)
 Update the canvas for the given rectangle in image pixel coordinates.
 
void updateCanvasViewRect (const QRectF &viewRect)
 Update the canvas for the given rectangle in view coordinates.
 
QPointF viewToPixel (const QPointF &viewCoord) const
 
QPointF widgetCenterInWidgetPixels ()
 
- Protected Member Functions inherited from KoToolBase
virtual QList< QPointer< QWidget > > createOptionWidgets ()
 
int grabSensitivity () const
 Convenience function to get the current grab sensitivity.
 
qreal handleDocRadius () const
 
QRectF handleGrabRect (const QPointF &position) const
 
QRectF handlePaintRect (const QPointF &position) const
 
int handleRadius () const
 Convenience function to get the current handle radius.
 
bool isActivated () const
 
 KoToolBase (KoToolBasePrivate &dd)
 
KoPointerEventlastDeliveredPointerEvent () const
 
void setAbstractResource (KoAbstractCanvasResourceInterfaceSP abstractResource)
 
void setConverter (KoDerivedResourceConverterSP converter)
 
void setIsOpacityPresetMode (bool value)
 
void setMaskSyntheticEvents (bool value)
 
void setTextMode (bool value)
 
QHash< int, KoAbstractCanvasResourceInterfaceSPtoolAbstractResources ()
 
QHash< int, KoDerivedResourceConverterSPtoolConverters ()
 
void useCursor (const QCursor &cursor)
 

Protected Attributes

bool assistantDuplicatingFlag {false}
 
KisPaintingAssistantSP m_assistantDrag
 
QPointer< KisCanvas2m_canvas
 
QPointF m_currentAdjustment
 
QPointF m_cursorStart
 
QPointF m_dragEnd
 
QPointF m_dragStart
 
KisPaintingAssistantHandleSP m_handleCombine
 
KisPaintingAssistantHandleSP m_handleDrag
 
KisPaintingAssistantHandleSP m_handleHover
 
int m_handleMaxDist {81}
 
QList< KisPaintingAssistantHandleSPm_handles
 
int m_handleSize {17}
 
KisPaintingAssistantSP m_newAssistant
 
Ui::AssistantsToolOptions m_options
 
QWidget * m_optionsWidget {0}
 
QPointF m_previousHandlePos
 
QLineF m_radius
 
QList< KisPaintingAssistantHandleSPm_sideHandles
 
bool m_snapIsRadial {false}
 
- Protected Attributes inherited from KoToolBase
KoToolBasePrivated_ptr
 

Private Types

enum  PerspectiveAssistantEditionMode {
  MODE_CREATION , MODE_EDITING , MODE_DRAGGING_NODE , MODE_DRAGGING_TRANSLATING_TWONODES ,
  MODE_DRAGGING_EDITOR_WIDGET
}
 

Private Slots

void loadAssistants ()
 
void removeAllAssistants ()
 
void saveAssistants ()
 
void slotChangeFixedLengthUnit (int index)
 
void slotCustomOpacityChanged ()
 
void slotGlobalAssistantOpacityChanged ()
 
void slotGlobalAssistantsColorChanged (const QColor &)
 
void slotLocalAssistantCheckboxChanged ()
 
void slotSelectedAssistantTypeChanged ()
 
void slotToggleDeleteButton (int index)
 
void slotToggleDockToolOptionsVisible ()
 
void slotToggleDuplicateButton (int index)
 
void slotToggleLockButton (int index)
 
void slotToggleMoveButton (int index)
 
void slotToggleSnapButton (int index)
 
void slotUpdateCustomColor ()
 
void updateToolOptionsUI ()
 

Private Member Functions

void addAssistant ()
 
void assistantSelected (KisPaintingAssistantSP assistant)
 
void beginActionImpl (KoPointerEvent *event)
 
void continueActionImpl (KoPointerEvent *event)
 
void drawEditorWidget (KisPaintingAssistantSP assistant, QPainter &_gc)
 
void endActionImpl (KoPointerEvent *event)
 
void removeAssistant (KisPaintingAssistantSP assistant)
 
bool snap (KoPointerEvent *event)
 
void updateEditorWidgetData ()
 

Private Attributes

int m_assistantHelperYOffset {10}
 
KisPaintingAssistantHandleSP m_highlightedNode
 
PerspectiveAssistantEditionMode m_internalMode { MODE_CREATION }
 
QList< KisPaintingAssistantSPm_origAssistantList
 
KisPaintingAssistantHandleSP m_selectedNode1
 
KisPaintingAssistantHandleSP m_selectedNode2
 
KisSpinBoxUnitManagerm_unitManager {0}
 
bool ToggleDockToolOptionsVisible = false
 

Additional Inherited Members

- Public Types inherited from KisTool
enum  { FLAG_USES_CUSTOM_PRESET =0x01 , FLAG_USES_CUSTOM_COMPOSITEOP =0x02 , FLAG_USES_CUSTOM_SIZE =0x04 }
 
enum  AlternateAction {
  ChangeSize = AlternateChangeSize , ChangeSizeSnap = AlternateChangeSizeSnap , SampleFgNode = AlternateSampleFgNode , SampleBgNode = AlternateSampleBgNode ,
  SampleFgImage = AlternateSampleFgImage , SampleBgImage = AlternateSampleBgImage , Secondary = AlternateSecondary , Third = AlternateThird ,
  Fourth = AlternateFourth , Fifth = AlternateFifth , NONE = 10000
}
 
enum  NodePaintAbility {
  VECTOR , CLONE , PAINT , UNPAINTABLE ,
  MYPAINTBRUSH_UNPAINTABLE
}
 
enum  ToolAction {
  Primary , AlternateChangeSize , AlternateChangeSizeSnap , AlternateSampleFgNode ,
  AlternateSampleBgNode , AlternateSampleFgImage , AlternateSampleBgImage , AlternateSecondary ,
  AlternateThird , AlternateFourth , AlternateFifth , Alternate_NONE = 10000
}
 
- Signals inherited from KisTool
void isActiveChanged (bool isActivated)
 
- Signals inherited from KoToolBase
void activateTool (const QString &id)
 
void cursorChanged (const QCursor &cursor)
 
void selectionChanged (bool hasSelection)
 
void statusTextChanged (const QString &statusText)
 
void textModeChanged (bool inTextMode)
 
- Static Public Member Functions inherited from KisTool
static AlternateAction actionToAlternateAction (ToolAction action)
 
- Public Attributes inherited from KisTool
KoColor currentBgColor
 
float currentExposure {1.0}
 
KoColor currentFgColor
 
KisFilterConfigurationSP currentGenerator
 
KoAbstractGradientSP currentGradient
 
KoPatternSP currentPattern
 
QCursor cursor
 
bool m_isActive {false}
 
ToolMode m_mode {HOVER_MODE}
 
QWidget * optionWidget {0}
 
- Public Attributes inherited from Private
KisCanvas2canvas
 
int displayedFrame
 
int intendedFrame
 
- Protected Types inherited from KisTool
enum  ToolMode : int {
  HOVER_MODE , PAINT_MODE , SECONDARY_PAINT_MODE , MIRROR_AXIS_SETUP_MODE ,
  GESTURE_MODE , PAN_MODE , OTHER , OTHER_1
}
 
- Protected Slots inherited from KisTool
virtual void resetCursorStyle ()
 
- Properties inherited from KisTool
bool isActive
 

Detailed Description

Definition at line 34 of file kis_assistant_tool.h.

Member Enumeration Documentation

◆ PerspectiveAssistantEditionMode

Enumerator
MODE_CREATION 
MODE_EDITING 
MODE_DRAGGING_NODE 
MODE_DRAGGING_TRANSLATING_TWONODES 
MODE_DRAGGING_EDITOR_WIDGET 

Definition at line 37 of file kis_assistant_tool.h.

37 {
38 MODE_CREATION, // This is the mode when there is not yet a perspective grid
39 MODE_EDITING, // This is the mode when the grid has been created, and we are waiting for the user to click on a control box
40 MODE_DRAGGING_NODE, // In this mode one node is translated
41 MODE_DRAGGING_TRANSLATING_TWONODES, // This mode is used when creating a new sub perspective grid
42 MODE_DRAGGING_EDITOR_WIDGET // This mode is used when dragging/moving the little editor widget
43 };

Constructor & Destructor Documentation

◆ KisAssistantTool()

KisAssistantTool::KisAssistantTool ( KoCanvasBase * canvas)

Definition at line 53 of file kis_assistant_tool.cc.

55 , m_canvas(dynamic_cast<KisCanvas2*>(canvas))
60{
61 Q_ASSERT(m_canvas);
62 setObjectName("tool_assistanttool");
63}
KisPaintingAssistantSP m_assistantDrag
KisPaintingAssistantSP m_newAssistant
KisSpinBoxUnitManager * m_unitManager
QPointer< KisCanvas2 > m_canvas
static QCursor arrowCursor()
Definition kis_cursor.cc:24
The KisDocumentAwareSpinBoxUnitManager class is a KisSpinBoxUnitManager that is able to connect to th...
KisTool(KoCanvasBase *canvas, const QCursor &cursor)
Definition kis_tool.cc:78
KisCanvas2 * canvas

References m_canvas.

◆ ~KisAssistantTool()

KisAssistantTool::~KisAssistantTool ( )
override

Definition at line 65 of file kis_assistant_tool.cc.

66{
67}

Member Function Documentation

◆ activate

void KisAssistantTool::activate ( const QSet< KoShape * > & shapes)
overrideslot

Definition at line 69 of file kis_assistant_tool.cc.

70{
71
72 KisTool::activate(shapes);
73
74 m_canvas->paintingAssistantsDecoration()->activateAssistantsEditor();
75 m_handles = m_canvas->paintingAssistantsDecoration()->handles();
76
78 m_canvas->paintingAssistantsDecoration()->setHandleSize(m_handleSize);
79
80
81 if (m_optionsWidget) {
82 m_canvas->paintingAssistantsDecoration()->deselectAssistant();
84 }
85
86 m_canvas->updateCanvas();
87
88}
QList< KisPaintingAssistantHandleSP > m_handles
PerspectiveAssistantEditionMode m_internalMode
void activate(const QSet< KoShape * > &shapes) override
Definition kis_tool.cc:93

References KisTool::activate(), m_canvas, m_handles, m_handleSize, m_internalMode, m_optionsWidget, MODE_CREATION, and updateToolOptionsUI().

◆ addAssistant()

void KisAssistantTool::addAssistant ( )
private

Definition at line 791 of file kis_assistant_tool.cc.

792{
793 m_canvas->paintingAssistantsDecoration()->addAssistant(m_newAssistant);
794
795 // generate the side handles for the Two Point assistant
796 if (m_newAssistant->id() == "two point"){
798 QSharedPointer<TwoPointAssistant> assis = qSharedPointerCast<TwoPointAssistant>(m_newAssistant);
799
800 if (*handles[0] == *handles[1] || *handles[1] == *handles[2]) {
801 // Place handles in sensible default position if any of
802 // them are overlapping (maybe because user
803 // double-clicked)
804 const QTransform transform = m_canvas->coordinatesConverter()->documentToWidgetTransform();
805 const QTransform inverted = transform.inverted();
806 const int size = inverted.map(QPointF(m_canvas->canvasWidget()->width(),0)).x();
807 *handles[0] = *handles[2] - QPointF(-size/3,0);
808 *handles[1] = *handles[2] - QPointF(size/3,0);
809 }
810
811 const QPointF p1 = *handles[0];
812 const QPointF p2 = *handles[1];
813 const QPointF p3 = *handles[2];
814
815 qreal size = 0;
816 QTransform t = assis->localTransform(p1,p2,p3,&size);
817 QTransform inv = t.inverted();
818
819 if (t.map(p1).x() * t.map(p2).x() > 0) {
820 // Put third handle between first and second if user
821 // placed it outside of them, then re-define the transform
822 const QLineF horizon = QLineF(t.map(p1),t.map(p2));
823 const QPointF origin = QPointF(horizon.center().x(),0);
824 *handles[2] = inv.map(origin);
825 t = assis->localTransform(p1,p2,*handles[2],&size);
826 inv = t.inverted();
827 }
828
829 const QPointF above = inv.map(QPointF(0,t.map(p1).y()+size));
830 const QPointF below = inv.map(QPointF(0,t.map(p1).y()-size));
831
832 Q_FOREACH (QPointF side, QList<QPointF>({above,below})) {
833 Q_FOREACH (QPointF vp, QList<QPointF>({p1, p2})) {
834 QLineF bar = QLineF(side, vp);
835 m_newAssistant->addHandle(new KisPaintingAssistantHandle(bar.pointAt(0.8)), HandleType::SIDE);
836 m_newAssistant->addHandle(new KisPaintingAssistantHandle(bar.pointAt(0.4)), HandleType::SIDE);
837 }
838 }
839 }
840
841
842 QList<KisPaintingAssistantSP> assistants = m_canvas->paintingAssistantsDecoration()->assistants();
844 m_canvas->viewManager()->undoAdapter()->addCommand(addAssistantCmd);
845
846 m_handles = m_canvas->paintingAssistantsDecoration()->handles();
847 m_canvas->paintingAssistantsDecoration()->setSelectedAssistant(m_newAssistant);
848 updateToolOptionsUI(); // vanishing point assistant will get an extra option
849
850 m_newAssistant.clear();
851}
QPointF p2
QPointF p3
QPointF p1
QList< KisPaintingAssistantSP > m_origAssistantList
static QList< KisPaintingAssistantSP > cloneAssistantList(const QList< KisPaintingAssistantSP > &list)
int size(const Forest< T > &forest)
Definition KisForest.h:1232

References EditAssistantsCommand::ADD, KisPaintingAssistant::cloneAssistantList(), m_canvas, m_handles, m_newAssistant, m_origAssistantList, p1, p2, p3, SIDE, and updateToolOptionsUI().

◆ assistantSelected()

void KisAssistantTool::assistantSelected ( KisPaintingAssistantSP assistant)
private

Definition at line 970 of file kis_assistant_tool.cc.

971{
972 m_canvas->paintingAssistantsDecoration()->setSelectedAssistant(assistant);
974}

References m_canvas, and updateToolOptionsUI().

◆ beginActionImpl()

void KisAssistantTool::beginActionImpl ( KoPointerEvent * event)
private

Definition at line 97 of file kis_assistant_tool.cc.

98{
100 m_origAssistantList = KisPaintingAssistant::cloneAssistantList(m_canvas->paintingAssistantsDecoration()->assistants());
101
102 bool newAssistantAllowed = true;
103
104 KisPaintingAssistantsDecorationSP canvasDecoration = m_canvas->paintingAssistantsDecoration();
105
106 if (m_newAssistant) {
108
109 if (!snap(event)) {
110 *m_newAssistant->handles().back() = canvasDecoration->snapToGuide(event, QPointF(), false);
111 }
112
113 if (m_newAssistant->handles().size() == m_newAssistant->numHandles()) {
114 addAssistant();
115 } else {
116 m_newAssistant->addHandle(new KisPaintingAssistantHandle(canvasDecoration->snapToGuide(event, QPointF(), false)), HandleType::NORMAL);
117 }
118 m_canvas->updateCanvas();
119 return;
120 }
121 m_handleDrag = 0;
122 double minDist = m_handleMaxDist;
123
124
125 QPointF mousePos = m_canvas->viewConverter()->documentToView(canvasDecoration->snapToGuide(event, QPointF(), false));//m_canvas->viewConverter()->documentToView(event->point);
126
127 // syncs the assistant handles to the handles reference we store in this tool
128 // they can get out of sync with the way the actions and paintevents occur
129 // we probably need to stop storing a reference in m_handles and call the assistants directly
130 m_handles = m_canvas->paintingAssistantsDecoration()->handles();
131
132
133 Q_FOREACH (KisPaintingAssistantSP assistant, m_canvas->paintingAssistantsDecoration()->assistants()) {
134
135 if (assistant->isLocked()) {
136 continue; // let's not modify an assistant that is locked
137 }
138
139
140 // find out which handle on all assistants is closest to the mouse position
141 // vanishing points have "side handles", so make sure to include that
142 {
143 QList<KisPaintingAssistantHandleSP> allAssistantHandles;
144 allAssistantHandles.append(assistant->handles());
145 allAssistantHandles.append(assistant->sideHandles());
146
147 Q_FOREACH (const KisPaintingAssistantHandleSP handle, allAssistantHandles) {
148
149 double dist = KisPaintingAssistant::norm2(mousePos - m_canvas->viewConverter()->documentToView(*handle));
150 if (dist < minDist) {
151 minDist = dist;
152 m_handleDrag = handle;
153
154 assistantSelected(assistant); // whatever handle is the closest contains the selected assistant
155 m_canvas->paintingAssistantsDecoration()->raiseAssistant(assistant);
156 }
157 }
158 }
159
160
161
162
163 if(m_handleDrag && assistant->id() == "perspective") {
164 // Look for the handle which was pressed
165
166
167 if (m_handleDrag == assistant->topLeft()) {
168 double dist = KisPaintingAssistant::norm2(mousePos - m_canvas->viewConverter()->documentToView(*m_handleDrag));
169 if (dist < minDist) {
170 minDist = dist;
171 }
172 m_dragStart = QPointF(assistant->topRight().data()->x(),assistant->topRight().data()->y());
174 } else if (m_handleDrag == assistant->topRight()) {
175 double dist = KisPaintingAssistant::norm2(mousePos - m_canvas->viewConverter()->documentToView(*m_handleDrag));
176 if (dist < minDist) {
177 minDist = dist;
178 }
180 m_dragStart = QPointF(assistant->topLeft().data()->x(),assistant->topLeft().data()->y());
181 } else if (m_handleDrag == assistant->bottomLeft()) {
182 double dist = KisPaintingAssistant::norm2(mousePos - m_canvas->viewConverter()->documentToView(*m_handleDrag));
183 if (dist < minDist) {
184 minDist = dist;
185 }
187 m_dragStart = QPointF(assistant->bottomRight().data()->x(),assistant->bottomRight().data()->y());
188 } else if (m_handleDrag == assistant->bottomRight()) {
189 double dist = KisPaintingAssistant::norm2(mousePos - m_canvas->viewConverter()->documentToView(*m_handleDrag));
190 if (dist < minDist) {
191 minDist = dist;
192 }
194 m_dragStart = QPointF(assistant->bottomLeft().data()->x(),assistant->bottomLeft().data()->y());
195 } else if (m_handleDrag == assistant->leftMiddle()) {
197 m_dragStart = QPointF((assistant->bottomLeft().data()->x()+assistant->topLeft().data()->x())*0.5,
198 (assistant->bottomLeft().data()->y()+assistant->topLeft().data()->y())*0.5);
199 m_selectedNode1 = new KisPaintingAssistantHandle(assistant->topLeft().data()->x(),assistant->topLeft().data()->y());
200 m_selectedNode2 = new KisPaintingAssistantHandle(assistant->bottomLeft().data()->x(),assistant->bottomLeft().data()->y());
201 m_newAssistant = toQShared(KisPaintingAssistantFactoryRegistry::instance()->get("perspective")->createPaintingAssistant());
202 m_newAssistant->addHandle(assistant->topLeft(), HandleType::NORMAL );
205 m_newAssistant->addHandle(assistant->bottomLeft(), HandleType::NORMAL);
206 m_dragEnd = event->point;
207 m_handleDrag = 0;
208 m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas
209 return;
210 } else if (m_handleDrag == assistant->rightMiddle()) {
211 m_dragStart = QPointF((assistant->topRight().data()->x()+assistant->bottomRight().data()->x())*0.5,
212 (assistant->topRight().data()->y()+assistant->bottomRight().data()->y())*0.5);
214 m_selectedNode1 = new KisPaintingAssistantHandle(assistant->topRight().data()->x(),assistant->topRight().data()->y());
215 m_selectedNode2 = new KisPaintingAssistantHandle(assistant->bottomRight().data()->x(),assistant->bottomRight().data()->y());
216 m_newAssistant = toQShared(KisPaintingAssistantFactoryRegistry::instance()->get("perspective")->createPaintingAssistant());
217 m_newAssistant->addHandle(assistant->topRight(), HandleType::NORMAL);
220 m_newAssistant->addHandle(assistant->bottomRight(), HandleType::NORMAL);
221 m_dragEnd = event->point;
222 m_handleDrag = 0;
223 m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas
224 return;
225 } else if (m_handleDrag == assistant->topMiddle()) {
226 m_dragStart = QPointF((assistant->topLeft().data()->x()+assistant->topRight().data()->x())*0.5,
227 (assistant->topLeft().data()->y()+assistant->topRight().data()->y())*0.5);
229 m_selectedNode1 = new KisPaintingAssistantHandle(assistant->topLeft().data()->x(),assistant->topLeft().data()->y());
230 m_selectedNode2 = new KisPaintingAssistantHandle(assistant->topRight().data()->x(),assistant->topRight().data()->y());
231 m_newAssistant = toQShared(KisPaintingAssistantFactoryRegistry::instance()->get("perspective")->createPaintingAssistant());
234 m_newAssistant->addHandle(assistant->topRight(), HandleType::NORMAL);
235 m_newAssistant->addHandle(assistant->topLeft(), HandleType::NORMAL);
236 m_dragEnd = event->point;
237 m_handleDrag = 0;
238 m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas
239 return;
240 } else if (m_handleDrag == assistant->bottomMiddle()) {
241 m_dragStart = QPointF((assistant->bottomLeft().data()->x()+assistant->bottomRight().data()->x())*0.5,
242 (assistant->bottomLeft().data()->y()+assistant->bottomRight().data()->y())*0.5);
244 m_selectedNode1 = new KisPaintingAssistantHandle(assistant->bottomLeft().data()->x(),assistant->bottomLeft().data()->y());
245 m_selectedNode2 = new KisPaintingAssistantHandle(assistant->bottomRight().data()->x(),assistant->bottomRight().data()->y());
246 m_newAssistant = toQShared(KisPaintingAssistantFactoryRegistry::instance()->get("perspective")->createPaintingAssistant());
247 m_newAssistant->addHandle(assistant->bottomLeft(), HandleType::NORMAL);
248 m_newAssistant->addHandle(assistant->bottomRight(), HandleType::NORMAL);
251 m_dragEnd = event->point;
252 m_handleDrag = 0;
253 m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas
254 return;
255 }
256 m_snapIsRadial = false;
257 }
258 else if (m_handleDrag && assistant->handles().size()>1 && (assistant->id() == "ruler" ||
259 assistant->id() == "parallel ruler" ||
260 assistant->id() == "infinite ruler" ||
261 assistant->id() == "spline" ||
262 assistant->id() == "curvilinear-perspective")){
263 if (m_handleDrag == assistant->handles()[0]) {
264 m_dragStart = *assistant->handles()[1];
265 } else if (m_handleDrag == assistant->handles()[1]) {
266 m_dragStart = *assistant->handles()[0];
267 } else if(assistant->handles().size()==4){
268 if (m_handleDrag == assistant->handles()[2]) {
269 m_dragStart = *assistant->handles()[0];
270 } else if (m_handleDrag == assistant->handles()[3]) {
271 m_dragStart = *assistant->handles()[1];
272 }
273 }
274 m_snapIsRadial = false;
275 } else if (m_handleDrag && assistant->handles().size()>2 && (assistant->id() == "ellipse" ||
276 assistant->id() == "concentric ellipse" ||
277 assistant->id() == "fisheye-point")){
278 m_snapIsRadial = false;
279 if (m_handleDrag == assistant->handles()[0]) {
280 m_dragStart = *assistant->handles()[1];
281 m_snapIsRadial = false;
282 } else if (m_handleDrag == assistant->handles()[1]) {
283 m_dragStart = *assistant->handles()[0];
284 m_snapIsRadial = false;
285 } else if (m_handleDrag == assistant->handles()[2]) {
286 m_dragStart = assistant->getEditorPosition();
287 m_radius = QLineF(m_dragStart, *assistant->handles()[0]);
288 m_snapIsRadial = true;
289 }
290 } else if (m_handleDrag && assistant->handles().size()>2 && assistant->id() == "two point") {
291
292 // If the user left the assistant's handles in an invalid
293 // state (ie 3rd handle isn't between the 1st and 2nd
294 // handle), then compute a sensible value for m_dragStart
295 // that respects it
296 QList<KisPaintingAssistantHandleSP> handles = assistant->handles();
297
298 const QPointF p1 = *assistant->handles()[0];
299 const QPointF p2 = *assistant->handles()[1];
300 const QPointF p3 = *assistant->handles()[2];
301
302 qreal size = 0;
303 QTransform t = qSharedPointerCast<TwoPointAssistant>(m_newAssistant)->localTransform(p1,p2,p3,&size);
304 QTransform inv = t.inverted();
305 if (t.map(p1).x() * t.map(p2).x() > 0) {
306
307 // We only care about m_dragStart if user is dragging a VP
308 if (m_handleDrag == assistant->handles()[0]) {
309 const QPointF safe_start = QPointF(-1.0*t.map(p1).x(),t.map(p1).y());
310 m_dragStart = inv.map(safe_start);
311 } else if (m_handleDrag == assistant->handles()[1]) {
312 const QPointF safe_start = QPointF(-1.0*t.map(p2).x(),t.map(p1).y());
313 m_dragStart = inv.map(safe_start);
314 }
315
316 m_snapIsRadial = false;
317 } else {
319 m_snapIsRadial = false;
320 }
321
322 } else if (m_handleDrag && assistant->id() == "vanishing point" &&
323 m_handleDrag == assistant->handles()[0]){
324 m_dragStart = assistant->getEditorPosition();
325 m_snapIsRadial = false;
326 }
327 }
328
329 m_currentAdjustment = QPointF();
330
331 if (m_handleDrag) {
332 // TODO: Shift-press should now be handled using the alternate actions
333 // if (event->modifiers() & Qt::ShiftModifier) {
334 // m_handleDrag->uncache();
335 // m_handleDrag = m_handleDrag->split()[0];
336 // m_handles = m_canvas->view()->paintingAssistantsDecoration()->handles();
337 // }
338 m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas
339 return;
340 }
341
342 m_assistantDrag.clear();
343
344 // list will contain the assistants whose control widgets are affected by the click event...
345 QList<KisPaintingAssistantSP> assistantsPressed;
346
347 // data for calculating mouse intersection with control widget.
348 AssistantEditorData &globalEditorWidgetData = m_canvas->paintingAssistantsDecoration()->globalEditorWidgetData;
349 const KisCoordinatesConverter *converter = m_canvas->coordinatesConverter();
350 QTransform initialTransform = converter->documentToWidgetTransform();
351 // for UI control widget options with move, show, and delete -- disregard document transforms like rotating and mirroring.
352 // otherwise the UI controls get awkward to use when they are at 45 degree angles or the order of controls gets flipped backwards
353 QPointF uiMousePosition = initialTransform.map(canvasDecoration->snapToGuide(event, QPointF(), false));
354
355 // find control widgets pressed...
356 Q_FOREACH (KisPaintingAssistantSP assistant, m_canvas->paintingAssistantsDecoration()->assistants()) {
357
358 QPointF actionsPosition = initialTransform.map(assistant->viewportConstrainedEditorPosition(converter, globalEditorWidgetData.boundingSize));
359
360 // first we must find if the click event intersects any assistant control widget rectangles.
361 // as it is possible for control widgets to overlap, we must then determine which control widget is actually being clicked based on the
362 // order of the assistants, which represent the z position hierarchy of their respective control widgets.
363
364 // calculate widget rect bound
365 QPointF actionsBGRectangle(actionsPosition + QPointF(globalEditorWidgetData.widgetOffset,globalEditorWidgetData.widgetOffset));
366 QRectF editorWidget = QRectF(actionsBGRectangle.x(), actionsBGRectangle.y(), globalEditorWidgetData.boundingSize.width(), globalEditorWidgetData.boundingSize.height());
367 // add all assistants that intersect the mouse to a list.
368 if (editorWidget.contains(uiMousePosition)) {
369 assistantsPressed.push_back(assistant);
370 }
371
372 }
373
374 // get assistant pressed...
375 if (!assistantsPressed.isEmpty()) {
376 // get closest assistant
377 KisPaintingAssistantSP assistant = assistantsPressed.last();
378 // move assistant to front of assistants list.
379 m_canvas->paintingAssistantsDecoration()->raiseAssistant(assistant);
380
381 assistantSelected(assistant);
382
383 QPointF actionsPosition = initialTransform.map(assistant->viewportConstrainedEditorPosition(converter, globalEditorWidgetData.boundingSize));
384
385 // loop through all activated buttons and see if any are being clicked
386 if(globalEditorWidgetData.moveButtonActivated) {
387 QPointF iconMovePosition(actionsPosition + globalEditorWidgetData.moveIconPosition);
388 QRectF moveRect(iconMovePosition, QSizeF(globalEditorWidgetData.buttonSize, globalEditorWidgetData.buttonSize));
389
390 if (moveRect.contains(uiMousePosition) && !assistant->isLocked()) {
391 m_assistantDrag = assistant;
392 m_cursorStart = event->point;
394
395 assistantSelected(assistant); // whatever handle is the closest contains the selected assistant
396
397 return;
398 }
399 }
400 if(globalEditorWidgetData.snapButtonActivated) {
401 QPointF iconSnapPosition(actionsPosition + globalEditorWidgetData.snapIconPosition);
402 QRectF visibleRect(iconSnapPosition, QSizeF(globalEditorWidgetData.buttonSize, globalEditorWidgetData.buttonSize));
403 if (visibleRect.contains(uiMousePosition)) {
404 newAssistantAllowed = false;
405 assistant->setSnappingActive(!assistant->isSnappingActive()); // toggle
406 assistant->uncache();//this updates the cache of the assistant, very important.
407
408 assistantSelected(assistant); // whatever handle is the closest contains the selected assistant
409 }
410 }
411 if(globalEditorWidgetData.lockButtonActivated) {
412 QPointF iconLockPosition(actionsPosition + globalEditorWidgetData.lockedIconPosition);
413 QRectF lockRect(iconLockPosition, QSizeF(globalEditorWidgetData.buttonSize, globalEditorWidgetData.buttonSize));
414 if (lockRect.contains(uiMousePosition)) {
415
416 assistant->setLocked(!assistant->isLocked());
417 assistantSelected(assistant); // whatever handle is the closest contains the selected assistant
419
420 return;
421 }
422 }
423 if(globalEditorWidgetData.duplicateButtonActivated) {
424 QPointF iconDuplicatePosition(actionsPosition + globalEditorWidgetData.duplicateIconPosition);
425 QRectF duplicateRect(iconDuplicatePosition,QSizeF(globalEditorWidgetData.buttonSize,globalEditorWidgetData.buttonSize));
426
427 if (duplicateRect.contains(uiMousePosition)) {
428 //create new assistant from old one
429 QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> handleMap;
430 m_newAssistant = assistant->clone(handleMap);
431 m_newAssistant->copySharedData(assistant);
432 m_newAssistant->setDuplicating(true);
433 //add assistant to global list and register UNDO/REDO object
434 m_canvas->paintingAssistantsDecoration()->addAssistant(m_newAssistant);
435 QList<KisPaintingAssistantSP> assistants = m_canvas->paintingAssistantsDecoration()->assistants();
437 m_canvas->viewManager()->undoAdapter()->addCommand(addAssistantCmd);
438 m_origAssistantList = KisPaintingAssistant::cloneAssistantList(m_canvas->paintingAssistantsDecoration()->assistants());
439 m_handles = m_canvas->paintingAssistantsDecoration()->handles();
440 m_canvas->paintingAssistantsDecoration()->setSelectedAssistant(m_newAssistant);
442
443 // if assistant is locked simply move the control widget, not the entire assistant
444 if(assistant->isLocked()) {
445 newAssistantAllowed = false;
447 m_dragStart = event->point;
448 m_dragEnd = event->point;
449 m_newAssistant.clear();
450 } else {
452 m_newAssistant.clear();
453 m_cursorStart = event->point;
455 m_dragStart = event->point;
456 m_dragEnd = event->point;
457 }
458
460 m_canvas->updateCanvas();
461 return;
462 }
463
464 }
465 if(globalEditorWidgetData.deleteButtonActivated) {
466 QPointF iconDeletePosition(actionsPosition + globalEditorWidgetData.deleteIconPosition);
467 QRectF deleteRect(iconDeletePosition, QSizeF(globalEditorWidgetData.buttonSize, globalEditorWidgetData.buttonSize));
468 if (deleteRect.contains(uiMousePosition) && !assistant->isLocked()) {
469 removeAssistant(assistant);
470 if(m_canvas->paintingAssistantsDecoration()->assistants().isEmpty()) {
473 m_canvas->updateCanvas();
474 return;
475 }
476
477 }
478 // if user clicking control widget background.
479 if((QRectF(actionsPosition + QPointF(10, 10), globalEditorWidgetData.boundingSize).adjusted(-2, -2, 2, 2).contains(uiMousePosition))) {
480 newAssistantAllowed = false;
482 assistantSelected(assistant);
483 m_dragStart = event->point;
484 m_dragEnd = event->point;
485
486 }
487
488
489 }
490
491 if (newAssistantAllowed==true) {//don't make a new assistant when I'm just toggling visibility//
492 QString key = m_options.availableAssistantsComboBox->model()->index( m_options.availableAssistantsComboBox->currentIndex(), 0 ).data(Qt::UserRole).toString();
493 KConfigGroup cfg = KSharedConfig::openConfig()->group(toolId());
494 cfg.writeEntry("AssistantType", key);
496 if (m_newAssistant->canBeLocal()) {
497 m_newAssistant->setLocal(m_options.localAssistantCheckbox->isChecked());
498 }
500 m_newAssistant->addHandle(new KisPaintingAssistantHandle(canvasDecoration->snapToGuide(event, QPointF(), false)), HandleType::NORMAL);
501 if (m_newAssistant->numHandles() <= 1) {
502 addAssistant();
503 } else {
504 m_newAssistant->addHandle(new KisPaintingAssistantHandle(canvasDecoration->snapToGuide(event, QPointF(), false)), HandleType::NORMAL);
505 }
506 }
507
508 if (m_newAssistant) {
509 m_newAssistant->setAssistantGlobalColorCache(m_canvas->paintingAssistantsDecoration()->globalAssistantsColor());
510 }
511
512 m_canvas->updateCanvas();
513}
VertexDescriptor get(PredecessorMap const &m, VertexDescriptor v)
KisPaintingAssistantHandleSP m_selectedNode2
Ui::AssistantsToolOptions m_options
KisPaintingAssistantHandleSP m_handleDrag
bool snap(KoPointerEvent *event)
void assistantSelected(KisPaintingAssistantSP assistant)
void removeAssistant(KisPaintingAssistantSP assistant)
KisPaintingAssistantHandleSP m_selectedNode1
static KisPaintingAssistantFactoryRegistry * instance()
static double norm2(const QPointF &p)
QPointF snapToGuide(KoPointerEvent *e, const QPointF &offset, bool useModifiers)
Q_INVOKABLE QString toolId() const
QSharedPointer< T > toQShared(T *ptr)
@ PAINT_MODE
Definition kis_tool.h:300
virtual void setMode(ToolMode mode)
Definition kis_tool.cc:403

References EditAssistantsCommand::ADD, addAssistant(), assistantDuplicatingFlag, assistantSelected(), AssistantEditorData::boundingSize, AssistantEditorData::buttonSize, KisPaintingAssistant::cloneAssistantList(), AssistantEditorData::deleteButtonActivated, AssistantEditorData::deleteIconPosition, KisCoordinatesConverter::documentToWidgetTransform(), AssistantEditorData::duplicateButtonActivated, AssistantEditorData::duplicateIconPosition, get(), KisPaintingAssistantFactoryRegistry::instance(), AssistantEditorData::lockButtonActivated, AssistantEditorData::lockedIconPosition, m_assistantDrag, m_canvas, m_currentAdjustment, m_cursorStart, m_dragEnd, m_dragStart, m_handleDrag, m_handleMaxDist, m_handles, m_internalMode, m_newAssistant, m_options, m_origAssistantList, m_radius, m_selectedNode1, m_selectedNode2, m_snapIsRadial, MODE_CREATION, MODE_DRAGGING_EDITOR_WIDGET, MODE_DRAGGING_NODE, MODE_DRAGGING_TRANSLATING_TWONODES, MODE_EDITING, AssistantEditorData::moveButtonActivated, AssistantEditorData::moveIconPosition, KisPaintingAssistant::norm2(), NORMAL, p1, p2, p3, KisTool::PAINT_MODE, removeAssistant(), KisTool::setMode(), snap(), AssistantEditorData::snapButtonActivated, AssistantEditorData::snapIconPosition, KisPaintingAssistantsDecoration::snapToGuide(), KoToolBase::toolId(), toQShared(), updateToolOptionsUI(), and AssistantEditorData::widgetOffset.

◆ beginAlternateAction()

void KisAssistantTool::beginAlternateAction ( KoPointerEvent * event,
KisTool::AlternateAction action )
overridevirtual

Reimplemented from KisTool.

Definition at line 1965 of file kis_assistant_tool.cc.

1966{
1967 Q_UNUSED(action);
1968 beginActionImpl(event);
1969}
void beginActionImpl(KoPointerEvent *event)
QAction * action(const QString &name) const

References KoToolBase::action(), and beginActionImpl().

◆ beginPrimaryAction()

void KisAssistantTool::beginPrimaryAction ( KoPointerEvent * event)
overridevirtual

Called by KisToolProxy when a primary action for the tool is started. The event stores the original event that started the stroke. The event is accepted by default. If the tool decides to ignore this particular action (e.g. when the node is not editable), it should call event->ignore(). Then no further continuePrimaryAction() or endPrimaryAction() will be called until the next user action.

Reimplemented from KisTool.

Definition at line 1983 of file kis_assistant_tool.cc.

1984{
1985 beginActionImpl(event);
1986}

References beginActionImpl().

◆ continueActionImpl()

void KisAssistantTool::continueActionImpl ( KoPointerEvent * event)
private

Definition at line 515 of file kis_assistant_tool.cc.

516{
517 KisPaintingAssistantsDecorationSP canvasDecoration = m_canvas->paintingAssistantsDecoration();
518
519 if (m_handleDrag) {
521 *m_handleDrag = event->point;
522
523 KisPaintingAssistantSP selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
524
525 if (!snap(event)) {
526 *m_handleDrag = canvasDecoration->snapToGuide(event, QPointF(), false);
527 }
529
530 m_handleCombine = 0;
531 if (!(event->modifiers() & Qt::ShiftModifier)) {
532 double minDist = 49.0;
533 QPointF mousePos = m_canvas->viewConverter()->documentToView(event->point);
534 Q_FOREACH (const KisPaintingAssistantHandleSP handle, m_handles) {
535 if (handle == m_handleDrag)
536 continue;
537
538
539 double dist = KisPaintingAssistant::norm2(mousePos - m_canvas->viewConverter()->documentToView(*handle));
540 if (dist < minDist) {
541 minDist = dist;
542 m_handleCombine = handle;
543 }
544 }
545 }
546 m_canvas->updateCanvas();
547 } else if (m_assistantDrag) {
548 QPointF newAdjustment = canvasDecoration->snapToGuide(event, QPointF(), false) - m_cursorStart;
549 if (event->modifiers() & Qt::ShiftModifier ) {
550 newAdjustment = snapToClosestNiceAngle(newAdjustment, QPointF(0, 0), M_PI / 4);
551 }
552 Q_FOREACH (KisPaintingAssistantHandleSP handle, m_assistantDrag->handles()) {
553 *handle += (newAdjustment - m_currentAdjustment);
554 }
555 if (m_assistantDrag->id()== "vanishing point" || m_assistantDrag->id()== "two point"){
556 Q_FOREACH (KisPaintingAssistantHandleSP handle, m_assistantDrag->sideHandles()) {
557 *handle += (newAdjustment - m_currentAdjustment);
558 }
559 }
560 m_assistantDrag->uncache();
561 m_currentAdjustment = newAdjustment;
562 m_canvas->updateCanvas();
563 m_dragEnd = event->point;
564
566
567 KisPaintingAssistantSP selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
568 QPointF currentOffset = selectedAssistant->editorWidgetOffset();
569 selectedAssistant->setEditorWidgetOffset(currentOffset + (event->point - m_dragEnd));
570 m_dragEnd = event->point;
571
572 } else {
573 event->ignore();
574 }
575
576 bool wasHighlightedNode = m_highlightedNode != 0;
577 QPointF mousep = m_canvas->viewConverter()->documentToView(event->point);
578 QList <KisPaintingAssistantSP> pAssistant= m_canvas->paintingAssistantsDecoration()->assistants();
579
580 Q_FOREACH (KisPaintingAssistantSP assistant, pAssistant) {
581 if(assistant->id() == "perspective") {
582 if ((m_highlightedNode = assistant->closestCornerHandleFromPoint(mousep))) {
585 } else {
586 m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas
587 break;
588 }
589 }
590 }
591
592 //this following bit sets the translations for the vanishing-point handles.
593 if(m_handleDrag && assistant->id() == "vanishing point" && assistant->sideHandles().size()==4) {
594 //for inner handles, the outer handle gets translated.
595 if (m_handleDrag == assistant->sideHandles()[0]) {
596 QLineF perspectiveline = QLineF(*assistant->handles()[0],
597 *assistant->sideHandles()[0]);
598
599 qreal length = QLineF(*assistant->sideHandles()[0],
600 *assistant->sideHandles()[1]).length();
601
602 if (length < 2.0){
603 length = 2.0;
604 }
605
606 length += perspectiveline.length();
607 perspectiveline.setLength(length);
608 *assistant->sideHandles()[1] = perspectiveline.p2();
609 }
610 else if (m_handleDrag == assistant->sideHandles()[2]){
611 QLineF perspectiveline = QLineF(*assistant->handles()[0], *assistant->sideHandles()[2]);
612 qreal length = QLineF(*assistant->sideHandles()[2], *assistant->sideHandles()[3]).length();
613
614 if (length<2.0){
615 length=2.0;
616 }
617
618 length += perspectiveline.length();
619 perspectiveline.setLength(length);
620 *assistant->sideHandles()[3] = perspectiveline.p2();
621 } // for outer handles, only the vanishing point is translated, but only if there's an intersection.
622 else if (m_handleDrag == assistant->sideHandles()[1]|| m_handleDrag == assistant->sideHandles()[3]){
623 QPointF vanishingpoint(0,0);
624 QLineF perspectiveline = QLineF(*assistant->sideHandles()[0], *assistant->sideHandles()[1]);
625 QLineF perspectiveline2 = QLineF(*assistant->sideHandles()[2], *assistant->sideHandles()[3]);
626
627 if (QLineF(perspectiveline2).intersects(QLineF(perspectiveline), &vanishingpoint) != QLineF::NoIntersection){
628 *assistant->handles()[0] = vanishingpoint;
629 }
630 }// and for the vanishing point itself, only the outer handles get translated.
631 else if (m_handleDrag == assistant->handles()[0]){
632 QLineF perspectiveline = QLineF(*assistant->handles()[0], *assistant->sideHandles()[0]);
633 QLineF perspectiveline2 = QLineF(*assistant->handles()[0], *assistant->sideHandles()[2]);
634 qreal length = QLineF(*assistant->sideHandles()[0], *assistant->sideHandles()[1]).length();
635 qreal length2 = QLineF(*assistant->sideHandles()[2], *assistant->sideHandles()[3]).length();
636
637 if (length < 2.0) {
638 length = 2.0;
639 }
640
641 if (length2 < 2.0) {
642 length2=2.0;
643 }
644
645 length += perspectiveline.length();
646 length2 += perspectiveline2.length();
647 perspectiveline.setLength(length);
648 perspectiveline2.setLength(length2);
649 *assistant->sideHandles()[1] = perspectiveline.p2();
650 *assistant->sideHandles()[3] = perspectiveline2.p2();
651 }
652
653 }
654 if (m_handleDrag && assistant->id() == "two point" && assistant->handles().size() >= 3 &&
655 assistant->sideHandles().size() == 8) {
656
657 QList<KisPaintingAssistantHandleSP> hndl = assistant->handles();
658 QList<KisPaintingAssistantHandleSP> side_hndl = assistant->sideHandles();
659
660 const bool far_handle_is_dragged =
661 m_handleDrag == side_hndl[1] || m_handleDrag == side_hndl[3] ||
662 m_handleDrag == side_hndl[5] || m_handleDrag == side_hndl[7];
663
664 if (far_handle_is_dragged) {
665 QLineF perspective_line_a, perspective_line_b;
666 QPointF vp_new_pos(0,0);
668 if (m_handleDrag == side_hndl[1] || m_handleDrag == side_hndl[5]) {
669 vp_moved = hndl[0];
670 perspective_line_a = QLineF(*side_hndl[0],*side_hndl[1]);
671 perspective_line_b = QLineF(*side_hndl[4],*side_hndl[5]);
672 } else {
673 vp_moved = hndl[1];
674 perspective_line_a = QLineF(*side_hndl[3],*side_hndl[2]);
675 perspective_line_b = QLineF(*side_hndl[6],*side_hndl[7]);
676 }
677 if (perspective_line_a.intersects(perspective_line_b, &vp_new_pos) != QLineF::NoIntersection) {
678 *vp_moved = vp_new_pos;
679 }
680 } else {
681 QLineF perspective_line_a1;
682 QLineF perspective_line_b1;
683 QLineF perspective_line_a2;
684 QLineF perspective_line_b2;
685
686 perspective_line_a1 = QLineF(*hndl[0], *side_hndl[0]);
687 perspective_line_a1.setLength(QLineF(*side_hndl[0],*side_hndl[1]).length());
688 perspective_line_a1.translate(*side_hndl[0] - perspective_line_a1.p1());
689 *side_hndl[1] = perspective_line_a1.p2();
690
691 perspective_line_b1 = QLineF(*hndl[0], *side_hndl[4]);
692 perspective_line_b1.setLength(QLineF(*side_hndl[4],*side_hndl[5]).length());
693 perspective_line_b1.translate(*side_hndl[4] - perspective_line_b1.p1());
694 *side_hndl[5] = perspective_line_b1.p2();
695
696 perspective_line_a2 = QLineF(*hndl[1], *side_hndl[2]);
697 perspective_line_a2.setLength(QLineF(*side_hndl[2],*side_hndl[3]).length());
698 perspective_line_a2.translate(*side_hndl[2] - perspective_line_a2.p1());
699 *side_hndl[3] = perspective_line_a2.p2();
700
701 perspective_line_b2 = QLineF(*hndl[1], *side_hndl[6]);
702 perspective_line_b2.setLength(QLineF(*side_hndl[6],*side_hndl[7]).length());
703 perspective_line_b2.translate(*side_hndl[6] - perspective_line_b2.p1());
704 *side_hndl[7] = perspective_line_b2.p2();
705 }
706 }
707 // The following section handles rulers that have been set to a
708 // constant length
709 if (m_handleDrag && (assistant->id() == "ruler" || assistant->id() == "infinite ruler")
710 && qSharedPointerCast<RulerAssistant>(assistant)->hasFixedLength()
711 && assistant->isAssistantComplete()) {
712
713 QSharedPointer<RulerAssistant> ruler = qSharedPointerCast<RulerAssistant>(assistant);
714
715 if (m_handleDrag == ruler->handles()[0]) {
716 // Dragging handle 1 moves the ruler
717 *ruler->handles()[1] += *ruler->handles()[0] - m_previousHandlePos;
718 }
719 else if (m_handleDrag == ruler->handles()[1]) {
720 // Dragging handle 2 only allows rotation
721 QPointF center = *ruler->handles()[0];
722 QPointF handle = *ruler->handles()[1];
723
724 QPointF direction = handle - center;
725 qreal distance = sqrt(KisPaintingAssistant::norm2(direction));
726 QPointF delta = direction / distance * ruler->fixedLength();
727
728 *ruler->handles()[1] = center + delta;
729 }
730 }
731 }
732 if (wasHighlightedNode && !m_highlightedNode) {
733 m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas
734 }
735}
qreal length(const QPointF &vec)
Definition Ellipse.cc:82
qreal distance(const QPointF &p1, const QPointF &p2)
KisPaintingAssistantHandleSP m_highlightedNode
KisPaintingAssistantHandleSP m_handleCombine
Qt::KeyboardModifiers modifiers() const
QPointF point
The point in document coordinates.
PointType snapToClosestNiceAngle(PointType point, PointType startPoint, qreal angle=(2 *M_PI)/24)
Definition kis_global.h:209
#define M_PI
Definition kis_global.h:111

References distance(), length(), m_assistantDrag, m_canvas, m_currentAdjustment, m_cursorStart, m_dragEnd, m_handleCombine, m_handleDrag, m_handles, m_highlightedNode, m_internalMode, M_PI, m_previousHandlePos, m_selectedNode1, m_selectedNode2, MODE_DRAGGING_EDITOR_WIDGET, KoPointerEvent::modifiers(), KisPaintingAssistant::norm2(), KoPointerEvent::point, snap(), snapToClosestNiceAngle(), KisPaintingAssistantsDecoration::snapToGuide(), and KisPaintingAssistantHandle::uncache().

◆ continueAlternateAction()

void KisAssistantTool::continueAlternateAction ( KoPointerEvent * event,
AlternateAction action )
overridevirtual

Reimplemented from KisTool.

Definition at line 1971 of file kis_assistant_tool.cc.

1972{
1973 Q_UNUSED(action);
1974 continueActionImpl(event);
1975}
void continueActionImpl(KoPointerEvent *event)

References KoToolBase::action(), and continueActionImpl().

◆ continuePrimaryAction()

void KisAssistantTool::continuePrimaryAction ( KoPointerEvent * event)
overridevirtual

Called by KisToolProxy when the primary action is in progress of pointer movement. If the tool has ignored the event in beginPrimaryAction(), this method will not be called.

Reimplemented from KisTool.

Definition at line 1988 of file kis_assistant_tool.cc.

1989{
1990 continueActionImpl(event);
1991}

References continueActionImpl().

◆ createOptionWidget()

QWidget * KisAssistantTool::createOptionWidget ( )
overridevirtual

Reimplement this if your tool actually has an option widget. Sets the option widget to 0 by default.

Reimplemented from KoToolBase.

Definition at line 1686 of file kis_assistant_tool.cc.

1687{
1688 if (!m_optionsWidget) {
1689 m_optionsWidget = new QWidget;
1690 m_options.setupUi(m_optionsWidget);
1691
1692 KConfigGroup cfg = KSharedConfig::openConfig()->group(toolId());
1693
1694 // See https://bugs.kde.org/show_bug.cgi?id=316896
1695 QWidget *specialSpacer = new QWidget(m_optionsWidget);
1696 specialSpacer->setObjectName("SpecialSpacer");
1697 specialSpacer->setFixedSize(0, 0);
1698 m_optionsWidget->layout()->addWidget(specialSpacer);
1699
1700 m_options.loadAssistantButton->setIcon(KisIconUtils::loadIcon("folder"));
1701 m_options.loadAssistantButton->setIconSize(QSize(16, 16));
1702 m_options.saveAssistantButton->setIcon(KisIconUtils::loadIcon("document-save-16"));
1703 m_options.saveAssistantButton->setIconSize(QSize(16, 16));
1704 m_options.deleteAllAssistantsButton->setIcon(KisIconUtils::loadIcon("edit-delete"));
1705 m_options.deleteAllAssistantsButton->setIconSize(QSize(16, 16));
1706
1707 m_options.showDockerOptionsButton->setIcon(KisIconUtils::loadIcon("arrow-right"));
1708 m_options.showDockerOptionsButton->setIconSize(QSize(16, 16));
1709
1710 QList<KoID> assistants;
1711 Q_FOREACH (const QString& key, KisPaintingAssistantFactoryRegistry::instance()->keys()) {
1713 assistants << KoID(key, name);
1714 }
1715 std::sort(assistants.begin(), assistants.end(), KoID::compareNames);
1716
1717 QString currentAssistantType = cfg.readEntry("AssistantType", "two point");
1718 int i = 0;
1719 int currentAssistantIndex = 0;
1720 Q_FOREACH(const KoID &id, assistants) {
1721 m_options.availableAssistantsComboBox->addItem(id.name(), id.id());
1722 if (id.id() == currentAssistantType) {
1723 currentAssistantIndex = i;
1724 }
1725 i++;
1726 }
1727 m_options.availableAssistantsComboBox->setCurrentIndex(currentAssistantIndex);
1728
1729 connect(m_options.availableAssistantsComboBox, SIGNAL(currentIndexChanged(int)), SLOT(slotSelectedAssistantTypeChanged()));
1730
1731 connect(m_options.saveAssistantButton, SIGNAL(clicked()), SLOT(saveAssistants()));
1732 connect(m_options.loadAssistantButton, SIGNAL(clicked()), SLOT(loadAssistants()));
1733 connect(m_options.deleteAllAssistantsButton, SIGNAL(clicked()), SLOT(removeAllAssistants()));
1734
1735 connect(m_options.assistantsColor, SIGNAL(changed(QColor)), SLOT(slotGlobalAssistantsColorChanged(QColor)));
1736 connect(m_options.assistantsGlobalOpacitySlider, SIGNAL(valueChanged(int)), SLOT(slotGlobalAssistantOpacityChanged()));
1737
1738 connect(m_options.vanishingPointAngleSpinbox, SIGNAL(valueChanged(double)), this, SLOT(slotChangeVanishingPointAngle(double)));
1739 connect(m_options.twoPointDensitySpinbox, SIGNAL(valueChanged(double)), this, SLOT(slotChangeTwoPointDensity(double)));
1740 connect(m_options.twoPointUseVerticalCheckbox, SIGNAL(stateChanged(int)), this, SLOT(slotChangeTwoPointUseVertical(int)));
1741
1742 connect(m_options.subdivisionsSpinbox, SIGNAL(valueChanged(int)), this, SLOT(slotChangeSubdivisions(int)));
1743 connect(m_options.minorSubdivisionsSpinbox, SIGNAL(valueChanged(int)), this, SLOT(slotChangeMinorSubdivisions(int)));
1744 connect(m_options.fixedLengthCheckbox, SIGNAL(stateChanged(int)), this, SLOT(slotEnableFixedLength(int)));
1745 connect(m_options.fixedLengthSpinbox, SIGNAL(valueChangedPt(double)), this, SLOT(slotChangeFixedLength(double)));
1746
1747 //update EditorWidgetData when checkbox clicked
1748 connect(m_options.showMove, SIGNAL(stateChanged(int)), this, SLOT(slotToggleMoveButton(int)));
1749 connect(m_options.showSnap, SIGNAL(stateChanged(int)), this, SLOT(slotToggleSnapButton(int)));
1750 connect(m_options.showLock, SIGNAL(stateChanged(int)), this, SLOT(slotToggleLockButton(int)));
1751 connect(m_options.showDuplicate, SIGNAL(stateChanged(int)), this, SLOT(slotToggleDuplicateButton(int)));
1752 connect(m_options.showDelete, SIGNAL(stateChanged(int)), this, SLOT(slotToggleDeleteButton(int)));
1753
1754 // initialize UI elements with existing data if possible
1755 if (m_canvas && m_canvas->paintingAssistantsDecoration()) {
1756 const QColor color = m_canvas->paintingAssistantsDecoration()->globalAssistantsColor();
1757
1758 QColor opaqueColor = color;
1759 opaqueColor.setAlpha(255);
1760
1761 m_options.assistantsColor->setColor(opaqueColor);
1762 m_options.customAssistantColorButton->setColor(opaqueColor);
1763 m_options.assistantsGlobalOpacitySlider->setValue(color.alphaF() * 100.0);
1764
1765 } else {
1766 m_options.assistantsColor->setColor(QColor(176, 176, 176, 255)); // grey default for all assistants
1767 m_options.assistantsGlobalOpacitySlider->setValue(100); // 100%
1768 }
1769
1770 m_options.assistantsGlobalOpacitySlider->setPrefix(i18n("Opacity: "));
1771 m_options.assistantsGlobalOpacitySlider->setSuffix(" %");
1772
1773
1774 // custom color of selected assistant
1775 m_options.customColorOpacitySlider->setValue(100); // 100%
1776 m_options.customColorOpacitySlider->setPrefix(i18n("Opacity: "));
1777 m_options.customColorOpacitySlider->setSuffix(" %");
1778
1779 connect(m_options.useCustomAssistantColor, SIGNAL(clicked(bool)), this, SLOT(slotUpdateCustomColor()));
1780 connect(m_options.customAssistantColorButton, SIGNAL(changed(QColor)), this, SLOT(slotUpdateCustomColor()));
1781 connect(m_options.customColorOpacitySlider, SIGNAL(valueChanged(int)), SLOT(slotCustomOpacityChanged()));
1782
1783 m_options.twoPointDensitySpinbox->setPrefix(i18n("Density: "));
1784 m_options.twoPointDensitySpinbox->setRange(0.1, 4.0, 2);
1785 m_options.twoPointDensitySpinbox->setSingleStep(0.1);
1786
1787 m_options.vanishingPointAngleSpinbox->setPrefix(i18n("Density: "));
1788 m_options.vanishingPointAngleSpinbox->setSuffix(QStringLiteral("°"));
1789 m_options.vanishingPointAngleSpinbox->setRange(1.0, 180.0);
1790 m_options.vanishingPointAngleSpinbox->setSingleStep(1.0);
1791
1792 m_options.subdivisionsSpinbox->setPrefix(i18n("Subdivisions: "));
1793 m_options.subdivisionsSpinbox->setRange(0, 100);
1794 m_options.subdivisionsSpinbox->setSoftRange(0, 20);
1795
1796 m_options.minorSubdivisionsSpinbox->setPrefix(i18n("Minor Subdivisions: "));
1797 m_options.minorSubdivisionsSpinbox->setRange(1, 5);
1798
1800 m_options.fixedLengthSpinbox->setUnitManager(m_unitManager);
1801 m_options.fixedLengthSpinbox->setDisplayUnit(false);
1802 m_options.fixedLengthSpinbox->setMinimum(0);
1803 m_options.fixedLengthUnit->setModel(m_unitManager);
1805 connect(m_options.fixedLengthUnit, SIGNAL(currentIndexChanged(int)), this, SLOT(slotChangeFixedLengthUnit(int)));
1806 connect(m_unitManager, SIGNAL(unitChanged(int)), m_options.fixedLengthUnit, SLOT(setCurrentIndex(int)));
1807
1808 m_options.vanishingPointAngleSpinbox->setVisible(false);
1809 m_options.twoPointDensitySpinbox->setVisible(false);
1810 m_options.subdivisionsSpinbox->setVisible(false);
1811 m_options.minorSubdivisionsSpinbox->setVisible(false);
1812 m_options.fixedLengthCheckbox->setVisible(false);
1813 m_options.fixedLengthSpinbox->setVisible(false);
1814 m_options.fixedLengthUnit->setVisible(false);
1815
1816
1817 m_options.localAssistantCheckbox->setChecked(cfg.readEntry("LimitAssistantToArea", false));
1818
1819 connect(m_options.localAssistantCheckbox, SIGNAL(stateChanged(int)), SLOT(slotLocalAssistantCheckboxChanged()));
1820
1821 // show panel for docker tool option visibility
1822 connect(m_options.showDockerOptionsButton, SIGNAL(clicked()), this, SLOT(slotToggleDockToolOptionsVisible()));
1823 // set control widget buttons on first startup.
1824 AssistantEditorData &globalEditorWidgetData = m_canvas->paintingAssistantsDecoration()->globalEditorWidgetData;
1825
1826
1827 if (globalEditorWidgetData.moveButtonActivated) {
1828 m_options.showMove->setChecked(true);
1829 }
1830 if (globalEditorWidgetData.snapButtonActivated) {
1831 m_options.showSnap->setChecked(true);
1832 }
1833 if (globalEditorWidgetData.lockButtonActivated) {
1834 m_options.showLock->setChecked(true);
1835 }
1836 if (globalEditorWidgetData.duplicateButtonActivated) {
1837 m_options.showDuplicate->setChecked(true);
1838 }
1839 if (globalEditorWidgetData.deleteButtonActivated) {
1840 m_options.showDelete->setChecked(true);
1841 }
1842 }
1843
1845
1846 return m_optionsWidget;
1847}
void slotChangeFixedLength(double value)
void slotChangeTwoPointUseVertical(int value)
void slotToggleMoveButton(int index)
void slotToggleDuplicateButton(int index)
void slotChangeFixedLengthUnit(int index)
void slotChangeTwoPointDensity(double value)
void slotChangeMinorSubdivisions(int value)
void slotToggleLockButton(int index)
void slotChangeVanishingPointAngle(double value)
void slotGlobalAssistantsColorChanged(const QColor &)
void slotToggleSnapButton(int index)
void slotChangeSubdivisions(int value)
void slotToggleDeleteButton(int index)
void slotEnableFixedLength(int enabled)
virtual QString name() const =0
void setApparentUnitFromSymbol(QString pSymbol)
void setUnitDimension(UnitDimension dimension)
T get(const QString &id) const
Definition KoID.h:30
static bool compareNames(const KoID &id1, const KoID &id2)
Definition KoID.h:87
const char * name(StandardAction id)
QIcon loadIcon(const QString &name)

References KoID::compareNames(), AssistantEditorData::deleteButtonActivated, AssistantEditorData::duplicateButtonActivated, KoGenericRegistry< T >::get(), KisPaintingAssistantFactoryRegistry::instance(), KisSpinBoxUnitManager::LENGTH, loadAssistants(), KisIconUtils::loadIcon(), AssistantEditorData::lockButtonActivated, m_canvas, m_options, m_optionsWidget, m_unitManager, AssistantEditorData::moveButtonActivated, KisPaintingAssistantFactory::name(), removeAllAssistants(), saveAssistants(), KisSpinBoxUnitManager::setApparentUnitFromSymbol(), KisSpinBoxUnitManager::setUnitDimension(), slotChangeFixedLength(), slotChangeFixedLengthUnit(), slotChangeMinorSubdivisions(), slotChangeSubdivisions(), slotChangeTwoPointDensity(), slotChangeTwoPointUseVertical(), slotChangeVanishingPointAngle(), slotCustomOpacityChanged(), slotEnableFixedLength(), slotGlobalAssistantOpacityChanged(), slotGlobalAssistantsColorChanged(), slotLocalAssistantCheckboxChanged(), slotSelectedAssistantTypeChanged(), slotToggleDeleteButton(), slotToggleDockToolOptionsVisible(), slotToggleDuplicateButton(), slotToggleLockButton(), slotToggleMoveButton(), slotToggleSnapButton(), slotUpdateCustomColor(), AssistantEditorData::snapButtonActivated, KoToolBase::toolId(), and updateToolOptionsUI().

◆ deactivate

void KisAssistantTool::deactivate ( )
overrideslot

Definition at line 90 of file kis_assistant_tool.cc.

91{
92 m_canvas->paintingAssistantsDecoration()->deactivateAssistantsEditor();
93 m_canvas->updateCanvas();
95}
void deactivate() override
Definition kis_tool.cc:131

References KisTool::deactivate(), and m_canvas.

◆ drawEditorWidget()

void KisAssistantTool::drawEditorWidget ( KisPaintingAssistantSP assistant,
QPainter & _gc )
private

◆ endActionImpl()

void KisAssistantTool::endActionImpl ( KoPointerEvent * event)
private

Definition at line 737 of file kis_assistant_tool.cc.

738{
740 // release duplication button flag
742 KisPaintingAssistantSP selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
743 selectedAssistant->setDuplicating(false);
745
746 // offset control widget if user simple click-releases duplication button
747 if (m_dragEnd == m_dragStart) {
748 // calculate offset independent from canvas resolution and zoom
749 const KisCoordinatesConverter *converter = m_canvas->coordinatesConverter();
750 // create offset unit, considering canvas resolution
751 const int offset = 20;
752 const float offsetUnit = offset / m_canvas->image()->xRes();
753 // use unit to calculate final offset, considering canvas zoom
754 QPointF widgetDuplicationOffset = QPointF(offsetUnit / converter->effectiveZoom(),offsetUnit / converter->effectiveZoom());
755 // apply offset to control widget
756 QPointF currentOffset = selectedAssistant->editorWidgetOffset();
757 selectedAssistant->setEditorWidgetOffset(currentOffset + widgetDuplicationOffset);
758 }
759 }
760
762 if (m_handleDrag) {
763 if (!(event->modifiers() & Qt::ShiftModifier) && m_handleCombine) {
766 m_handles = m_canvas->paintingAssistantsDecoration()->handles();
767 }
769 } else {
770 m_assistantDrag.clear();
771 }
772 dbgUI << "creating undo command...";
773 KUndo2Command *command = new EditAssistantsCommand(m_canvas, m_origAssistantList, KisPaintingAssistant::cloneAssistantList(m_canvas->paintingAssistantsDecoration()->assistants()));
774 m_canvas->viewManager()->undoAdapter()->addCommand(command);
775 dbgUI << "done";
777 addAssistant();
780 KisPaintingAssistantSP selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
781 QPointF currentOffset = selectedAssistant->editorWidgetOffset();
782 selectedAssistant->setEditorWidgetOffset(currentOffset + (event->point - m_dragEnd));
783 }
784 else {
785 event->ignore();
786 }
787
788 m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas
789}
void mergeWith(KisPaintingAssistantHandleSP)
#define dbgUI
Definition kis_debug.h:52
@ HOVER_MODE
Definition kis_tool.h:299

References addAssistant(), assistantDuplicatingFlag, KisPaintingAssistant::cloneAssistantList(), dbgUI, KisCoordinatesConverter::effectiveZoom(), KisTool::HOVER_MODE, m_assistantDrag, m_canvas, m_dragEnd, m_dragStart, m_handleCombine, m_handleDrag, m_handles, m_internalMode, m_origAssistantList, KisPaintingAssistantHandle::mergeWith(), MODE_CREATION, MODE_DRAGGING_EDITOR_WIDGET, MODE_DRAGGING_TRANSLATING_TWONODES, KoPointerEvent::modifiers(), KoPointerEvent::point, KisTool::setMode(), and KisPaintingAssistantHandle::uncache().

◆ endAlternateAction()

void KisAssistantTool::endAlternateAction ( KoPointerEvent * event,
AlternateAction action )
overridevirtual

Reimplemented from KisTool.

Definition at line 1977 of file kis_assistant_tool.cc.

1978{
1979 Q_UNUSED(action);
1980 endActionImpl(event);
1981}
void endActionImpl(KoPointerEvent *event)

References KoToolBase::action(), and endActionImpl().

◆ endPrimaryAction()

void KisAssistantTool::endPrimaryAction ( KoPointerEvent * event)
overridevirtual

Called by KisToolProxy when the primary action is being finished, that is while mouseRelease or tabletRelease event. If the tool has ignored the event in beginPrimaryAction(), this method will not be called.

Reimplemented from KisTool.

Definition at line 1993 of file kis_assistant_tool.cc.

1994{
1995 endActionImpl(event);
1996}

References endActionImpl().

◆ keyPressEvent()

void KisAssistantTool::keyPressEvent ( QKeyEvent * event)
overridevirtual

Called when a key is pressed. Implementors should call event->ignore() if they do not actually use the event. Default implementation ignores this event.

Parameters
eventstate and reason of this key press

Reimplemented from KoToolBase.

Definition at line 1357 of file kis_assistant_tool.cc.

1358{
1359 // When the user is in the middle of creating a new
1360 // assistant the escape key can be used to cancel this process.
1361 if (event->key()==Qt::Key_Escape && (m_newAssistant)) {
1362 // Clear shared pointer to the assistant being created so
1363 // it gets cleaned-up
1364 m_newAssistant.clear();
1365 m_canvas->updateCanvas();
1366 event->accept();
1367 } else {
1368 event->ignore();
1369 }
1370}

References m_canvas, and m_newAssistant.

◆ loadAssistants

void KisAssistantTool::loadAssistants ( )
privateslot

Definition at line 1435 of file kis_assistant_tool.cc.

1436{
1437 KoFileDialog dialog(m_canvas->viewManager()->mainWindowAsQWidget(), KoFileDialog::OpenFile, "OpenAssistant");
1438 dialog.setCaption(i18n("Select an Assistant"));
1439 dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
1440 dialog.setMimeTypeFilters(QStringList() << "application/x-krita-assistant", "application/x-krita-assistant");
1441 QString filename = dialog.filename();
1442
1443 QFile file(filename);
1444 if (!file.open(QIODevice::ReadOnly)) { return; }
1445
1446 QByteArray data = file.readAll();
1447 QXmlStreamReader xml(data);
1448 QMap<int, KisPaintingAssistantHandleSP> handleMap;
1449 QMap<int, KisPaintingAssistantHandleSP> sideHandleMap;
1450 KisPaintingAssistantSP assistant;
1451 bool errors = false;
1452
1453 m_origAssistantList = KisPaintingAssistant::cloneAssistantList(m_canvas->paintingAssistantsDecoration()->assistants());
1454
1455
1456 while (!xml.atEnd()) {
1457 switch (xml.readNext()) {
1458 case QXmlStreamReader::StartElement:
1459 if (xml.name() == "handle") {
1460 if (assistant && !xml.attributes().value("ref").isEmpty()) {
1461 KisPaintingAssistantHandleSP handle = handleMap.value(xml.attributes().value("ref").toString().toInt());
1462 if (handle) {
1463 assistant->addHandle(handle, HandleType::NORMAL);
1464 } else {
1465 errors = true;
1466 }
1467 } else {
1468 QString strId = xml.attributes().value("id").toString(),
1469 strX = xml.attributes().value("x").toString(),
1470 strY = xml.attributes().value("y").toString();
1471
1472
1473
1474 if (!strId.isEmpty() && !strX.isEmpty() && !strY.isEmpty()) {
1475 int id = strId.toInt();
1476 double x = strX.toDouble(),
1477 y = strY.toDouble();
1478 if (!handleMap.contains(id)) {
1479 handleMap.insert(id, new KisPaintingAssistantHandle(x, y));
1480 } else {
1481 errors = true;
1482 }
1483 } else {
1484 errors = true;
1485 }
1486 }
1487 // for vanishing point assistant
1488 } else if (xml.name() == "sidehandle"){
1489
1490 // read in sidehandles
1491 if (!xml.attributes().value("id").isEmpty()) {
1492 QString strId = xml.attributes().value("id").toString(),
1493 strX = xml.attributes().value("x").toString(),
1494 strY = xml.attributes().value("y").toString();
1495 if (!strId.isEmpty() && !strX.isEmpty() && !strY.isEmpty()) {
1496 int id = strId.toInt();
1497 double x = strX.toDouble();
1498 double y = strY.toDouble();
1499 if (!sideHandleMap.contains(id)) {
1500 sideHandleMap.insert(id, new KisPaintingAssistantHandle(x,y));
1501 }}
1502 }
1503 // addHandle to assistant
1504 if (!xml.attributes().value("ref").isEmpty() && assistant) {
1505 KisPaintingAssistantHandleSP handle = sideHandleMap.value(xml.attributes().value("ref").toString().toInt());
1506 if (handle) {
1507 assistant->addHandle(handle, HandleType::SIDE);
1508 }
1509 }
1510
1511 } else if (xml.name() == "assistant") {
1512 const KisPaintingAssistantFactory* factory = KisPaintingAssistantFactoryRegistry::instance()->get(xml.attributes().value("type").toString());
1513
1514 if (factory) {
1515 if (assistant) {
1516 errors = true;
1517 assistant.clear();
1518 }
1519 assistant = toQShared(factory->createPaintingAssistant());
1520 } else {
1521 errors = true;
1522 }
1523
1524 if (assistant) {
1525 // load custom shared assistant properties
1526 if (xml.attributes().hasAttribute("useCustomColor")) {
1527 auto useCustomColor = xml.attributes().value("useCustomColor");
1528
1529 bool usingColor = false;
1530 if (useCustomColor.toString() == "1") {
1531 usingColor = true;
1532 }
1533 assistant->setUseCustomColor(usingColor);
1534 }
1535
1536 if ( xml.attributes().hasAttribute("useCustomColor")) {
1537 auto customColor = xml.attributes().value("customColor");
1538 assistant->setAssistantCustomColor( KisDomUtils::qStringToQColor(customColor.toString()) );
1539
1540 }
1541 }
1542 }
1543
1544 if (assistant) {
1545 assistant->loadCustomXml(&xml);
1546 }
1547
1548
1549 break;
1550 case QXmlStreamReader::EndElement:
1551 if (xml.name() == "assistant") {
1552 if (assistant) {
1553 if (assistant->handles().size() == assistant->numHandles()) {
1554 if (assistant->id() == "vanishing point" && sideHandleMap.empty()){
1555 // Create side handles if the saved vp assistant doesn't have any.
1556 QPointF pos = *assistant->handles()[0];
1557 assistant->addHandle(new KisPaintingAssistantHandle(pos+QPointF(-70,0)), HandleType::SIDE);
1558 assistant->addHandle(new KisPaintingAssistantHandle(pos+QPointF(-140,0)), HandleType::SIDE);
1559 assistant->addHandle(new KisPaintingAssistantHandle(pos+QPointF(70,0)), HandleType::SIDE);
1560 assistant->addHandle(new KisPaintingAssistantHandle(pos+QPointF(140,0)), HandleType::SIDE);
1561 }
1562 m_canvas->paintingAssistantsDecoration()->addAssistant(assistant);
1563 } else {
1564 errors = true;
1565 }
1566 assistant.clear();
1567 }
1568 }
1569
1570 break;
1571 default:
1572 break;
1573 }
1574
1575 }
1576 if (assistant) {
1577 errors = true;
1578 assistant.clear();
1579 }
1580 if (xml.hasError()) {
1581 QMessageBox::warning(qApp->activeWindow(), i18nc("@title:window", "Krita"), xml.errorString());
1582 }
1583 if (errors) {
1584 QMessageBox::warning(qApp->activeWindow(), i18nc("@title:window", "Krita"), i18n("Errors were encountered. Not all assistants were successfully loaded."));
1585 }
1586
1587 KUndo2Command *command = new EditAssistantsCommand(m_canvas, m_origAssistantList, KisPaintingAssistant::cloneAssistantList(m_canvas->paintingAssistantsDecoration()->assistants()));
1588 m_canvas->viewManager()->undoAdapter()->addCommand(command);
1589
1590 m_handles = m_canvas->paintingAssistantsDecoration()->handles();
1591 m_canvas->updateCanvas();
1592}
QList< QString > QStringList
KoToolFactoryBase * factory() const
QColor qStringToQColor(QString colorString)

References KisPaintingAssistant::cloneAssistantList(), KoToolBase::factory(), KoGenericRegistry< T >::get(), KisPaintingAssistantFactoryRegistry::instance(), m_canvas, m_handles, m_origAssistantList, NORMAL, KoFileDialog::OpenFile, KisDomUtils::qStringToQColor(), SIDE, and toQShared().

◆ mouseMoveEvent()

void KisAssistantTool::mouseMoveEvent ( KoPointerEvent * event)
overridevirtual

Called when the mouse or stylus moved over the canvas. Implementors should call event->ignore() if they do not actually use the event.

Parameters
eventstate and reason of this mouse or stylus move

Implements KoToolBase.

Definition at line 1314 of file kis_assistant_tool.cc.

1315{
1316 m_handleHover = 0;
1318
1319 KisPaintingAssistantHandleSP new_handle = m_newAssistant->handles().back();
1320 if (!snap(event)) {
1321 KisPaintingAssistantsDecorationSP canvasDecoration = m_canvas->paintingAssistantsDecoration();
1322 *new_handle = canvasDecoration->snapToGuide(event, QPointF(), false);
1323 }
1324
1326 QPointF translate = event->point - m_dragEnd;
1327 m_dragEnd = event->point;
1328 m_selectedNode1.data()->operator = (QPointF(m_selectedNode1.data()->x(),m_selectedNode1.data()->y()) + translate);
1329 m_selectedNode2.data()->operator = (QPointF(m_selectedNode2.data()->x(),m_selectedNode2.data()->y()) + translate);
1330 } else if (mode() == KisTool::HOVER_MODE) {
1331
1332 // find a handle underneath...
1333 double minDist = m_handleMaxDist;
1334
1335 QPointF mousePos = m_canvas->viewConverter()->documentToView(event->point);
1336
1337 Q_FOREACH (KisPaintingAssistantSP assistant, m_canvas->paintingAssistantsDecoration()->assistants()) {
1338 QList<KisPaintingAssistantHandleSP> allAssistantHandles;
1339 allAssistantHandles.append(assistant->handles());
1340 allAssistantHandles.append(assistant->sideHandles());
1341
1342 Q_FOREACH (const KisPaintingAssistantHandleSP handle, allAssistantHandles) {
1343
1344 double dist = KisPaintingAssistant::norm2(mousePos - m_canvas->viewConverter()->documentToView(*handle));
1345 if (dist < minDist) {
1346 minDist = dist;
1347 m_handleHover = handle;
1348 }
1349 }
1350 }
1351 }
1352
1353 m_canvas->updateCanvasDecorations();
1354}
KisPaintingAssistantHandleSP m_handleHover
virtual ToolMode mode() const
Definition kis_tool.cc:407

References KisSharedPtr< T >::data(), KisTool::HOVER_MODE, m_canvas, m_dragEnd, m_handleHover, m_handleMaxDist, m_internalMode, m_newAssistant, m_selectedNode1, m_selectedNode2, KisTool::mode(), MODE_CREATION, MODE_DRAGGING_TRANSLATING_TWONODES, KisPaintingAssistant::norm2(), KoPointerEvent::point, snap(), and KisPaintingAssistantsDecoration::snapToGuide().

◆ paint()

void KisAssistantTool::paint ( QPainter & gc,
const KoViewConverter & converter )
overrideprotectedvirtual

Draws the editor widget controls with move, activate, and delete This also creates a lot of assistant specific stuff for vanishing points and perspective grids Whatever is painted here will be underneath the content painted in the kis_painting_assistant_decoration The kis_painting_assistant_decoration paints the final assistant, so this is more of just editor controls

Implements KoToolBase.

Definition at line 1372 of file kis_assistant_tool.cc.

1373{
1374 QRectF canvasSize = QRectF(QPointF(0, 0), QSizeF(m_canvas->image()->size()));
1375
1376 // show special display while a new assistant is in the process of being created
1377 if (m_newAssistant) {
1378
1379 QColor assistantColor = m_canvas->displayRendererInterface()->convertColorToDisplayColorSpace(KoColor(m_newAssistant->effectiveAssistantColor(), KoColorSpaceRegistry::instance()->rgb8()));
1380 assistantColor.setAlpha(80);
1381
1382 m_newAssistant->drawAssistant(_gc, canvasSize, m_canvas->coordinatesConverter(), m_canvas->displayRendererInterface(), false, m_canvas, true, false);
1383 Q_FOREACH (const KisPaintingAssistantHandleSP handle, m_newAssistant->handles()) {
1384 QPainterPath path;
1385 path.addEllipse(QRectF(_converter.documentToView(*handle) - QPointF(m_handleSize * 0.5, m_handleSize * 0.5), QSizeF(m_handleSize, m_handleSize)));
1386
1387 _gc.save();
1388 _gc.setPen(Qt::NoPen);
1389 _gc.setBrush(assistantColor);
1390 _gc.drawPath(path);
1391 _gc.restore();
1392 }
1393 }
1394
1395
1396 Q_FOREACH (KisPaintingAssistantSP assistant, m_canvas->paintingAssistantsDecoration()->assistants()) {
1397
1398 QColor assistantColor = m_canvas->displayRendererInterface()->convertColorToDisplayColorSpace(KoColor(assistant->effectiveAssistantColor(), KoColorSpaceRegistry::instance()->rgb8()));
1399 assistantColor.setAlpha(80);
1400
1401 Q_FOREACH (const KisPaintingAssistantHandleSP handle, m_handles) {
1402 QRectF ellipse(_converter.documentToView(*handle) - QPointF(m_handleSize * 0.5, m_handleSize * 0.5),
1403 QSizeF(m_handleSize, m_handleSize));
1404
1405 // render handles differently if it is the one being dragged.
1406 if (handle == m_handleDrag || handle == m_handleCombine || (handle == m_handleHover && !handle->chiefAssistant()->isLocked())) {
1407 QPen stroke(assistantColor, 4);
1408 _gc.save();
1409 _gc.setPen(stroke);
1410 _gc.setBrush(Qt::NoBrush);
1411 _gc.drawEllipse(ellipse);
1412 _gc.restore();
1413 }
1414
1415 }
1416 }
1417}
KisPaintingAssistant * chiefAssistant() const
static KoColorSpaceRegistry * instance()
const KoColorSpace * rgb8(const QString &profileName=QString())

References KisPaintingAssistantHandle::chiefAssistant(), KoViewConverter::documentToView(), KoColorSpaceRegistry::instance(), KisPaintingAssistant::isLocked(), m_canvas, m_handleCombine, m_handleDrag, m_handleHover, m_handles, m_handleSize, m_newAssistant, and KoColorSpaceRegistry::rgb8().

◆ priority()

virtual quint32 KisAssistantTool::priority ( )
inlinevirtual

Definition at line 48 of file kis_assistant_tool.h.

48 {
49 return 3;
50 }

◆ removeAllAssistants

void KisAssistantTool::removeAllAssistants ( )
privateslot

Definition at line 1419 of file kis_assistant_tool.cc.

1420{
1421 m_origAssistantList = m_canvas->paintingAssistantsDecoration()->assistants();
1422
1423 m_canvas->paintingAssistantsDecoration()->removeAll();
1424
1425 KUndo2Command *removeAssistantCmd = new EditAssistantsCommand(m_canvas, m_origAssistantList, KisPaintingAssistant::cloneAssistantList(m_canvas->paintingAssistantsDecoration()->assistants()));
1426 m_canvas->viewManager()->undoAdapter()->addCommand(removeAssistantCmd);
1427
1428 m_handles = m_canvas->paintingAssistantsDecoration()->handles();
1429 m_canvas->updateCanvas();
1430
1431 m_canvas->paintingAssistantsDecoration()->deselectAssistant();
1433}

References KisPaintingAssistant::cloneAssistantList(), m_canvas, m_handles, m_origAssistantList, and updateToolOptionsUI().

◆ removeAssistant()

void KisAssistantTool::removeAssistant ( KisPaintingAssistantSP assistant)
private

Definition at line 956 of file kis_assistant_tool.cc.

957{
958 QList<KisPaintingAssistantSP> assistants = m_canvas->paintingAssistantsDecoration()->assistants();
959
960 m_canvas->paintingAssistantsDecoration()->removeAssistant(assistant);
961
962 KUndo2Command *removeAssistantCmd = new EditAssistantsCommand(m_canvas, m_origAssistantList, KisPaintingAssistant::cloneAssistantList(m_canvas->paintingAssistantsDecoration()->assistants()), EditAssistantsCommand::REMOVE, assistants.indexOf(assistant));
963 m_canvas->viewManager()->undoAdapter()->addCommand(removeAssistantCmd);
964
965 m_handles = m_canvas->paintingAssistantsDecoration()->handles();
966 m_canvas->paintingAssistantsDecoration()->deselectAssistant();
968}

References KisPaintingAssistant::cloneAssistantList(), m_canvas, m_handles, m_origAssistantList, EditAssistantsCommand::REMOVE, and updateToolOptionsUI().

◆ saveAssistants

void KisAssistantTool::saveAssistants ( )
privateslot

Definition at line 1594 of file kis_assistant_tool.cc.

1595{
1596
1597 if (m_handles.isEmpty()) return;
1598
1599 QByteArray data;
1600 QXmlStreamWriter xml(&data);
1601 xml.writeStartDocument();
1602 xml.writeStartElement("paintingassistant");
1603 xml.writeAttribute("color",
1605 m_canvas->paintingAssistantsDecoration()->globalAssistantsColor())); // global color if no custom color used
1606
1607
1608 xml.writeStartElement("handles");
1609 QMap<KisPaintingAssistantHandleSP, int> handleMap;
1610 Q_FOREACH (const KisPaintingAssistantHandleSP handle, m_handles) {
1611 int id = handleMap.size();
1612 handleMap.insert(handle, id);
1613 xml.writeStartElement("handle");
1614 //xml.writeAttribute("type", handle->handleType());
1615 xml.writeAttribute("id", QString::number(id));
1616 xml.writeAttribute("x", QString::number(double(handle->x()), 'f', 3));
1617 xml.writeAttribute("y", QString::number(double(handle->y()), 'f', 3));
1618 xml.writeEndElement();
1619 }
1620 xml.writeEndElement();
1621 xml.writeStartElement("sidehandles");
1622 QMap<KisPaintingAssistantHandleSP, int> sideHandleMap;
1623 Q_FOREACH (KisPaintingAssistantSP assistant, m_canvas->paintingAssistantsDecoration()->assistants()) {
1624 Q_FOREACH (KisPaintingAssistantHandleSP handle, assistant->sideHandles()) {
1625 int id = sideHandleMap.size();
1626 sideHandleMap.insert(handle, id);
1627 xml.writeStartElement("sidehandle");
1628 xml.writeAttribute("id", QString::number(id));
1629 xml.writeAttribute("x", QString::number(double(handle->x()), 'f', 3));
1630 xml.writeAttribute("y", QString::number(double(handle->y()), 'f', 3));
1631 xml.writeEndElement();
1632 }
1633 }
1634 xml.writeStartElement("assistants");
1635
1636
1637 Q_FOREACH (const KisPaintingAssistantSP assistant, m_canvas->paintingAssistantsDecoration()->assistants()) {
1638 xml.writeStartElement("assistant");
1639 xml.writeAttribute("type", assistant->id());
1640 xml.writeAttribute("useCustomColor", QString::number(assistant->useCustomColor()));
1641 xml.writeAttribute("customColor", KisDomUtils::qColorToQString(assistant->assistantCustomColor()));
1642
1643
1644
1645 // custom assistant properties like angle density on vanishing point
1646 assistant->saveCustomXml(&xml);
1647
1648 // handle information
1649 xml.writeStartElement("handles");
1650 Q_FOREACH (const KisPaintingAssistantHandleSP handle, assistant->handles()) {
1651 xml.writeStartElement("handle");
1652 xml.writeAttribute("ref", QString::number(handleMap.value(handle)));
1653 xml.writeEndElement();
1654 }
1655 xml.writeEndElement();
1656 if (!sideHandleMap.empty()) {
1657 xml.writeStartElement("sidehandles");
1658 Q_FOREACH (const KisPaintingAssistantHandleSP handle, assistant->sideHandles()) {
1659 xml.writeStartElement("sidehandle");
1660 xml.writeAttribute("ref", QString::number(sideHandleMap.value(handle)));
1661 xml.writeEndElement();
1662 }
1663 xml.writeEndElement();
1664 }
1665 xml.writeEndElement();
1666 }
1667 xml.writeEndElement();
1668 xml.writeEndElement();
1669 xml.writeEndDocument();
1670
1671 KoFileDialog dialog(m_canvas->viewManager()->mainWindowAsQWidget(), KoFileDialog::SaveFile, "OpenAssistant");
1672 dialog.setCaption(i18n("Save Assistant"));
1673 dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
1674 dialog.setMimeTypeFilters(QStringList() << "application/x-krita-assistant", "application/x-krita-assistant");
1675 QString filename = dialog.filename();
1676 if (filename.isEmpty()) return;
1677
1678 QFile file(filename);
1679 if (file.open(QIODevice::WriteOnly)) {
1680 file.write(data);
1681 } else {
1682 qWarning() << "Couldn't open file" << file.fileName() << "for writing:" << file.errorString();
1683 }
1684}
QString qColorToQString(QColor color)

References m_canvas, m_handles, KisDomUtils::qColorToQString(), and KoFileDialog::SaveFile.

◆ slotChangeFixedLength

void KisAssistantTool::slotChangeFixedLength ( double value)
slot

Definition at line 1240 of file kis_assistant_tool.cc.

1240 {
1241 // This slot should only be called when the user actually changes the
1242 // value, not when it is changed through unit conversions. Use
1243 // QSignalBlocker on the spin box when converting units to achieve this.
1244
1245 if (m_canvas->paintingAssistantsDecoration()->assistants().length() == 0) {
1246 return;
1247 }
1248
1249 // get the selected assistant and change the angle value
1250 KisPaintingAssistantSP m_selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
1251 if (m_selectedAssistant) {
1252 bool isRulerAssistant = m_selectedAssistant->id() == "ruler"
1253 || m_selectedAssistant->id() == "infinite ruler";
1254
1255 if (isRulerAssistant) {
1256 QSharedPointer <RulerAssistant> assis = qSharedPointerCast<RulerAssistant>(m_selectedAssistant);
1257 // Stores the newly entered data (length & unit) in the assistant
1258 assis->setFixedLengthUnit(m_unitManager->getApparentUnitSymbol());
1259 assis->setFixedLength(m_options.fixedLengthSpinbox->value());
1260 assis->ensureLength();
1261 m_options.fixedLengthSpinbox->setPrefix("");
1262 }
1263 }
1264
1265 m_canvas->updateCanvasDecorations();
1266}

References KisSpinBoxUnitManager::getApparentUnitSymbol(), m_canvas, m_options, and m_unitManager.

◆ slotChangeFixedLengthUnit

void KisAssistantTool::slotChangeFixedLengthUnit ( int index)
privateslot

Definition at line 1268 of file kis_assistant_tool.cc.

1268 {
1269 if (m_canvas->paintingAssistantsDecoration()->assistants().length() == 0) {
1270 return;
1271 }
1272
1273 // get the selected assistant and change the angle value
1274 KisPaintingAssistantSP m_selectedAssistant =
1275 m_canvas->paintingAssistantsDecoration()->selectedAssistant();
1276 if (m_selectedAssistant) {
1277 bool isRulerAssistant = m_selectedAssistant->id() == "ruler" ||
1278 m_selectedAssistant->id() == "infinite ruler";
1279
1280 if (isRulerAssistant) {
1281 QSharedPointer<RulerAssistant> assis = qSharedPointerCast<RulerAssistant>(m_selectedAssistant);
1282
1283 // Saving and restoring the actual length manually, since the
1284 // unit manager rounds without warning during conversion
1285 qreal current_length = assis->fixedLength();
1286 {
1287 // Block signals from the spinbox while changing the unit to
1288 // avoid edits via valueChanged() in the meantime
1289 QSignalBlocker b(m_options.fixedLengthSpinbox);
1291 m_options.fixedLengthSpinbox->changeValue(current_length);
1292 }
1293
1294 QString unit = m_unitManager->getApparentUnitSymbol();
1295
1296 if (unit == assis->fixedLengthUnit()) {
1297 // If the previous unit is selected, show no prefix: perfect match
1298 m_options.fixedLengthSpinbox->setPrefix("");
1299 }
1300 else {
1301 if (abs(m_options.fixedLengthSpinbox->value() - current_length) > 1e-3) {
1302 // If the units don't match, show the approximate symbol as prefix
1303 m_options.fixedLengthSpinbox->setPrefix(u8"\u2248");
1304 } else {
1305 // If the units don't match but converted perfectly
1306 // (close enough: +- 0.001 pt), show equals instead
1307 m_options.fixedLengthSpinbox->setPrefix("=");
1308 }
1309 }
1310 }
1311 }
1312}
Point abs(const Point &pt)

References KisSpinBoxUnitManager::getApparentUnitSymbol(), m_canvas, m_options, m_unitManager, and KisSpinBoxUnitManager::selectApparentUnitFromIndex().

◆ slotChangeMinorSubdivisions

void KisAssistantTool::slotChangeMinorSubdivisions ( int value)
slot

Definition at line 1187 of file kis_assistant_tool.cc.

1187 {
1188 if (m_canvas->paintingAssistantsDecoration()->assistants().length() == 0) {
1189 return;
1190 }
1191
1192 // get the selected assistant and change the angle value
1193 KisPaintingAssistantSP m_selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
1194 if (m_selectedAssistant) {
1195 bool isRulerAssistant = m_selectedAssistant->id() == "ruler"
1196 || m_selectedAssistant->id() == "infinite ruler";
1197
1198 if (isRulerAssistant) {
1199 QSharedPointer <RulerAssistant> assis = qSharedPointerCast<RulerAssistant>(m_selectedAssistant);
1200 assis->setMinorSubdivisions(value);
1201 }
1202 }
1203
1204 m_canvas->updateCanvasDecorations();
1205}
float value(const T *src, size_t ch)

References m_canvas, and value().

◆ slotChangeSubdivisions

void KisAssistantTool::slotChangeSubdivisions ( int value)
slot

Definition at line 1159 of file kis_assistant_tool.cc.

1159 {
1160 if (m_canvas->paintingAssistantsDecoration()->assistants().length() == 0) {
1161 return;
1162 }
1163
1164 // get the selected assistant and change the angle value
1165 KisPaintingAssistantSP m_selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
1166 if (m_selectedAssistant) {
1167 bool isRulerAssistant = m_selectedAssistant->id() == "ruler"
1168 || m_selectedAssistant->id() == "infinite ruler";
1169 bool isPerspectiveAssistant = m_selectedAssistant->id() == "perspective";
1170
1171 if (isRulerAssistant) {
1172 QSharedPointer <RulerAssistant> assis = qSharedPointerCast<RulerAssistant>(m_selectedAssistant);
1173 assis->setSubdivisions(value);
1174
1175 m_options.minorSubdivisionsSpinbox->setEnabled(value > 0);
1176 }
1177
1178 else if (isPerspectiveAssistant) {
1179 QSharedPointer <PerspectiveAssistant> assis = qSharedPointerCast<PerspectiveAssistant>(m_selectedAssistant);
1180 assis->setSubdivisions(value);
1181 }
1182 }
1183
1184 m_canvas->updateCanvasDecorations();
1185}

References m_canvas, m_options, and value().

◆ slotChangeTwoPointDensity

void KisAssistantTool::slotChangeTwoPointDensity ( double value)
slot

Definition at line 1119 of file kis_assistant_tool.cc.

1120{
1121 if ( m_canvas->paintingAssistantsDecoration()->assistants().length() == 0) {
1122 return;
1123 }
1124
1125 // get the selected assistant and change the angle value
1126 KisPaintingAssistantSP m_selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
1127 if (m_selectedAssistant) {
1128 bool isTwoPointAssistant = m_selectedAssistant->id() == "two point";
1129
1130 if (isTwoPointAssistant) {
1131 QSharedPointer <TwoPointAssistant> assis = qSharedPointerCast<TwoPointAssistant>(m_selectedAssistant);
1132 assis->setGridDensity((float)value);
1133 }
1134 }
1135
1136 m_canvas->updateCanvasDecorations();
1137}

References m_canvas, and value().

◆ slotChangeTwoPointUseVertical

void KisAssistantTool::slotChangeTwoPointUseVertical ( int value)
slot

Definition at line 1139 of file kis_assistant_tool.cc.

1140{
1141 if ( m_canvas->paintingAssistantsDecoration()->assistants().length() == 0) {
1142 return;
1143 }
1144
1145 // get the selected assistant and change the angle value
1146 KisPaintingAssistantSP m_selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
1147 if (m_selectedAssistant) {
1148 bool isTwoPointAssistant = m_selectedAssistant->id() == "two point";
1149
1150 if (isTwoPointAssistant) {
1151 QSharedPointer <TwoPointAssistant> assis = qSharedPointerCast<TwoPointAssistant>(m_selectedAssistant);
1152 assis->setUseVertical(value == Qt::Checked);
1153 }
1154 }
1155
1156 m_canvas->updateCanvasDecorations();
1157}

References m_canvas, and value().

◆ slotChangeVanishingPointAngle

void KisAssistantTool::slotChangeVanishingPointAngle ( double value)
slot

Definition at line 1099 of file kis_assistant_tool.cc.

1100{
1101 if ( m_canvas->paintingAssistantsDecoration()->assistants().length() == 0) {
1102 return;
1103 }
1104
1105 // get the selected assistant and change the angle value
1106 KisPaintingAssistantSP m_selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
1107 if (m_selectedAssistant) {
1108 bool isVanishingPointAssistant = m_selectedAssistant->id() == "vanishing point";
1109
1110 if (isVanishingPointAssistant) {
1111 QSharedPointer <VanishingPointAssistant> assis = qSharedPointerCast<VanishingPointAssistant>(m_selectedAssistant);
1112 assis->setReferenceLineDensity((float)value);
1113 }
1114 }
1115
1116 m_canvas->updateCanvasDecorations();
1117}

References m_canvas, and value().

◆ slotCustomOpacityChanged

void KisAssistantTool::slotCustomOpacityChanged ( )
privateslot

Definition at line 1893 of file kis_assistant_tool.cc.

1894{
1895 KisPaintingAssistantSP m_selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
1896 if (m_selectedAssistant) {
1897 QColor newColor = m_selectedAssistant->assistantCustomColor();
1898 qreal newOpacity = m_options.customColorOpacitySlider->value() * 0.01 * 255.0;
1899 newColor.setAlpha(int(newOpacity));
1900 m_selectedAssistant->setAssistantCustomColor(newColor);
1901 m_selectedAssistant->uncache();
1902 }
1903
1904 // this forces the canvas to refresh to see the changes immediately
1905 m_canvas->paintingAssistantsDecoration()->uncache();
1906 m_canvas->updateCanvasDecorations();
1907}

References m_canvas, and m_options.

◆ slotEnableFixedLength

void KisAssistantTool::slotEnableFixedLength ( int enabled)
slot

Definition at line 1207 of file kis_assistant_tool.cc.

1207 {
1208 if (m_canvas->paintingAssistantsDecoration()->assistants().length() == 0) {
1209 return;
1210 }
1211
1212 // get the selected assistant and change the angle value
1213 KisPaintingAssistantSP m_selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
1214 if (m_selectedAssistant) {
1215 bool isRulerAssistant = m_selectedAssistant->id() == "ruler"
1216 || m_selectedAssistant->id() == "infinite ruler";
1217
1218 if (isRulerAssistant) {
1219 QSharedPointer <RulerAssistant> assis = qSharedPointerCast<RulerAssistant>(m_selectedAssistant);
1220
1221 m_options.fixedLengthSpinbox->setVisible(enabled);
1222 m_options.fixedLengthUnit->setVisible(enabled);
1223
1224 if (enabled && !assis->hasFixedLength() && assis->handles().size() >= 2) {
1225 // When enabling, set the length to the current length.
1226 QPointF a = *assis->handles()[0];
1227 QPointF b = *assis->handles()[1];
1228 qreal length = sqrt(KisPaintingAssistant::norm2(b - a));
1229 assis->setFixedLength(length);
1230 m_options.fixedLengthSpinbox->changeValue(length);
1231 }
1232
1233 assis->enableFixedLength(enabled);
1234 }
1235 }
1236
1237 m_canvas->updateCanvasDecorations();
1238}

References length(), m_canvas, m_options, and KisPaintingAssistant::norm2().

◆ slotGlobalAssistantOpacityChanged

void KisAssistantTool::slotGlobalAssistantOpacityChanged ( )
privateslot

Definition at line 1863 of file kis_assistant_tool.cc.

1864{
1865 QColor newColor = m_canvas->paintingAssistantsDecoration()->globalAssistantsColor();
1866 qreal newOpacity = m_options.assistantsGlobalOpacitySlider->value() * 0.01 * 255.0;
1867 newColor.setAlpha(int(newOpacity));
1868 m_canvas->paintingAssistantsDecoration()->setGlobalAssistantsColor(newColor);
1869
1870 m_canvas->paintingAssistantsDecoration()->uncache();
1871 m_canvas->updateCanvasDecorations();
1872}

References m_canvas, and m_options.

◆ slotGlobalAssistantsColorChanged

void KisAssistantTool::slotGlobalAssistantsColorChanged ( const QColor & setColor)
privateslot

send the color and opacity information from the UI to the kis_painting_decoration which manages the assistants

Definition at line 1849 of file kis_assistant_tool.cc.

1850{
1851 // color and alpha are stored separately, so we need to merge the values before sending it on
1852 int oldAlpha = m_canvas->paintingAssistantsDecoration()->globalAssistantsColor().alpha();
1853
1854 QColor newColor = setColor;
1855 newColor.setAlpha(oldAlpha);
1856
1857 m_canvas->paintingAssistantsDecoration()->setGlobalAssistantsColor(newColor);
1858
1859 m_canvas->paintingAssistantsDecoration()->uncache();
1860 m_canvas->updateCanvasDecorations();
1861}
void setColor(PaintDeviceSP device, const QPoint &pt, const KoColor &color)

References m_canvas.

◆ slotLocalAssistantCheckboxChanged

void KisAssistantTool::slotLocalAssistantCheckboxChanged ( )
privateslot

Definition at line 1909 of file kis_assistant_tool.cc.

1910{
1911 KConfigGroup cfg = KSharedConfig::openConfig()->group(toolId());
1912 cfg.writeEntry("LimitAssistantToArea", m_options.localAssistantCheckbox->isChecked());
1913}

References m_options, and KoToolBase::toolId().

◆ slotSelectedAssistantTypeChanged

void KisAssistantTool::slotSelectedAssistantTypeChanged ( )
privateslot

Definition at line 1915 of file kis_assistant_tool.cc.

1916{
1918}

References updateToolOptionsUI().

◆ slotToggleDeleteButton

void KisAssistantTool::slotToggleDeleteButton ( int index)
privateslot

Definition at line 1958 of file kis_assistant_tool.cc.

1959{
1960 AssistantEditorData &globalEditorWidgetData = m_canvas->paintingAssistantsDecoration()->globalEditorWidgetData;
1961 globalEditorWidgetData.deleteButtonActivated = (index > 0) ? true:false;
1963}

References AssistantEditorData::deleteButtonActivated, m_canvas, and updateEditorWidgetData().

◆ slotToggleDockToolOptionsVisible

void KisAssistantTool::slotToggleDockToolOptionsVisible ( )
privateslot

Definition at line 1919 of file kis_assistant_tool.cc.

1919 {
1920
1922 m_options.showDockerOptionsPanel->setVisible(ToggleDockToolOptionsVisible);
1923
1925 m_options.showDockerOptionsButton->setIcon(KisIconUtils::loadIcon("arrow-down"));
1926 }
1927 else{
1928 m_options.showDockerOptionsButton->setIcon(KisIconUtils::loadIcon("arrow-right"));
1929 }
1930
1931 m_options.showDockerOptionsButton->setIconSize(QSize(16, 16));
1932
1933}

References KisIconUtils::loadIcon(), m_options, and ToggleDockToolOptionsVisible.

◆ slotToggleDuplicateButton

void KisAssistantTool::slotToggleDuplicateButton ( int index)
privateslot

Definition at line 1952 of file kis_assistant_tool.cc.

1953{
1954 AssistantEditorData &globalEditorWidgetData = m_canvas->paintingAssistantsDecoration()->globalEditorWidgetData;
1955 globalEditorWidgetData.duplicateButtonActivated = (index > 0) ? true:false;
1957}

References AssistantEditorData::duplicateButtonActivated, m_canvas, and updateEditorWidgetData().

◆ slotToggleLockButton

void KisAssistantTool::slotToggleLockButton ( int index)
privateslot

Definition at line 1946 of file kis_assistant_tool.cc.

1947{
1948 AssistantEditorData &globalEditorWidgetData = m_canvas->paintingAssistantsDecoration()->globalEditorWidgetData;
1949 globalEditorWidgetData.lockButtonActivated = (index > 0) ? true:false;
1951}

References AssistantEditorData::lockButtonActivated, m_canvas, and updateEditorWidgetData().

◆ slotToggleMoveButton

void KisAssistantTool::slotToggleMoveButton ( int index)
privateslot

Definition at line 1934 of file kis_assistant_tool.cc.

1935{
1936 AssistantEditorData &globalEditorWidgetData = m_canvas->paintingAssistantsDecoration()->globalEditorWidgetData;
1937 globalEditorWidgetData.moveButtonActivated = (index > 0) ? true:false;
1939}

References m_canvas, AssistantEditorData::moveButtonActivated, and updateEditorWidgetData().

◆ slotToggleSnapButton

void KisAssistantTool::slotToggleSnapButton ( int index)
privateslot

Definition at line 1940 of file kis_assistant_tool.cc.

1941{
1942 AssistantEditorData &globalEditorWidgetData = m_canvas->paintingAssistantsDecoration()->globalEditorWidgetData;
1943 globalEditorWidgetData.snapButtonActivated = (index > 0) ? true:false;
1945}

References m_canvas, AssistantEditorData::snapButtonActivated, and updateEditorWidgetData().

◆ slotUpdateCustomColor

void KisAssistantTool::slotUpdateCustomColor ( )
privateslot

Definition at line 1874 of file kis_assistant_tool.cc.

1875{
1876 // get the selected assistant and change the angle value
1877 KisPaintingAssistantSP m_selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
1878 if (m_selectedAssistant) {
1879 m_selectedAssistant->setUseCustomColor(m_options.useCustomAssistantColor->isChecked());
1880
1881 // changing color doesn't keep alpha, so update that before we send it on
1882 QColor newColor = m_options.customAssistantColorButton->color();
1883 newColor.setAlpha(m_selectedAssistant->assistantCustomColor().alpha());
1884
1885 m_selectedAssistant->setAssistantCustomColor(newColor);
1886 m_selectedAssistant->uncache();
1887 }
1888
1890 m_canvas->updateCanvasDecorations();
1891}

References m_canvas, m_options, and updateToolOptionsUI().

◆ snap()

bool KisAssistantTool::snap ( KoPointerEvent * event)
private

Definition at line 1998 of file kis_assistant_tool.cc.

1999{
2000 if (event->modifiers() == Qt::NoModifier) {
2001 return false;
2002 }
2003
2004 if (m_handleDrag) {
2005 KisPaintingAssistantsDecorationSP canvasDecoration = m_canvas->paintingAssistantsDecoration();
2006 KisPaintingAssistantSP selectedAssistant = canvasDecoration->selectedAssistant();
2007 QList<KisPaintingAssistantHandleSP> handles = selectedAssistant->handles();
2008
2009 if (selectedAssistant->id() == "two point" && m_handleDrag != handles[2] &&
2010 event->modifiers() != Qt::ShiftModifier) {
2011 // Snapping interactions that are specific to the two point assistant.
2012 // Skip this code block when only Shift is pressed, as
2013 // Shift means we only need closest-axis snapping.
2014
2015 QSharedPointer<TwoPointAssistant> assis = qSharedPointerCast<TwoPointAssistant>(selectedAssistant);
2016 KisPaintingAssistantHandleSP handleOpp = m_handleDrag == handles[0] ? handles[1] : handles[0];
2017 const QPointF prevPoint = m_currentAdjustment.isNull() ? m_dragStart : m_currentAdjustment;
2018
2019 qreal size = 0;
2020 const QTransform t = assis->localTransform(prevPoint,*handleOpp,*handles[2],&size);
2021 const QTransform inv = t.inverted();
2022
2023 // Exact alignment matters here, so fudge horizon line
2024 // to be perfectly horizontal instead of trusting the
2025 // QTransform calculation to do it
2026 const QLineF horizon = QLineF(t.map(prevPoint), QPointF(t.map(*handleOpp).x(),t.map(prevPoint).y()));
2027 const QPointF sp = QPointF(0,horizon.p1().y()+size);
2028
2029 const bool preserve_distortion_snap = event->modifiers() == Qt::ControlModifier;
2030 const bool preserve_left_right_ratio_snap = event->modifiers() == (Qt::ControlModifier|Qt::ShiftModifier);
2031 const bool preserve_horizon_snap = event->modifiers() == Qt::AltModifier;
2032
2033 QPointF snap_point;
2034 QPointF opp_snap_point;
2035 QLineF sp_to_opp_vp;
2036
2037 if (preserve_distortion_snap) {
2038 const QLineF sp_to_vp = QLineF(sp, t.map(*m_handleDrag));
2039 sp_to_opp_vp = sp_to_vp.normalVector();
2040 sp_to_vp.intersects(horizon,&snap_point);
2041 } else if (preserve_left_right_ratio_snap) {
2042 const QLineF prev_sp_to_vp = QLineF(sp, horizon.p1());
2043 QLineF new_sp_to_vp = prev_sp_to_vp.translated(t.map(*m_handleDrag)-sp);
2044 QPointF new_sp;
2045 new_sp_to_vp.intersects(QLineF(QPoint(0,0),QPointF(0,1)),&new_sp);
2046 sp_to_opp_vp = new_sp_to_vp.normalVector().translated(new_sp-new_sp_to_vp.p1());
2047 new_sp_to_vp.intersects(horizon,&snap_point);
2048 } else if (preserve_horizon_snap) {
2049 snap_point = QPointF(t.map(*m_handleDrag).x(),horizon.p1().y());
2050 sp_to_opp_vp = QLineF(sp,QPointF(t.map(prevPoint).x(),horizon.p1().y())).normalVector();
2051 }
2052
2053 // The snapping modes must be robust against falling into
2054 // invalid configurations, so test if the new snap points
2055 // actually do make sense
2056 const bool no_intersection =
2057 // NB: opp_snap_point is initialized here
2058 sp_to_opp_vp.intersects(horizon, &opp_snap_point) == QLineF::NoIntersection;
2059 const bool origin_is_between =
2060 (snap_point.x() < 0 && opp_snap_point.x() > 0) ||
2061 (snap_point.x() > 0 && opp_snap_point.x() < 0);
2062 const bool null_opp_point =
2063 qFuzzyIsNull(opp_snap_point.x()) ||
2064 qFuzzyIsNull(opp_snap_point.y());
2065 const bool overlapping_snap_points =
2066 qFuzzyCompare(opp_snap_point.x(),snap_point.x());
2067
2068 // Revert to original state if new points are invalid
2069 if (!origin_is_between || no_intersection || null_opp_point || overlapping_snap_points) {
2071 QPointF oppStart;
2072 // Use different recovery method for different
2073 // snapping modes
2074 if (preserve_distortion_snap) {
2075 sp_to_opp_vp = QLineF(sp, t.map(m_dragStart)).normalVector();
2076 sp_to_opp_vp.intersects(horizon, &oppStart);
2077 } else {
2078 const QPointF p1 = t.map(m_dragStart);
2079 const qreal p2x = preserve_horizon_snap ? t.map(*handleOpp).x() : -p1.x();
2080 const QPointF p2 = QPointF(p2x,p1.y());
2081 const QLineF new_horizon = QLineF(p1,p2);
2082 const qreal new_size = sqrt(pow(new_horizon.length()/2.0,2) -
2083 pow(abs(new_horizon.center().x()),2));
2084 const QPointF new_sp = QPointF(0,horizon.p1().y()+new_size);
2085 sp_to_opp_vp = QLineF(new_sp, t.map(m_dragStart)).normalVector();
2086 }
2087 sp_to_opp_vp.intersects(horizon, &oppStart);
2088 *handleOpp=inv.map(oppStart);
2089 m_currentAdjustment = QPointF(0,0); // clear
2090 } else {
2091 // otherwise use the new configuration if it's valid
2092 *m_handleDrag = inv.map(snap_point);
2093 *handleOpp = inv.map(opp_snap_point);
2095 }
2096 } else if (m_snapIsRadial == true) {
2097 QLineF dragRadius = QLineF(m_dragStart, event->point);
2098 dragRadius.setLength(m_radius.length());
2099 *m_handleDrag = dragRadius.p2();
2100 } else {
2101 QPointF snap_point = snapToClosestNiceAngle(event->point, m_dragStart);
2102 *m_handleDrag = snap_point;
2103 }
2104 } else {
2107 KisPaintingAssistantHandleSP handle_snap = handles.back();
2108 // for any assistant, snap 2nd handle to x or y axis relative to first handle
2109 if (handles.size() == 2) {
2110 QPointF snap_point = snapToClosestNiceAngle(event->point, (QPointF)(*handles[0]));
2111 *handle_snap = snap_point;
2112 } else {
2113 bool was_snapped = false;
2114 if (m_newAssistant->id() == "spline") {
2116 handles.size() == 3 ? start = handles[0] : start = handles[1];
2117 QPointF snap_point = snapToClosestNiceAngle(event->point, (QPointF)(*start));
2118 *handle_snap = snap_point;
2119 was_snapped = true;
2120 }
2121
2122 if (m_newAssistant->id() == "ellipse" ||
2123 m_newAssistant->id() == "concentric ellipse" ||
2124 m_newAssistant->id() == "fisheye-point") {
2125 QPointF center = QLineF(*handles[0], *handles[1]).center();
2126 QLineF radius = QLineF(center,*handles[0]);
2127 QLineF dragRadius = QLineF(center, event->point);
2128 dragRadius.setLength(radius.length());
2129 *handle_snap = dragRadius.p2();
2130 was_snapped = true;
2131 }
2132
2133 if (m_newAssistant->id() == "perspective") {
2135 handles.size() == 3 ? start = handles[1] : start = handles[2];
2136 QPointF snap_point = snapToClosestNiceAngle(event->point, (QPointF)(*start));
2137 *handle_snap = snap_point;
2138 was_snapped = true;
2139 }
2140 return was_snapped;
2141 }
2142 }
2143 }
2144 return true;
2145}
static bool qFuzzyCompare(half p1, half p2)
static bool qFuzzyIsNull(half h)

References m_canvas, m_currentAdjustment, m_dragStart, m_handleDrag, m_internalMode, m_newAssistant, m_radius, m_snapIsRadial, MODE_CREATION, KoPointerEvent::modifiers(), p1, p2, KoPointerEvent::point, qFuzzyCompare(), qFuzzyIsNull(), KisPaintingAssistantsDecoration::selectedAssistant(), and snapToClosestNiceAngle().

◆ updateEditorWidgetData()

void KisAssistantTool::updateEditorWidgetData ( )
private

Definition at line 853 of file kis_assistant_tool.cc.

854{
855
856 AssistantEditorData &globalEditorWidgetData = m_canvas->paintingAssistantsDecoration()->globalEditorWidgetData;
857 if( !globalEditorWidgetData.moveButtonActivated && !globalEditorWidgetData.snapButtonActivated && !globalEditorWidgetData.lockButtonActivated &&
858 !globalEditorWidgetData.duplicateButtonActivated && !globalEditorWidgetData.deleteButtonActivated) {
859 globalEditorWidgetData.widgetActivated = false;
860 } else globalEditorWidgetData.widgetActivated = true;
861
862 int horizontalButtonLimit = globalEditorWidgetData.horizontalButtonLimit;
863 int buttonCount = 0;
864 int horizontalButtonCount = 0;
865 int positionX = 15;
866 int positionY = 15;
867
868 //loop through all buttons and calculate positions
869 if(globalEditorWidgetData.moveButtonActivated) {
870
871 buttonCount++;
872 horizontalButtonCount++;
873 if(horizontalButtonCount > horizontalButtonLimit)
874 {
875 horizontalButtonCount = 1;
876 positionX = 15;
877 positionY += globalEditorWidgetData.buttonSize + globalEditorWidgetData.buttonPadding;
878 }
879 //the size icon is a little smaller than the others visually, so the icon is scaled
880 //and the positioin is adjusted by -5 to compinsate
881 globalEditorWidgetData.moveIconPosition.setX(positionX-5);
882 globalEditorWidgetData.moveIconPosition.setY(positionY-5);
883 positionX += globalEditorWidgetData.buttonSize + globalEditorWidgetData.buttonPadding;
884 }
885 if(globalEditorWidgetData.snapButtonActivated) {
886 buttonCount++;
887 horizontalButtonCount++;
888 if(horizontalButtonCount > horizontalButtonLimit)
889 {
890 horizontalButtonCount = 1;
891 positionX = 15;
892 positionY += globalEditorWidgetData.buttonSize + globalEditorWidgetData.buttonPadding;
893 }
894 globalEditorWidgetData.snapIconPosition.setX(positionX);
895 globalEditorWidgetData.snapIconPosition.setY(positionY);
896 positionX += globalEditorWidgetData.buttonSize + globalEditorWidgetData.buttonPadding;
897 }
898 if(globalEditorWidgetData.lockButtonActivated) {
899 buttonCount++;
900 horizontalButtonCount++;
901 if(horizontalButtonCount > horizontalButtonLimit)
902 {
903 horizontalButtonCount = 1;
904 positionX = 15;
905 positionY += globalEditorWidgetData.buttonSize + globalEditorWidgetData.buttonPadding;
906 }
907 globalEditorWidgetData.lockedIconPosition.setX(positionX);
908 globalEditorWidgetData.lockedIconPosition.setY(positionY);
909 positionX += globalEditorWidgetData.buttonSize + globalEditorWidgetData.buttonPadding;
910 }
911 if(globalEditorWidgetData.duplicateButtonActivated) {
912 buttonCount++;
913 horizontalButtonCount++;
914 if(horizontalButtonCount > horizontalButtonLimit)
915 {
916 horizontalButtonCount = 0;
917 positionX = 15;
918 positionY += globalEditorWidgetData.buttonSize + globalEditorWidgetData.buttonPadding;
919 }
920 globalEditorWidgetData.duplicateIconPosition.setX(positionX);
921 globalEditorWidgetData.duplicateIconPosition.setY(positionY);
922 positionX += globalEditorWidgetData.buttonSize + globalEditorWidgetData.buttonPadding;
923 }
924 if(globalEditorWidgetData.deleteButtonActivated) {
925 buttonCount++;
926 horizontalButtonCount++;
927 if(horizontalButtonCount > horizontalButtonLimit)
928 {
929 horizontalButtonCount = 1;
930 positionX = 15;
931 positionY += globalEditorWidgetData.buttonSize + globalEditorWidgetData.buttonPadding;
932 }
933 globalEditorWidgetData.deleteIconPosition.setX(positionX);
934 globalEditorWidgetData.deleteIconPosition.setY(positionY);
935 positionX += globalEditorWidgetData.buttonSize + globalEditorWidgetData.buttonPadding;
936 }
937
938 int buttonSection = globalEditorWidgetData.buttonSize+globalEditorWidgetData.buttonPadding;
939 int boundingWidgetWidth = (buttonCount < horizontalButtonLimit) ? buttonCount*buttonSection:horizontalButtonLimit*buttonSection;
940 boundingWidgetWidth += 5;
941 globalEditorWidgetData.boundingSize.setWidth(boundingWidgetWidth+globalEditorWidgetData.dragDecorationWidth);
942
943 int buttonToWidthRatio = (buttonCount/horizontalButtonLimit);
944 if(buttonCount%horizontalButtonLimit != 0) {
945 buttonToWidthRatio++;
946 }
947
948 int boundingWidgetHeight = buttonToWidthRatio*buttonSection;
949 boundingWidgetHeight += 5;
950 globalEditorWidgetData.boundingSize.setHeight(boundingWidgetHeight);
951
952
953 m_canvas->updateCanvasDecorations();
954}

References AssistantEditorData::boundingSize, AssistantEditorData::buttonPadding, AssistantEditorData::buttonSize, AssistantEditorData::deleteButtonActivated, AssistantEditorData::deleteIconPosition, AssistantEditorData::dragDecorationWidth, AssistantEditorData::duplicateButtonActivated, AssistantEditorData::duplicateIconPosition, AssistantEditorData::horizontalButtonLimit, AssistantEditorData::lockButtonActivated, AssistantEditorData::lockedIconPosition, m_canvas, AssistantEditorData::moveButtonActivated, AssistantEditorData::moveIconPosition, AssistantEditorData::snapButtonActivated, AssistantEditorData::snapIconPosition, and AssistantEditorData::widgetActivated.

◆ updateToolOptionsUI

void KisAssistantTool::updateToolOptionsUI ( )
privateslot

Definition at line 976 of file kis_assistant_tool.cc.

977{
978 KisPaintingAssistantSP m_selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
979
980 bool hasActiveAssistant = m_selectedAssistant ? true : false;
981 AssistantEditorData &globalEditorWidgetData = m_canvas->paintingAssistantsDecoration()->globalEditorWidgetData;
982
983 if(globalEditorWidgetData.moveButtonActivated) {
984 m_options.showMove->setChecked(true);
985 }
986 if(globalEditorWidgetData.snapButtonActivated) {
987 m_options.showSnap->setChecked(true);
988 }
989 if(globalEditorWidgetData.lockButtonActivated) {
990 m_options.showLock->setChecked(true);
991 }
992 if(globalEditorWidgetData.duplicateButtonActivated) {
993 m_options.showDuplicate->setChecked(true);
994 }
995 if(globalEditorWidgetData.deleteButtonActivated) {
996 m_options.showDelete->setChecked(true);
997 }
998
999 if (m_selectedAssistant) {
1000 bool isVanishingPointAssistant = m_selectedAssistant->id() == "vanishing point";
1001 bool isTwoPointAssistant = m_selectedAssistant->id() == "two point";
1002 bool isRulerAssistant = m_selectedAssistant->id() == "ruler"
1003 || m_selectedAssistant->id() == "infinite ruler";
1004 bool isPerspectiveAssistant = m_selectedAssistant->id() == "perspective";
1005
1006 m_options.vanishingPointAngleSpinbox->setVisible(isVanishingPointAssistant);
1007 m_options.twoPointDensitySpinbox->setVisible(isTwoPointAssistant);
1008 m_options.twoPointUseVerticalCheckbox->setVisible(isTwoPointAssistant);
1009 m_options.subdivisionsSpinbox->setVisible(isRulerAssistant || isPerspectiveAssistant);
1010 m_options.minorSubdivisionsSpinbox->setVisible(isRulerAssistant);
1011 m_options.fixedLengthCheckbox->setVisible(isRulerAssistant);
1012 // show checkboxes for controlling which control widget buttons are visible
1013 m_options.showMove->setVisible(true);
1014 m_options.showSnap->setVisible(true);
1015 m_options.showLock->setVisible(true);
1016 m_options.showDuplicate->setVisible(true);
1017 m_options.showDelete->setVisible(true);
1018
1019
1020
1021 if (isVanishingPointAssistant) {
1022 QSharedPointer <VanishingPointAssistant> assis = qSharedPointerCast<VanishingPointAssistant>(m_selectedAssistant);
1023 m_options.vanishingPointAngleSpinbox->setValue(assis->referenceLineDensity());
1024 }
1025
1026 if (isTwoPointAssistant) {
1027 QSharedPointer <TwoPointAssistant> assis = qSharedPointerCast<TwoPointAssistant>(m_selectedAssistant);
1028 m_options.twoPointDensitySpinbox->setValue(assis->gridDensity());
1029 m_options.twoPointUseVerticalCheckbox->setChecked(assis->useVertical());
1030 }
1031
1032 if (isRulerAssistant) {
1033 QSharedPointer <RulerAssistant> assis = qSharedPointerCast<RulerAssistant>(m_selectedAssistant);
1034 m_options.subdivisionsSpinbox->setValue(assis->subdivisions());
1035 m_options.minorSubdivisionsSpinbox->setValue(assis->minorSubdivisions());
1036 m_options.fixedLengthCheckbox->setChecked(assis->hasFixedLength());
1037
1038 m_options.fixedLengthSpinbox->setVisible(assis->hasFixedLength());
1039 m_options.fixedLengthUnit->setVisible(assis->hasFixedLength());
1040 {
1041 // Block valueChanged signals during unit switch
1042 QSignalBlocker b(m_options.fixedLengthSpinbox);
1043 m_unitManager->setApparentUnitFromSymbol(assis->fixedLengthUnit());
1044 m_options.fixedLengthUnit->setCurrentIndex(m_unitManager->getApparentUnitId());
1045 m_options.fixedLengthSpinbox->changeValue(assis->fixedLength());
1046 }
1047 m_options.fixedLengthSpinbox->setPrefix("");
1048 } else {
1049 m_options.fixedLengthSpinbox->setVisible(false);
1050 m_options.fixedLengthUnit->setVisible(false);
1051 }
1052
1053 if (isPerspectiveAssistant) {
1054 QSharedPointer <PerspectiveAssistant> assis = qSharedPointerCast<PerspectiveAssistant>(m_selectedAssistant);
1055 m_options.subdivisionsSpinbox->setValue(assis->subdivisions());
1056 }
1057
1058 // load custom color settings from assistant (this happens when changing assistant
1059 m_options.useCustomAssistantColor->setChecked(m_selectedAssistant->useCustomColor());
1060 m_options.customAssistantColorButton->setColor(m_selectedAssistant->assistantCustomColor());
1061
1062
1063 double opacity = (double)m_selectedAssistant->assistantCustomColor().alpha()/(double)255.00 * (double)100.00 ;
1064 opacity = ceil(opacity); // helps keep the 0-100% slider from shifting
1065
1066 m_options.customColorOpacitySlider->blockSignals(true);
1067 m_options.customColorOpacitySlider->setValue((double)opacity);
1068 m_options.customColorOpacitySlider->blockSignals(false);
1069
1070 } else {
1071 m_options.vanishingPointAngleSpinbox->setVisible(false);
1072 m_options.twoPointDensitySpinbox->setVisible(false);
1073 m_options.twoPointUseVerticalCheckbox->setVisible(false);
1074 m_options.subdivisionsSpinbox->setVisible(false);
1075 m_options.minorSubdivisionsSpinbox->setVisible(false);
1076 m_options.fixedLengthCheckbox->setVisible(false);
1077 m_options.fixedLengthSpinbox->setVisible(false);
1078 m_options.fixedLengthUnit->setVisible(false);
1079 }
1080
1081 // show/hide elements if an assistant is selected or not
1082 m_options.useCustomAssistantColor->setVisible(hasActiveAssistant);
1083
1084 // hide custom color options if use custom color is not selected
1085 bool showCustomColorSettings = m_options.useCustomAssistantColor->isChecked() && hasActiveAssistant;
1086 m_options.customColorOpacitySlider->setVisible(showCustomColorSettings);
1087 m_options.customAssistantColorButton->setVisible(showCustomColorSettings);
1088
1089 // disable global color settings if we are using the custom color
1090 m_options.assistantsGlobalOpacitySlider->setEnabled(!showCustomColorSettings);
1091 m_options.assistantsColor->setEnabled(!showCustomColorSettings);
1092 m_options.globalColorLabel->setEnabled(!showCustomColorSettings);
1093
1094 QString key = m_options.availableAssistantsComboBox->model()->index( m_options.availableAssistantsComboBox->currentIndex(), 0 ).data(Qt::UserRole).toString();
1095 m_options.localAssistantCheckbox->setVisible(key == "two point" || key == "vanishing point" || key == "parallel ruler");
1096
1097}
int getApparentUnitId() const
get the position of the apparent unit in the list of units. It is useful if we want to build a model ...

References AssistantEditorData::deleteButtonActivated, AssistantEditorData::duplicateButtonActivated, KisSpinBoxUnitManager::getApparentUnitId(), AssistantEditorData::lockButtonActivated, m_canvas, m_options, m_unitManager, AssistantEditorData::moveButtonActivated, KisSpinBoxUnitManager::setApparentUnitFromSymbol(), and AssistantEditorData::snapButtonActivated.

Member Data Documentation

◆ assistantDuplicatingFlag

bool KisAssistantTool::assistantDuplicatingFlag {false}
protected

Definition at line 172 of file kis_assistant_tool.h.

172{false}; // this flag is set during an assistant duplication

◆ m_assistantDrag

KisPaintingAssistantSP KisAssistantTool::m_assistantDrag
protected

Definition at line 155 of file kis_assistant_tool.h.

◆ m_assistantHelperYOffset

int KisAssistantTool::m_assistantHelperYOffset {10}
private

Definition at line 178 of file kis_assistant_tool.h.

178{10}; // used by the assistant editor icons for placement on the canvas.

◆ m_canvas

QPointer<KisCanvas2> KisAssistantTool::m_canvas
protected

this class manipulates the kis_painting_assistant_decorations a lot, so this class is a helper to get a reference to it and call "updateCanvas" which refreshes the display

Definition at line 146 of file kis_assistant_tool.h.

◆ m_currentAdjustment

QPointF KisAssistantTool::m_currentAdjustment
protected

Definition at line 162 of file kis_assistant_tool.h.

◆ m_cursorStart

QPointF KisAssistantTool::m_cursorStart
protected

Definition at line 161 of file kis_assistant_tool.h.

◆ m_dragEnd

QPointF KisAssistantTool::m_dragEnd
protected

Definition at line 169 of file kis_assistant_tool.h.

◆ m_dragStart

QPointF KisAssistantTool::m_dragStart
protected

Definition at line 166 of file kis_assistant_tool.h.

◆ m_handleCombine

KisPaintingAssistantHandleSP KisAssistantTool::m_handleCombine
protected

Definition at line 153 of file kis_assistant_tool.h.

◆ m_handleDrag

KisPaintingAssistantHandleSP KisAssistantTool::m_handleDrag
protected

Definition at line 152 of file kis_assistant_tool.h.

◆ m_handleHover

KisPaintingAssistantHandleSP KisAssistantTool::m_handleHover
protected

Definition at line 154 of file kis_assistant_tool.h.

◆ m_handleMaxDist

int KisAssistantTool::m_handleMaxDist {81}
protected

Definition at line 171 of file kis_assistant_tool.h.

171{81}; // how far away the user can click and still select a handle

◆ m_handles

QList<KisPaintingAssistantHandleSP> KisAssistantTool::m_handles
protected

the handles are retrieved from the kis_painting_decoration originally They are used here to generate and manipulate editor handles with the tool's primary action

Definition at line 150 of file kis_assistant_tool.h.

◆ m_handleSize

int KisAssistantTool::m_handleSize {17}
protected

Definition at line 170 of file kis_assistant_tool.h.

170{17}; // how large the editor handles will appear

◆ m_highlightedNode

KisPaintingAssistantHandleSP KisAssistantTool::m_highlightedNode
private

Definition at line 177 of file kis_assistant_tool.h.

◆ m_internalMode

PerspectiveAssistantEditionMode KisAssistantTool::m_internalMode { MODE_CREATION }
private

Definition at line 176 of file kis_assistant_tool.h.

176{ MODE_CREATION };

◆ m_newAssistant

KisPaintingAssistantSP KisAssistantTool::m_newAssistant
protected

Used while a new assistant is being created. Most assistants need multiple points to exist so this helps manage the visual state while this creation process is going on

Definition at line 159 of file kis_assistant_tool.h.

◆ m_options

Ui::AssistantsToolOptions KisAssistantTool::m_options
protected

Definition at line 164 of file kis_assistant_tool.h.

◆ m_optionsWidget

QWidget* KisAssistantTool::m_optionsWidget {0}
protected

Definition at line 165 of file kis_assistant_tool.h.

165{0};

◆ m_origAssistantList

QList<KisPaintingAssistantSP> KisAssistantTool::m_origAssistantList
private

Definition at line 179 of file kis_assistant_tool.h.

◆ m_previousHandlePos

QPointF KisAssistantTool::m_previousHandlePos
protected

Definition at line 163 of file kis_assistant_tool.h.

◆ m_radius

QLineF KisAssistantTool::m_radius
protected

Definition at line 167 of file kis_assistant_tool.h.

◆ m_selectedNode1

KisPaintingAssistantHandleSP KisAssistantTool::m_selectedNode1
private

Definition at line 177 of file kis_assistant_tool.h.

◆ m_selectedNode2

KisPaintingAssistantHandleSP KisAssistantTool::m_selectedNode2
private

Definition at line 177 of file kis_assistant_tool.h.

◆ m_sideHandles

QList<KisPaintingAssistantHandleSP> KisAssistantTool::m_sideHandles
protected

Definition at line 151 of file kis_assistant_tool.h.

◆ m_snapIsRadial

bool KisAssistantTool::m_snapIsRadial {false}
protected

Definition at line 168 of file kis_assistant_tool.h.

168{false};

◆ m_unitManager

KisSpinBoxUnitManager* KisAssistantTool::m_unitManager {0}
private

Definition at line 180 of file kis_assistant_tool.h.

180{0};

◆ ToggleDockToolOptionsVisible

bool KisAssistantTool::ToggleDockToolOptionsVisible = false
private

Definition at line 89 of file kis_assistant_tool.h.


The documentation for this class was generated from the following files: