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

The SvgTextCursor class. More...

#include <SvgTextCursor.h>

+ Inheritance diagram for SvgTextCursor:

Classes

class  InputQueryUpdateBlocker
 

Public Types

enum  MoveMode {
  MoveNone , MoveLeft , MoveRight , MoveUp ,
  MoveDown , MoveNextChar , MovePreviousChar , MoveNextLine ,
  MovePreviousLine , MoveWordLeft , MoveWordRight , MoveWordEnd ,
  MoveWordStart , MoveLineStart , MoveLineEnd , ParagraphStart ,
  ParagraphEnd
}
 
enum  TypeSettingModeHandle {
  NoHandle , StartPos , EndPos , BaselineShift ,
  Ascender , Descender , LineHeightTop , LineHeightBottom ,
  BaselineAlphabetic , BaselineIdeographic , BaselineMiddle , BaselineHanging ,
  BaselineMathematical , BaselineCentral
}
 Handles used by type setting mode. More...
 

Signals

void selectionChanged ()
 Sents an update selection was changed.
 
void sigOpenGlyphPalette ()
 Called by actions, tells the parent tool to open the glyph palette.
 
void updateCursorDecoration (QRectF updateRect)
 Sents an update to the parent tool to update it's decorations.
 

Public Member Functions

void copy () const
 copy copies plain text into the clipboard between anchor and pos.
 
QPair< KoSvgTextProperties, KoSvgTextPropertiescurrentTextProperties () const
 currentTextProperties
 
QCursor cursorTypeForTypeSetting () const
 Return appropriate typeSetting cursor;.
 
void deselectText ()
 Deselect all text. This effectively makes anchor the same as pos.
 
void focusIn ()
 Turns on blinking cursor.
 
void focusOut ()
 Stops blinking cursor.
 
int getAnchor ()
 Get the current selection anchor. This is the same as position, unless there's a selection.
 
int getPos ()
 Get the current position.
 
QString handleName (TypeSettingModeHandle handle) const
 handleName
 
bool hasSelection () override
 return true if the tool currently has something selected that can be copied or deleted.
 
void inputMethodEvent (QInputMethodEvent *event)
 Process an input method event. This is used by IME like virtual keyboards.
 
QVariant inputMethodQuery (Qt::InputMethodQuery query) const
 Process an input method query and return the requested result.
 
void insertRichText (KoSvgTextShape *insert, bool inheritPropertiesIfPossible=false)
 Insert rich text at getPos();.
 
void insertText (QString text)
 Insert text at getPos()
 
bool isAddingCommand () const
 the cursor is currently adding a command
 
void keyPressEvent (QKeyEvent *event)
 Handle the cursor-related key events.
 
void mergePropertiesIntoSelection (const KoSvgTextProperties props, const QSet< KoSvgTextProperties::PropertyId > removeProperties=QSet< KoSvgTextProperties::PropertyId >(), bool paragraphOnly=false, bool selectWord=false)
 mergePropertiesIntoSelection Within Krita's SVG/CSS text system, it is possible to apply incomplete properties to a whole range. In that case, only the existing properties are applied. Properties can also be removed this way.
 
void moveCursor (MoveMode mode, bool moveAnchor=true)
 Move the cursor, and, if you don't want a selection, move the anchor.
 
void notifyCursorPosChanged (int pos, int anchor) override
 
void notifyMarkupChanged () override
 
void notifyShapeChanged (KoShape::ChangeType type, KoShape *shape) override
 
void paintDecorations (QPainter &gc, QColor selectionColor, int decorationThickness=1, qreal handleRadius=5.0, KisHandlePalette handlePalette=KisHandlePalette())
 Paint all decorations and blinkingcursors.
 
bool paste ()
 paste pastes plain text in the clipboard at pos. Uses pasteRichTextByDefault to determine whether to try and paste rich text.
 
int posForTypeSettingHandleAndRect (const TypeSettingModeHandle handle, const QRectF regionOfInterest)
 posForHandleAndRect Returns the closest cursor position for a given region and typesetting handle. Used by the type setting mode to find the relevant metrics to scale.
 
QList< KoSvgTextPropertiespropertiesForRange () const
 propertiesForRange
 
QList< KoSvgTextPropertiespropertiesForShape () const
 propertiesForShape
 
bool registerPropertyAction (QAction *action, const QString &name)
 Register an action.
 
void removeLastCodePoint ()
 removeLastCodePoint Special function to remove the last code point. Triggered by backspace. This is distinct from remove text, as some clusters have multiple code points, but it is generally expected backspace deletes the codepoints while delete with selection deletes the whole cluster.
 
void removeSelection ()
 removeSelection if there's a selection, creates a text-removal command.
 
void removeText (MoveMode first, MoveMode second)
 removeText remove text relative to the current position. This will move the cursor according to the move modes and then remove the text between the two positions.
 
void setCaretSetting (int cursorWidth=1, int cursorFlash=1000, int cursorFlashLimit=5000, bool drawCursorInAdditionToSelection=false)
 setCaretSetting Set the caret settings for the cursor. Qt has some standard functionality associated, which we pass via this.
 
bool setDominantBaselineFromHandle (const TypeSettingModeHandle handle)
 setDominantBaselineFromHandle Set the dominant baseline from a given handle.
 
void setDrawTypeSettingHandle (bool draw)
 
void setPasteRichTextByDefault (const bool pasteRichText=true)
 setPasteRichText
 
void setPos (int pos, int anchor)
 Set the pos and the anchor.
 
void setPosToPoint (QPointF point, bool moveAnchor=true)
 Set the pos from a point. This currently does a search inside the text shape.
 
void setShape (KoSvgTextShape *textShape)
 setShape
 
void setTypeSettingHandleHovered (TypeSettingModeHandle hovered=TypeSettingModeHandle::NoHandle)
 Set a given typesetting handle as hovered, so it will be drawn as such.
 
void setTypeSettingModeActive (bool activate)
 Set type setting mode active.
 
void setVisualMode (const bool visualMode=true)
 setVisualMode set whether the navigation mode is visual or logical. This right now primarily affects Bidirectional text.
 
KoSvgTextShapeshape () const
 Get the current text shape.
 
 SvgTextCursor (KoCanvasBase *canvas)
 
KoSvgTextPropertiesInterfacetextPropertyInterface ()
 
TypeSettingModeHandle typeSettingHandleAtPos (const QRectF regionOfInterest)
 Get typeSettingMode handle for text;.
 
void updateModifiers (const Qt::KeyboardModifiers modifiers)
 
void updateTypeSettingDecorFromShape ()
 Update the type setting decorations.
 
 ~SvgTextCursor ()
 
- Public Member Functions inherited from Private
 Private (KisCanvas2 *c)
 
- Public Member Functions inherited from KoToolSelection
 KoToolSelection (QObject *parent=0)
 
 ~KoToolSelection () override
 
- Public Member Functions inherited from KoSvgTextShape::TextCursorChangeListener
void notifyShapeChanged (ChangeType type, KoShape *shape) override
 
- Public Member Functions inherited from KoShape::ShapeChangeListener
virtual ~ShapeChangeListener ()
 

Public Attributes

QList< QAction * > actions
 
int anchor = 0
 
QLineF anchorCaret
 
int anchorIndex = 0
 
bool blockQueryUpdates = false
 Block qApp->inputMethod->update(), enabled during the inputmethod event flow.
 
KoCanvasBasecanvas
 
QLineF cursorCaret
 
QColor cursorColor
 
QTimer cursorFlash
 
QTimer cursorFlashLimit
 
QPainterPath cursorShape
 
bool cursorVisible = false
 
int cursorWidth = 1
 
bool drawCursorInAdditionToSelection = false
 
bool drawTypeSettingHandle = true
 
qreal handleRadius = 7
 
bool hasFocus = false
 
SvgTextCursor::TypeSettingModeHandle hoveredTypeSettingHandle = SvgTextCursor::NoHandle
 
QPainterPath IMEDecoration
 The decorations for the current preedit string.
 
SvgTextCursorPropertyInterfaceinterface {nullptr}
 
bool isAddingCommand = false
 
Qt::KeyboardModifiers lastKnownModifiers
 
QRectF oldCursorRect
 
QRectF oldIMEDecorationRect
 Update Rectangle of previous decoration.
 
QRectF oldSelectionRect
 
QRectF oldTypeSettingRect
 
bool pasteRichText = true
 
int pos = 0
 
int posIndex = 0
 
SvgTextInsertCommandpreEditCommand {nullptr}
 PreEdit string as an command provided by the input method.
 
int preEditLength = -1
 Length of the preEditString.
 
int preEditStart = -1
 Start of the preEdit string as a cursor pos.
 
KisAcyclicSignalConnector resourceManagerAcyclicConnector
 
QPainterPath selection
 
KoSvgTextShapeshape {nullptr}
 
QVector< IMEDecorationInfostyleMap
 Decoration info (underlines) for the preEdit string to differentiate it from regular text.
 
TypeSettingDecorInfo typeSettingDecor
 
bool typeSettingMode = false
 
bool visualNavigation = true
 
- Public Attributes inherited from Private
KisCanvas2canvas
 
int displayedFrame
 
int intendedFrame
 

Private Slots

void blinkCursor ()
 Called by timer, toggles the text cursor visible or invisible.
 
void canvasResourceChanged (int key, const QVariant &value)
 Called when the canvas resources (foreground/background) change.
 
void clearFormattingAction ()
 Called by the clear formatting action.
 
bool pastePlainText ()
 pastePlainText Explicitely paste plaintext at pos.
 
bool pasteRichText ()
 pasteRichText
 
void propertyAction ()
 Called by the actions to execute a property change based on their data.
 
void removeTransformsFromRange ()
 removeTransformsFromRange Called by actions to remove svg character transforms from range.
 
void stopBlinkCursor ()
 Called by timer, stops the text blinking animation.
 
void updateCanvasResources ()
 Update the canvas resources with fore and background color.
 
void updateInputMethodItemTransform ()
 

Private Member Functions

bool acceptableInput (const QKeyEvent *event) const
 More or less copied from bool QInputControl::isAcceptableInput(const QKeyEvent *event) const.
 
void addCommandToUndoAdapter (KUndo2Command *cmd)
 Adds a command to the canvas of the parent tool.
 
void commitIMEPreEdit ()
 
int moveModeResult (const MoveMode mode, int &pos, bool visual=false) const
 Processes a move action, returns the input.
 
SvgTextRemoveCommandremoveSelectionImpl (bool allowCleanUp, KUndo2Command *parent=0)
 removeSelection if there's a selection, creates a text-removal command.
 
void updateCursor (bool firstUpdate=false)
 update the cursor shape. First update will block ensuring the canvas is visible so setShape won't cause this.
 
void updateIMEDecoration ()
 
void updateSelection ()
 
void updateTypeSettingDecoration ()
 

Private Attributes

const QScopedPointer< Privated
 

Detailed Description

The SvgTextCursor class.

This class handles cursor movement and text editing operations.

It acts as the KoToolSelection for SvgTextTool, allowing it to integrate with the basic KoToolBase functionality for copy, cut paste and clear.

A selection is defined as the anchor being different from the cursor position, with the move operation accepting whether you want to shift the cursor position.

It is also a shape listener to allow the textcursor to update itself whenever the corresponding text shape changes.

Note for Android: to get a debug view of where the text input is at the operating system level, you can set an environment variable:

qputenv("KRITA_ANDROID_EDIT_TEXT_DEBUG_DRAW", "1")

Definition at line 156 of file SvgTextCursor.cpp.

Member Enumeration Documentation

◆ MoveMode

Enumerator
MoveNone 
MoveLeft 
MoveRight 
MoveUp 
MoveDown 
MoveNextChar 
MovePreviousChar 
MoveNextLine 
MovePreviousLine 
MoveWordLeft 
MoveWordRight 
MoveWordEnd 
MoveWordStart 
MoveLineStart 
MoveLineEnd 
ParagraphStart 
ParagraphEnd 

Definition at line 55 of file SvgTextCursor.h.

◆ TypeSettingModeHandle

Handles used by type setting mode.

Enumerator
NoHandle 
StartPos 
EndPos 
BaselineShift 

The text properties handles.

Ascender 
Descender 
LineHeightTop 
LineHeightBottom 
BaselineAlphabetic 

Baselines.

BaselineIdeographic 
BaselineMiddle 
BaselineHanging 
BaselineMathematical 
BaselineCentral 

Definition at line 76 of file SvgTextCursor.h.

Constructor & Destructor Documentation

◆ SvgTextCursor()

SvgTextCursor::SvgTextCursor ( KoCanvasBase * canvas)
explicit

Definition at line 252 of file SvgTextCursor.cpp.

