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)
 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 155 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 54 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 75 of file SvgTextCursor.h.

Constructor & Destructor Documentation

◆ SvgTextCursor()

SvgTextCursor::SvgTextCursor ( KoCanvasBase * canvas)
explicit

Definition at line 251 of file SvgTextCursor.cpp.

251 :
252 d(new Private)
253{
254 d->canvas = canvas;
255 d->interface = new SvgTextCursorPropertyInterface(this);
256 if (d->canvas->canvasController()) {
257 // Mockcanvas in the tests has no canvas controller.
258 connect(d->canvas->canvasController()->proxyObject, SIGNAL(sizeChanged(QSize)), this, SLOT(updateInputMethodItemTransform()));
259 connect(d->canvas->canvasController()->proxyObject,
260 SIGNAL(moveDocumentOffset(QPointF, QPointF)),
261 this,
263 connect(d->canvas->canvasController()->proxyObject,
264 SIGNAL(effectiveZoomChanged(qreal)),
265 this,
267 connect(d->canvas->canvasController()->proxyObject,
268 SIGNAL(documentRotationChanged(qreal)),
269 this,
271 connect(d->canvas->canvasController()->proxyObject,
272 SIGNAL(documentMirrorStatusChanged(bool, bool)),
273 this,
275 d->resourceManagerAcyclicConnector.connectBackwardResourcePair(
276 d->canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)),
277 this, SLOT(canvasResourceChanged(int,QVariant)));
278 d->resourceManagerAcyclicConnector.connectForwardVoid(d->interface, SIGNAL(textCharacterSelectionChanged()), this, SLOT(updateCanvasResources()));
279 }
280
281}
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 283 of file SvgTextCursor.cpp.

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

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 2098 of file SvgTextCursor.cpp.

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

◆ addCommandToUndoAdapter()

void SvgTextCursor::addCommandToUndoAdapter ( KUndo2Command * cmd)
private

Adds a command to the canvas of the parent tool.

Definition at line 2012 of file SvgTextCursor.cpp.

2013{
2014 if (d->canvas) {
2015 if (cmd) {
2016 d->isAddingCommand = true;
2017 d->canvas->addCommand(cmd);
2018 d->isAddingCommand = false;
2019 }
2020 }
2021}

References d.

◆ blinkCursor

void SvgTextCursor::blinkCursor ( )
privateslot

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

Definition at line 1272 of file SvgTextCursor.cpp.

1273{
1274 if (d->shape) {
1275 Q_EMIT updateCursorDecoration(d->shape->shapeToDocument(d->cursorShape.boundingRect()) | d->oldCursorRect);
1276 d->cursorVisible = !d->cursorVisible;
1277 }
1278}
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 1318 of file SvgTextCursor.cpp.

1319{
1321 return;
1322
1323 KoSvgTextProperties props;
1324 KoSvgTextProperties shapeProps = hasSelection()? d->shape->propertiesForPos(qMin(d->pos, d->anchor), true): d->shape->textProperties();
1327 if (!bg->compareTo(shapeProps.background().data())
1328 || !shapeProps.hasProperty(KoSvgTextProperties::FillId)) {
1330 QVariant::fromValue(KoSvgText::BackgroundProperty(bg)));
1331 }
1332 } else if (key == KoCanvasResource::BackgroundColor) {
1335 KoShapeStrokeSP shapeStroke = qSharedPointerDynamicCast<KoShapeStroke>(shapeProps.stroke());
1336 if (shapeStroke->isVisible()) {
1337 stroke.reset(new KoShapeStroke(*shapeStroke));
1338 }
1339 }
1340 stroke->setColor(value.value<KoColor>().toQColor());
1341 if (!stroke->compareFillTo(shapeProps.stroke().data()) || !shapeProps.hasProperty(KoSvgTextProperties::StrokeId)) {
1343 QVariant::fromValue(KoSvgText::StrokeProperty(stroke)));
1344 }
1345 }
1346 if (!props.isEmpty()) {
1347 mergePropertiesIntoSelection(props, QSet<KoSvgTextProperties::PropertyId>(), !hasSelection());
1348 }
1349}
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 1362 of file SvgTextCursor.cpp.

1363{
1364 KoSvgTextProperties props;
1365
1366 QSet<KoSvgTextProperties::PropertyId> ids;
1367
1368 for (int i = 0; i < int(KoSvgTextProperties::LastPropertyId); i++) {
1369 ids.insert(KoSvgTextProperties::PropertyId(i));
1370 }
1371
1372 mergePropertiesIntoSelection(props, ids);
1373}
@ 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 2122 of file SvgTextCursor.cpp.

