treemodel.cpp
author insilmaril
Wed, 09 Sep 2009 12:57:06 +0000
changeset 793 cac93797c580
parent 791 f1006de05c54
child 794 d922fb6ea482
permissions -rw-r--r--
more fixes for collision detection
insilmaril@725
     1
#include <QtGui>
insilmaril@725
     2
insilmaril@741
     3
#include <iostream>
insilmaril@741
     4
using namespace std;
insilmaril@741
     5
insilmaril@788
     6
#include "attributeitem.h"
insilmaril@750
     7
#include "branchitem.h"
insilmaril@788
     8
#include "imageitem.h"
insilmaril@725
     9
#include "treeitem.h"
insilmaril@725
    10
#include "treemodel.h"
insilmaril@790
    11
#include "xlinkitem.h"
insilmaril@725
    12
insilmaril@725
    13
TreeModel::TreeModel(QObject *parent)
insilmaril@725
    14
    : QAbstractItemModel(parent)
insilmaril@725
    15
{
insilmaril@725
    16
    QList<QVariant> rootData;
insilmaril@790
    17
    rootData << "Heading" << "Type";
insilmaril@791
    18
    rootItem = new BranchItem(rootData);
insilmaril@725
    19
}
insilmaril@725
    20
insilmaril@725
    21
TreeModel::~TreeModel()
insilmaril@725
    22
{
insilmaril@725
    23
    delete rootItem;
insilmaril@725
    24
}
insilmaril@725
    25
insilmaril@725
    26
QVariant TreeModel::data(const QModelIndex &index, int role) const
insilmaril@725
    27
{
insilmaril@725
    28
    if (!index.isValid())
insilmaril@725
    29
        return QVariant();
insilmaril@725
    30
insilmaril@725
    31
    if (role != Qt::DisplayRole)
insilmaril@725
    32
        return QVariant();
insilmaril@725
    33
insilmaril@745
    34
    TreeItem *item = getItem (index);
insilmaril@725
    35
insilmaril@725
    36
    return item->data(index.column());
insilmaril@725
    37
}
insilmaril@725
    38
insilmaril@725
    39
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
insilmaril@725
    40
{
insilmaril@725
    41
    if (!index.isValid())
insilmaril@791
    42
        return Qt::NoItemFlags;
insilmaril@725
    43
insilmaril@725
    44
    return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
insilmaril@725
    45
}
insilmaril@725
    46
insilmaril@725
    47
QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
insilmaril@725
    48
                               int role) const
insilmaril@725
    49
{
insilmaril@725
    50
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
insilmaril@725
    51
        return rootItem->data(section);
insilmaril@725
    52
insilmaril@725
    53
    return QVariant();
insilmaril@725
    54
}
insilmaril@725
    55
insilmaril@788
    56
QModelIndex TreeModel::index (TreeItem* ti)
insilmaril@788
    57
{
insilmaril@788
    58
	if (!ti->parent())
insilmaril@788
    59
		return QModelIndex();
insilmaril@788
    60
	else	
insilmaril@791
    61
		return createIndex (ti->row(),0,ti);
insilmaril@788
    62
}
insilmaril@788
    63
insilmaril@725
    64
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent)
insilmaril@725
    65
            const
