1 /*
2  * Copyright Johannes Sixt
3  * This file is licensed under the GNU General Public License Version 2.
4  * See the file COPYING in the toplevel directory of the source directory.
5  */
6 
7 #ifndef EXPRWND_H
8 #define EXPRWND_H
9 
10 #include <QTreeWidget>
11 #include <QLineEdit>
12 #include <QPixmap>
13 #include <list>
14 
15 class ProgramTypeTable;
16 class TypeInfo;
17 struct ExprValue;
18 class ExprWnd;
19 class QStringList;
20 
21 /*! \brief a variable's value is the tree of sub-variables */
22 class VarTree : public QTreeWidgetItem
23 {
24 public:
25     enum VarKind { VKsimple, VKpointer, VKstruct, VKarray,
26 	VKdummy				//!< used to update only children
27     };
28     VarKind m_varKind;
29     enum NameKind { NKplain, NKstatic, NKtype,
30 	NKanonymous,			//!< an anonymous struct or union
31 	NKaddress			//!< a dereferenced pointer
32     };
33     NameKind m_nameKind;
34     const TypeInfo* m_type;			//!< the type of struct if it could be derived
35     int m_exprIndex;			//!< used in struct value update
36     bool m_exprIndexUseGuard;		//!< ditto; if guard expr should be used
37     QString m_partialValue;		//!< while struct value update is in progress
38 
39     VarTree(VarTree* parent, ExprValue* v);
40     VarTree(ExprWnd* parent, ExprValue* v);
41     virtual ~VarTree();
42 public:
43     QString computeExpr() const;
44     bool isToplevelExpr() const;
45     /** is this element an ancestor of (or equal to) child? */
46     bool isAncestorEq(const VarTree* child) const;
47     /** update the regular value; returns whether a repaint is necessary */
48     bool updateValue(const QString& newValue);
49     /** update the "quick member" value; returns whether repaint is necessary */
50     bool updateStructValue(const QString& newValue);
51     /** find out the type of this value using the child values */
52     void inferTypesOfChildren(ProgramTypeTable& typeTable);
53     /** get the type from base class part */
54     const TypeInfo* inferTypeFromBaseClass();
55     /** returns whether the pointer is a wchar_t */
56     bool isWcharT() const;
57 
getText()58     QString getText() const { return text(0); }
59     using QTreeWidgetItem::setText;
setText(const QString & t)60     void setText(const QString& t) { QTreeWidgetItem::setText(0, t); }
setPixmap(const QPixmap & p)61     void setPixmap(const QPixmap& p) { QTreeWidgetItem::setIcon(0, QIcon(p)); }
value()62     QString value() const { return m_baseValue; }
63     QString displayedValue() const;
child(int i)64     VarTree* child(int i) const { return static_cast<VarTree*>(QTreeWidgetItem::child(i)); }
65 
66     virtual QVariant data(int column, int role) const;
67 
68 private:
69     void updateValueText();
70     QString m_baseValue;	//!< The "normal value" that the driver reported
71     QString m_structValue;	//!< The "quick member" value
72     bool m_baseChanged : 1;
73     bool m_structChanged : 1;
74 };
75 
76 /**
77  * Represents the value tree that is parsed by the debugger drivers.
78  */
79 struct ExprValue
80 {
81     QString m_name;
82     QString m_value;
83     VarTree::VarKind m_varKind;
84     VarTree::NameKind m_nameKind;
85     ExprValue* m_child;			/* the first child expression */
86     ExprValue* m_next;			/* the next sibling expression */
87     bool m_initiallyExpanded;
88 
89     ExprValue(const QString& name, VarTree::NameKind kind);
90     ~ExprValue();
91 
valueExprValue92     const QString& value() const {
93         return m_value;
94     }
95 
96     void appendChild(ExprValue* newChild);
97     int childCount() const;
98 };
99 
100 
101 class ValueEdit : public QLineEdit
102 {
103     Q_OBJECT
104 public:
105     ValueEdit(ExprWnd* parent);
106     ~ValueEdit();
107 
108     void terminate(bool commit);
109     VarTree* m_item;
110     bool m_finished;
111 protected:
112     void keyPressEvent(QKeyEvent *e);
113     void focusOutEvent(QFocusEvent* ev);
114     void paintEvent(QPaintEvent* e);
115 public slots:
116     void slotSelectionChanged();
117 signals:
118     void done(VarTree*, const QString&);
119 };
120 
121 
122 class ExprWnd : public QTreeWidget
123 {
124     Q_OBJECT
125 public:
126     ExprWnd(QWidget* parent, const QString& colHeader);
127     ~ExprWnd();
128 
129     /** returns the list with the expressions at the topmost level */
130     QStringList exprList() const;
131     /** appends a copy of expr to the end of the tree at the topmost level;
132      * returns a pointer to the inserted top-level item */
133     VarTree* insertExpr(ExprValue* expr, ProgramTypeTable& typeTable);
134     /** updates an existing expression */
135     void updateExpr(ExprValue* expr, ProgramTypeTable& typeTable);
136     void updateExpr(VarTree* display, ExprValue* newValues, ProgramTypeTable& typeTable);
137     /** updates the value and repaints it for a single item (not the children) */
138     void updateSingleExpr(VarTree* display, ExprValue* newValues);
139     /** updates only the value of the node */
140     void updateStructValue(VarTree* display);
141     /** get a top-level expression by name */
142     VarTree* topLevelExprByName(const QString& name) const;
143     /** return a member of the struct that pointer \a v refers to */
144     static VarTree* ptrMemberByName(VarTree* v, const QString& name);
145     /** return a member of the struct \a v */
146     static VarTree* memberByName(VarTree* v, const QString& name);
147     /** removes an expression; must be on the topmost level*/
148     void removeExpr(VarTree* item);
149     /** clears the list of pointers needing updates */
150     void clearPendingUpdates();
151     /** returns a pointer to update (or 0) and removes it from the list */
152     VarTree* nextUpdatePtr();
153     VarTree* nextUpdateType();
154     VarTree* nextUpdateStruct();
155     void editValue(VarTree* item, const QString& text);
156     /** tells whether the a value is currently edited */
157     bool isEditing() const;
158 
selectedItem()159     VarTree* selectedItem() const { return static_cast<VarTree*>(QTreeWidget::currentItem()); }
topLevelItem(int i)160     VarTree* topLevelItem(int i) const { return static_cast<VarTree*>(QTreeWidget::topLevelItem(i)); }
161 
162 protected:
163     void updateExprRec(VarTree* display, ExprValue* newValues, ProgramTypeTable& typeTable);
164     void replaceChildren(VarTree* display, ExprValue* newValues);
165     void collectUnknownTypes(VarTree* item);
166     void checkUnknownType(VarTree* item);
167     static QString formatWCharPointer(QString value);
168     QPixmap m_pixPointer;
169 
170     std::list<VarTree*> m_updatePtrs;	//!< dereferenced pointers that need update
171     std::list<VarTree*> m_updateType;	//!< structs whose type must be determined
172     std::list<VarTree*> m_updateStruct;	//!< structs whose nested value needs update
173 
174     ValueEdit* m_edit;
175 
176     /** remove items that are in the subTree from the list */
177     void unhookSubtree(VarTree* subTree);
178     static void unhookSubtree(std::list<VarTree*>& list, VarTree* subTree);
179 
180 signals:
181     void removingItem(VarTree*);
182     void editValueCommitted(VarTree*, const QString&);
183 };
184 
185 #endif // EXPRWND_H
186