2123{
2124 if (!d->preEditCommand) {
2125 return;
2126 }
2127
2128 qApp->inputMethod()->commit();
2129
2130 if (!d->preEditCommand) {
2131 return;
2132 }
2133
2134 d->preEditCommand->undo();
2135 d->preEditCommand = nullptr;
2136 d->preEditStart = -1;
2137 d->preEditLength = 0;
2139 updateCursor();
2140}
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 737 of file SvgTextCursor.cpp.

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

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

References d.

◆ cursorTypeForTypeSetting()

QCursor SvgTextCursor::cursorTypeForTypeSetting ( ) const

Return appropriate typeSetting cursor;.

Definition at line 455 of file SvgTextCursor.cpp.

456{
457 if (d->hoveredTypeSettingHandle == StartPos ||
458 d->hoveredTypeSettingHandle == StartPos ||
459 d->typeSettingDecor.testBaselines(d->lastKnownModifiers)) {
460 return Qt::ArrowCursor;
461 } else if (d->shape) {
462 return (d->shape->writingMode() == KoSvgText::HorizontalTB)? Qt::SizeVerCursor: Qt::SizeHorCursor;
463 }
464 return Qt::ArrowCursor;
465}
@ 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 829 of file SvgTextCursor.cpp.

830{
831 setPos(d->pos, d->pos);
832}
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 1659 of file SvgTextCursor.cpp.

1660{
1661 d->cursorFlash.start();
1662 d->cursorFlashLimit.start();
1663 d->cursorVisible = false;
1664 d->hasFocus = true;
1665 blinkCursor();
1666}
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 1668 of file SvgTextCursor.cpp.

1669{
1670 d->hasFocus = false;
1672}
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 351 of file SvgTextCursor.cpp.

352{
353 return d->anchor;
354}

References d.

◆ getPos()

int SvgTextCursor::getPos ( )

Get the current position.

Definition at line 346 of file SvgTextCursor.cpp.

347{
348 return d->pos;
349}

References d.

◆ handleName()

QString SvgTextCursor::handleName ( TypeSettingModeHandle handle) const

handleName

Returns
translated name of a given handle.

Definition at line 467 of file SvgTextCursor.cpp.

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

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 1375 of file SvgTextCursor.cpp.

1376{
1377 return d->pos != d->anchor;
1378}

References d.

◆ inputMethodEvent()

void SvgTextCursor::inputMethodEvent ( QInputMethodEvent * event)

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

Definition at line 1069 of file SvgTextCursor.cpp.

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

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

References d, dbgTools, and length().

◆ insertRichText()

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

Insert rich text at getPos();.

Definition at line 623 of file SvgTextCursor.cpp.

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

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

◆ insertText()

void SvgTextCursor::insertText ( QString text)

Insert text at getPos()

Definition at line 607 of file SvgTextCursor.cpp.

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

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 1412 of file SvgTextCursor.cpp.