insilmaril@725
    66
{
insilmaril@791
    67
	// Make sure to return invalid index for invalid values (see modeltest)
insilmaril@791
    68
	if (row<0 || column<0) return QModelIndex();
insilmaril@791
    69
	if (column!=0) return QModelIndex();
insilmaril@791
    70
insilmaril@725
    71
    TreeItem *parentItem;
insilmaril@725
    72
insilmaril@725
    73
    if (!parent.isValid())
insilmaril@791
    74
	{
insilmaril@725
    75
        parentItem = rootItem;
insilmaril@788
    76
		/*
insilmaril@788
    77
		cout << "TM::index()  no parent?! xxx\n";
insilmaril@788
    78
		cout << "   row="<<row<<"  col="<<column<<endl;
insilmaril@788
    79
		cout << "   parent.internal="<< parent.internalPointer()<<endl;
insilmaril@788
    80
		*/
insilmaril@788
    81
		// Somehow index is requested where parentIndex is invalid.
insilmaril@788
    82
		// what's happening here...?
insilmaril@788
    83
		// Check if Qt examples also return index of rootIem then...
insilmaril@788
    84
insilmaril@788
    85
	}	
insilmaril@725
    86
    else
insilmaril@745
    87
        parentItem = getItem (parent);
insilmaril@725
    88
insilmaril@725
    89
    TreeItem *childItem = parentItem->child(row);
insilmaril@791
    90
	//cout << "TM::index  parentItem="<<parentItem<<"  childItem="<<childItem<<"  row="<<row<<" col="<<column<<endl;
insilmaril@725
    91
    if (childItem)
insilmaril@725
    92
        return createIndex(row, column, childItem);
insilmaril@725
    93
    else
insilmaril@725
    94
        return QModelIndex();
insilmaril@725
    95
}
insilmaril@725
    96
insilmaril@725
    97
QModelIndex TreeModel::parent(const QModelIndex &index) const
insilmaril@725
    98
{
insilmaril@725
    99
    if (!index.isValid())
insilmaril@725
   100
        return QModelIndex();
insilmaril@725
   101
insilmaril@788
   102
	//FIXME-3 cout << "TM::parent  ri="<<rootItem<< "  row="<<index.row()<<"  col="<<index.column()<<endl;
insilmaril@745
   103
    TreeItem *ti= getItem (index);
insilmaril@788
   104
	//cout << "            ti="<<ti<<endl;
insilmaril@788
   105
	//cout << "               "<<ti->getHeadingStd()<<endl;
insilmaril@745
   106
    TreeItem *parentItem = ti->parent();
insilmaril@788
   107
	//cout << "            pi="<<parentItem<<endl;
insilmaril@725
   108
insilmaril@745
   109
	//cout << "TreeModel::parent  ti="<<ti<<" "<<ti->getHeading().toStdString()<<"  pi="<<parentItem<<"  "<<endl;
insilmaril@725
   110
    if (parentItem == rootItem)
insilmaril@725
   111
        return QModelIndex();
insilmaril@725
   112
insilmaril@791
   113
/*
insilmaril@745
   114
	if (!parentItem)
insilmaril@746
   115
        return QModelIndex();	// FIXME-3 do this to avoid segfault, but why?
insilmaril@746
   116
		                        // see also my question on qt-interest in march
insilmaril@791
   117
*/
insilmaril@745
   118
    return createIndex(parentItem->childNumber(), 0, parentItem);
insilmaril@725
   119
}
insilmaril@725
   120
insilmaril@725
   121
int TreeModel::rowCount(const QModelIndex &parent) const
insilmaril@725
   122
{
insilmaril@725
   123
    TreeItem *parentItem;
insilmaril@725
   124
insilmaril@725
   125
    if (!parent.isValid())
insilmaril@725
   126
        parentItem = rootItem;
insilmaril@725
   127
    else
insilmaril@745
   128
        parentItem = getItem (parent);
insilmaril@725
   129
insilmaril@725
   130
    return parentItem->childCount();
insilmaril@725
   131
}
insilmaril@725
   132
insilmaril@741
   133
int TreeModel::columnCount(const QModelIndex &parent) const
insilmaril@726
   134
{
insilmaril@791
   135
	int c;
insilmaril@741
   136
    if (parent.isValid())
insilmaril@791
   137
	{
insilmaril@791
   138
        c= getItem (parent)->columnCount();
insilmaril@791
   139
		//cout << "TM::colCount  c="<<c<<"  parent="<<getItem (parent)<<endl;	
insilmaril@791
   140
	}
insilmaril@741
   141
    else
insilmaril@791
   142
	{
insilmaril@791
   143
        c= rootItem->columnCount();
insilmaril@791
   144
		//cout << "TM::colCount  c="<<c<<"  parent=invalid"<<endl;	
insilmaril@791
   145
	}
insilmaril@791
   146
	return c;
insilmaril@726
   147
}
insilmaril@726
   148