252 :
253 d(new Private)
254{
255 d->canvas = canvas;
256 d->interface = new SvgTextCursorPropertyInterface(this);
257 if (d->canvas->canvasController()) {
258 // Mockcanvas in the tests has no canvas controller.
259 connect(d->canvas->canvasController()->proxyObject, SIGNAL(sizeChanged(QSize)), this, SLOT(updateInputMethodItemTransform()));
260 connect(d->canvas->canvasController()->proxyObject,
261 SIGNAL(moveDocumentOffset(QPointF, QPointF)),
262 this,
264 connect(d->canvas->canvasController()->proxyObject,
265 SIGNAL(effectiveZoomChanged(qreal)),
266 this,
268 connect(d->canvas->canvasController()->proxyObject,
269 SIGNAL(documentRotationChanged(qreal)),
270 this,
272 connect(d->canvas->canvasController()->proxyObject,
273 SIGNAL(documentMirrorStatusChanged(bool, bool)),
274 this,
276 d->resourceManagerAcyclicConnector.connectBackwardResourcePair(
277 d->canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)),
278 this, SLOT(canvasResourceChanged(int,QVariant)));
279 d->resourceManagerAcyclicConnector.connectForwardVoid(d->interface, SIGNAL(textCharacterSelectionChanged()), this, SLOT(updateCanvasResources()));
280 }
281
282}
Interface to interact with the text property manager.
const QScopedPointer< Private > d
void updateCanvasResources()
Update the canvas resources with fore and background color.
void canvasResourceChanged(int key, const QVariant &value)
Called when the canvas resources (foreground/background) change.
KoCanvasBase * canvas
void updateInputMethodItemTransform()

References canvas, canvasResourceChanged(), d, updateCanvasResources(), and updateInputMethodItemTransform().

◆ ~SvgTextCursor()

SvgTextCursor::~SvgTextCursor ( )

Definition at line 284 of file SvgTextCursor.cpp.

285{
287 d->cursorFlash.stop();
288 d->cursorFlashLimit.stop();
289 d->shape = nullptr;
290}

References commitIMEPreEdit(), and d.

Member Function Documentation

◆ acceptableInput()

bool SvgTextCursor::acceptableInput ( const QKeyEvent * event) const
private

More or less copied from bool QInputControl::isAcceptableInput(const QKeyEvent *event) const.

Tests whether the current keyboard input can be printed as text, or is probably a shortcut. This is so that various keyboard events, like print don't get inserted as text.

Definition at line 2103 of file SvgTextCursor.cpp.

2104{
2105 const QString text = event->text();
2106 if (text.isEmpty())
2107 return false;
2108 const QChar c = text.at(0);
2109 // Formatting characters such as ZWNJ, ZWJ, RLM, etc. This needs to go before the
2110 // next test, since CTRL+SHIFT is sometimes used to input it on Windows.
2111 if (c.category() == QChar::Other_Format)
2112 return true;
2113 // QTBUG-35734: ignore Ctrl/Ctrl+Shift; accept only AltGr (Alt+Ctrl) on German keyboards
2114 if (event->modifiers() == Qt::ControlModifier
2115 || event->modifiers() == (Qt::ShiftModifier | Qt::ControlModifier)) {
2116 return false;
2117 }
2118 if (c.isPrint())
2119 return true;
2120 if (c.category() == QChar::Other_PrivateUse)
2121 return true;
2122 if (c == QLatin1Char('\t'))
2123 return true;
2124 return false;
2125}

◆ addCommandToUndoAdapter()

void SvgTextCursor::addCommandToUndoAdapter ( KUndo2Command * cmd)
private

Adds a command to the canvas of the parent tool.

Definition at line 2017 of file SvgTextCursor.cpp.

2018{
2019 if (d->canvas) {
2020 if (cmd) {
2021 d->isAddingCommand = true;
2022 d->canvas->addCommand(cmd);
2023 d->isAddingCommand = false;
2024 }
2025 }
2026}

References d.

◆ blinkCursor

void SvgTextCursor::blinkCursor ( )
privateslot

Called by timer, toggles the text cursor visible or invisible.

Definition at line 1277 of file SvgTextCursor.cpp.

1278{
1279 if (d->shape) {
1280 Q_EMIT updateCursorDecoration(d->shape->shapeToDocument(d->cursorShape.boundingRect()) | d->oldCursorRect);
1281 d->cursorVisible = !d->cursorVisible;
1282 }
1283}
void updateCursorDecoration(QRectF updateRect)
Sents an update to the parent tool to update it's decorations.

References d, and updateCursorDecoration().

◆ canvasResourceChanged

void SvgTextCursor::canvasResourceChanged ( int key,
const QVariant & value )
privateslot

Called when the canvas resources (foreground/background) change.

Definition at line 1323 of file SvgTextCursor.cpp.

1324{
1326 return;
1327
1328 KoSvgTextProperties props;
1329 KoSvgTextProperties shapeProps = hasSelection()? d->shape->propertiesForPos(qMin(d->pos, d->anchor), true): d->shape->textProperties();
1332 if (!bg->compareTo(shapeProps.background().data())
1333 || !shapeProps.hasProperty(KoSvgTextProperties::FillId)) {
1335 QVariant::fromValue(KoSvgText::BackgroundProperty(bg)));
1336 }
1337 } else if (key == KoCanvasResource::BackgroundColor) {
1340 KoShapeStrokeSP shapeStroke = qSharedPointerDynamicCast<KoShapeStroke>(shapeProps.stroke());
1341 if (shapeStroke->isVisible()) {
1342 stroke.reset(new KoShapeStroke(*shapeStroke));
1343 }
1344 }
1345 stroke->setColor(value.value<KoColor>().toQColor());
1346 if (!stroke->compareFillTo(shapeProps.stroke().data()) || !shapeProps.hasProperty(KoSvgTextProperties::StrokeId)) {
1348 QVariant::fromValue(KoSvgText::StrokeProperty(stroke)));
1349 }
1350 }
1351 if (!props.isEmpty()) {
1352 mergePropertiesIntoSelection(props, QSet<KoSvgTextProperties::PropertyId>(), !hasSelection());
1353 }
1354}
float value(const T *src, size_t ch)
A simple solid color shape background.
void toQColor(QColor *c) const
a convenience method for the above.
Definition KoColor.cpp:198
@ StrokeId
KoSvgText::StrokeProperty.
@ FillId
KoSvgText::BackgroundProperty.
QSharedPointer< KoShapeBackground > background() const
KoShapeStrokeModelSP stroke() const
bool hasProperty(PropertyId id) const
void setProperty(PropertyId id, const QVariant &value)
@ BackgroundColor
The active background color selected for this canvas.
@ ForegroundColor
The active foreground color selected for this canvas.
BackgroundProperty is a special wrapper around KoShapeBackground for managing it in KoSvgTextProperti...
Definition KoSvgText.h:714
StrokeProperty is a special wrapper around KoShapeStrokeModel for managing it in KoSvgTextProperties.
Definition KoSvgText.h:733
void mergePropertiesIntoSelection(const KoSvgTextProperties props, const QSet< KoSvgTextProperties::PropertyId > removeProperties=QSet< KoSvgTextProperties::PropertyId >(), bool paragraphOnly=false, bool selectWord=false)
mergePropertiesIntoSelection Within Krita's SVG/CSS text system, it is possible to apply incomplete p...
bool hasSelection() override
return true if the tool currently has something selected that can be copied or deleted.

References KoSvgTextProperties::background(), KoCanvasResource::BackgroundColor, d, KoSvgTextProperties::FillId, KoCanvasResource::ForegroundColor, KoSvgTextProperties::hasProperty(), hasSelection(), KoSvgTextProperties::isEmpty(), mergePropertiesIntoSelection(), KoSvgTextProperties::setProperty(), KoSvgTextProperties::stroke(), KoSvgTextProperties::StrokeId, KoColor::toQColor(), and value().

◆ clearFormattingAction

void SvgTextCursor::clearFormattingAction ( )
privateslot

Called by the clear formatting action.

Definition at line 1367 of file SvgTextCursor.cpp.

1368{
1369 KoSvgTextProperties props;
1370
1371 QSet<KoSvgTextProperties::PropertyId> ids;
1372
1373 for (int i = 0; i < int(KoSvgTextProperties::LastPropertyId); i++) {
1374 ids.insert(KoSvgTextProperties::PropertyId(i));
1375 }
1376
1377 mergePropertiesIntoSelection(props, ids);
1378}
@ LastPropertyId
Last Property ID, used for iteration.

References KoSvgTextProperties::LastPropertyId, and mergePropertiesIntoSelection().

◆ commitIMEPreEdit()

void SvgTextCursor::commitIMEPreEdit ( )
private

This applies any running IME interactions, used when the shape is deselected halfways through an IME interaction.

Definition at line 2127 of file SvgTextCursor.cpp.

2128{
2129 if (!d->preEditCommand) {
2130 return;
2131 }
2132
2133 qApp->inputMethod()->commit();
2134
2135 if (!d->preEditCommand) {
2136 return;
2137 }
2138
2139 d->preEditCommand->undo();
2140 d->preEditCommand = nullptr;
2141 d->preEditStart = -1;
2142 d->preEditLength = 0;
2144 updateCursor();
2145}
void updateCursor(bool firstUpdate=false)
update the cursor shape. First update will block ensuring the canvas is visible so setShape won't cau...

References d, updateCursor(), and updateIMEDecoration().

◆ copy()

void SvgTextCursor::copy ( ) const

copy copies plain text into the clipboard between anchor and pos.

Definition at line 738 of file SvgTextCursor.cpp.

739{
740 if (d->shape) {
741 int start = d->shape->indexForPos(qMin(d->anchor, d->pos));
742 int length = d->shape->indexForPos(qMax(d->anchor, d->pos)) - start;
743 QString copied = d->shape->plainText().mid(start, length);
744 std::unique_ptr<KoSvgTextShape> copy = d->shape->copyRange(start, length);
745 QClipboard *cb = QApplication::clipboard();
746
747 if (copy) {
748 KoSvgTextShapeMarkupConverter converter(copy.get());
749 QString svg;
750 QString styles;
751 QString html;
752 QMimeData *svgData = new QMimeData();
753 if (converter.convertToSvg(&svg, &styles)) {
754 QString svgDoc = QString("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"2.0\">%1\n%2</svg>").arg(styles).arg(svg);
755 svgData->setData(QLatin1String("image/svg+xml"), svgDoc.toUtf8());
756 }
757 svgData->setText(copied);
758 if (converter.convertToHtml(&html))
759 svgData->setHtml(html);
760 cb->setMimeData(svgData);
761 } else {
762 cb->setText(copied);
763 }
764
765 }
766}
qreal length(const QPointF &vec)
Definition Ellipse.cc:82

References KoSvgTextShapeMarkupConverter::convertToHtml(), KoSvgTextShapeMarkupConverter::convertToSvg(), d, and length().

◆ currentTextProperties()

QPair< KoSvgTextProperties, KoSvgTextProperties > SvgTextCursor::currentTextProperties ( ) const

currentTextProperties

Returns
a qpair, where the first is the properties without inheritance, and the second, with inheritance.

Definition at line 676 of file SvgTextCursor.cpp.

677{
678 if (d->shape) {
679 return QPair<KoSvgTextProperties, KoSvgTextProperties>(d->shape->propertiesForPos(d->pos), d->shape->propertiesForPos(d->pos, true));
680 }
681 return QPair<KoSvgTextProperties, KoSvgTextProperties>();
682}

References d.

◆ cursorTypeForTypeSetting()

QCursor SvgTextCursor::cursorTypeForTypeSetting ( ) const

Return appropriate typeSetting cursor;.

Definition at line 456 of file SvgTextCursor.cpp.

457{
458 if (d->hoveredTypeSettingHandle == StartPos ||
459 d->hoveredTypeSettingHandle == StartPos ||
460 d->typeSettingDecor.testBaselines(d->lastKnownModifiers)) {
461 return Qt::ArrowCursor;
462 } else if (d->shape) {
463 return (d->shape->writingMode() == KoSvgText::HorizontalTB)? Qt::SizeVerCursor: Qt::SizeHorCursor;
464 }
465 return Qt::ArrowCursor;
466}
@ HorizontalTB
Definition KoSvgText.h:38

References d, KoSvgText::HorizontalTB, and StartPos.

◆ deselectText()

void SvgTextCursor::deselectText ( )

Deselect all text. This effectively makes anchor the same as pos.

Definition at line 830 of file SvgTextCursor.cpp.

831{
832 setPos(d->pos, d->pos);
833}
void setPos(int pos, int anchor)
Set the pos and the anchor.

References d, and setPos().

◆ focusIn()

void SvgTextCursor::focusIn ( )

Turns on blinking cursor.

Definition at line 1664 of file SvgTextCursor.cpp.

1665{
1666 d->cursorFlash.start();
1667 d->cursorFlashLimit.start();
1668 d->cursorVisible = false;
1669 d->hasFocus = true;
1670 blinkCursor();
1671}
void blinkCursor()
Called by timer, toggles the text cursor visible or invisible.

References blinkCursor(), and d.

◆ focusOut()

void SvgTextCursor::focusOut ( )

Stops blinking cursor.

Definition at line 1673 of file SvgTextCursor.cpp.

1674{
1675 d->hasFocus = false;
1677}
void stopBlinkCursor()
Called by timer, stops the text blinking animation.

References d, and stopBlinkCursor().

◆ getAnchor()

int SvgTextCursor::getAnchor ( )

Get the current selection anchor. This is the same as position, unless there's a selection.

Definition at line 352 of file SvgTextCursor.cpp.

353{
354 return d->anchor;
355}

References d.

◆ getPos()

int SvgTextCursor::getPos ( )

Get the current position.

Definition at line 347 of file SvgTextCursor.cpp.

348{
349 return d->pos;
350}

References d.

◆ handleName()

QString SvgTextCursor::handleName ( TypeSettingModeHandle handle) const

handleName

Returns
translated name of a given handle.

Definition at line 468 of file SvgTextCursor.cpp.

469{
470 bool baseline = d->typeSettingDecor.testBaselines(d->lastKnownModifiers);
471 if (handle == Ascender) {
472 if (baseline) {
473 return i18nc("Type setting mode line name", "Text Top");
474 } else {
475 return i18nc("Type setting mode line name", "Font Size");
476 }
477 } else if (handle == Descender) {
478 if (baseline) {
479 return i18nc("Type setting mode line name", "Text Bottom");
480 } else {
481 return i18nc("Type setting mode line name", "Font Size");
482 }
483 } else if (handle == BaselineAlphabetic) {
484 return i18nc("Type setting mode line name", "Alphabetic");
485 } else if (handle == BaselineIdeographic) {
486 return i18nc("Type setting mode line name", "Ideographic");
487 } else if (handle == BaselineHanging) {
488 return i18nc("Type setting mode line name", "Hanging");
489 } else if (handle == BaselineMiddle) {
490 return i18nc("Type setting mode line name", "Middle");
491 } else if (handle == BaselineMathematical) {
492 return i18nc("Type setting mode line name", "Mathematical");
493 } else if (handle == BaselineCentral) {
494 return i18nc("Type setting mode line name", "Central");
495 } else if (handle == LineHeightTop || handle == LineHeightBottom) {
496 return i18nc("Type setting mode line name", "Line Height");
497 } else if (handle == BaselineShift) {
498 if (baseline) {
499 return i18nc("Type setting mode line name", "Current Baseline");
500 } else {
501 return i18nc("Type setting mode line name", "Baseline Shift");
502 }
503 } else {
504 return QString();
505 }
506}

References Ascender, BaselineAlphabetic, BaselineCentral, BaselineHanging, BaselineIdeographic, BaselineMathematical, BaselineMiddle, BaselineShift, d, Descender, LineHeightBottom, and LineHeightTop.

◆ hasSelection()

bool SvgTextCursor::hasSelection ( )
overridevirtual

return true if the tool currently has something selected that can be copied or deleted.

Reimplemented from KoToolSelection.

Definition at line 1380 of file SvgTextCursor.cpp.

1381{
1382 return d->pos != d->anchor;
1383}

References d.

◆ inputMethodEvent()

void SvgTextCursor::inputMethodEvent ( QInputMethodEvent * event)

Process an input method event. This is used by IME like virtual keyboards.

Definition at line 1074 of file SvgTextCursor.cpp.