1413{
1415
1416 updateModifiers(event->modifiers());
1417
1418 if (d->preEditCommand) {
1419 //MacOS will keep sending keyboard events during IME handling.
1420 event->accept();
1421 return;
1422 }
1423
1424 bool select = event->modifiers().testFlag(Qt::ShiftModifier);
1425
1426 if (!((Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier) & event->modifiers())) {
1427
1428 switch (event->key()) {
1429 case Qt::Key_Right:
1431 event->accept();
1432 break;
1433 case Qt::Key_Left:
1435 event->accept();
1436 break;
1437 case Qt::Key_Up:
1439 event->accept();
1440 break;
1441 case Qt::Key_Down:
1443 event->accept();
1444 break;
1445 case Qt::Key_Delete:
1447 event->accept();
1448 break;
1449 case Qt::Key_Backspace:
1451 event->accept();
1452 break;
1453 case Qt::Key_Return:
1454 case Qt::Key_Enter:
1455 insertText("\n");
1456 event->accept();
1457 break;
1458 default:
1459 event->ignore();
1460 }
1461
1462 if (event->isAccepted()) {
1463 return;
1464 }
1465 }
1466 if (acceptableInput(event)) {
1467 insertText(event->text());
1468 event->accept();
1469 return;
1470 }
1471
1472 KoSvgTextProperties props = d->shape->textProperties();
1473
1476
1477 // Qt's keysequence stuff doesn't handle vertical, so to test all the standard keyboard shortcuts as if it did,
1478 // we reinterpret the direction keys according to direction and writing mode, and test against that.
1479
1480 int newKey = event->key();
1481
1482 if (direction == KoSvgText::DirectionRightToLeft) {
1483 switch (newKey) {
1484 case Qt::Key_Left:
1485 newKey = Qt::Key_Right;
1486 break;
1487 case Qt::Key_Right:
1488 newKey = Qt::Key_Left;
1489 break;
1490 default:
1491 break;
1492 }
1493 }
1494
1495 if (mode == KoSvgText::VerticalRL) {
1496 switch (newKey) {
1497 case Qt::Key_Left:
1498 newKey = Qt::Key_Down;
1499 break;
1500 case Qt::Key_Right:
1501 newKey = Qt::Key_Up;
1502 break;
1503 case Qt::Key_Up:
1504 newKey = Qt::Key_Left;
1505 break;
1506 case Qt::Key_Down:
1507 newKey = Qt::Key_Right;
1508 break;
1509 default:
1510 break;
1511 }
1512 } else if (mode == KoSvgText::VerticalRL) {
1513 switch (newKey) {
1514 case Qt::Key_Left:
1515 newKey = Qt::Key_Up;
1516 break;
1517 case Qt::Key_Right:
1518 newKey = Qt::Key_Down;
1519 break;
1520 case Qt::Key_Up:
1521 newKey = Qt::Key_Left;
1522 break;
1523 case Qt::Key_Down:
1524 newKey = Qt::Key_Right;
1525 break;
1526 default:
1527 break;
1528 }
1529 }
1530
1531 QKeySequence testSequence(event->modifiers() | newKey);
1532
1533
1534 // Note for future, when we have format changing actions:
1535 // We'll need to test format change actions before the standard
1536 // keys, as one of the standard keys for deleting a line is ctrl+u
1537 // which would probably be expected to do underline before deleting.
1538
1539 Q_FOREACH(QAction *action, d->actions) {
1540 if (action->shortcut() == testSequence) {
1541 event->accept();
1542 action->trigger();
1543 return;
1544 }
1545 }
1546
1547 // This first set is already tested above, however, if they still
1548 // match, then it's one of the extra sequences for MacOs, which
1549 // seem to be purely logical, instead of the visual set we tested
1550 // above.
1551 if (testSequence == QKeySequence::MoveToNextChar) {
1553 event->accept();
1554 } else if (testSequence == QKeySequence::SelectNextChar) {
1556 event->accept();
1557 } else if (testSequence == QKeySequence::MoveToPreviousChar) {
1559 event->accept();
1560 } else if (testSequence == QKeySequence::SelectPreviousChar) {
1562 event->accept();
1563 } else if (testSequence == QKeySequence::MoveToNextLine) {
1565 event->accept();
1566 } else if (testSequence == QKeySequence::SelectNextLine) {
1568 event->accept();
1569 } else if (testSequence == QKeySequence::MoveToPreviousLine) {
1571 event->accept();
1572 } else if (testSequence == QKeySequence::SelectPreviousLine) {
1574 event->accept();
1575
1576 } else if (testSequence == QKeySequence::MoveToNextWord) {
1578 event->accept();
1579 } else if (testSequence == QKeySequence::SelectNextWord) {
1581 event->accept();
1582 } else if (testSequence == QKeySequence::MoveToPreviousWord) {
1584 event->accept();
1585 } else if (testSequence == QKeySequence::SelectPreviousWord) {
1587 event->accept();
1588
1589 } else if (testSequence == QKeySequence::MoveToStartOfLine) {
1591 event->accept();
1592 } else if (testSequence == QKeySequence::SelectStartOfLine) {
1594 event->accept();
1595 } else if (testSequence == QKeySequence::MoveToEndOfLine) {
1597 event->accept();
1598 } else if (testSequence == QKeySequence::SelectEndOfLine) {
1600 event->accept();
1601
1602 } else if (testSequence == QKeySequence::MoveToStartOfBlock
1603 || testSequence == QKeySequence::MoveToStartOfDocument) {
1605 event->accept();
1606 } else if (testSequence == QKeySequence::SelectStartOfBlock
1607 || testSequence == QKeySequence::SelectStartOfDocument) {
1609 event->accept();
1610
1611 } else if (testSequence == QKeySequence::MoveToEndOfBlock
1612 || testSequence == QKeySequence::MoveToEndOfDocument) {
1614 event->accept();
1615 } else if (testSequence == QKeySequence::SelectEndOfBlock
1616 || testSequence == QKeySequence::SelectEndOfDocument) {
1618 event->accept();
1619
1620 }else if (testSequence == QKeySequence::DeleteStartOfWord) {
1622 event->accept();
1623 } else if (testSequence == QKeySequence::DeleteEndOfWord) {
1625 event->accept();
1626 } else if (testSequence == QKeySequence::DeleteEndOfLine) {
1628 event->accept();
1629 } else if (testSequence == QKeySequence::DeleteCompleteLine) {
1631 event->accept();
1632 } else if (testSequence == QKeySequence::Backspace) {
1634 event->accept();
1635 } else if (testSequence == QKeySequence::Delete) {
1637 event->accept();
1638
1639 } else if (testSequence == QKeySequence::InsertLineSeparator
1640 || testSequence == QKeySequence::InsertParagraphSeparator) {
1641 insertText("\n");
1642 event->accept();
1643 } else {
1644 event->ignore();
1645 }
1646}
@ 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 699 of file SvgTextCursor.cpp.

