-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathbasemodel.h
406 lines (344 loc) · 13.5 KB
/
basemodel.h
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
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
/***** BEGIN LICENSE BLOCK *****
BSD License
Copyright (c) 2005-2012, NIF File Format Library and Tools
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the NIF File Format Library and Tools project may not be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***** END LICENCE BLOCK *****/
#ifndef BaseModel_H
#define BaseModel_H
#include <QAbstractItemModel>
#include <QIODevice>
class QAbstractItemDelegate;
#include "niftypes.h"
#include "nifitem.h"
#include "message.h"
//! \file basemodel.h BaseModel
//! Base class for nif and kfm models, which store files in memory.
/*!
* This class serves as an abstract base class for NifModel and KfmModel
* classes.
*/
class BaseModel : public QAbstractItemModel
{
Q_OBJECT
public:
//! Constructor
BaseModel( QObject * parent = 0 );
//! Destructor
~BaseModel();
//! Clear model data.
virtual void clear() = 0;
//! Load from file.
bool loadFromFile( const QString & filename );
//! Save to file.
bool saveToFile( const QString & filename ) const;
//! Generic load from QIODevice.
virtual bool load( QIODevice & device ) = 0;
//! Generic save to QIODevice.
virtual bool save( QIODevice & device ) const = 0;
//! If the model was loaded from a file then getFolder returns the folder.
/*!
* This function is used to resolve external resources.
* \return The folder of the last file that was loaded with loadFromFile.
*/
QString getFolder() const { return folder; }
//! Return true if the index pointed to is an array.
/*!
* \param array The index to check.
* \return true if the index is an array.
*/
bool isArray( const QModelIndex & iArray ) const;
//! Update the size of an array (append or remove items).
/*!
* \param array The index of the array whose size to update.
* \return true if the update succeeded, false otherwise.
*/
bool updateArray( const QModelIndex & iArray );
//! Update the size of an array by name.
bool updateArray( const QModelIndex & parent, const QString & name );
//! Get an model index array as a QVector.
/*!
* \param array The index of the array to get.
* \return The array as QVector.
*/
template <typename T> QVector<T> getArray( const QModelIndex & iArray ) const;
//! Get an model index array as a QVector by name.
template <typename T> QVector<T> getArray( const QModelIndex & iArray, const QString & name ) const;
//! Write a QVector to a model index array.
template <typename T> void setArray( const QModelIndex & iArray, const QVector<T> & array );
//! Write a QVector to a model index array by name.
template <typename T> void setArray( const QModelIndex & iArray, const QString & name, const QVector<T> & array );
//! Get an item.
template <typename T> T get( const QModelIndex & index ) const;
//! Get an item by name.
template <typename T> T get( const QModelIndex & parent, const QString & name ) const;
//! Set an item.
template <typename T> bool set( const QModelIndex & index, const T & d );
//! Set an item by name.
template <typename T> bool set( const QModelIndex & parent, const QString & name, const T & v );
//! Get an item as a NifValue.
NifValue getValue( const QModelIndex & index ) const;
/* Not implemented? */
// Get an item as a NifValue by name.
//NifValue getValue( const QModelIndex & parent, const QString & name ) const;
//! Set an item from a NifValue.
bool setValue( const QModelIndex & index, const NifValue & v );
//! Set an item from a NifValue by name.
bool setValue( const QModelIndex & parent, const QString & name, const NifValue & v );
// get item attributes
//! Get the item name.
QString itemName( const QModelIndex & index ) const;
//! Get the item type string.
QString itemType( const QModelIndex & index ) const;
//! Get the item argument string.
QString itemArg( const QModelIndex & index ) const;
//! Get the item arr1 string.
QString itemArr1( const QModelIndex & index ) const;
//! Get the item arr2 string.
QString itemArr2( const QModelIndex & index ) const;
//! Get the item condition string.
QString itemCond( const QModelIndex & index ) const;
//! Get the item first version.
quint32 itemVer1( const QModelIndex & index ) const;
//! Get the item last version.
quint32 itemVer2( const QModelIndex & index ) const;
//! Get the item documentation.
QString itemText( const QModelIndex & index ) const;
//! Get the item template string.
QString itemTmplt( const QModelIndex & index ) const;
//! Find a branch by name.
QModelIndex getIndex( const QModelIndex & parent, const QString & name ) const;
//! Evaluate condition and version.
bool evalCondition( const QModelIndex & idx, bool chkParents = false ) const;
//! Evaluate version.
bool evalVersion( const QModelIndex & idx, bool chkParents = false ) const;
//! Is name a NiBlock identifier (<niobject abstract="0"> or <niobject abstract="1">)?
virtual bool isAncestorOrNiBlock( const QString & /*name*/ ) const { return false; };
//! Returns true if name inherits ancestor.
virtual bool inherits( const QString & /*name*/, const QString & /*ancestor*/ ) const { return false; };
// This is here to avoid compiler confusion with QObject::inherits.
bool inherits ( const char * className ) const {
return QObject::inherits(className);
}
//! Get version as a string
virtual QString getVersion() const = 0;
//! Get version as a number
virtual quint32 getVersionNumber() const = 0;
//! Column names
enum {
NameCol = 0,
TypeCol = 1,
ValueCol = 2,
ArgCol = 3,
Arr1Col = 4,
Arr2Col = 5,
CondCol = 6,
Ver1Col = 7,
Ver2Col = 8,
VerCondCol = 9,
NumColumns = 10,
};
// QAbstractModel interface
//! Creates a model index for the given row and column
/*!
* \see QAbstractItemModel::createIndex()
*/
QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const;
//! Finds the parent of the specified index
QModelIndex parent( const QModelIndex & index ) const;
//! Finds the number of rows
int rowCount( const QModelIndex & parent = QModelIndex() ) const;
//! Finds the number of columns
int columnCount( const QModelIndex & parent = QModelIndex() ) const { Q_UNUSED(parent); return NumColumns; }
//! Finds the data associated with an index
/*!
* \param index The index to find data for
* \param role The Qt::ItemDataRole to get data for
*/
QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const;
//! Sets data associated with an index
/*!
* \param index The index to set data for
* \param value The data to set
* \param role The Qt::ItemDataRole to use
*/
bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole );
//! Get the header data for a section
QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
//! Finds the flags for an index
Qt::ItemFlags flags( const QModelIndex & index ) const;
//! Message mode
enum MsgMode
{
EmitMessages, CollectMessages
};
//! Set the Message mode
void setMessageMode( MsgMode m ) { msgMode = m; }
//! Get Messages collected
QList<Message> getMessages() const { QList<Message> lst = messages; messages.clear(); return lst; }
signals:
//! Messaging signal
void sigMessage( const Message & msg ) const;
//! Progress signal
void sigProgress( int c, int m ) const;
protected:
//! Update an array item
virtual bool updateArrayItem( NifItem * array, bool fast ) = 0;
//! Get the size of an array
int getArraySize( NifItem * array ) const;
//! Evaluate a string for an array
int evaluateInt( NifItem * item, const Expression & expr) const;
//! Get an item
virtual NifItem * getItem( NifItem * parent, const QString & name ) const;
//! Get an item by name
NifItem * getItemX( NifItem * item, const QString & name ) const; // find upwards
//! Find an item by name
NifItem * findItemX( NifItem * item, const QString & name ) const;
//! Get an item by name
template <typename T> T get( NifItem * parent, const QString & name ) const;
//! Get an item
template <typename T> T get( NifItem * item ) const;
//! Set an item by name
template <typename T> bool set( NifItem * parent, const QString & name, const T & d );
//! Set an item
template <typename T> bool set( NifItem * item, const T & d );
//! Set an item value
virtual bool setItemValue( NifItem * item, const NifValue & v ) = 0;
//! Set an item value by name
bool setItemValue( NifItem * parent, const QString & name, const NifValue & v );
//! Evaluate version
virtual bool evalVersion( NifItem * item, bool chkParents = false ) const = 0;
//! Evaluate conditions
bool evalCondition( NifItem * item, bool chkParents = false ) const;
//! Convert a version number to a string
virtual QString ver2str( quint32 ) const = 0;
//! Convert a version string to a number
virtual quint32 str2ver( QString ) const = 0;
//! Set the header string
virtual bool setHeaderString( const QString & ) = 0;
//! The root item
NifItem * root;
//! The filepath of the model
QString folder;
//! The messaging mode
MsgMode msgMode;
//! A list of messages
mutable QList<Message> messages;
//! Handle a message
void msg( const Message & m ) const;
friend class NifIStream;
friend class NifOStream;
friend class BaseModelEval;
}; // class BaseModel
template <typename T> inline T BaseModel::get( NifItem * parent, const QString & name ) const
{
NifItem * item = getItem( parent, name );
if ( item )
return item->value().get<T>();
else
return T();
}
template <typename T> inline T BaseModel::get( const QModelIndex & parent, const QString & name ) const
{
NifItem * parentItem = static_cast<NifItem*>( parent.internalPointer() );
if ( ! ( parent.isValid() && parentItem && parent.model() == this ) )
return T();
NifItem * item = getItem( parentItem, name );
if ( item )
return item->value().get<T>();
else
return T();
}
template <typename T> inline bool BaseModel::set( NifItem * parent, const QString & name, const T & d )
{
NifItem * item = getItem( parent, name );
if ( item )
return set( item, d );
else
return false;
}
template <typename T> inline bool BaseModel::set( const QModelIndex & parent, const QString & name, const T & d )
{
NifItem * parentItem = static_cast<NifItem*>( parent.internalPointer() );
if ( ! ( parent.isValid() && parentItem && parent.model() == this ) )
return false;
NifItem * item = getItem( parentItem, name );
if ( item )
return set( item, d );
else
return false;
}
template <typename T> inline T BaseModel::get( NifItem * item ) const
{
return item->value().get<T>();
}
template <typename T> inline T BaseModel::get( const QModelIndex & index ) const
{
NifItem * item = static_cast<NifItem*>( index.internalPointer() );
if ( ! ( index.isValid() && item && index.model() == this ) )
return T();
return item->value().get<T>();
}
template <typename T> inline bool BaseModel::set( NifItem * item, const T & d )
{
if ( item->value().set( d ) )
{
emit dataChanged( createIndex( item->row(), ValueCol, item ), createIndex( item->row(), ValueCol, item ) );
return true;
}
else
return false;
}
template <typename T> inline bool BaseModel::set( const QModelIndex & index, const T & d )
{
NifItem * item = static_cast<NifItem*>( index.internalPointer() );
if ( ! ( index.isValid() && item && index.model() == this ) ) return false;
return set( item, d );
}
template <typename T> inline QVector<T> BaseModel::getArray( const QModelIndex & iArray ) const
{
NifItem * item = static_cast<NifItem*>( iArray.internalPointer() );
if ( isArray( iArray ) && item && iArray.model() == this )
return item->getArray<T>();
return QVector<T>();
}
template <typename T> inline QVector<T> BaseModel::getArray( const QModelIndex & iParent, const QString & name ) const
{
return getArray<T>( getIndex( iParent, name ) );
}
template <typename T> inline void BaseModel::setArray( const QModelIndex & iArray, const QVector<T> & array )
{
NifItem * item = static_cast<NifItem*>( iArray.internalPointer() );
if ( isArray( iArray ) && item && iArray.model() == this )
{
item->setArray<T>( array );
int x = item->childCount() - 1;
if ( x >= 0 )
emit dataChanged( createIndex( 0, ValueCol, item->child( 0 ) ), createIndex( x, ValueCol, item->child( x ) ) );
}
}
template <typename T> inline void BaseModel::setArray( const QModelIndex & iParent, const QString & name, const QVector<T> & array )
{
setArray<T>( getIndex( iParent, name ), array );
}
#endif