1075{
1076 dbgTools << "Commit:"<< event->commitString() << "predit:"<< event->preeditString();
1077 dbgTools << "Replacement:"<< event->replacementStart() << event->replacementLength();
1078
1079 QRectF updateRect = d->shape? d->shape->boundingRect(): QRectF();
1080 SvgTextShapeManagerBlocker blocker(d->canvas->shapeManager());
1081
1082 bool isGettingInput = !event->commitString().isEmpty() || !event->preeditString().isEmpty()
1083 || event->replacementLength() > 0;
1084
1085 // Remove previous preedit string.
1086 if (d->preEditCommand) {
1087 d->preEditCommand->undo();
1088 d->preEditCommand = 0;
1089 d->preEditStart = -1;
1090 d->preEditLength = -1;
1091 updateRect |= d->shape? d->shape->boundingRect(): QRectF();
1092 }
1093
1094 if (!d->shape || !isGettingInput) {
1095 blocker.unlock();
1096 d->canvas->shapeManager()->update(updateRect);
1097 event->ignore();
1098 return;
1099 }
1100
1101 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(d);
1102
1103 // remove the selection if any.
1105
1106 // set the text insertion pos to replacement start and also remove replacement length, if any.
1107 int originalPos = d->pos;
1108 int index = d->shape->indexForPos(d->pos) + event->replacementStart();
1109 d->pos = d->shape->posForIndex(index);
1110 if (event->replacementLength() > 0) {
1112 index + event->replacementLength(),
1113 originalPos,
1114 d->anchor,
1115 event->replacementLength(),
1116 false);
1118 }
1119
1120 // add the commit string, if any.
1121 if (!event->commitString().isEmpty()) {
1122 insertText(event->commitString());
1123 }
1124
1125 // set the selection...
1126 Q_FOREACH(const QInputMethodEvent::Attribute attribute, event->attributes()) {
1127 if (attribute.type == QInputMethodEvent::Selection) {
1128 d->pos = d->shape->posForIndex(attribute.start);
1129 int index = d->shape->indexForPos(d->pos);
1130 d->anchor = d->shape->posForIndex(index + attribute.length);
1131 }
1132 }
1133
1134
1135 // insert a preedit string, if any.
1136 if (!event->preeditString().isEmpty()) {
1137 int index = d->shape->indexForPos(d->pos);
1138 d->preEditCommand = new SvgTextInsertCommand(d->shape, d->pos, d->anchor, event->preeditString());
1139 d->preEditCommand->redo();
1140 d->preEditLength = event->preeditString().size();
1141 d->preEditStart = d->shape->posForIndex(index, true);
1142 } else {
1143 d->preEditCommand = 0;
1144 }
1145
1146 // Apply the cursor offset for the preedit.
1148 Q_FOREACH(const QInputMethodEvent::Attribute attribute, event->attributes()) {
1149 dbgTools << "attribute: "<< attribute.type << "start: " << attribute.start
1150 << "length: " << attribute.length << "val: " << attribute.value;
1151 // Text Format is about setting the look of the preedit string, and there can be multiple per event
1152 // we primarily interpret the underline. When a background color is set, we increase the underline
1153 // thickness, as that's what is actually supposed to happen according to the comments in the
1154 // platform input contexts for both macOS and Windows.
1155
1156 if (attribute.type == QInputMethodEvent::TextFormat) {
1157 QVariant val = attribute.value;
1158 QTextCharFormat form = val.value<QTextFormat>().toCharFormat();
1159
1160 if (attribute.length == 0 || attribute.start < 0 || !attribute.value.isValid()) {
1161 continue;
1162 }
1163
1164 int positionA = -1;
1165 int positionB = -1;
1166 if (!styleMap.isEmpty()) {
1167 for (int i = 0; i < styleMap.size(); i++) {
1168 if (attribute.start >= styleMap.at(i).start
1169 && attribute.start < styleMap.at(i).start + styleMap.at(i).length) {
1170 positionA = i;
1171 }
1172 if (attribute.start + attribute.length > styleMap.at(i).start
1173 && attribute.start + attribute.length <= styleMap.at(i).start + styleMap.at(i).length) {
1174 positionB = i;
1175 }
1176 }
1177
1178 if (positionA > -1 && positionA == positionB) {
1179 IMEDecorationInfo decoration1 = styleMap.at(positionA);
1180 IMEDecorationInfo decoration2 = decoration1;
1181 IMEDecorationInfo decoration3 = decoration1;
1182 decoration3.start = (attribute.start+attribute.length);
1183 decoration3.length = (decoration1.start + decoration1.length) - decoration3.start;
1184 decoration1.length = attribute.start - decoration1.start;
1185 decoration2.start = attribute.start;
1186 decoration2.length = attribute.length;
1187 if (decoration1.length > 0) {
1188 styleMap[positionA] = decoration1;
1189 if (decoration2.length > 0) {
1190 positionA += 1;
1191 styleMap.insert(positionA, decoration2);
1192 }
1193 } else {
1194 styleMap[positionA] = decoration2;
1195 }
1196 if (decoration3.length > 0) {
1197 styleMap.insert(positionA + 1, decoration3);
1198 }
1199 } else if (positionA > -1 && positionB > -1
1200 && positionA != positionB) {
1201 IMEDecorationInfo decoration1 = styleMap.at(positionA);
1202 IMEDecorationInfo decoration2 = decoration1;
1203 IMEDecorationInfo decoration3 = styleMap.at(positionB);
1204 IMEDecorationInfo decoration4 = decoration3;
1205 decoration2.length = (decoration1.start + decoration1.length) - attribute.start;
1206 decoration1.length = attribute.start - decoration1.start;
1207 decoration2.start = attribute.start;
1208
1209 decoration4.start = (attribute.start+attribute.length);
1210 decoration3.length = (decoration3.start + decoration3.length) - decoration4.start;
1211 decoration3.length = decoration4.start - decoration3.start;
1212 if (decoration1.length > 0) {
1213 styleMap[positionA] = decoration1;
1214 if (decoration2.length > 0) {
1215 positionA += 1;
1216 styleMap.insert(positionA, decoration2);
1217 }
1218 } else {
1219 styleMap[positionA] = decoration2;
1220 }
1221
1222 if (decoration3.length > 0) {
1223 styleMap[positionB] = decoration3;
1224 if (decoration4.length > 0) {
1225 styleMap.insert(positionB + 1, decoration4);
1226 }
1227 } else {
1228 styleMap[positionB] = decoration4;
1229 }
1230 }
1231 }
1232
1233 if (positionA > -1 && !styleMap.isEmpty()) {
1234
1235 for(int i = positionA; i <= positionB; i++) {
1236 IMEDecorationInfo decoration = styleMap.at(i);
1237 decoration.setDecorationFromQTextCharFormat(form);
1238 styleMap[i] = decoration;
1239 }
1240
1241 } else {
1242 IMEDecorationInfo decoration;
1243 decoration.start = attribute.start;
1244 decoration.length = attribute.length;
1245 decoration.setDecorationFromQTextCharFormat(form);
1246 styleMap.append(decoration);
1247 }
1248
1249 // QInputMethodEvent::Language is about setting the locale on the given preedit string, which is not possible yet.
1250 // QInputMethodEvent::Ruby is supposedly ruby info for the preedit string, but none of the platform integrations
1251 // actually implement this at time of writing, and it may have been something from a previous live of Qt's.
1252 } else if (attribute.type == QInputMethodEvent::Cursor) {
1253 if (d->preEditStart < 0) {
1254 d->anchor = d->pos;
1255 } else {
1256 int index = d->shape->indexForPos(d->preEditStart);
1257 d->pos = d->shape->posForIndex(index + attribute.start);
1258 d->anchor = d->pos;
1259 }
1260
1261 // attribute value is the cursor color, and should be used to paint the cursor.
1262 // attribute length is about whether the cursor should be visible at all...
1263 }
1264 }
1265
1266 blocker.unlock();
1267 updateRect |= d->shape->boundingRect();
1268 // TODO: replace with KoShapeBulkActionLock
1269 d->shape->updateAbsolute(updateRect);
1270 d->styleMap = styleMap;
1273 updateCursor();
1274 event->accept();
1275}
#define dbgTools
Definition kis_debug.h:48
int start
The startPos from the attribute.
void setDecorationFromQTextCharFormat(QTextCharFormat format)
int length
The length from the attribute.
void insertText(QString text)
Insert text at getPos()
QVector< IMEDecorationInfo > styleMap
Decoration info (underlines) for the preEdit string to differentiate it from regular text.
void addCommandToUndoAdapter(KUndo2Command *cmd)
Adds a command to the canvas of the parent tool.
SvgTextRemoveCommand * removeSelectionImpl(bool allowCleanUp, KUndo2Command *parent=0)
removeSelection if there's a selection, creates a text-removal command.

References addCommandToUndoAdapter(), d, dbgTools, insertText(), IMEDecorationInfo::length, removeSelectionImpl(), IMEDecorationInfo::setDecorationFromQTextCharFormat(), IMEDecorationInfo::start, styleMap, updateCursor(), updateIMEDecoration(), and updateSelection().

◆ inputMethodQuery()

QVariant SvgTextCursor::inputMethodQuery ( Qt::InputMethodQuery query) const

Process an input method query and return the requested result.

Definition at line 946 of file SvgTextCursor.cpp.

947{
948 dbgTools << "receiving inputmethod query" << query;
949
950 // Because we set the input item transform to be shape->document->view->widget->window,
951 // the coordinates here should be in shape coordinates.
952 switch(query) {
953 case Qt::ImEnabled:
954 return d->shape? true: false;
955 break;
956 case Qt::ImCursorRectangle:
957 // The platform integration will always define the cursor as the 'left side' handle.
958 if (d->shape) {
959 QPointF caret1(d->cursorCaret.p1());
960 QPointF caret2(d->cursorCaret.p2());
961
962
963 QRectF rect = QRectF(caret1, caret2).normalized();
964 if (!rect.isValid()) {
965 if (rect.height() < 1) {
966 rect.adjust(0, -1, 0, 0);
967 }
968 if (rect.width() < 1) {
969 rect.adjust(0, 0, 1, 0);
970 }
971
972 }
973 return rect.toAlignedRect();
974 }
975 break;
976 case Qt::ImAnchorRectangle:
977 // The platform integration will always define the anchor as the 'right side' handle.
978 if (d->shape) {
979 QPointF caret1(d->anchorCaret.p1());
980 QPointF caret2(d->anchorCaret.p2());
981 QRectF rect = QRectF(caret1, caret2).normalized();
982 if (rect.isEmpty()) {
983 if (rect.height() < 1) {
984 rect.adjust(0, -1, 0, 0);
985 }
986 if (rect.width() < 1) {
987 rect = rect.adjusted(-1, 0, 0, 0).normalized();
988 }
989 }
990 return rect.toAlignedRect();
991 }
992 break;
993 //case Qt::ImFont: // not sure what this is used for, but we cannot sent out without access to properties.
994 case Qt::ImAbsolutePosition:
995 case Qt::ImCursorPosition:
996 if (d->shape) {
997 return d->shape->indexForPos(d->pos);
998 }
999 break;
1000 case Qt::ImSurroundingText:
1001 if (d->shape) {
1002 QString surroundingText = d->shape->plainText();
1003 int preEditIndex = d->preEditCommand? d->shape->indexForPos(d->preEditStart): 0;
1004 surroundingText.remove(preEditIndex, d->preEditLength);
1005 return surroundingText;
1006 }
1007 break;
1008 case Qt::ImCurrentSelection:
1009 if (d->shape) {
1010 QString surroundingText = d->shape->plainText();
1011 int preEditIndex = d->preEditCommand? d->shape->indexForPos(d->preEditStart): 0;
1012 surroundingText.remove(preEditIndex, d->preEditLength);
1013 int start = d->shape->indexForPos(qMin(d->anchor, d->pos));
1014 int length = d->shape->indexForPos(qMax(d->anchor, d->pos)) - start;
1015 return surroundingText.mid(start, length);
1016 }
1017 break;
1018 case Qt::ImTextBeforeCursor:
1019 if (d->shape) {
1020 int start = d->shape->indexForPos(d->pos);
1021 QString surroundingText = d->shape->plainText();
1022 int preEditIndex = d->preEditCommand? d->shape->indexForPos(d->preEditStart): 0;
1023 surroundingText.remove(preEditIndex, d->preEditLength);
1024 return surroundingText.left(start);
1025 }
1026 break;
1027 case Qt::ImTextAfterCursor:
1028 if (d->shape) {
1029 int start = d->shape->indexForPos(d->pos);
1030 QString surroundingText = d->shape->plainText();
1031 int preEditIndex = d->preEditCommand? d->shape->indexForPos(d->preEditStart): 0;
1032 surroundingText.remove(preEditIndex, d->preEditLength);
1033 return surroundingText.right(start);
1034 }
1035 break;
1036 case Qt::ImMaximumTextLength:
1037 return QVariant(); // infinite text length!
1038 break;
1039 case Qt::ImAnchorPosition:
1040 if (d->shape) {
1041 return d->shape->indexForPos(d->anchor);
1042 }
1043 break;
1044 case Qt::ImHints:
1045 // It would be great to use Qt::ImhNoTextHandles or Qt::ImhNoEditMenu,
1046 // but neither are implemented for anything but web platform integration
1047 return Qt::ImhMultiLine;
1048 break;
1049 // case Qt::ImPreferredLanguage: // requires access to properties.
1050#if defined(Q_OS_ANDROID) && KRITA_QT_HAS_ANDROID_INPUT_PLATFORM_DATA_SOFT_INPUT_ADJUST_NOTHING
1051 case Qt::ImPlatformData:
1052 // Platform-specific data. Qt normally only uses this on iOS, but we
1053 // have a patch that allows us to control the keyboard pan behavior.
1054 // Normally it pans the application window up if the text area would end
1055 // up underneath the keyboard, but that's silly for the on-canvas text
1056 // input because the location can be changed by panning the canvas. And
1057 // if you do that while the keyboard is up, you end up with the whole
1058 // window panned up for no reason until you dismiss and re-show it, so
1059 // better to just do nothing in the first place and let the user pan.
1060 return Qt::ANDROID_INPUT_PLATFORM_DATA_SOFT_INPUT_ADJUST_NOTHING;
1061#endif
1062 case Qt::ImEnterKeyType:
1063 if (d->shape) {
1064 return Qt::EnterKeyDefault; // because input method hint is always multiline, this will show a return key.
1065 }
1066 break;
1067 // case Qt::ImInputItemClipRectangle // whether the input item is clipped?
1068 default:
1069 return QVariant();
1070 }
1071 return QVariant();
1072}

References d, dbgTools, and length().

◆ insertRichText()

void SvgTextCursor::insertRichText ( KoSvgTextShape * insert,
bool inheritPropertiesIfPossible = false )

Insert rich text at getPos();.

Definition at line 624 of file SvgTextCursor.cpp.

625{
626 if (d->shape) {
627 //KUndo2Command *parentCmd = new KUndo2Command;
628 if (hasSelection()) {
629 SvgTextRemoveCommand *removeCmd = removeSelectionImpl(false);
630 addCommandToUndoAdapter(removeCmd);
631 }
632
633 SvgTextInsertRichCommand *cmd = new SvgTextInsertRichCommand(d->shape, insert, d->pos, d->anchor, inheritPropertiesIfPossible);
635
636 }
637}