700{
701 if (d->shape) {
702 int start = -1;
703 int end = -1;
704 if (!paragraphOnly) {
705 start = d->pos;
706 end = d->anchor;
707 }
708 if (selectWord && d->pos == d->anchor) {
709 const int finalPos = d->shape->posForIndex(d->shape->plainText().size());
710 start = qBound(0, moveModeResult(MoveWordStart, d->pos, d->visualNavigation), finalPos);
711 end = qBound(0, moveModeResult(MoveWordEnd, d->pos, d->visualNavigation), finalPos);
712 }
713 KUndo2Command *cmd = new SvgTextMergePropertiesRangeCommand(d->shape, props, start, end, removeProperties);
715 }
716}
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 592 of file SvgTextCursor.cpp.

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

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 2023 of file SvgTextCursor.cpp.

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

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 1393 of file SvgTextCursor.cpp.

1394{
1395 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(d);
1396 d->pos = pos;
1397 d->anchor = anchor;
1398 updateCursor();
1401}
void updateTypeSettingDecoration()

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

◆ notifyMarkupChanged()

void SvgTextCursor::notifyMarkupChanged ( )
overridevirtual

Implements KoSvgTextShape::TextCursorChangeListener.

Definition at line 1403 of file SvgTextCursor.cpp.

1404{
1405 d->interface->emitSelectionChange();
1406 d->interface->emitCharacterSelectionChange();
1407 updateCursor();
1410}

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 1380 of file SvgTextCursor.cpp.

1381{
1382 Q_UNUSED(type);
1383 Q_UNUSED(shape);
1384 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(d);
1385 d->pos = d->shape->posForIndex(d->posIndex);
1386 d->anchor = d->shape->posForIndex(d->anchorIndex);
1387 updateCursor(true);
1391}
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 )

Paint all decorations and blinkingcursors.

Definition at line 839 of file SvgTextCursor.cpp.

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

768{
769 bool success = d->pasteRichText? pasteRichText(): pastePlainText();
770 return success;
771}
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 809 of file SvgTextCursor.cpp.

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

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 554 of file SvgTextCursor.cpp.

555{
556 if (!d->shape) return 0;
557
559 d->shape->getPositionsAndRotationsForRange(d->pos, d->anchor);
560 if (infos.size() < 1) return 0;
561
562 const QRectF roi = d->shape->documentToShape(regionOfInterest);
563
564 for (auto it = infos.begin(); it != infos.end(); it++) {
565 const int currentPos = (d->pos == d->anchor)? -1 :d->shape->posForIndex(it->logicalIndex);
566 const KoSvgTextProperties props = d->shape->propertiesForPos(currentPos, true);
568
569 KoSvgText::FontMetrics metrics = (d->pos == d->anchor)? props.metrics(true, true): it->metrics;
570 const bool isHorizontal = d->shape->writingMode() == KoSvgText::HorizontalTB;
571
572 const qreal scaleMetrics = props.fontSize().value/qreal(metrics.fontSize);
573 const int lineGap = lineHeight.isNormal? metrics.lineGap: (lineHeight.length.value/scaleMetrics)-(metrics.ascender-metrics.descender);
574
575 QTransform t = QTransform::fromTranslate(it->finalPos.x(), it->finalPos.y());
576 t.rotate(it->rotateDeg);
577
578 const QMap<SvgTextCursor::TypeSettingModeHandle, int> types
579 = typeSettingBaselinesFromMetrics(metrics, lineGap, isHorizontal);
580
581 const int metric = types.value(handle);
582 QPointF offset = isHorizontal? QPointF(0, -(metric*scaleMetrics)): QPointF(metric*scaleMetrics, 0);
583 QLineF line = t.map(QLineF(offset, offset+it->advance));
584 if (KisAlgebra2D::intersectLineRect(line, roi.toAlignedRect(), false)) return d->shape->posForIndex(it->logicalIndex);
585 }
586
587 return 0;
588}
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 683 of file SvgTextCursor.cpp.

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

