37#include <QApplication>
39#include <QKeySequence>
42#include <QInputMethodEvent>
57 if (s == QTextCharFormat::DotLine) {
59 }
else if (s == QTextCharFormat::DashUnderline) {
61 }
else if (s == QTextCharFormat::WaveUnderline) {
63 }
else if (s == QTextCharFormat::SpellCheckUnderline) {
74 if (format.hasProperty(QTextFormat::FontUnderline)) {
77 if (format.hasProperty(QTextFormat::FontOverline)) {
80 if (format.hasProperty(QTextFormat::FontStrikeOut)) {
84 if (format.hasProperty(QTextFormat::TextUnderlineStyle)) {
93 if (format.hasProperty(QTextFormat::BackgroundBrush)) {
94 thick = format.background().isOpaque();
113 QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>
baselines;
114 QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>
paths;
117 QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>
parentPaths;
124 for (
int i = 0; i<
paths.values().size(); i++) {
125 total |=
paths.values().at(i).boundingRect();
127 for (
int i = 0; i<
baselines.values().size(); i++) {
128 total |=
baselines.values().at(i).boundingRect();
130 for (
int i = 0; i<
parentPaths.values().size(); i++) {
131 total |=
parentPaths.values().at(i).boundingRect();
136 total |=
edges.boundingRect();
137 QRectF
rect(0, 0, handleRadius, handleRadius);
146 return (modifiers & Qt::ShiftModifier);
158 , m_unblockQueryUpdates(!
std::exchange(d->blockQueryUpdates, true))
170 QInputMethod *inputMethod = QGuiApplication::inputMethod();
172 if (m_unblockQueryUpdates) {
173 m_d->blockQueryUpdates =
false;
174 inputMethod->update(Qt::ImQueryInput);
177 if (m_changeVisibility) {
178 inputMethod->setVisible(m_d->shape !=
nullptr);
185 m_changeVisibility = changeVisibility;
191 bool m_changeVisibility =
false;
195 bool isAddingCommand =
false;
202 bool cursorVisible =
false;
203 bool hasFocus =
false;
211 bool drawCursorInAdditionToSelection =
false;
220 bool visualNavigation =
true;
221 bool pasteRichText =
true;
225 bool typeSettingMode =
false;
227 bool drawTypeSettingHandle =
true;
228 qreal handleRadius = 7;
233 int preEditStart = -1;
234 int preEditLength = -1;
238 bool blockQueryUpdates =
false;
252 if (
d->canvas->canvasController()) {
255 connect(
d->canvas->canvasController()->proxyObject,
256 SIGNAL(moveDocumentOffset(QPointF, QPointF)),
259 connect(
d->canvas->canvasController()->proxyObject,
260 SIGNAL(effectiveZoomChanged(qreal)),
263 connect(
d->canvas->canvasController()->proxyObject,
264 SIGNAL(documentRotationChanged(qreal)),
267 connect(
d->canvas->canvasController()->proxyObject,
268 SIGNAL(documentMirrorStatusChanged(
bool,
bool)),
271 d->resourceManagerAcyclicConnector.connectBackwardResourcePair(
274 d->resourceManagerAcyclicConnector.connectForwardVoid(
d->interface, SIGNAL(textCharacterSelectionChanged()),
this, SLOT(
updateCanvasResources()));
282 d->cursorFlash.stop();
283 d->cursorFlashLimit.stop();
294 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(
d);
295 inputQueryUpdateBlocker.setChangeVisibility(
true);
299 d->shape->removeShapeChangeListener(
this);
301 d->shape = textShape;
305 d->pos =
d->shape->posForIndex(
d->shape->plainText().size());
313 d->interface->emitSelectionChange();
322 connect(&
d->cursorFlash, SIGNAL(timeout()),
this, SLOT(
blinkCursor()));
323 connect(&
d->cursorFlashLimit, SIGNAL(timeout()),
this, SLOT(
stopBlinkCursor()));
328 d->visualNavigation = visualMode;
338 d->typeSettingMode = activate;
354 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(
d);
364 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(
d);
365 int pos =
d->shape->posForPointLineSensitive(
d->shape->documentToShape(point));
366 if (
d->preEditCommand) {
367 int start =
d->shape->indexForPos(
d->preEditStart);
368 int end = start +
d->preEditLength;
371 qApp->inputMethod()->invokeAction(QInputMethod::Click,
posIndex - start);
378 const int finalPos =
d->shape->posForIndex(
d->shape->plainText().size());
379 d->pos = qBound(0,
pos, finalPos);
380 if (moveAnchor ||
d->anchor < 0 ||
d->anchor > finalPos) {
392 if (!(
d->typeSettingMode &&
d->shape &&
d->canvas))
return handle;
394 const QRectF roiInShape =
d->shape->absoluteTransformation().inverted().mapRect(regionOfInterest);
396 if (
d->typeSettingDecor.handlesEnabled) {
397 if (roiInShape.contains(
d->typeSettingDecor.handles.first)) {
399 }
else if (roiInShape.contains(
d->typeSettingDecor.handles.second)) {
403 if (handle !=
NoHandle)
return handle;
404 if (!
d->typeSettingDecor.boundingRect(
d->handleRadius).intersects(roiInShape))
return handle;
406 qreal closest = std::numeric_limits<qreal>::max();
407 QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath> paths
408 =
d->typeSettingDecor.testBaselines(
d->lastKnownModifiers)?
d->typeSettingDecor.baselines:
d->typeSettingDecor.paths;
410 const QPainterPath path = paths.value(baseline);
411 if (!path.intersects(roiInShape))
continue;
414 Q_FOREACH(
const QPolygonF poly, polys) {
415 if (poly.size() < 2)
continue;
416 for (
int i = 1; i < poly.size(); i++) {
417 QLineF l(poly.at(i-1), poly.at(i));
422 d->typeSettingDecor.closestBaselinePoint =
434 d->hoveredTypeSettingHandle = hovered;
439 d->drawTypeSettingHandle = draw;
447 && !(
d->shape->topLevelNodeForPos(
d->pos).textPath()));
453 if (
d->hoveredTypeSettingHandle ==
StartPos ||
454 d->hoveredTypeSettingHandle ==
StartPos ||
455 d->typeSettingDecor.testBaselines(
d->lastKnownModifiers)) {
456 return Qt::ArrowCursor;
457 }
else if (
d->shape) {
460 return Qt::ArrowCursor;
465 bool baseline =
d->typeSettingDecor.testBaselines(
d->lastKnownModifiers);
468 return i18nc(
"Type setting mode line name",
"Text Top");
470 return i18nc(
"Type setting mode line name",
"Font Size");
474 return i18nc(
"Type setting mode line name",
"Text Bottom");
476 return i18nc(
"Type setting mode line name",
"Font Size");
479 return i18nc(
"Type setting mode line name",
"Alphabetic");
481 return i18nc(
"Type setting mode line name",
"Ideographic");
483 return i18nc(
"Type setting mode line name",
"Hanging");
485 return i18nc(
"Type setting mode line name",
"Middle");
487 return i18nc(
"Type setting mode line name",
"Mathematical");
489 return i18nc(
"Type setting mode line name",
"Central");
491 return i18nc(
"Type setting mode line name",
"Line Height");
494 return i18nc(
"Type setting mode line name",
"Current Baseline");
496 return i18nc(
"Type setting mode line name",
"Baseline Shift");
505 if (handle ==
NoHandle)
return false;
506 if (!
d->typeSettingDecor.testBaselines(
d->lastKnownModifiers))
return false;
535 return QMap<SvgTextCursor::TypeSettingModeHandle, int> {
552 if (!
d->shape)
return 0;
555 d->shape->getPositionsAndRotationsForRange(
d->pos,
d->anchor);
556 if (infos.size() < 1)
return 0;
558 const QRectF roi =
d->shape->documentToShape(regionOfInterest);
560 for (
auto it = infos.begin(); it != infos.end(); it++) {
561 const int currentPos = (
d->pos ==
d->anchor)? -1 :
d->shape->posForIndex(it->logicalIndex);
568 const qreal scaleMetrics = props.
fontSize().
value/qreal(metrics.fontSize);
569 const int lineGap = lineHeight.
isNormal? metrics.lineGap: (lineHeight.
length.
value/scaleMetrics)-(metrics.ascender-metrics.descender);
571 QTransform t = QTransform::fromTranslate(it->finalPos.x(), it->finalPos.y());
572 t.rotate(it->rotateDeg);
574 const QMap<SvgTextCursor::TypeSettingModeHandle, int> types
577 const int metric = types.value(handle);
578 QPointF offset = isHorizontal? QPointF(0, -(metric*scaleMetrics)): QPointF(metric*scaleMetrics, 0);
579 QLineF line = t.map(QLineF(offset, offset+it->advance));
592 const int finalPos =
d->shape->posForIndex(
d->shape->plainText().size());
645 int posStart = qMin(posA, posB);
646 int posEnd = qMax(posA, posB);
647 int indexEnd =
d->shape->indexForPos(posEnd);
648 int length = indexEnd -
d->shape->indexForPos(posStart);
664 int lastIndex =
d->shape->indexForPos(
d->pos);
674 return QPair<KoSvgTextProperties, KoSvgTextProperties>(
d->shape->propertiesForPos(
d->pos),
d->shape->propertiesForPos(
d->pos,
true));
676 return QPair<KoSvgTextProperties, KoSvgTextProperties>();
684 start = qMin(
d->pos,
d->anchor);
685 end = qMax(
d->pos,
d->anchor);
686 return d->shape->propertiesForRange(start, end);
692 return {
d->shape->propertiesForRange(-1, -1)};
700 if (!paragraphOnly) {
704 if (selectWord &&
d->pos ==
d->anchor) {
705 const int finalPos =
d->shape->posForIndex(
d->shape->plainText().size());
724 if (
d->anchor !=
d->pos) {
725 int end =
d->shape->indexForPos(qMax(
d->anchor,
d->pos));
726 int length =
d->shape->indexForPos(qMax(
d->anchor,
d->pos)) -
d->shape->indexForPos(qMin(
d->anchor,
d->pos));
736 int start =
d->shape->indexForPos(qMin(
d->anchor,
d->pos));
737 int length =
d->shape->indexForPos(qMax(
d->anchor,
d->pos)) - start;
738 QString copied =
d->shape->plainText().mid(start,
length);
739 std::unique_ptr<KoSvgTextShape> copy =
d->shape->copyRange(start,
length);
740 QClipboard *cb = QApplication::clipboard();
747 QMimeData *svgData =
new QMimeData();
749 QString svgDoc = QString(
"<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"2.0\">%1\n%2</svg>").arg(styles).arg(svg);
750 svgData->setData(QLatin1String(
"image/svg+xml"), svgDoc.toUtf8());
752 svgData->setText(copied);
754 svgData->setHtml(html);
755 cb->setMimeData(svgData);
771 bool success =
false;
773 QClipboard *cb = QApplication::clipboard();
774 const QMimeData *mimeData = cb->mimeData();
778 while (shapes.size() > 0) {
785 }
else if (mimeData->hasHtml()) {
786 QString html = mimeData->html();
791 if (converter.convertFromHtml(html, &svg, &styles)
792 && converter.convertFromSvg(svg, styles,
d->shape->boundingRect(), 72.0) ) {
807 bool success =
false;
808 QClipboard *cb = QApplication::clipboard();
809 const QMimeData *mimeData = cb->mimeData();
810 if (mimeData->hasText()) {
839 gc.setTransform(
d->shape->absoluteTransformation(),
true);
841 if (
d->pos !=
d->anchor && !
d->typeSettingMode) {
844 QBrush brush(selectionColor);
845 gc.fillPath(
d->selection, brush);
849 if ( (
d->drawCursorInAdditionToSelection ||
d->pos ==
d->anchor)
850 &&
d->cursorVisible) {
852 pen.setCosmetic(
true);
853 QColor c =
d->cursorColor.isValid()?
d->cursorColor: Qt::black;
855 pen.setWidth((
d->cursorWidth + 2) * decorationThickness);
857 gc.drawPath(
d->cursorShape);
859 pen.setWidth(
d->cursorWidth * decorationThickness);
861 gc.drawPath(
d->cursorShape);
865 if (
d->preEditCommand) {
867 QBrush brush(selectionColor);
869 gc.fillPath(
d->IMEDecoration, brush);
872 if (
d->typeSettingMode &&
d->drawTypeSettingHandle) {
874 QTransform painterTf = gc.transform();
879 QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath> paths
880 =
d->typeSettingDecor.testBaselines(
d->lastKnownModifiers)?
d->typeSettingDecor.baselines:
d->typeSettingDecor.paths;
881 QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath> parentPaths
882 =
d->typeSettingDecor.testBaselines(
d->lastKnownModifiers)?
d->typeSettingDecor.parentBaselines:
d->typeSettingDecor.parentPaths;
884 const QPainterPath
p = paths.value(handle);
885 const QPainterPath parent = parentPaths.value(handle);
886 if (
d->hoveredTypeSettingHandle == handle) {
892 QPen pen(selectionColor, decorationThickness, handle ==
BaselineShift? Qt::SolidLine: Qt::DashLine);
893 pen.setCosmetic(
true);
896 gc.drawPath(painterTf.map(parent));
897 gc.drawPath(painterTf.map(
p));
901 QPen pen(selectionColor, decorationThickness, Qt::SolidLine);
902 pen.setCosmetic(
true);
905 gc.drawPath(painterTf.map(
d->typeSettingDecor.edges));
909 if (
d->typeSettingDecor.handlesEnabled) {
915 QString name =
handleName(
d->hoveredTypeSettingHandle);
916 if (!name.isEmpty()) {
919 QFont font = gc.font();
920 font.setHintingPreference(QFont::PreferFullHinting);
921 textP.addText(painterTf.map(
d->typeSettingDecor.closestBaselinePoint).toPoint(), font, name);
924 pen.setCosmetic(
true);
925 pen.setWidth(decorationThickness);
928 gc.fillPath(textP, QBrush(selectionColor));
939 dbgTools <<
"receiving inputmethod query" << query;
945 return d->shape?
true:
false;
947 case Qt::ImCursorRectangle:
950 QPointF caret1(
d->cursorCaret.p1());
951 QPointF caret2(
d->cursorCaret.p2());
954 QRectF
rect = QRectF(caret1, caret2).normalized();
955 if (!
rect.isValid()) {
956 if (
rect.height() < 1) {
957 rect.adjust(0, -1, 0, 0);
959 if (
rect.width() < 1) {
960 rect.adjust(0, 0, 1, 0);
964 return rect.toAlignedRect();
967 case Qt::ImAnchorRectangle:
970 QPointF caret1(
d->anchorCaret.p1());
971 QPointF caret2(
d->anchorCaret.p2());
972 QRectF
rect = QRectF(caret1, caret2).normalized();
973 if (
rect.isEmpty()) {
974 if (
rect.height() < 1) {
975 rect.adjust(0, -1, 0, 0);
977 if (
rect.width() < 1) {
978 rect =
rect.adjusted(-1, 0, 0, 0).normalized();
981 return rect.toAlignedRect();
985 case Qt::ImAbsolutePosition:
986 case Qt::ImCursorPosition:
988 return d->shape->indexForPos(
d->pos);
991 case Qt::ImSurroundingText:
993 QString surroundingText =
d->shape->plainText();
994 int preEditIndex =
d->preEditCommand?
d->shape->indexForPos(
d->preEditStart): 0;
995 surroundingText.remove(preEditIndex,
d->preEditLength);
996 return surroundingText;
999 case Qt::ImCurrentSelection:
1001 QString surroundingText =
d->shape->plainText();
1002 int preEditIndex =
d->preEditCommand?
d->shape->indexForPos(
d->preEditStart): 0;
1003 surroundingText.remove(preEditIndex,
d->preEditLength);
1004 int start =
d->shape->indexForPos(qMin(
d->anchor,
d->pos));
1005 int length =
d->shape->indexForPos(qMax(
d->anchor,
d->pos)) - start;
1006 return surroundingText.mid(start,
length);
1009 case Qt::ImTextBeforeCursor:
1011 int start =
d->shape->indexForPos(
d->pos);
1012 QString surroundingText =
d->shape->plainText();
1013 int preEditIndex =
d->preEditCommand?
d->shape->indexForPos(
d->preEditStart): 0;
1014 surroundingText.remove(preEditIndex,
d->preEditLength);
1015 return surroundingText.left(start);
1018 case Qt::ImTextAfterCursor:
1020 int start =
d->shape->indexForPos(
d->pos);
1021 QString surroundingText =
d->shape->plainText();
1022 int preEditIndex =
d->preEditCommand?
d->shape->indexForPos(
d->preEditStart): 0;
1023 surroundingText.remove(preEditIndex,
d->preEditLength);
1024 return surroundingText.right(start);
1027 case Qt::ImMaximumTextLength:
1030 case Qt::ImAnchorPosition:
1032 return d->shape->indexForPos(
d->anchor);
1038 return Qt::ImhMultiLine;
1042 case Qt::ImEnterKeyType:
1044 return Qt::EnterKeyDefault;
1056 dbgTools <<
"Commit:"<<
event->commitString() <<
"predit:"<<
event->preeditString();
1057 dbgTools <<
"Replacement:"<<
event->replacementStart() <<
event->replacementLength();
1059 QRectF updateRect =
d->shape?
d->shape->boundingRect(): QRectF();
1060 SvgTextShapeManagerBlocker blocker(
d->canvas->shapeManager());
1062 bool isGettingInput = !
event->commitString().isEmpty() || !
event->preeditString().isEmpty()
1063 ||
event->replacementLength() > 0;
1066 if (
d->preEditCommand) {
1067 d->preEditCommand->undo();
1068 d->preEditCommand = 0;
1069 d->preEditStart = -1;
1070 d->preEditLength = -1;
1071 updateRect |=
d->shape?
d->shape->boundingRect(): QRectF();
1074 if (!
d->shape || !isGettingInput) {
1076 d->canvas->shapeManager()->update(updateRect);
1081 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(
d);
1087 int originalPos =
d->pos;
1088 int index =
d->shape->indexForPos(
d->pos) +
event->replacementStart();
1089 d->pos =
d->shape->posForIndex(index);
1090 if (event->replacementLength() > 0) {
1092 index + event->replacementLength(),
1095 event->replacementLength(),
1101 if (!event->commitString().isEmpty()) {
1106 Q_FOREACH(
const QInputMethodEvent::Attribute attribute, event->attributes()) {
1107 if (attribute.type == QInputMethodEvent::Selection) {
1108 d->pos =
d->shape->posForIndex(attribute.start);
1109 int index =
d->shape->indexForPos(
d->pos);
1110 d->anchor =
d->shape->posForIndex(index + attribute.length);
1116 if (!event->preeditString().isEmpty()) {
1117 int index =
d->shape->indexForPos(
d->pos);
1119 d->preEditCommand->redo();
1120 d->preEditLength =
event->preeditString().size();
1121 d->preEditStart =
d->shape->posForIndex(index,
true);
1123 d->preEditCommand = 0;
1128 Q_FOREACH(
const QInputMethodEvent::Attribute attribute, event->attributes()) {
1129 dbgTools <<
"attribute: "<< attribute.type <<
"start: " << attribute.start
1130 <<
"length: " << attribute.length <<
"val: " << attribute.value;
1136 if (attribute.type == QInputMethodEvent::TextFormat) {
1137 QVariant val = attribute.value;
1138 QTextCharFormat form = val.value<QTextFormat>().toCharFormat();
1140 if (attribute.length == 0 || attribute.start < 0 || !attribute.value.isValid()) {
1147 for (
int i = 0; i <
styleMap.size(); i++) {
1148 if (attribute.start >=
styleMap.at(i).start
1152 if (attribute.start + attribute.length >
styleMap.at(i).start
1153 && attribute.start + attribute.length <=
styleMap.at(i).start +
styleMap.at(i).length) {
1158 if (positionA > -1 && positionA == positionB) {
1162 decoration3.
start = (attribute.start+attribute.length);
1164 decoration1.
length = attribute.start - decoration1.
start;
1165 decoration2.
start = attribute.start;
1166 decoration2.
length = attribute.length;
1167 if (decoration1.
length > 0) {
1169 if (decoration2.
length > 0) {
1171 styleMap.insert(positionA, decoration2);
1176 if (decoration3.
length > 0) {
1177 styleMap.insert(positionA + 1, decoration3);
1179 }
else if (positionA > -1 && positionB > -1
1180 && positionA != positionB) {
1185 decoration2.
length = (decoration1.
start + decoration1.
length) - attribute.start;
1186 decoration1.
length = attribute.start - decoration1.
start;
1187 decoration2.
start = attribute.start;
1189 decoration4.
start = (attribute.start+attribute.length);
1192 if (decoration1.
length > 0) {
1194 if (decoration2.
length > 0) {
1196 styleMap.insert(positionA, decoration2);
1202 if (decoration3.
length > 0) {
1204 if (decoration4.
length > 0) {
1205 styleMap.insert(positionB + 1, decoration4);
1213 if (positionA > -1 && !
styleMap.isEmpty()) {
1215 for(
int i = positionA; i <= positionB; i++) {
1223 decoration.
start = attribute.start;
1224 decoration.
length = attribute.length;
1232 }
else if (attribute.type == QInputMethodEvent::Cursor) {
1233 if (
d->preEditStart < 0) {
1236 int index =
d->shape->indexForPos(
d->preEditStart);
1237 d->pos =
d->shape->posForIndex(index + attribute.start);
1247 updateRect |=
d->shape->boundingRect();
1249 d->shape->updateAbsolute(updateRect);
1261 d->cursorVisible = !
d->cursorVisible;
1267 d->cursorFlash.stop();
1268 d->cursorFlashLimit.stop();
1269 d->cursorVisible =
true;
1278 if (!
d->canvas->canvasWidget()) {
1281 QPoint
pos =
d->canvas->canvasWidget()->mapTo(
d->canvas->canvasWidget()->window(), QPoint());
1282 QTransform widgetToWindow = QTransform::fromTranslate(
pos.x(),
pos.y());
1283 QTransform inputItemTransform = widgetToWindow;
1284 QRectF inputRect =
d->canvas->canvasWidget()->geometry();
1286 inputRect =
d->shape->outlineRect().normalized();
1287 QTransform shapeTransform =
d->shape->absoluteTransformation();
1288 QTransform docToView =
d->canvas->viewConverter()->documentToView();
1289 QTransform viewToWidget =
d->canvas->viewConverter()->viewToWidget();
1290 inputItemTransform = shapeTransform * docToView * viewToWidget * widgetToWindow;
1293 QInputMethod *inputMethod = QGuiApplication::inputMethod();
1294 inputMethod->setInputItemTransform(inputItemTransform);
1295 inputMethod->setInputItemRectangle(inputRect);
1296 if (!
d->blockQueryUpdates) {
1297 inputMethod->update(Qt::ImQueryInput);
1312 if (!bg->compareTo(shapeProps.
background().data())
1321 if (shapeStroke->isVisible()) {
1338 QAction *action =
dynamic_cast<QAction*
>(QObject::sender());
1339 if (!action || !
d->shape)
return;
1343 if (properties.
isEmpty())
return;
1351 QSet<KoSvgTextProperties::PropertyId> ids;
1362 return d->pos !=
d->anchor;
1369 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(
d);
1370 d->pos =
d->shape->posForIndex(
d->posIndex);
1371 d->anchor =
d->shape->posForIndex(
d->anchorIndex);
1380 Private::InputQueryUpdateBlocker inputQueryUpdateBlocker(
d);
1390 d->interface->emitSelectionChange();
1391 d->interface->emitCharacterSelectionChange();
1403 if (
d->preEditCommand) {
1409 bool select =
event->modifiers().testFlag(Qt::ShiftModifier);
1411 if (!((Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier) & event->modifiers())) {
1413 switch (event->key()) {
1430 case Qt::Key_Delete:
1434 case Qt::Key_Backspace:
1438 case Qt::Key_Return:
1447 if (event->isAccepted()) {
1465 int newKey =
event->key();
1470 newKey = Qt::Key_Right;
1473 newKey = Qt::Key_Left;
1483 newKey = Qt::Key_Down;
1486 newKey = Qt::Key_Up;
1489 newKey = Qt::Key_Left;
1492 newKey = Qt::Key_Right;
1500 newKey = Qt::Key_Up;
1503 newKey = Qt::Key_Down;
1506 newKey = Qt::Key_Left;
1509 newKey = Qt::Key_Right;
1516 QKeySequence testSequence(event->modifiers() | newKey);
1524 Q_FOREACH(QAction *action,
d->actions) {
1525 if (action->shortcut() == testSequence) {
1536 if (testSequence == QKeySequence::MoveToNextChar) {
1539 }
else if (testSequence == QKeySequence::SelectNextChar) {
1542 }
else if (testSequence == QKeySequence::MoveToPreviousChar) {
1545 }
else if (testSequence == QKeySequence::SelectPreviousChar) {
1548 }
else if (testSequence == QKeySequence::MoveToNextLine) {
1551 }
else if (testSequence == QKeySequence::SelectNextLine) {
1554 }
else if (testSequence == QKeySequence::MoveToPreviousLine) {
1557 }
else if (testSequence == QKeySequence::SelectPreviousLine) {
1561 }
else if (testSequence == QKeySequence::MoveToNextWord) {
1564 }
else if (testSequence == QKeySequence::SelectNextWord) {
1567 }
else if (testSequence == QKeySequence::MoveToPreviousWord) {
1570 }
else if (testSequence == QKeySequence::SelectPreviousWord) {
1574 }
else if (testSequence == QKeySequence::MoveToStartOfLine) {
1577 }
else if (testSequence == QKeySequence::SelectStartOfLine) {
1580 }
else if (testSequence == QKeySequence::MoveToEndOfLine) {
1583 }
else if (testSequence == QKeySequence::SelectEndOfLine) {
1587 }
else if (testSequence == QKeySequence::MoveToStartOfBlock
1588 || testSequence == QKeySequence::MoveToStartOfDocument) {
1591 }
else if (testSequence == QKeySequence::SelectStartOfBlock
1592 || testSequence == QKeySequence::SelectStartOfDocument) {
1596 }
else if (testSequence == QKeySequence::MoveToEndOfBlock
1597 || testSequence == QKeySequence::MoveToEndOfDocument) {
1600 }
else if (testSequence == QKeySequence::SelectEndOfBlock
1601 || testSequence == QKeySequence::SelectEndOfDocument) {
1605 }
else if (testSequence == QKeySequence::DeleteStartOfWord) {
1608 }
else if (testSequence == QKeySequence::DeleteEndOfWord) {
1611 }
else if (testSequence == QKeySequence::DeleteEndOfLine) {
1614 }
else if (testSequence == QKeySequence::DeleteCompleteLine) {
1617 }
else if (testSequence == QKeySequence::Backspace) {
1620 }
else if (testSequence == QKeySequence::Delete) {
1624 }
else if (testSequence == QKeySequence::InsertLineSeparator
1625 || testSequence == QKeySequence::InsertParagraphSeparator) {
1635 d->lastKnownModifiers = modifiers;
1641 return d->isAddingCommand;
1646 d->cursorFlash.start();
1647 d->cursorFlashLimit.start();
1648 d->cursorVisible =
false;
1655 d->hasFocus =
false;
1662 d->actions.append(action);
1663 connect(action, SIGNAL(triggered(
bool)),
this, SLOT(
propertyAction()));
1665 }
else if (name ==
"svg_insert_special_character") {
1666 d->actions.append(action);
1669 }
else if (name ==
"svg_paste_rich_text") {
1670 d->actions.append(action);
1671 connect(action, SIGNAL(triggered(
bool)),
this, SLOT(
pasteRichText()));
1673 }
else if (name ==
"svg_paste_plain_text") {
1674 d->actions.append(action);
1675 connect(action, SIGNAL(triggered(
bool)),
this, SLOT(
pastePlainText()));
1677 }
else if (name ==
"svg_remove_transforms_from_range") {
1678 d->actions.append(action);
1681 }
else if (name ==
"svg_clear_formatting") {
1682 d->actions.append(action);
1685 }
else if (action) {
1686 d->actions.append(action);
1694 return d->interface;
1700 d->oldCursorRect =
d->shape->shapeToDocument(
d->cursorShape.boundingRect());
1701 d->posIndex =
d->shape->indexForPos(
d->pos);
1702 d->anchorIndex =
d->shape->indexForPos(
d->anchor);
1706 d->cursorColor = QColor();
1707 d->cursorShape =
d->shape?
d->shape->cursorForPos(
d->pos,
d->cursorCaret,
d->cursorColor): QPainterPath();
1709 if (!
d->blockQueryUpdates) {
1710 qApp->inputMethod()->update(Qt::ImQueryInput);
1712 d->interface->emitCharacterSelectionChange();
1713 if (!(
d->canvas->canvasWidget() &&
d->canvas->canvasController())) {
1717 if (
d->shape && !firstUpdate) {
1718 QRectF
rect =
d->shape->shapeToDocument(
d->cursorShape.boundingRect());
1719 d->canvas->canvasController()->ensureVisibleDoc(
rect,
false);
1721 if (
d->canvas->canvasWidget()->hasFocus()) {
1722 d->cursorFlash.start();
1723 d->cursorFlashLimit.start();
1724 d->cursorVisible =
false;
1732 d->oldSelectionRect =
d->shape->shapeToDocument(
d->selection.boundingRect());
1733 d->shape->cursorForPos(
d->anchor,
d->anchorCaret,
d->cursorColor);
1734 d->selection =
d->shape->selectionBoxes(
d->pos,
d->anchor);
1737 if (!
d->blockQueryUpdates) {
1738 QGuiApplication::inputMethod()->update(Qt::ImQueryInput);
1746 d->oldIMEDecorationRect =
d->shape->shapeToDocument(
d->IMEDecoration.boundingRect());
1747 KoSvgText::TextDecorations decor;
1749 d->IMEDecoration = QPainterPath();
1750 if (
d->preEditCommand) {
1753 int startIndex =
d->shape->indexForPos(
d->preEditStart) + info.
start;
1754 int endIndex = startIndex + info.
length;
1755 qreal minimum =
d->canvas->viewToDocument(QPointF(1, 1)).x();
1756 d->IMEDecoration.addPath(
d->shape->underlines(
d->shape->posForIndex(startIndex),
1757 d->shape->posForIndex(endIndex),
1762 d->IMEDecoration.setFillRule(Qt::WindingFill);
1784 const int metric,
const bool isHorizontal,
1786 const qreal scaleMetrics,
const QPointF &advance,
1787 QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath> &decor){
1788 QPointF offset = isHorizontal? QPointF(0, -(metric*scaleMetrics)): QPointF(metric*scaleMetrics, 0);
1790 QPainterPath
p = decor.value(handle);
1792 const QPointF startPos = t.map(offset);
1793 const QPointF endPos = t.map(offset+advance);
1794 if (
p.currentPosition() != startPos) {
1799 decor.insert(handle,
p);
1802void processEdges(QTransform t, QMap<SvgTextCursor::TypeSettingModeHandle, int> values,
1803 const bool isHorizontal,
1804 const qreal scaleMetrics,
1805 const QPointF advance,
1806 QPainterPath &path) {
1807 QPointF
p1(values.first(), 0);
1808 QPointF
p2(values.last(), 0);
1809 Q_FOREACH(
const int val, values) {
1818 p1 = QPointF(
p1.y(), -
p1.x());
1819 p2 = QPointF(
p2.y(), -
p2.x());
1823 path.moveTo(t.map(
p1+advance));
1824 path.lineTo(t.map(
p2+advance));
1828 QTransform t = QTransform::fromTranslate(pos.x(), pos.y());
1829 t.rotate(rotateDeg);
1836 if (
d->shape &&
d->typeSettingMode) {
1839 d->shape->getPositionsAndRotationsForRange(
d->pos,
d->anchor);
1840 if (infos.size() < 1)
return;
1842 const bool rtl = infos.first().rtl;
1846 if (infos.size() > 1) {
1848 for (
auto it = infos.begin(); it != infos.end(); it++) {
1849 if (it->visualIndex >= 0) {
1854 for (
auto it = infos.rbegin(); it != infos.rend(); it++) {
1855 if (it->visualIndex >= 0) {
1862 QTransform t = QTransform::fromTranslate(last.
finalPos.x(), last.
finalPos.y());
1870 d->typeSettingDecor.paths = QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>();
1871 d->typeSettingDecor.baselines = QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>();
1872 d->typeSettingDecor.edges = QPainterPath();
1873 d->typeSettingDecor.parentPaths = QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>();
1874 d->typeSettingDecor.parentBaselines = QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>();
1876 if (
d->pos ==
d->anchor) {
1877 metricInfos =
d->shape->getPositionsAndRotationsForRange(0,
d->shape->posForIndex(
d->shape->plainText().size()));
1880 const int minPos = qMin(
d->pos,
d->anchor);
1881 const int maxPos = qMax(
d->pos,
d->anchor);
1882 const int endPos =
d->shape->posForIndex(
d->shape->plainText().size());
1885 if (minPos > 0 || maxPos < endPos) {
1889 const qreal scaleMetrics = props.
fontSize().
value/qreal(metrics.fontSize);
1890 const int lineGap =
calcLineHeight(lineHeight, metrics, scaleMetrics);
1892 const QMap<SvgTextCursor::TypeSettingModeHandle, int> types
1898 positions << qMax(0, minPos-1);
1899 positions << maxPos;
1900 positions << endPos;
1902 Q_FOREACH(
const int pos, positions) {
1904 d->shape->getPositionsAndRotationsForRange(
pos,
pos);
1905 parentInfos.append(info.first());
1908 QPointF drawOffset = isHorizontal? QPointF(
d->handleRadius*2, 0): QPointF(0,
d->handleRadius*2);
1910 drawOffset =
d->canvas->viewConverter()->viewToDocument().map(drawOffset);
1912 bool toggleOffset = rtl;
1914 for (
auto it = parentInfos.begin(); it != parentInfos.end(); it++) {
1915 const bool currentIsMin = (
d->shape->posForIndex(it->logicalIndex) == minPos);
1916 const bool currentIsMax = (
d->shape->posForIndex(it->logicalIndex) == maxPos);
1918 if ((currentIsMin && minPos == 0) || (currentIsMax && maxPos == endPos)) {
1919 toggleOffset = !toggleOffset;
1923 const QPointF finalPos = toggleOffset? it->finalPos + (it->advance - drawOffset): it->finalPos;
1924 const QPointF advance = drawOffset;
1929 const int metric = types.value(handle);
1930 processBaseline(handle, metric, isHorizontal, t, scaleMetrics, advance,
d->typeSettingDecor.parentBaselines);
1934 if (currentIsMin && minPos == maxPos && !toggleOffset) {
1935 toggleOffset = !toggleOffset;
1938 const QPointF advance = toggleOffset? it->advance: QPointF();
1940 processEdges(t, types, isHorizontal, scaleMetrics, advance,
d->typeSettingDecor.edges);
1943 toggleOffset = !toggleOffset;
1948 bool toggleOffset =
false;
1949 for (
auto it = metricInfos.begin(); it != metricInfos.end(); it++) {
1950 const int currentPos = (
d->pos ==
d->anchor)? -1 :
d->shape->posForIndex(it->logicalIndex);
1959 const int lineGap =
calcLineHeight(lineHeight, metrics, scaleMetrics);
1963 const QMap<SvgTextCursor::TypeSettingModeHandle, int> types
1967 const int metric = types.value(handle);
1968 processBaseline(handle, metric, isHorizontal, t, scaleMetrics, it->advance,
d->typeSettingDecor.baselines);
1970 if ((currentPos == minPos || currentPos+1 == maxPos) && minPos != maxPos) {
1971 const QPointF advance = toggleOffset? it->advance: QPointF();
1972 toggleOffset = !toggleOffset;
1973 processEdges(t, types, isHorizontal, scaleMetrics, advance,
d->typeSettingDecor.edges);
1982 d->typeSettingDecor.paths.insert(handle,
d->typeSettingDecor.baselines.value(handle));
1983 d->typeSettingDecor.parentPaths.insert(handle,
d->typeSettingDecor.parentBaselines.value(handle));
1990 updateRect =
d->shape->shapeToDocument(
d->typeSettingDecor.boundingRect(
d->handleRadius));
1994 d->oldTypeSettingRect = updateRect;
2001 d->isAddingCommand =
true;
2002 d->canvas->addCommand(cmd);
2003 d->isAddingCommand =
false;
2015 newPos =
d->shape->posLeft(
pos, visual);
2018 newPos =
d->shape->posRight(
pos, visual);
2021 newPos =
d->shape->posUp(
pos, visual);
2024 newPos =
d->shape->posDown(
pos, visual);
2027 newPos =
d->shape->previousIndex(
pos);
2030 newPos =
d->shape->nextIndex(
pos);
2033 newPos =
d->shape->previousLine(
pos);
2036 newPos =
d->shape->nextLine(
pos);
2039 newPos =
d->shape->wordLeft(
pos, visual);
2040 if (newPos ==
pos) {
2041 newPos =
d->shape->posLeft(
pos, visual);
2042 newPos =
d->shape->wordLeft(newPos, visual);
2046 newPos =
d->shape->wordRight(
pos, visual);
2047 if (newPos ==
pos) {
2048 newPos =
d->shape->posRight(
pos, visual);
2049 newPos =
d->shape->wordRight(newPos, visual);
2053 newPos =
d->shape->wordStart(
pos);
2054 if (newPos ==
pos) {
2055 newPos =
d->shape->previousIndex(
pos);
2056 newPos =
d->shape->wordStart(newPos);
2060 newPos =
d->shape->wordEnd(
pos);
2061 if (newPos ==
pos) {
2062 newPos =
d->shape->nextIndex(
pos);
2063 newPos =
d->shape->wordEnd(newPos);
2067 newPos =
d->shape->lineStart(
pos);
2070 newPos =
d->shape->lineEnd(
pos);
2076 newPos =
d->shape->posForIndex(
d->shape->plainText().size());
2085 const QString text =
event->text();
2088 const QChar c = text.at(0);
2091 if (c.category() == QChar::Other_Format)
2094 if (event->modifiers() == Qt::ControlModifier
2095 || event->modifiers() == (Qt::ShiftModifier | Qt::ControlModifier)) {
2100 if (c.category() == QChar::Other_PrivateUse)
2102 if (c == QLatin1Char(
'\t'))
2109 if (!
d->preEditCommand) {
2113 qApp->inputMethod()->commit();
2115 if (!
d->preEditCommand) {
2119 d->preEditCommand->undo();
2120 d->preEditCommand =
nullptr;
2121 d->preEditStart = -1;
2122 d->preEditLength = 0;
2131 if (
d->shape &&
d->canvas->resourceManager() &&
d->pos ==
d->anchor) {
2138 if (c !=
d->canvas->resourceManager()->foregroundColor()) {
2139 d->canvas->resourceManager()->setForegroundColor(c);
2147 if (c !=
d->canvas->resourceManager()->backgroundColor()) {
2148 d->canvas->resourceManager()->setBackgroundColor(c);
2152 Q_FOREACH (QAction *action,
d->actions) {
2154 action->blockSignals(
true);
2158 if (action->isChecked() != checked) {
2159 action->setChecked(checked);
2162 action->blockSignals(
false);
2190 return d->parent->propertiesForShape();
2197 if (
d->parent->shape()->singleNode()) {
2200 return d->parent->propertiesForRange();
2212 d->parent->mergePropertiesIntoSelection(properties, removeProperties,
true);
2217 d->parent->mergePropertiesIntoSelection(properties, removeProperties,
false,
true);
2222 return d->parent->hasSelection();
2234 if (!
d->parent->shape())
return;
2235 d->compressor.start();
2240 d->characterCompressor.start();
qreal length(const QPointF &vec)
float value(const T *src, size_t ch)
VertexDescriptor get(PredecessorMap const &m, VertexDescriptor v)
qreal distance(const QPointF &p1, const QPointF &p2)
static QColor bgColorForCaret(QColor c, int opacity=64)
QTransform posAndRotateTransform(const QPointF pos, const qreal rotateDeg)
QMap< SvgTextCursor::TypeSettingModeHandle, int > typeSettingBaselinesFromMetrics(const KoSvgText::FontMetrics metrics, const qreal lineGap, const bool isHorizontal)
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 KisHandlePainterHelper class is a special helper for painting handles around objects....
void drawPath(const QPainterPath &path)
void drawHandleRect(const QPointF ¢er, qreal radius)
void setHandleStyle(const KisHandleStyle &style)
void drawHandleCircle(const QPointF ¢er, qreal radius)
static KisHandleStyle & partiallyHighlightedPrimaryHandles()
static KisHandleStyle & secondarySelection()
A simple solid color shape background.
QColor color() const
Returns the background color.
void setOpacity(quint8 alpha)
void fromQColor(const QColor &c)
Convenient function for converting from a QColor.
void toQColor(QColor *c) const
a convenience method for the above.
bool isVisible() const override
void addShapeChangeListener(ShapeChangeListener *listener)
KoShapeAnchor * anchor() const
ChangeType
Used by shapeChanged() to select which change was made.
QList< KoShape * > fetchShapes(QRectF viewportInPx, qreal resolutionPPI, QSizeF *fragmentSize=nullptr)
The KoSvgTextPropertiesInterface class.
void textCharacterSelectionChanged()
void textSelectionChanged()
Emit to signal to KisTextPropertiesManager to call getSelectedProperties.
@ DominantBaselineId
KoSvgText::Baseline.
@ AlignmentBaselineId
KoSvgText::Baseline.
@ LineHeightId
KoSvgText::AutoValue.
@ StrokeId
KoSvgText::StrokeProperty.
@ FillId
KoSvgText::BackgroundProperty.
@ WritingModeId
KoSvgText::WritingMode.
@ DirectionId
KoSvgText::Direction.
@ LastPropertyId
Last Property ID, used for iteration.
QSharedPointer< KoShapeBackground > background() const
KoShapeStrokeModelSP stroke() const
KoSvgText::FontMetrics metrics(const bool withResolvedLineHeight=true, const bool offsetByBaseline=false) const
metrics Return the metrics of the first available font.
bool hasProperty(PropertyId id) const
void setProperty(PropertyId id, const QVariant &value)
QVariant propertyOrDefault(PropertyId id) const
KoSvgText::CssLengthPercentage fontSize() const
bool convertToSvg(QString *svgText, QString *stylesText)
bool convertToHtml(QString *htmlText)
convertToHtml convert the text in the text shape to html
@ PreformattedText
Text-on-Path falls under this or PrePositionedText depending on collapse of lines.
Interface to interact with the text property manager.
const QScopedPointer< Private > d
virtual bool spanSelection() override
Whether the tool is currently selecting a set of characters instead of whole paragraphs.
SvgTextCursorPropertyInterface(SvgTextCursor *parent)
virtual void setCharacterPropertiesOnSelected(KoSvgTextProperties properties, QSet< KoSvgTextProperties::PropertyId > removeProperties=QSet< KoSvgTextProperties::PropertyId >()) override
setCharacterPropertiesOnSelected This sets the properties for a character selection instead of the fu...
virtual KoSvgTextProperties getInheritedProperties() override
getInheritedProperties The properties that should be visible when a given property isn't available in...
virtual QList< KoSvgTextProperties > getSelectedProperties() override
getSelectedProperties
virtual void setPropertiesOnSelected(KoSvgTextProperties properties, QSet< KoSvgTextProperties::PropertyId > removeProperties=QSet< KoSvgTextProperties::PropertyId >()) override
setPropertiesOnSelected This sets the properties on the selection. The implementation is responsible ...
~SvgTextCursorPropertyInterface()
void emitSelectionChange()
virtual bool characterPropertiesEnabled() override
Whether character selections are possible at all.
virtual QList< KoSvgTextProperties > getCharacterProperties() override
getSelectedProperties
void emitCharacterSelectionChange()
InputQueryUpdateBlocker(SvgTextCursor::Private *d)
void setChangeVisibility(bool changeVisibility)
InputQueryUpdateBlocker(const QScopedPointer< Private > &d)
bool m_unblockQueryUpdates
~InputQueryUpdateBlocker()
The SvgTextMergePropertiesRangeCommand class This sets properties on a specific range in a single tex...
The SvgTextRemoveTransformsFromRange class Removes the SVG 1.1 character transforms from the range.
static bool actionEnabled(QAction *action, const QList< KoSvgTextProperties > currentProperties)
static QStringList possibleActions()
static KoSvgTextProperties getModifiedProperties(const QAction *action, QList< KoSvgTextProperties > currentProperties)
static bool configureAction(QAction *action, const QString &name)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
qreal kisDistanceToLine(const QPointF &m, const QLineF &line)
QPointF kisProjectOnVector(const QPointF &base, const QPointF &v)
bool intersectLineRect(QLineF &line, const QRect rect, bool extend)
qreal luminosityCoarse(const QColor &c, bool sRGBtrc)
luminosityCoarse This calculates the luminosity of the given QColor. It uses a very coarse (10 step) ...
@ BackgroundColor
The active background color selected for this canvas.
@ ForegroundColor
The active foreground color selected for this canvas.
TextDecorationStyle
Style of the text-decoration.
@ Solid
Draw a solid line.Ex: --—.
@ Dashed
Draw a dashed line. Ex: - - - - -.
@ Wavy
Draw a wavy line. We currently make a zigzag, ex: ^^^^^.
@ Dotted
Draw a dotted line. Ex: .....
Direction
Base direction used by Bidi algorithm.
Baseline
Baseline values used by dominant-baseline and baseline-align.
@ BaselineAlphabetic
Use 'romn' or the baseline for LCG scripts.
@ BaselineTextBottom
Bottom side of the inline line-box.
@ BaselineTextTop
Top side of the inline line-box.
@ BaselineCentral
Use the center between the ideographic over and under.
int start
The startPos from the attribute.
void setDecorationFromQTextCharFormat(QTextCharFormat format)
void setDecorationFromQStyle(QTextCharFormat::UnderlineStyle s)
bool thick
Whether the decoration needs to be doubled in size.
int length
The length from the attribute.
KoSvgText::TextDecorationStyle style
The style.
KoSvgText::TextDecorations decor
Which sides get decorated.
The KoSvgTextCharacterInfo class This is a small struct to convey information about character positio...
static bool visualLessThan(const KoSvgTextCharacterInfo &a, const KoSvgTextCharacterInfo &b)
BackgroundProperty is a special wrapper around KoShapeBackground for managing it in KoSvgTextProperti...
The FontMetrics class A class to keep track of a variety of font metrics. Note that values are in Fre...
qint32 ideographicCenterBaseline
default baseline for vertical, centered between over and under.
qint32 ideographicUnderBaseline
location of ideographic under baseline from origin, may fall back to descender.
qint32 xHeight
height of X, defaults to 0.5 fontsize.
qint32 lineGap
additional linegap between consecutive lines.
qint32 fontSize
Currently set size, CSS unit 'em'.
qint32 alphabeticBaseline
location of alphabetic baseline from origin.
qint32 descender
distance for origin to bottom.
qint32 ascender
distance from origin to top.
qint32 mathematicalBaseline
location of mathematical baseline from origin.
qint32 hangingBaseline
location of the hanging baseline used in north brahmic scripts.
bool isNumber
Length or number.
CssLengthPercentage length
bool isNormal
It's a number indicating the lineHeight;.
StrokeProperty is a special wrapper around KoShapeStrokeModel for managing it in KoSvgTextProperties.
KisSignalCompressor characterCompressor
KisSignalCompressor compressor
Private(SvgTextCursor *parent)
void setTypeSettingHandleHovered(TypeSettingModeHandle hovered=TypeSettingModeHandle::NoHandle)
Set a given typesetting handle as hovered, so it will be drawn as such.
void setVisualMode(const bool visualMode=true)
setVisualMode set whether the navigation mode is visual or logical. This right now primarily affects ...
void keyPressEvent(QKeyEvent *event)
Handle the cursor-related key events.
KoSvgTextPropertiesInterface * textPropertyInterface()
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...
void stopBlinkCursor()
Called by timer, stops the text blinking animation.
QList< QAction * > actions
int getAnchor()
Get the current selection anchor. This is the same as position, unless there's a selection.
void insertText(QString text)
Insert text at getPos()
void removeTransformsFromRange()
removeTransformsFromRange Called by actions to remove svg character transforms from range.
bool drawCursorInAdditionToSelection
QPair< KoSvgTextProperties, KoSvgTextProperties > currentTextProperties() const
currentTextProperties
void updateIMEDecoration()
void paintDecorations(QPainter &gc, QColor selectionColor, int decorationThickness=1, qreal handleRadius=5.0)
Paint all decorations and blinkingcursors.
QVector< IMEDecorationInfo > styleMap
Decoration info (underlines) for the preEdit string to differentiate it from regular text.
const QScopedPointer< Private > d
void deselectText()
Deselect all text. This effectively makes anchor the same as pos.
bool hasSelection() override
return true if the tool currently has something selected that can be copied or deleted.
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,...
void setPos(int pos, int anchor)
Set the pos and the anchor.
void addCommandToUndoAdapter(KUndo2Command *cmd)
Adds a command to the canvas of the parent tool.
void clearFormattingAction()
Called by the clear formatting action.
void notifyShapeChanged(KoShape::ChangeType type, KoShape *shape) override
QRectF oldIMEDecorationRect
Update Rectangle of previous decoration.
QString handleName(TypeSettingModeHandle handle) const
handleName
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.
void blinkCursor()
Called by timer, toggles the text cursor visible or invisible.
void updateCanvasResources()
Update the canvas resources with fore and background color.
SvgTextCursor(KoCanvasBase *canvas)
TypeSettingModeHandle
Handles used by type setting mode.
@ BaselineAlphabetic
Baselines.
@ BaselineShift
The text properties handles.
void inputMethodEvent(QInputMethodEvent *event)
Process an input method event. This is used by IME like virtual keyboards.
void canvasResourceChanged(int key, const QVariant &value)
Called when the canvas resources (foreground/background) change.
void setPosToPoint(QPointF point, bool moveAnchor=true)
Set the pos from a point. This currently does a search inside the text shape.
QCursor cursorTypeForTypeSetting() const
Return appropriate typeSetting cursor;.
void moveCursor(MoveMode mode, bool moveAnchor=true)
Move the cursor, and, if you don't want a selection, move the anchor.
void setPasteRichTextByDefault(const bool pasteRichText=true)
setPasteRichText
bool acceptableInput(const QKeyEvent *event) const
More or less copied from bool QInputControl::isAcceptableInput(const QKeyEvent *event) const.
QList< KoSvgTextProperties > propertiesForRange() const
propertiesForRange
TypeSettingDecorInfo typeSettingDecor
QVariant inputMethodQuery(Qt::InputMethodQuery query) const
Process an input method query and return the requested result.
void removeSelection()
removeSelection if there's a selection, creates a text-removal command.
void setTypeSettingModeActive(bool activate)
Set type setting mode active.
void updateTypeSettingDecoration()
void removeText(MoveMode first, MoveMode second)
removeText remove text relative to the current position. This will move the cursor according to the m...
bool setDominantBaselineFromHandle(const TypeSettingModeHandle handle)
setDominantBaselineFromHandle Set the dominant baseline from a given handle.
int moveModeResult(const MoveMode mode, int &pos, bool visual=false) const
Processes a move action, returns the input.
int getPos()
Get the current position.
void focusOut()
Stops blinking cursor.
void removeLastCodePoint()
removeLastCodePoint Special function to remove the last code point. Triggered by backspace....
int posForTypeSettingHandleAndRect(const TypeSettingModeHandle handle, const QRectF regionOfInterest)
posForHandleAndRect Returns the closest cursor position for a given region and typesetting handle....
QRectF oldTypeSettingRect
TypeSettingModeHandle typeSettingHandleAtPos(const QRectF regionOfInterest)
Get typeSettingMode handle for text;.
void notifyMarkupChanged() override
bool pastePlainText()
pastePlainText Explicitely paste plaintext at pos.
bool registerPropertyAction(QAction *action, const QString &name)
Register an action.
void selectionChanged()
Sents an update selection was changed.
void focusIn()
Turns on blinking cursor.
void updateCursorDecoration(QRectF updateRect)
Sents an update to the parent tool to update it's decorations.
void setDrawTypeSettingHandle(bool draw)
bool paste()
paste pastes plain text in the clipboard at pos. Uses pasteRichTextByDefault to determine whether to ...
QPainterPath IMEDecoration
The decorations for the current preedit string.
void updateTypeSettingDecorFromShape()
Update the type setting decorations.
void updateModifiers(const Qt::KeyboardModifiers modifiers)
KisAcyclicSignalConnector resourceManagerAcyclicConnector
QList< KoSvgTextProperties > propertiesForShape() const
propertiesForShape
void setShape(KoSvgTextShape *textShape)
setShape
void updateInputMethodItemTransform()
Qt::KeyboardModifiers lastKnownModifiers
void insertRichText(KoSvgTextShape *insert, bool inheritPropertiesIfPossible=false)
Insert rich text at getPos();.
SvgTextRemoveCommand * removeSelectionImpl(bool allowCleanUp, KUndo2Command *parent=0)
removeSelection if there's a selection, creates a text-removal command.
void notifyCursorPosChanged(int pos, int anchor) override
void copy() const
copy copies plain text into the clipboard between anchor and pos.
void updateCursor(bool firstUpdate=false)
update the cursor shape. First update will block ensuring the canvas is visible so setShape won't cau...
QPointF closestBaselinePoint
QMap< SvgTextCursor::TypeSettingModeHandle, QPainterPath > paths
QMap< SvgTextCursor::TypeSettingModeHandle, QPainterPath > baselines
QMap< SvgTextCursor::TypeSettingModeHandle, QPainterPath > parentBaselines
QPair< QPointF, QPointF > handles
QMap< SvgTextCursor::TypeSettingModeHandle, QPainterPath > parentPaths
QRectF boundingRect(qreal handleRadius)
bool testBaselines(Qt::KeyboardModifiers modifiers)