References addCommandToUndoAdapter(), KoShape::anchor(), d, hasSelection(), and removeSelectionImpl().

◆ insertText()

void SvgTextCursor::insertText ( QString text)

Insert text at getPos()

Definition at line 608 of file SvgTextCursor.cpp.

609{
610
611 if (d->shape) {
612 //KUndo2Command *parentCmd = new KUndo2Command;
613 if (hasSelection()) {
614 SvgTextRemoveCommand *removeCmd = removeSelectionImpl(false);
615 addCommandToUndoAdapter(removeCmd);
616 }
617
618 SvgTextInsertCommand *insertCmd = new SvgTextInsertCommand(d->shape, d->pos, d->anchor, text);
619 addCommandToUndoAdapter(insertCmd);
620
621 }
622}

References addCommandToUndoAdapter(), d, hasSelection(), and removeSelectionImpl().

◆ isAddingCommand()

bool SvgTextCursor::isAddingCommand ( ) const

the cursor is currently adding a command

◆ keyPressEvent()

void SvgTextCursor::keyPressEvent ( QKeyEvent * event)

Handle the cursor-related key events.

Definition at line 1417 of file SvgTextCursor.cpp.

1418{
1420
1421 updateModifiers(event->modifiers());
1422
1423 if (d->preEditCommand) {
1424 //MacOS will keep sending keyboard events during IME handling.
1425 event->accept();
1426 return;
1427 }
1428
1429 bool select = event->modifiers().testFlag(Qt::ShiftModifier);
1430
1431 if (!((Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier) & event->modifiers())) {
1432
1433 switch (event->key()) {
1434 case Qt::Key_Right:
1436 event->accept();
1437 break;
1438 case Qt::Key_Left:
1440 event->accept();
1441 break;
1442 case Qt::Key_Up:
1444 event->accept();
1445 break;
1446 case Qt::Key_Down:
1448 event->accept();
1449 break;
1450 case Qt::Key_Delete:
1452 event->accept();
1453 break;
1454 case Qt::Key_Backspace:
1456 event->accept();
1457 break;
1458 case Qt::Key_Return:
1459 case Qt::Key_Enter:
1460 insertText("\n");
1461 event->accept();
1462 break;
1463 default:
1464 event->ignore();
1465 }
1466
1467 if (event->isAccepted()) {
1468 return;
1469 }
1470 }
1471 if (acceptableInput(event)) {
1472 insertText(event->text());
1473 event->accept();
1474 return;
1475 }
1476
1477 KoSvgTextProperties props = d->shape->textProperties();
1478
1481
1482 // Qt's keysequence stuff doesn't handle vertical, so to test all the standard keyboard shortcuts as if it did,
1483 // we reinterpret the direction keys according to direction and writing mode, and test against that.
1484
1485 int newKey = event->key();
1486
1487 if (direction == KoSvgText::DirectionRightToLeft) {
1488 switch (newKey) {
1489 case Qt::Key_Left:
1490 newKey = Qt::Key_Right;
1491 break;
1492 case Qt::Key_Right:
1493 newKey = Qt::Key_Left;
1494 break;
1495 default:
1496 break;
1497 }
1498 }
1499
1500 if (mode == KoSvgText::VerticalRL) {
1501 switch (newKey) {
1502 case Qt::Key_Left:
1503 newKey = Qt::Key_Down;
1504 break;
1505 case Qt::Key_Right:
1506 newKey = Qt::Key_Up;
1507 break;
1508 case Qt::Key_Up:
1509 newKey = Qt::Key_Left;
1510 break;
1511 case Qt::Key_Down:
1512 newKey = Qt::Key_Right;
1513 break;
1514 default:
1515 break;
1516 }
1517 } else if (mode == KoSvgText::VerticalRL) {
1518 switch (newKey) {
1519 case Qt::Key_Left:
1520 newKey = Qt::Key_Up;
1521 break;
1522 case Qt::Key_Right:
1523 newKey = Qt::Key_Down;
1524 break;
1525 case Qt::Key_Up:
1526 newKey = Qt::Key_Left;
1527 break;
1528 case Qt::Key_Down:
1529 newKey = Qt::Key_Right;
1530 break;
1531 default:
1532 break;
1533 }
1534 }
1535
1536 QKeySequence testSequence(event->modifiers() | newKey);
1537
1538
1539 // Note for future, when we have format changing actions:
1540 // We'll need to test format change actions before the standard
1541 // keys, as one of the standard keys for deleting a line is ctrl+u
1542 // which would probably be expected to do underline before deleting.
1543
1544 Q_FOREACH(QAction *action, d->actions) {
1545 if (action->shortcut() == testSequence) {
1546 event->accept();
1547 action->trigger();
1548 return;
1549 }
1550 }
1551
1552 // This first set is already tested above, however, if they still
1553 // match, then it's one of the extra sequences for MacOs, which
1554 // seem to be purely logical, instead of the visual set we tested
1555 // above.
1556 if (testSequence == QKeySequence::MoveToNextChar) {
1558 event->accept();
1559 } else if (testSequence == QKeySequence::SelectNextChar) {
1561 event->accept();
1562 } else if (testSequence == QKeySequence::MoveToPreviousChar) {
1564 event->accept();
1565 } else if (testSequence == QKeySequence::SelectPreviousChar) {
1567 event->accept();
1568 } else if (testSequence == QKeySequence::MoveToNextLine) {
1570 event->accept();
1571 } else if (testSequence == QKeySequence::SelectNextLine) {
1573 event->accept();
1574 } else if (testSequence == QKeySequence::MoveToPreviousLine) {
1576 event->accept();
1577 } else if (testSequence == QKeySequence::SelectPreviousLine) {
1579 event->accept();
1580
1581 } else if (testSequence == QKeySequence::MoveToNextWord) {
1583 event->accept();
1584 } else if (testSequence == QKeySequence::SelectNextWord) {
1586 event->accept();
1587 } else if (testSequence == QKeySequence::MoveToPreviousWord) {
1589 event->accept();
1590 } else if (testSequence == QKeySequence::SelectPreviousWord) {
1592 event->accept();
1593
1594 } else if (testSequence == QKeySequence::MoveToStartOfLine) {
1596 event->accept();
1597 } else if (testSequence == QKeySequence::SelectStartOfLine) {
1599 event->accept();
1600 } else if (testSequence == QKeySequence::MoveToEndOfLine) {
1602 event->accept();
1603 } else if (testSequence == QKeySequence::SelectEndOfLine) {
1605 event->accept();
1606
1607 } else if (testSequence == QKeySequence::MoveToStartOfBlock
1608 || testSequence == QKeySequence::MoveToStartOfDocument) {
1610 event->accept();
1611 } else if (testSequence == QKeySequence::SelectStartOfBlock
1612 || testSequence == QKeySequence::SelectStartOfDocument) {
1614 event->accept();
1615
1616 } else if (testSequence == QKeySequence::MoveToEndOfBlock
1617 || testSequence == QKeySequence::MoveToEndOfDocument) {
1619 event->accept();
1620 } else if (testSequence == QKeySequence::SelectEndOfBlock
1621 || testSequence == QKeySequence::SelectEndOfDocument) {
1623 event->accept();
1624
1625 }else if (testSequence == QKeySequence::DeleteStartOfWord) {
1627 event->accept();
1628 } else if (testSequence == QKeySequence::DeleteEndOfWord) {
1630 event->accept();
1631 } else if (testSequence == QKeySequence::DeleteEndOfLine) {
1633 event->accept();
1634 } else if (testSequence == QKeySequence::DeleteCompleteLine) {
1636 event->accept();
1637 } else if (testSequence == QKeySequence::Backspace) {
1639 event->accept();
1640 } else if (testSequence == QKeySequence::Delete) {
1642 event->accept();
1643
1644 } else if (testSequence == QKeySequence::InsertLineSeparator
1645 || testSequence == QKeySequence::InsertParagraphSeparator) {
1646 insertText("\n");
1647 event->accept();
1648 } else {
1649 event->ignore();
1650 }
1651}
@ WritingModeId
KoSvgText::WritingMode.
@ DirectionId
KoSvgText::Direction.
QVariant propertyOrDefault(PropertyId id) const
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
Direction
Base direction used by Bidi algorithm.
Definition KoSvgText.h:48
@ DirectionRightToLeft
Definition KoSvgText.h:50
void moveCursor(MoveMode mode, bool moveAnchor=true)
Move the cursor, and, if you don't want a selection, move the anchor.
bool acceptableInput(const QKeyEvent *event) const
More or less copied from bool QInputControl::isAcceptableInput(const QKeyEvent *event) const.
void removeText(MoveMode first, MoveMode second)
removeText remove text relative to the current position. This will move the cursor according to the m...
void removeLastCodePoint()
removeLastCodePoint Special function to remove the last code point. Triggered by backspace....
void updateModifiers(const Qt::KeyboardModifiers modifiers)

References acceptableInput(), d, KoSvgTextProperties::DirectionId, KoSvgText::DirectionRightToLeft, insertText(), KIS_SAFE_ASSERT_RECOVER_RETURN, moveCursor(), MoveDown, MoveLeft, MoveLineEnd, MoveLineStart, MoveNextChar, MoveNextLine, MoveNone, MovePreviousChar, MovePreviousLine, MoveRight, MoveUp, MoveWordEnd, MoveWordStart, ParagraphEnd, ParagraphStart, KoSvgTextProperties::propertyOrDefault(), removeLastCodePoint(), removeText(), updateModifiers(), KoSvgText::VerticalRL, and KoSvgTextProperties::WritingModeId.

◆ mergePropertiesIntoSelection()

void SvgTextCursor::mergePropertiesIntoSelection ( const KoSvgTextProperties props,
const QSet< KoSvgTextProperties::PropertyId > removeProperties = QSet<KoSvgTextProperties::PropertyId>(),
bool paragraphOnly = false,
bool selectWord = false )

mergePropertiesIntoSelection Within Krita's SVG/CSS text system, it is possible to apply incomplete properties to a whole range. In that case, only the existing properties are applied. Properties can also be removed this way.

Parameters
props– properties to apply.
removeProperties– properties to be removed.
paragraphOnly– whether to apply to the paragraph.
selectWord– whether to select the word if there's no selection.

Definition at line 700 of file SvgTextCursor.cpp.

701{
702 if (d->shape) {
703 int start = -1;
704 int end = -1;
705 if (!paragraphOnly) {
706 start = d->pos;
707 end = d->anchor;
708 }
709 if (selectWord && d->pos == d->anchor) {
710 const int finalPos = d->shape->posForIndex(d->shape->plainText().size());
711 start = qBound(0, moveModeResult(MoveWordStart, d->pos, d->visualNavigation), finalPos);
712 end = qBound(0, moveModeResult(MoveWordEnd, d->pos, d->visualNavigation), finalPos);
713 }
714 KUndo2Command *cmd = new SvgTextMergePropertiesRangeCommand(d->shape, props, start, end, removeProperties);
716 }
717}
The SvgTextMergePropertiesRangeCommand class This sets properties on a specific range in a single tex...
int moveModeResult(const MoveMode mode, int &pos, bool visual=false) const
Processes a move action, returns the input.

References addCommandToUndoAdapter(), d, moveModeResult(), MoveWordEnd, and MoveWordStart.

◆ moveCursor()

void SvgTextCursor::moveCursor ( MoveMode mode,
bool moveAnchor = true )

Move the cursor, and, if you don't want a selection, move the anchor.

Definition at line 593 of file SvgTextCursor.cpp.

594{
595 if (d->shape) {
596
597 const int finalPos = d->shape->posForIndex(d->shape->plainText().size());
598 d->pos = qBound(0, moveModeResult(mode, d->pos, d->visualNavigation), finalPos);
599
600 if (moveAnchor) {
601 d->anchor = d->pos;
602 }
604 updateCursor();
605 }
606}

References d, moveModeResult(), updateCursor(), and updateSelection().

◆ moveModeResult()

int SvgTextCursor::moveModeResult ( const MoveMode mode,
int & pos,
bool visual = false ) const
private

Processes a move action, returns the input.

Definition at line 2028 of file SvgTextCursor.cpp.

2029{
2030 int newPos = pos;
2031 switch (mode) {
2032 case MoveNone:
2033 break;
2034 case MoveLeft:
2035 newPos = d->shape->posLeft(pos, visual);
2036 break;
2037 case MoveRight:
2038 newPos = d->shape->posRight(pos, visual);
2039 break;
2040 case MoveUp:
2041 newPos = d->shape->posUp(pos, visual);
2042 break;
2043 case MoveDown:
2044 newPos = d->shape->posDown(pos, visual);
2045 break;
2046 case MovePreviousChar:
2047 newPos = d->shape->previousIndex(pos);
2048 break;
2049 case MoveNextChar:
2050 newPos = d->shape->nextIndex(pos);
2051 break;
2052 case MovePreviousLine:
2053 newPos = d->shape->previousLine(pos);
2054 break;
2055 case MoveNextLine:
2056 newPos = d->shape->nextLine(pos);
2057 break;
2058 case MoveWordLeft:
2059 newPos = d->shape->wordLeft(pos, visual);
2060 if (newPos == pos) {
2061 newPos = d->shape->posLeft(pos, visual);
2062 newPos = d->shape->wordLeft(newPos, visual);
2063 }
2064 break;
2065 case MoveWordRight:
2066 newPos = d->shape->wordRight(pos, visual);
2067 if (newPos == pos) {
2068 newPos = d->shape->posRight(pos, visual);
2069 newPos = d->shape->wordRight(newPos, visual);
2070 }
2071 break;
2072 case MoveWordStart:
2073 newPos = d->shape->wordStart(pos);
2074 if (newPos == pos) {
2075 newPos = d->shape->previousIndex(pos);
2076 newPos = d->shape->wordStart(newPos);
2077 }
2078 break;
2079 case MoveWordEnd:
2080 newPos = d->shape->wordEnd(pos);
2081 if (newPos == pos) {
2082 newPos = d->shape->nextIndex(pos);
2083 newPos = d->shape->wordEnd(newPos);
2084 }
2085 break;
2086 case MoveLineStart:
2087 newPos = d->shape->lineStart(pos);
2088 break;
2089 case MoveLineEnd:
2090 newPos = d->shape->lineEnd(pos);
2091 break;
2092 case ParagraphStart:
2093 newPos = 0;
2094 break;
2095 case ParagraphEnd:
2096 newPos = d->shape->posForIndex(d->shape->plainText().size());
2097 break;
2098 }
2099 return newPos;
2100}

References d, MoveDown, MoveLeft, MoveLineEnd, MoveLineStart, MoveNextChar, MoveNextLine, MoveNone, MovePreviousChar, MovePreviousLine, MoveRight, MoveUp, MoveWordEnd, MoveWordLeft, MoveWordRight, MoveWordStart, ParagraphEnd, ParagraphStart, and pos.