References d.

◆ propertiesForShape()

QList< KoSvgTextProperties > SvgTextCursor::propertiesForShape ( ) const

propertiesForShape

Returns
properties for the current shape.

Definition at line 693 of file SvgTextCursor.cpp.

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

References d.

◆ propertyAction

void SvgTextCursor::propertyAction ( )
privateslot

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

Definition at line 1351 of file SvgTextCursor.cpp.

1352{
1353 QAction *action = dynamic_cast<QAction*>(QObject::sender());
1354 if (!action || !d->shape) return;
1355
1356 const QList<KoSvgTextProperties> p = d->shape->propertiesForRange(qMin(d->pos, d->anchor), qMax(d->pos, d->anchor));
1358 if (properties.isEmpty()) return;
1359 mergePropertiesIntoSelection(properties);
1360}
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 1674 of file SvgTextCursor.cpp.

1675{
1676 if (SvgTextShortCuts::configureAction(action, name)) {
1677 d->actions.append(action);
1678 connect(action, SIGNAL(triggered(bool)), this, SLOT(propertyAction()));
1679 return true;
1680 } else if (name == "svg_insert_special_character") {
1681 d->actions.append(action);
1682 connect(action, SIGNAL(triggered(bool)), this, SIGNAL(sigOpenGlyphPalette()));
1683 return true;
1684 } else if (name == "svg_paste_rich_text") {
1685 d->actions.append(action);
1686 connect(action, SIGNAL(triggered(bool)), this, SLOT(pasteRichText()));
1687 return true;
1688 } else if (name == "svg_paste_plain_text") {
1689 d->actions.append(action);
1690 connect(action, SIGNAL(triggered(bool)), this, SLOT(pastePlainText()));
1691 return true;
1692 } else if (name == "svg_remove_transforms_from_range") {
1693 d->actions.append(action);
1694 connect(action, SIGNAL(triggered(bool)), this, SLOT(removeTransformsFromRange()));
1695 return true;
1696 } else if (name == "svg_clear_formatting") {
1697 d->actions.append(action);
1698 connect(action, SIGNAL(triggered(bool)), this, SLOT(clearFormattingAction()));
1699 return true;
1700 } else if (action) {
1701 d->actions.append(action);
1702 return true;
1703 }
1704 return false;
1705}
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 660 of file SvgTextCursor.cpp.

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

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 718 of file SvgTextCursor.cpp.

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

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 724 of file SvgTextCursor.cpp.

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

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 638 of file SvgTextCursor.cpp.

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

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 821 of file SvgTextCursor.cpp.

822{
823 if (d->shape) {
824 KUndo2Command *cmd = new SvgTextRemoveTransformsFromRange(d->shape, d->pos, d->anchor);
826 }
827}
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 320 of file SvgTextCursor.cpp.

321{
322 d->cursorFlash.setInterval(cursorFlash/2);
323 d->cursorFlashLimit.setInterval(cursorFlashLimit);
324 d->cursorWidth = cursorWidth;
325 d->drawCursorInAdditionToSelection = drawCursorInAdditionToSelection;
326 connect(&d->cursorFlash, SIGNAL(timeout()), this, SLOT(blinkCursor()));
327 connect(&d->cursorFlashLimit, SIGNAL(timeout()), this, SLOT(stopBlinkCursor()));
328}
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 507 of file SvgTextCursor.cpp.

508{
509 if (handle == NoHandle) return false;
510 if (!d->typeSettingDecor.testBaselines(d->lastKnownModifiers)) return false;
512 if (handle == Ascender) {
514 } else if (handle == Descender) {
516 } else if (handle == BaselineAlphabetic) {
518 } else if (handle == BaselineIdeographic) {
520 } else if (handle == BaselineHanging) {
522 } else if (handle == BaselineMiddle) {
523 baseline = KoSvgText::BaselineMiddle;
524 } else if (handle == BaselineMathematical) {
526 } else if (handle == BaselineCentral) {
528 } else {
529 return false;
530 }
532 props.setProperty(KoSvgTextProperties::DominantBaselineId, QVariant::fromValue(baseline));
533 props.setProperty(KoSvgTextProperties::AlignmentBaselineId, QVariant::fromValue(baseline));
535 return true;
536}
@ 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 441 of file SvgTextCursor.cpp.

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

