31#include <QPainterPath>
32#include <QDesktopServices>
33#include <QApplication>
37#include <QActionGroup>
39#include <klocalizedstring.h>
43#include <KSharedConfig>
96 static const bool debugEnabled = !qEnvironmentVariableIsEmpty(
"KRITA_DEBUG_TEXTTOOL");
103 , m_textCursor(canvas)
107 const int cursorFlashLimit = 5000;
108 const bool enableCursorWithSelection = QApplication::style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected);
110 , qApp->cursorFlashTime()
112 , enableCursorWithSelection);
116 QAction *a =
action(name);
118 dbgTools <<
"registered" << name << a->shortcut();
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"
130 Q_FOREACH (
const QString name, extraActions) {
131 QAction *a =
action(name);
134 qWarning() <<
"could not register" << name << a->shortcut();
140 QActionGroup *textTypeActions =
new QActionGroup(
this);
146 QActionGroup *typeSettingActions =
new QActionGroup(
this);
157 m_base_cursor = QCursor(QPixmap(
":/tool_text_basic.xpm"), 7, 7);
160 m_text_on_path = QCursor(QPixmap(
":/tool_text_on_path.xpm"), 7, 7);
163 m_ibeam_vertical = QCursor(QPixmap(
":/tool_text_i_beam_vertical.xpm"), 11, 11);
206 const KisCanvas2 *canvas2 = qobject_cast<const KisCanvas2 *>(this->
canvas());
241 optionWidget->setMinimumWidth(100);
242 optionWidget->setMinimumHeight(100);
244 optionWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
245 optionWidget->setSource(QUrl(
"qrc:/SvgTextToolOptions.qml"));
249 if (optionWidget->errors().isEmpty()) {
250 optionWidget->rootObject()->setProperty(
"manager", QVariant::fromValue(
m_optionManager.data()));
253 qWarning() << optionWidget->errors();
264 const KisCanvas2 *canvas2 = qobject_cast<const KisCanvas2 *>(this->
canvas());
269 optionWidget->setPalette(docker->palette());
272 docker->setVisible(!docker->isVisible());
299 if (shapes.isEmpty())
return 0;
313 m_editor->setWindowTitle(i18nc(
"@title:window",
"Krita - Edit Text"));
314 m_editor->setWindowModality(Qt::ApplicationModal);
315 m_editor->setAttribute( Qt::WA_QuitOnClose,
false );
325 m_editor->setWindowFlags(Qt::Dialog);
326 m_editor->menuBar()->setNativeMenuBar(
false);
358 QString grapheme = QString();
377 if (replaceLastGlyph) {
388 for (
auto it = paraProps.constBegin(); it != paraProps.constEnd(); it++) {
389 propStrings.append(QString(
"%1: %2;").arg(it.key()).arg(it.value()));
392 for (
auto it = paraProps.constBegin(); it != paraProps.constEnd(); it++) {
393 propStrings.append(QString(
"%1: %2;").arg(it.key()).arg(it.value()));
396 return QString(
"<defs>\n <style>\n text {\n %1\n }\n </style>\n</defs>").arg(propStrings.join(
"\n "));
401 const bool useCurrent =
m_optionManager->optionsModel()->useCurrentTextProperties();
402 const QString presetName =
m_optionManager->optionsModel()->cssStylePresetName();
405 if (useCurrent || presetName.isEmpty()) {
419 props = style->properties(dpi,
true);
428 bg->setColor(fontColor);
437 if (shapes.size() == 1) {
443 }
else if (shapes.size() > 1) {
446 Q_FOREACH (
KoShape *shape, shapes) {
449 foundTextShape = textShape;
455 if (foundTextShape) {
545 if (index == shape->
textType())
return;
551 parentCommand->
setText(cmd->text());
573 QActionGroup *typeConvertGroup =
action(
"text_type_preformatted")->actionGroup();
574 if (typeConvertGroup) {
575 typeConvertGroup->setExclusive(
true);
577 Q_FOREACH (QAction *a, typeConvertGroup->actions()) {
578 a->setCheckable(
true);
583 if (typeConvertGroup) {
584 typeConvertGroup->setEnabled(
true);
592 if (typeConvertGroup) {
593 typeConvertGroup->setEnabled(
false);
597 action(
"svg_type_setting_move_selection_start_down_1_px")->actionGroup()->setEnabled(enableTypeSetting);
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);
619 const KisCanvas2 *canvas2 = qobject_cast<const KisCanvas2 *>(this->
canvas());
627 parentCommand->
setText(cmd->text());
650 if (std::optional<InlineSizeInfo> info = InlineSizeInfo::fromShape(shape,
length * pxlToPt)) {
654 if (
canvas()->snapGuide()->isSnapping()) {
689 if (std::optional<InlineSizeInfo> info = InlineSizeInfo::fromShape(shape,
length * pxlToPt)) {
747 KoSvgTextShape::DebugElements el{};
749 el |= Element::CharBbox;
752 el |= Element::LineBox;
827 if (!
selectedShape && !hoveredShape && !hoveredFlowShape && !crossLayerPossible) {
832 }
else if (hoveredShape) {
841 }
else if (hoveredFlowShape) {
846 }
else if (crossLayerPossible) {
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;
873 return Qt::SizeBDiagCursor;
879 const KisCanvas2 *
const canvas2 = qobject_cast<const KisCanvas2 *>(canvas);
883 return angleToCursor(QVector2D(wdgLine.p2() - wdgLine.p1()).normalized());
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)) {
940 }
else if (startZone.containsPoint(event->
point, Qt::OddEvenFill)){
951 if (moveBorderRegion.containsPoint(event->
point, Qt::OddEvenFill) && !textOutline.containsPoint(event->
point, Qt::OddEvenFill)) {
953 cursor = Qt::SizeAllCursor;
959 bool isHorizontal =
true;
964 bool textAreasHovered =
false;
969 textAreasHovered =
true;
989 }
else if (hoveredFlowShape) {
1040 && (event->key() == Qt::Key_Control || event->key() == Qt::Key_Alt || event->key() == Qt::Key_Shift
1041 || event->key() == Qt::Key_Meta)) {
1045 }
else if (event->key() == Qt::Key_Escape) {
1058 && (event->key() == Qt::Key_Control || event->key() == Qt::Key_Alt || event->key() == Qt::Key_Shift
1059 || event->key() == Qt::Key_Meta)) {
1119 QAction *a =
action(actionName);
1121 connect(a, SIGNAL(triggered()), mapper, SLOT(map()));
1124 if (group && !a->actionGroup()) {
1125 group->addAction(a);
qreal length(const QPointF &vec)
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
QTransform imageToDocumentTransform() 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 ¢er, qreal radius)
static KisHandleStyle & highlightedPrimaryHandlesWithSolidOutline()
static KisHandleStyle & highlightedPrimaryHandles()
static KisHandleStyle & partiallyHighlightedPrimaryHandles()
static KisHandleStyle & secondarySelection()
static KisHandleStyle & primarySelection()
QDockWidget * dockWidget(const QString &id)
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
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.
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)
QTransform absoluteTransformation() const
static KisHandlePainterHelper createHandlePainterHelperView(QPainter *painter, KoShape *shape, const KoViewConverter &converter, qreal handleRadius=0.0, int decorationThickness=1)
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
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,...
bool draggingInlineSize()
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 setStrategyActive(bool isActive)
void setHandleRadius(qreal radius)
void setDecorationThickness(qreal thickness)
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
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
KoSelection * koSelection() const
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
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.
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..
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.
friend class SvgChangeTextPathInfoStrategy
friend class SvgCreateTextStrategy
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)
T kisGrowRect(const T &rect, U offset)
@ SvgTextPropertyData
KoSvgTextPropertyDataStruct.
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...
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();.
void copy() const
copy copies plain text into the clipboard between anchor and pos.