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