summaryrefslogtreecommitdiffstats
path: root/src/item.h
blob: f1968d2bbc0f61328280f8b99a882f1c0a66086e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
/***************************************************************************
 *   Copyright (C) 2004-2005 by David Saxton                               *
 *   david@bluehaze.org                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/

#ifndef ITEM_H
#define ITEM_H

#include "variant.h"

#include <qcanvas.h>
#include <qfont.h>
#include <qguardedptr.h>


class Document;
class EventInfo;
class Item;
class ItemData;
class ItemDocument;
class ItemView;
class DoubleSpinBox;
class Document;
class Variant;
class QBitArray;

typedef Item*(*createItemPtr)( ItemDocument *itemDocument, bool newItem, const char *id );
typedef QGuardedPtr<Item> GuardedItem;
typedef QMap<QString, Variant*> VariantDataMap;
typedef QValueList<GuardedItem> ItemList;

/**
@author David Saxton
@author Daniel Clarke
*/
class Item : public QObject, public QCanvasPolygon
{
Q_OBJECT
public:
	Item( ItemDocument *itemDocument, bool newItem, const QString &id );
	virtual ~Item();

	/**
	 * @return Pointer to the VariantMap used for internal data storage
	 */
	VariantDataMap *variantMap() { return &m_variantData; }
	
	double dataDouble( const QString & id ) const;
	int dataInt( const QString & id ) const;
	bool dataBool( const QString & id ) const;
	QString dataString( const QString & id ) const;
	QColor dataColor( const QString & id ) const;
	
	virtual Variant * createProperty( const QString & id, Variant::Type::Value type );
	Variant * property( const QString & id ) const;
	bool hasProperty( const QString & id ) const;
	
	/**
	 * Whether or not we can rotate the item
	 */
	virtual bool canRotate() const { return false; }
	/**
	 * Whether or not we can flip the item
	 */
	virtual bool canFlip() const { return false; }
	/**
	 * Whether or not we can resize the item
	 */
	virtual bool canResize() const { return false; }
	/**
	 * Returns whether the CNItem allows itself to be moved on the canvas.
	 * Most do, but some (such as the PicItem) don't allow this
	 */
	virtual bool isMovable() const { return true; }
	/**
	 * If your item doesn't move, yet still continously changes what is being
	 * displayed (such as a seven segment display or a lamp), then this should
	 * return true (set m_bDynamicContent to be true in your constructor).
	 */
	bool hasDynamicContent() const { return m_bDynamicContent; }
	/**
	 * Returns a identifier for the CNItem, which is unique on the ICNDocument
	 */
	QString id() const { return m_id; }
	QString type() const { return m_type; }
	/**
	 * Called from ItemLibrary after this class and subclasses have finished
	 * constructing themselves.
	 */
	virtual void finishedCreation();
	/**
	 * Sets the selected flag of the item to yes. selected or unselected will be
	 * emitted as appropriate
	 */
	virtual void setSelected( bool yes );
	/**
	 * Convenience function for setting the item bounding area as changed on the
	 * canvas
	 */
	void setChanged();
	/**
	 * Sets this item as a child of the given item. Calls reparented with the
	 * old and the new parent.
	 */
	void setParentItem( Item *parentItem );
	/**
	 * The parent item for this item, or NULL if none
	 */
	Item *parentItem() const { return p_parentItem; }
	ItemDocument *itemDocument() const { return p_itemDocument; }
	/**
	 * Returns the number of items away from the top item this is
	 * (parent-wise). Returns 0 if has no parent.
	 */
	int level() const;
	/**
	 * If true, then adds ItemDocument::Z::(RaisedItem-Item) to the z value of
	 * the item.
	 */
	void setRaised( bool isRaised );
	/**
	 * @Returns whether raised or not
	 */
	bool isRaised() const { return m_bIsRaised; }
	/**
	 * Sets this item to the given baseZ level, and calls this function for the
	 * children with baseZ incremented by one. Reinherit this function to set
	 * the Z of attached stuff (such as nodes).
	 */
	virtual void updateZ( int baseZ );
	/**
	 * Returns the item's position in the overall z-stack of items.
	 */
	int baseZ() const { return m_baseZ; }
	/**
	 * Adds a child. Calls the virtual function childAdded.
	 */
	void addChild( Item *child );
	/**
	 * Returns the list of children.
	 * @param if includeGrandChildren is true then this list will also contain
	 * the children's children, and so on recursively, instead of just the
	 * immediate children.
	 */
	ItemList children( bool includeGrandChildren = false ) const;
	/**
	 * Returns whether we have the given child as either a direct child, or as
	 * either a direct or indirect child
	 */
	bool contains( Item *item, bool direct = false ) const;
	/**
	 * Calls prePresize with the bounds, and if that returns true, sets
	 * m_sizeRect to the given rect, and then calls postResize.
	 * @param forceItemPoints if true, will set the item points to a rectangle of the given size
	 */
	void setSize( QRect sizeRect, bool forceItemPoints = false );
	/**
	 * Convenience function.
	 * @see setSize( QRect sizeRect, bool forceItemPoints );
	 */
	void setSize( int x, int y, int w, int h, bool forceItemPoints = false ) { setSize( QRect(x,y,w,h), forceItemPoints ); }
	/**
	 * @returns the m_sizeRect rectangble that contains the item points
	 */
	QRect sizeRect() const { return m_sizeRect; }
	/**
	 * Reinherit this function if you want to determine what the minimum size is
	 * that this item can be resized to.
	 */
	virtual QSize minimumSize() const { return QSize(0,0); }
	int offsetX() const { return m_sizeRect.x(); }
	int offsetY() const { return m_sizeRect.y(); }
	int width() const { return m_sizeRect.width(); }
	int height() const { return m_sizeRect.height(); }
	virtual bool mousePressEvent( const EventInfo &eventInfo );
	virtual bool mouseReleaseEvent( const EventInfo &eventInfo );
	virtual bool mouseDoubleClickEvent ( const EventInfo &eventInfo );
	virtual bool mouseMoveEvent( const EventInfo &eventInfo );
	virtual bool wheelEvent( const EventInfo &eventInfo );
	virtual void enterEvent();
	virtual void leaveEvent();
	/**
	 * Returns the name of the CNItem, e.g. "Resistor"
	 */
	QString name() const { return m_name; }
	/**
	 * Returns a description of the CNItem, with html tags if appropriate.
	 */
	QString description() const { return m_desc; }
	/**
	 * Modifies the exponent of the number so that it appears readable:
	 * eg 10000->10, 174822->175, 0.6->600, etc
	 */
	static int getNumberPre( double num );
	/**
	 * Returns the SI exponent of the number as a letter:
	 * eg 10000 returns 'k', 0.6 returns 'm', etc
	 */
	static QString getNumberMag( double num );
	/**
	 * Returns the multiplier required to get the num up to human readable form:
	 * eg 10000 returns 0.001, etc
	 */
	static double getMultiplier( double num );
	/**
	 * Returns the multiplier required to get the num from human readable form
	 * to its actual value based on the SI exponent:
	 * eg 'm' returns 0.001, etc
	 */
	static double getMultiplier( const QString &mag );
	
