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();
1401 if (
d->preEditCommand) {
1407 bool select =
event->modifiers().testFlag(Qt::ShiftModifier);
1409 if (!((Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier) & event->modifiers())) {
1411 switch (event->key()) {
1428 case Qt::Key_Delete:
1432 case Qt::Key_Backspace:
1436 case Qt::Key_Return:
1445 if (event->isAccepted()) {
1463 int newKey =
event->key();
1468 newKey = Qt::Key_Right;
1471 newKey = Qt::Key_Left;
1481 newKey = Qt::Key_Down;
1484 newKey = Qt::Key_Up;
1487 newKey = Qt::Key_Left;
1490 newKey = Qt::Key_Right;
1498 newKey = Qt::Key_Up;
1501 newKey = Qt::Key_Down;
1504 newKey = Qt::Key_Left;
1507 newKey = Qt::Key_Right;
1514 QKeySequence testSequence(event->modifiers() | newKey);
1522 Q_FOREACH(QAction *action,
d->actions) {
1523 if (action->shortcut() == testSequence) {
1534 if (testSequence == QKeySequence::MoveToNextChar) {
1537 }
else if (testSequence == QKeySequence::SelectNextChar) {
1540 }
else if (testSequence == QKeySequence::MoveToPreviousChar) {
1543 }
else if (testSequence == QKeySequence::SelectPreviousChar) {
1546 }
else if (testSequence == QKeySequence::MoveToNextLine) {
1549 }
else if (testSequence == QKeySequence::SelectNextLine) {
1552 }
else if (testSequence == QKeySequence::MoveToPreviousLine) {
1555 }
else if (testSequence == QKeySequence::SelectPreviousLine) {
1559 }
else if (testSequence == QKeySequence::MoveToNextWord) {
1562 }
else if (testSequence == QKeySequence::SelectNextWord) {
1565 }
else if (testSequence == QKeySequence::MoveToPreviousWord) {
1568 }
else if (testSequence == QKeySequence::SelectPreviousWord) {
1572 }
else if (testSequence == QKeySequence::MoveToStartOfLine) {
1575 }
else if (testSequence == QKeySequence::SelectStartOfLine) {
1578 }
else if (testSequence == QKeySequence::MoveToEndOfLine) {
1581 }
else if (testSequence == QKeySequence::SelectEndOfLine) {
1585 }
else if (testSequence == QKeySequence::MoveToStartOfBlock
1586 || testSequence == QKeySequence::MoveToStartOfDocument) {
1589 }
else if (testSequence == QKeySequence::SelectStartOfBlock
1590 || testSequence == QKeySequence::SelectStartOfDocument) {
1594 }
else if (testSequence == QKeySequence::MoveToEndOfBlock
1595 || testSequence == QKeySequence::MoveToEndOfDocument) {
1598 }
else if (testSequence == QKeySequence::SelectEndOfBlock
1599 || testSequence == QKeySequence::SelectEndOfDocument) {
1603 }
else if (testSequence == QKeySequence::DeleteStartOfWord) {
1606 }
else if (testSequence == QKeySequence::DeleteEndOfWord) {
1609 }
else if (testSequence == QKeySequence::DeleteEndOfLine) {
1612 }
else if (testSequence == QKeySequence::DeleteCompleteLine) {
1615 }
else if (testSequence == QKeySequence::Backspace) {
1618 }
else if (testSequence == QKeySequence::Delete) {
1622 }
else if (testSequence == QKeySequence::InsertLineSeparator
1623 || testSequence == QKeySequence::InsertParagraphSeparator) {
1633 d->lastKnownModifiers = modifiers;
1639 return d->isAddingCommand;
1644 d->cursorFlash.start();
1645 d->cursorFlashLimit.start();
1646 d->cursorVisible =
false;
1653 d->hasFocus =
false;
1660 d->actions.append(action);
1661 connect(action, SIGNAL(triggered(
bool)),
this, SLOT(
propertyAction()));
1663 }
else if (name ==
"svg_insert_special_character") {
1664 d->actions.append(action);
1667 }
else if (name ==
"svg_paste_rich_text") {
1668 d->actions.append(action);
1669 connect(action, SIGNAL(triggered(
bool)),
this, SLOT(
pasteRichText()));
1671 }
else if (name ==
"svg_paste_plain_text") {
1672 d->actions.append(action);
1673 connect(action, SIGNAL(triggered(
bool)),
this, SLOT(
pastePlainText()));
1675 }
else if (name ==
"svg_remove_transforms_from_range") {
1676 d->actions.append(action);
1679 }
else if (name ==
"svg_clear_formatting") {
1680 d->actions.append(action);
1683 }
else if (action) {
1684 d->actions.append(action);
1692 return d->interface;
1698 d->oldCursorRect =
d->shape->shapeToDocument(
d->cursorShape.boundingRect());
1699 d->posIndex =
d->shape->indexForPos(
d->pos);
1700 d->anchorIndex =
d->shape->indexForPos(
d->anchor);
1704 d->cursorColor = QColor();
1705 d->cursorShape =
d->shape?
d->shape->cursorForPos(
d->pos,
d->cursorCaret,
d->cursorColor): QPainterPath();
1707 if (!
d->blockQueryUpdates) {
1708 qApp->inputMethod()->update(Qt::ImQueryInput);
1710 d->interface->emitCharacterSelectionChange();
1711 if (!(
d->canvas->canvasWidget() &&
d->canvas->canvasController())) {
1715 if (
d->shape && !firstUpdate) {
1716 QRectF
rect =
d->shape->shapeToDocument(
d->cursorShape.boundingRect());
1717 d->canvas->canvasController()->ensureVisibleDoc(
rect,
false);
1719 if (
d->canvas->canvasWidget()->hasFocus()) {
1720 d->cursorFlash.start();
1721 d->cursorFlashLimit.start();
1722 d->cursorVisible =
false;
1730 d->oldSelectionRect =
d->shape->shapeToDocument(
d->selection.boundingRect());
1731 d->shape->cursorForPos(
d->anchor,
d->anchorCaret,
d->cursorColor);
1732 d->selection =
d->shape->selectionBoxes(
d->pos,
d->anchor);
1735 if (!
d->blockQueryUpdates) {
1736 QGuiApplication::inputMethod()->update(Qt::ImQueryInput);
1744 d->oldIMEDecorationRect =
d->shape->shapeToDocument(
d->IMEDecoration.boundingRect());
1745 KoSvgText::TextDecorations decor;
1747 d->IMEDecoration = QPainterPath();
1748 if (
d->preEditCommand) {
1751 int startIndex =
d->shape->indexForPos(
d->preEditStart) + info.
start;
1752 int endIndex = startIndex + info.
length;
1753 qreal minimum =
d->canvas->viewToDocument(QPointF(1, 1)).x();
1754 d->IMEDecoration.addPath(
d->shape->underlines(
d->shape->posForIndex(startIndex),
1755 d->shape->posForIndex(endIndex),
1760 d->IMEDecoration.setFillRule(Qt::WindingFill);
1782 const int metric,
const bool isHorizontal,
1784 const qreal scaleMetrics,
const QPointF &advance,
1785 QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath> &decor){
1786 QPointF offset = isHorizontal? QPointF(0, -(metric*scaleMetrics)): QPointF(metric*scaleMetrics, 0);
1788 QPainterPath
p = decor.value(handle);
1790 const QPointF startPos = t.map(offset);
1791 const QPointF endPos = t.map(offset+advance);
1792 if (
p.currentPosition() != startPos) {
1797 decor.insert(handle,
p);
1800void processEdges(QTransform t, QMap<SvgTextCursor::TypeSettingModeHandle, int> values,
1801 const bool isHorizontal,
1802 const qreal scaleMetrics,
1803 const QPointF advance,
1804 QPainterPath &path) {
1805 QPointF
p1(values.first(), 0);
1806 QPointF
p2(values.last(), 0);
1807 Q_FOREACH(
const int val, values) {
1816 p1 = QPointF(
p1.y(), -
p1.x());
1817 p2 = QPointF(
p2.y(), -
p2.x());
1821 path.moveTo(t.map(
p1+advance));
1822 path.lineTo(t.map(
p2+advance));
1826 QTransform t = QTransform::fromTranslate(pos.x(), pos.y());
1827 t.rotate(rotateDeg);
1834 if (
d->shape &&
d->typeSettingMode) {
1837 d->shape->getPositionsAndRotationsForRange(
d->pos,
d->anchor);
1838 if (infos.size() < 1)
return;
1840 const bool rtl = infos.first().rtl;
1844 if (infos.size() > 1) {
1846 for (
auto it = infos.begin(); it != infos.end(); it++) {
1847 if (it->visualIndex >= 0) {
1852 for (
auto it = infos.rbegin(); it != infos.rend(); it++) {
1853 if (it->visualIndex >= 0) {
1860 QTransform t = QTransform::fromTranslate(last.
finalPos.x(), last.
finalPos.y());
1868 d->typeSettingDecor.paths = QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>();
1869 d->typeSettingDecor.baselines = QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>();
1870 d->typeSettingDecor.edges = QPainterPath();
1871 d->typeSettingDecor.parentPaths = QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>();
1872 d->typeSettingDecor.parentBaselines = QMap<SvgTextCursor::TypeSettingModeHandle, QPainterPath>();
1874 if (
d->pos ==
d->anchor) {
1875 metricInfos =
d->shape->getPositionsAndRotationsForRange(0,
d->shape->posForIndex(
d->shape->plainText().size()));
1878 const int minPos = qMin(
d->pos,
d->anchor);
1879 const int maxPos = qMax(
d->pos,
d->anchor);
1880 const int endPos =
d->shape->posForIndex(
d->shape->plainText().size());
1883 if (minPos > 0 || maxPos < endPos) {
1887 const qreal scaleMetrics = props.
fontSize().
value/qreal(metrics.fontSize);
1888 const int lineGap =
calcLineHeight(lineHeight, metrics, scaleMetrics);
1890 const QMap<SvgTextCursor::TypeSettingModeHandle, int> types
1896 positions << qMax(0, minPos-1);
1897 positions << maxPos;
1898 positions << endPos;
1900 Q_FOREACH(
const int pos, positions) {
1902 d->shape->getPositionsAndRotationsForRange(
pos,
pos);
1903 parentInfos.append(info.first());
1906 QPointF drawOffset = isHorizontal? QPointF(
d->handleRadius*2, 0): QPointF(0,
d->handleRadius*2);
1908 drawOffset =
d->canvas->viewConverter()->viewToDocument().map(drawOffset);
1910 bool toggleOffset = rtl;
1912 for (
auto it = parentInfos.begin(); it != parentInfos.end(); it++) {
1913 const bool currentIsMin = (
d->shape->posForIndex(it->logicalIndex) == minPos);
1914 const QPointF finalPos = toggleOffset? it->finalPos + (it->advance - drawOffset): it->finalPos;
1915 const QPointF advance = drawOffset;
1920 const int metric = types.value(handle);
1921 processBaseline(handle, metric, isHorizontal, t, scaleMetrics, advance,
d->typeSettingDecor.parentBaselines);
1926 if (currentIsMin && minPos == maxPos && !toggleOffset) {
1927 toggleOffset = !toggleOffset;
1930 const QPointF advance = toggleOffset? it->advance: QPointF();
1932 processEdges(t, types, isHorizontal, scaleMetrics, advance,
d->typeSettingDecor.edges);
1935 toggleOffset = !toggleOffset;
1940 bool toggleOffset =
false;
1941 for (
auto it = metricInfos.begin(); it != metricInfos.end(); it++) {
1942 const int currentPos = (
d->pos ==
d->anchor)? -1 :
d->shape->posForIndex(it->logicalIndex);
1951 const int lineGap =
calcLineHeight(lineHeight, metrics, scaleMetrics);
1955 const QMap<SvgTextCursor::TypeSettingModeHandle, int> types
1959 const int metric = types.value(handle);
1960 processBaseline(handle, metric, isHorizontal, t, scaleMetrics, it->advance,
d->typeSettingDecor.baselines);
1962 if ((currentPos == minPos || currentPos+1 == maxPos) && minPos != maxPos) {
1963 const QPointF advance = toggleOffset? it->advance: QPointF();
1964 toggleOffset = !toggleOffset;
1965 processEdges(t, types, isHorizontal, scaleMetrics, advance,
d->typeSettingDecor.edges);
1974 d->typeSettingDecor.paths.insert(handle,
d->typeSettingDecor.baselines.value(handle));
1975 d->typeSettingDecor.parentPaths.insert(handle,
d->typeSettingDecor.parentBaselines.value(handle));
1982 updateRect =
d->shape->shapeToDocument(
d->typeSettingDecor.boundingRect(
d->handleRadius));
1986 d->oldTypeSettingRect = updateRect;
1993 d->isAddingCommand =
true;
1994 d->canvas->addCommand(cmd);
1995 d->isAddingCommand =
false;
2007 newPos =
d->shape->posLeft(
pos, visual);
2010 newPos =
d->shape->posRight(
pos, visual);
2013 newPos =
d->shape->posUp(
pos, visual);
2016 newPos =
d->shape->posDown(
pos, visual);
2019 newPos =
d->shape->previousIndex(
pos);
2022 newPos =
d->shape->nextIndex(
pos);
2025 newPos =
d->shape->previousLine(
pos);
2028 newPos =
d->shape->nextLine(
pos);
2031 newPos =
d->shape->wordLeft(
pos, visual);
2032 if (newPos ==
pos) {
2033 newPos =
d->shape->posLeft(
pos, visual);
2034 newPos =
d->shape->wordLeft(newPos, visual);
2038 newPos =
d->shape->wordRight(
pos, visual);
2039 if (newPos ==
pos) {
2040 newPos =
d->shape->posRight(
pos, visual);
2041 newPos =
d->shape->wordRight(newPos, visual);
2045 newPos =
d->shape->wordStart(
pos);
2046 if (newPos ==
pos) {
2047 newPos =
d->shape->previousIndex(
pos);
2048 newPos =
d->shape->wordStart(newPos);
2052 newPos =
d->shape->wordEnd(
pos);
2053 if (newPos ==
pos) {
2054 newPos =
d->shape->nextIndex(
pos);
2055 newPos =
d->shape->wordEnd(newPos);
2059 newPos =
d->shape->lineStart(
pos);
2062 newPos =
d->shape->lineEnd(
pos);
2068 newPos =
d->shape->posForIndex(
d->shape->plainText().size());
2077 const QString text =
event->text();
2080 const QChar c = text.at(0);
2083 if (c.category() == QChar::Other_Format)
2086 if (event->modifiers() == Qt::ControlModifier
2087 || event->modifiers() == (Qt::ShiftModifier | Qt::ControlModifier)) {
2092 if (c.category() == QChar::Other_PrivateUse)
2094 if (c == QLatin1Char(
'\t'))
2101 if (!
d->preEditCommand) {
2105 qApp->inputMethod()->commit();
2107 if (!
d->preEditCommand) {
2111 d->preEditCommand->undo();
2112 d->preEditCommand =
nullptr;
2113 d->preEditStart = -1;
2114 d->preEditLength = 0;
2123 if (
d->shape &&
d->canvas->resourceManager() &&
d->pos ==
d->anchor) {
2130 if (c !=
d->canvas->resourceManager()->foregroundColor()) {
2131 d->canvas->resourceManager()->setForegroundColor(c);
2139 if (c !=
d->canvas->resourceManager()->backgroundColor()) {
2140 d->canvas->resourceManager()->setBackgroundColor(c);
2144 Q_FOREACH (QAction *action,
d->actions) {
2146 action->blockSignals(
true);
2150 if (action->isChecked() != checked) {
2151 action->setChecked(checked);
2154 action->blockSignals(
false);
2182 return d->parent->propertiesForShape();
2189 if (
d->parent->shape()->singleNode()) {
2192 return d->parent->propertiesForRange();
2204 d->parent->mergePropertiesIntoSelection(properties, removeProperties,
true);
2209 d->parent->mergePropertiesIntoSelection(properties, removeProperties,
false,
true);
2214 return d->parent->hasSelection();
2226 if (!
d->parent->shape())
return;
2227 d->compressor.start();
2232 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)