some fixes to the cmake files. It still is not working
[kdeedu-porting.git] / kalzium / libavogadro-kalzium / src / primitiveitemmodel.cpp
blobbc40c1d945b056f66f0b640c8b4749519e6c4d4c
1 /**********************************************************************
2 PrimitiveItemModel - Model for representing primitives.
4 Copyright (C) 2007 Donald Ephraim Curtis <dcurtis3@sourceforge.net>
6 This file is part of the Avogadro molecular editor project.
7 For more information, see <http://avogadro.sourceforge.net/>
9 Avogadro is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 Avogadro is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 02110-1301, USA.
23 **********************************************************************/
25 #include <avogadro/primitiveitemmodel.h>
27 #include <QTimer>
28 #include <QVector>
30 namespace Avogadro {
31 class PrimitiveItemModelPrivate
33 public:
34 PrimitiveItemModelPrivate() : engine(0), molecule(0) {}
36 Engine *engine;
38 Molecule *molecule;
40 // use this to optimize insert / delete
41 QMap<int, Primitive::Type> rowTypeMap;
43 // keep track of the model sizes for each parent
44 QVector<int> size;
47 * for Molecules we have to cache additions / subtractions
48 * because when we get the signal we haven't actually added
49 * the atom to the molecule, rather it's been created but not
50 * yet added.
52 QVector<QVector<Primitive *> > moleculeCache;
55 PrimitiveItemModel::PrimitiveItemModel( Engine *engine, QObject *parent) : QAbstractItemModel(parent), d(new PrimitiveItemModelPrivate)
57 d->engine = engine;
59 d->rowTypeMap.insert(0, Primitive::AtomType);
60 d->rowTypeMap.insert(1, Primitive::BondType);
61 d->rowTypeMap.insert(2, Primitive::ResidueType);
63 d->size.resize(d->rowTypeMap.size());
65 connect(engine, SIGNAL(changed()), this, SLOT(engineChanged()));
66 PrimitiveList list = engine->primitives();
67 foreach(int row, d->rowTypeMap.keys())
69 d->size[row] = list.count(d->rowTypeMap[row]);
73 PrimitiveItemModel::PrimitiveItemModel( Molecule *molecule, QObject *parent) : QAbstractItemModel(parent), d(new PrimitiveItemModelPrivate)
75 d->molecule = molecule;
77 d->rowTypeMap.insert(0, Primitive::AtomType);
78 d->rowTypeMap.insert(1, Primitive::BondType);
79 d->rowTypeMap.insert(2, Primitive::ResidueType);
81 d->size.resize(d->rowTypeMap.size());
82 d->moleculeCache.resize(d->rowTypeMap.size());
84 d->size[0] = molecule->NumAtoms();
85 d->size[1] = molecule->NumBonds();
86 d->size[2] = molecule->NumResidues();
88 connect(molecule, SIGNAL(primitiveAdded(Primitive *)),
89 this, SLOT(addPrimitive(Primitive *)));
90 connect(molecule, SIGNAL(primitiveUpdated(Primitive *)),
91 this, SLOT(updatePrimitive(Primitive *)));
92 connect(molecule, SIGNAL(primitiveRemoved(Primitive *)),
93 this, SLOT(removePrimitive(Primitive *)));
96 void PrimitiveItemModel::addPrimitive(Primitive *primitive)
98 int parentRow = d->rowTypeMap.key(primitive->type());
100 if(parentRow < d->size.size())
102 int last = d->size[parentRow]++;
103 beginInsertRows(createIndex(parentRow, 0, 0), last, last);
104 if(d->molecule) {
105 d->moleculeCache[parentRow].append(primitive);
107 endInsertRows();
111 void PrimitiveItemModel::updatePrimitive(Primitive *primitive)
113 int parentRow = d->rowTypeMap.key(primitive->type());
115 if(parentRow < d->size.size())
117 int row = primitiveIndex(primitive);
118 emit dataChanged(createIndex(row, 0, primitive), createIndex(row, 0, primitive));
122 void PrimitiveItemModel::removePrimitive(Primitive *primitive)
124 int parentRow = d->rowTypeMap.key(primitive->type());
125 if(parentRow < d->size.size())
127 int row = primitiveIndex(primitive);
128 //assert(row > -1);
129 if (row < 0)
130 return;
131 beginRemoveRows(createIndex(parentRow, 0, 0), row, row);
132 if(d->molecule)
134 d->moleculeCache[parentRow].remove(row);
136 d->size[parentRow]--;
137 endRemoveRows();
141 int PrimitiveItemModel::primitiveIndex(Primitive *primitive)
143 if(d->molecule)
145 int parentRow = d->rowTypeMap.key(primitive->type());
146 return d->moleculeCache[parentRow].indexOf(primitive);
148 else if (d->engine)
150 QList<Primitive *> subList = d->engine->primitives().subList(primitive->type());
151 return subList.indexOf(primitive);
154 return -1;
158 void PrimitiveItemModel::engineChanged()
160 PrimitiveList list = d->engine->primitives();
161 foreach(int row, d->rowTypeMap.keys())
163 Primitive::Type type = d->rowTypeMap[row];
164 int newsize = list.count(type);
165 int oldsize = d->size.at(row);
166 if(newsize < oldsize)
168 d->size[row] = newsize;
170 beginRemoveRows(createIndex(row,0,0), newsize, oldsize-1);
171 QList<Primitive *> subList = list.subList(type);
172 if(subList.size())
174 // this is a minor hack to simplify things although it doesn't currently update the view
175 emit layoutChanged();
177 endRemoveRows();
179 else if(newsize > oldsize)
181 d->size[row] = newsize;
182 beginInsertRows(createIndex(row,0,0), oldsize, newsize-1);
183 endInsertRows();
188 QModelIndex PrimitiveItemModel::parent( const QModelIndex & index ) const
190 if(!index.isValid())
192 return QModelIndex();
195 Primitive *primitive = static_cast<Primitive *>(index.internalPointer());
196 if(primitive)
198 int row = d->rowTypeMap.key(primitive->type());
199 return createIndex(row, 0, 0);
201 return QModelIndex();
204 int PrimitiveItemModel::rowCount( const QModelIndex & parent ) const
206 if(!parent.isValid())
208 return d->rowTypeMap.size();
211 Primitive *primitive = static_cast<Primitive *>(parent.internalPointer());
212 if(!primitive)
214 return d->size[parent.row()];
217 return 0;
220 int PrimitiveItemModel::columnCount( const QModelIndex & ) const
222 return 1;
225 QVariant PrimitiveItemModel::data ( const QModelIndex & index, int role ) const
227 if(!index.isValid() || index.column() != 0)
229 return QVariant();
232 Primitive *primitive = static_cast<Primitive *>(index.internalPointer());
233 if(primitive)
235 if(role == Qt::DisplayRole) {
236 Primitive::Type type = primitive->type();
238 QString str;
239 if(type == Primitive::MoleculeType) {
240 str = tr("Molecule");
242 else if(type == Primitive::AtomType) {
243 Atom *atom = (Atom*)primitive;
244 str = tr("Atom") + ' '
245 + QString(OpenBabel::etab.GetSymbol(atom->GetAtomicNum()))
246 + ' ' + QString::number(atom->GetIdx());
248 else if(type == Primitive::BondType){
249 Bond *bond = (Bond*)primitive;
250 Atom *beginAtom = (Atom *)bond->GetBeginAtom();
251 Atom *endAtom = (Atom *)bond->GetEndAtom();
252 str = tr("Bond") + ' ' + QString::number(bond->GetIdx()) + " (";
253 if(beginAtom) {
254 str += QString::number(beginAtom->GetIdx());
255 } else {
256 // this should never happen: Bond always has a beginning -GRH
257 str += '-';
260 str += ',';
262 if(endAtom) {
263 str += QString::number(endAtom->GetIdx());
264 } else {
265 // this should never happen: Bond always has an end -GRH
266 str += '-';
268 str += ')';
269 } // end bond
270 else if(type == Primitive::ResidueType) {
271 Residue *residue = (Residue*)primitive;
272 str = tr("Residue") + ' ';
273 str += QString(residue->GetName().c_str()) + ' '
274 + QString(residue->GetNumString().c_str());
277 return str;
279 } else if ( role == PrimitiveItemModel::PrimitiveRole ) {
280 return qVariantFromValue(primitive);
284 if(role == Qt::DisplayRole && index.row() < d->rowTypeMap.size())
286 Primitive::Type type = d->rowTypeMap[index.row()];
287 if(type == Primitive::AtomType) {
288 return tr("Atoms");
289 } else if (type == Primitive::BondType) {
290 return tr("Bonds");
291 } else if (type == Primitive::ResidueType) {
292 return tr("Residues");
296 return QVariant();
299 Qt::ItemFlags PrimitiveItemModel::flags ( const QModelIndex & index ) const
301 if(!index.isValid()) {
302 return 0;
305 Primitive *primitive = static_cast<Primitive *>(index.internalPointer());
306 if(primitive)
308 return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
311 return Qt::ItemIsEnabled;
314 QModelIndex PrimitiveItemModel::index ( int row, int column, const QModelIndex & parent ) const
316 if(!parent.isValid())
318 return createIndex(row, column);
321 Primitive *primitive = static_cast<Primitive *>(parent.internalPointer());
322 if(primitive)
324 return QModelIndex();
327 if(d->engine)
329 QList<Primitive *> subList =
330 d->engine->primitives().subList(d->rowTypeMap[parent.row()]);
331 if(row < subList.size()) {
332 return createIndex(row, column, subList.at(row));
334 } else if (d->molecule) {
335 // Primitive::Type type = d->rowTypeMap[parent.row()];
336 int parentRow = parent.row();
338 Primitive *primitive;
339 primitive = d->moleculeCache[parentRow].at(row);
340 return createIndex(row, column, primitive);
343 return QModelIndex();
346 } // end namespace Avogadro
348 #include "primitiveitemmodel.moc"