Krita Source Code Documentation
Loading...
Searching...
No Matches
SvgTextTool.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2
3 SPDX-FileCopyrightText: 2017 Boudewijn Rempt <boud@valdyas.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "SvgTextTool.h"
10#include "KoSvgTextShape.h"
16#include "SvgInlineSizeHelper.h"
17#include "SvgMoveTextCommand.h"
18#include "SvgMoveTextStrategy.h"
20#include "SvgTextEditor.h"
23#include "SvgTextShortCuts.h"
30
31#include <QPainterPath>
32#include <QDesktopServices>
33#include <QApplication>
34#include <QStyle>
35#include <QDockWidget>
36#include <QQuickItem>
37#include <QActionGroup>
38
39#include <klocalizedstring.h>
40
41#include <KisPart.h>
42#include <kis_canvas2.h>
43#include <KSharedConfig>
44#include "kis_assert.h"
46
47#include <KoFileDialog.h>
48#include <KoIcon.h>
49#include <KoCanvasBase.h>
50#include <KoSelection.h>
51#include <KoShapeManager.h>
52#include <KoShapeController.h>
53#include <KoShapeRegistry.h>
54#include <KoShapeFactoryBase.h>
55#include <KoPointerEvent.h>
56#include <KoProperties.h>
58#include "KoToolManager.h"
59#include <KoShapeFillWrapper.h>
61#include <KoPathShape.h>
62#include <KoPathSegment.h>
63
65#include <KoCssStylePreset.h>
67#include <KoColorBackground.h>
68#include <KisResourceModel.h>
69
71#include <KisViewManager.h>
72#include <KisQQuickWidget.h>
73#include <QQmlError>
74#include <KisMainWindow.h>
75
77#include "kis_tool_utils.h"
78#include "kis_debug.h"
80
81#ifdef Q_OS_ANDROID
82#include <QMenuBar>
83#endif
84
85
87
88constexpr double INLINE_SIZE_DASHES_PATTERN_A = 4.0;
89constexpr double INLINE_SIZE_DASHES_PATTERN_B = 8.0;
91constexpr double INLINE_SIZE_HANDLE_THICKNESS = 1.0;
92
93
94static bool debugEnabled()
95{
96 static const bool debugEnabled = !qEnvironmentVariableIsEmpty("KRITA_DEBUG_TEXTTOOL");
97 return debugEnabled;
98}
99
101 : KoToolBase(canvas)
102 , m_optionManager(new SvgTextToolOptionsManager(this))
103 , m_textCursor(canvas)
104 , m_textOutlineHelper(new KoSvgTextShapeOutlineHelper(canvas))
105{
106 // TODO: figure out whether we should use system config for this, Windows and GTK have values for it, but Qt and MacOS don't(?).
107 const int cursorFlashLimit = 5000;
108 const bool enableCursorWithSelection = QApplication::style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected);
109 m_textCursor.setCaretSetting(QApplication::style()->pixelMetric(QStyle::PM_TextCursorWidth)
110 , qApp->cursorFlashTime()
111 , cursorFlashLimit
112 , enableCursorWithSelection);
113 connect(&m_textCursor, SIGNAL(updateCursorDecoration(QRectF)), this, SLOT(slotUpdateCursorDecoration(QRectF)));
114
115 Q_FOREACH(const QString name, SvgTextShortCuts::possibleActions()) {
116 QAction *a = action(name);
118 dbgTools << "registered" << name << a->shortcut();
119 }
120 }
121
122 const QStringList extraActions = {
123 "svg_insert_special_character",
124 "svg_paste_rich_text",
125 "svg_paste_plain_text",
126 "svg_remove_transforms_from_range",
127 "svg_clear_formatting"
128 };
129 connect(&m_textCursor, SIGNAL(sigOpenGlyphPalette()), this, SLOT(showGlyphPalette()));
130 Q_FOREACH (const QString name, extraActions) {
131 QAction *a = action(name);
132 if (a) {
134 qWarning() << "could not register" << name << a->shortcut();
135 }
136 }
137 }
138
140 QActionGroup *textTypeActions = new QActionGroup(this);
141 addMappedAction(m_textTypeSignalsMapper.data(), "text_type_preformatted", KoSvgTextShape::PreformattedText, textTypeActions);
142 addMappedAction(m_textTypeSignalsMapper.data(), "text_type_inline_wrap", KoSvgTextShape::InlineWrap, textTypeActions);
143 addMappedAction(m_textTypeSignalsMapper.data(), "text_type_pre_positioned", KoSvgTextShape::PrePositionedText, textTypeActions);
144
146 QActionGroup *typeSettingActions = new QActionGroup(this);
147 addMappedAction(m_typeSettingMovementMapper.data(), "svg_type_setting_move_selection_start_down_1_px", Qt::Key_Down, typeSettingActions);
148 addMappedAction(m_typeSettingMovementMapper.data(), "svg_type_setting_move_selection_start_up_1_px", Qt::Key_Up, typeSettingActions);
149 addMappedAction(m_typeSettingMovementMapper.data(), "svg_type_setting_move_selection_start_left_1_px", Qt::Key_Left, typeSettingActions);
150 addMappedAction(m_typeSettingMovementMapper.data(), "svg_type_setting_move_selection_start_right_1_px", Qt::Key_Right, typeSettingActions);
151
152 m_textOutlineHelper->setDrawBoundingRect(false);
153 m_textOutlineHelper->setDrawTextWrappingArea(true);
154
155 connect(&m_textCursor, SIGNAL(selectionChanged()), this, SLOT(updateTextPathHelper()));
156
157 m_base_cursor = QCursor(QPixmap(":/tool_text_basic.xpm"), 7, 7);
158 m_text_inline_horizontal = QCursor(QPixmap(":/tool_text_inline_horizontal.xpm"), 7, 7);
159 m_text_inline_vertical = QCursor(QPixmap(":/tool_text_inline_vertical.xpm"), 7, 7);
160 m_text_on_path = QCursor(QPixmap(":/tool_text_on_path.xpm"), 7, 7);
161 m_text_in_shape = QCursor(QPixmap(":/tool_text_in_shape.xpm"), 7, 7);
162 m_ibeam_horizontal = QCursor(QPixmap(":/tool_text_i_beam_horizontal.xpm"), 11, 11);
163 m_ibeam_vertical = QCursor(QPixmap(":/tool_text_i_beam_vertical.xpm"), 11, 11);
164 m_ibeam_horizontal_done = QCursor(QPixmap(":/tool_text_i_beam_horizontal_done.xpm"), 5, 11);
165}
166
168{
169 if(m_editor) {
170 m_editor->close();
171 }
172 if(m_glyphPalette) {
173 m_glyphPalette->close();
174 }
175}
176
177void SvgTextTool::activate(const QSet<KoShape *> &shapes)
178{
179 KoToolBase::activate(shapes);
180 m_canvasConnections.addConnection(canvas()->selectedShapesProxy(), SIGNAL(selectionChanged()), this, SLOT(slotShapeSelectionChanged()));
181
182 KisCanvas2 *canvas2 = qobject_cast<KisCanvas2 *>(this->canvas());
183 if (canvas2) {
184 canvas2->setCurrentShapeManagerOwnerShape(nullptr);
186 QDockWidget *docker = canvas2->viewManager()->mainWindow()->dockWidget("TextProperties");
187 if (docker && m_optionManager) {
188 m_optionManager->setTextPropertiesOpen(docker->isVisible());
189 }
190 }
191
192 connect(m_textTypeSignalsMapper.data(), SIGNAL(mapped(int)), this, SLOT(slotConvertType(int)));
193 connect(m_typeSettingMovementMapper.data(), SIGNAL(mapped(int)), this, SLOT(slotMoveTextSelection(int)));
194
197
199}
200
202{
205 m_textCursor.setShape(nullptr);
206 const KisCanvas2 *canvas2 = qobject_cast<const KisCanvas2 *>(this->canvas());
207 if (canvas2) {
209 }
210 // Exiting text editing mode is handled by requestStrokeEnd
211 disconnect(m_textTypeSignalsMapper.data(), 0, this, 0);
212 disconnect(m_typeSettingMovementMapper.data(), 0, this, 0);
213
214 m_hoveredShapeHighlightRect = QPainterPath();
215
217}
218
220{
221 return nullptr;
222}
223
224QVariant SvgTextTool::inputMethodQuery(Qt::InputMethodQuery query) const
225{
226 if (canvas()) {
227 return m_textCursor.inputMethodQuery(query);
228 } else {
229 return KoToolBase::inputMethodQuery(query);
230 }
231}
232
233void SvgTextTool::inputMethodEvent(QInputMethodEvent *event)
234{
236}
237
239{
240 KisQQuickWidget *optionWidget = new KisQQuickWidget();
241 optionWidget->setMinimumWidth(100);
242 optionWidget->setMinimumHeight(100);
243
244 optionWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
245 optionWidget->setSource(QUrl("qrc:/SvgTextToolOptions.qml"));
246
247 m_optionManager->optionsModel()->setConfigName(this->toolId());
248 m_optionManager->setShowDebug(debugEnabled());
249 if (optionWidget->errors().isEmpty()) {
250 optionWidget->rootObject()->setProperty("manager", QVariant::fromValue(m_optionManager.data()));
251 optionWidget->connectMinimumHeightToRootObject();
252 } else {
253 qWarning() << optionWidget->errors();
254 }
255
256
257 connect(m_optionManager.data(), SIGNAL(openTextEditor()), SLOT(showEditor()));
258 connect(m_optionManager.data(), SIGNAL(openGlyphPalette()), SLOT(showGlyphPalette()));
259
260 connect(m_optionManager.data(), SIGNAL(convertTextType(int)), SLOT(slotConvertType(int)));
261 connect(m_optionManager.data(), SIGNAL(typeSettingModeChanged()), SLOT(slotUpdateTypeSettingMode()));
262 connect(m_optionManager->optionsModel(), SIGNAL(useVisualBidiCursorChanged(bool)), this, SLOT(slotUpdateVisualCursor()));
263 connect(m_optionManager->optionsModel(), SIGNAL(pasteRichtTextByDefaultChanged(bool)), this, SLOT(slotUpdateTextPasteBehaviour()));
264 const KisCanvas2 *canvas2 = qobject_cast<const KisCanvas2 *>(this->canvas());
265 if (canvas2 && canvas2->viewManager()->mainWindow()) {
266 QDockWidget *docker = canvas2->viewManager()->mainWindow()->dockWidget("TextProperties");
267 m_optionManager->setShowTextPropertyButton((docker));
268 if (docker) {
269 optionWidget->setPalette(docker->palette());
270 m_optionManager->setTextPropertiesOpen(docker->isVisible());
272 docker->setVisible(!docker->isVisible());
273 });
274 // Once we have docker toggling actions, we should revisit this.
275 }
276 }
280
281
282 return optionWidget;
283}
284
292
294{
296 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(canvas()->selectedShapesProxy(), 0);
297
299 if (shapes.isEmpty()) return 0;
300
301 KoSvgTextShape *textShape = dynamic_cast<KoSvgTextShape*>(shapes.first());
302
303 return textShape;
304}
305
307{
308 KoSvgTextShape *shape = selectedShape();
309 if (!shape) return;
310
311 if (!m_editor) {
312 m_editor = new SvgTextEditor(QApplication::activeWindow());
313 m_editor->setWindowTitle(i18nc("@title:window", "Krita - Edit Text"));
314 m_editor->setWindowModality(Qt::ApplicationModal);
315 m_editor->setAttribute( Qt::WA_QuitOnClose, false );
316
317 connect(m_editor, SIGNAL(textUpdated(KoSvgTextShape*,QString,QString)), SLOT(textUpdated(KoSvgTextShape*,QString,QString)));
318
319 m_editor->activateWindow(); // raise on creation only
320 }
321 if (!m_editor->isVisible()) {
322 m_editor->setInitialShape(shape);
323#ifdef Q_OS_ANDROID
324 // for window manager
325 m_editor->setWindowFlags(Qt::Dialog);
326 m_editor->menuBar()->setNativeMenuBar(false);
327#endif
328 m_editor->show();
329 }
330}
331
332void SvgTextTool::textUpdated(KoSvgTextShape *shape, const QString &svg, const QString &defs)
333{
334 SvgTextChangeCommand *cmd = new SvgTextChangeCommand(shape, svg, defs);
335 canvas()->addCommand(cmd);
336}
337
339{
340 if (!m_glyphPalette) {
341 m_glyphPalette = new GlyphPaletteDialog(QApplication::activeWindow());
342 m_glyphPalette->setAttribute( Qt::WA_QuitOnClose, false );
343
344 connect(&m_textCursor, SIGNAL(selectionChanged()), this, SLOT(updateGlyphPalette()));
345 connect(m_glyphPalette, SIGNAL(signalInsertRichText(KoSvgTextShape*, bool)), this, SLOT(insertRichText(KoSvgTextShape*, bool)));
346
347 m_glyphPalette->activateWindow();
348 }
349 if (!m_glyphPalette->isVisible()) {
350 m_glyphPalette->show();
352 }
353}
354
356{
357 if (m_glyphPalette && m_glyphPalette->isVisible()) {
358 QString grapheme = QString();
359 if (m_textCursor.shape()) {
360 int pos = m_textCursor.getPos();
361 int pos2 = pos > 0? m_textCursor.shape()->posLeft(pos, false): m_textCursor.shape()->posRight(pos, false);
362 int start = m_textCursor.shape()->indexForPos(qMin(pos, pos2));
363 int end = m_textCursor.shape()->indexForPos(qMax(pos, pos2));
364 grapheme = m_textCursor.shape()->plainText().mid(start, end-start);
365 }
366 m_glyphPalette->setGlyphModelFromProperties(m_textCursor.currentTextProperties(), grapheme);
367 }
368}
369
374
375void SvgTextTool::insertRichText(KoSvgTextShape *richText, bool replaceLastGlyph)
376{
377 if (replaceLastGlyph) {
380 }
381 m_textCursor.insertRichText(richText, true);
382}
383
385{
386 QStringList propStrings;
387 QMap<QString, QString> paraProps = properties.convertParagraphProperties();
388 for (auto it = paraProps.constBegin(); it != paraProps.constEnd(); it++) {
389 propStrings.append(QString("%1: %2;").arg(it.key()).arg(it.value()));
390 }
391 paraProps = properties.convertToSvgTextAttributes();
392 for (auto it = paraProps.constBegin(); it != paraProps.constEnd(); it++) {
393 propStrings.append(QString("%1: %2;").arg(it.key()).arg(it.value()));
394 }
395
396 return QString("<defs>\n <style>\n text {\n %1\n }\n </style>\n</defs>").arg(propStrings.join("\n "));
397}
398
400{
401 const bool useCurrent = m_optionManager->optionsModel()->useCurrentTextProperties();
402 const QString presetName = m_optionManager->optionsModel()->cssStylePresetName();
403
405 if (useCurrent || presetName.isEmpty()) {
407 props = textData.commonProperties;
408 } else {
410 QVector<KoResourceSP> res = model->resourcesForName(presetName);
411 if (res.first()) {
412 KoCssStylePresetSP style = res.first().staticCast<KoCssStylePreset>();
413 qreal dpi = 72;
414 KisCanvas2 *canvas2 = qobject_cast<KisCanvas2 *>(this->canvas());
415 if (canvas2) {
416 dpi = canvas2->image()->xRes() * 72.0;
417 }
418 if (style) {
419 props = style->properties(dpi, true);
420 }
421 }
422 }
423
424 QColor fontColor = (canvas()->resourceManager()->isUsingOtherColor()
425 ? canvas()->resourceManager()->backgroundColor()
426 : canvas()->resourceManager()->foregroundColor()).toQColor();
428 bg->setColor(fontColor);
430 props.setProperty(KoSvgTextProperties::FillId, QVariant::fromValue(bgProp));
431 return props;
432}
433
435{
437 if (shapes.size() == 1) {
438 KoSvgTextShape *textShape = selectedShape();
439 if (!textShape) {
441 return;
442 }
443 } else if (shapes.size() > 1) {
444 KoSvgTextShape *foundTextShape = nullptr;
445
446 Q_FOREACH (KoShape *shape, shapes) {
447 KoSvgTextShape *textShape = dynamic_cast<KoSvgTextShape*>(shape);
448 if (textShape) {
449 foundTextShape = textShape;
450 break;
451 }
452 }
453
455 if (foundTextShape) {
456 koSelection()->select(foundTextShape);
457 }
458 return;
459 }
460 KoSvgTextShape *const shape = selectedShape();
461 if (shape != m_textCursor.shape()) {
462 m_textCursor.setShape(shape);
464 if (shape) {
465 setTextMode(true);
466 } else {
467 setTextMode(false);
468 }
469 }
471}
472
474{
476}
477
482
484{
485 return m_textCursor.paste();
486}
487
492
499
504
509
511{
512 if (!isActivated()) return;
516 m_interactionStrategy->cancelInteraction();
517 m_interactionStrategy = nullptr;
518 useCursor(Qt::ArrowCursor);
520 } else if (isInTextMode()) {
522 }
523 }
524}
525
534
536{
537 if (canvas()) {
538 canvas()->updateCanvas(updateRect);
539 }
540}
541
543 KoSvgTextShape *shape = selectedShape();
544 if (shape) {
545 if (index == shape->textType()) return;
547 KUndo2Command *parentCommand = new KUndo2Command();
550 KoSvgConvertTextTypeCommand *cmd = new KoSvgConvertTextTypeCommand(shape, type, m_textCursor.getPos(), parentCommand);
551 parentCommand->setText(cmd->text());
555 canvas()->addCommand(parentCommand);
557 }
558}
559
561{
562 m_textCursor.setVisualMode(m_optionManager->optionsModel()->useVisualBidiCursor());
563}
564
566{
567 m_textCursor.setPasteRichTextByDefault(m_optionManager->optionsModel()->pasteRichtTextByDefault());
568}
569
571{
572 KoSvgTextShape *shape = selectedShape();
573 QActionGroup *typeConvertGroup = action("text_type_preformatted")->actionGroup();
574 if (typeConvertGroup) {
575 typeConvertGroup->setExclusive(true);
576 }
577 Q_FOREACH (QAction *a, typeConvertGroup->actions()) {
578 a->setCheckable(true);
579 }
580 if (m_optionManager) {
581 if (shape) {
582 m_optionManager->convertToTextType(int(shape->textType()));
583 if (typeConvertGroup) {
584 typeConvertGroup->setEnabled(true);
585 }
586 action("text_type_preformatted")->setChecked(shape->textType() == KoSvgTextShape::PreformattedText);
587 action("text_type_pre_positioned")->setChecked(shape->textType() == KoSvgTextShape::PrePositionedText);
588 action("text_type_inline_wrap")->setChecked(shape->textType() == KoSvgTextShape::InlineWrap);
589
590 } else {
591 m_optionManager->convertToTextType(-1);
592 if (typeConvertGroup) {
593 typeConvertGroup->setEnabled(false);
594 }
595 }
596 const bool enableTypeSetting = (m_optionManager->typeSettingMode() && shape && (shape->textType() == KoSvgTextShape::PreformattedText ||shape->textType() == KoSvgTextShape::PrePositionedText));
597 action("svg_type_setting_move_selection_start_down_1_px")->actionGroup()->setEnabled(enableTypeSetting);
599 }
600}
601
603{
604 KoSvgTextShape *shape = selectedShape();
605 if (!shape) return;
606 QPointF offset;
607 // test type setting mode.
608 if (index == Qt::Key_Down) {
609 offset = QPointF(0, 1);
610 } else if (index == Qt::Key_Up) {
611 offset = QPointF(0, -1);
612 } else if (index == Qt::Key_Right) {
613 offset = QPointF(-1, 0);
614 } else if (index == Qt::Key_Left) {
615 offset = QPointF(1, 0);
616 } else {
617 return;
618 }
619 const KisCanvas2 *canvas2 = qobject_cast<const KisCanvas2 *>(this->canvas());
620 if (canvas2) {
621 offset = canvas2->coordinatesConverter()->imageToDocumentTransform().map(offset);
622 }
623 KUndo2Command *parentCommand = new KUndo2Command();
627 parentCommand->setText(cmd->text());
628 canvas()->addCommand(parentCommand);
629}
630
636
638{
639 QRectF rect;
640 KoSvgTextShape *const shape = selectedShape();
641 if (shape) {
642 rect |= shape->boundingRect();
643
644 const QPointF anchor = shape->absoluteTransformation().map(QPointF());
645 rect |= kisGrowRect(QRectF(anchor, anchor), handleRadius());
646
647 qreal pxlToPt = canvas()->viewConverter()->viewToDocumentX(1.0);
649
650 if (std::optional<InlineSizeInfo> info = InlineSizeInfo::fromShape(shape, length * pxlToPt)) {
651 rect |= kisGrowRect(info->boundingRect(), handleRadius() * 2);
652 }
653
654 if (canvas()->snapGuide()->isSnapping()) {
656 }
657 }
658
659 rect |= m_hoveredShapeHighlightRect.boundingRect();
660
661 rect |= m_textOutlineHelper->decorationRect();
662 rect |= m_textOnPathHelper.decorationRect(canvas()->viewConverter()->documentToView());
663
664 return rect;
665}
666
667void SvgTextTool::paint(QPainter &gc, const KoViewConverter &converter)
668{
669 if (!isActivated()) return;
670
672 m_interactionStrategy->paint(gc, converter);
673 }
674
675 KoSvgTextShape *shape = selectedShape();
676 if (shape) {
677 KisHandlePainterHelper handlePainter =
679
682 QPainterPath path;
683 path.addRect(shape->outlineRect());
684 handlePainter.drawPath(path);
685 }
686
687 qreal pxlToPt = canvas()->viewConverter()->viewToDocumentX(1.0);
689 if (std::optional<InlineSizeInfo> info = InlineSizeInfo::fromShape(shape, length * pxlToPt)) {
691 handlePainter.drawConnectionLine(info->baselineLineLocal());
692
696 }
698 handlePainter.drawHandleLine(info->startLineLocal());
699 handlePainter.drawHandleLine(info->startLineDashes(), INLINE_SIZE_HANDLE_THICKNESS, dashPattern, INLINE_SIZE_DASHES_PATTERN_A);
700
705 }
706 handlePainter.drawHandleLine(info->endLineLocal());
707 handlePainter.drawHandleLine(info->endLineDashes(), INLINE_SIZE_HANDLE_THICKNESS, dashPattern, INLINE_SIZE_DASHES_PATTERN_A);
708 }
709
712 } else {
714 }
715 handlePainter.drawHandleCircle(QPointF(), KoToolBase::handleRadius() * 0.75);
716 }
717
718 m_textOutlineHelper->setDecorationThickness(decorationThickness());
719 m_textOutlineHelper->setHandleRadius(handleRadius());
720 m_textOutlineHelper->paint(&gc, converter);
723 m_textOnPathHelper.paint(&gc, converter);
724 gc.setTransform(converter.documentToView(), true);
725 {
727 if (!m_hoveredShapeHighlightRect.isEmpty()) {
729 QPainterPath path;
730 path.addPath(m_hoveredShapeHighlightRect);
731 handlePainter.drawPath(path);
732 }
733 }
734 if (shape) {
735 m_textCursor.paintDecorations(gc, qApp->palette().color(QPalette::Highlight), decorationThickness(), handleRadius());
736 }
738 gc.save();
739 canvas()->snapGuide()->paint(gc, converter);
740 gc.restore();
741 }
742
743 // Paint debug outline
744 if (debugEnabled() && shape) {
745 gc.save();
746 using Element = KoSvgTextShape::DebugElement;
747 KoSvgTextShape::DebugElements el{};
748 if (m_optionManager->showCharacterDebug()) {
749 el |= Element::CharBbox;
750 }
751 if (m_optionManager->showLineDebug()) {
752 el |= Element::LineBox;
753 }
754
755 gc.setTransform(shape->absoluteTransformation(), true);
756 shape->paintDebug(gc, el);
757 gc.restore();
758 }
759}
760
762{
763 // When using touch drawing, we only ever receive move events after the
764 // finger has pressed down. We have to issue an artificial move here so that
765 // the tool's state is updated properly to handle the press.
766 if (event->isTouchEvent()) {
767 mouseMoveEvent(event);
768 }
769
771
772 if (selectedShape) {
773 if (m_textOutlineHelper->contourModeButtonHovered(event->point)) {
774 m_textOutlineHelper->toggleTextContourMode(selectedShape);
775 event->accept();
776 KoToolManager::instance()->switchToolRequested("InteractionTool");
777 return;
778 }
779
782 if (handle != SvgTextCursor::NoHandle) {
787 }
788 event->accept();
789 return;
790 }
794 m_textOutlineHelper->setDrawTextWrappingArea(false);
795 event->accept();
796 return;
797 } else if (m_textOnPathHelper.hitTest(event->point, canvas()->viewConverter()->viewToDocument())) {
801 event->accept();
802 return;
806 event->accept();
807 return;
811 event->accept();
812 return;
816 event->accept();
817 return;
818 }
819 }
820
821 KoSvgTextShape *hoveredShape = dynamic_cast<KoSvgTextShape *>(canvas()->shapeManager()->shapeAt(event->point));
822 KoPathShape *hoveredFlowShape = dynamic_cast<KoPathShape *>(canvas()->shapeManager()->shapeAt(event->point));
823 QString shapeType;
824 QPainterPath hoverPath = KisToolUtils::shapeHoverInfoCrossLayer(canvas(), event->point, shapeType);
825 bool crossLayerPossible = !hoverPath.isEmpty() && shapeType == KoSvgTextShape_SHAPEID;
826
827 if (!selectedShape && !hoveredShape && !hoveredFlowShape && !crossLayerPossible) {
828 QPointF point = canvas()->snapGuide()->snap(event->point, event->modifiers());
829 m_interactionStrategy.reset(new SvgCreateTextStrategy(this, point));
831 event->accept();
832 } else if (hoveredShape) {
833 if (hoveredShape != selectedShape) {
835 canvas()->shapeManager()->selection()->select(hoveredShape);
836 m_hoveredShapeHighlightRect = QPainterPath();
837 }
838 m_interactionStrategy.reset(new SvgSelectTextStrategy(this, &m_textCursor, event->point, event->modifiers()));
840 event->accept();
841 } else if (hoveredFlowShape) {
842 QPointF point = canvas()->snapGuide()->snap(event->point, event->modifiers());
843 m_interactionStrategy.reset(new SvgCreateTextStrategy(this, point, hoveredFlowShape));
845 event->accept();
846 } else if (crossLayerPossible) {
848 m_interactionStrategy.reset(new SvgSelectTextStrategy(this, &m_textCursor, event->point, event->modifiers()));
850 m_hoveredShapeHighlightRect = QPainterPath();
851 } else {
853 }
854 event->accept();
855 } else { // if there's a selected shape but no hovered shape...
857 event->accept();
858 }
859
861}
862
863static inline Qt::CursorShape angleToCursor(const QVector2D unit)
864{
865 constexpr float SIN_PI_8 = 0.382683432;
866 if (unit.y() < SIN_PI_8 && unit.y() > -SIN_PI_8) {
867 return Qt::SizeHorCursor;
868 } else if (unit.x() < SIN_PI_8 && unit.x() > -SIN_PI_8) {
869 return Qt::SizeVerCursor;
870 } else if ((unit.x() > 0 && unit.y() > 0) || (unit.x() < 0 && unit.y() < 0)) {
871 return Qt::SizeFDiagCursor;
872 } else {
873 return Qt::SizeBDiagCursor;
874 }
875}
876
877static inline Qt::CursorShape lineToCursor(const QLineF line, const KoCanvasBase *const canvas)
878{
879 const KisCanvas2 *const canvas2 = qobject_cast<const KisCanvas2 *>(canvas);
880 KIS_ASSERT(canvas2);
881 const KisCoordinatesConverter *const converter = canvas2->coordinatesConverter();
882 QLineF wdgLine = converter->flakeToWidget(line);
883 return angleToCursor(QVector2D(wdgLine.p2() - wdgLine.p1()).normalized());
884}
885
887{
888 m_lastMousePos = event->point;
889 m_hoveredShapeHighlightRect = QPainterPath();
891
893 m_interactionStrategy->handleMouseMove(event->point, event->modifiers());
896 if (c && c->draggingInlineSize() && !c->hasWrappingShape()) {
897 if (this->writingMode() == KoSvgText::HorizontalTB) {
899 } else {
901 }
902 } else {
904 }
905 } else if (m_dragging == DragMode::Select && this->selectedShape()) {
907 // Todo: replace with something a little less hacky.
908 if (selectedShape->writingMode() == KoSvgText::HorizontalTB) {
910 } else {
912 }
913 } else if (m_dragging != DragMode::InShapeOffset) {
914 useCursor(Qt::ArrowCursor);
915 }
916 event->accept();
917 } else {
919
921 QCursor cursor = m_base_cursor;
922 if (selectedShape) {
924 const qreal sensitivity = grabSensitivityInPt();
925
928 if (handle != SvgTextCursor::NoHandle) {
931 }
932
934 if (std::optional<InlineSizeInfo> info = InlineSizeInfo::fromShape(selectedShape)) {
935 const QPolygonF zone = info->endLineGrabRect(sensitivity);
936 const QPolygonF startZone = info->startLineGrabRect(sensitivity);
937 if (zone.containsPoint(event->point, Qt::OddEvenFill)) {
939 cursor = lineToCursor(info->baselineLine(), canvas());
940 } else if (startZone.containsPoint(event->point, Qt::OddEvenFill)){
942 cursor = lineToCursor(info->baselineLine(), canvas());
943 }
944 }
945 }
946
948 const QPolygonF textOutline = selectedShape->absoluteTransformation().map(selectedShape->outlineRect());
949 const QPolygonF moveBorderRegion = selectedShape->absoluteTransformation().map(kisGrowRect(selectedShape->outlineRect(),
950 sensitivity * 2));
951 if (moveBorderRegion.containsPoint(event->point, Qt::OddEvenFill) && !textOutline.containsPoint(event->point, Qt::OddEvenFill)) {
953 cursor = Qt::SizeAllCursor;
954 }
955 }
956 }
957
958 QString shapeType;
959 bool isHorizontal = true;
960 const KoSvgTextShape *hoveredShape = dynamic_cast<KoSvgTextShape *>(canvas()->shapeManager()->shapeAt(event->point));
961 const KoPathShape *hoveredFlowShape = dynamic_cast<KoPathShape *>(canvas()->shapeManager()->shapeAt(event->point));
962 QPainterPath hoverPath = KisToolUtils::shapeHoverInfoCrossLayer(canvas(), event->point, shapeType, &isHorizontal);
963
964 bool textAreasHovered = false;
965 if (m_textOnPathHelper.hitTest(event->point, canvas()->viewConverter()->viewToDocument()) ) {
966 cursor = Qt::ArrowCursor;
967 } else if(std::optional<QPointF> offsetVector = SvgChangeTextPaddingMarginStrategy::hitTest(selectedShape, event->point, grabSensitivityInPt())) {
968 cursor = lineToCursor(QLineF(QPointF(0, 0), offsetVector.value()).normalVector(), canvas());
969 textAreasHovered = true;
970 } else if (selectedShape && selectedShape == hoveredShape && m_highlightItem == HighlightItem::None) {
973 } else {
975 }
976 } else if (hoveredShape && m_highlightItem == HighlightItem::None) {
977 if (!hoveredShape->textWrappingAreas().isEmpty()) {
978 Q_FOREACH(QPainterPath path, hoveredShape->textWrappingAreas()) {
979 m_hoveredShapeHighlightRect.addPath(hoveredShape->absoluteTransformation().map(path));
980 }
981 } else {
982 m_hoveredShapeHighlightRect.addRect(hoveredShape->boundingRect());
983 }
984 if (hoveredShape->writingMode() == KoSvgText::HorizontalTB) {
986 } else {
988 }
989 } else if (hoveredFlowShape) {
990 m_hoveredShapeHighlightRect.addPath(hoveredFlowShape->absoluteTransformation().map(hoveredFlowShape->outline()));
991 if (hoveredFlowShape->segmentAtPoint(event->point, handleGrabRect(event->point)).isValid()) {
993 } else {
995 }
996 } else if (!hoverPath.isEmpty() && shapeType == KoSvgTextShape_SHAPEID && m_highlightItem == HighlightItem::None) {
997 m_hoveredShapeHighlightRect = hoverPath;
998 if (isHorizontal) {
1000 } else {
1002 }
1003 }
1004 m_textOutlineHelper->setTextAreasHovered(textAreasHovered);
1006 event->ignore();
1007 }
1008
1010}
1011
1013{
1015 m_interactionStrategy->finishInteraction(event->modifiers());
1016 KUndo2Command *const command = m_interactionStrategy->createCommand();
1017 if (command) {
1019 canvas()->addCommand(command);
1021 }
1022 m_interactionStrategy = nullptr;
1025 }
1027 m_textOutlineHelper->setDrawTextWrappingArea(true);
1030 event->accept();
1031 } else {
1033 }
1034 event->accept();
1035}
1036
1037void SvgTextTool::keyPressEvent(QKeyEvent *event)
1038{
1040 && (event->key() == Qt::Key_Control || event->key() == Qt::Key_Alt || event->key() == Qt::Key_Shift
1041 || event->key() == Qt::Key_Meta)) {
1042 m_interactionStrategy->handleMouseMove(m_lastMousePos, event->modifiers());
1043 event->accept();
1044 return;
1045 } else if (event->key() == Qt::Key_Escape) {
1047 } else if (selectedShape()) {
1049 }
1050
1051 event->ignore();
1052}
1053
1054void SvgTextTool::keyReleaseEvent(QKeyEvent *event)
1055{
1056 m_textCursor.updateModifiers(event->modifiers());
1058 && (event->key() == Qt::Key_Control || event->key() == Qt::Key_Alt || event->key() == Qt::Key_Shift
1059 || event->key() == Qt::Key_Meta)) {
1060 m_interactionStrategy->handleMouseMove(m_lastMousePos, event->modifiers());
1061 event->accept();
1062 } else {
1063 event->ignore();
1064 }
1065}
1066
1067void SvgTextTool::focusInEvent(QFocusEvent *event)
1068{
1070 event->accept();
1071}
1072
1073void SvgTextTool::focusOutEvent(QFocusEvent *event)
1074{
1076 event->accept();
1077}
1078
1080{
1081 if (canvas()->shapeManager()->shapeAt(event->point) != selectedShape()) {
1082 event->ignore(); // allow the event to be used by another
1083 return;
1084 } else {
1085 m_textCursor.setPosToPoint(event->point, true);
1088 }
1089 const QRectF updateRect = std::exchange(m_hoveredShapeHighlightRect, QPainterPath()).boundingRect();
1090 canvas()->updateCanvas(kisGrowRect(updateRect, 100));
1091 event->accept();
1092}
1093
1095{
1096 if (canvas()->shapeManager()->shapeAt(event->point) == selectedShape()) {
1097 // TODO: Consider whether we want to use sentence based selection instead:
1098 // QTextBoundaryFinder allows us to find sentences if necessary.
1101 event->accept();
1102 }
1103}
1104
1106{
1107 const int sensitivity = grabSensitivity();
1108 return canvas()->viewConverter()->viewToDocumentX(sensitivity);
1109}
1110
1116
1117void SvgTextTool::addMappedAction(KisSignalMapper *mapper, const QString &actionName, const int value, QActionGroup *group)
1118{
1119 QAction *a = action(actionName);
1120 if (a) {
1121 connect(a, SIGNAL(triggered()), mapper, SLOT(map()));
1122 mapper->setMapping(a, value);
1123 m_textCursor.registerPropertyAction(a, actionName);
1124 if (group && !a->actionGroup()) {
1125 group->addAction(a);
1126 }
1127 }
1128}
1129
qreal length(const QPointF &vec)
Definition Ellipse.cc:82
float value(const T *src, size_t ch)
#define KoSvgTextShape_SHAPEID
constexpr double INLINE_SIZE_DASHES_PATTERN_A
static Qt::CursorShape lineToCursor(const QLineF line, const KoCanvasBase *const canvas)
constexpr int INLINE_SIZE_DASHES_PATTERN_LENGTH
Size of the hidden part of the inline-size handle dashes.
constexpr double INLINE_SIZE_HANDLE_THICKNESS
Total amount of trailing dashes on inline-size handles.
constexpr double INLINE_SIZE_DASHES_PATTERN_B
Size of the visible part of the inline-size handle dashes.
static Qt::CursorShape angleToCursor(const QVector2D unit)
static bool debugEnabled()
Linethickness.
The GlyphPaletteDialog class.
void setText(const KUndo2MagicString &text)
The KisAllresourcesModel class provides access to the cache database for a particular resource type....
QVector< KoResourceSP > resourcesForName(const QString &name) const
KisCoordinatesConverter * coordinatesConverter
void setCurrentShapeManagerOwnerShape(KoShape *source) override
sets the group shape that is supposed to be "entered"
KisImageWSP image() const
KisViewManager * viewManager() const
_Private::Traits< T >::Result flakeToWidget(const T &obj) const
The KisHandlePainterHelper class is a special helper for painting handles around objects....
void drawPath(const QPainterPath &path)
void drawConnectionLine(const QLineF &line)
void setHandleStyle(const KisHandleStyle &style)
void drawHandleLine(const QLineF &line, qreal width=1.0, QVector< qreal > dashPattern={}, qreal dashOffset=0.0)
void drawHandleCircle(const QPointF &center, qreal radius)
static KisHandleStyle & highlightedPrimaryHandlesWithSolidOutline()
static KisHandleStyle & highlightedPrimaryHandles()
static KisHandleStyle & partiallyHighlightedPrimaryHandles()
static KisHandleStyle & secondarySelection()
static KisHandleStyle & primarySelection()
double xRes() const
QDockWidget * dockWidget(const QString &id)
The PopupWidgetInterface abstract class defines the basic interface that will be used by all popup wi...
The KisQQuickWidget class.
void connectMinimumHeightToRootObject()
connectMinimumHeightToRootObject By default we scale rootObject to widget, but in some situations we ...
static KisAllResourcesModel * resourceModel(const QString &resourceType)
void addConnection(Sender sender, Signal signal, Receiver receiver, Method method, Qt::ConnectionType type=Qt::AutoConnection)
The KisSignalMapper class bundles signals from identifiable senders.
void setMapping(QObject *sender, int id)
void setTextPropertiesInterface(KoSvgTextPropertiesInterface *interface)
setTextPropertiesInterface set the text properties interface. This should be done on tool activation....
KisMainWindow * mainWindow() const
KisTextPropertiesManager * textPropertyManager() const
KoSnapGuide * snapGuide
virtual KoShapeManager * shapeManager() const =0
virtual const KoViewConverter * viewConverter() const =0
virtual void updateCanvas(const QRectF &rc)=0
virtual void addCommand(KUndo2Command *command)=0
QPointer< KoCanvasResourceProvider > resourceManager
virtual KoSelectedShapesProxy * selectedShapesProxy() const =0
selectedShapesProxy() is a special interface for keeping a persistent connections to selectionChanged...
A simple solid color shape background.
The KoCssStylePreset class.
bool isValid() const
Returns if segment is valid, e.g. has two valid points.
The position of a path point within a path shape.
Definition KoPathShape.h:63
KoPathSegment segmentAtPoint(const QPointF &point, const QRectF &grabRoi) const
QPainterPath outline() const override
reimplemented
bool isTouchEvent() const
Qt::KeyboardModifiers modifiers() const
QPointF point
The point in document coordinates.
virtual KoSelection * selection()=0
void deselectAll()
clear the selections list
void select(KoShape *shape)
const QList< KoShape * > selectedEditableShapes() const
KoShape * shapeAt(const QPointF &position, KoFlake::ShapeSelection selection=KoFlake::ShapeOnTop, bool omitHiddenShapes=true)
KoSelection * selection
QTransform absoluteTransformation() const
Definition KoShape.cpp:335
static KisHandlePainterHelper createHandlePainterHelperView(QPainter *painter, KoShape *shape, const KoViewConverter &converter, qreal handleRadius=0.0, int decorationThickness=1)
Definition KoShape.cpp:982
void paint(QPainter &painter, const KoViewConverter &converter)
paints the guide
QPointF snap(const QPointF &mousePosition, Qt::KeyboardModifiers modifiers)
snaps the mouse position, returns if mouse was snapped
QRectF boundingRect()
returns the bounding rect of the guide
The SvgConvertTextTypeCommand class This command allows textshapes to be converted between preformatt...
@ FillId
KoSvgText::BackgroundProperty.
@ WritingModeId
KoSvgText::WritingMode.
QMap< QString, QString > convertToSvgTextAttributes() const
QMap< QString, QString > convertParagraphProperties() const
convertParagraphProperties some properties only apply to the root shape, so we write those separately...
void setProperty(PropertyId id, const QVariant &value)
QVariant propertyOrDefault(PropertyId id) const
static void removeContourShapesFromFlow(KoSvgTextShape *textShape, KUndo2Command *parent, bool textInShape, bool textPaths)
removeContourShapesFromFlow Create a command to remove all contour shapes of a certain type from the ...
The KoSvgTextShapeOutlineHelper class helper class that draws the text outlines and contour mode butt...
int posLeft(int pos, bool visual=false)
QRectF boundingRect() const override
Get the bounding box of the shape.
QList< QPainterPath > textWrappingAreas() const
textWrappingAreas The text wrapping areas are computed from shapesInside() and shapesSubtract(),...
int indexForPos(int pos) const
indexForPos get the string index for a given cursor position.
@ PreformattedText
Text-on-Path falls under this or PrePositionedText depending on collapse of lines.
@ TextInShape
Uses shape-inside to wrap and preserves spaces.
@ InlineWrap
Uses inline size to wrap and preserves spaces.
TextType textType() const
textType This enum gives an indication of what kind of text this shape is. The different text types a...
int posRight(int pos, bool visual=false)
void paintDebug(QPainter &painter, DebugElements elements) const
KoSvgText::WritingMode writingMode() const
writingMode There's a number of places we need to check the writing mode to provide proper controls.
QRectF outlineRect() const override
KoCanvasBase * canvas() const
Returns the canvas the tool is working on.
void selectionChanged(bool hasSelection)
Q_INVOKABLE QString toolId() const
QCursor cursor() const
return the last emitted cursor
int grabSensitivity() const
Convenience function to get the current grab sensitivity.
void setTextMode(bool value)
virtual void repaintDecorations()
int handleRadius() const
Convenience function to get the current handle radius.
void useCursor(const QCursor &cursor)
virtual void activate(const QSet< KoShape * > &shapes)
bool isInTextMode() const
QRectF handleGrabRect(const QPointF &position) const
virtual void deactivate()
QAction * action(const QString &name) const
bool isActivated() const
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const
int decorationThickness() const
decorationThickness The minimum thickness for tool decoration lines, this is derived from the screen ...
void switchToolRequested(const QString &id)
static KoToolManager * instance()
Return the toolmanager singleton.
virtual qreal viewToDocumentX(qreal viewX) const
virtual QPointF documentToView(const QPointF &documentPoint) const
static std::optional< QPointF > hitTest(KoSvgTextShape *shape, const QPointF &mousePos, const qreal grabSensitivityInPts)
hitTest Tests whether the current mouse position is over a text wrapping area, and if so,...
QRectF decorationRect(const QTransform documentToView) const
decorationRect
void setShape(KoSvgTextShape *shape)
setShape Set the shape for which to draw the text path.
void paint(QPainter *painter, const KoViewConverter &converter)
paint Paint the handles for the text path.
bool hitTest(QPointF mouseInPts, const QTransform viewToDocument)
hitTest
void setPos(int pos)
setPos the the position of the cursor, where the text path is sought. A single text shape can have mu...
static QStringList possibleActions()
The SvgTextToolOptionsManager class.
void openTextPropertiesDocker(bool open)
void activate(const QSet< KoShape * > &shapes) override
reimplemented from KoToolBase
void mouseTripleClickEvent(KoPointerEvent *event) override
reimplemented from KoToolBase
void copy() const override
reimplemented from superclass
bool selectAll() override
selectAll select all data the tool can select.
KisSignalAutoConnectionsStore m_canvasConnections
~SvgTextTool() override
void requestStrokeCancellation() override
void inputMethodEvent(QInputMethodEvent *event) override
QScopedPointer< KisSignalMapper > m_textTypeSignalsMapper
void mouseMoveEvent(KoPointerEvent *event) override
reimplemented from KoToolBase
std::unique_ptr< KoInteractionStrategy > m_interactionStrategy
void keyPressEvent(QKeyEvent *event) override
void requestStrokeEnd() override
void slotTextTypeUpdated()
slotTextTypeUpdated Update the text type in the tool options.
QPointer< GlyphPaletteDialog > m_glyphPalette
QScopedPointer< SvgTextToolOptionsManager > m_optionManager
QCursor m_base_cursor
KoSelection * koSelection() const
DragMode m_dragging
void mouseReleaseEvent(KoPointerEvent *event) override
reimplemented from KoToolBase
void slotUpdateVisualCursor()
slotUpdateVisualCursor update the visual cursor mode on the text cursor.
QString generateDefs(const KoSvgTextProperties &properties=KoSvgTextProperties())
generateDefs This generates a defs section with the appropriate css and css strings assigned.
qreal grabSensitivityInPt() const
void deleteSelection() override
reimplemented from superclass
QCursor m_text_inline_horizontal
QCursor m_ibeam_horizontal
KoSvgTextShape * selectedShape() const
QPointF m_lastMousePos
QCursor m_ibeam_horizontal_done
SvgTextTool(KoCanvasBase *canvas)
QVariant inputMethodQuery(Qt::InputMethodQuery query) const override
void slotShapeSelectionChanged()
selectionChanged called when the canvas selection is changed.
void showGlyphPalette()
showGlyphPalette Shows the glyph palette dialog.
QCursor m_text_inline_vertical
QPainterPath m_hoveredShapeHighlightRect
void focusInEvent(QFocusEvent *event) override
bool hasSelection() override
reimplemented from superclass
SvgTextOnPathDecorationHelper m_textOnPathHelper
KoSvgTextProperties propertiesForNewText() const
propertiesForNewText get the text properties that should be used for new text.
void updateGlyphPalette()
updateGlyphPalette update the glyph palette dialog from the current selection.
void mouseDoubleClickEvent(KoPointerEvent *event) override
reimplemented from superclass
bool m_strategyAddingCommand
KisPopupWidgetInterface * popupWidget() override
HighlightItem m_highlightItem
void focusOutEvent(QFocusEvent *event) override
void updateTextPathHelper()
KoToolSelection * selection() override
reimplemented from superclass
void slotUpdateTextPasteBehaviour()
slotUpdateTextPasteBehaviour update the default text paste behaviour.
void deselect() override
deselect the tool should clear the selection if it has one.
QCursor m_ibeam_vertical
virtual QWidget * createOptionWidget() override
reimplemented from KoToolBase
void insertRichText(KoSvgTextShape *richText, bool replaceLastGlyph=false)
insertRichText Insert a rich text shape, used by the glyph palette..
QCursor m_text_in_shape
void textUpdated(KoSvgTextShape *shape, const QString &svg, const QString &defs)
void deactivate() override
reimplemented from KoToolBase
void mousePressEvent(KoPointerEvent *event) override
reimplemented from KoToolBase
void slotUpdateCursorDecoration(QRectF updateRect)
updateCursor update the canvas decorations in a particular update rect for the text cursor.
QCursor m_text_on_path
void showEditor()
friend class SvgChangeTextPathInfoStrategy
Definition SvgTextTool.h:40
friend class SvgCreateTextStrategy
Definition SvgTextTool.h:39
QScopedPointer< KisSignalMapper > m_typeSettingMovementMapper
void slotMoveTextSelection(int index)
slotMoveTextSelection Move the start of the selection in typesetting mode by image 1 pix.
void paint(QPainter &gc, const KoViewConverter &converter) override
reimplemented from KoToolBase
SvgTextCursor m_textCursor
KoSvgText::WritingMode writingMode() const
QScopedPointer< KoSvgTextShapeOutlineHelper > m_textOutlineHelper
QRectF decorationsRect() const override
reimplemented from KoToolBase
bool paste() override
reimplemented from superclass
void slotUpdateTypeSettingMode()
slotUpdateTypeSettingMode Enable typesetting mode from the tool options.
void slotConvertType(int index)
slotConvertType
void addMappedAction(KisSignalMapper *mapper, const QString &actionName, const int value, QActionGroup *group=nullptr)
QPointer< SvgTextEditor > m_editor
void keyReleaseEvent(QKeyEvent *event) override
The SvgTextTypeSettingStrategy class This class encompasses the typesetting mode.
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
#define dbgTools
Definition kis_debug.h:48
T kisGrowRect(const T &rect, U offset)
Definition kis_global.h:186
bool selectShapeCrossLayer(KoCanvasBase *canvas, const QPointF &point, const QString &shapeType, bool skipCurrentShapes)
selectShapeCrossLayer Tries to select a shape under the cursor regardless of which layer it is on,...
QPainterPath shapeHoverInfoCrossLayer(KoCanvasBase *canvas, const QPointF &point, QString &shapeType, bool *isHorizontal, bool skipCurrentShapes)
shapeHoverInfoCrossLayer get hover info of shapes on all layers.
@ SvgTextPropertyData
KoSvgTextPropertyDataStruct.
@ HorizontalTB
Definition KoSvgText.h:38
const QString CssStyles
The KoSvgTextPropertyData struct.
KoSvgTextProperties commonProperties
The properties common between all the selected text.
BackgroundProperty is a special wrapper around KoShapeBackground for managing it in KoSvgTextProperti...
Definition KoSvgText.h:714
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()
int getAnchor()
Get the current selection anchor. This is the same as position, unless there's a selection.
QPair< KoSvgTextProperties, KoSvgTextProperties > currentTextProperties() const
currentTextProperties
void paintDecorations(QPainter &gc, QColor selectionColor, int decorationThickness=1, qreal handleRadius=5.0)
Paint all decorations and blinkingcursors.
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.
TypeSettingModeHandle
Handles used by type setting mode.
void inputMethodEvent(QInputMethodEvent *event)
Process an input method event. This is used by IME like virtual keyboards.
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
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.
bool setDominantBaselineFromHandle(const TypeSettingModeHandle handle)
setDominantBaselineFromHandle Set the dominant baseline from a given handle.
int getPos()
Get the current position.
void focusOut()
Stops blinking cursor.
TypeSettingModeHandle typeSettingHandleAtPos(const QRectF regionOfInterest)
Get typeSettingMode handle for text;.
bool registerPropertyAction(QAction *action, const QString &name)
Register an action.
void focusIn()
Turns on blinking cursor.
void setDrawTypeSettingHandle(bool draw)
bool paste()
paste pastes plain text in the clipboard at pos. Uses pasteRichTextByDefault to determine whether to ...
void updateTypeSettingDecorFromShape()
Update the type setting decorations.
void updateModifiers(const Qt::KeyboardModifiers modifiers)
void setShape(KoSvgTextShape *textShape)
setShape
void insertRichText(KoSvgTextShape *insert, bool inheritPropertiesIfPossible=false)
Insert rich text at getPos();.
KoSvgTextShape * shape
void copy() const
copy copies plain text into the clipboard between anchor and pos.