References d.

◆ setPasteRichTextByDefault()

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

setPasteRichText

Parameters
pasteRichText– whether to paste rich text when possible.

Definition at line 335 of file SvgTextCursor.cpp.

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

References d, and pasteRichText.

◆ setPos()

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

Set the pos and the anchor.

Definition at line 356 of file SvgTextCursor.cpp.

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

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 365 of file SvgTextCursor.cpp.

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

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 296 of file SvgTextCursor.cpp.

297{
298 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(d);
299 inputQueryUpdateBlocker.setChangeVisibility(true);
300
301 if (d->shape) {
303 d->shape->removeShapeChangeListener(this);
304 }
305 d->shape = textShape;
306 if (d->shape) {
307 d->shape->addShapeChangeListener(this);
309 d->pos = d->shape->posForIndex(d->shape->plainText().size());
311 } else {
312 d->pos = 0;
313 }
314 d->anchor = 0;
315 updateCursor(true);
317 d->interface->emitSelectionChange();
318}
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 436 of file SvgTextCursor.cpp.

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

References d.

◆ setTypeSettingModeActive()

void SvgTextCursor::setTypeSettingModeActive ( bool activate)

Set type setting mode active.

Definition at line 340 of file SvgTextCursor.cpp.

341{
342 d->typeSettingMode = activate;
344}

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 330 of file SvgTextCursor.cpp.

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

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 1280 of file SvgTextCursor.cpp.

1281{
1282 d->cursorFlash.stop();
1283 d->cursorFlashLimit.stop();
1284 d->cursorVisible = true;
1285 if (d->shape) {
1286 Q_EMIT updateCursorDecoration(d->shape->shapeToDocument(d->cursorShape.boundingRect()) | d->oldCursorRect);
1287 }
1288}

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 1707 of file SvgTextCursor.cpp.

1708{
1709 return d->interface;
1710}

References d.

◆ typeSettingHandleAtPos()

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

Get typeSettingMode handle for text;.

Definition at line 392 of file SvgTextCursor.cpp.

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

2143{
2144 // Only update canvas resources when there's no selection.
2145 // This relies on Krita not setting anything on the text when there's no selection.
2146 if (d->shape && d->canvas->resourceManager() && d->pos == d->anchor) {
2147 KoSvgTextProperties props = hasSelection()? d->shape->propertiesForPos(qMin(d->pos, d->anchor), true): d->shape->textProperties();
2148 KoColorBackground *bg = dynamic_cast<KoColorBackground *>(props.background().data());
2149 if (bg && props.hasProperty(KoSvgTextProperties::FillId)) {
2150 KoColor c;
2151 c.fromQColor(bg->color());
2152 c.setOpacity(1.0);
2153 if (c != d->canvas->resourceManager()->foregroundColor()) {
2154 d->canvas->resourceManager()->setForegroundColor(c);
2155 }
2156 }
2157 KoShapeStroke *stroke = dynamic_cast<KoShapeStroke *>(props.stroke().data());
2158 if (stroke && stroke->isVisible() && stroke->color().isValid() && props.hasProperty(KoSvgTextProperties::StrokeId)) {
2159 KoColor c;
2160 c.fromQColor(stroke->color());
2161 c.setOpacity(1.0);
2162 if (c != d->canvas->resourceManager()->backgroundColor()) {
2163 d->canvas->resourceManager()->setBackgroundColor(c);
2164 }
2165 }
2166
2167 Q_FOREACH (QAction *action, d->actions) {
2168 // Blocking signals so that we don't get a toggle action while evaluating the checked-ness.
2169 action->blockSignals(true);
2170 const QList<KoSvgTextProperties> r = d->shape->propertiesForRange(qMin(d->pos, d->anchor), qMax(d->pos, d->anchor), true);
2171 if (action->isCheckable() && SvgTextShortCuts::possibleActions().contains(action->objectName())) {
2172 const bool checked = SvgTextShortCuts::actionEnabled(action, r);
2173 if (action->isChecked() != checked) {
2174 action->setChecked(checked);
2175 }
2176 }
2177 action->blockSignals(false);
2178 }
2179 }
2180}
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 1712 of file SvgTextCursor.cpp.

