1 /*
2     SPDX-FileCopyrightText: 2002 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
3     SPDX-FileCopyrightText: 2002 John Firebaugh <jfirebaugh@kde.org>
4     SPDX-FileCopyrightText: 2007 Hamish Rodda <rodda@kde.org>
5 
6     SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 
10 #ifndef KDEVPLATFORM_BREAKPOINTMODEL_H
11 #define KDEVPLATFORM_BREAKPOINTMODEL_H
12 
13 #include <QAbstractTableModel>
14 
15 #include <KTextEditor/MarkInterface>
16 #include "breakpoint.h"
17 
18 class QUrl;
19 
20 namespace KParts { class Part; }
21 namespace KTextEditor {
22 class Cursor;
23 }
24 
25 namespace KDevelop
26 {
27 class IDocument;
28 class Breakpoint;
29 class BreakpointModelPrivate;
30 
31 class KDEVPLATFORMDEBUGGER_EXPORT BreakpointModel : public QAbstractTableModel
32 {
33     Q_OBJECT
34 
35 public:
36     enum Column {
37         /**
38          * Whether the breakpoint is active or not (settable by user): value is Qt::Checked
39          * or Qt::Unchecked.
40          */
41         EnableColumn,
42 
43         /**
44          * Synchronization state of the breakpoint (not settable by user): value is one of the
45          * BreakpointState enum values.
46          */
47         StateColumn,
48 
49         /**
50          * Kind/type of breakpoint (never changes): value is one of the BreakpointKind
51          * enum values.
52          */
53         KindColumn,
54 
55         /**
56          * Location of the breakpoint (modifiable by user); value is a string describing the
57          * location; note that the formatting of retrieved data can be affected by a custom
58          * BreakpointRole.
59          */
60         LocationColumn,
61 
62         /**
63          * Condition for conditional breakpoints (modifiable by user).
64          */
65         ConditionColumn,
66 
67         /**
68          * The number of times this breakpoint has been hit (cannot be modified by the user).
69          */
70         HitCountColumn,
71 
72         /**
73          * How many hits of the breakpoint will be ignored before the breakpoint actually stops
74          * the program (can be modified by the user and is updated by the debugger backend).
75          */
76         IgnoreHitsColumn,
77 
78         NumColumns
79     };
80 
81     enum ColumnFlag {
82         EnableColumnFlag = 1 << EnableColumn,
83         StateColumnFlag = 1 << StateColumn,
84         KindColumnFlag = 1 << KindColumn,
85         LocationColumnFlag = 1 << LocationColumn,
86         ConditionColumnFlag = 1 << ConditionColumn,
87         HitCountColumnFlag = 1 << HitCountColumn,
88         IgnoreHitsColumnFlag = 1 << IgnoreHitsColumn
89     };
90     Q_DECLARE_FLAGS(ColumnFlags, ColumnFlag)
91 
92     explicit BreakpointModel(QObject* parent);
93     ~BreakpointModel() override;
94 
95     QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
96     Qt::ItemFlags flags(const QModelIndex &index) const override;
97     QModelIndex breakpointIndex(Breakpoint *b, int column);
98     bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
99     int rowCount(const QModelIndex& parent = QModelIndex()) const override;
100     int columnCount(const QModelIndex& parent = QModelIndex()) const override;
101 
102      ///Note: to retrieve the full path use Breakpoint::LocationRole, Qt::DisplayRole returns only a file's name
103     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
104     bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
105 
106     void toggleBreakpoint(const QUrl &url, const KTextEditor::Cursor& cursor);
107 
108 
109     KDevelop::Breakpoint* addCodeBreakpoint();
110     KDevelop::Breakpoint* addCodeBreakpoint(const QUrl& location, int line);
111     KDevelop::Breakpoint* addCodeBreakpoint(const QString& expression);
112     KDevelop::Breakpoint* addWatchpoint();
113     KDevelop::Breakpoint* addWatchpoint(const QString& expression);
114     KDevelop::Breakpoint* addReadWatchpoint();
115     KDevelop::Breakpoint* addReadWatchpoint(const QString& expression);
116     KDevelop::Breakpoint* addAccessWatchpoint();
117     KDevelop::Breakpoint* addAccessWatchpoint(const QString& expression);
118 
119     Breakpoint* breakpoint(int row) const;
120     QList<Breakpoint*> breakpoints() const;
121 
122 Q_SIGNALS:
123     void error(int row, const QString& errorText);
124     void hit(int row);
125 
126 public Q_SLOTS:
127     void save();
128     void load();
129 
130 private:
131     enum MarkType {
132         BreakpointMark = KTextEditor::MarkInterface::BreakpointActive,
133         ReachedBreakpointMark  = KTextEditor::MarkInterface::BreakpointReached,
134         DisabledBreakpointMark = KTextEditor::MarkInterface::BreakpointDisabled,
135         PendingBreakpointMark   = KTextEditor::MarkInterface::markType08,
136 
137         AllBreakpointMarks = BreakpointMark | ReachedBreakpointMark | DisabledBreakpointMark | PendingBreakpointMark
138     };
139 
140 private Q_SLOTS:
141 
142     void updateMarks();
143 
144     void slotPartAdded(KParts::Part* part);
145 
146     /**
147     * Called by the TextEditor interface when the marks have changed position
148     * because the user has added or removed source.
149     * In here we figure out if we need to reset the breakpoints due to
150     * these source changes.
151     */
152     void markChanged(KTextEditor::Document *document, KTextEditor::Mark mark, KTextEditor::MarkInterface::MarkChangeAction action);
153     void textDocumentCreated(KDevelop::IDocument*);
154     void documentSaved(KDevelop::IDocument*);
155     void aboutToDeleteMovingInterfaceContent(KTextEditor::Document *document);
156 
157     void markContextMenuRequested( KTextEditor::Document* document, KTextEditor::Mark mark,
158                                const QPoint &pos, bool& handled );
159 
160 private:
161     static const QPixmap* breakpointPixmap();
162     static const QPixmap* pendingBreakpointPixmap();
163     static const QPixmap* reachedBreakpointPixmap();
164     static const QPixmap* disabledBreakpointPixmap();
165 
166 private:
167     friend class Breakpoint;
168     friend class IBreakpointController;
169 
170     void updateState(int row, Breakpoint::BreakpointState state);
171     void updateHitCount(int row, int hitCount);
172     void updateErrorText(int row, const QString& errorText);
173     void notifyHit(int row);
174 
175     void registerBreakpoint(Breakpoint* breakpoint);
176     void scheduleSave();
177 
178     void reportChange(Breakpoint *breakpoint, Breakpoint::Column column);
179     uint breakpointType(Breakpoint *breakpoint) const;
180     Breakpoint *breakpoint(const QUrl& url, int line) const;
181 
182     void setupMovingCursor(KTextEditor::Document* document, Breakpoint* breakpoint) const;
183 
184 private:
185     const QScopedPointer<class BreakpointModelPrivate> d_ptr;
186     Q_DECLARE_PRIVATE(BreakpointModel)
187 };
188 
189 #if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
190 Q_DECLARE_OPERATORS_FOR_FLAGS(BreakpointModel::ColumnFlags)
191 #endif
192 
193 }
194 
195 #if QT_VERSION < QT_VERSION_CHECK(5, 12, 0)
196 Q_DECLARE_OPERATORS_FOR_FLAGS(KDevelop::BreakpointModel::ColumnFlags)
197 #endif
198 
199 #endif
200