vymmodel.cpp
changeset 847 43268373032d
parent 845 b98c1793bb8b
child 848 e265f07f2173
     1.1 --- a/vymmodel.cpp	Fri Apr 09 14:24:04 2010 +0000
     1.2 +++ b/vymmodel.cpp	Wed Jun 09 13:14:08 2010 +0000
     1.3 @@ -12,14 +12,13 @@
     1.4  #include "exporthtmldialog.h"
     1.5  #include "file.h"
     1.6  #include "findresultmodel.h"
     1.7 -#include "geometry.h"		// for addBBox
     1.8  #include "mainwindow.h"
     1.9  #include "misc.h"
    1.10  #include "parser.h"
    1.11  #include "process.h"
    1.12  
    1.13 -#include "warningdialog.h"
    1.14  #include "xlinkitem.h"
    1.15 +#include "xlinkobj.h"
    1.16  #include "xml-freemind.h"
    1.17  #include "xmlobj.h"
    1.18  #include "xml-vym.h"
    1.19 @@ -54,7 +53,7 @@
    1.20  
    1.21  VymModel::VymModel()
    1.22  {
    1.23 -    //cout << "Const VymModel\n";
    1.24 +    //qDebug()<< "Const VymModel";
    1.25  	init();
    1.26  	rootItem->setModel (this);
    1.27  }
    1.28 @@ -62,18 +61,20 @@
    1.29  
    1.30  VymModel::~VymModel() 
    1.31  {
    1.32 -    //cout << "Destr VymModel\n";
    1.33 +    //qDebug() << "Destr VymModel begin this="<<this;
    1.34  	autosaveTimer->stop();
    1.35  	fileChangedTimer->stop();
    1.36 -	clear();
    1.37 -	if (mapEditor) delete (mapEditor);
    1.38 +	//qApp->processEvents();	// Update view (scene()->update() is not enough)
    1.39 +    //qDebug() << "Destr VymModel end   this="<<this;
    1.40  }	
    1.41  
    1.42  void VymModel::clear() 
    1.43  {
    1.44 -	unselect();
    1.45  	while (rootItem->childCount() >0)
    1.46 +	{
    1.47 +		//qDebug()<<"VM::clear  ri="<<rootItem<<"  ri->count()="<<rootItem->childCount();
    1.48  		deleteItem (rootItem->getChildNum(0) );
    1.49 +	}
    1.50  }
    1.51  
    1.52  void VymModel::init () 
    1.53 @@ -125,11 +126,11 @@
    1.54  	// find routine
    1.55  	findReset();
    1.56  
    1.57 -	// animations	// FIXME-3 switch to new animation system 
    1.58 -	animationUse=settings.readBoolEntry("/animation/use",false);	// FIXME-3 add options to control _what_ is animated
    1.59 +	// animations	// FIXME-4 switch to new animation system 
    1.60 +	animationUse=settings.readBoolEntry("/animation/use",false);	// FIXME-4 add options to control _what_ is animated
    1.61  	animationTicks=settings.readNumEntry("/animation/ticks",10);
    1.62  	animationInterval=settings.readNumEntry("/animation/interval",50);
    1.63 -	animObjList.clear();
    1.64 +	animObjList.clear();	
    1.65  	animationTimer=new QTimer (this);
    1.66  	connect(animationTimer, SIGNAL(timeout()), this, SLOT(animate()));
    1.67  
    1.68 @@ -144,6 +145,9 @@
    1.69  
    1.70  	hidemode=TreeItem::HideNone;
    1.71  
    1.72 +	// Avoid recursions later
    1.73 +	cleaningUpLinks=false;
    1.74 +
    1.75  	// Network
    1.76  	netstate=Offline;
    1.77  
    1.78 @@ -236,21 +240,34 @@
    1.79  	// Find the used flags while traversing the tree	// FIXME-3 this can be done local to vymmodel maybe...
    1.80  	standardFlagsMaster->resetUsedCounter();
    1.81  	
    1.82 +
    1.83 +	// Temporary list of links
    1.84 +	QList <Link*> tmpLinks;
    1.85 +
    1.86  	// Build xml recursivly
    1.87  	if (!saveSel)
    1.88 +	{
    1.89  		// Save all mapcenters as complete map, if saveSel not set
    1.90 -		s+=saveTreeToDir(tmpdir,prefix,offset);
    1.91 -	else
    1.92 +			s+=saveTreeToDir(tmpdir,prefix,offset,tmpLinks);
    1.93 +
    1.94 +		// Save local settings
    1.95 +		s+=settings.getDataXML (destPath);
    1.96 +
    1.97 +		// Save selection
    1.98 +		if (getSelectedItem() && !saveSel ) 
    1.99 +			s+=xml.valueElement("select",getSelectString());
   1.100 +
   1.101 +	} else
   1.102  	{
   1.103  		switch (saveSel->getType())
   1.104  		{
   1.105  			case TreeItem::Branch:
   1.106  				// Save Subtree
   1.107 -				s+=((BranchItem*)saveSel)->saveToDir(tmpdir,prefix,offset);
   1.108 +				s+=((BranchItem*)saveSel)->saveToDir(tmpdir,prefix,offset,tmpLinks);
   1.109  				break;
   1.110  			case TreeItem::MapCenter:
   1.111  				// Save Subtree
   1.112 -				s+=((BranchItem*)saveSel)->saveToDir(tmpdir,prefix,offset);
   1.113 +				s+=((BranchItem*)saveSel)->saveToDir(tmpdir,prefix,offset,tmpLinks);
   1.114  				break;
   1.115  			case TreeItem::Image:
   1.116  				// Save Image
   1.117 @@ -262,12 +279,11 @@
   1.118  		}
   1.119  	}
   1.120  
   1.121 -	// Save local settings
   1.122 -	s+=settings.getDataXML (destPath);
   1.123 -
   1.124 -	// Save selection
   1.125 -	if (getSelectedItem() && !saveSel ) 
   1.126 -		s+=xml.valueElement("select",getSelectString());
   1.127 +	// Save XLinks
   1.128 +	for (int i=0; i<tmpLinks.count();++i)
   1.129 +	{
   1.130 +		s+=tmpLinks.at(i)->saveToDir();
   1.131 +	}
   1.132  
   1.133  	xml.decIndent();
   1.134  	s+=xml.endElement("vymmap");
   1.135 @@ -278,12 +294,11 @@
   1.136  	return s;
   1.137  }
   1.138  
   1.139 -QString VymModel::saveTreeToDir (const QString &tmpdir,const QString &prefix, const QPointF &offset)
   1.140 +QString VymModel::saveTreeToDir (const QString &tmpdir,const QString &prefix, const QPointF &offset, QList <Link*> &tmpLinks)
   1.141  {
   1.142      QString s;
   1.143 -
   1.144  	for (int i=0; i<rootItem->branchCount(); i++)
   1.145 -		s+=rootItem->getBranchNum(i)->saveToDir (tmpdir,prefix,offset);
   1.146 +		s+=rootItem->getBranchNum(i)->saveToDir (tmpdir,prefix,offset,tmpLinks);
   1.147      return s;
   1.148  }
   1.149  
   1.150 @@ -338,10 +353,22 @@
   1.151  	return destPath;
   1.152  }
   1.153  
   1.154 -ErrorCode VymModel::load (QString fname, const LoadMode &lmode, const FileType &ftype)
   1.155 +ErrorCode VymModel::loadMap (
   1.156 +	QString fname, 
   1.157 +	const LoadMode &lmode, 
   1.158 +	bool saveStateFlag, 
   1.159 +	const FileType &ftype,
   1.160 +	int pos)
   1.161  {
   1.162  	ErrorCode err=success;
   1.163  
   1.164 +	// Get updated zoomFactor, before applying one read from file in the end
   1.165 +	if (mapEditor) zoomFactor=mapEditor->getZoomFactorTarget();
   1.166 +
   1.167 +	// For ImportReplace let's insert a new branch and replace that
   1.168 +	BranchItem *selbi=getSelectedBranch();
   1.169 +	BranchItem *newbi=NULL;
   1.170 +
   1.171  	parseBaseHandler *handler;
   1.172  	fileType=ftype;
   1.173  	switch (fileType)
   1.174 @@ -361,20 +388,23 @@
   1.175  		selModel->clearSelection();
   1.176  	} else
   1.177  	{
   1.178 -		BranchItem *bi=getSelectedBranch();
   1.179 -		if (!bi) return aborted;
   1.180 +		if (!selbi) return aborted;
   1.181  		if (lmode==ImportAdd)
   1.182 -			saveStateChangingPart(
   1.183 -				bi,
   1.184 -				bi,
   1.185 +			if (saveStateFlag) saveStateChangingPart(
   1.186 +				selbi,
   1.187 +				selbi,
   1.188  				QString("addMapInsert (%1)").arg(fname),
   1.189 -				QString("Add map %1 to %2").arg(fname).arg(getObjectName(bi)));
   1.190 -		else	
   1.191 -			saveStateChangingPart(
   1.192 -				bi,
   1.193 -				bi,
   1.194 +				QString("Add map %1 to %2").arg(fname).arg(getObjectName(selbi)));
   1.195 +		if (lmode==ImportReplace)
   1.196 +		{
   1.197 +			if (saveStateFlag) saveStateChangingPart(
   1.198 +				selbi,
   1.199 +				selbi,
   1.200  				QString("addMapReplace(%1)").arg(fname),
   1.201 -				QString("Add map %1 to %2").arg(fname).arg(getObjectName(bi)));
   1.202 +				QString("Add map %1 to %2").arg(fname).arg(getObjectName(selbi)));
   1.203 +			newbi=addNewBranchInt (selbi,-1);	// Add below selection	
   1.204 +			select (newbi);
   1.205 +		}
   1.206  	}	
   1.207      
   1.208  
   1.209 @@ -465,7 +495,11 @@
   1.210  			tmpdir=fname.left(fname.findRev("/",-1));	
   1.211  		handler->setTmpDir (tmpdir);
   1.212  		handler->setInputFile (file.name());
   1.213 -		handler->setLoadMode (lmode);
   1.214 +		if (lmode==ImportReplace)
   1.215 +			handler->setLoadMode (ImportAdd,pos);
   1.216 +		else	
   1.217 +			handler->setLoadMode (lmode,pos);
   1.218 +
   1.219  		bool ok = reader.parse( source );
   1.220  		blockReposition=false;
   1.221  		blockSaveState=blockSaveStateOrg;
   1.222 @@ -473,18 +507,27 @@
   1.223  		file.close();
   1.224  		if ( ok ) 
   1.225  		{
   1.226 -			reposition();	
   1.227 -			emitSelectionChanged();
   1.228  			if (lmode==NewMap)
   1.229  			{
   1.230  				mapDefault=false;
   1.231  				mapChanged=false;
   1.232  				mapUnsaved=false;
   1.233  				autosaveTimer->stop();
   1.234 +
   1.235 +				// Reset timestamp to check for later updates of file
   1.236 +				fileChangedTime=QFileInfo (destPath).lastModified();
   1.237  			}
   1.238  
   1.239 -			// Reset timestamp to check for later updates of file
   1.240 -			fileChangedTime=QFileInfo (destPath).lastModified();
   1.241 +	
   1.242 +
   1.243 +			if (lmode==ImportReplace)
   1.244 +			{
   1.245 +				deleteItem (selbi);
   1.246 +				select (newbi);
   1.247 +				deleteKeepChildren (false);
   1.248 +			}
   1.249 +			reposition();	
   1.250 +			emitSelectionChanged();
   1.251  		} else 
   1.252  		{
   1.253  			QMessageBox::critical( 0, tr( "Critical Parse Error" ),
   1.254 @@ -640,96 +683,6 @@
   1.255  	return err;
   1.256  }
   1.257  
   1.258 -void VymModel::addMapReplaceInt(const QString &undoSel, const QString &path)	
   1.259 -{
   1.260 -	QString pathDir=path.left(path.findRev("/"));
   1.261 -	QDir d(pathDir);
   1.262 -	QFile file (path);
   1.263 -
   1.264 -	if (d.exists() )
   1.265 -	{
   1.266 -		// We need to parse saved XML data
   1.267 -		parseVYMHandler handler;
   1.268 -		QXmlInputSource source( file);
   1.269 -		QXmlSimpleReader reader;
   1.270 -		reader.setContentHandler( &handler );
   1.271 -		reader.setErrorHandler( &handler );
   1.272 -		handler.setModel ( this);
   1.273 -		handler.setTmpDir ( pathDir );	// needed to load files with rel. path
   1.274 -		if (undoSel.isEmpty())
   1.275 -		{
   1.276 -			unselect();
   1.277 -			clear();
   1.278 -			handler.setLoadMode (NewMap);
   1.279 -		} else	
   1.280 -		{
   1.281 -			select (undoSel);
   1.282 -			handler.setLoadMode (ImportReplace);
   1.283 -		}	
   1.284 -		blockReposition=true;
   1.285 -		bool ok = reader.parse( source );
   1.286 -		blockReposition=false;
   1.287 -		if (! ok ) 
   1.288 -		{	
   1.289 -			// This should never ever happen
   1.290 -			QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
   1.291 -								    handler.errorProtocol());
   1.292 -		}
   1.293 -	} else	
   1.294 -		QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
   1.295 -}
   1.296 -
   1.297 -bool VymModel::addMapInsertInt (const QString &path)
   1.298 -{
   1.299 -	QString pathDir=path.left(path.findRev("/"));
   1.300 -	QDir d(pathDir);
   1.301 -	QFile file (path);
   1.302 -
   1.303 -	if (d.exists() )
   1.304 -	{
   1.305 -		// We need to parse saved XML data
   1.306 -		parseVYMHandler handler;
   1.307 -		QXmlInputSource source( file);
   1.308 -		QXmlSimpleReader reader;
   1.309 -		reader.setContentHandler( &handler );
   1.310 -		reader.setErrorHandler( &handler );
   1.311 -		handler.setModel (this);
   1.312 -		handler.setTmpDir ( pathDir );	// needed to load files with rel. path
   1.313 -		handler.setLoadMode (ImportAdd);
   1.314 -		blockReposition=true;
   1.315 -		bool ok = reader.parse( source );
   1.316 -		blockReposition=false;
   1.317 -		if ( ok ) return true;
   1.318 -		{	
   1.319 -			// This should never ever happen
   1.320 -			QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
   1.321 -									handler.errorProtocol());
   1.322 -		}
   1.323 -	} else	
   1.324 -		QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
   1.325 -	return false;
   1.326 -}
   1.327 -
   1.328 -bool VymModel::addMapInsertInt (const QString &path, int pos)
   1.329 -{
   1.330 -	BranchItem *selbi=getSelectedBranch();
   1.331 -	if (selbi)
   1.332 -	{
   1.333 -		if (addMapInsertInt (path))
   1.334 -		{
   1.335 -			if (selbi->depth()>0)
   1.336 -				relinkBranch (selbi->getLastBranch(), selbi,pos);
   1.337 -			return true;	
   1.338 -		} else
   1.339 -		{
   1.340 -			QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
   1.341 -			return false;
   1.342 -		}	
   1.343 -	}		
   1.344 -	qWarning ("ME::addMapInsertInt nothing selected");
   1.345 -	return false;
   1.346 -}
   1.347 -
   1.348  ImageItem* VymModel::loadFloatImageInt (BranchItem *dst,QString fn)
   1.349  {
   1.350  	ImageItem *ii=createImage(dst);
   1.351 @@ -975,7 +928,7 @@
   1.352  			{
   1.353  				case QMessageBox::Yes:
   1.354  					// Reload map
   1.355 -					load (filePath,NewMap,fileType);
   1.356 +					loadMap (filePath);
   1.357  		        case QMessageBox::Cancel:
   1.358  					fileChangedTime=tmod; // allow autosave to overwrite newer file!
   1.359  			}
   1.360 @@ -1109,7 +1062,7 @@
   1.361  		return false;
   1.362  }
   1.363  
   1.364 -void VymModel::undo()
   1.365 +void VymModel::undo()	//FIXME-1 segfault when trying to undo in a brandnew map
   1.366  {
   1.367  	// Can we undo at all?
   1.368  	if (undosAvail<1) return;
   1.369 @@ -1253,6 +1206,7 @@
   1.370  		makeSubDirs (histDir);
   1.371  
   1.372  	// Save depending on how much needs to be saved	
   1.373 +	QList <Link*> tmpLinks;
   1.374  	if (saveSel)
   1.375  		backupXML=saveToDir (histDir,mapName+"-",false, QPointF (),saveSel);
   1.376  		
   1.377 @@ -1529,7 +1483,7 @@
   1.378  	return sortFilter;
   1.379  }
   1.380  
   1.381 -void VymModel::setHeading(const QString &s)
   1.382 +void VymModel::setHeading(const QString &s) 
   1.383  {
   1.384  	BranchItem *selbi=getSelectedBranch();
   1.385  	if (selbi)
   1.386 @@ -1541,7 +1495,7 @@
   1.387  			"setHeading (\""+s+"\")", 
   1.388  			QString("Set heading of %1 to \"%2\"").arg(getObjectName(selbi)).arg(s) );
   1.389  		selbi->setHeading(s );
   1.390 -		emitDataHasChanged ( selbi);	//FIXME-3 maybe emit signal from TreeItem? 
   1.391 +		emitDataHasChanged ( selbi);	//FIXME-4 maybe emit signal from TreeItem? 
   1.392  		reposition();
   1.393  		emitSelectionChanged();
   1.394  	}
   1.395 @@ -1655,7 +1609,7 @@
   1.396  {
   1.397  	rmodel->clear();
   1.398  	rmodel->setSearchString (s);
   1.399 -	rmodel->setSearchFlags (0);	//FIXME-2 translate cs to QTextDocument::FindFlag
   1.400 +	rmodel->setSearchFlags (0);	//FIXME-3 translate cs to QTextDocument::FindFlag
   1.401  	BranchItem *cur=NULL;
   1.402  	BranchItem *prev=NULL;
   1.403  	nextBranch(cur,prev);
   1.404 @@ -1671,7 +1625,7 @@
   1.405  		int j=0;
   1.406  		while ( i>=0)
   1.407  		{
   1.408 -			i=n.indexOf (s,i,cs); //FIXME-2 add subitems to rmodel
   1.409 +			i=n.indexOf (s,i,cs); 
   1.410  			if (i>=0) 
   1.411  			{
   1.412  				// If not there yet, add "parent" item
   1.413 @@ -2050,20 +2004,17 @@
   1.414  
   1.415  void VymModel::pasteNoSave(const int &n)
   1.416  {
   1.417 -	bool old=blockSaveState;
   1.418 -	blockSaveState=true;
   1.419  	bool zippedOrg=zipped;
   1.420  	if (redosAvail > 0 || n!=0)
   1.421  	{
   1.422  		// Use the "historical" buffer
   1.423  		QString bakMapName(QString("history-%1").arg(n));
   1.424  		QString bakMapDir(tmpMapDir +"/"+bakMapName);
   1.425 -		load (bakMapDir+"/"+clipboardFile,ImportAdd, VymMap);
   1.426 +		loadMap (bakMapDir+"/"+clipboardFile,ImportAdd, false);
   1.427  	} else
   1.428  		// Use the global buffer
   1.429 -		load (clipboardDir+"/"+clipboardFile,ImportAdd, VymMap);
   1.430 +		loadMap (clipboardDir+"/"+clipboardFile,ImportAdd, false);
   1.431  	zipped=zippedOrg;
   1.432 -	blockSaveState=old;
   1.433  }
   1.434  
   1.435  void VymModel::paste()	
   1.436 @@ -2231,39 +2182,61 @@
   1.437  	return NULL;
   1.438  }
   1.439  
   1.440 -XLinkItem* VymModel::createXLink(BranchItem *bi,bool createMO)
   1.441 -{
   1.442 -	if (bi)
   1.443 -	{
   1.444 +bool VymModel::createLink(Link *link, bool createMO)
   1.445 +{
   1.446 +		BranchItem *begin=link->getBeginBranch();
   1.447 +		BranchItem *end  =link->getEndBranch();
   1.448 +
   1.449 +		if (!begin || !end)
   1.450 +		{
   1.451 +			qWarning ()<<"VM::createXLinkNew part of XLink is NULL";
   1.452 +			return false;
   1.453 +		}
   1.454 +
   1.455 +
   1.456  		QModelIndex parix;
   1.457  		int n;
   1.458  
   1.459  		QList<QVariant> cData;
   1.460 -		cData << "new xLink"<<"undef";
   1.461 -
   1.462 -		XLinkItem *newxli=new XLinkItem(cData) ;	
   1.463 -		newxli->setBegin (bi);
   1.464 +
   1.465 +		cData << "new Link begin"<<"undef";
   1.466 +		XLinkItem *newli=new XLinkItem(cData) ;	
   1.467 +		newli->setLink (link);
   1.468 +		link->setBeginLinkItem (newli);
   1.469  
   1.470  		emit (layoutAboutToBeChanged() );
   1.471  
   1.472 -			parix=index(bi);
   1.473 -			n=bi->getRowNumAppend(newxli);
   1.474 +			parix=index(begin);
   1.475 +			n=begin->getRowNumAppend(newli);
   1.476  			beginInsertRows (parix,n,n);
   1.477 -			bi->appendChild (newxli);	
   1.478 +			begin->appendChild (newli);	
   1.479  			endInsertRows ();
   1.480  
   1.481 +		cData.clear();
   1.482 +		cData << "new Link end"<<"undef";
   1.483 +		newli=new XLinkItem(cData) ;	
   1.484 +		newli->setLink (link);
   1.485 +		link->setEndLinkItem (newli);
   1.486 +
   1.487 +			parix=index(end);
   1.488 +			n=end->getRowNumAppend(newli);
   1.489 +			beginInsertRows (parix,n,n);
   1.490 +			end->appendChild (newli);	
   1.491 +			endInsertRows ();
   1.492 +
   1.493  		emit (layoutChanged() );
   1.494  
   1.495 -		// save scroll state. If scrolled, automatically select
   1.496 -		// new branch in order to tmp unscroll parent...
   1.497 +		xlinks.append (link);
   1.498 +		link->activate();
   1.499 +
   1.500  		if (createMO) 
   1.501  		{
   1.502 -			newxli->createMapObj(mapScene);
   1.503 +			link->createMapObj(mapScene);
   1.504  			reposition();
   1.505  		}
   1.506 -		return newxli;
   1.507 -	} 
   1.508 -	return NULL;
   1.509 +//	} 
   1.510 +	//return newli;
   1.511 +	return true;
   1.512  }
   1.513  
   1.514  AttributeItem* VymModel::addAttribute()	
   1.515 @@ -2279,7 +2252,7 @@
   1.516  	return NULL;
   1.517  }
   1.518  
   1.519 -AttributeItem* VymModel::addAttribute(AttributeItem *ai)	// FIXME-2 savestate missing
   1.520 +AttributeItem* VymModel::addAttribute(AttributeItem *ai)	// FIXME-3 savestate missing
   1.521  {
   1.522  	BranchItem *selbi=getSelectedBranch();
   1.523  	if (selbi)
   1.524 @@ -2294,7 +2267,7 @@
   1.525  
   1.526  		emit (layoutChanged() );
   1.527  
   1.528 -		ai->createMapObj(mapScene);		//FIXME-2 check that...
   1.529 +		ai->createMapObj(mapScene);		//FIXME-3 check that...
   1.530  		reposition();
   1.531  		return ai;
   1.532  	}
   1.533 @@ -2564,7 +2537,30 @@
   1.534  	return false;
   1.535  }
   1.536  
   1.537 -void VymModel::deleteSelection()	//FIXME-2 xLinks in a deleted subtree are not restored on undo	
   1.538 +void VymModel::cleanupLinks()	
   1.539 +{
   1.540 +	// This probably could be done more elegant from destructor of a Link,
   1.541 +	// but somehow this resulted in strange segfaults deep in Qt and glibc...
   1.542 +	//qDebug ()<<"VM::cleanupLinks begin"<< "CUL="<<cleaningUpLinks;
   1.543 +	cleaningUpLinks=true;
   1.544 +	Link *l;
   1.545 +	XLinkItem *xli;
   1.546 +	while (!xlinks_obsolete.isEmpty())
   1.547 +	{
   1.548 +		l=xlinks_obsolete.takeFirst();
   1.549 +		xli=l->getBeginLinkItem();
   1.550 +		//qDebug()<<"VM::cleanupLinks  a)  l="<<l<<"  xli="<<xli;
   1.551 +		if (xli) deleteItem (xli);
   1.552 +		xli=l->getEndLinkItem();
   1.553 +		//qDebug()<<"VM::cleanupLinks  b)  l="<<l<<"  xli="<<xli;
   1.554 +		if (xli) deleteItem (xli);
   1.555 +		delete (l);
   1.556 +	}
   1.557 +	cleaningUpLinks=false;
   1.558 +	//qDebug ()<<"VM::cleanupLinks end";
   1.559 +}
   1.560 +
   1.561 +void VymModel::deleteSelection()	
   1.562  {
   1.563  	BranchItem *selbi=getSelectedBranch();
   1.564  
   1.565 @@ -2586,12 +2582,14 @@
   1.566  		}
   1.567  		return;
   1.568  	}
   1.569 +
   1.570  	TreeItem *ti=getSelectedItem();
   1.571 +
   1.572  	if (ti)
   1.573  	{	// Delete other item
   1.574  		TreeItem *pi=ti->parent();
   1.575  		if (!pi) return;
   1.576 -		if (ti->getType()==TreeItem::Image || ti->getType()==TreeItem::Attribute)
   1.577 +		if (ti->getType()==TreeItem::Image || ti->getType()==TreeItem::Attribute||ti->getType()==TreeItem::XLink)
   1.578  		{
   1.579  			saveStateChangingPart(
   1.580  				pi, 
   1.581 @@ -2605,16 +2603,12 @@
   1.582  			select (pi);
   1.583  			reposition();
   1.584  			emitShowSelection();
   1.585 -		} else if (ti->getType()==TreeItem::XLink)
   1.586 -		{
   1.587 -			//FIXME-2 savestate for deleting xlink missing
   1.588 -			deleteItem (ti);
   1.589  		} else
   1.590  			qWarning ("VymmModel::deleteSelection()  unknown type?!");
   1.591  	}
   1.592  }
   1.593  
   1.594 -void VymModel::deleteKeepChildren()	//FIXME-3 does not work yet for mapcenters
   1.595 +void VymModel::deleteKeepChildren(bool saveStateFlag)	//FIXME-3 does not work yet for mapcenters
   1.596  
   1.597  {
   1.598  	BranchItem *selbi=getSelectedBranch();
   1.599 @@ -2634,7 +2628,7 @@
   1.600  
   1.601  		QPointF p;
   1.602  		if (selbi->getLMO()) p=selbi->getLMO()->getRelPos();
   1.603 -		saveStateChangingPart(
   1.604 +		if (saveStateFlag) saveStateChangingPart(
   1.605  			pi,
   1.606  			selbi,
   1.607  			"deleteKeepChildren ()",
   1.608 @@ -2693,6 +2687,7 @@
   1.609  	if (ti)
   1.610  	{
   1.611  		TreeItem *pi=ti->parent();
   1.612 +		//qDebug()<<"VM::deleteItem  start ti="<<ti<<"  "<<ti->getHeading()<<"  pi="<<pi<<"="<<pi->getHeading();
   1.613  		QModelIndex parentIndex=index(pi);
   1.614  
   1.615  		emit (layoutAboutToBeChanged() );
   1.616 @@ -2704,11 +2699,19 @@
   1.617  		reposition();
   1.618  
   1.619  		emit (layoutChanged() );
   1.620 +		//qDebug()<<"VM::deleteItem  end   ti="<<ti;
   1.621 +		if (!cleaningUpLinks) cleanupLinks();
   1.622  		if (pi->depth()>=0) return pi;
   1.623  	}	
   1.624  	return NULL;
   1.625  }
   1.626  
   1.627 +void VymModel::deleteLink(Link* l)	
   1.628 +{
   1.629 +	int i=xlinks.indexOf(l);
   1.630 +	if (i>-1) xlinks_obsolete.append (xlinks.takeAt (i));
   1.631 +}
   1.632 +
   1.633  void VymModel::clearItem (TreeItem *ti)
   1.634  {
   1.635  	if (ti)
   1.636 @@ -3138,35 +3141,30 @@
   1.637  	}
   1.638  }
   1.639  
   1.640 -void VymModel::editXLink(int i)	
   1.641 -{
   1.642 -	i=0;
   1.643 +void VymModel::editXLink(int i)
   1.644 +{
   1.645  	BranchItem *selbi=getSelectedBranch();
   1.646  	if (selbi)
   1.647  	{
   1.648 -		XLinkItem *xli=selbi->getXLinkNum(i);
   1.649 -		if (xli) 
   1.650 +		Link *l=selbi->getXLinkNum(i)->getLink();
   1.651 +		if (l) 
   1.652  		{
   1.653  			EditXLinkDialog dia;
   1.654 -			dia.setXLink (xli);
   1.655 +			dia.setLink (l);
   1.656  			dia.setSelection(selbi);
   1.657  			if (dia.exec() == QDialog::Accepted)
   1.658  			{
   1.659  				if (dia.useSettingsGlobal() )
   1.660  				{
   1.661 -					setMapDefXLinkColor (xli->getColor() );
   1.662 -					setMapDefXLinkWidth (xli->getWidth() );
   1.663 +					setMapDefXLinkColor (l->getColor() );
   1.664 +					setMapDefXLinkWidth (l->getWidth() );
   1.665  				}
   1.666 -				if (dia.deleteXLink()) deleteItem (xli);
   1.667 +				if (dia.deleteXLink()) delete (l);
   1.668  			}
   1.669  		}	
   1.670  	}
   1.671  }
   1.672  
   1.673 -
   1.674 -
   1.675 -
   1.676 -
   1.677  //////////////////////////////////////////////
   1.678  // Scripting
   1.679  //////////////////////////////////////////////
   1.680 @@ -3252,7 +3250,7 @@
   1.681  			//s=parser.parString (ok,0);	// selection
   1.682  			t=parser.parString (ok,0);	// path to map
   1.683  			if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
   1.684 -			addMapReplaceInt(getSelectString(selbi),t);	
   1.685 +			loadMap (t,ImportReplace,false,VymMap,n);
   1.686  		}
   1.687  	/////////////////////////////////////////////////////////////////////
   1.688  	} else if (com==QString("addMapInsert"))
   1.689 @@ -3271,18 +3269,19 @@
   1.690  				t=parser.parString (ok,0);	// path to map
   1.691  				n=parser.parInt(ok,1);		// position
   1.692  				if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
   1.693 -				addMapInsertInt(t,n);	
   1.694 +				loadMap (t,ImportAdd,false,VymMap,n);
   1.695  			}
   1.696  		} else if (parser.parCount()==1)
   1.697  		{
   1.698  			t=parser.parString (ok,0);	// path to map
   1.699  			if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
   1.700 -			addMapInsertInt(t);	
   1.701 +			loadMap (t,ImportAdd,false);
   1.702  		} else
   1.703  			parser.setError (Aborted,"Wrong number of parameters");
   1.704  	/////////////////////////////////////////////////////////////////////
   1.705 -	} else if (com==QString("addXLink"))
   1.706 -	{
   1.707 +	} else if (com==QString("addXLink"))  //FIXME-2 not ported yet to Link
   1.708 +	{
   1.709 +	/*
   1.710  		if (parser.parCount()>1)
   1.711  		{
   1.712  			s=parser.parString (ok,0);	// begin
   1.713 @@ -3308,6 +3307,7 @@
   1.714  				parser.setError (Aborted,"Couldn't select begin or end of xLink");
   1.715  		} else
   1.716  			parser.setError (Aborted,"Need at least 2 parameters for begin and end");
   1.717 +	*/		
   1.718  	/////////////////////////////////////////////////////////////////////
   1.719  	} else if (com=="clearFlags")	
   1.720  	{
   1.721 @@ -4424,8 +4424,15 @@
   1.722  	//cout << "VM::reposition blocked="<<blockReposition<<endl;
   1.723  	if (blockReposition) return;
   1.724  
   1.725 +	BranchObj *bo;
   1.726  	for (int i=0;i<rootItem->branchCount(); i++)
   1.727 -		rootItem->getBranchObjNum(i)->reposition();	//	for positioning heading
   1.728 +	{
   1.729 +		bo=rootItem->getBranchObjNum(i);
   1.730 +		if (bo)
   1.731 +			bo->reposition();	//	for positioning heading
   1.732 +		else
   1.733 +			qDebug()<<"VM::reposition bo=0";
   1.734 +	}	
   1.735  	//emitSelectionChanged();	
   1.736  }
   1.737  
   1.738 @@ -4763,6 +4770,20 @@
   1.739  		animObjList.removeAt (i);
   1.740  }
   1.741  
   1.742 +void VymModel::stopAllAnimation ()
   1.743 +{
   1.744 +	BranchObj *bo;
   1.745 +	int i=0;
   1.746 +	while (i<animObjList.size() )
   1.747 +	{
   1.748 +		bo=(BranchObj*)animObjList.at(i);
   1.749 +		bo->stopAnimation();
   1.750 +		bo->requestReposition();
   1.751 +		i++;
   1.752 +	} 
   1.753 +	reposition();
   1.754 +}
   1.755 +
   1.756  void VymModel::sendSelection()
   1.757  {
   1.758  	if (netstate!=Server) return;
   1.759 @@ -5269,3 +5290,8 @@
   1.760  	return s;
   1.761  }
   1.762  
   1.763 +QString VymModel::getSelectString (BranchItem *bi) 
   1.764 +{
   1.765 +	return getSelectString ((TreeItem*)bi);
   1.766 +}
   1.767 +