1 /* This file is part of the KDE project
2  * Copyright (C) 2006-2009 Thomas Zander <zander@kde.org>
3  * Copyright (C) 2008 Thorsten Zachmann <zachmann@kde.org>
4  * Copyright (C) 2009 KO GmbH <cbo@kogmbh.com>
5  * Copyright (C) 2011 Mojtaba Shahi Senobari <mojtaba.shahi3000@gmail.com>
6  * Copyright (C) 2008, 2012 Pierre Stirnweiss <pstirnweiss@googlemail.org>
7  * Copyright (C) 2014 Denis Kuplyakov <dener.kup@gmail.com>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24 
25 #ifndef KOTEXTTOOL_H
26 #define KOTEXTTOOL_H
27 
28 #include "TextShape.h"
29 #include "KoPointedAt.h"
30 
31 #include <KoToolBase.h>
32 #include <KoTextCommandBase.h>
33 #include <KoUnit.h>
34 #include <KoBorder.h>
35 
36 #include <QClipboard>
37 #include <QHash>
38 #include <QTextBlock>
39 #include <QTextCursor>
40 #include <QTimer>
41 #include <QWeakPointer>
42 #include <QRectF>
43 #include <QPointer>
44 
45 #include <TextEditingPluginContainer.h>
46 
47 class InsertCharacter;
48 class KoChangeTracker;
49 class KoCharacterStyle;
50 class KoColor;
51 class KoColorPopupAction;
52 class KoParagraphStyle;
53 class KoStyleManager;
54 class KoTextEditor;
55 class UndoTextCommand;
56 
57 class QAction;
58 class KActionMenu;
59 class KoFontFamilyAction;
60 class FontSizeAction;
61 
62 class KUndo2Command;
63 
64 class QDrag;
65 class QMimeData;
66 class QMenu;
67 
68 class MockCanvas;
69 class TextToolSelection;
70 
71 /**
72  * This is the tool for the text-shape (which is a flake-based plugin).
73  */
74 class TextTool : public KoToolBase, public KoUndoableTool
75 {
76     Q_OBJECT
77 public:
78     explicit TextTool(KoCanvasBase *canvas);
79 #ifndef NDEBUG
80     explicit TextTool(MockCanvas *canvas);
81 #endif
82     ~TextTool() override;
83 
84     /// reimplemented from superclass
85     void paint(QPainter &painter, const KoViewConverter &converter) override;
86 
87     /// reimplemented from superclass
88     void mousePressEvent(KoPointerEvent *event) override;
89     /// reimplemented from superclass
90     void mouseDoubleClickEvent(KoPointerEvent *event) override;
91     /// reimplemented from superclass
92     void mouseTripleClickEvent(KoPointerEvent *event) override;
93     /// reimplemented from superclass
94     void mouseMoveEvent(KoPointerEvent *event) override;
95     /// reimplemented from superclass
96     void mouseReleaseEvent(KoPointerEvent *event) override;
97     /// reimplemented from superclass
98     void keyPressEvent(QKeyEvent *event) override;
99     /// reimplemented from superclass
100     void keyReleaseEvent(QKeyEvent *event) override;
101     /// reimplemented from superclass
102     void activate(ToolActivation activation, const QSet<KoShape *> &shapes) override;
103     /// reimplemented from superclass
104     void deactivate() override;
105     /// reimplemented from superclass
106     void copy() const override;
107 
108     /// reimplemented from KoUndoableTool
setAddUndoCommandAllowed(bool allowed)109     void setAddUndoCommandAllowed(bool allowed) override
110     {
111         m_allowAddUndoCommand = allowed;
112     }
113 
114     ///reimplemented
115     void deleteSelection() override;
116     /// reimplemented from superclass
117     void cut() override;
118     /// reimplemented from superclass
119     bool paste() override;
120     /// reimplemented from superclass
121     void dragMoveEvent(QDragMoveEvent *event, const QPointF &point) override;
122     /// reimplemented from superclass
123     void dragLeaveEvent(QDragLeaveEvent *event) override;
124     /// reimplemented from superclass
125     void dropEvent(QDropEvent *event, const QPointF &point) override;
126 
127     /// reimplemented from superclass
128     void repaintDecorations() override;
129 
130     /// reimplemented from superclass
131     KoToolSelection *selection() override;
132     /// reimplemented from superclass
133     QList<QPointer<QWidget> > createOptionWidgets() override;
134 
135     /// reimplemented from superclass
136     QVariant inputMethodQuery(Qt::InputMethodQuery query, const KoViewConverter &converter) const override;
137     /// reimplemented from superclass
138     void inputMethodEvent(QInputMethodEvent *event) override;
139 
140     /// The following two methods allow an undo/redo command to tell the tool, it will modify the QTextDocument and wants to be parent of the undo/redo commands resulting from these changes.
141 
142     void startEditing(KUndo2Command *command);
143 
144     void stopEditing();
145 
146     void setShapeData(KoTextShapeData *data);
147 
148     QRectF caretRect(QTextCursor *cursor, bool *upToDate = 0) const;
149 
150     QRectF textRect(QTextCursor &cursor) const;
151 
152 protected:
153     virtual void createActions();
textShape()154     TextShape *textShape()
155     {
156         return m_textShape;
157     }
158 
159     friend class SimpleParagraphWidget;
160     friend class ParagraphSettingsDialog;
161 
textEditor()162     KoTextEditor *textEditor()
163     {
164         return m_textEditor.data();
165     }
166 
167 public Q_SLOTS:
168     /// Insert comment to document.
169     void insertAnnotation();
170     /// start the textedit-plugin.
171     void startTextEditingPlugin(const QString &pluginId);
172     /// reimplemented from KoToolBase
173     void canvasResourceChanged(int key, const QVariant &res) override;
174 
175 Q_SIGNALS:
176     /// emitted every time a different styleManager is set.
177     void styleManagerChanged(KoStyleManager *manager);
178     /// emitted every time a caret move leads to a different character format being under the caret
179     void charFormatChanged(const QTextCharFormat &format, const QTextCharFormat &refBlockCharFormat);
180     /// emitted every time a caret move leads to a different paragraph format being under the caret
181     void blockFormatChanged(const QTextBlockFormat &format);
182     /// emitted every time a caret move leads to a different paragraph format being under the caret
183     void blockChanged(const QTextBlock &block);
184 
185 private Q_SLOTS:
186     /// inserts new paragraph and includes it into the new section
187     void insertNewSection();
188     /// configures params of the current section
189     void configureSection();
190     /// inserts paragraph between sections bounds
191     void splitSections();
192     /// paste text from the clipboard without formatting
193     void pasteAsText();
194     /// make the selected text bold or not
195     void bold(bool);
196     /// make the selected text italic or not
197     void italic(bool);
198     /// underline of the selected text
199     void underline(bool underline);
200     /// strikethrough of the selected text
201     void strikeOut(bool strikeOut);
202     /// insert a non breaking space at the caret position
203     void nonbreakingSpace();
204     /// insert a non breaking hyphen at the caret position
205     void nonbreakingHyphen();
206     /// insert a soft hyphen at the caret position
207     void softHyphen();
208     /// insert a linebreak at the caret position
209     void lineBreak();
210     /// force the remainder of the text into the next page
211     void insertFrameBreak();
212     /// align all of the selected text left
213     void alignLeft();
214     /// align all of the selected text right
215     void alignRight();
216     /// align all of the selected text centered
217     void alignCenter();
218     /// align all of the selected text block-justified
219     void alignBlock();
220     /// make the selected text switch to be super-script
221     void superScript(bool);
222     /// make the selected text switch to be sub-script
223     void subScript(bool);
224     /// move the paragraph indent of the selected text to be less (left on LtR text)
225     void decreaseIndent();
226     /// move the paragraph indent of the selected text to be more (right on LtR text)
227     void increaseIndent();
228     /// Increase the font size. This will preserve eventual difference in font size within the selection.
229     void increaseFontSize();
230     /// Decrease font size. See above.
231     void decreaseFontSize();
232     /// Set font family
233     void setFontFamily(const QString &);
234     /// Set Font size
235     void setFontSize(qreal size);
236     /// see KoTextEditor::insertIndexMarker
237     void insertIndexMarker();
238     /// shows a dialog to insert a table
239     void insertTable();
240     /// insert a table of given dimensions
241     void insertTableQuick(int rows, int columns);
242     /// insert a row above
243     void insertTableRowAbove();
244     /// insert a row below
245     void insertTableRowBelow();
246     /// insert a column left
247     void insertTableColumnLeft();
248     /// insert a column right
249     void insertTableColumnRight();
250     /// delete a column
251     void deleteTableColumn();
252     /// delete a row
253     void deleteTableRow();
254     /// merge table cells
255     void mergeTableCells();
256     /// split previous merged table cells
257     void splitTableCells();
258     /// format the table border (enter table pen mode)
259     void setTableBorderData(const KoBorder::BorderData &data);
260     /// shows a dialog to alter the paragraph properties
261     void formatParagraph();
262     /// select all text in the current document.
263     void selectAll();
264     /// show the style manager
265     void showStyleManager(int styleId = -1);
266     /// change color of a selected text
267     void setTextColor(const KoColor &color);
268     /// change background color of a selected text
269     void setBackgroundColor(const KoColor &color);
270     /// Enable or disable grow-width-to-fit-text.
271     void setGrowWidthToFit(bool enabled);
272     /// Enable or disable grow-height-to-fit-text.
273     void setGrowHeightToFit(bool enabled);
274     /// Enable or disable shrink-to-fit-text.
275     void setShrinkToFit(bool enabled);
276     /// set Paragraph style of current selection. Existing style will be completely overridden.
277     void setStyle(KoParagraphStyle *style);
278     /// set the characterStyle of the current selection. see above.
279     void setStyle(KoCharacterStyle *style);
280     /// set the level of current selected list
281     void setListLevel(int level);
282 
283     /// slot to call when a series of commands is started that together need to become 1 undo action.
284     void startMacro(const QString &title);
285     /// slot to call when a series of commands has ended that together should be 1 undo action.
286     void stopMacro();
287 
288     /// show the insert special character docker.
289     void insertSpecialCharacter();
290     /// insert string
291     void insertString(const QString &string);
292 
293     /// returns the focus to canvas when styles are selected in the optionDocker
294     void returnFocusToCanvas();
295 
296     void selectFont();
297     void shapeAddedToCanvas();
298 
299     void blinkCaret();
300     void relayoutContent();
301 
302     // called when the m_textShapeData has been deleted.
303     void shapeDataRemoved();
304 
305     //Show tooltip with editing info
306     void showEditTip();
307 
308     /// print debug about the details of the text document
309     void debugTextDocument();
310     /// print debug about the details of the styles on the current text document
311     void debugTextStyles();
312 
313     void ensureCursorVisible(bool moveView = true);
314 
315     void createStyleFromCurrentBlockFormat(const QString &name);
316     void createStyleFromCurrentCharFormat(const QString &name);
317 
318     void testSlot(bool);
319 
320     /// change block text direction
321     void textDirectionChanged();
322 
323     void updateActions();
324 
325     QMenu* popupActionsMenu() override;
326 
327 private:
328     void repaintCaret();
329     void repaintSelection();
330     KoPointedAt hitTest(const QPointF &point) const;
331     void updateStyleManager();
332     void updateSelectedShape(const QPointF &point, bool noDocumentChange);
333     void updateSelectionHandler();
334     void editingPluginEvents();
335     void finishedWord();
336     void finishedParagraph();
337     void startingSimpleEdit();
338     void runUrl(KoPointerEvent *event, QString &url);
339     void useTableBorderCursor();
340 
341     QMimeData *generateMimeData() const;
342 
343     TextEditingPluginContainer *textEditingPluginContainer();
344 
345 private:
346     friend class UndoTextCommand;
347     friend class ChangeTracker;
348     friend class TextCutCommand;
349     friend class ShowChangesCommand;
350 
351     TextShape *m_textShape; // where caret of m_textEditor currently is
352     KoTextShapeData *m_textShapeData; // where caret of m_textEditor currently is
353     QWeakPointer<KoTextEditor> m_textEditor;
354     QWeakPointer<KoTextEditor> m_oldTextEditor;
355     KoChangeTracker *m_changeTracker;
356     KoUnit m_unit;
357     bool m_allowActions;
358     bool m_allowAddUndoCommand;
359     bool m_allowResourceManagerUpdates;
360     int m_prevCursorPosition; /// used by editingPluginEvents
361     int m_prevMouseSelectionStart, m_prevMouseSelectionEnd;
362 
363     QTimer m_caretTimer;
364     bool m_caretTimerState;
365     QAction *m_actionPasteAsText;
366     QAction *m_actionFormatBold;
367     QAction *m_actionFormatItalic;
368     QAction *m_actionFormatUnderline;
369     QAction *m_actionFormatStrikeOut;
370     QAction *m_actionAlignLeft;
371     QAction *m_actionAlignRight;
372     QAction *m_actionAlignCenter;
373     QAction *m_actionAlignBlock;
374     QAction *m_actionFormatSuper;
375     QAction *m_actionFormatSub;
376     QAction *m_actionFormatIncreaseIndent;
377     QAction *m_actionFormatDecreaseIndent;
378     QAction *m_growWidthAction;
379     QAction *m_growHeightAction;
380     QAction *m_shrinkToFitAction;
381     QAction *m_actionChangeDirection;
382     QAction *m_actionInsertSection;
383     QAction *m_actionConfigureSection;
384     QAction *m_actionSplitSections;
385     KActionMenu *m_variableMenu;
386 
387     FontSizeAction *m_actionFormatFontSize;
388     KoFontFamilyAction *m_actionFormatFontFamily;
389     KoColorPopupAction *m_actionFormatTextColor;
390     KoColorPopupAction *m_actionFormatBackgroundColor;
391 
392     KUndo2Command *m_currentCommand; //this command will be the direct parent of undoCommands generated as the result of QTextDocument changes
393 
394     bool m_currentCommandHasChildren;
395 
396     InsertCharacter *m_specialCharacterDocker;
397 
398     QPointer<TextEditingPluginContainer> m_textEditingPlugins;
399 
400     bool m_textTyping;
401     bool m_textDeleting;
402 
403     QTimer m_editTipTimer;
404     KoPointedAt m_editTipPointedAt;
405     QPoint m_editTipPos;
406 
407     bool m_delayedEnsureVisible;
408     TextToolSelection *m_toolSelection;
409 
410     KoPointedAt m_tableDragInfo;
411     bool m_tableDraggedOnce;
412     bool m_tableDragWithShift;
413     QPointF m_draggingOrigin;
414     qreal m_dx;
415     qreal m_dy;
416     bool m_tablePenMode;
417     KoBorder::BorderData m_tablePenBorderData;
418     mutable QRectF m_lastImMicroFocus;
419 
420     bool m_clickWithinSelection;
421     QDrag *m_drag;
422     QAbstractTextDocumentLayout::Selection m_preDragSelection;
423 
424     QScopedPointer<QMenu> m_contextMenu;
425 };
426 
427 #endif
428