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