26#include <QPainterPath>
27#include <QDesktopServices>
28#include <QApplication>
33#include <klocalizedstring.h>
37#include <KSharedConfig>
86 static const bool debugEnabled = !qEnvironmentVariableIsEmpty(
"KRITA_DEBUG_TEXTTOOL");
92 , m_textCursor(canvas)
96 int cursorFlashLimit = 5000;
98 , qApp->cursorFlashTime()
103 QAction *a =
action(name);
105 dbgTools <<
"registered" << name << a->shortcut();
110 "svg_insert_special_character",
111 "svg_paste_rich_text",
112 "svg_paste_plain_text"
115 Q_FOREACH (
const QString name, extraActions) {
116 QAction *a =
action(name);
119 qWarning() <<
"could not register" << name << a->shortcut();
125 const QMap<QString, int> convertActions {
130 Q_FOREACH(
const QString name, convertActions.keys()) {
131 QAction *a =
action(name);
136 m_base_cursor = QCursor(QPixmap(
":/tool_text_basic.xpm"), 7, 7);
139 m_text_on_path = QCursor(QPixmap(
":/tool_text_on_path.xpm"), 7, 7);
142 m_ibeam_vertical = QCursor(QPixmap(
":/tool_text_i_beam_vertical.xpm"), 11, 11);
161 const KisCanvas2 *canvas2 = qobject_cast<const KisCanvas2 *>(this->
canvas());
183 const KisCanvas2 *canvas2 = qobject_cast<const KisCanvas2 *>(this->
canvas());
217 optionWidget->setMinimumWidth(100);
218 optionWidget->setMinimumHeight(100);
220 optionWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
221 optionWidget->setSource(QUrl(
"qrc:/SvgTextToolOptions.qml"));
224 if (optionWidget->errors().isEmpty()) {
225 optionWidget->rootObject()->setProperty(
"manager", QVariant::fromValue(
m_optionManager.data()));
228 qWarning() << optionWidget->errors();
238 const KisCanvas2 *canvas2 = qobject_cast<const KisCanvas2 *>(this->
canvas());
243 optionWidget->setPalette(docker->palette());
246 docker->setVisible(!docker->isVisible());
273 if (shapes.isEmpty())
return 0;
287 m_editor->setWindowTitle(i18nc(
"@title:window",
"Krita - Edit Text"));
288 m_editor->setWindowModality(Qt::ApplicationModal);
289 m_editor->setAttribute( Qt::WA_QuitOnClose,
false );
300 m_editor->setWindowFlags(Qt::Dialog);
301 m_editor->menuBar()->setNativeMenuBar(
false);
333 QString grapheme = QString();
347 if (replaceLastGlyph) {
365 for (
auto it = paraProps.constBegin(); it != paraProps.constEnd(); it++) {
366 propStrings.append(QString(
"%1: %2;").arg(it.key()).arg(it.value()));
369 for (
auto it = paraProps.constBegin(); it != paraProps.constEnd(); it++) {
370 propStrings.append(QString(
"%1: %2;").arg(it.key()).arg(it.value()));
373 return QString(
"<defs>\n <style>\n text {\n %1\n }\n </style>\n</defs>").arg(propStrings.join(
"\n "));
378 const bool useCurrent =
m_optionManager->optionsModel()->useCurrentTextProperties();
379 const QString presetName =
m_optionManager->optionsModel()->cssStylePresetName();
382 if (useCurrent || presetName.isEmpty()) {
396 props = style->properties(dpi,
true);
405 bg->setColor(fontColor);
414 if (shapes.size() == 1) {
420 }
else if (shapes.size() > 1) {
423 Q_FOREACH (
KoShape *shape, shapes) {
426 foundTextShape = textShape;
432 if (foundTextShape) {
524 parentCommand->
setText(cmd->text());
547 action(
"text_type_preformatted")->setEnabled(
true);
548 action(
"text_type_pre_positioned")->setEnabled(
true);
549 action(
"text_type_inline_wrap")->setEnabled(
true);
555 action(
"text_type_preformatted")->setEnabled(
false);
556 action(
"text_type_pre_positioned")->setEnabled(
false);
557 action(
"text_type_inline_wrap")->setEnabled(
false);
575 if (std::optional<InlineSizeInfo> info = InlineSizeInfo::fromShape(shape,
length * pxlToPt)) {
579 if (
canvas()->snapGuide()->isSnapping()) {
612 if (std::optional<InlineSizeInfo> info = InlineSizeInfo::fromShape(shape,
length * pxlToPt)) {
664 KoSvgTextShape::DebugElements el{};
666 el |= Element::CharBbox;
669 el |= Element::LineBox;
706 if (!
selectedShape && !hoveredShape && !crossLayerPossible) {
711 }
else if (hoveredShape) {
720 }
else if (crossLayerPossible) {
739 constexpr float SIN_PI_8 = 0.382683432;
740 if (unit.y() < SIN_PI_8 && unit.y() > -SIN_PI_8) {
741 return Qt::SizeHorCursor;
742 }
else if (unit.x() < SIN_PI_8 && unit.x() > -SIN_PI_8) {
743 return Qt::SizeVerCursor;
744 }
else if ((unit.x() > 0 && unit.y() > 0) || (unit.x() < 0 && unit.y() < 0)) {
745 return Qt::SizeFDiagCursor;
747 return Qt::SizeBDiagCursor;
753 const KisCanvas2 *
const canvas2 = qobject_cast<const KisCanvas2 *>(canvas);
757 return angleToCursor(QVector2D(wdgLine.p2() - wdgLine.p1()).normalized());
797 if (std::optional<InlineSizeInfo> info = InlineSizeInfo::fromShape(
selectedShape)) {
798 const QPolygonF zone = info->endLineGrabRect(sensitivity);
799 const QPolygonF startZone = info->startLineGrabRect(sensitivity);
800 if (zone.containsPoint(event->
point, Qt::OddEvenFill)) {
803 }
else if (startZone.containsPoint(event->
point, Qt::OddEvenFill)){
813 if (moveBorderRegion.containsPoint(event->
point, Qt::OddEvenFill) && !textOutline.containsPoint(event->
point, Qt::OddEvenFill)) {
815 cursor = Qt::SizeAllCursor;
821 bool isHorizontal =
true;
830 }
else if (hoveredShape) {
836 paths.addPath(hoveredShape->
absoluteTransformation().map(path->absoluteTransformation().map(path->outline())));
839 if (!paths.isEmpty()) {
910 && (event->key() == Qt::Key_Control || event->key() == Qt::Key_Alt || event->key() == Qt::Key_Shift
911 || event->key() == Qt::Key_Meta)) {
915 }
else if (event->key() == Qt::Key_Escape) {
927 && (event->key() == Qt::Key_Control || event->key() == Qt::Key_Alt || event->key() == Qt::Key_Shift
928 || event->key() == Qt::Key_Meta)) {
qreal length(const QPointF &vec)
#define KoSvgTextShape_SHAPEID
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
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
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 ¢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 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.
A KoPathSegment consist of two neighboring KoPathPoints.
bool isValid() const
Returns if segment is valid, e.g. has two valid points.
The position of a path point within a path shape.
bool isClosedSubpath(int subpathIndex) const
Checks if a subpath is closed.
QPainterPath outline() const override
reimplemented
int subpathCount() const
Returns the number of subpaths in the path.
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
int posLeft(int pos, bool visual=false)
QRectF boundingRect() const override
Get the bounding box of the shape.
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.
@ InlineWrap
Uses inline size to wrap and preserves spaces.
QList< KoShape * > shapesInside
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
bool draggingInlineSize()
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.
void slotTextEditorClosed()
QCursor m_text_inline_vertical
QPainterPath m_hoveredShapeHighlightRect
void focusInEvent(QFocusEvent *event) override
bool hasSelection() override
reimplemented from superclass
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
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 SvgCreateTextStrategy
void paint(QPainter &gc, const KoViewConverter &converter) override
reimplemented from KoToolBase
SvgTextCursor m_textCursor
KoSvgText::WritingMode writingMode() const
QRectF decorationsRect() const override
reimplemented from KoToolBase
bool paste() override
reimplemented from superclass
void slotConvertType(int index)
slotConvertType
QPointer< SvgTextEditor > m_editor
void keyReleaseEvent(QKeyEvent *event) override
#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 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 setCaretSetting(int cursorWidth=1, int cursorFlash=1000, int cursorFlashLimit=5000)
setCaretSetting Set the caret settings for the cursor. Qt has some standard functionality associated,...
QPair< KoSvgTextProperties, KoSvgTextProperties > currentTextProperties() const
currentTextProperties
bool hasSelection() override
return true if the tool currently has something selected that can be copied or deleted.
void setPos(int pos, int anchor)
Set the pos and the anchor.
void insertRichText(KoSvgTextShape *insert)
Insert rich text at getPos();.
void inputMethodEvent(QInputMethodEvent *event)
void setPosToPoint(QPointF point, bool moveAnchor=true)
Set the pos from a point. This currently does a search inside the text shape.
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
void removeSelection()
removeSelection if there's a selection, creates a text-removal command.
int getPos()
Get the current position.
void focusOut()
Stops blinking cursor.
bool registerPropertyAction(QAction *action, const QString &name)
Register an action.
void focusIn()
Turns on blinking cursor.
void paintDecorations(QPainter &gc, QColor selectionColor, int decorationThickness=1)
bool paste()
paste pastes plain text in the clipboard at pos. Uses pasteRichTextByDefault to determine whether to ...
void setShape(KoSvgTextShape *textShape)
setShape
void copy() const
copy copies plain text into the clipboard between anchor and pos.