◆ notifyCursorPosChanged()

void SvgTextCursor::notifyCursorPosChanged ( int pos,
int anchor )
overridevirtual

TextCursorChangeListener reimplementation, this allows undo commands to update the cursor without having the cursor owned by the command.

Implements KoSvgTextShape::TextCursorChangeListener.

Definition at line 1398 of file SvgTextCursor.cpp.

1399{
1400 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(d);
1401 d->pos = pos;
1402 d->anchor = anchor;
1403 updateCursor();
1406}
void updateTypeSettingDecoration()

References anchor, d, pos, updateCursor(), updateSelection(), and updateTypeSettingDecoration().

◆ notifyMarkupChanged()

void SvgTextCursor::notifyMarkupChanged ( )
overridevirtual

Implements KoSvgTextShape::TextCursorChangeListener.

Definition at line 1408 of file SvgTextCursor.cpp.

1409{
1410 d->interface->emitSelectionChange();
1411 d->interface->emitCharacterSelectionChange();
1412 updateCursor();
1415}

References d, updateCursor(), updateSelection(), and updateTypeSettingDecoration().

◆ notifyShapeChanged()

void SvgTextCursor::notifyShapeChanged ( KoShape::ChangeType type,
KoShape * shape )
overridevirtual

ShapeChangeListener reimplementation. This will update the cursor position when the shape was updated.

Implements KoShape::ShapeChangeListener.

Definition at line 1385 of file SvgTextCursor.cpp.

1386{
1387 Q_UNUSED(type);
1388 Q_UNUSED(shape);
1389 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(d);
1390 d->pos = d->shape->posForIndex(d->posIndex);
1391 d->anchor = d->shape->posForIndex(d->anchorIndex);
1392 updateCursor(true);
1396}
KoSvgTextShape * shape

References d, shape, updateCursor(), updateInputMethodItemTransform(), updateSelection(), and updateTypeSettingDecoration().

◆ paintDecorations()

void SvgTextCursor::paintDecorations ( QPainter & gc,
QColor selectionColor,
int decorationThickness = 1,
qreal handleRadius = 5.0,
KisHandlePalette handlePalette = KisHandlePalette() )

Paint all decorations and blinkingcursors.

Definition at line 844 of file SvgTextCursor.cpp.

845{
846 if (d->shape) {
847 gc.save();
848 gc.setTransform(d->shape->absoluteTransformation(), true);
849
850 if (d->pos != d->anchor && !d->typeSettingMode) {
851 gc.save();
852 gc.setOpacity(0.5);
853 QBrush brush(selectionColor);
854 gc.fillPath(d->selection, brush);
855 gc.restore();
856 }
857
858 if ( (d->drawCursorInAdditionToSelection || d->pos == d->anchor)
859 && d->cursorVisible) {
860 QPen pen;
861 pen.setCosmetic(true);
862 QColor c = d->cursorColor.isValid()? d->cursorColor: Qt::black;
863 pen.setColor(bgColorForCaret(c, handlePalette));
864 pen.setWidth((d->cursorWidth + 2) * decorationThickness);
865 gc.setPen(pen);
866 gc.drawPath(d->cursorShape);
867 pen.setColor(d->canvas->displayRendererInterface()->convertColorToDisplayColorSpace(KoColor(c, KoColorSpaceRegistry::instance()->rgb8())) );
868 pen.setWidth(d->cursorWidth * decorationThickness);
869 gc.setPen(pen);
870 gc.drawPath(d->cursorShape);
871
872 }
873
874 if (d->preEditCommand) {
875 gc.save();
876 QBrush brush(selectionColor);
877 gc.setOpacity(0.5);
878 gc.fillPath(d->IMEDecoration, brush);
879 gc.restore();
880 }
881 if (d->typeSettingMode && d->drawTypeSettingHandle) {
882 d->handleRadius = handleRadius;
883 QTransform painterTf = gc.transform();
884 KisHandlePainterHelper helper(&gc, handleRadius, decorationThickness);
886 const KisHandleStyle regular = KisHandleStyle::secondarySelection(handlePalette);
887
888 QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath> paths
889 = d->typeSettingDecor.testBaselines(d->lastKnownModifiers)? d->typeSettingDecor.baselines: d->typeSettingDecor.paths;
890 QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath> parentPaths
891 = d->typeSettingDecor.testBaselines(d->lastKnownModifiers)? d->typeSettingDecor.parentBaselines: d->typeSettingDecor.parentPaths;
892 Q_FOREACH(SvgTextCursor::TypeSettingModeHandle handle, paths.keys()) {
893 const QPainterPath p = paths.value(handle);
894 const QPainterPath parent = parentPaths.value(handle);
895 if (d->hoveredTypeSettingHandle == handle) {
896 helper.setHandleStyle(highlight);
897 helper.drawPath(parent);
898 helper.drawPath(p);
899 } else {
900 gc.save();
901 QPen pen(selectionColor, decorationThickness, handle == BaselineShift? Qt::SolidLine: Qt::DashLine);
902 pen.setCosmetic(true);
903 gc.setPen(pen);
904 gc.setOpacity(0.5);
905 gc.drawPath(painterTf.map(parent));
906 gc.drawPath(painterTf.map(p));
907 gc.restore();
908 }
909 gc.save();
910 QPen pen(selectionColor, decorationThickness, Qt::SolidLine);
911 pen.setCosmetic(true);
912 gc.setPen(pen);
913 gc.setOpacity(0.5);
914 gc.drawPath(painterTf.map(d->typeSettingDecor.edges));
915 gc.restore();
916 }
917
918 if (d->typeSettingDecor.handlesEnabled) {
919 helper.setHandleStyle(d->hoveredTypeSettingHandle == EndPos? highlight: regular);
920 helper.drawHandleCircle(d->typeSettingDecor.handles.second);
921 helper.setHandleStyle(d->hoveredTypeSettingHandle == StartPos? highlight: regular);
922 helper.drawHandleRect(d->typeSettingDecor.handles.first);
923 }
924 QString name = handleName(d->hoveredTypeSettingHandle);
925 if (!name.isEmpty()) {
926 QPainterPath textP;
927 // When we're drawing on opengl, there's no anti-aliasing, so we should have full hinting for readabiltiy.
928 QFont font = gc.font();
929 font.setHintingPreference(QFont::PreferFullHinting);
930 textP.addText(painterTf.map(d->typeSettingDecor.closestBaselinePoint).toPoint(), font, name);
931 gc.save();
932 QPen pen(bgColorForCaret(selectionColor, handlePalette, 255));
933 pen.setCosmetic(true);
934 pen.setWidth(decorationThickness);
935 gc.setPen(pen);
936 gc.drawPath(textP);
937 gc.fillPath(textP, QBrush(selectionColor));
938 gc.restore();
939 }
940
941 }
942 gc.restore();
943 }
944}
const Params2D p
static QColor bgColorForCaret(QColor c, KisHandlePalette handlePalette, int opacity=64)
The KisHandlePainterHelper class is a special helper for painting handles around objects....
static KisHandleStyle & partiallyHighlightedPrimaryHandles(KisHandlePalette palette=KisHandlePalette())
static KisHandleStyle & secondarySelection(KisHandlePalette palette=KisHandlePalette())
const char * name(StandardAction id)
ChildIterator< value_type, is_const > parent(const ChildIterator< value_type, is_const > &it)
Definition KisForest.h:327
static KoColorSpaceRegistry * instance()
QString handleName(TypeSettingModeHandle handle) const
handleName
TypeSettingModeHandle
Handles used by type setting mode.

References BaselineShift, bgColorForCaret(), d, KisHandlePainterHelper::drawHandleCircle(), KisHandlePainterHelper::drawHandleRect(), KisHandlePainterHelper::drawPath(), EndPos, handleName(), handleRadius, KoColorSpaceRegistry::instance(), p, KisHandleStyle::partiallyHighlightedPrimaryHandles(), KisHandleStyle::secondarySelection(), KisHandlePainterHelper::setHandleStyle(), and StartPos.

◆ paste()

bool SvgTextCursor::paste ( )

paste pastes plain text in the clipboard at pos. Uses pasteRichTextByDefault to determine whether to try and paste rich text.

Returns
true when successfull.

Definition at line 768 of file SvgTextCursor.cpp.

769{
770 bool success = d->pasteRichText? pasteRichText(): pastePlainText();
771 return success;
772}
bool pastePlainText()
pastePlainText Explicitely paste plaintext at pos.

References d, pastePlainText(), and pasteRichText.

◆ pastePlainText

bool SvgTextCursor::pastePlainText ( )
privateslot

pastePlainText Explicitely paste plaintext at pos.

Returns
true when successfull.

Definition at line 810 of file SvgTextCursor.cpp.

811{
812 bool success = false;
813 QClipboard *cb = QApplication::clipboard();
814 const QMimeData *mimeData = cb->mimeData();
815 if (mimeData->hasText()) {
816 insertText(mimeData->text());
817 success = true;
818 }
819 return success;
820}

References insertText().

◆ pasteRichText

bool SvgTextCursor::pasteRichText ( )
privateslot

pasteRichText

Returns
try to paste rich text at pos.

◆ posForTypeSettingHandleAndRect()

int SvgTextCursor::posForTypeSettingHandleAndRect ( const TypeSettingModeHandle handle,
const QRectF regionOfInterest )

posForHandleAndRect Returns the closest cursor position for a given region and typesetting handle. Used by the type setting mode to find the relevant metrics to scale.

Returns
cursor pos closest.

Definition at line 555 of file SvgTextCursor.cpp.

556{
557 if (!d->shape) return 0;
558
560 d->shape->getPositionsAndRotationsForRange(d->pos, d->anchor);
561 if (infos.size() < 1) return 0;
562
563 const QRectF roi = d->shape->documentToShape(regionOfInterest);
564
565 for (auto it = infos.begin(); it != infos.end(); it++) {
566 const int currentPos = (d->pos == d->anchor)? -1 :d->shape->posForIndex(it->logicalIndex);
567 const KoSvgTextProperties props = d->shape->propertiesForPos(currentPos, true);
569
570 KoSvgText::FontMetrics metrics = (d->pos == d->anchor)? props.metrics(true, true): it->metrics;
571 const bool isHorizontal = d->shape->writingMode() == KoSvgText::HorizontalTB;
572
573 const qreal scaleMetrics = props.fontSize().value/qreal(metrics.fontSize);
574 const int lineGap = lineHeight.isNormal? metrics.lineGap: (lineHeight.length.value/scaleMetrics)-(metrics.ascender-metrics.descender);
575
576 QTransform t = QTransform::fromTranslate(it->finalPos.x(), it->finalPos.y());
577 t.rotate(it->rotateDeg);
578
579 const QMap<SvgTextCursor::TypeSettingModeHandle, int> types
580 = typeSettingBaselinesFromMetrics(metrics, lineGap, isHorizontal);
581
582 const int metric = types.value(handle);
583 QPointF offset = isHorizontal? QPointF(0, -(metric*scaleMetrics)): QPointF(metric*scaleMetrics, 0);
584 QLineF line = t.map(QLineF(offset, offset+it->advance));
585 if (KisAlgebra2D::intersectLineRect(line, roi.toAlignedRect(), false)) return d->shape->posForIndex(it->logicalIndex);
586 }
587
588 return 0;
589}
QMap< SvgTextCursor::TypeSettingModeHandle, int > typeSettingBaselinesFromMetrics(const KoSvgText::FontMetrics metrics, const qreal lineGap, const bool isHorizontal)
@ LineHeightId
KoSvgText::AutoValue.
KoSvgText::FontMetrics metrics(const bool withResolvedLineHeight=true, const bool offsetByBaseline=false) const
metrics Return the metrics of the first available font.
KoSvgText::CssLengthPercentage fontSize() const
bool intersectLineRect(QLineF &line, const QRect rect, bool extend)
The FontMetrics class A class to keep track of a variety of font metrics. Note that values are in Fre...
Definition KoSvgText.h:327
CssLengthPercentage length
Definition KoSvgText.h:693
bool isNormal
It's a number indicating the lineHeight;.
Definition KoSvgText.h:696

References d, KoSvgTextProperties::fontSize(), KoSvgText::HorizontalTB, KisAlgebra2D::intersectLineRect(), KoSvgText::LineHeightInfo::isNormal, KoSvgText::LineHeightInfo::length, KoSvgTextProperties::LineHeightId, KoSvgTextProperties::metrics(), KoSvgTextProperties::propertyOrDefault(), typeSettingBaselinesFromMetrics(), and KoSvgText::CssLengthPercentage::value.

◆ propertiesForRange()

QList< KoSvgTextProperties > SvgTextCursor::propertiesForRange ( ) const

propertiesForRange

Returns
properties for the current range defined by the cursor pos and anchor.

Definition at line 684 of file SvgTextCursor.cpp.

685{
686 if (!d->shape) return QList<KoSvgTextProperties>();
687 int start = -1;
688 int end = -1;
689 start = qMin(d->pos, d->anchor);
690 end = qMax(d->pos, d->anchor);
691 return d->shape->propertiesForRange(start, end);
692}

References d.

◆ propertiesForShape()

QList< KoSvgTextProperties > SvgTextCursor::propertiesForShape ( ) const

propertiesForShape

Returns
properties for the current shape.

Definition at line 694 of file SvgTextCursor.cpp.

695{
696 if (!d->shape) return QList<KoSvgTextProperties>();
697 return {d->shape->propertiesForRange(-1, -1)};
698}

References d.

◆ propertyAction

void SvgTextCursor::propertyAction ( )
privateslot

Called by the actions to execute a property change based on their data.

Definition at line 1356 of file SvgTextCursor.cpp.

1357{
1358 QAction *action = dynamic_cast<QAction*>(QObject::sender());
1359 if (!action || !d->shape) return;
1360
1361 const QList<KoSvgTextProperties> p = d->shape->propertiesForRange(qMin(d->pos, d->anchor), qMax(d->pos, d->anchor));
1363 if (properties.isEmpty()) return;
1364 mergePropertiesIntoSelection(properties);
1365}
static KoSvgTextProperties getModifiedProperties(const QAction *action, QList< KoSvgTextProperties > currentProperties)

References d, SvgTextShortCuts::getModifiedProperties(), KoSvgTextProperties::isEmpty(), mergePropertiesIntoSelection(), and p.

◆ registerPropertyAction()

bool SvgTextCursor::registerPropertyAction ( QAction * action,
const QString & name )

Register an action.

Definition at line 1679 of file SvgTextCursor.cpp.

