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 Enter key or any equivalent. 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 52 of file kis_assistant_tool.cc.

54 , m_canvas(dynamic_cast<KisCanvas2*>(canvas))
59{
60 Q_ASSERT(m_canvas);
61 setObjectName("tool_assistanttool");
62}
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 64 of file kis_assistant_tool.cc.

65{
66}

Member Function Documentation

◆ activate

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

Definition at line 68 of file kis_assistant_tool.cc.

69{
70
71 KisTool::activate(shapes);
72
73 m_canvas->paintingAssistantsDecoration()->activateAssistantsEditor();
74 m_handles = m_canvas->paintingAssistantsDecoration()->handles();
75
77 m_canvas->paintingAssistantsDecoration()->setHandleSize(m_handleSize);
78
79
80 if (m_optionsWidget) {
81 m_canvas->paintingAssistantsDecoration()->deselectAssistant();
83 }
84
85 m_canvas->updateCanvas();
86
87}
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 790 of file kis_assistant_tool.cc.

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

970{
971 m_canvas->paintingAssistantsDecoration()->setSelectedAssistant(assistant);
973}

References m_canvas, and updateToolOptionsUI().

◆ beginActionImpl()

void KisAssistantTool::beginActionImpl ( KoPointerEvent * event)
private

Definition at line 96 of file kis_assistant_tool.cc.

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

1964{
1965 Q_UNUSED(action);
1966 beginActionImpl(event);
1967}
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 1981 of file kis_assistant_tool.cc.

1982{
1983 beginActionImpl(event);
1984}

References beginActionImpl().

◆ continueActionImpl()

void KisAssistantTool::continueActionImpl ( KoPointerEvent * event)
private

Definition at line 514 of file kis_assistant_tool.cc.

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

1970{
1971 Q_UNUSED(action);
1972 continueActionImpl(event);
1973}
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 1986 of file kis_assistant_tool.cc.

1987{
1988 continueActionImpl(event);
1989}

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 1684 of file kis_assistant_tool.cc.

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

90{
91 m_canvas->paintingAssistantsDecoration()->deactivateAssistantsEditor();
92 m_canvas->updateCanvas();
94}
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 736 of file kis_assistant_tool.cc.

737{
739 // release duplication button flag
741 KisPaintingAssistantSP selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
742 selectedAssistant->setDuplicating(false);
744
745 // offset control widget if user simple click-releases duplication button
746 if (m_dragEnd == m_dragStart) {
747 // calculate offset independent from canvas resolution and zoom
748 const KisCoordinatesConverter *converter = m_canvas->coordinatesConverter();
749 // create offset unit, considering canvas resolution
750 const int offset = 20;
751 const float offsetUnit = offset / m_canvas->image()->xRes();
752 // use unit to calculate final offset, considering canvas zoom
753 QPointF widgetDuplicationOffset = QPointF(offsetUnit / converter->effectiveZoom(),offsetUnit / converter->effectiveZoom());
754 // apply offset to control widget
755 QPointF currentOffset = selectedAssistant->editorWidgetOffset();
756 selectedAssistant->setEditorWidgetOffset(currentOffset + widgetDuplicationOffset);
757 }
758 }
759
761 if (m_handleDrag) {
762 if (!(event->modifiers() & Qt::ShiftModifier) && m_handleCombine) {
765 m_handles = m_canvas->paintingAssistantsDecoration()->handles();
766 }
768 } else {
769 m_assistantDrag.clear();
770 }
771 dbgUI << "creating undo command...";
772 KUndo2Command *command = new EditAssistantsCommand(m_canvas, m_origAssistantList, KisPaintingAssistant::cloneAssistantList(m_canvas->paintingAssistantsDecoration()->assistants()));
773 m_canvas->viewManager()->undoAdapter()->addCommand(command);
774 dbgUI << "done";
776 addAssistant();
779 KisPaintingAssistantSP selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant();
780 QPointF currentOffset = selectedAssistant->editorWidgetOffset();
781 selectedAssistant->setEditorWidgetOffset(currentOffset + (event->point - m_dragEnd));
782 }
783 else {
784 event->ignore();
785 }
786
787 m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas
788}
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 1975 of file kis_assistant_tool.cc.

1976{
1977 Q_UNUSED(action);
1978 endActionImpl(event);
1979}
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 1991 of file kis_assistant_tool.cc.

1992{
1993 endActionImpl(event);
1994}

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 1356 of file kis_assistant_tool.cc.

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

References m_canvas, and m_newAssistant.

◆ loadAssistants

void KisAssistantTool::loadAssistants ( )
privateslot

