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