1680{
1681 if (SvgTextShortCuts::configureAction(action, name)) {
1682 d->actions.append(action);
1683 connect(action, SIGNAL(triggered(bool)), this, SLOT(propertyAction()));
1684 return true;
1685 } else if (name == "svg_insert_special_character") {
1686 d->actions.append(action);
1687 connect(action, SIGNAL(triggered(bool)), this, SIGNAL(sigOpenGlyphPalette()));
1688 return true;
1689 } else if (name == "svg_paste_rich_text") {
1690 d->actions.append(action);
1691 connect(action, SIGNAL(triggered(bool)), this, SLOT(pasteRichText()));
1692 return true;
1693 } else if (name == "svg_paste_plain_text") {
1694 d->actions.append(action);
1695 connect(action, SIGNAL(triggered(bool)), this, SLOT(pastePlainText()));
1696 return true;
1697 } else if (name == "svg_remove_transforms_from_range") {
1698 d->actions.append(action);
1699 connect(action, SIGNAL(triggered(bool)), this, SLOT(removeTransformsFromRange()));
1700 return true;
1701 } else if (name == "svg_clear_formatting") {
1702 d->actions.append(action);
1703 connect(action, SIGNAL(triggered(bool)), this, SLOT(clearFormattingAction()));
1704 return true;
1705 } else if (action) {
1706 d->actions.append(action);
1707 return true;
1708 }
1709 return false;
1710}
static bool configureAction(QAction *action, const QString &name)
void removeTransformsFromRange()
removeTransformsFromRange Called by actions to remove svg character transforms from range.
void clearFormattingAction()
Called by the clear formatting action.
void sigOpenGlyphPalette()
Called by actions, tells the parent tool to open the glyph palette.
void propertyAction()
Called by the actions to execute a property change based on their data.

References clearFormattingAction(), SvgTextShortCuts::configureAction(), d, pastePlainText(), pasteRichText, propertyAction(), removeTransformsFromRange(), and sigOpenGlyphPalette().

◆ removeLastCodePoint()

void SvgTextCursor::removeLastCodePoint ( )

removeLastCodePoint Special function to remove the last code point. Triggered by backspace. This is distinct from remove text, as some clusters have multiple code points, but it is generally expected backspace deletes the codepoints while delete with selection deletes the whole cluster.

Definition at line 661 of file SvgTextCursor.cpp.

662{
663 if (d->shape) {
664 SvgTextRemoveCommand *removeCmd;
665 if (hasSelection()) {
666 removeCmd = removeSelectionImpl(true);
667 addCommandToUndoAdapter(removeCmd);
668 } else {
669 int lastIndex = d->shape->indexForPos(d->pos);
670 removeCmd = new SvgTextRemoveCommand(d->shape, lastIndex, d->pos, d->anchor, 1, true);
671 addCommandToUndoAdapter(removeCmd);
672 }
673 }
674}

References addCommandToUndoAdapter(), d, hasSelection(), and removeSelectionImpl().

◆ removeSelection()

void SvgTextCursor::removeSelection ( )

removeSelection if there's a selection, creates a text-removal command.

Parameters
parent
Returns
the text-removal command, if possible, if there's no selection or shape, it'll return 0;

Definition at line 719 of file SvgTextCursor.cpp.

720{
721 KUndo2Command *removeCmd = removeSelectionImpl(true);
722 addCommandToUndoAdapter(removeCmd);
723}

References addCommandToUndoAdapter(), and removeSelectionImpl().

◆ removeSelectionImpl()

SvgTextRemoveCommand * SvgTextCursor::removeSelectionImpl ( bool allowCleanUp,
KUndo2Command * parent = 0 )
private

removeSelection if there's a selection, creates a text-removal command.

Parameters
parent
Returns
the text-removal command, if possible, if there's no selection or shape, it'll return 0;

Definition at line 725 of file SvgTextCursor.cpp.

726{
727 SvgTextRemoveCommand *removeCmd = nullptr;
728 if (d->shape) {
729 if (d->anchor != d->pos) {
730 int end = d->shape->indexForPos(qMax(d->anchor, d->pos));
731 int length = d->shape->indexForPos(qMax(d->anchor, d->pos)) - d->shape->indexForPos(qMin(d->anchor, d->pos));
732 removeCmd = new SvgTextRemoveCommand(d->shape, end, d->pos, d->anchor, length, allowCleanUp, parent);
733 }
734 }
735 return removeCmd;
736}

References d, and length().

◆ removeText()

void SvgTextCursor::removeText ( SvgTextCursor::MoveMode first,
SvgTextCursor::MoveMode second )

removeText remove text relative to the current position. This will move the cursor according to the move modes and then remove the text between the two positions.

Parameters
firsthow the cursor should move to get to the start position.
secondhow the cursor should move to get to the end position.

Definition at line 639 of file SvgTextCursor.cpp.

640{
641 if (d->shape) {
642 SvgTextRemoveCommand *removeCmd;
643 if (hasSelection()) {
644 removeCmd = removeSelectionImpl(true);
645 addCommandToUndoAdapter(removeCmd);
646 } else {
647 int posA = moveModeResult(first, d->pos, d->visualNavigation);
648 int posB = moveModeResult(second, d->pos, d->visualNavigation);
649
650 int posStart = qMin(posA, posB);
651 int posEnd = qMax(posA, posB);
652 int indexEnd = d->shape->indexForPos(posEnd);
653 int length = indexEnd - d->shape->indexForPos(posStart);
654
655 removeCmd = new SvgTextRemoveCommand(d->shape, indexEnd, d->pos, d->anchor, length, true);
656 addCommandToUndoAdapter(removeCmd);
657 }
658 }
659}

References addCommandToUndoAdapter(), d, hasSelection(), length(), moveModeResult(), and removeSelectionImpl().

◆ removeTransformsFromRange

void SvgTextCursor::removeTransformsFromRange ( )
privateslot

removeTransformsFromRange Called by actions to remove svg character transforms from range.

Definition at line 822 of file SvgTextCursor.cpp.

823{
824 if (d->shape) {
825 KUndo2Command *cmd = new SvgTextRemoveTransformsFromRange(d->shape, d->pos, d->anchor);
827 }
828}
The SvgTextRemoveTransformsFromRange class Removes the SVG 1.1 character transforms from the range.

References addCommandToUndoAdapter(), and d.

◆ selectionChanged

void SvgTextCursor::selectionChanged ( )
signal

Sents an update selection was changed.

◆ setCaretSetting()

void SvgTextCursor::setCaretSetting ( int cursorWidth = 1,
int cursorFlash = 1000,
int cursorFlashLimit = 5000,
bool drawCursorInAdditionToSelection = false )

setCaretSetting Set the caret settings for the cursor. Qt has some standard functionality associated, which we pass via this.

Parameters
cursorWidth- Cursor width from the style.
cursorFlash- the total time it takes for a cursor to hide reapear.
cursorFlashLimit- maximum amount of time a cursor is allowed to flash.

Definition at line 321 of file SvgTextCursor.cpp.

322{
323 d->cursorFlash.setInterval(cursorFlash/2);
324 d->cursorFlashLimit.setInterval(cursorFlashLimit);
325 d->cursorWidth = cursorWidth;
326 d->drawCursorInAdditionToSelection = drawCursorInAdditionToSelection;
327 connect(&d->cursorFlash, SIGNAL(timeout()), this, SLOT(blinkCursor()));
328 connect(&d->cursorFlashLimit, SIGNAL(timeout()), this, SLOT(stopBlinkCursor()));
329}
bool drawCursorInAdditionToSelection

References blinkCursor(), cursorFlash, cursorFlashLimit, cursorWidth, d, drawCursorInAdditionToSelection, and stopBlinkCursor().

◆ setDominantBaselineFromHandle()

bool SvgTextCursor::setDominantBaselineFromHandle ( const TypeSettingModeHandle handle)

setDominantBaselineFromHandle Set the dominant baseline from a given handle.

Returns
true if dominant baseline was set, false if the handle doesn't correspond to a baseline.

Definition at line 508 of file SvgTextCursor.cpp.

509{
510 if (handle == NoHandle) return false;
511 if (!d->typeSettingDecor.testBaselines(d->lastKnownModifiers)) return false;
513 if (handle == Ascender) {
515 } else if (handle == Descender) {
517 } else if (handle == BaselineAlphabetic) {
519 } else if (handle == BaselineIdeographic) {
521 } else if (handle == BaselineHanging) {
523 } else if (handle == BaselineMiddle) {
524 baseline = KoSvgText::BaselineMiddle;
525 } else if (handle == BaselineMathematical) {
527 } else if (handle == BaselineCentral) {
529 } else {
530 return false;
531 }
533 props.setProperty(KoSvgTextProperties::DominantBaselineId, QVariant::fromValue(baseline));
534 props.setProperty(KoSvgTextProperties::AlignmentBaselineId, QVariant::fromValue(baseline));
536 return true;
537}
@ DominantBaselineId
KoSvgText::Baseline.
@ AlignmentBaselineId
KoSvgText::Baseline.
Baseline
Baseline values used by dominant-baseline and baseline-align.
Definition KoSvgText.h:213
@ BaselineAlphabetic
Use 'romn' or the baseline for LCG scripts.
Definition KoSvgText.h:225
@ BaselineHanging
Definition KoSvgText.h:226
@ BaselineMiddle
Definition KoSvgText.h:232
@ BaselineTextBottom
Bottom side of the inline line-box.
Definition KoSvgText.h:234
@ BaselineIdeographic
Definition KoSvgText.h:223
@ BaselineMathematical
Definition KoSvgText.h:228
@ BaselineTextTop
Top side of the inline line-box.
Definition KoSvgText.h:235
@ BaselineCentral
Use the center between the ideographic over and under.
Definition KoSvgText.h:231

References KoSvgTextProperties::AlignmentBaselineId, Ascender, KoSvgText::BaselineAlphabetic, BaselineAlphabetic, KoSvgText::BaselineAuto, KoSvgText::BaselineCentral, BaselineCentral, KoSvgText::BaselineHanging, BaselineHanging, KoSvgText::BaselineIdeographic, BaselineIdeographic, KoSvgText::BaselineMathematical, BaselineMathematical, KoSvgText::BaselineMiddle, BaselineMiddle, KoSvgText::BaselineTextBottom, KoSvgText::BaselineTextTop, d, Descender, KoSvgTextProperties::DominantBaselineId, mergePropertiesIntoSelection(), NoHandle, and KoSvgTextProperties::setProperty().

◆ setDrawTypeSettingHandle()

void SvgTextCursor::setDrawTypeSettingHandle ( bool draw)

Whether to draw the type setting handles. Turned off when the typesetting strategy is active to give artists more control.

Definition at line 442 of file SvgTextCursor.cpp.

443{
444 d->drawTypeSettingHandle = draw;
445}

References d.

◆ setPasteRichTextByDefault()

void SvgTextCursor::setPasteRichTextByDefault ( const bool pasteRichText = true)

setPasteRichText

Parameters
pasteRichText– whether to paste rich text when possible.

Definition at line 336 of file SvgTextCursor.cpp.

337{
338 d->pasteRichText = pasteRichText;
339}

References d, and pasteRichText.

◆ setPos()

void SvgTextCursor::setPos ( int pos,
int anchor )

Set the pos and the anchor.

Definition at line 357 of file SvgTextCursor.cpp.

358{
359 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(d);
360 d->pos = pos;
361 d->anchor = anchor;
362 updateCursor();
364}

References anchor, d, pos, updateCursor(), and updateSelection().

◆ setPosToPoint()

void SvgTextCursor::setPosToPoint ( QPointF point,
bool moveAnchor = true )

Set the pos from a point. This currently does a search inside the text shape.

Definition at line 366 of file SvgTextCursor.cpp.

367{
368 if (d->shape) {
369 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(d);
370 int pos = d->shape->posForPointLineSensitive(d->shape->documentToShape(point));
371 if (d->preEditCommand) {
372 int start = d->shape->indexForPos(d->preEditStart);
373 int end = start + d->preEditLength;
374 int posIndex = d->shape->indexForPos(pos);
375 if (posIndex > start && posIndex <= end) {
376 qApp->inputMethod()->invokeAction(QInputMethod::Click, posIndex - start);
377 return;
378 } else {
380 }
381 }
382
383 const int finalPos = d->shape->posForIndex(d->shape->plainText().size());
384 d->pos = qBound(0, pos, finalPos);
385 if (moveAnchor || d->anchor < 0 || d->anchor > finalPos) {
386 d->anchor = d->pos;
387 }
388 updateCursor();
390 }
391}

References commitIMEPreEdit(), d, pos, posIndex, updateCursor(), and updateSelection().

◆ setShape()

void SvgTextCursor::setShape ( KoSvgTextShape * textShape)

setShape

Parameters
textShapeKoSvgTextShape to set, is allowed to be a nullptr, the cursor just won't do anything.

Definition at line 297 of file SvgTextCursor.cpp.

298{
299 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(d);
300 inputQueryUpdateBlocker.setChangeVisibility(true);
301
302 if (d->shape) {
304 d->shape->removeShapeChangeListener(this);
305 }
306 d->shape = textShape;
307 if (d->shape) {
308 d->shape->addShapeChangeListener(this);
310 d->pos = d->shape->posForIndex(d->shape->plainText().size());
312 } else {
313 d->pos = 0;
314 }
315 d->anchor = 0;
316 updateCursor(true);
318 d->interface->emitSelectionChange();
319}
void addShapeChangeListener(ShapeChangeListener *listener)
Definition KoShape.cpp:1152
void updateTypeSettingDecorFromShape()
Update the type setting decorations.

References KoShape::addShapeChangeListener(), commitIMEPreEdit(), d, updateCursor(), updateInputMethodItemTransform(), updateSelection(), and updateTypeSettingDecorFromShape().

◆ setTypeSettingHandleHovered()

void SvgTextCursor::setTypeSettingHandleHovered ( TypeSettingModeHandle hovered = TypeSettingModeHandle::NoHandle)

Set a given typesetting handle as hovered, so it will be drawn as such.

Definition at line 437 of file SvgTextCursor.cpp.

438{
439 d->hoveredTypeSettingHandle = hovered;
440}

References d.

◆ setTypeSettingModeActive()

void SvgTextCursor::setTypeSettingModeActive ( bool activate)

Set type setting mode active.

Definition at line 341 of file SvgTextCursor.cpp.

342{
343 d->typeSettingMode = activate;
345}

References d, and updateTypeSettingDecoration().

◆ setVisualMode()

void SvgTextCursor::setVisualMode ( const bool visualMode = true)

setVisualMode set whether the navigation mode is visual or logical. This right now primarily affects Bidirectional text.

Parameters
modewhether to turn off visual mode.

Definition at line 331 of file SvgTextCursor.cpp.

332{
333 d->visualNavigation = visualMode;
334}

References d.

◆ shape()

KoSvgTextShape * SvgTextCursor::shape ( ) const

Get the current text shape.

Returns
KoSvgTextShape *

◆ sigOpenGlyphPalette

void SvgTextCursor::sigOpenGlyphPalette ( )
signal

Called by actions, tells the parent tool to open the glyph palette.