1713{
1714 if (d->shape) {
1715 d->oldCursorRect = d->shape->shapeToDocument(d->cursorShape.boundingRect());
1716 d->posIndex = d->shape->indexForPos(d->pos);
1717 d->anchorIndex = d->shape->indexForPos(d->anchor);
1718 emit selectionChanged();
1720 }
1721 d->cursorColor = QColor();
1722 d->cursorShape = d->shape? d->shape->cursorForPos(d->pos, d->cursorCaret, d->cursorColor): QPainterPath();
1723
1724 if (!d->blockQueryUpdates) {
1725 qApp->inputMethod()->update(Qt::ImQueryInput);
1726 }
1727 d->interface->emitCharacterSelectionChange();
1728 if (!(d->canvas->canvasWidget() && d->canvas->canvasController())) {
1729 // Mockcanvas in the tests has neither.
1730 return;
1731 }
1732 if (d->shape && !firstUpdate) {
1733 QRectF rect = d->shape->shapeToDocument(d->cursorShape.boundingRect());
1734 d->canvas->canvasController()->ensureVisibleDoc(rect, false);
1735 }
1736 if (d->canvas->canvasWidget()->hasFocus()) {
1737 d->cursorFlash.start();
1738 d->cursorFlashLimit.start();
1739 d->cursorVisible = false;
1740 blinkCursor();
1741 }
1742}
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 1758 of file SvgTextCursor.cpp.

1759{
1760 if (d->shape) {
1761 d->oldIMEDecorationRect = d->shape->shapeToDocument(d->IMEDecoration.boundingRect());
1762 KoSvgText::TextDecorations decor;
1763 decor.setFlag(KoSvgText::DecorationUnderline, true);
1764 d->IMEDecoration = QPainterPath();
1765 if (d->preEditCommand) {
1766 Q_FOREACH(const IMEDecorationInfo info, d->styleMap) {
1767
1768 int startIndex = d->shape->indexForPos(d->preEditStart) + info.start;
1769 int endIndex = startIndex + info.length;
1770 qreal minimum = d->canvas->viewToDocument(QPointF(1, 1)).x();
1771 d->IMEDecoration.addPath(d->shape->underlines(d->shape->posForIndex(startIndex),
1772 d->shape->posForIndex(endIndex),
1773 info.decor,
1774 info.style,
1775 minimum,
1776 info.thick));
1777 d->IMEDecoration.setFillRule(Qt::WindingFill);
1778 }
1779 }
1780
1781 Q_EMIT updateCursorDecoration(d->shape->shapeToDocument(d->IMEDecoration.boundingRect()) | d->oldIMEDecorationRect);
1782 }
1783}
@ 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 1290 of file SvgTextCursor.cpp.

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

References d, and pos.

◆ updateModifiers()

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

Definition at line 1648 of file SvgTextCursor.cpp.

1649{
1650 d->lastKnownModifiers = modifiers;
1652}

References d, and updateTypeSettingDecoration().

◆ updateSelection()

void SvgTextCursor::updateSelection ( )
private

Definition at line 1744 of file SvgTextCursor.cpp.

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

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 1848 of file SvgTextCursor.cpp.

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

447{
448 if (d->shape) {
449 d->typeSettingDecor.handlesEnabled = ((d->shape->textType() == KoSvgTextShape::PreformattedText
450 || d->shape->textType() == KoSvgTextShape::PrePositionedText)
451 && !(d->shape->topLevelNodeForPos(d->pos).textPath()));
452 }
453}
@ 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 246 of file SvgTextCursor.cpp.

◆ anchor

int SvgTextCursor::anchor = 0

Definition at line 201 of file SvgTextCursor.cpp.

◆ anchorCaret

QLineF SvgTextCursor::anchorCaret

Definition at line 213 of file SvgTextCursor.cpp.

◆ anchorIndex

int SvgTextCursor::anchorIndex = 0

Definition at line 222 of file SvgTextCursor.cpp.

◆ blockQueryUpdates

bool SvgTextCursor::blockQueryUpdates = false

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

Definition at line 242 of file SvgTextCursor.cpp.

◆ canvas

KoCanvasBase* SvgTextCursor::canvas

Definition at line 198 of file SvgTextCursor.cpp.

◆ cursorCaret

QLineF SvgTextCursor::cursorCaret

Definition at line 212 of file SvgTextCursor.cpp.

◆ cursorColor

QColor SvgTextCursor::cursorColor

Definition at line 210 of file SvgTextCursor.cpp.

◆ cursorFlash

QTimer SvgTextCursor::cursorFlash

Definition at line 204 of file SvgTextCursor.cpp.

◆ cursorFlashLimit

QTimer SvgTextCursor::cursorFlashLimit

Definition at line 205 of file SvgTextCursor.cpp.

◆ cursorShape

QPainterPath SvgTextCursor::cursorShape

