1 /*
2     SPDX-FileCopyrightText: 2001 Christoph Cullmann <cullmann@kde.org>
3 
4     Documentation:
5     SPDX-FileCopyrightText: 2005 Dominik Haumann <dhdev@gmx.de>
6 
7     SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9 
10 #ifndef KTEXTEDITOR_MARKINTERFACE_H
11 #define KTEXTEDITOR_MARKINTERFACE_H
12 
13 #include <ktexteditor_export.h>
14 
15 #include <QHash>
16 #include <QObject>
17 
18 class QIcon;
19 class QPixmap;
20 class QPoint;
21 class QMenu;
22 
23 namespace KTextEditor
24 {
25 class Document;
26 
27 /**
28  * \class Mark markinterface.h <KTextEditor/MarkInterface>
29  *
30  * \brief Mark class containing line and mark types.
31  *
32  * \section mark_intro Introduction
33  *
34  * The class Mark represents a mark in a Document. It contains the \e line
35  * and \e type. A line can have multiple marks, like a \e bookmark and a
36  * \e breakpoint, i.e. the \e type contains all marks combined with a logical
37  * \e OR (<tt>|</tt>). There are several predefined mark types, look into the
38  * MarkInterface for further details.
39  *
40  * \see KTextEditor::MarkInterface, KTextEditor::Document
41  */
42 class Mark
43 {
44 public:
45     /** The line that contains the mark. */
46     int line;
47 
48     /** The mark types in the line, combined with logical OR. */
49     uint type;
50 };
51 
52 /**
53  * \class MarkInterface markinterface.h <KTextEditor/MarkInterface>
54  *
55  * \brief Mark extension interface for the Document.
56  *
57  * \ingroup kte_group_doc_extensions
58  *
59  * \section markext_intro Introduction
60  *
61  * The MarkInterface provides methods to enable and disable marks in a
62  * Document, a marked line can be visualized for example with a shaded
63  * background color and/or a pixmap in the iconborder of the Document's View.
64  * There are a number of predefined mark types, specified in
65  * reservedMarkersCount(). Additionally it is possible to add custom marks
66  * and set custom pixmaps.
67  *
68  * \section markext_access Accessing the Interface
69  *
70  * The MarkInterface is supposed to be an extension interface for a Document,
71  * i.e. the Document inherits the interface \e provided that the
72  * KTextEditor library in use implements the interface. Use qobject_cast to access
73  * the interface:
74  * \code
75  * // doc is of type KTextEditor::Document*
76  * auto iface = qobject_cast<KTextEditor::MarkInterface*>(doc);
77  *
78  * if (iface) {
79  *     // the implementation supports the interface
80  *     // do stuff
81  * } else {
82  *     // the implementation does not support the interface
83  * }
84  * \endcode
85  *
86  * \section markext_handling Handling Marks
87  *
88  * Get all marks in the document by calling marks(). Use clearMarks() to
89  * remove all marks in the entire document. A single mark can be retrieved
90  * with mark(). To remove all marks from a line call clearMark(). To add
91  * and remove marks from a given line use addMark() and removeMark(). It is
92  * also possible to replace all marks with setMark(), i.e. setMark() is the
93  * same as a call of clearMark() followed by addMark(). The signals
94  * marksChanged() and markChanged() are emitted whenever a line's marks
95  * changed.
96  *
97  * \attention A mark type is represented as an \e uint. An \e uint can have
98  *     several mark types combined (see above: logical OR). That means for
99  *     all functions/signals with an \e uint parameter, e.g. setMark(),
100  *     removeMark(), etc, the \e uint may contain \e multiple marks, i.e.
101  *     you can add and remove multiple marks \e simultaneously.
102  *
103  * \section markext_userdefined User Defined Marks
104  *
105  * All marks that should be editable by the user can be specified with a mark
106  * mask via setEditableMarks(). To set a description and pixmap of a mark type
107  * call setMarkDescription() and setMarkPixmap().
108  *
109  * \see KTextEditor::Document, KTextEditor::Mark
110  * \author Christoph Cullmann \<cullmann@kde.org\>
111  */
112 class KTEXTEDITOR_EXPORT MarkInterface
113 {
114 public:
115     MarkInterface();
116 
117     /**
118      * Virtual destructor.
119      */
120     virtual ~MarkInterface();
121 
122     //
123     // slots !!!
124     //
125 public:
126     /**
127      * Get all marks set on the \p line.
128      * \param line requested line
129      * \return a \e uint representing of the marks set in \p line concatenated
130      *         by logical OR
131      * \see addMark(), removeMark()
132      */
133     virtual uint mark(int line) = 0;
134 
135     /**
136      * Set the \p line's mark types to \p markType.
137      * If \p line already contains a mark of the given type it has no effect.
138      * All other marks are deleted before the mark is set. You can achieve
139      * the same by calling
140      * \code
141      * clearMark(line);
142      * addMark(line, markType);
143      * \endcode
144      * \param line line to set the mark
145      * \param markType mark type
146      * \see clearMark(), addMark(), mark()
147      */
148     virtual void setMark(int line, uint markType) = 0;
149 
150     /**
151      * Clear all marks set in the \p line.
152      * \param line line to clear marks
153      * \see clearMarks(), removeMark(), addMark()
154      */
155     virtual void clearMark(int line) = 0;
156 
157     /**
158      * Add marks of type \p markType to \p line. Existing marks on this line
159      * are preserved. If the mark \p markType already is set, nothing
160      * happens.
161      * \param line line to set the mark
162      * \param markType mark type
163      * \see removeMark(), setMark()
164      */
165     virtual void addMark(int line, uint markType) = 0;
166 
167     /**
168      * Remove the mark mask of type \p markType from \p line.
169      * \param line line to remove the mark
170      * \param markType mark type to be removed
171      * \see clearMark()
172      */
173     virtual void removeMark(int line, uint markType) = 0;
174 
175     /**
176      * Get a hash holding all marks in the document.
177      * The hash key for a mark is its line.
178      * \return a hash holding all marks in the document
179      *
180      * KF6 TODO: Change Mark* to Mark. No need for pointer here.
181      */
182     virtual const QHash<int, KTextEditor::Mark *> &marks() = 0;
183 
184     /**
185      * Clear all marks in the entire document.
186      * \see clearMark(), removeMark()
187      */
188     /// TODO: dominik: add argument unit mask = 0
189     virtual void clearMarks() = 0;
190 
191     /**
192      * Get the number of predefined mark types we have so far.
193      * \note FIXME: If you change this you have to make sure katepart
194      *              supports the new size!
195      * \return number of reserved marker types
196      */
reservedMarkersCount()197     static int reservedMarkersCount()
198     {
199         return 7;
200     }
201 
202     /**
203      * Predefined mark types.
204      *
205      * To add a new standard mark type, edit this interface and document
206      * the type.
207      */
208     enum MarkTypes {
209         /** Bookmark */
210         markType01 = 0x1,
211         /** Breakpoint active */
212         markType02 = 0x2,
213         /** Breakpoint reached */
214         markType03 = 0x4,
215         /** Breakpoint disabled */
216         markType04 = 0x8,
217         /** Execution mark */
218         markType05 = 0x10,
219         /** Warning */
220         markType06 = 0x20,
221         /** Error */
222         markType07 = 0x40,
223 
224         markType08 = 0x80,
225         markType09 = 0x100,
226         markType10 = 0x200,
227         markType11 = 0x400,
228         markType12 = 0x800,
229         markType13 = 0x1000,
230         markType14 = 0x2000,
231         markType15 = 0x4000,
232         markType16 = 0x8000,
233         markType17 = 0x10000,
234         markType18 = 0x20000,
235         markType19 = 0x40000,
236         markType20 = 0x80000,
237         markType21 = 0x100000,
238         markType22 = 0x200000,
239         markType23 = 0x400000,
240         markType24 = 0x800000,
241         markType25 = 0x1000000,
242         markType26 = 0x2000000,
243         markType27 = 0x4000000,
244         markType28 = 0x8000000,
245         markType29 = 0x10000000,
246         markType30 = 0x20000000,
247         markType31 = 0x40000000,
248         markType32 = 0x80000000,
249         /* reserved marks */
250         Bookmark = markType01,
251         BreakpointActive = markType02,
252         BreakpointReached = markType03,
253         BreakpointDisabled = markType04,
254         Execution = markType05,
255         Warning = markType06,
256         Error = markType07,
257         SearchMatch = markType32,
258     };
259 
260     //
261     // signals !!!
262     //
263 public:
264     /**
265      * The \p document emits this signal whenever a mark mask changed.
266      * \param document document which emitted this signal
267      * \see markChanged()
268      */
269     virtual void marksChanged(KTextEditor::Document *document) = 0;
270 
271     /*
272      * Methods to modify mark properties.
273      */
274 public:
275     /**
276      * Set the \p mark's pixmap to \p pixmap.
277      * \param mark mark to which the pixmap will be attached
278      * \param pixmap new pixmap
279      * \see setMarkDescription()
280      */
281     virtual void setMarkPixmap(MarkTypes mark, const QPixmap &pixmap) = 0;
282 
283     /**
284      * Get the \p mark's pixmap.
285      * \param mark mark type. If the pixmap does not exist the resulting is null
286      *        (check with QPixmap::isNull()).
287      * \see setMarkDescription()
288      */
289     virtual QPixmap markPixmap(MarkTypes mark) const = 0;
290 
291     /**
292      * Set the \p mark's description to \p text.
293      * \param mark mark to set the description
294      * \param text new descriptive text
295      * \see markDescription(), setMarkPixmap()
296      */
297     virtual void setMarkDescription(MarkTypes mark, const QString &text) = 0;
298 
299     /**
300      * Get the \p mark's description to text.
301      * \param mark mark to set the description
302      * \return text of the given \p mark or QString(), if the entry does not
303      *         exist
304      * \see setMarkDescription(), setMarkPixmap()
305      */
306     virtual QString markDescription(MarkTypes mark) const = 0;
307 
308     /**
309      * Set the mark mask the user is allowed to toggle to \p markMask.
310      * I.e. concatenate all editable marks with a logical OR. If the user should
311      * be able to add a bookmark and set a breakpoint with the context menu in
312      * the icon pane, you have to call
313      * \code
314      * // iface is of Type KTextEditor::MarkInterface*
315      * // only make bookmark and breakpoint editable
316      * iface->setEditableMarks( MarkInterface::Bookmark |
317      *                          MarkInterface::BreakpointActive );
318      *
319      * // or preserve last settings, and add bookmark and breakpoint
320      * iface->setEditableMarks( iface->editableMarks() |
321      *                          MarkInterface::Bookmark |
322      *                          MarkInterface::BreakpointActive );
323      * \endcode
324      * \param markMask bitmap pattern
325      * \see editableMarks(), setMarkPixmap(), setMarkDescription()
326      */
327     virtual void setEditableMarks(uint markMask) = 0;
328 
329     /**
330      * Get, which marks can be toggled by the user.
331      * The returned value is a mark mask containing all editable marks combined
332      * with a logical OR.
333      * \return mark mask containing all editable marks
334      * \see setEditableMarks()
335      */
336     virtual uint editableMarks() const = 0;
337 
338     /**
339      * Possible actions on a mark.
340      * \see markChanged()
341      */
342     enum MarkChangeAction {
343         MarkAdded = 0, /**< action: a mark was added.  */
344         MarkRemoved = 1 /**< action: a mark was removed. */
345     };
346 
347     //
348     // signals !!!
349     //
350 public:
351     /**
352      * The \p document emits this signal whenever the \p mark changes.
353      * \param document the document which emitted the signal
354      * \param mark changed mark
355      * \param action action, either removed or added
356      * \see marksChanged()
357      */
358     virtual void markChanged(KTextEditor::Document *document, KTextEditor::Mark mark, KTextEditor::MarkInterface::MarkChangeAction action) = 0;
359 
360 Q_SIGNALS:
361 
362     /**
363      * The \p document emits this signal whenever the \p mark is hovered using the mouse,
364      * and the receiver may show a tooltip.
365      * \param document the document which emitted the signal
366      * \param mark mark that was hovered
367      * \param position mouse position during the hovering
368      * \param handled set this to 'true' if this event was handled externally
369      */
370     void markToolTipRequested(KTextEditor::Document *document, KTextEditor::Mark mark, QPoint position, bool &handled);
371 
372     /**
373      * The \p document emits this signal whenever the \p mark is right-clicked to show a context menu.
374      * The receiver may show an own context menu instead of the kate internal one.
375      * \param document the document which emitted the signal
376      * \param mark mark that was right-clicked
377      * \param pos position where the menu should be started
378      * \param handled set this to 'true' if this event was handled externally, and kate should not create an own context menu.
379      */
380     void markContextMenuRequested(KTextEditor::Document *document, KTextEditor::Mark mark, QPoint pos, bool &handled);
381 
382     /**
383      * The \p document emits this signal whenever the \p mark is left-clicked.
384      * \param document the document which emitted the signal
385      * \param mark mark that was right-clicked
386      * \param handled set this to 'true' if this event was handled externally, and kate should not do own handling of the left click.
387      */
388     void markClicked(KTextEditor::Document *document, KTextEditor::Mark mark, bool &handled);
389 
390 private:
391     class MarkInterfacePrivate *const d = nullptr;
392 };
393 
394 /**
395  * \brief Mark extension interface for the Document, version 2
396  *
397  * \ingroup kte_group_doc_extensions
398  *
399  * \section markextv2_intro Introduction
400  *
401  * The MarkInterfaceV2 allows to do the same as MarkInterface
402  * and additionally
403  * - (1) set an icon for a mark type instead of just a pixmap
404  *
405  * \section markextv2_access Accessing the Interface
406  *
407  * The MarkInterfaceV2 is supposed to be an extension interface for a Document,
408  * i.e. the Document inherits the interface \e provided that the
409  * KTextEditor library in use implements the interface. Use qobject_cast to access
410  * the interface:
411  * \code
412  * // doc is of type KTextEditor::Document*
413  * auto iface = qobject_cast<KTextEditor::MarkInterfaceV2*>(doc);
414  *
415  * if (iface) {
416  *     // the implementation supports the interface
417  *     // do stuff
418  * } else {
419  *     // the implementation does not support the interface
420  * }
421  * \endcode
422  *
423  * \since 5.69
424  */
425 class KTEXTEDITOR_EXPORT MarkInterfaceV2 : public MarkInterface
426 {
427     // KF6: Merge KTextEditor::MarkInterfaceV2 into KTextEditor::MarkInterface, drop QPixmap API (kossebau)
428 public:
~MarkInterfaceV2()429     ~MarkInterfaceV2() override
430     {
431     }
432 
433     /**
434      * Set the \p mark's icon to \p icon.
435      * \param markType mark type to which the icon will be attached
436      * \param icon new icon
437      * \see setMarkDescription()
438      */
439     virtual void setMarkIcon(MarkTypes markType, const QIcon &icon) = 0;
440 
441     /**
442      * Get the \p mark's icon.
443      * \param markType mark type. If the icon does not exist the resulting is null
444      *        (check with QIcon::isNull()).
445      * \see setMarkDescription()
446      */
447     virtual QIcon markIcon(MarkTypes markType) const = 0;
448 };
449 
450 }
451 
452 Q_DECLARE_INTERFACE(KTextEditor::MarkInterface, "org.kde.KTextEditor.MarkInterface")
453 Q_DECLARE_INTERFACE(KTextEditor::MarkInterfaceV2, "org.kde.KTextEditor.MarkInterfaceV2")
454 
455 #endif
456