◆ stopBlinkCursor

void SvgTextCursor::stopBlinkCursor ( )
privateslot

Called by timer, stops the text blinking animation.

Definition at line 1285 of file SvgTextCursor.cpp.

1286{
1287 d->cursorFlash.stop();
1288 d->cursorFlashLimit.stop();
1289 d->cursorVisible = true;
1290 if (d->shape) {
1291 Q_EMIT updateCursorDecoration(d->shape->shapeToDocument(d->cursorShape.boundingRect()) | d->oldCursorRect);
1292 }
1293}

References d, and updateCursorDecoration().

◆ textPropertyInterface()

KoSvgTextPropertiesInterface * SvgTextCursor::textPropertyInterface ( )

The text properties interface. This is how the text properties docker communicates with the text tool.

Definition at line 1712 of file SvgTextCursor.cpp.

1713{
1714 return d->interface;
1715}

References d.

◆ typeSettingHandleAtPos()

SvgTextCursor::TypeSettingModeHandle SvgTextCursor::typeSettingHandleAtPos ( const QRectF regionOfInterest)

Get typeSettingMode handle for text;.

Definition at line 393 of file SvgTextCursor.cpp.

394{
396
397 if (!(d->typeSettingMode && d->shape && d->canvas)) return handle;
398
399 const QRectF roiInShape = d->shape->absoluteTransformation().inverted().mapRect(regionOfInterest);
400
401 if (d->typeSettingDecor.handlesEnabled) {
402 if (roiInShape.contains(d->typeSettingDecor.handles.first)) {
404 } else if (roiInShape.contains(d->typeSettingDecor.handles.second)) {
405 handle = SvgTextCursor::EndPos;
406 }
407 }
408 if (handle != NoHandle) return handle;
409 if (!d->typeSettingDecor.boundingRect(d->handleRadius).intersects(roiInShape)) return handle;
410
411 qreal closest = std::numeric_limits<qreal>::max();
412 QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath> paths
413 = d->typeSettingDecor.testBaselines(d->lastKnownModifiers)? d->typeSettingDecor.baselines: d->typeSettingDecor.paths;
414 Q_FOREACH (const SvgTextCursor::TypeSettingModeHandle baseline, paths.keys()) {
415 const QPainterPath path = paths.value(baseline);
416 if (!path.intersects(roiInShape)) continue;
417
418 const QList<QPolygonF> polys = path.toSubpathPolygons();
419 Q_FOREACH(const QPolygonF poly, polys) {
420 if (poly.size() < 2) continue;
421 for (int i = 1; i < poly.size(); i++) {
422 QLineF l(poly.at(i-1), poly.at(i));
423 qreal distance = kisDistanceToLine(roiInShape.center(), l);
424 if (distance < closest) {
425 handle = baseline;
426 closest = distance;
427 d->typeSettingDecor.closestBaselinePoint =
428 kisProjectOnVector(l.p2() - l.p1(), roiInShape.center() - l.p1()) + l.p1();
429 }
430 }
431 }
432 }
433
434 return handle;
435}
qreal distance(const QPointF &p1, const QPointF &p2)
qreal kisDistanceToLine(const QPointF &m, const QLineF &line)
Definition kis_global.h:234
QPointF kisProjectOnVector(const QPointF &base, const QPointF &v)
Definition kis_global.h:280

References d, distance(), EndPos, kisDistanceToLine(), kisProjectOnVector(), NoHandle, and StartPos.

◆ updateCanvasResources

void SvgTextCursor::updateCanvasResources ( )
privateslot

Update the canvas resources with fore and background color.

Definition at line 2147 of file SvgTextCursor.cpp.

2148{
2149 // Only update canvas resources when there's no selection.
2150 // This relies on Krita not setting anything on the text when there's no selection.
2151 if (d->shape && d->canvas->resourceManager() && d->pos == d->anchor) {
2152 KoSvgTextProperties props = hasSelection()? d->shape->propertiesForPos(qMin(d->pos, d->anchor), true): d->shape->textProperties();
2153 KoColorBackground *bg = dynamic_cast<KoColorBackground *>(props.background().data());
2154 if (bg && props.hasProperty(KoSvgTextProperties::FillId)) {
2155 KoColor c;
2156 c.fromQColor(bg->color());
2157 c.setOpacity(1.0);
2158 if (c != d->canvas->resourceManager()->foregroundColor()) {
2159 d->canvas->resourceManager()->setForegroundColor(c);
2160 }
2161 }
2162 KoShapeStroke *stroke = dynamic_cast<KoShapeStroke *>(props.stroke().data());
2163 if (stroke && stroke->isVisible() && stroke->color().isValid() && props.hasProperty(KoSvgTextProperties::StrokeId)) {
2164 KoColor c;
2165 c.fromQColor(stroke->color());
2166 c.setOpacity(1.0);
2167 if (c != d->canvas->resourceManager()->backgroundColor()) {
2168 d->canvas->resourceManager()->setBackgroundColor(c);
2169 }
2170 }
2171
2172 Q_FOREACH (QAction *action, d->actions) {
2173 // Blocking signals so that we don't get a toggle action while evaluating the checked-ness.
2174 action->blockSignals(true);
2175 const QList<KoSvgTextProperties> r = d->shape->propertiesForRange(qMin(d->pos, d->anchor), qMax(d->pos, d->anchor), true);
2176 if (action->isCheckable() && SvgTextShortCuts::possibleActions().contains(action->objectName())) {
2177 const bool checked = SvgTextShortCuts::actionEnabled(action, r);
2178 if (action->isChecked() != checked) {
2179 action->setChecked(checked);
2180 }
2181 }
2182 action->blockSignals(false);
2183 }
2184 }
2185}
QColor color() const
Returns the background color.
void setOpacity(quint8 alpha)
Definition KoColor.cpp:333
void fromQColor(const QColor &c)
Convenient function for converting from a QColor.
Definition KoColor.cpp:213
bool isVisible() const override
static bool actionEnabled(QAction *action, const QList< KoSvgTextProperties > currentProperties)
static QStringList possibleActions()

References SvgTextShortCuts::actionEnabled(), KoSvgTextProperties::background(), KoColorBackground::color(), KoShapeStroke::color, d, KoSvgTextProperties::FillId, KoColor::fromQColor(), KoSvgTextProperties::hasProperty(), hasSelection(), KoShapeStroke::isVisible(), SvgTextShortCuts::possibleActions(), KoColor::setOpacity(), KoSvgTextProperties::stroke(), and KoSvgTextProperties::StrokeId.

◆ updateCursor()

void SvgTextCursor::updateCursor ( bool firstUpdate = false)
private

update the cursor shape. First update will block ensuring the canvas is visible so setShape won't cause this.

Definition at line 1717 of file SvgTextCursor.cpp.

1718{
1719 if (d->shape) {
1720 d->oldCursorRect = d->shape->shapeToDocument(d->cursorShape.boundingRect());
1721 d->posIndex = d->shape->indexForPos(d->pos);
1722 d->anchorIndex = d->shape->indexForPos(d->anchor);
1723 emit selectionChanged();
1725 }
1726 d->cursorColor = QColor();
1727 d->cursorShape = d->shape? d->shape->cursorForPos(d->pos, d->cursorCaret, d->cursorColor): QPainterPath();
1728
1729 if (!d->blockQueryUpdates) {
1730 qApp->inputMethod()->update(Qt::ImQueryInput);
1731 }
1732 d->interface->emitCharacterSelectionChange();
1733 if (!(d->canvas->canvasWidget() && d->canvas->canvasController())) {
1734 // Mockcanvas in the tests has neither.
1735 return;
1736 }
1737 if (d->shape && !firstUpdate) {
1738 QRectF rect = d->shape->shapeToDocument(d->cursorShape.boundingRect());
1739 d->canvas->canvasController()->ensureVisibleDoc(rect, false);
1740 }
1741 if (d->canvas->canvasWidget()->hasFocus()) {
1742 d->cursorFlash.start();
1743 d->cursorFlashLimit.start();
1744 d->cursorVisible = false;
1745 blinkCursor();
1746 }
1747}
void selectionChanged()
Sents an update selection was changed.

References blinkCursor(), d, selectionChanged(), and updateTypeSettingDecoration().

◆ updateCursorDecoration

void SvgTextCursor::updateCursorDecoration ( QRectF updateRect)
signal

Sents an update to the parent tool to update it's decorations.

◆ updateIMEDecoration()

void SvgTextCursor::updateIMEDecoration ( )
private

Definition at line 1763 of file SvgTextCursor.cpp.

1764{
1765 if (d->shape) {
1766 d->oldIMEDecorationRect = d->shape->shapeToDocument(d->IMEDecoration.boundingRect());
1767 KoSvgText::TextDecorations decor;
1768 decor.setFlag(KoSvgText::DecorationUnderline, true);
1769 d->IMEDecoration = QPainterPath();
1770 if (d->preEditCommand) {
1771 Q_FOREACH(const IMEDecorationInfo info, d->styleMap) {
1772
1773 int startIndex = d->shape->indexForPos(d->preEditStart) + info.start;
1774 int endIndex = startIndex + info.length;
1775 qreal minimum = d->canvas->viewToDocument(QPointF(1, 1)).x();
1776 d->IMEDecoration.addPath(d->shape->underlines(d->shape->posForIndex(startIndex),
1777 d->shape->posForIndex(endIndex),
1778 info.decor,
1779 info.style,
1780 minimum,
1781 info.thick));
1782 d->IMEDecoration.setFillRule(Qt::WindingFill);
1783 }
1784 }
1785
1786 Q_EMIT updateCursorDecoration(d->shape->shapeToDocument(d->IMEDecoration.boundingRect()) | d->oldIMEDecorationRect);
1787 }
1788}
@ DecorationUnderline
Definition KoSvgText.h:259
bool thick
Whether the decoration needs to be doubled in size.
KoSvgText::TextDecorationStyle style
The style.
KoSvgText::TextDecorations decor
Which sides get decorated.

References d, IMEDecorationInfo::decor, KoSvgText::DecorationUnderline, IMEDecorationInfo::length, IMEDecorationInfo::start, IMEDecorationInfo::style, IMEDecorationInfo::thick, and updateCursorDecoration().

◆ updateInputMethodItemTransform

void SvgTextCursor::updateInputMethodItemTransform ( )
privateslot

Definition at line 1295 of file SvgTextCursor.cpp.

1296{
1297 // Mockcanvas in the tests has no window.
1298 if (!d->canvas->canvasWidget()) {
1299 return;
1300 }
1301 QPoint pos = d->canvas->canvasWidget()->mapTo(d->canvas->canvasWidget()->window(), QPoint());
1302 QTransform widgetToWindow = QTransform::fromTranslate(pos.x(), pos.y());
1303 QTransform inputItemTransform = widgetToWindow;
1304 QRectF inputRect = d->canvas->canvasWidget()->geometry();
1305 if (d->shape) {
1306 inputRect = d->shape->outlineRect().normalized();
1307 QTransform shapeTransform = d->shape->absoluteTransformation();
1308 QTransform docToView = d->canvas->viewConverter()->documentToView();
1309 QTransform viewToWidget = d->canvas->viewConverter()->viewToWidget();
1310 inputItemTransform = shapeTransform * docToView * viewToWidget * widgetToWindow;
1311 // Only mess with IME if we're actually the thing being typed at.
1312 if (d->hasFocus) {
1313 QInputMethod *inputMethod = QGuiApplication::inputMethod();
1314 inputMethod->setInputItemTransform(inputItemTransform);
1315 inputMethod->setInputItemRectangle(inputRect);
1316 if (!d->blockQueryUpdates) {
1317 inputMethod->update(Qt::ImQueryInput);
1318 }
1319 }
1320 }
1321}

References d, and pos.

◆ updateModifiers()

void SvgTextCursor::updateModifiers ( const Qt::KeyboardModifiers modifiers)

Definition at line 1653 of file SvgTextCursor.cpp.

1654{
1655 d->lastKnownModifiers = modifiers;
1657}

References d, and updateTypeSettingDecoration().

◆ updateSelection()

void SvgTextCursor::updateSelection ( )
private

Definition at line 1749 of file SvgTextCursor.cpp.

1750{
1751 if (d->shape) {
1752 d->oldSelectionRect = d->shape->shapeToDocument(d->selection.boundingRect());
1753 d->shape->cursorForPos(d->anchor, d->anchorCaret, d->cursorColor);
1754 d->selection = d->shape->selectionBoxes(d->pos, d->anchor);
1755 Q_EMIT updateCursorDecoration(d->shape->shapeToDocument(d->selection.boundingRect()) | d->oldSelectionRect);
1756
1757 if (!d->blockQueryUpdates) {
1758 QGuiApplication::inputMethod()->update(Qt::ImQueryInput);
1759 }
1760 }
1761}

References d, and updateCursorDecoration().

◆ updateTypeSettingDecoration()

void SvgTextCursor::updateTypeSettingDecoration ( )
private

This adds the start and end decoration...

This could be better but requires better nodeindex retrieval...

Split up baselines into paths and baselines.

Definition at line 1853 of file SvgTextCursor.cpp.