insilmaril@791
   149
BranchItem* TreeModel::next(BranchItem* &current, BranchItem* &previous, BranchItem* start)	// FIXME-3 change this to nextBranch and use "next" for all TIs
insilmaril@741
   150
{
insilmaril@776
   151
/*FIXME-3	cout << "TM::next \n"; 
insilmaril@776
   152
	std::string ch="()"; if (current) ch=current->getHeadingStd();
insilmaril@776
   153
	std::string ph="()"; if (previous) ph=previous->getHeadingStd();
insilmaril@776
   154
	cout << "  cur="<<ch << " prev="<<ph<<endl;
insilmaril@776
   155
*/
insilmaril@776
   156
insilmaril@741
   157
	// Walk through map beginning at current with previous==0
insilmaril@741
   158
	// Start at root, if current==NULL
insilmaril@750
   159
	if (!current) current=(BranchItem*)rootItem;
insilmaril@741
   160
insilmaril@741
   161
	// Are we just beginning to walk the map?
insilmaril@741
   162
	if (!previous)
insilmaril@741
   163
	{
insilmaril@773
   164
		if (!start) start=current;
insilmaril@741
   165
		previous=current;
insilmaril@741
   166
		current=current->getFirstBranch();
insilmaril@741
   167
		return current;
insilmaril@741
   168
	}
insilmaril@741
   169
insilmaril@741
   170
	// Going up or down (deeper)?
insilmaril@741
   171
	if (current->depth() > previous->depth() )
insilmaril@741
   172
	{	
insilmaril@741
   173
		// Coming from above
insilmaril@741
   174
		// Trying  to go down deeper
insilmaril@776
   175
//		cout << "  trying to go deeper\n";
insilmaril@741
   176
		if (current->branchCount() >0 )
insilmaril@741
   177
		{
insilmaril@776
   178
//			cout << "  yes, going deeper\n";
insilmaril@741
   179
			previous=current;
insilmaril@741
   180
			current=current->getFirstBranch();
insilmaril@741
   181
			return current;
insilmaril@741
   182
		}	
insilmaril@741
   183
		// turn around and go up again
insilmaril@776
   184
//		cout << "  sorry, turn around\n";
insilmaril@776
   185
		BranchItem *bi=current;
insilmaril@776
   186
		current=previous;
insilmaril@776
   187
		previous=bi;
insilmaril@741
   188
	}	
insilmaril@741
   189
insilmaril@776
   190
/*
insilmaril@776
   191
	cout << "  coming from below\n";
insilmaril@776
   192
	ch="()"; if (current) ch=current->getHeadingStd();
insilmaril@776
   193
	ph="()"; if (previous) ph=previous->getHeadingStd();
insilmaril@776
   194
	cout << "  cur="<<ch << " prev="<<ph<<endl;
insilmaril@776
   195
*/	
insilmaril@773
   196
	// Coming from below
insilmaril@741
   197
	// Trying to go down again to siblings
insilmaril@741
   198
insilmaril@750
   199
	BranchItem *sibling=current->getBranchNum (previous->num()+1);
insilmaril@776
   200
//	cout <<"    prev->num()="<<previous->num()<<endl;
insilmaril@741
   201
insilmaril@741
   202
	if (sibling)
insilmaril@741
   203
	{	
insilmaril@741
   204
		// Found sibling of previous, go there
insilmaril@776
   205
//		cout << "  sib=cur="<<sibling->getHeadingStd()<<endl;
insilmaril@741
   206
		previous=current;
insilmaril@741
   207
		current=sibling;
insilmaril@741
   208
		return current;
insilmaril@741
   209
	} 
insilmaril@741
   210
insilmaril@773
   211
	// If we only needed to go through subtree, we are done now
insilmaril@773
   212
	if (start==current) return NULL;
insilmaril@773
   213
insilmaril@741
   214
	// Go up and try to find siblings of current
insilmaril@776
   215
//	cout <<"  going up again...\n";
insilmaril@741
   216
	previous=current;
insilmaril@750
   217
	current=(BranchItem*)current->parent();
insilmaril@741
   218
insilmaril@741
   219
	// Check if we still can go somewhere
insilmaril@741
   220
	if (!current) return current;
insilmaril@741
   221
	
insilmaril@741
   222
	while (current && current->depth() < previous->depth() )
insilmaril@773
   223
		current=next (current,previous,start);
insilmaril@741
   224
		
insilmaril@741
   225
	return current;
insilmaril@741
   226
}
insilmaril@741
   227