Definition at line 209 of file SvgTextCursor.cpp.

◆ cursorVisible

bool SvgTextCursor::cursorVisible = false

Definition at line 206 of file SvgTextCursor.cpp.

◆ cursorWidth

int SvgTextCursor::cursorWidth = 1

Definition at line 214 of file SvgTextCursor.cpp.

◆ d

const QScopedPointer<Private> SvgTextCursor::d
private

Definition at line 393 of file SvgTextCursor.h.

◆ drawCursorInAdditionToSelection

bool SvgTextCursor::drawCursorInAdditionToSelection = false

Definition at line 215 of file SvgTextCursor.cpp.

◆ drawTypeSettingHandle

bool SvgTextCursor::drawTypeSettingHandle = true

Definition at line 231 of file SvgTextCursor.cpp.

◆ handleRadius

qreal SvgTextCursor::handleRadius = 7

Definition at line 232 of file SvgTextCursor.cpp.

◆ hasFocus

bool SvgTextCursor::hasFocus = false

Definition at line 207 of file SvgTextCursor.cpp.

◆ hoveredTypeSettingHandle

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

Definition at line 230 of file SvgTextCursor.cpp.

◆ IMEDecoration

QPainterPath SvgTextCursor::IMEDecoration

The decorations for the current preedit string.

Definition at line 240 of file SvgTextCursor.cpp.

◆ interface

SvgTextCursorPropertyInterface* SvgTextCursor::interface {nullptr}

Definition at line 244 of file SvgTextCursor.cpp.

244{nullptr};

◆ isAddingCommand

bool SvgTextCursor::isAddingCommand = false

Definition at line 199 of file SvgTextCursor.cpp.

◆ lastKnownModifiers

Qt::KeyboardModifiers SvgTextCursor::lastKnownModifiers

Definition at line 227 of file SvgTextCursor.cpp.

◆ oldCursorRect

QRectF SvgTextCursor::oldCursorRect

Definition at line 211 of file SvgTextCursor.cpp.

◆ oldIMEDecorationRect

QRectF SvgTextCursor::oldIMEDecorationRect

Update Rectangle of previous decoration.

Definition at line 241 of file SvgTextCursor.cpp.

◆ oldSelectionRect

QRectF SvgTextCursor::oldSelectionRect

Definition at line 217 of file SvgTextCursor.cpp.

◆ oldTypeSettingRect

QRectF SvgTextCursor::oldTypeSettingRect

Definition at line 233 of file SvgTextCursor.cpp.

◆ pasteRichText

bool SvgTextCursor::pasteRichText = true

Definition at line 225 of file SvgTextCursor.cpp.

◆ pos

int SvgTextCursor::pos = 0

Definition at line 200 of file SvgTextCursor.cpp.

◆ posIndex

int SvgTextCursor::posIndex = 0

Definition at line 221 of file SvgTextCursor.cpp.

◆ preEditCommand

SvgTextInsertCommand* SvgTextCursor::preEditCommand {nullptr}

PreEdit string as an command provided by the input method.

Definition at line 236 of file SvgTextCursor.cpp.

236{nullptr};

◆ preEditLength

int SvgTextCursor::preEditLength = -1

Length of the preEditString.

Definition at line 238 of file SvgTextCursor.cpp.

◆ preEditStart

int SvgTextCursor::preEditStart = -1

Start of the preEdit string as a cursor pos.

Definition at line 237 of file SvgTextCursor.cpp.

◆ resourceManagerAcyclicConnector

KisAcyclicSignalConnector SvgTextCursor::resourceManagerAcyclicConnector

Definition at line 248 of file SvgTextCursor.cpp.

◆ selection

QPainterPath SvgTextCursor::selection

Definition at line 216 of file SvgTextCursor.cpp.

◆ shape

KoSvgTextShape * SvgTextCursor::shape {nullptr}

Definition at line 202 of file SvgTextCursor.cpp.

202{nullptr};

◆ styleMap

QVector<IMEDecorationInfo> SvgTextCursor::styleMap

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

Definition at line 239 of file SvgTextCursor.cpp.

◆ typeSettingDecor

TypeSettingDecorInfo SvgTextCursor::typeSettingDecor

Definition at line 234 of file SvgTextCursor.cpp.

◆ typeSettingMode

bool SvgTextCursor::typeSettingMode = false

Definition at line 229 of file SvgTextCursor.cpp.

◆ visualNavigation

bool SvgTextCursor::visualNavigation = true

Definition at line 224 of file SvgTextCursor.cpp.


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