1854{
1855 QRectF updateRect;
1856 if (d->shape && d->typeSettingMode) {
1857
1859 d->shape->getPositionsAndRotationsForRange(d->pos, d->anchor);
1860 if (infos.size() < 1) return;
1861
1862 const bool rtl = infos.first().rtl;
1863
1864 KoSvgTextCharacterInfo first = infos.first();
1865 KoSvgTextCharacterInfo last = infos.last();
1866 if (infos.size() > 1) {
1867 std::sort(infos.begin(), infos.end(), KoSvgTextCharacterInfo::visualLessThan);
1868 for (auto it = infos.begin(); it != infos.end(); it++) {
1869 if (it->visualIndex >= 0) {
1870 first = *it;
1871 break;
1872 }
1873 }
1874 for (auto it = infos.rbegin(); it != infos.rend(); it++) {
1875 if (it->visualIndex >= 0) {
1876 last = *it;
1877 break;
1878 }
1879 }
1880 }
1881
1882 QTransform t = QTransform::fromTranslate(last.finalPos.x(), last.finalPos.y());
1883 t.rotate(last.rotateDeg);
1884 last.finalPos = t.map(last.advance);
1885
1886 d->typeSettingDecor.handles.first = rtl? last.finalPos: first.finalPos;
1887 d->typeSettingDecor.handles.second = rtl? first.finalPos: last.finalPos;
1888
1889 //Start collecting the metrics decoration...
1890 d->typeSettingDecor.paths = QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>();
1891 d->typeSettingDecor.baselines = QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>();
1892 d->typeSettingDecor.edges = QPainterPath();
1893 d->typeSettingDecor.parentPaths = QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>();
1894 d->typeSettingDecor.parentBaselines = QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>();
1895 QList<KoSvgTextCharacterInfo> metricInfos = infos;
1896 if (d->pos == d->anchor) {
1897 metricInfos = d->shape->getPositionsAndRotationsForRange(0, d->shape->posForIndex(d->shape->plainText().size()));
1898 }
1899 const bool isHorizontal = d->shape->writingMode() == KoSvgText::HorizontalTB;
1900 const int minPos = qMin(d->pos, d->anchor);
1901 const int maxPos = qMax(d->pos, d->anchor);
1902 const int endPos = d->shape->posForIndex(d->shape->plainText().size());
1903
1905 if (minPos > 0 || maxPos < endPos) {
1906 const KoSvgTextProperties props = d->shape->textProperties();
1908 KoSvgText::FontMetrics metrics = props.metrics(true, true);
1909 const qreal scaleMetrics = props.fontSize().value/qreal(metrics.fontSize);
1910 const int lineGap = calcLineHeight(lineHeight, metrics, scaleMetrics);
1911
1912 const QMap<SvgTextCursor::TypeSettingModeHandle, int> types
1913 = typeSettingBaselinesFromMetrics(metrics, lineGap, isHorizontal);
1914
1916 QList<int> positions;
1917 positions << 0;
1918 positions << qMax(0, minPos-1);
1919 positions << maxPos;
1920 positions << endPos;
1921
1922 Q_FOREACH(const int pos, positions) {
1924 d->shape->getPositionsAndRotationsForRange(pos, pos);
1925 parentInfos.append(info.first());
1926 }
1927
1928 QPointF drawOffset = isHorizontal? QPointF(d->handleRadius*2, 0): QPointF(0, d->handleRadius*2);
1929 if (d->canvas) {
1930 drawOffset = d->canvas->viewConverter()->viewToDocument().map(drawOffset);
1931 }
1932 bool toggleOffset = rtl;
1933
1934 for (auto it = parentInfos.begin(); it != parentInfos.end(); it++) {
1935 const bool currentIsMin = (d->shape->posForIndex(it->logicalIndex) == minPos);
1936 const bool currentIsMax = (d->shape->posForIndex(it->logicalIndex) == maxPos);
1937
1938 if ((currentIsMin && minPos == 0) || (currentIsMax && maxPos == endPos)) {
1939 toggleOffset = !toggleOffset;
1940 continue;
1941 }
1942
1943 const QPointF finalPos = toggleOffset? it->finalPos + (it->advance - drawOffset): it->finalPos;
1944 const QPointF advance = drawOffset;
1945
1946 const QTransform t = posAndRotateTransform(finalPos, it->rotateDeg);
1947
1948 Q_FOREACH(SvgTextCursor::TypeSettingModeHandle handle, types.keys()) {
1949 const int metric = types.value(handle);
1950 processBaseline(handle, metric, isHorizontal, t, scaleMetrics, advance, d->typeSettingDecor.parentBaselines);
1951 }
1952
1953 {
1954 if (currentIsMin && minPos == maxPos && !toggleOffset) {
1955 toggleOffset = !toggleOffset;
1956 continue;
1957 }
1958 const QPointF advance = toggleOffset? it->advance: QPointF();
1959 const QTransform t = posAndRotateTransform(it->finalPos, it->rotateDeg);
1960 processEdges(t, types, isHorizontal, scaleMetrics, advance, d->typeSettingDecor.edges);
1961 }
1962
1963 toggleOffset = !toggleOffset;
1964 }
1965 }
1966
1968 bool toggleOffset = false; // MetricInfos are visually-ordered.
1969 for (auto it = metricInfos.begin(); it != metricInfos.end(); it++) {
1970 const int currentPos = (d->pos == d->anchor)? -1 :d->shape->posForIndex(it->logicalIndex);
1971
1972 KoSvgTextProperties props = d->shape->propertiesForPos(currentPos, true);
1974 KoSvgText::FontMetrics propMetrics = props.metrics(true, true);
1975
1976 KoSvgText::FontMetrics metrics = (d->pos == d->anchor)? propMetrics :it->metrics;
1977
1978 const qreal scaleMetrics = props.fontSize().value/qreal(metrics.fontSize);
1979 const int lineGap = calcLineHeight(lineHeight, metrics, scaleMetrics);
1980
1981 const QTransform t = posAndRotateTransform(it->finalPos, it->rotateDeg);
1982
1983 const QMap<SvgTextCursor::TypeSettingModeHandle, int> types
1984 = typeSettingBaselinesFromMetrics(metrics, lineGap, isHorizontal);
1985
1986 Q_FOREACH(SvgTextCursor::TypeSettingModeHandle handle, types.keys()) {
1987 const int metric = types.value(handle);
1988 processBaseline(handle, metric, isHorizontal, t, scaleMetrics, it->advance, d->typeSettingDecor.baselines);
1989 }
1990 if ((currentPos == minPos || currentPos+1 == maxPos) && minPos != maxPos) {
1991 const QPointF advance = toggleOffset? it->advance: QPointF();
1992 toggleOffset = !toggleOffset;
1993 processEdges(t, types, isHorizontal, scaleMetrics, advance, d->typeSettingDecor.edges);
1994 }
1995 }
1996
1998 const QList<SvgTextCursor::TypeSettingModeHandle> nonBaselines = {
2000 };
2001 Q_FOREACH(SvgTextCursor::TypeSettingModeHandle handle, nonBaselines) {
2002 d->typeSettingDecor.paths.insert(handle, d->typeSettingDecor.baselines.value(handle));
2003 d->typeSettingDecor.parentPaths.insert(handle, d->typeSettingDecor.parentBaselines.value(handle));
2004 }
2005 d->typeSettingDecor.baselines.remove(LineHeightTop);
2006 d->typeSettingDecor.baselines.remove(LineHeightBottom);
2007 d->typeSettingDecor.parentBaselines.remove(LineHeightTop);
2008 d->typeSettingDecor.parentBaselines.remove(LineHeightBottom);
2009
2010 updateRect = d->shape->shapeToDocument(d->typeSettingDecor.boundingRect(d->handleRadius));
2011 }
2012 updateTypeSettingDecorFromShape(); // To remove the text-in-path nodes..
2013 Q_EMIT updateCursorDecoration(updateRect | d->oldTypeSettingRect);
2014 d->oldTypeSettingRect = updateRect;
2015}
QTransform posAndRotateTransform(const QPointF pos, const qreal rotateDeg)
int calcLineHeight(const KoSvgText::LineHeightInfo &lineHeight, const KoSvgText::FontMetrics &metrics, const qreal scaleMetrics)
void processBaseline(const SvgTextCursor::TypeSettingModeHandle handle, const int metric, const bool isHorizontal, QTransform t, const qreal scaleMetrics, const QPointF &advance, QMap< SvgTextCursor::TypeSettingModeHandle, QPainterPath > &decor)
void processEdges(QTransform t, QMap< SvgTextCursor::TypeSettingModeHandle, int > values, const bool isHorizontal, const qreal scaleMetrics, const QPointF advance, QPainterPath &path)
The KoSvgTextCharacterInfo class This is a small struct to convey information about character positio...
static bool visualLessThan(const KoSvgTextCharacterInfo &a, const KoSvgTextCharacterInfo &b)
qint32 fontSize
Currently set size, CSS unit 'em'.
Definition KoSvgText.h:329

References KoSvgTextCharacterInfo::advance, Ascender, BaselineShift, calcLineHeight(), d, Descender, KoSvgTextCharacterInfo::finalPos, KoSvgText::FontMetrics::fontSize, KoSvgTextProperties::fontSize(), KoSvgText::HorizontalTB, LineHeightBottom, KoSvgTextProperties::LineHeightId, LineHeightTop, KoSvgTextProperties::metrics(), pos, posAndRotateTransform(), processBaseline(), processEdges(), KoSvgTextProperties::propertyOrDefault(), KoSvgTextCharacterInfo::rotateDeg, typeSettingBaselinesFromMetrics(), updateCursorDecoration(), updateTypeSettingDecorFromShape(), KoSvgText::CssLengthPercentage::value, and KoSvgTextCharacterInfo::visualLessThan().

◆ updateTypeSettingDecorFromShape()

void SvgTextCursor::updateTypeSettingDecorFromShape ( )

Update the type setting decorations.

Definition at line 447 of file SvgTextCursor.cpp.

448{
449 if (d->shape) {
450 d->typeSettingDecor.handlesEnabled = ((d->shape->textType() == KoSvgTextShape::PreformattedText
451 || d->shape->textType() == KoSvgTextShape::PrePositionedText)
452 && !(d->shape->topLevelNodeForPos(d->pos).textPath()));
453 }
454}
@ PreformattedText
Text-on-Path falls under this or PrePositionedText depending on collapse of lines.

References d, KoSvgTextShape::PreformattedText, and KoSvgTextShape::PrePositionedText.

Member Data Documentation

◆ actions

QList<QAction*> SvgTextCursor::actions

Definition at line 247 of file SvgTextCursor.cpp.

◆ anchor

int SvgTextCursor::anchor = 0

Definition at line 202 of file SvgTextCursor.cpp.

◆ anchorCaret

QLineF SvgTextCursor::anchorCaret

Definition at line 214 of file SvgTextCursor.cpp.

◆ anchorIndex

int SvgTextCursor::anchorIndex = 0

Definition at line 223 of file SvgTextCursor.cpp.

◆ blockQueryUpdates

bool SvgTextCursor::blockQueryUpdates = false

Block qApp->inputMethod->update(), enabled during the inputmethod event flow.

Definition at line 243 of file SvgTextCursor.cpp.

◆ canvas

KoCanvasBase* SvgTextCursor::canvas

Definition at line 199 of file SvgTextCursor.cpp.

◆ cursorCaret

QLineF SvgTextCursor::cursorCaret

Definition at line 213 of file SvgTextCursor.cpp.

◆ cursorColor

QColor SvgTextCursor::cursorColor

Definition at line 211 of file SvgTextCursor.cpp.

◆ cursorFlash

QTimer SvgTextCursor::cursorFlash

Definition at line 205 of file SvgTextCursor.cpp.

◆ cursorFlashLimit

QTimer SvgTextCursor::cursorFlashLimit

Definition at line 206 of file SvgTextCursor.cpp.

◆ cursorShape

QPainterPath SvgTextCursor::cursorShape

Definition at line 210 of file SvgTextCursor.cpp.

◆ cursorVisible

bool SvgTextCursor::cursorVisible = false

Definition at line 207 of file SvgTextCursor.cpp.

◆ cursorWidth

int SvgTextCursor::cursorWidth = 1

Definition at line 215 of file SvgTextCursor.cpp.

◆ d

const QScopedPointer<Private> SvgTextCursor::d
private

Definition at line 394 of file SvgTextCursor.h.

◆ drawCursorInAdditionToSelection

bool SvgTextCursor::drawCursorInAdditionToSelection = false

Definition at line 216 of file SvgTextCursor.cpp.

◆ drawTypeSettingHandle

bool SvgTextCursor::drawTypeSettingHandle = true

Definition at line 232 of file SvgTextCursor.cpp.

◆ handleRadius

qreal SvgTextCursor::handleRadius = 7

Definition at line 233 of file SvgTextCursor.cpp.

◆ hasFocus

bool SvgTextCursor::hasFocus = false

Definition at line 208 of file SvgTextCursor.cpp.

◆ hoveredTypeSettingHandle

SvgTextCursor::TypeSettingModeHandle SvgTextCursor::hoveredTypeSettingHandle = SvgTextCursor::NoHandle

Definition at line 231 of file SvgTextCursor.cpp.

◆ IMEDecoration

QPainterPath SvgTextCursor::IMEDecoration

The decorations for the current preedit string.

Definition at line 241 of file SvgTextCursor.cpp.

◆ interface

SvgTextCursorPropertyInterface* SvgTextCursor::interface {nullptr}

Definition at line 245 of file SvgTextCursor.cpp.

245{nullptr};

◆ isAddingCommand

bool SvgTextCursor::isAddingCommand = false

Definition at line 200 of file SvgTextCursor.cpp.

◆ lastKnownModifiers

Qt::KeyboardModifiers SvgTextCursor::lastKnownModifiers

Definition at line 228 of file SvgTextCursor.cpp.

◆ oldCursorRect

QRectF SvgTextCursor::oldCursorRect

Definition at line 212 of file SvgTextCursor.cpp.

◆ oldIMEDecorationRect

QRectF SvgTextCursor::oldIMEDecorationRect

Update Rectangle of previous decoration.

Definition at line 242 of file SvgTextCursor.cpp.

◆ oldSelectionRect

QRectF SvgTextCursor::oldSelectionRect

Definition at line 218 of file SvgTextCursor.cpp.

◆ oldTypeSettingRect

QRectF SvgTextCursor::oldTypeSettingRect

Definition at line 234 of file SvgTextCursor.cpp.

◆ pasteRichText

bool SvgTextCursor::pasteRichText = true

Definition at line 226 of file SvgTextCursor.cpp.

◆ pos

int SvgTextCursor::pos = 0

Definition at line 201 of file SvgTextCursor.cpp.

◆ posIndex

int SvgTextCursor::posIndex = 0

Definition at line 222 of file SvgTextCursor.cpp.

◆ preEditCommand

SvgTextInsertCommand* SvgTextCursor::preEditCommand {nullptr}

PreEdit string as an command provided by the input method.

Definition at line 237 of file SvgTextCursor.cpp.

237{nullptr};

◆ preEditLength

int SvgTextCursor::preEditLength = -1

Length of the preEditString.

Definition at line 239 of file SvgTextCursor.cpp.

◆ preEditStart

int SvgTextCursor::preEditStart = -1

Start of the preEdit string as a cursor pos.

Definition at line 238 of file SvgTextCursor.cpp.

◆ resourceManagerAcyclicConnector

KisAcyclicSignalConnector SvgTextCursor::resourceManagerAcyclicConnector

Definition at line 249 of file SvgTextCursor.cpp.

◆ selection

QPainterPath SvgTextCursor::selection

Definition at line 217 of file SvgTextCursor.cpp.

◆ shape

KoSvgTextShape * SvgTextCursor::shape {nullptr}

Definition at line 203 of file SvgTextCursor.cpp.

203{nullptr};

◆ styleMap

QVector<IMEDecorationInfo> SvgTextCursor::styleMap

Decoration info (underlines) for the preEdit string to differentiate it from regular text.

Definition at line 240 of file SvgTextCursor.cpp.

◆ typeSettingDecor

TypeSettingDecorInfo SvgTextCursor::typeSettingDecor

Definition at line 235 of file SvgTextCursor.cpp.

◆ typeSettingMode

bool SvgTextCursor::typeSettingMode = false

Definition at line 230 of file SvgTextCursor.cpp.

◆ visualNavigation

bool SvgTextCursor::visualNavigation = true

Definition at line 225 of file SvgTextCursor.cpp.


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