	virtual ItemData itemData() const;
	virtual void restoreFromItemData( const ItemData &itemData );
	
	const QFont & font() const { return m_font; }
	
public slots:
	virtual void removeItem();
	/**
	 * Moves item - use this instead of moveBy() so that associated Nodes also get moved
	 */
	virtual void moveBy( double dx, double dy );
	/**
	 * Removes a child. Calls the virtual function childRemoved
	 */
	void removeChild( Item *child );
	
signals:
	/**
	 * Emitted when the CNItem is removed. Normally, this signal is caught by associated
	 * nodes, who will remove themselves as well.
	 */
	void removed( Item *item );
	/**
	 * Emitted when the item is selected
	 */
	void selected( Item *item, bool isSelected = true );
	/**
	 * Emitted when the item is unselected
	 */
	void unselected( Item *item, bool isSelected = false );
	/**
	 * Emitted when the item is resized (after calling postResize)
	 */
	void resized();
	/**
	 * Emitted when the item is moved (by dx, dy).
	 */
	void movedBy( double dx, double dy );
	
protected slots:
	virtual void dataChanged() {};
	
protected:
	/**
	 * Reinherit this function if you want to do anything with children. Called
	 * after the parent is changed, with the old parent and the new parent.
	 */
	virtual void reparented( Item */*oldParent*/, Item */*newParent*/ ) {};
	/**
	 * Reinherit this function if you want to do anything with children. Called
	 * after a child has been added.
	 */
	virtual void childAdded( Item * ) {};
	/**
	 * Reinherit this function if you want to do anything with children. Called
	 * after a child has been removed.
	 */
	virtual void childRemoved( Item * ) {};
	/**
	 * Set the rough bounding points for this item. Calls itemPointsChanged
	 * after setting the points
	 */
	void setItemPoints( const QPointArray &pa, bool setSizeFromPoints = true );
	/**
	 * Reinherit this function if you want to apply any sort of transformation
	 * to the item points
	 */
	virtual void itemPointsChanged();
	virtual bool preResize( QRect sizeRect ) { Q_UNUSED(sizeRect); return true; }
	virtual void postResize() {};
	
	QString m_id;
	QString m_name, m_desc; // Name and description
	QString m_type;
	GuardedItem p_parentItem; // If attached to a parent item
	ItemList m_children;
	QGuardedPtr<ItemDocument> p_itemDocument;
	QPointArray m_itemPoints; // The unorientated and unsized item points
	
	friend class ItemLibrary;
	
	int m_baseZ;
	bool m_bIsRaised;
	bool m_bDoneCreation;
	bool b_deleted;
	bool m_bDynamicContent;
	QFont m_font;
	QRect m_sizeRect;
	VariantDataMap m_variantData;
};

#endif