1 /*
2     This file is part of KCachegrind.
3 
4     SPDX-FileCopyrightText: 2003-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
5 
6     SPDX-License-Identifier: GPL-2.0-only
7 */
8 
9 /*
10  * Trace Item View
11  */
12 
13 #ifndef TRACEITEMVIEW_H
14 #define TRACEITEMVIEW_H
15 
16 #include <QTimer>
17 
18 #include "tracedata.h"
19 
20 class QWidget;
21 class QMenu;
22 
23 class TopLevelBase;
24 class TraceItemView;
25 
26 /* Helper class for TraceItemView for merging update requests.
27  *
28  * This can not be directly done in TraceItemView which can not have slots,
29  * as this would need TraceItemView to be inherited from QObject. However,
30  * we want subclasses of TraceItemView to also inherit from QWidget, and
31  * multiple inheritance of a QObject is impossible
32  */
33 class TraceItemViewUpdateTimer: public QTimer
34 {
35     Q_OBJECT
36 
37 public:
38     explicit TraceItemViewUpdateTimer(TraceItemView* view);
39 
40 private Q_SLOTS:
41     void timeoutTriggered();
42 
43 private:
44     TraceItemView* _view;
45 };
46 
47 
48 /**
49  * Abstract Base Class for KCachegrind Views
50  *
51  * This class delivers the shared functionality of all KCachegrind
52  * Views for one ProfileCost (like Function, Object...), the "active"
53  * item. Additional view attributes are current primary cost type,
54  * an optional secondary cost type, group type,
55  * and possibly a selected costitem in this view.
56  * Note that there is a difference in changing the selected item of
57  * a view (this usually changes selection in other views, too), and
58  * activating that item.
59  */
60 class TraceItemView
61 {
62     friend class TraceItemViewUpdateTimer;
63 
64 public:
65 
66     /**
67      * Change type for update functions
68      * - @c dataChanged is used if e.g. cycles are recalculated
69      */
70     enum { nothingChanged      = 0,
71            eventTypeChanged    = 1,
72            eventType2Changed   = 2,
73            groupTypeChanged    = 4,
74            partsChanged        = 8,
75            activeItemChanged   = 16,
76            selectedItemChanged = 32,
77            dataChanged         = 64,
78            configChanged       = 128 };
79 
80     enum Direction { None, Back, Forward, Up };
81 
82     // a TraceItemView can have a position in a parent container
83     enum Position { Hidden, Top, Right, Left, Bottom };
84 
85     explicit TraceItemView(TraceItemView* parentView, TopLevelBase* top = nullptr);
86     virtual ~TraceItemView();
87 
88     virtual QString whatsThis() const;
89 
90     // visualization layout and options (uses ConfigStorage)
91     virtual void saveLayout(const QString& prefix, const QString& postfix);
92     virtual void restoreLayout(const QString& prefix, const QString& postfix);
93     virtual void saveOptions(const QString& prefix, const QString& postfix);
94     virtual void restoreOptions(const QString& prefix, const QString& postfix);
95 
96     // Immediate remove all references to old data, and set the new.
97     // This resets the visualization state.
98     // A GUI update has to be triggered with updateView().
99     // Overwrite in container views to also set new data for all members.
100     virtual void setData(TraceData* d);
101 
102     // modify visualization state, updates automatically
setEventType(EventType * t)103     void setEventType(EventType* t) { _newEventType = t; updateView(); }
setEventType2(EventType * t)104     void setEventType2(EventType* t) { _newEventType2 = t; updateView(); }
set(ProfileContext::Type g)105     void set(ProfileContext::Type g) { _newGroupType = g; updateView(); }
set(const TracePartList & l)106     void set(const TracePartList& l) { _newPartList = l; updateView(); }
107     // returns false if nothing can be shown for this trace item
108     bool activate(CostItem* i);
109     void select(CostItem* i);
notifyChange(int changeType)110     void notifyChange(int changeType) { _status |= changeType; updateView(); }
111     // all in one
112     bool set(int, TraceData*, EventType*, EventType*,
113              ProfileContext::Type, const TracePartList&,
114              CostItem*, CostItem*);
115 
116     // if mergeUpdates is true (default), calls to updateView do not
117     // directly trigger an update of the view
setMergeUpdates(bool b)118     void setMergeUpdates(bool b) { _mergeUpdates = b; }
119 
120     // general update request, call if view is/gets visible
121     // force: update immediately even if invisible and no change was detected
122     void updateView(bool force = false);
123 
124     /**
125      * Notification from child views.
126      * Default implementation notifies parent
127      */
128     virtual void selected(TraceItemView* sender, CostItem*);
129     virtual void partsSelected(TraceItemView* sender, const TracePartList&);
130     virtual void directionActivated(TraceItemView* sender, Direction);
131     virtual void selectedEventType(TraceItemView* sender, EventType*);
132     virtual void selectedEventType2(TraceItemView* sender, EventType*);
133     virtual void activated(TraceItemView* sender, CostItem*);
134     virtual void selectedGroupType(TraceItemView* sender, ProfileContext::Type);
135 
136     // getters...
137     // always get the newest values
data()138     TraceData* data() const { return _newData; }
activeItem()139     CostItem* activeItem() const { return _newActiveItem; }
selectedItem()140     CostItem* selectedItem() const { return _newSelectedItem; }
eventType()141     EventType* eventType() const { return _newEventType; }
eventType2()142     EventType* eventType2() const { return _newEventType2; }
groupType()143     ProfileContext::Type groupType() const { return _newGroupType; }
partList()144     const TracePartList& partList() const { return _newPartList; }
145 
146     TraceFunction* activeFunction();
status()147     int status() const { return _status; }
148 
149     // pointer to top level window to e.g. show status messages
setTopLevel(TopLevelBase * t)150     void setTopLevel(TopLevelBase* t) { _topLevel = t; }
topLevel()151     TopLevelBase* topLevel() const { return _topLevel; }
152 
setPosition(Position p)153     void setPosition(Position p) { _pos = p; }
position()154     Position position() const { return _pos; }
155 
setTitle(QString t)156     void setTitle(QString t) { _title = t; }
title()157     QString title() const { return _title; }
158 
159     // We depend on derived class to be a widget.
160     // Force overriding by making this abstract.
161     virtual QWidget* widget() = 0;
162 
163     /**
164      * Called when a new item is about to become active.
165      * Itemviews should reimplement this to notify that a
166      * given item cannot be shown (return 0) or should be
167      * redirected to another item to be shown as active.
168      *
169      * Use the methods like data() instead of _data here, as
170      * _data possibly will give old/wrong information.
171      */
canShow(CostItem * i)172     virtual CostItem* canShow(CostItem* i) { return i; }
173 
174     /* convenience functions for often used context menu items */
175     void addEventTypeMenu(QMenu*,bool withCost2 = true);
176     void addGoMenu(QMenu*);
177 
178 protected:
179     // helpers to call selected()/activated() of parentView
180     void selected(CostItem*);
181     void partsSelected(const TracePartList&);
182     void activated(CostItem*);
183     void selectedEventType(EventType*);
184     void selectedEventType2(EventType*);
185     void selectedGroupType(ProfileContext::Type);
186     void directionActivated(TraceItemView::Direction);
187 
188     /* Is this view visible?
189      * if not, doUpdate() will not be called by updateView()
190      */
191     virtual bool isViewVisible();
192 
193     // update handler (to be reimplemented)
194     virtual void doUpdate(int changeType, bool force);
195 
196     TraceItemView* _parentView;
197     TopLevelBase* _topLevel;
198 
199     TraceData* _data;
200     TracePartList _partList;
201     CostItem *_activeItem, *_selectedItem;
202     EventType *_eventType, *_eventType2;
203     ProfileContext::Type _groupType;
204 
205 private:
206     /* Multiple update requests via updateView() are merged, and result in one
207      * call to triggerUpdate() after a timeout (using TraceItemViewUpdateTimer)
208      */
209     void triggerUpdate(bool force);
210 
211     TraceData* _newData;
212     TracePartList _newPartList;
213     CostItem *_newActiveItem, *_newSelectedItem;
214     EventType *_newEventType, *_newEventType2;
215     ProfileContext::Type _newGroupType;
216     TraceItemViewUpdateTimer* _updateTimer;
217 
218     QString _title;
219     int _status;
220     bool _mergeUpdates, _needsUpdate;
221     Position _pos;
222 };
223 
224 
225 
226 #endif
227