Definition at line 1434 of file kis_assistant_tool.cc.

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

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

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

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

◆ 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 1418 of file kis_assistant_tool.cc.

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

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

◆ removeAssistant()

void KisAssistantTool::removeAssistant ( KisPaintingAssistantSP assistant)
private

Definition at line 955 of file kis_assistant_tool.cc.

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

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

◆ saveAssistants

void KisAssistantTool::saveAssistants ( )
privateslot

Definition at line 1595 of file kis_assistant_tool.cc.

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

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

◆ slotChangeFixedLength

void KisAssistantTool::slotChangeFixedLength ( double value)
slot

Definition at line 1239 of file kis_assistant_tool.cc.

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

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

◆ slotChangeFixedLengthUnit

void KisAssistantTool::slotChangeFixedLengthUnit ( int index)
privateslot

Definition at line 1267 of file kis_assistant_tool.cc.

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

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

References m_canvas, and value().

◆ slotChangeSubdivisions

void KisAssistantTool::slotChangeSubdivisions ( int value)
slot

Definition at line 1158 of file kis_assistant_tool.cc.

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

References m_canvas, m_options, and value().

◆ slotChangeTwoPointDensity

void KisAssistantTool::slotChangeTwoPointDensity ( double value)
slot

Definition at line 1118 of file kis_assistant_tool.cc.

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

References m_canvas, and value().

◆ slotChangeTwoPointUseVertical

void KisAssistantTool::slotChangeTwoPointUseVertical ( int value)
slot

Definition at line 1138 of file kis_assistant_tool.cc.

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

References m_canvas, and value().

◆ slotChangeVanishingPointAngle

void KisAssistantTool::slotChangeVanishingPointAngle ( double value)
slot

Definition at line 1098 of file kis_assistant_tool.cc.

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

References m_canvas, and value().

◆ slotCustomOpacityChanged

void KisAssistantTool::slotCustomOpacityChanged ( )
privateslot

Definition at line 1891 of file kis_assistant_tool.cc.

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

References m_canvas, and m_options.

◆ slotEnableFixedLength

void KisAssistantTool::slotEnableFixedLength ( int enabled)
slot

Definition at line 1206 of file kis_assistant_tool.cc.

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

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

◆ slotGlobalAssistantOpacityChanged

void KisAssistantTool::slotGlobalAssistantOpacityChanged ( )
privateslot

Definition at line 1861 of file kis_assistant_tool.cc.

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

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 1847 of file kis_assistant_tool.cc.

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

References m_canvas.

◆ slotLocalAssistantCheckboxChanged

void KisAssistantTool::slotLocalAssistantCheckboxChanged ( )
privateslot

Definition at line 1907 of file kis_assistant_tool.cc.

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

References m_options, and KoToolBase::toolId().

◆ slotSelectedAssistantTypeChanged

void KisAssistantTool::slotSelectedAssistantTypeChanged ( )
privateslot

Definition at line 1913 of file kis_assistant_tool.cc.

1914{
1916}

References updateToolOptionsUI().

◆ slotToggleDeleteButton

void KisAssistantTool::slotToggleDeleteButton ( int index)
privateslot

Definition at line 1956 of file kis_assistant_tool.cc.

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

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

◆ slotToggleDockToolOptionsVisible

void KisAssistantTool::slotToggleDockToolOptionsVisible ( )
privateslot

Definition at line 1917 of file kis_assistant_tool.cc.

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

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

◆ slotToggleDuplicateButton

void KisAssistantTool::slotToggleDuplicateButton ( int index)
privateslot

Definition at line 1950 of file kis_assistant_tool.cc.

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

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

◆ slotToggleLockButton

void KisAssistantTool::slotToggleLockButton ( int index)
privateslot

Definition at line 1944 of file kis_assistant_tool.cc.

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

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

◆ slotToggleMoveButton

void KisAssistantTool::slotToggleMoveButton ( int index)
privateslot

Definition at line 1932 of file kis_assistant_tool.cc.

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

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

◆ slotToggleSnapButton

void KisAssistantTool::slotToggleSnapButton ( int index)
privateslot

Definition at line 1938 of file kis_assistant_tool.cc.

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

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

◆ slotUpdateCustomColor

void KisAssistantTool::slotUpdateCustomColor ( )
privateslot

Definition at line 1872 of file kis_assistant_tool.cc.

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

References m_canvas, m_options, and updateToolOptionsUI().

◆ snap()

bool KisAssistantTool::snap ( KoPointerEvent * event)
private

Definition at line 1996 of file kis_assistant_tool.cc.

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

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

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 975 of file kis_assistant_tool.cc.

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