insilmaril@727
   228
bool TreeModel::removeRows ( int row, int count, const QModelIndex & parent)
insilmaril@727
   229
{
insilmaril@727
   230
	int last=row+count-1;
insilmaril@745
   231
    TreeItem *pi= getItem (parent);
insilmaril@755
   232
	TreeItem *ti;
insilmaril@727
   233
insilmaril@788
   234
	cout << "TM::removeRows  row="<<row<<"  count="<<count<<endl;
insilmaril@727
   235
	for (int i=row; i<=last; i++)
insilmaril@727
   236
	{
insilmaril@755
   237
		ti=pi->getChildNum (row);
insilmaril@790
   238
		cout << "   pi="<<pi<<"  ti="<<ti<<endl;
insilmaril@755
   239
		pi->removeChild (row);	// does not delete object!
insilmaril@791
   240
		delete ti;
insilmaril@791
   241
		/* FIXME-3
insilmaril@756
   242
		switch (ti->getType()) 
insilmaril@756
   243
		{
insilmaril@756
   244
			case TreeItem::MapCenter: 
insilmaril@756
   245
				delete (BranchItem*)ti; 
insilmaril@756
   246
				break;
insilmaril@756
   247
			case TreeItem::Branch:
insilmaril@756
   248
				delete (BranchItem*)ti; 
insilmaril@756
   249
				break;
insilmaril@776
   250
			case TreeItem::Image:
insilmaril@776
   251
				delete (ImageItem*)ti; 
insilmaril@776
   252
				break;
insilmaril@788
   253
			case TreeItem::Attribute:
insilmaril@788
   254
				delete (AttributeItem*)ti; 
insilmaril@788
   255
				break;
insilmaril@790
   256
			case TreeItem::XLink:
insilmaril@790
   257
				delete (XLinkItem*)ti; 
insilmaril@790
   258
				break;
insilmaril@756
   259
			default:
insilmaril@756
   260
				delete ti;
insilmaril@756
   261
				break;
insilmaril@756
   262
		}
insilmaril@791
   263
		*/
insilmaril@727
   264
	}
insilmaril@745
   265
	return true;
insilmaril@745
   266
}
insilmaril@727
   267
insilmaril@745
   268
TreeItem *TreeModel::getItem(const QModelIndex &index) const
insilmaril@745
   269
{
insilmaril@788
   270
//FIXME-3	cout << "TM::getItem  "<<index.internalPointer()<<endl;
insilmaril@745
   271
    if (index.isValid()) {
insilmaril@745
   272
		TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
insilmaril@745
   273
insilmaril@788
   274
//		cout << "   item="<<item<<endl;
insilmaril@745
   275
        if (item) return item;
insilmaril@745
   276
    }
insilmaril@791
   277
    return NULL;
insilmaril@727
   278
}
insilmaril@727
   279
insilmaril@793
   280
BranchItem *TreeModel::getRootItem()
insilmaril@754
   281
{
insilmaril@754
   282
	return rootItem;
insilmaril@754
   283
}
insilmaril@754
   284