vymmodel.cpp
changeset 721 12958f987bcf
parent 696 0c2d74acf035
child 722 462d39502273
     1.1 --- a/vymmodel.cpp	Wed Jul 16 10:44:44 2008 +0000
     1.2 +++ b/vymmodel.cpp	Wed Jul 16 10:46:14 2008 +0000
     1.3 @@ -1,32 +1,122 @@
     1.4  #include <QApplication>
     1.5  #include <typeinfo>
     1.6  
     1.7 +#include "vymmodel.h"
     1.8 +
     1.9 +#include "editxlinkdialog.h"
    1.10 +#include "exports.h"
    1.11 +#include "exportxhtmldialog.h"
    1.12 +#include "file.h"
    1.13  #include "geometry.h"		// for addBBox
    1.14 -#include "vymmodel.h"
    1.15 -
    1.16 -
    1.17 +#include "mainwindow.h"
    1.18 +#include "mapcenterobj.h"
    1.19 +#include "misc.h"
    1.20 +#include "parser.h"
    1.21 +#include "selection.h"
    1.22 +
    1.23 +
    1.24 +#include "warningdialog.h"
    1.25 +#include "xml-freemind.h"
    1.26 +#include "xml-vym.h"
    1.27 +
    1.28 +
    1.29 +extern bool debug;
    1.30 +extern Main *mainWindow;
    1.31  extern Settings settings;
    1.32 +extern QString tmpVymDir;
    1.33 +
    1.34 +extern TextEditor *textEditor;
    1.35 +
    1.36 +
    1.37 +extern QString clipboardDir;
    1.38 +extern QString clipboardFile;
    1.39 +extern bool clipboardEmpty;
    1.40 +
    1.41 +extern ImageIO imageIO;
    1.42 +
    1.43 +extern QString vymName;
    1.44 +extern QString vymVersion;
    1.45 +extern QDir vymBaseDir;
    1.46 +
    1.47 +extern QDir lastImageDir;
    1.48 +extern QDir lastFileDir;
    1.49 +
    1.50 +extern FlagRowObj *standardFlagsDefault;
    1.51 +
    1.52 +extern Settings settings;
    1.53 +
    1.54 +
    1.55 +
    1.56 +int VymModel::mapNum=0;	// make instance
    1.57  
    1.58  VymModel::VymModel() 
    1.59  {
    1.60  //    cout << "Const VymModel\n";
    1.61 +	init();
    1.62  }
    1.63  
    1.64  
    1.65  VymModel::~VymModel() 
    1.66  {
    1.67  //    cout << "Destr VymModel\n";
    1.68 +	autosaveTimer->stop();
    1.69 +	fileChangedTimer->stop();
    1.70 +	clear();
    1.71  }	
    1.72  
    1.73  void VymModel::clear() 
    1.74  {
    1.75 +	selection.clear();
    1.76 +
    1.77  	while (!mapCenters.isEmpty())
    1.78  		delete mapCenters.takeFirst();
    1.79  }
    1.80  
    1.81  void VymModel::init () 
    1.82  {
    1.83 -	addMapCenter();
    1.84 +	// We should have at least one map center to start with
    1.85 +	// addMapCenter();  FIXME create this in MapEditor as long as model is part of that
    1.86 +
    1.87 +	// History 
    1.88 +	mapNum++;
    1.89 +    mapChanged=false;
    1.90 +	mapDefault=true;
    1.91 +	mapUnsaved=false;
    1.92 +
    1.93 +	curStep=0;
    1.94 +	redosAvail=0;
    1.95 +	undosAvail=0;
    1.96 +
    1.97 + 	stepsTotal=settings.readNumEntry("/history/stepsTotal",100);
    1.98 +	undoSet.setEntry ("/history/stepsTotal",QString::number(stepsTotal));
    1.99 +	mainWindow->updateHistory (undoSet);
   1.100 +
   1.101 +	// Create tmp dirs
   1.102 +	makeTmpDirectories();
   1.103 +	
   1.104 +	// Files
   1.105 +	zipped=true;
   1.106 +	filePath="";
   1.107 +	fileName=tr("unnamed");
   1.108 +	mapName="";
   1.109 +	blockReposition=false;
   1.110 +	blockSaveState=false;
   1.111 +
   1.112 +	autosaveTimer=new QTimer (this);
   1.113 +	connect(autosaveTimer, SIGNAL(timeout()), this, SLOT(autosave()));
   1.114 +
   1.115 +	fileChangedTimer=new QTimer (this);
   1.116 +	fileChangedTimer->start(3000);
   1.117 +	connect(fileChangedTimer, SIGNAL(timeout()), this, SLOT(fileChanged()));
   1.118 +
   1.119 +
   1.120 +	// selections
   1.121 +	selection.setModel (this);
   1.122 +	selection.unselect();
   1.123 +
   1.124 +	// find routine
   1.125 +	itFind=NULL;				
   1.126 +	EOFind=false;
   1.127  
   1.128  	// animations
   1.129  	animationUse=settings.readBoolEntry("/animation/use",false);
   1.130 @@ -36,8 +126,36 @@
   1.131  	animationTimer=new QTimer (this);
   1.132  	connect(animationTimer, SIGNAL(timeout()), this, SLOT(animate()));
   1.133  
   1.134 +	// View - map
   1.135 +	defLinkColor=QColor (0,0,255);
   1.136 +	defXLinkColor=QColor (180,180,180);
   1.137 +	linkcolorhint=LinkableMapObj::DefaultColor;
   1.138 +	linkstyle=LinkableMapObj::PolyParabel;
   1.139 +	defXLinkWidth=1;
   1.140 +	defXLinkColor=QColor (230,230,230);
   1.141 +
   1.142 +	hidemode=HideNone;
   1.143 +
   1.144 +
   1.145 +
   1.146 +	// Network
   1.147 +	netstate=Offline;
   1.148 +
   1.149 +	// Create MapCenter
   1.150 +	//  addMapCenter();  FIXME create this in MapEditor until BO and MCO are independent of scene
   1.151 +
   1.152  }
   1.153  
   1.154 +void VymModel::makeTmpDirectories()
   1.155 +{
   1.156 +	// Create unique temporary directories
   1.157 +	tmpMapDir = tmpVymDir+QString("/model-%1").arg(mapNum);
   1.158 +	histPath = tmpMapDir+"/history";
   1.159 +	QDir d;
   1.160 +	d.mkdir (tmpMapDir);
   1.161 +}
   1.162 +
   1.163 +
   1.164  void VymModel::setMapEditor(MapEditor *me)
   1.165  {
   1.166  	mapEditor=me;
   1.167 @@ -50,76 +168,1183 @@
   1.168  	return mapEditor;
   1.169  }
   1.170  
   1.171 -void VymModel::setVersion (const QString &s)
   1.172 +bool VymModel::isRepositionBlocked()
   1.173  {
   1.174 -	version=s;
   1.175 +	return blockReposition;
   1.176  }
   1.177  
   1.178 -void VymModel::setAuthor (const QString &s)
   1.179 +void VymModel::updateActions()	// FIXME  maybe don't update if blockReposition is set
   1.180  {
   1.181 -	author=s;
   1.182 +	// Tell mainwindow to update states of actions
   1.183 +	mainWindow->updateActions();
   1.184  }
   1.185  
   1.186 -QString VymModel::getAuthor()
   1.187 +
   1.188 +
   1.189 +QString VymModel::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPointF &offset, LinkableMapObj *saveSel)
   1.190  {
   1.191 -	return author;
   1.192 +	// tmpdir		temporary directory to which data will be written
   1.193 +	// prefix		mapname, which will be appended to images etc.
   1.194 +	// writeflags	Only write flags for "real" save of map, not undo
   1.195 +	// offset		offset of bbox of whole map in scene. 
   1.196 +	//				Needed for XML export
   1.197 +	
   1.198 +	// Save Header
   1.199 +	QString ls;
   1.200 +	switch (linkstyle)
   1.201 +	{
   1.202 +		case LinkableMapObj::Line: 
   1.203 +			ls="StyleLine";
   1.204 +			break;
   1.205 +		case LinkableMapObj::Parabel:
   1.206 +			ls="StyleParabel";
   1.207 +			break;
   1.208 +		case LinkableMapObj::PolyLine:	
   1.209 +			ls="StylePolyLine";
   1.210 +			break;
   1.211 +		default:
   1.212 +			ls="StylePolyParabel";
   1.213 +			break;
   1.214 +	}	
   1.215 +
   1.216 +	QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
   1.217 +	QString colhint="";
   1.218 +	if (linkcolorhint==LinkableMapObj::HeadingColor) 
   1.219 +		colhint=attribut("linkColorHint","HeadingColor");
   1.220 +
   1.221 +	QString mapAttr=attribut("version",vymVersion);
   1.222 +	if (!saveSel)
   1.223 +		mapAttr+= attribut("author",author) +
   1.224 +				  attribut("comment",comment) +
   1.225 +			      attribut("date",getDate()) +
   1.226 +		          attribut("backgroundColor", mapScene->backgroundBrush().color().name() ) +
   1.227 +		          attribut("selectionColor", selection.getColor().name() ) +
   1.228 +		          attribut("linkStyle", ls ) +
   1.229 +		          attribut("linkColor", defLinkColor.name() ) +
   1.230 +		          attribut("defXLinkColor", defXLinkColor.name() ) +
   1.231 +		          attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
   1.232 +		          colhint; 
   1.233 +	s+=beginElement("vymmap",mapAttr);
   1.234 +	incIndent();
   1.235 +
   1.236 +	// Find the used flags while traversing the tree
   1.237 +	standardFlagsDefault->resetUsedCounter();
   1.238 +	
   1.239 +	// Reset the counters before saving
   1.240 +	// TODO constr. of FIO creates lots of objects, better do this in some other way...
   1.241 +	FloatImageObj (mapScene).resetSaveCounter();
   1.242 +
   1.243 +	// Build xml recursivly
   1.244 +	if (!saveSel || typeid (*saveSel) == typeid (MapCenterObj))
   1.245 +		// Save complete map, if saveSel not set
   1.246 +		s+=saveToDir(tmpdir,prefix,writeflags,offset);
   1.247 +	else
   1.248 +	{
   1.249 +		if ( typeid(*saveSel) == typeid(BranchObj) )
   1.250 +			// Save Subtree
   1.251 +			s+=((BranchObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
   1.252 +		else if ( typeid(*saveSel) == typeid(FloatImageObj) )
   1.253 +			// Save image
   1.254 +			s+=((FloatImageObj*)(saveSel))->saveToDir(tmpdir,prefix);
   1.255 +	}
   1.256 +
   1.257 +	// Save local settings
   1.258 +	s+=settings.getDataXML (destPath);
   1.259 +
   1.260 +	// Save selection
   1.261 +	if (!selection.isEmpty() && !saveSel ) 
   1.262 +		s+=valueElement("select",selection.getSelectString());
   1.263 +
   1.264 +	decIndent();
   1.265 +	s+=endElement("vymmap");
   1.266 +
   1.267 +	if (writeflags)
   1.268 +		standardFlagsDefault->saveToDir (tmpdir+"/flags/","",writeflags);
   1.269 +	return s;
   1.270  }
   1.271  
   1.272 -void VymModel::setComment (const QString &s)
   1.273 +void VymModel::setFilePath(QString fpath, QString destname)
   1.274  {
   1.275 -	comment=s;
   1.276 +	if (fpath.isEmpty() || fpath=="")
   1.277 +	{
   1.278 +		filePath="";
   1.279 +		fileName="";
   1.280 +		destPath="";
   1.281 +	} else
   1.282 +	{
   1.283 +		filePath=fpath;		// becomes absolute path
   1.284 +		fileName=fpath;		// gets stripped of path
   1.285 +		destPath=destname;	// needed for vymlinks and during load to reset fileChangedTime
   1.286 +
   1.287 +		// If fpath is not an absolute path, complete it
   1.288 +		filePath=QDir(fpath).absPath();
   1.289 +		fileDir=filePath.left (1+filePath.findRev ("/"));
   1.290 +
   1.291 +		// Set short name, too. Search from behind:
   1.292 +		int i=fileName.findRev("/");
   1.293 +		if (i>=0) fileName=fileName.remove (0,i+1);
   1.294 +
   1.295 +		// Forget the .vym (or .xml) for name of map
   1.296 +		mapName=fileName.left(fileName.findRev(".",-1,true) );
   1.297 +	}
   1.298  }
   1.299  
   1.300 -QString VymModel::getComment ()
   1.301 +void VymModel::setFilePath(QString fpath)
   1.302  {
   1.303 -	return comment;
   1.304 +	setFilePath (fpath,fpath);
   1.305  }
   1.306  
   1.307 -QString VymModel::getDate ()
   1.308 +QString VymModel::getFilePath()
   1.309  {
   1.310 -	return QDate::currentDate().toString ("yyyy-MM-dd");
   1.311 +	return filePath;
   1.312  }
   1.313  
   1.314 -void VymModel::setScene (QGraphicsScene *s)
   1.315 +QString VymModel::getFileName()
   1.316  {
   1.317 -	mapScene=s;
   1.318 -    init();	// Here we have a mapScene set, 
   1.319 -			// which is (still) needed to create MapCenters
   1.320 +	return fileName;
   1.321  }
   1.322  
   1.323 +QString VymModel::getMapName()
   1.324 +{
   1.325 +	return mapName;
   1.326 +}
   1.327 +
   1.328 +QString VymModel::getDestPath()
   1.329 +{
   1.330 +	return destPath;
   1.331 +}
   1.332 +
   1.333 +ErrorCode VymModel::load (QString fname, const LoadMode &lmode, const FileType &ftype)
   1.334 +{
   1.335 +	ErrorCode err=success;
   1.336 +
   1.337 +	parseBaseHandler *handler;
   1.338 +	fileType=ftype;
   1.339 +	switch (fileType)
   1.340 +	{
   1.341 +		case VymMap: handler=new parseVYMHandler; break;
   1.342 +		case FreemindMap : handler=new parseFreemindHandler; break;
   1.343 +		default: 
   1.344 +			QMessageBox::critical( 0, tr( "Critical Parse Error" ),
   1.345 +				   "Unknown FileType in VymModel::load()");
   1.346 +		return aborted;	
   1.347 +	}
   1.348 +	if (lmode==NewMap)
   1.349 +	{
   1.350 +		selection.clear();
   1.351 +		// FIXME not needed??? model->setMapEditor(this);
   1.352 +		// (map state is set later at end of load...)
   1.353 +	} else
   1.354 +	{
   1.355 +		BranchObj *bo=selection.getBranch();
   1.356 +		if (!bo) return aborted;
   1.357 +		if (lmode==ImportAdd)
   1.358 +			saveStateChangingPart(
   1.359 +				bo,
   1.360 +				bo,
   1.361 +				QString("addMapInsert (%1)").arg(fname),
   1.362 +				QString("Add map %1 to %2").arg(fname).arg(getObjectName(bo)));
   1.363 +		else	
   1.364 +			saveStateChangingPart(
   1.365 +				bo,
   1.366 +				bo,
   1.367 +				QString("addMapReplace(%1)").arg(fname),
   1.368 +				QString("Add map %1 to %2").arg(fname).arg(getObjectName(bo)));
   1.369 +	}	
   1.370 +    
   1.371 +
   1.372 +	// Create temporary directory for packing
   1.373 +	bool ok;
   1.374 +	QString tmpZipDir=makeTmpDir (ok,"vym-pack");
   1.375 +	if (!ok)
   1.376 +	{
   1.377 +		QMessageBox::critical( 0, tr( "Critical Load Error" ),
   1.378 +		   tr("Couldn't create temporary directory before load\n"));
   1.379 +		return aborted; 
   1.380 +	}
   1.381 +
   1.382 +	// Try to unzip file
   1.383 +	err=unzipDir (tmpZipDir,fname);
   1.384 +	QString xmlfile;
   1.385 +	if (err==nozip)
   1.386 +	{
   1.387 +		xmlfile=fname;
   1.388 +		zipped=false;
   1.389 +	} else
   1.390 +	{
   1.391 +		zipped=true;
   1.392 +		
   1.393 +		// Look for mapname.xml
   1.394 +		xmlfile= fname.left(fname.findRev(".",-1,true));
   1.395 +		xmlfile=xmlfile.section( '/', -1 );
   1.396 +		QFile mfile( tmpZipDir + "/" + xmlfile + ".xml");
   1.397 +		if (!mfile.exists() )
   1.398 +		{
   1.399 +			// mapname.xml does not exist, well, 
   1.400 +			// maybe someone renamed the mapname.vym file...
   1.401 +			// Try to find any .xml in the toplevel 
   1.402 +			// directory of the .vym file
   1.403 +			QStringList flist=QDir (tmpZipDir).entryList("*.xml");
   1.404 +			if (flist.count()==1) 
   1.405 +			{
   1.406 +				// Only one entry, take this one
   1.407 +				xmlfile=tmpZipDir + "/"+flist.first();
   1.408 +			} else
   1.409 +			{
   1.410 +				for ( QStringList::Iterator it = flist.begin(); it != flist.end(); ++it ) 
   1.411 +					*it=tmpZipDir + "/" + *it;
   1.412 +				// TODO Multiple entries, load all (but only the first one into this ME)
   1.413 +				//mainWindow->fileLoadFromTmp (flist);
   1.414 +				//returnCode=1;	// Silently forget this attempt to load
   1.415 +				qWarning ("MainWindow::load (fn)  multimap found...");
   1.416 +			}	
   1.417 +				
   1.418 +			if (flist.isEmpty() )
   1.419 +			{
   1.420 +				QMessageBox::critical( 0, tr( "Critical Load Error" ),
   1.421 +						   tr("Couldn't find a map (*.xml) in .vym archive.\n"));
   1.422 +				err=aborted;				   
   1.423 +			}	
   1.424 +		} //file doesn't exist	
   1.425 +		else
   1.426 +			xmlfile=mfile.name();
   1.427 +	}
   1.428 +
   1.429 +	QFile file( xmlfile);
   1.430 +
   1.431 +	// I am paranoid: file should exist anyway
   1.432 +	// according to check in mainwindow.
   1.433 +	if (!file.exists() )
   1.434 +	{
   1.435 +		QMessageBox::critical( 0, tr( "Critical Parse Error" ),
   1.436 +				   tr(QString("Couldn't open map %1").arg(file.name())));
   1.437 +		err=aborted;	
   1.438 +	} else
   1.439 +	{
   1.440 +		bool blockSaveStateOrg=blockSaveState;
   1.441 +		blockReposition=true;
   1.442 +		blockSaveState=true;
   1.443 +		QXmlInputSource source( file);
   1.444 +		QXmlSimpleReader reader;
   1.445 +		reader.setContentHandler( handler );
   1.446 +		reader.setErrorHandler( handler );
   1.447 +		handler->setModel ( this);
   1.448 +
   1.449 +
   1.450 +		// We need to set the tmpDir in order  to load files with rel. path
   1.451 +		QString tmpdir;
   1.452 +		if (zipped)
   1.453 +			tmpdir=tmpZipDir;
   1.454 +		else
   1.455 +			tmpdir=fname.left(fname.findRev("/",-1));	
   1.456 +		handler->setTmpDir (tmpdir);
   1.457 +		handler->setInputFile (file.name());
   1.458 +		handler->setLoadMode (lmode);
   1.459 +		bool ok = reader.parse( source );
   1.460 +		blockReposition=false;
   1.461 +		blockSaveState=blockSaveStateOrg;
   1.462 +		file.close();
   1.463 +		if ( ok ) 
   1.464 +		{
   1.465 +			reposition();	// FIXME reposition the view instead...
   1.466 +			selection.update();
   1.467 +			if (lmode==NewMap)
   1.468 +			{
   1.469 +				mapDefault=false;
   1.470 +				mapChanged=false;
   1.471 +				mapUnsaved=false;
   1.472 +				autosaveTimer->stop();
   1.473 +			}
   1.474 +
   1.475 +			// Reset timestamp to check for later updates of file
   1.476 +			fileChangedTime=QFileInfo (destPath).lastModified();
   1.477 +		} else 
   1.478 +		{
   1.479 +			QMessageBox::critical( 0, tr( "Critical Parse Error" ),
   1.480 +					   tr( handler->errorProtocol() ) );
   1.481 +			// returnCode=1;	
   1.482 +			// Still return "success": the map maybe at least
   1.483 +			// partially read by the parser
   1.484 +		}	
   1.485 +	}	
   1.486 +
   1.487 +	// Delete tmpZipDir
   1.488 +	removeDir (QDir(tmpZipDir));
   1.489 +
   1.490 +	updateActions();
   1.491 +
   1.492 +	return err;
   1.493 +}
   1.494 +
   1.495 +ErrorCode VymModel::save (const SaveMode &savemode)
   1.496 +{
   1.497 +	QString tmpZipDir;
   1.498 +	QString mapFileName;
   1.499 +	QString safeFilePath;
   1.500 +
   1.501 +	ErrorCode err=success;
   1.502 +
   1.503 +	if (zipped)
   1.504 +		// save as .xml
   1.505 +		mapFileName=mapName+".xml";
   1.506 +	else
   1.507 +		// use name given by user, even if he chooses .doc
   1.508 +		mapFileName=fileName;
   1.509 +
   1.510 +	// Look, if we should zip the data:
   1.511 +	if (!zipped)
   1.512 +	{
   1.513 +		QMessageBox mb( vymName,
   1.514 +			tr("The map %1\ndid not use the compressed "
   1.515 +			"vym file format.\nWriting it uncompressed will also write images \n"
   1.516 +			"and flags and thus may overwrite files in the "
   1.517 +			"given directory\n\nDo you want to write the map").arg(filePath),
   1.518 +			QMessageBox::Warning,
   1.519 +			QMessageBox::Yes | QMessageBox::Default,
   1.520 +			QMessageBox::No ,
   1.521 +			QMessageBox::Cancel | QMessageBox::Escape);
   1.522 +		mb.setButtonText( QMessageBox::Yes, tr("compressed (vym default)") );
   1.523 +		mb.setButtonText( QMessageBox::No, tr("uncompressed") );
   1.524 +		mb.setButtonText( QMessageBox::Cancel, tr("Cancel"));
   1.525 +		switch( mb.exec() ) 
   1.526 +		{
   1.527 +			case QMessageBox::Yes:
   1.528 +				// save compressed (default file format)
   1.529 +				zipped=true;
   1.530 +				break;
   1.531 +			case QMessageBox::No:
   1.532 +				// save uncompressed
   1.533 +				zipped=false;
   1.534 +				break;
   1.535 +			case QMessageBox::Cancel:
   1.536 +				// do nothing
   1.537 +				return aborted;
   1.538 +				break;
   1.539 +		}
   1.540 +	}
   1.541 +
   1.542 +	// First backup existing file, we 
   1.543 +	// don't want to add to old zip archives
   1.544 +	QFile f(destPath);
   1.545 +	if (f.exists())
   1.546 +	{
   1.547 +		if ( settings.value ("/mapeditor/writeBackupFile").toBool())
   1.548 +		{
   1.549 +			QString backupFileName(destPath + "~");
   1.550 +			QFile backupFile(backupFileName);
   1.551 +			if (backupFile.exists() && !backupFile.remove())
   1.552 +			{
   1.553 +				QMessageBox::warning(0, tr("Save Error"),
   1.554 +									 tr("%1\ncould not be removed before saving").arg(backupFileName));
   1.555 +			}
   1.556 +			else if (!f.rename(backupFileName))
   1.557 +			{
   1.558 +				QMessageBox::warning(0, tr("Save Error"),
   1.559 +									 tr("%1\ncould not be renamed before saving").arg(destPath));
   1.560 +			}
   1.561 +		}
   1.562 +	}
   1.563 +
   1.564 +	if (zipped)
   1.565 +	{
   1.566 +		// Create temporary directory for packing
   1.567 +		bool ok;
   1.568 +		tmpZipDir=makeTmpDir (ok,"vym-zip");
   1.569 +		if (!ok)
   1.570 +		{
   1.571 +			QMessageBox::critical( 0, tr( "Critical Load Error" ),
   1.572 +			   tr("Couldn't create temporary directory before save\n"));
   1.573 +			return aborted; 
   1.574 +		}
   1.575 +
   1.576 +		safeFilePath=filePath;
   1.577 +		setFilePath (tmpZipDir+"/"+ mapName+ ".xml", safeFilePath);
   1.578 +	} // zipped
   1.579 +
   1.580 +	// Create mapName and fileDir
   1.581 +	makeSubDirs (fileDir);
   1.582 +
   1.583 +	QString saveFile;
   1.584 +	if (savemode==CompleteMap || selection.isEmpty())
   1.585 +	{
   1.586 +		// Save complete map
   1.587 +		saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),NULL);
   1.588 +		mapChanged=false;
   1.589 +		mapUnsaved=false;
   1.590 +		autosaveTimer->stop();
   1.591 +	}
   1.592 +	else	
   1.593 +	{
   1.594 +		// Save part of map
   1.595 +		if (selection.type()==Selection::FloatImage)
   1.596 +			saveFloatImage();
   1.597 +		else	
   1.598 +			saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),selection.getBranch());	
   1.599 +		// TODO take care of multiselections
   1.600 +	}	
   1.601 +
   1.602 +	if (!saveStringToDisk(fileDir+mapFileName,saveFile))
   1.603 +	{
   1.604 +		err=aborted;
   1.605 +		qWarning ("ME::saveStringToDisk failed!");
   1.606 +	}
   1.607 +
   1.608 +	if (zipped)
   1.609 +	{
   1.610 +		// zip
   1.611 +		if (err==success) err=zipDir (tmpZipDir,destPath);
   1.612 +
   1.613 +		// Delete tmpDir
   1.614 +		removeDir (QDir(tmpZipDir));
   1.615 +
   1.616 +		// Restore original filepath outside of tmp zip dir
   1.617 +		setFilePath (safeFilePath);
   1.618 +	}
   1.619 +
   1.620 +	updateActions();
   1.621 +	fileChangedTime=QFileInfo (destPath).lastModified();
   1.622 +	return err;
   1.623 +}
   1.624 +
   1.625 +void VymModel::addMapReplaceInt(const QString &undoSel, const QString &path)
   1.626 +{
   1.627 +	QString pathDir=path.left(path.findRev("/"));
   1.628 +	QDir d(pathDir);
   1.629 +	QFile file (path);
   1.630 +
   1.631 +	if (d.exists() )
   1.632 +	{
   1.633 +		// We need to parse saved XML data
   1.634 +		parseVYMHandler handler;
   1.635 +		QXmlInputSource source( file);
   1.636 +		QXmlSimpleReader reader;
   1.637 +		reader.setContentHandler( &handler );
   1.638 +		reader.setErrorHandler( &handler );
   1.639 +		handler.setModel ( this);
   1.640 +		handler.setTmpDir ( pathDir );	// needed to load files with rel. path
   1.641 +		if (undoSel.isEmpty())
   1.642 +		{
   1.643 +			unselect();
   1.644 +			clear();
   1.645 +			handler.setLoadMode (NewMap);
   1.646 +		} else	
   1.647 +		{
   1.648 +			select (undoSel);
   1.649 +			handler.setLoadMode (ImportReplace);
   1.650 +		}	
   1.651 +		blockReposition=true;
   1.652 +		bool ok = reader.parse( source );
   1.653 +		blockReposition=false;
   1.654 +		if (! ok ) 
   1.655 +		{	
   1.656 +			// This should never ever happen
   1.657 +			QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
   1.658 +								    handler.errorProtocol());
   1.659 +		}
   1.660 +	} else	
   1.661 +		QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
   1.662 +}
   1.663 +
   1.664 +void VymModel::addMapInsertInt (const QString &path, int pos)
   1.665 +{
   1.666 +	BranchObj *sel=selection.getBranch();
   1.667 +	if (sel)
   1.668 +	{
   1.669 +		QString pathDir=path.left(path.findRev("/"));
   1.670 +		QDir d(pathDir);
   1.671 +		QFile file (path);
   1.672 +
   1.673 +		if (d.exists() )
   1.674 +		{
   1.675 +			// We need to parse saved XML data
   1.676 +			parseVYMHandler handler;
   1.677 +			QXmlInputSource source( file);
   1.678 +			QXmlSimpleReader reader;
   1.679 +			reader.setContentHandler( &handler );
   1.680 +			reader.setErrorHandler( &handler );
   1.681 +			handler.setModel (this);
   1.682 +			handler.setTmpDir ( pathDir );	// needed to load files with rel. path
   1.683 +			handler.setLoadMode (ImportAdd);
   1.684 +			blockReposition=true;
   1.685 +			bool ok = reader.parse( source );
   1.686 +			blockReposition=false;
   1.687 +			if (! ok ) 
   1.688 +			{	
   1.689 +				// This should never ever happen
   1.690 +				QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
   1.691 +										handler.errorProtocol());
   1.692 +			}
   1.693 +			if (sel->getDepth()>0)
   1.694 +				sel->getLastBranch()->linkTo (sel,pos);
   1.695 +		} else	
   1.696 +			QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
   1.697 +	}		
   1.698 +}
   1.699 +
   1.700 +FloatImageObj* VymModel::loadFloatImageInt (QString fn)
   1.701 +{
   1.702 +	BranchObj *bo=selection.getBranch();
   1.703 +	if (bo)
   1.704 +	{
   1.705 +		FloatImageObj *fio;
   1.706 +		bo->addFloatImage();
   1.707 +		fio=bo->getLastFloatImage();
   1.708 +		fio->load(fn);
   1.709 +		reposition();
   1.710 +		// FIXME needed? scene()->update();
   1.711 +		return fio;
   1.712 +	}
   1.713 +	return NULL;
   1.714 +}	
   1.715 +
   1.716 +void VymModel::loadFloatImage ()
   1.717 +{
   1.718 +	BranchObj *bo=selection.getBranch();
   1.719 +	if (bo)
   1.720 +	{
   1.721 +
   1.722 +		Q3FileDialog *fd=new Q3FileDialog( NULL);
   1.723 +		fd->setMode (Q3FileDialog::ExistingFiles);
   1.724 +		fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
   1.725 +		ImagePreview *p =new ImagePreview (fd);
   1.726 +		fd->setContentsPreviewEnabled( TRUE );
   1.727 +		fd->setContentsPreview( p, p );
   1.728 +		fd->setPreviewMode( Q3FileDialog::Contents );
   1.729 +		fd->setCaption(vymName+" - " +tr("Load image"));
   1.730 +		fd->setDir (lastImageDir);
   1.731 +		fd->show();
   1.732 +
   1.733 +		if ( fd->exec() == QDialog::Accepted )
   1.734 +		{
   1.735 +			// TODO loadFIO in QT4 use:	lastImageDir=fd->directory();
   1.736 +			lastImageDir=QDir (fd->dirPath());
   1.737 +			QString s;
   1.738 +			FloatImageObj *fio;
   1.739 +			for (int j=0; j<fd->selectedFiles().count(); j++)
   1.740 +			{
   1.741 +				s=fd->selectedFiles().at(j);
   1.742 +				fio=loadFloatImageInt (s);
   1.743 +				if (fio)
   1.744 +					saveState(
   1.745 +						(LinkableMapObj*)fio,
   1.746 +						"delete ()",
   1.747 +						bo, 
   1.748 +						QString ("loadImage (%1)").arg(s ),
   1.749 +						QString("Add image %1 to %2").arg(s).arg(getObjectName(bo))
   1.750 +					);
   1.751 +				else
   1.752 +					// TODO loadFIO error handling
   1.753 +					qWarning ("Failed to load "+s);
   1.754 +			}
   1.755 +		}
   1.756 +		delete (p);
   1.757 +		delete (fd);
   1.758 +	}
   1.759 +}
   1.760 +
   1.761 +void VymModel::saveFloatImageInt  (FloatImageObj *fio, const QString &type, const QString &fn)
   1.762 +{
   1.763 +	fio->save (fn,type);
   1.764 +}
   1.765 +
   1.766 +void VymModel::saveFloatImage ()
   1.767 +{
   1.768 +	FloatImageObj *fio=selection.getFloatImage();
   1.769 +	if (fio)
   1.770 +	{
   1.771 +		QFileDialog *fd=new QFileDialog( NULL);
   1.772 +		fd->setFilters (imageIO.getFilters());
   1.773 +		fd->setCaption(vymName+" - " +tr("Save image"));
   1.774 +		fd->setFileMode( QFileDialog::AnyFile );
   1.775 +		fd->setDirectory (lastImageDir);
   1.776 +//		fd->setSelection (fio->getOriginalFilename());
   1.777 +		fd->show();
   1.778 +
   1.779 +		QString fn;
   1.780 +		if ( fd->exec() == QDialog::Accepted && fd->selectedFiles().count()==1)
   1.781 +		{
   1.782 +			fn=fd->selectedFiles().at(0);
   1.783 +			if (QFile (fn).exists() )
   1.784 +			{
   1.785 +				QMessageBox mb( vymName,
   1.786 +					tr("The file %1 exists already.\n"
   1.787 +					"Do you want to overwrite it?").arg(fn),
   1.788 +				QMessageBox::Warning,
   1.789 +				QMessageBox::Yes | QMessageBox::Default,
   1.790 +				QMessageBox::Cancel | QMessageBox::Escape,
   1.791 +				QMessageBox::NoButton );
   1.792 +
   1.793 +				mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
   1.794 +				mb.setButtonText( QMessageBox::No, tr("Cancel"));
   1.795 +				switch( mb.exec() ) 
   1.796 +				{
   1.797 +					case QMessageBox::Yes:
   1.798 +						// save 
   1.799 +						break;
   1.800 +					case QMessageBox::Cancel:
   1.801 +						// do nothing
   1.802 +						delete (fd);
   1.803 +						return;
   1.804 +						break;
   1.805 +				}
   1.806 +			}
   1.807 +			saveFloatImageInt (fio,fd->selectedFilter(),fn );
   1.808 +		}
   1.809 +		delete (fd);
   1.810 +	}
   1.811 +}
   1.812 +
   1.813 +
   1.814 +void VymModel::importDirInt(BranchObj *dst, QDir d)
   1.815 +{
   1.816 +	BranchObj *bo=selection.getBranch();
   1.817 +	if (bo)
   1.818 +	{
   1.819 +		// Traverse directories
   1.820 +		d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
   1.821 +		QFileInfoList list = d.entryInfoList();
   1.822 +		QFileInfo fi;
   1.823 +
   1.824 +		for (int i = 0; i < list.size(); ++i) 
   1.825 +		{
   1.826 +			fi=list.at(i);
   1.827 +			if (fi.fileName() != "." && fi.fileName() != ".." )
   1.828 +			{
   1.829 +				dst->addBranch();
   1.830 +				bo=dst->getLastBranch();
   1.831 +				bo->setHeading (fi.fileName() );
   1.832 +				bo->setColor (QColor("blue"));
   1.833 +				bo->toggleScroll();
   1.834 +				if ( !d.cd(fi.fileName()) ) 
   1.835 +					QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
   1.836 +				else 
   1.837 +				{
   1.838 +					// Recursively add subdirs
   1.839 +					importDirInt (bo,d);
   1.840 +					d.cdUp();
   1.841 +				}
   1.842 +			}	
   1.843 +		}		
   1.844 +		// Traverse files
   1.845 +		d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
   1.846 +		list = d.entryInfoList();
   1.847 +
   1.848 +		for (int i = 0; i < list.size(); ++i) 
   1.849 +		{
   1.850 +			fi=list.at(i);
   1.851 +			dst->addBranch();
   1.852 +			bo=dst->getLastBranch();
   1.853 +			bo->setHeading (fi.fileName() );
   1.854 +			bo->setColor (QColor("black"));
   1.855 +			if (fi.fileName().right(4) == ".vym" )
   1.856 +				bo->setVymLink (fi.filePath());
   1.857 +		}	
   1.858 +	}		
   1.859 +}
   1.860 +
   1.861 +void VymModel::importDirInt (const QString &s)
   1.862 +{
   1.863 +	BranchObj *bo=selection.getBranch();
   1.864 +	if (bo)
   1.865 +	{
   1.866 +		saveStateChangingPart (bo,bo,QString ("importDir (\"%1\")").arg(s),QString("Import directory structure from %1").arg(s));
   1.867 +
   1.868 +		QDir d(s);
   1.869 +		importDirInt (bo,d);
   1.870 +	}
   1.871 +}	
   1.872 +
   1.873 +void VymModel::importDir()
   1.874 +{
   1.875 +	BranchObj *bo=selection.getBranch();
   1.876 +	if (bo)
   1.877 +	{
   1.878 +		QStringList filters;
   1.879 +		filters <<"VYM map (*.vym)";
   1.880 +		QFileDialog *fd=new QFileDialog( NULL,vymName+ " - " +tr("Choose directory structure to import"));
   1.881 +		fd->setMode (QFileDialog::DirectoryOnly);
   1.882 +		fd->setFilters (filters);
   1.883 +		fd->setCaption(vymName+" - " +tr("Choose directory structure to import"));
   1.884 +		fd->show();
   1.885 +
   1.886 +		QString fn;
   1.887 +		if ( fd->exec() == QDialog::Accepted )
   1.888 +		{
   1.889 +			importDirInt (fd->selectedFile() );
   1.890 +			reposition();
   1.891 +			//FIXME needed? scene()->update();
   1.892 +		}
   1.893 +	}	
   1.894 +}
   1.895 +
   1.896 +
   1.897 +void VymModel::autosave()
   1.898 +{
   1.899 +	QDateTime now=QDateTime().currentDateTime();
   1.900 +
   1.901 +	// Disable autosave, while we have gone back in history
   1.902 +	int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
   1.903 +	if (redosAvail>0) return;
   1.904 +
   1.905 +	// Also disable autosave for new map without filename
   1.906 +	if (filePath.isEmpty()) return;
   1.907 +
   1.908 +
   1.909 +	if (mapUnsaved &&mapChanged && settings.value ("/autosave/use",true).toBool() )
   1.910 +	{
   1.911 +		if (QFileInfo(filePath).lastModified()<=fileChangedTime) 
   1.912 +			mainWindow->fileSave (this);
   1.913 +		else
   1.914 +			if (debug)
   1.915 +				cout <<"  ME::autosave  rejected, file on disk is newer than last save.\n"; 
   1.916 +
   1.917 +	}	
   1.918 +}
   1.919 +
   1.920 +void VymModel::fileChanged()
   1.921 +{
   1.922 +	// Check if file on disk has changed meanwhile
   1.923 +	if (!filePath.isEmpty())
   1.924 +	{
   1.925 +		QDateTime tmod=QFileInfo (filePath).lastModified();
   1.926 +		if (tmod>fileChangedTime)
   1.927 +		{
   1.928 +			// FIXME switch to current mapeditor and finish lineedits...
   1.929 +			QMessageBox mb( vymName,
   1.930 +				tr("The file of the map  on disk has changed:\n\n"  
   1.931 +				   "   %1\n\nDo you want to reload that map with the new file?").arg(filePath),
   1.932 +				QMessageBox::Question,
   1.933 +				QMessageBox::Yes ,
   1.934 +				QMessageBox::Cancel | QMessageBox::Default,
   1.935 +				QMessageBox::NoButton );
   1.936 +
   1.937 +			mb.setButtonText( QMessageBox::Yes, tr("Reload"));
   1.938 +			mb.setButtonText( QMessageBox::No, tr("Ignore"));
   1.939 +			switch( mb.exec() ) 
   1.940 +			{
   1.941 +				case QMessageBox::Yes:
   1.942 +					// Reload map
   1.943 +					load (filePath,NewMap,fileType);
   1.944 +		        case QMessageBox::Cancel:
   1.945 +					fileChangedTime=tmod; // allow autosave to overwrite newer file!
   1.946 +			}
   1.947 +		}
   1.948 +	}	
   1.949 +}
   1.950 +
   1.951 +bool VymModel::isDefault()
   1.952 +{
   1.953 +    return mapDefault;
   1.954 +}
   1.955 +
   1.956 +void VymModel::makeDefault()
   1.957 +{
   1.958 +	mapChanged=false;
   1.959 +	mapDefault=true;
   1.960 +}
   1.961 +
   1.962 +bool VymModel::hasChanged()
   1.963 +{
   1.964 +    return mapChanged;
   1.965 +}
   1.966 +
   1.967 +void VymModel::setChanged()
   1.968 +{
   1.969 +	if (!mapChanged)
   1.970 +		autosaveTimer->start(settings.value("/autosave/ms/",300000).toInt());
   1.971 +	mapChanged=true;
   1.972 +	mapDefault=false;
   1.973 +	mapUnsaved=true;
   1.974 +	findReset();
   1.975 +}
   1.976 +
   1.977 +
   1.978 +QString VymModel::getObjectName (const LinkableMapObj *lmo)
   1.979 +{
   1.980 +	QString s;
   1.981 +	if (!lmo) return QString("Error: NULL has no name!");
   1.982 +
   1.983 +	if ((typeid(*lmo) == typeid(BranchObj) ||
   1.984 +				      typeid(*lmo) == typeid(MapCenterObj))) 
   1.985 +	{
   1.986 +		
   1.987 +		s=(((BranchObj*)lmo)->getHeading());
   1.988 +		if (s=="") s="unnamed";
   1.989 +		return QString("branch (%1)").arg(s);
   1.990 +	}	
   1.991 +	if ((typeid(*lmo) == typeid(FloatImageObj) ))
   1.992 +		return QString ("floatimage [%1]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
   1.993 +	return QString("Unknown type has no name!");
   1.994 +}
   1.995 +
   1.996 +void VymModel::redo()
   1.997 +{
   1.998 +	// Can we undo at all?
   1.999 +	if (redosAvail<1) return;
  1.1000 +
  1.1001 +	bool blockSaveStateOrg=blockSaveState;
  1.1002 +	blockSaveState=true;
  1.1003 +	
  1.1004 +	redosAvail--;
  1.1005 +
  1.1006 +	if (undosAvail<stepsTotal) undosAvail++;
  1.1007 +	curStep++;
  1.1008 +	if (curStep>stepsTotal) curStep=1;
  1.1009 +	QString undoCommand=  undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
  1.1010 +	QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
  1.1011 +	QString redoCommand=  undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
  1.1012 +	QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
  1.1013 +	QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
  1.1014 +	QString version=undoSet.readEntry ("/history/version");
  1.1015 +
  1.1016 +	/* TODO Maybe check for version, if we save the history
  1.1017 +	if (!checkVersion(version))
  1.1018 +		QMessageBox::warning(0,tr("Warning"),
  1.1019 +			tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
  1.1020 +	*/ 
  1.1021 +
  1.1022 +	// Find out current undo directory
  1.1023 +	QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
  1.1024 +
  1.1025 +	if (debug)
  1.1026 +	{
  1.1027 +		cout << "VymModel::redo() begin\n";
  1.1028 +		cout << "    undosAvail="<<undosAvail<<endl;
  1.1029 +		cout << "    redosAvail="<<redosAvail<<endl;
  1.1030 +		cout << "       curStep="<<curStep<<endl;
  1.1031 +		cout << "    ---------------------------"<<endl;
  1.1032 +		cout << "    comment="<<comment.toStdString()<<endl;
  1.1033 +		cout << "    undoCom="<<undoCommand.toStdString()<<endl;
  1.1034 +		cout << "    undoSel="<<undoSelection.toStdString()<<endl;
  1.1035 +		cout << "    redoCom="<<redoCommand.toStdString()<<endl;
  1.1036 +		cout << "    redoSel="<<redoSelection.toStdString()<<endl;
  1.1037 +		cout << "    ---------------------------"<<endl<<endl;
  1.1038 +	}
  1.1039 +
  1.1040 +	// select  object before redo
  1.1041 +	if (!redoSelection.isEmpty())
  1.1042 +		select (redoSelection);
  1.1043 +
  1.1044 +
  1.1045 +	parseAtom (redoCommand);
  1.1046 +	reposition();
  1.1047 +
  1.1048 +	blockSaveState=blockSaveStateOrg;
  1.1049 +
  1.1050 +	undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
  1.1051 +	undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
  1.1052 +	undoSet.setEntry ("/history/curStep",QString::number(curStep));
  1.1053 +	undoSet.writeSettings(histPath);
  1.1054 +
  1.1055 +	mainWindow->updateHistory (undoSet);
  1.1056 +	updateActions();
  1.1057 +
  1.1058 +	/* TODO remove testing
  1.1059 +	cout << "ME::redo() end\n";
  1.1060 +	cout << "    undosAvail="<<undosAvail<<endl;
  1.1061 +	cout << "    redosAvail="<<redosAvail<<endl;
  1.1062 +	cout << "       curStep="<<curStep<<endl;
  1.1063 +	cout << "    ---------------------------"<<endl<<endl;
  1.1064 +	*/
  1.1065 +
  1.1066 +
  1.1067 +}
  1.1068 +
  1.1069 +bool VymModel::isRedoAvailable()
  1.1070 +{
  1.1071 +	if (undoSet.readNumEntry("/history/redosAvail",0)>0)
  1.1072 +		return true;
  1.1073 +	else	
  1.1074 +		return false;
  1.1075 +}
  1.1076 +
  1.1077 +void VymModel::undo()
  1.1078 +{
  1.1079 +	// Can we undo at all?
  1.1080 +	if (undosAvail<1) return;
  1.1081 +
  1.1082 +	mainWindow->statusMessage (tr("Autosave disabled during undo."));
  1.1083 +
  1.1084 +	bool blockSaveStateOrg=blockSaveState;
  1.1085 +	blockSaveState=true;
  1.1086 +	
  1.1087 +	QString undoCommand=  undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
  1.1088 +	QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
  1.1089 +	QString redoCommand=  undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
  1.1090 +	QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
  1.1091 +	QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
  1.1092 +	QString version=undoSet.readEntry ("/history/version");
  1.1093 +
  1.1094 +	/* TODO Maybe check for version, if we save the history
  1.1095 +	if (!checkVersion(version))
  1.1096 +		QMessageBox::warning(0,tr("Warning"),
  1.1097 +			tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
  1.1098 +	*/
  1.1099 +
  1.1100 +	// Find out current undo directory
  1.1101 +	QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
  1.1102 +
  1.1103 +	// select  object before undo
  1.1104 +	if (!undoSelection.isEmpty())
  1.1105 +		select (undoSelection);
  1.1106 +
  1.1107 +	if (debug)
  1.1108 +	{
  1.1109 +		cout << "VymModel::undo() begin\n";
  1.1110 +		cout << "    undosAvail="<<undosAvail<<endl;
  1.1111 +		cout << "    redosAvail="<<redosAvail<<endl;
  1.1112 +		cout << "       curStep="<<curStep<<endl;
  1.1113 +		cout << "    ---------------------------"<<endl;
  1.1114 +		cout << "    comment="<<comment.toStdString()<<endl;
  1.1115 +		cout << "    undoCom="<<undoCommand.toStdString()<<endl;
  1.1116 +		cout << "    undoSel="<<undoSelection.toStdString()<<endl;
  1.1117 +		cout << "    redoCom="<<redoCommand.toStdString()<<endl;
  1.1118 +		cout << "    redoSel="<<redoSelection.toStdString()<<endl;
  1.1119 +		cout << "    ---------------------------"<<endl<<endl;
  1.1120 +	}	
  1.1121 +	parseAtom (undoCommand);
  1.1122 +	reposition();
  1.1123 +
  1.1124 +	undosAvail--;
  1.1125 +	curStep--; 
  1.1126 +	if (curStep<1) curStep=stepsTotal;
  1.1127 +
  1.1128 +	redosAvail++;
  1.1129 +
  1.1130 +	blockSaveState=blockSaveStateOrg;
  1.1131 +/* TODO remove testing
  1.1132 +	cout << "VymModel::undo() end\n";
  1.1133 +	cout << "    undosAvail="<<undosAvail<<endl;
  1.1134 +	cout << "    redosAvail="<<redosAvail<<endl;
  1.1135 +	cout << "       curStep="<<curStep<<endl;
  1.1136 +	cout << "    ---------------------------"<<endl<<endl;
  1.1137 +*/
  1.1138 +
  1.1139 +	undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
  1.1140 +	undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
  1.1141 +	undoSet.setEntry ("/history/curStep",QString::number(curStep));
  1.1142 +	undoSet.writeSettings(histPath);
  1.1143 +
  1.1144 +	mainWindow->updateHistory (undoSet);
  1.1145 +	updateActions();
  1.1146 +	selection.update();
  1.1147 +	ensureSelectionVisible();
  1.1148 +}
  1.1149 +
  1.1150 +bool VymModel::isUndoAvailable()
  1.1151 +{
  1.1152 +	if (undoSet.readNumEntry("/history/undosAvail",0)>0)
  1.1153 +		return true;
  1.1154 +	else	
  1.1155 +		return false;
  1.1156 +}
  1.1157 +
  1.1158 +void VymModel::gotoHistoryStep (int i)
  1.1159 +{
  1.1160 +	// Restore variables
  1.1161 +	int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
  1.1162 +	int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
  1.1163 +
  1.1164 +	if (i<0) i=undosAvail+redosAvail;
  1.1165 +
  1.1166 +	// Clicking above current step makes us undo things
  1.1167 +	if (i<undosAvail) 
  1.1168 +	{	
  1.1169 +		for (int j=0; j<undosAvail-i; j++) undo();
  1.1170 +		return;
  1.1171 +	}	
  1.1172 +	// Clicking below current step makes us redo things
  1.1173 +	if (i>undosAvail) 
  1.1174 +		for (int j=undosAvail; j<i; j++) 
  1.1175 +		{
  1.1176 +			if (debug) cout << "VymModel::gotoHistoryStep redo "<<j<<"/"<<undosAvail<<" i="<<i<<endl;
  1.1177 +			redo();
  1.1178 +		}
  1.1179 +
  1.1180 +	// And ignore clicking the current row ;-)	
  1.1181 +}
  1.1182 +
  1.1183 +
  1.1184 +QString VymModel::getHistoryPath()
  1.1185 +{
  1.1186 +	QString histName(QString("history-%1").arg(curStep));
  1.1187 +	return (tmpMapDir+"/"+histName);
  1.1188 +}
  1.1189 +
  1.1190 +void VymModel::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, LinkableMapObj *saveSel)
  1.1191 +{
  1.1192 +	sendData(redoCom);	//FIXME testing
  1.1193 +
  1.1194 +	// Main saveState
  1.1195 +
  1.1196 +
  1.1197 +	if (blockSaveState) return;
  1.1198 +
  1.1199 +	if (debug) cout << "ME::saveState() for  "<<qPrintable (mapName)<<endl;
  1.1200 +	
  1.1201 +	// Find out current undo directory
  1.1202 +	if (undosAvail<stepsTotal) undosAvail++;
  1.1203 +	curStep++;
  1.1204 +	if (curStep>stepsTotal) curStep=1;
  1.1205 +	
  1.1206 +	QString backupXML="";
  1.1207 +	QString histDir=getHistoryPath();
  1.1208 +	QString bakMapPath=histDir+"/map.xml";
  1.1209 +
  1.1210 +	// Create histDir if not available
  1.1211 +	QDir d(histDir);
  1.1212 +	if (!d.exists()) 
  1.1213 +		makeSubDirs (histDir);
  1.1214 +
  1.1215 +	// Save depending on how much needs to be saved	
  1.1216 +	if (saveSel)
  1.1217 +		backupXML=saveToDir (histDir,mapName+"-",false, QPointF (),saveSel);
  1.1218 +		
  1.1219 +	QString undoCommand="";
  1.1220 +	if (savemode==UndoCommand)
  1.1221 +	{
  1.1222 +		undoCommand=undoCom;
  1.1223 +	}	
  1.1224 +	else if (savemode==PartOfMap )
  1.1225 +	{
  1.1226 +		undoCommand=undoCom;
  1.1227 +		undoCommand.replace ("PATH",bakMapPath);
  1.1228 +	}
  1.1229 +
  1.1230 +	if (!backupXML.isEmpty())
  1.1231 +		// Write XML Data to disk
  1.1232 +		saveStringToDisk (bakMapPath,backupXML);
  1.1233 +
  1.1234 +	// We would have to save all actions in a tree, to keep track of 
  1.1235 +	// possible redos after a action. Possible, but we are too lazy: forget about redos.
  1.1236 +	redosAvail=0;
  1.1237 +
  1.1238 +	// Write the current state to disk
  1.1239 +	undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
  1.1240 +	undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
  1.1241 +	undoSet.setEntry ("/history/curStep",QString::number(curStep));
  1.1242 +	undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
  1.1243 +	undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
  1.1244 +	undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
  1.1245 +	undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
  1.1246 +	undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
  1.1247 +	undoSet.setEntry (QString("/history/version"),vymVersion);
  1.1248 +	undoSet.writeSettings(histPath);
  1.1249 +
  1.1250 +	if (debug)
  1.1251 +	{
  1.1252 +		// TODO remove after testing
  1.1253 +		//cout << "          into="<< histPath.toStdString()<<endl;
  1.1254 +		cout << "    stepsTotal="<<stepsTotal<<
  1.1255 +		", undosAvail="<<undosAvail<<
  1.1256 +		", redosAvail="<<redosAvail<<
  1.1257 +		", curStep="<<curStep<<endl;
  1.1258 +		cout << "    ---------------------------"<<endl;
  1.1259 +		cout << "    comment="<<comment.toStdString()<<endl;
  1.1260 +		cout << "    undoCom="<<undoCommand.toStdString()<<endl;
  1.1261 +		cout << "    undoSel="<<undoSelection.toStdString()<<endl;
  1.1262 +		cout << "    redoCom="<<redoCom.toStdString()<<endl;
  1.1263 +		cout << "    redoSel="<<redoSelection.toStdString()<<endl;
  1.1264 +		if (saveSel) cout << "    saveSel="<<qPrintable (getSelectString(saveSel))<<endl;
  1.1265 +		cout << "    ---------------------------"<<endl;
  1.1266 +	}
  1.1267 +
  1.1268 +	mainWindow->updateHistory (undoSet);
  1.1269 +	setChanged();
  1.1270 +	updateActions();
  1.1271 +}
  1.1272 +
  1.1273 +
  1.1274 +void VymModel::saveStateChangingPart(LinkableMapObj *undoSel, LinkableMapObj* redoSel, const QString &rc, const QString &comment)
  1.1275 +{
  1.1276 +	// save the selected part of the map, Undo will replace part of map 
  1.1277 +	QString undoSelection="";
  1.1278 +	if (undoSel)
  1.1279 +		undoSelection=getSelectString(undoSel);
  1.1280 +	else
  1.1281 +		qWarning ("VymModel::saveStateChangingPart  no undoSel given!");
  1.1282 +	QString redoSelection="";
  1.1283 +	if (redoSel)
  1.1284 +		redoSelection=getSelectString(undoSel);
  1.1285 +	else
  1.1286 +		qWarning ("VymModel::saveStateChangingPart  no redoSel given!");
  1.1287 +		
  1.1288 +
  1.1289 +	saveState (PartOfMap,
  1.1290 +		undoSelection, "addMapReplace (\"PATH\")",
  1.1291 +		redoSelection, rc, 
  1.1292 +		comment, 
  1.1293 +		undoSel);
  1.1294 +}
  1.1295 +
  1.1296 +void VymModel::saveStateRemovingPart(LinkableMapObj *redoSel, const QString &comment)
  1.1297 +{
  1.1298 +	if (!redoSel)
  1.1299 +	{
  1.1300 +		qWarning ("VymModel::saveStateRemovingPart  no redoSel given!");
  1.1301 +		return;
  1.1302 +	}
  1.1303 +	QString undoSelection=getSelectString (redoSel->getParObj());
  1.1304 +	QString redoSelection=getSelectString(redoSel);
  1.1305 +	if (typeid(*redoSel) == typeid(BranchObj)  ) 
  1.1306 +	{
  1.1307 +		// save the selected branch of the map, Undo will insert part of map 
  1.1308 +		saveState (PartOfMap,
  1.1309 +			undoSelection, QString("addMapInsert (\"PATH\",%1)").arg(((BranchObj*)redoSel)->getNum()),
  1.1310 +			redoSelection, "delete ()", 
  1.1311 +			comment, 
  1.1312 +			redoSel);
  1.1313 +	}
  1.1314 +}
  1.1315 +
  1.1316 +
  1.1317 +void VymModel::saveState(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment) 
  1.1318 +{
  1.1319 +	// "Normal" savestate: save commands, selections and comment
  1.1320 +	// so just save commands for undo and redo
  1.1321 +	// and use current selection
  1.1322 +
  1.1323 +	QString redoSelection="";
  1.1324 +	if (redoSel) redoSelection=getSelectString(redoSel);
  1.1325 +	QString undoSelection="";
  1.1326 +	if (undoSel) undoSelection=getSelectString(undoSel);
  1.1327 +
  1.1328 +	saveState (UndoCommand,
  1.1329 +		undoSelection, uc,
  1.1330 +		redoSelection, rc, 
  1.1331 +		comment, 
  1.1332 +		NULL);
  1.1333 +}
  1.1334 +
  1.1335 +void VymModel::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment) 
  1.1336 +{
  1.1337 +	// "Normal" savestate: save commands, selections and comment
  1.1338 +	// so just save commands for undo and redo
  1.1339 +	// and use current selection
  1.1340 +	saveState (UndoCommand,
  1.1341 +		undoSel, uc,
  1.1342 +		redoSel, rc, 
  1.1343 +		comment, 
  1.1344 +		NULL);
  1.1345 +}
  1.1346 +
  1.1347 +void VymModel::saveState(const QString &uc, const QString &rc, const QString &comment) 
  1.1348 +{
  1.1349 +	// "Normal" savestate applied to model (no selection needed): 
  1.1350 +	// save commands  and comment
  1.1351 +	saveState (UndoCommand,
  1.1352 +		NULL, uc,
  1.1353 +		NULL, rc, 
  1.1354 +		comment, 
  1.1355 +		NULL);
  1.1356 +}
  1.1357 +
  1.1358 +
  1.1359  QGraphicsScene* VymModel::getScene ()
  1.1360  {
  1.1361  	return mapScene;
  1.1362  }
  1.1363  
  1.1364 -MapCenterObj* VymModel::addMapCenter()
  1.1365 -{
  1.1366 -	return addMapCenter (QPointF(0,0));
  1.1367 -}
  1.1368 -
  1.1369 -MapCenterObj* VymModel::addMapCenter(QPointF absPos)
  1.1370 -{
  1.1371 -	MapCenterObj *mapCenter = new MapCenterObj(mapScene);
  1.1372 -	mapCenter->move (absPos);
  1.1373 -    mapCenter->setVisibility (true);
  1.1374 -	mapCenter->setHeading (QApplication::translate("Heading of mapcenter in new map", "New map"));
  1.1375 -	mapCenter->setMapEditor(mapEditor);		//FIXME needed to get defLinkStyle, mapLinkColorHint ... for later added objects
  1.1376 -	mapCenters.append(mapCenter);
  1.1377 -	return mapCenter;
  1.1378 -}
  1.1379 -
  1.1380 -MapCenterObj *VymModel::removeMapCenter(MapCenterObj* mco)
  1.1381 -{
  1.1382 -	int i=mapCenters.indexOf (mco);
  1.1383 -	if (i>=0)
  1.1384 -	{
  1.1385 -		mapCenters.removeAt (i);
  1.1386 -		delete (mco);
  1.1387 -		if (i>0) return mapCenters.at(i-1);	// Return previous MCO
  1.1388 -	}
  1.1389 -	return NULL;
  1.1390 -}
  1.1391 -
  1.1392  BranchObj* VymModel::first()
  1.1393  {
  1.1394  	if (mapCenters.count()>0) 
  1.1395 @@ -196,6 +1421,10 @@
  1.1396  	return NULL;
  1.1397  }
  1.1398  
  1.1399 +void VymModel::removeSelection()
  1.1400 +{
  1.1401 +}
  1.1402 +
  1.1403  QString VymModel::saveToDir (const QString &tmpdir,const QString &prefix, int verbose, const QPointF &offset)
  1.1404  {
  1.1405      QString s;
  1.1406 @@ -205,11 +1434,2264 @@
  1.1407      return s;
  1.1408  }
  1.1409  
  1.1410 +//////////////////////////////////////////////
  1.1411 +// Interface 
  1.1412 +//////////////////////////////////////////////
  1.1413 +void VymModel::setVersion (const QString &s)
  1.1414 +{
  1.1415 +	version=s;
  1.1416 +}
  1.1417 +
  1.1418 +void VymModel::setAuthor (const QString &s)
  1.1419 +{
  1.1420 +	saveState (
  1.1421 +		QString ("setMapAuthor (\"%1\")").arg(author),
  1.1422 +		QString ("setMapAuthor (\"%1\")").arg(s),
  1.1423 +		QString ("Set author of map to \"%1\"").arg(s)
  1.1424 +	);
  1.1425 +
  1.1426 +	author=s;
  1.1427 +}
  1.1428 +
  1.1429 +QString VymModel::getAuthor()
  1.1430 +{
  1.1431 +	return author;
  1.1432 +}
  1.1433 +
  1.1434 +void VymModel::setComment (const QString &s)
  1.1435 +{
  1.1436 +	saveState (
  1.1437 +		QString ("setMapComment (\"%1\")").arg(comment),
  1.1438 +		QString ("setMapComment (\"%1\")").arg(s),
  1.1439 +		QString ("Set comment of map")
  1.1440 +	);
  1.1441 +
  1.1442 +	comment=s;
  1.1443 +}
  1.1444 +
  1.1445 +QString VymModel::getComment ()
  1.1446 +{
  1.1447 +	return comment;
  1.1448 +}
  1.1449 +
  1.1450 +QString VymModel::getDate ()
  1.1451 +{
  1.1452 +	return QDate::currentDate().toString ("yyyy-MM-dd");
  1.1453 +}
  1.1454 +
  1.1455 +void VymModel::setHeading(const QString &s)
  1.1456 +{
  1.1457 +	BranchObj *sel=selection.getBranch();
  1.1458 +	if (sel)
  1.1459 +	{
  1.1460 +		saveState(
  1.1461 +			sel,
  1.1462 +			"setHeading (\""+sel->getHeading()+"\")", 
  1.1463 +			sel,
  1.1464 +			"setHeading (\""+s+"\")", 
  1.1465 +			QString("Set heading of %1 to \"%2\"").arg(getObjectName(sel)).arg(s) );
  1.1466 +		sel->setHeading(s );
  1.1467 +		reposition();
  1.1468 +		selection.update();
  1.1469 +		ensureSelectionVisible();
  1.1470 +	}
  1.1471 +}
  1.1472 +
  1.1473 +QString VymModel::getHeading(bool &ok, QPoint &p)
  1.1474 +{
  1.1475 +	BranchObj *bo=selection.getBranch();
  1.1476 +	if (bo)
  1.1477 +	{
  1.1478 +		ok=true;
  1.1479 +		//p=scene->mapFromScene(bo->getAbsPos());	// FIXME this is view-dependant!!!
  1.1480 +		return bo->getHeading();
  1.1481 +	}
  1.1482 +	ok=false;
  1.1483 +	return QString();
  1.1484 +}
  1.1485 +
  1.1486 +
  1.1487 +void VymModel::setHeadingInt(const QString &s)
  1.1488 +{
  1.1489 +	BranchObj *bo=selection.getBranch();
  1.1490 +	if (bo)
  1.1491 +	{
  1.1492 +		bo->setHeading(s);
  1.1493 +		reposition();
  1.1494 +		selection.update();
  1.1495 +		ensureSelectionVisible();
  1.1496 +	}
  1.1497 +}
  1.1498 +
  1.1499 +BranchObj* VymModel::findText (QString s, bool cs)
  1.1500 +{
  1.1501 +	QTextDocument::FindFlags flags=0;
  1.1502 +	if (cs) flags=QTextDocument::FindCaseSensitively;
  1.1503 +
  1.1504 +	if (!itFind) 
  1.1505 +	{	// Nothing found or new find process
  1.1506 +		if (EOFind)
  1.1507 +			// nothing found, start again
  1.1508 +			EOFind=false;
  1.1509 +		itFind=first();
  1.1510 +	}	
  1.1511 +	bool searching=true;
  1.1512 +	bool foundNote=false;
  1.1513 +	while (searching && !EOFind)
  1.1514 +	{
  1.1515 +		if (itFind)
  1.1516 +		{
  1.1517 +			// Searching in Note
  1.1518 +			if (itFind->getNote().contains(s,cs))
  1.1519 +			{
  1.1520 +				if (selection.single()!=itFind) 
  1.1521 +				{
  1.1522 +					selection.select(itFind);
  1.1523 +					ensureSelectionVisible();
  1.1524 +				}
  1.1525 +				if (textEditor->findText(s,flags)) 
  1.1526 +				{
  1.1527 +					searching=false;
  1.1528 +					foundNote=true;
  1.1529 +				}	
  1.1530 +			}
  1.1531 +			// Searching in Heading
  1.1532 +			if (searching && itFind->getHeading().contains (s,cs) ) 
  1.1533 +			{
  1.1534 +				selection.select(itFind);
  1.1535 +				ensureSelectionVisible();
  1.1536 +				searching=false;
  1.1537 +			}
  1.1538 +		}	
  1.1539 +		if (!foundNote)
  1.1540 +		{
  1.1541 +			itFind=next(itFind);
  1.1542 +			if (!itFind) EOFind=true;
  1.1543 +		}
  1.1544 +	//cout <<"still searching...  "<<qPrintable( itFind->getHeading())<<endl;
  1.1545 +	}	
  1.1546 +	if (!searching)
  1.1547 +		return selection.getBranch();
  1.1548 +	else
  1.1549 +		return NULL;
  1.1550 +}
  1.1551 +
  1.1552 +void VymModel::findReset()
  1.1553 +{	// Necessary if text to find changes during a find process
  1.1554 +	itFind=NULL;
  1.1555 +	EOFind=false;
  1.1556 +}
  1.1557 +
  1.1558 +
  1.1559 +
  1.1560 +void VymModel::setScene (QGraphicsScene *s)
  1.1561 +{
  1.1562 +	mapScene=s;
  1.1563 +    init();	// Here we have a mapScene set, 
  1.1564 +			// which is (still) needed to create MapCenters
  1.1565 +}
  1.1566 +
  1.1567 +void VymModel::setURL(const QString &url)
  1.1568 +{
  1.1569 +	BranchObj *bo=selection.getBranch();
  1.1570 +	if (bo)
  1.1571 +	{
  1.1572 +		QString oldurl=bo->getURL();
  1.1573 +		bo->setURL (url);
  1.1574 +		saveState (
  1.1575 +			bo,
  1.1576 +			QString ("setURL (\"%1\")").arg(oldurl),
  1.1577 +			bo,
  1.1578 +			QString ("setURL (\"%1\")").arg(url),
  1.1579 +			QString ("set URL of %1 to %2").arg(getObjectName(bo)).arg(url)
  1.1580 +		);
  1.1581 +		updateActions();
  1.1582 +		reposition();
  1.1583 +		selection.update();
  1.1584 +		ensureSelectionVisible();
  1.1585 +	}
  1.1586 +}	
  1.1587 +
  1.1588 +QString VymModel::getURL()
  1.1589 +{
  1.1590 +	BranchObj *bo=selection.getBranch();
  1.1591 +	if (bo)
  1.1592 +		return bo->getURL();
  1.1593 +	else
  1.1594 +		return "";
  1.1595 +}
  1.1596 +
  1.1597 +QStringList VymModel::getURLs()
  1.1598 +{
  1.1599 +	QStringList urls;
  1.1600 +	BranchObj *bo=selection.getBranch();
  1.1601 +	if (bo)
  1.1602 +	{		
  1.1603 +		bo=bo->first();	
  1.1604 +		while (bo) 
  1.1605 +		{
  1.1606 +			if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
  1.1607 +			bo=bo->next();
  1.1608 +		}	
  1.1609 +	}	
  1.1610 +	return urls;
  1.1611 +}
  1.1612 +
  1.1613 +void VymModel::linkFloatImageTo(const QString &dstString)	
  1.1614 +{
  1.1615 +	FloatImageObj *fio=selection.getFloatImage();
  1.1616 +	if (fio)
  1.1617 +	{
  1.1618 +		BranchObj *dst=(BranchObj*)findObjBySelect(dstString);
  1.1619 +		if (dst && (typeid(*dst)==typeid (BranchObj) || 
  1.1620 +					typeid(*dst)==typeid (MapCenterObj)))
  1.1621 +		{			
  1.1622 +			LinkableMapObj *dstPar=dst->getParObj();
  1.1623 +			QString parString=getSelectString(dstPar);
  1.1624 +			QString fioPreSelectString=getSelectString(fio);
  1.1625 +			QString fioPreParentSelectString=getSelectString (fio->getParObj());
  1.1626 +			((BranchObj*)dst)->addFloatImage (fio);
  1.1627 +			selection.unselect();
  1.1628 +			((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
  1.1629 +			fio=((BranchObj*)dst)->getLastFloatImage();
  1.1630 +			fio->setRelPos();
  1.1631 +			fio->reposition();
  1.1632 +			selection.select(fio);
  1.1633 +			saveState(
  1.1634 +				getSelectString(fio),
  1.1635 +				QString("linkTo (\"%1\")").arg(fioPreParentSelectString), 
  1.1636 +				fioPreSelectString, 
  1.1637 +				QString ("linkTo (\"%1\")").arg(dstString),
  1.1638 +				QString ("Link floatimage to %1").arg(getObjectName(dst)));
  1.1639 +		}
  1.1640 +	}
  1.1641 +}
  1.1642 +
  1.1643 +
  1.1644 +void VymModel::setFrameType(const FrameObj::FrameType &t)
  1.1645 +{
  1.1646 +	BranchObj *bo=selection.getBranch();
  1.1647 +	if (bo)
  1.1648 +	{
  1.1649 +		QString s=bo->getFrameTypeName();
  1.1650 +		bo->setFrameType (t);
  1.1651 +		saveState (bo, QString("setFrameType (\"%1\")").arg(s),
  1.1652 +			bo, QString ("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),QString ("set type of frame to %1").arg(s));
  1.1653 +		reposition();
  1.1654 +		bo->updateLink();
  1.1655 +	}
  1.1656 +}
  1.1657 +
  1.1658 +void VymModel::setFrameType(const QString &s)	
  1.1659 +{
  1.1660 +	BranchObj *bo=selection.getBranch();
  1.1661 +	if (bo)
  1.1662 +	{
  1.1663 +		saveState (bo, QString("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),
  1.1664 +			bo, QString ("setFrameType (\"%1\")").arg(s),QString ("set type of frame to %1").arg(s));
  1.1665 +		bo->setFrameType (s);
  1.1666 +		reposition();
  1.1667 +		bo->updateLink();
  1.1668 +	}
  1.1669 +}
  1.1670 +
  1.1671 +void VymModel::setFramePenColor(const QColor &c)	
  1.1672 +{
  1.1673 +	BranchObj *bo=selection.getBranch();
  1.1674 +	if (bo)
  1.1675 +	{
  1.1676 +		saveState (bo, QString("setFramePenColor (\"%1\")").arg(bo->getFramePenColor().name() ),
  1.1677 +			bo, QString ("setFramePenColor (\"%1\")").arg(c.name() ),QString ("set pen color of frame to %1").arg(c.name() ));
  1.1678 +		bo->setFramePenColor (c);
  1.1679 +	}	
  1.1680 +}
  1.1681 +
  1.1682 +void VymModel::setFrameBrushColor(const QColor &c)	
  1.1683 +{
  1.1684 +	BranchObj *bo=selection.getBranch();
  1.1685 +	if (bo)
  1.1686 +	{
  1.1687 +		saveState (bo, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
  1.1688 +			bo, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
  1.1689 +		bo->setFrameBrushColor (c);
  1.1690 +	}	
  1.1691 +}
  1.1692 +
  1.1693 +void VymModel::setFramePadding (const int &i)
  1.1694 +{
  1.1695 +	BranchObj *bo=selection.getBranch();
  1.1696 +	if (bo)
  1.1697 +	{
  1.1698 +		saveState (bo, QString("setFramePadding (\"%1\")").arg(bo->getFramePadding() ),
  1.1699 +			bo, QString ("setFramePadding (\"%1\")").arg(i),QString ("set brush color of frame to %1").arg(i));
  1.1700 +		bo->setFramePadding (i);
  1.1701 +		reposition();
  1.1702 +		bo->updateLink();
  1.1703 +	}	
  1.1704 +}
  1.1705 +
  1.1706 +void VymModel::setFrameBorderWidth(const int &i)
  1.1707 +{
  1.1708 +	BranchObj *bo=selection.getBranch();
  1.1709 +	if (bo)
  1.1710 +	{
  1.1711 +		saveState (bo, QString("setFrameBorderWidth (\"%1\")").arg(bo->getFrameBorderWidth() ),
  1.1712 +			bo, QString ("setFrameBorderWidth (\"%1\")").arg(i),QString ("set border width of frame to %1").arg(i));
  1.1713 +		bo->setFrameBorderWidth (i);
  1.1714 +		reposition();
  1.1715 +		bo->updateLink();
  1.1716 +	}	
  1.1717 +}
  1.1718 +
  1.1719 +void VymModel::setIncludeImagesVer(bool b)	
  1.1720 +{
  1.1721 +	BranchObj *bo=selection.getBranch();
  1.1722 +	if (bo)
  1.1723 +	{
  1.1724 +		QString u= b ? "false" : "true";
  1.1725 +		QString r=!b ? "false" : "true";
  1.1726 +		
  1.1727 +		saveState(
  1.1728 +			bo,
  1.1729 +			QString("setIncludeImagesVertically (%1)").arg(u),
  1.1730 +			bo, 
  1.1731 +			QString("setIncludeImagesVertically (%1)").arg(r),
  1.1732 +			QString("Include images vertically in %1").arg(getObjectName(bo))
  1.1733 +		);	
  1.1734 +		bo->setIncludeImagesVer(b);
  1.1735 +		reposition();
  1.1736 +	}	
  1.1737 +}
  1.1738 +
  1.1739 +void VymModel::setIncludeImagesHor(bool b)	
  1.1740 +{
  1.1741 +	BranchObj *bo=selection.getBranch();
  1.1742 +	if (bo)
  1.1743 +	{
  1.1744 +		QString u= b ? "false" : "true";
  1.1745 +		QString r=!b ? "false" : "true";
  1.1746 +		
  1.1747 +		saveState(
  1.1748 +			bo,
  1.1749 +			QString("setIncludeImagesHorizontally (%1)").arg(u),
  1.1750 +			bo, 
  1.1751 +			QString("setIncludeImagesHorizontally (%1)").arg(r),
  1.1752 +			QString("Include images horizontally in %1").arg(getObjectName(bo))
  1.1753 +		);	
  1.1754 +		bo->setIncludeImagesHor(b);
  1.1755 +		reposition();
  1.1756 +	}	
  1.1757 +}
  1.1758 +
  1.1759 +void VymModel::setHideLinkUnselected (bool b)
  1.1760 +{
  1.1761 +	LinkableMapObj *sel=selection.single();
  1.1762 +	if (sel &&
  1.1763 +		(selection.type() == Selection::Branch || 
  1.1764 +		selection.type() == Selection::MapCenter  ||
  1.1765 +		selection.type() == Selection::FloatImage ))
  1.1766 +	{
  1.1767 +		QString u= b ? "false" : "true";
  1.1768 +		QString r=!b ? "false" : "true";
  1.1769 +		
  1.1770 +		saveState(
  1.1771 +			sel,
  1.1772 +			QString("setHideLinkUnselected (%1)").arg(u),
  1.1773 +			sel, 
  1.1774 +			QString("setHideLinkUnselected (%1)").arg(r),
  1.1775 +			QString("Hide link of %1 if unselected").arg(getObjectName(sel))
  1.1776 +		);	
  1.1777 +		sel->setHideLinkUnselected(b);
  1.1778 +	}
  1.1779 +}
  1.1780 +
  1.1781 +void VymModel::setHideExport(bool b)
  1.1782 +{
  1.1783 +	BranchObj *bo=selection.getBranch();
  1.1784 +	if (bo)
  1.1785 +	{
  1.1786 +		bo->setHideInExport (b);
  1.1787 +		QString u= b ? "false" : "true";
  1.1788 +		QString r=!b ? "false" : "true";
  1.1789 +		
  1.1790 +		saveState(
  1.1791 +			bo,
  1.1792 +			QString ("setHideExport (%1)").arg(u),
  1.1793 +			bo,
  1.1794 +			QString ("setHideExport (%1)").arg(r),
  1.1795 +			QString ("Set HideExport flag of %1 to %2").arg(getObjectName(bo)).arg (r)
  1.1796 +		);	
  1.1797 +		updateActions();
  1.1798 +		reposition();
  1.1799 +		selection.update();
  1.1800 +		// FIXME needed? scene()->update();
  1.1801 +	}
  1.1802 +}
  1.1803 +
  1.1804 +void VymModel::toggleHideExport()
  1.1805 +{
  1.1806 +	BranchObj *bo=selection.getBranch();
  1.1807 +	if (bo)
  1.1808 +		setHideExport ( !bo->hideInExport() );
  1.1809 +}
  1.1810 +
  1.1811 +
  1.1812 +void VymModel::copy()
  1.1813 +{
  1.1814 +	LinkableMapObj *sel=selection.single();
  1.1815 +	if (sel)
  1.1816 +	{
  1.1817 +		if (redosAvail == 0)
  1.1818 +		{
  1.1819 +			// Copy to history
  1.1820 +			QString s=getSelectString(sel);
  1.1821 +			saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy selection to clipboard",sel  );
  1.1822 +			curClipboard=curStep;
  1.1823 +		}
  1.1824 +
  1.1825 +		// Copy also to global clipboard, because we are at last step in history
  1.1826 +		QString bakMapName(QString("history-%1").arg(curStep));
  1.1827 +		QString bakMapDir(tmpMapDir +"/"+bakMapName);
  1.1828 +		copyDir (bakMapDir,clipboardDir );
  1.1829 +
  1.1830 +		clipboardEmpty=false;
  1.1831 +		updateActions();
  1.1832 +	}	    
  1.1833 +}
  1.1834 +
  1.1835 +
  1.1836 +void VymModel::pasteNoSave(const int &n)
  1.1837 +{
  1.1838 +	bool old=blockSaveState;
  1.1839 +	blockSaveState=true;
  1.1840 +	bool zippedOrg=zipped;
  1.1841 +	if (redosAvail > 0 || n!=0)
  1.1842 +	{
  1.1843 +		// Use the "historical" buffer
  1.1844 +		QString bakMapName(QString("history-%1").arg(n));
  1.1845 +		QString bakMapDir(tmpMapDir +"/"+bakMapName);
  1.1846 +		load (bakMapDir+"/"+clipboardFile,ImportAdd, VymMap);
  1.1847 +	} else
  1.1848 +		// Use the global buffer
  1.1849 +		load (clipboardDir+"/"+clipboardFile,ImportAdd, VymMap);
  1.1850 +	zipped=zippedOrg;
  1.1851 +	blockSaveState=old;
  1.1852 +}
  1.1853 +
  1.1854 +void VymModel::paste()		
  1.1855 +{   
  1.1856 +	BranchObj *sel=selection.getBranch();
  1.1857 +	if (sel)
  1.1858 +	{
  1.1859 +		saveStateChangingPart(
  1.1860 +			sel,
  1.1861 +			sel,
  1.1862 +			QString ("paste (%1)").arg(curClipboard),
  1.1863 +			QString("Paste to %1").arg( getObjectName(sel))
  1.1864 +		);
  1.1865 +		pasteNoSave(0);
  1.1866 +		reposition();
  1.1867 +	}
  1.1868 +}
  1.1869 +
  1.1870 +void VymModel::cut()
  1.1871 +{
  1.1872 +	LinkableMapObj *sel=selection.single();
  1.1873 +	if ( sel && (selection.type() == Selection::Branch ||
  1.1874 +		selection.type()==Selection::MapCenter ||
  1.1875 +		selection.type()==Selection::FloatImage))
  1.1876 +	{
  1.1877 +	/* No savestate! savestate is called in cutNoSave
  1.1878 +		saveStateChangingPart(
  1.1879 +			sel->getParObj(),
  1.1880 +			sel,
  1.1881 +			"cut ()",
  1.1882 +			QString("Cut %1").arg(getObjectName(sel ))
  1.1883 +		);
  1.1884 +	*/	
  1.1885 +		copy();
  1.1886 +		deleteSelection();
  1.1887 +		reposition();
  1.1888 +	}
  1.1889 +}
  1.1890 +
  1.1891 +void VymModel::moveBranchUp()
  1.1892 +{
  1.1893 +	BranchObj* bo=selection.getBranch();
  1.1894 +	BranchObj* par;
  1.1895 +	if (bo)
  1.1896 +	{
  1.1897 +		if (!bo->canMoveBranchUp()) return;
  1.1898 +		par=(BranchObj*)(bo->getParObj());
  1.1899 +		BranchObj *obo=par->moveBranchUp (bo);	// bo will be the one below selection
  1.1900 +		saveState (getSelectString(bo),"moveBranchDown ()",getSelectString(obo),"moveBranchUp ()",QString("Move up %1").arg(getObjectName(bo)));
  1.1901 +		reposition();
  1.1902 +		//FIXME needed? scene()->update();
  1.1903 +		selection.update();
  1.1904 +		ensureSelectionVisible();
  1.1905 +	}
  1.1906 +}
  1.1907 +
  1.1908 +void VymModel::moveBranchDown()
  1.1909 +{
  1.1910 +	BranchObj* bo=selection.getBranch();
  1.1911 +	BranchObj* par;
  1.1912 +	if (bo)
  1.1913 +	{
  1.1914 +		if (!bo->canMoveBranchDown()) return;
  1.1915 +		par=(BranchObj*)(bo->getParObj());
  1.1916 +		BranchObj *obo=par->moveBranchDown(bo);	// bo will be the one above selection
  1.1917 +		saveState(getSelectString(bo),"moveBranchUp ()",getSelectString(obo),"moveBranchDown ()",QString("Move down %1").arg(getObjectName(bo)));
  1.1918 +		reposition();
  1.1919 +		//FIXME needed? scene()->update();
  1.1920 +		selection.update();
  1.1921 +		ensureSelectionVisible();
  1.1922 +	}	
  1.1923 +}
  1.1924 +
  1.1925 +void VymModel::sortChildren()
  1.1926 +{
  1.1927 +	BranchObj* bo=selection.getBranch();
  1.1928 +	if (bo)
  1.1929 +	{
  1.1930 +		if(bo->countBranches()>1)
  1.1931 +		{
  1.1932 +			saveStateChangingPart(bo,bo, "sortChildren ()",QString("Sort children of %1").arg(getObjectName(bo)));
  1.1933 +			bo->sortChildren();
  1.1934 +			reposition();
  1.1935 +			ensureSelectionVisible();
  1.1936 +		}
  1.1937 +	}
  1.1938 +}
  1.1939 +
  1.1940 +MapCenterObj* VymModel::addMapCenter ()
  1.1941 +{
  1.1942 +	MapCenterObj *mco=addMapCenter (QPointF(0,0));
  1.1943 +	selection.select (mco);
  1.1944 +	updateActions();
  1.1945 +	ensureSelectionVisible();
  1.1946 +	saveState (
  1.1947 +		mco,
  1.1948 +		"delete()",
  1.1949 +		NULL,
  1.1950 +		// FIXME  how to position LineEdit without contextMenuPos ?
  1.1951 +		// QString ("addMapCenter (%1,%2)").arg (contextMenuPos.x()).arg(contextMenuPos.y()),
  1.1952 +		// QString ("Adding MapCenter to (%1,%2").arg (contextMenuPos.x()).arg(contextMenuPos.y())
  1.1953 +		QString ("addMapCenter (%1,%2)").arg (0).arg(0),
  1.1954 +		QString ("Adding MapCenter to (%1,%2").arg (0).arg(0)
  1.1955 +	);	
  1.1956 +	return mco;	
  1.1957 +}
  1.1958 +
  1.1959 +MapCenterObj* VymModel::addMapCenter(QPointF absPos)
  1.1960 +{
  1.1961 +	MapCenterObj *mapCenter = new MapCenterObj(mapScene);
  1.1962 +	mapCenter->move (absPos);
  1.1963 +    mapCenter->setVisibility (true);
  1.1964 +	mapCenter->setHeading (QApplication::translate("Heading of mapcenter in new map", "New map"));
  1.1965 +	mapCenter->setMapEditor(mapEditor);		//FIXME needed to get defLinkStyle, mapLinkColorHint ... for later added objects
  1.1966 +	mapCenters.append(mapCenter);
  1.1967 +	return mapCenter;
  1.1968 +}
  1.1969 +
  1.1970 +MapCenterObj *VymModel::removeMapCenter(MapCenterObj* mco)
  1.1971 +{
  1.1972 +	int i=mapCenters.indexOf (mco);
  1.1973 +	if (i>=0)
  1.1974 +	{
  1.1975 +		mapCenters.removeAt (i);
  1.1976 +		delete (mco);
  1.1977 +		if (i>0) return mapCenters.at(i-1);	// Return previous MCO
  1.1978 +	}
  1.1979 +	return NULL;
  1.1980 +}
  1.1981 +
  1.1982 +
  1.1983 +BranchObj* VymModel::addNewBranchInt(int num)
  1.1984 +{
  1.1985 +	// Depending on pos:
  1.1986 +	// -3		insert in children of parent  above selection 
  1.1987 +	// -2		add branch to selection 
  1.1988 +	// -1		insert in children of parent below selection 
  1.1989 +	// 0..n		insert in children of parent at pos
  1.1990 +	BranchObj *newbo=NULL;
  1.1991 +	BranchObj *bo=selection.getBranch();
  1.1992 +	if (bo)
  1.1993 +	{
  1.1994 +		if (num==-2)
  1.1995 +		{
  1.1996 +			// save scroll state. If scrolled, automatically select
  1.1997 +			// new branch in order to tmp unscroll parent...
  1.1998 +			newbo=bo->addBranch();
  1.1999 +			
  1.2000 +		}else if (num==-1)
  1.2001 +		{
  1.2002 +			num=bo->getNum()+1;
  1.2003 +			bo=(BranchObj*)bo->getParObj();
  1.2004 +			if (bo) newbo=bo->insertBranch(num);
  1.2005 +		}else if (num==-3)
  1.2006 +		{
  1.2007 +			num=bo->getNum();
  1.2008 +			bo=(BranchObj*)bo->getParObj();
  1.2009 +			if (bo) newbo=bo->insertBranch(num);
  1.2010 +		}
  1.2011 +		if (!newbo) return NULL;
  1.2012 +	}	
  1.2013 +	return newbo;
  1.2014 +}	
  1.2015 +
  1.2016 +BranchObj* VymModel::addNewBranch(int pos)
  1.2017 +{
  1.2018 +	// Different meaning than num in addNewBranchInt!
  1.2019 +	// -1	add above
  1.2020 +	//  0	add as child
  1.2021 +	// +1	add below
  1.2022 +	BranchObj *bo = selection.getBranch();
  1.2023 +	BranchObj *newbo=NULL;
  1.2024 +
  1.2025 +	if (bo)
  1.2026 +	{
  1.2027 +		// FIXME  do we still need this in model? setCursor (Qt::ArrowCursor);
  1.2028 +
  1.2029 +		newbo=addNewBranchInt (pos-2);
  1.2030 +
  1.2031 +		if (newbo)
  1.2032 +		{
  1.2033 +			saveState(
  1.2034 +				newbo,		
  1.2035 +				"delete ()",
  1.2036 +				bo,
  1.2037 +				QString ("addBranch (%1)").arg(pos),
  1.2038 +				QString ("Add new branch to %1").arg(getObjectName(bo)));	
  1.2039 +
  1.2040 +			reposition();
  1.2041 +			selection.update();
  1.2042 +			latestSelectionString=getSelectString(newbo);
  1.2043 +			// In Network mode, the client needs to know where the new branch is,
  1.2044 +			// so we have to pass on this information via saveState.
  1.2045 +			// TODO: Get rid of this positioning workaround
  1.2046 +			QString ps=qpointfToString (newbo->getAbsPos());
  1.2047 +			sendData ("selectLatestAdded ()");
  1.2048 +			sendData (QString("move %1").arg(ps));
  1.2049 +			sendSelection();
  1.2050 +		}
  1.2051 +	}	
  1.2052 +	return newbo;
  1.2053 +}
  1.2054 +
  1.2055 +
  1.2056 +BranchObj* VymModel::addNewBranchBefore()
  1.2057 +{
  1.2058 +	BranchObj *newbo=NULL;
  1.2059 +	BranchObj *bo = selection.getBranch();
  1.2060 +	if (bo && selection.type()==Selection::Branch)
  1.2061 +		 // We accept no MapCenterObj here, so we _have_ a parent
  1.2062 +	{
  1.2063 +		QPointF p=bo->getRelPos();
  1.2064 +
  1.2065 +
  1.2066 +		BranchObj *parbo=(BranchObj*)(bo->getParObj());
  1.2067 +
  1.2068 +		// add below selection
  1.2069 +		newbo=parbo->insertBranch(bo->getNum()+1);
  1.2070 +		if (newbo)
  1.2071 +		{
  1.2072 +			newbo->move2RelPos (p);
  1.2073 +
  1.2074 +			// Move selection to new branch
  1.2075 +			bo->linkTo (newbo,-1);
  1.2076 +
  1.2077 +			saveState (newbo, "deleteKeepChildren ()", newbo, "addBranchBefore ()", 
  1.2078 +				QString ("Add branch before %1").arg(getObjectName(bo)));
  1.2079 +
  1.2080 +			reposition();
  1.2081 +			selection.update();
  1.2082 +		}
  1.2083 +	}	
  1.2084 +	latestSelectionString=selection.getSelectString();
  1.2085 +	return newbo;
  1.2086 +}
  1.2087 +
  1.2088 +void VymModel::deleteSelection()
  1.2089 +{
  1.2090 +	BranchObj *bo = selection.getBranch();
  1.2091 +	if (bo && selection.type()==Selection::MapCenter)
  1.2092 +	{
  1.2093 +	//	BranchObj* par=(BranchObj*)(bo->getParObj());
  1.2094 +		selection.unselect();
  1.2095 +	/* FIXME Note:  does saveStateRemovingPart work for MCO? (No parent!)
  1.2096 +		saveStateRemovingPart (bo, QString ("Delete %1").arg(getObjectName(bo)));
  1.2097 +		*/
  1.2098 +		bo=removeMapCenter ((MapCenterObj*)bo);
  1.2099 +		if (bo) 
  1.2100 +		{
  1.2101 +			selection.select (bo);
  1.2102 +			ensureSelectionVisible();
  1.2103 +			selection.update();
  1.2104 +		}	
  1.2105 +		reposition();
  1.2106 +		return;
  1.2107 +	}
  1.2108 +	if (bo && selection.type()==Selection::Branch)
  1.2109 +	{
  1.2110 +		BranchObj* par=(BranchObj*)bo->getParObj();
  1.2111 +		selection.unselect();
  1.2112 +		saveStateRemovingPart (bo, QString ("Delete %1").arg(getObjectName(bo)));
  1.2113 +		par->removeBranch(bo);
  1.2114 +		selection.select (par);
  1.2115 +		ensureSelectionVisible();
  1.2116 +		reposition();
  1.2117 +		selection.update();
  1.2118 +		return;
  1.2119 +	}
  1.2120 +	FloatImageObj *fio=selection.getFloatImage();
  1.2121 +	if (fio)
  1.2122 +	{
  1.2123 +		BranchObj* par=(BranchObj*)fio->getParObj();
  1.2124 +		saveStateChangingPart(
  1.2125 +			par, 
  1.2126 +			fio,
  1.2127 +			"delete ()",
  1.2128 +			QString("Delete %1").arg(getObjectName(fio))
  1.2129 +		);
  1.2130 +		selection.unselect();
  1.2131 +		par->removeFloatImage(fio);
  1.2132 +		selection.select (par);
  1.2133 +		reposition();
  1.2134 +		selection.update();
  1.2135 +		ensureSelectionVisible();
  1.2136 +		return;
  1.2137 +	}
  1.2138 +}
  1.2139 +
  1.2140 +void VymModel::deleteKeepChildren()
  1.2141 +{
  1.2142 +	BranchObj *bo=selection.getBranch();
  1.2143 +	BranchObj *par;
  1.2144 +	if (bo)
  1.2145 +	{
  1.2146 +		par=(BranchObj*)(bo->getParObj());
  1.2147 +		QPointF p=bo->getRelPos();
  1.2148 +		saveStateChangingPart(
  1.2149 +			bo->getParObj(),
  1.2150 +			bo,
  1.2151 +			"deleteKeepChildren ()",
  1.2152 +			QString("Remove %1 and keep its children").arg(getObjectName(bo))
  1.2153 +		);
  1.2154 +
  1.2155 +		QString sel=getSelectString(bo);
  1.2156 +		unselect();
  1.2157 +		par->removeBranchHere(bo);
  1.2158 +		reposition();
  1.2159 +		select (sel);
  1.2160 +		selection.getBranch()->move2RelPos (p);
  1.2161 +		reposition();
  1.2162 +	}	
  1.2163 +}
  1.2164 +
  1.2165 +void VymModel::deleteChildren()
  1.2166 +{
  1.2167 +	BranchObj *bo=selection.getBranch();
  1.2168 +	if (bo)
  1.2169 +	{		
  1.2170 +		saveStateChangingPart(
  1.2171 +			bo, 
  1.2172 +			bo,
  1.2173 +			"deleteChildren ()",
  1.2174 +			QString( "Remove children of branch %1").arg(getObjectName(bo))
  1.2175 +		);
  1.2176 +		bo->removeChildren();
  1.2177 +		reposition();
  1.2178 +	}	
  1.2179 +}
  1.2180 +
  1.2181 +
  1.2182 +bool VymModel::scrollBranch(BranchObj *bo)
  1.2183 +{
  1.2184 +	if (bo)
  1.2185 +	{
  1.2186 +		if (bo->isScrolled()) return false;
  1.2187 +		if (bo->countBranches()==0) return false;
  1.2188 +		if (bo->getDepth()==0) return false;
  1.2189 +		QString u,r;
  1.2190 +		r="scroll";
  1.2191 +		u="unscroll";
  1.2192 +		saveState(
  1.2193 +			bo,
  1.2194 +			QString ("%1 ()").arg(u),
  1.2195 +			bo,
  1.2196 +			QString ("%1 ()").arg(r),
  1.2197 +			QString ("%1 %2").arg(r).arg(getObjectName(bo))
  1.2198 +		);
  1.2199 +		bo->toggleScroll();
  1.2200 +		selection.update();
  1.2201 +		// FIXME needed? scene()->update();
  1.2202 +		return true;
  1.2203 +	}	
  1.2204 +	return false;
  1.2205 +}
  1.2206 +
  1.2207 +bool VymModel::unscrollBranch(BranchObj *bo)
  1.2208 +{
  1.2209 +	if (bo)
  1.2210 +	{
  1.2211 +		if (!bo->isScrolled()) return false;
  1.2212 +		if (bo->countBranches()==0) return false;
  1.2213 +		if (bo->getDepth()==0) return false;
  1.2214 +		QString u,r;
  1.2215 +		u="scroll";
  1.2216 +		r="unscroll";
  1.2217 +		saveState(
  1.2218 +			bo,
  1.2219 +			QString ("%1 ()").arg(u),
  1.2220 +			bo,
  1.2221 +			QString ("%1 ()").arg(r),
  1.2222 +			QString ("%1 %2").arg(r).arg(getObjectName(bo))
  1.2223 +		);
  1.2224 +		bo->toggleScroll();
  1.2225 +		selection.update();
  1.2226 +		// FIXME needed? scene()->update();
  1.2227 +		return true;
  1.2228 +	}	
  1.2229 +	return false;
  1.2230 +}
  1.2231 +
  1.2232 +void VymModel::toggleScroll()
  1.2233 +{
  1.2234 +	BranchObj *bo=selection.getBranch();
  1.2235 +	if (selection.type()==Selection::Branch )
  1.2236 +	{
  1.2237 +		if (bo->isScrolled())
  1.2238 +			unscrollBranch (bo);
  1.2239 +		else
  1.2240 +			scrollBranch (bo);
  1.2241 +	}
  1.2242 +}
  1.2243 +
  1.2244 +void VymModel::unscrollChildren() 
  1.2245 +{
  1.2246 +	BranchObj *bo=selection.getBranch();
  1.2247 +	if (bo)
  1.2248 +	{
  1.2249 +		bo->first();
  1.2250 +		while (bo) 
  1.2251 +		{
  1.2252 +			if (bo->isScrolled()) unscrollBranch (bo);
  1.2253 +			bo=bo->next();
  1.2254 +		}
  1.2255 +	}	
  1.2256 +}
  1.2257 +void VymModel::addFloatImage (const QPixmap &img) 
  1.2258 +{
  1.2259 +	BranchObj *bo=selection.getBranch();
  1.2260 +	if (bo)
  1.2261 +  {
  1.2262 +	FloatImageObj *fio=bo->addFloatImage();
  1.2263 +    fio->load(img);
  1.2264 +    fio->setOriginalFilename("No original filename (image added by dropevent)");	
  1.2265 +	QString s=getSelectString(bo);
  1.2266 +	saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy dropped image to clipboard",fio  );
  1.2267 +	saveState (fio,"delete ()", bo,QString("paste(%1)").arg(curStep),"Pasting dropped image");
  1.2268 +    reposition();
  1.2269 +    // FIXME needed? scene()->update();
  1.2270 +  }
  1.2271 +}
  1.2272 +
  1.2273 +
  1.2274 +void VymModel::colorBranch (QColor c)
  1.2275 +{
  1.2276 +	BranchObj *bo=selection.getBranch();
  1.2277 +	if (bo)
  1.2278 +	{
  1.2279 +		saveState(
  1.2280 +			bo, 
  1.2281 +			QString ("colorBranch (\"%1\")").arg(bo->getColor().name()),
  1.2282 +			bo,
  1.2283 +			QString ("colorBranch (\"%1\")").arg(c.name()),
  1.2284 +			QString("Set color of %1 to %2").arg(getObjectName(bo)).arg(c.name())
  1.2285 +		);	
  1.2286 +		bo->setColor(c); // color branch
  1.2287 +	}
  1.2288 +}
  1.2289 +
  1.2290 +void VymModel::colorSubtree (QColor c)
  1.2291 +{
  1.2292 +	BranchObj *bo=selection.getBranch();
  1.2293 +	if (bo) 
  1.2294 +	{
  1.2295 +		saveStateChangingPart(
  1.2296 +			bo, 
  1.2297 +			bo,
  1.2298 +			QString ("colorSubtree (\"%1\")").arg(c.name()),
  1.2299 +			QString ("Set color of %1 and children to %2").arg(getObjectName(bo)).arg(c.name())
  1.2300 +		);	
  1.2301 +		bo->setColorSubtree (c); // color links, color children
  1.2302 +	}
  1.2303 +}
  1.2304 +
  1.2305 +QColor VymModel::getCurrentHeadingColor()
  1.2306 +{
  1.2307 +	BranchObj *bo=selection.getBranch();
  1.2308 +	if (bo) return bo->getColor(); 
  1.2309 +	
  1.2310 +	QMessageBox::warning(0,"Warning","Can't get color of heading,\nthere's no branch selected");
  1.2311 +	return Qt::black;
  1.2312 +}
  1.2313 +
  1.2314 +
  1.2315 +
  1.2316 +void VymModel::editURL()
  1.2317 +{
  1.2318 +	BranchObj *bo=selection.getBranch();
  1.2319 +	if (bo)
  1.2320 +	{		
  1.2321 +		bool ok;
  1.2322 +		QString text = QInputDialog::getText(
  1.2323 +				"VYM", tr("Enter URL:"), QLineEdit::Normal,
  1.2324 +				bo->getURL(), &ok, NULL);
  1.2325 +		if ( ok) 
  1.2326 +			// user entered something and pressed OK
  1.2327 +			setURL(text);
  1.2328 +	}
  1.2329 +}
  1.2330 +
  1.2331 +void VymModel::editLocalURL()
  1.2332 +{
  1.2333 +	BranchObj *bo=selection.getBranch();
  1.2334 +	if (bo)
  1.2335 +	{		
  1.2336 +		QStringList filters;
  1.2337 +		filters <<"All files (*)";
  1.2338 +		filters << tr("Text","Filedialog") + " (*.txt)";
  1.2339 +		filters << tr("Spreadsheet","Filedialog") + " (*.odp,*.sxc)";
  1.2340 +		filters << tr("Textdocument","Filedialog") +" (*.odw,*.sxw)";
  1.2341 +		filters << tr("Images","Filedialog") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)";
  1.2342 +		QFileDialog *fd=new QFileDialog( NULL,vymName+" - " +tr("Set URL to a local file"));
  1.2343 +		fd->setFilters (filters);
  1.2344 +		fd->setCaption(vymName+" - " +tr("Set URL to a local file"));
  1.2345 +		fd->setDirectory (lastFileDir);
  1.2346 +		if (! bo->getVymLink().isEmpty() )
  1.2347 +			fd->selectFile( bo->getURL() );
  1.2348 +		fd->show();
  1.2349 +
  1.2350 +		if ( fd->exec() == QDialog::Accepted )
  1.2351 +		{
  1.2352 +			lastFileDir=QDir (fd->directory().path());
  1.2353 +			setURL (fd->selectedFile() );
  1.2354 +		}
  1.2355 +	}
  1.2356 +}
  1.2357 +
  1.2358 +
  1.2359 +void VymModel::editHeading2URL()
  1.2360 +{
  1.2361 +	BranchObj *bo=selection.getBranch();
  1.2362 +	if (bo)
  1.2363 +		setURL (bo->getHeading());
  1.2364 +}	
  1.2365 +
  1.2366 +void VymModel::editBugzilla2URL()
  1.2367 +{
  1.2368 +	BranchObj *bo=selection.getBranch();
  1.2369 +	if (bo)
  1.2370 +	{		
  1.2371 +		QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
  1.2372 +		setURL (url);
  1.2373 +	}
  1.2374 +}	
  1.2375 +
  1.2376 +void VymModel::editFATE2URL()
  1.2377 +{
  1.2378 +	BranchObj *bo=selection.getBranch();
  1.2379 +	if (bo)
  1.2380 +	{		
  1.2381 +		QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
  1.2382 +		saveState(
  1.2383 +			bo,
  1.2384 +			"setURL (\""+bo->getURL()+"\")",
  1.2385 +			bo,
  1.2386 +			"setURL (\""+url+"\")",
  1.2387 +			QString("Use heading of %1 as link to FATE").arg(getObjectName(bo))
  1.2388 +		);	
  1.2389 +		bo->setURL (url);
  1.2390 +		updateActions();
  1.2391 +	}
  1.2392 +}	
  1.2393 +
  1.2394 +void VymModel::editVymLink()
  1.2395 +{
  1.2396 +	BranchObj *bo=selection.getBranch();
  1.2397 +	if (bo)
  1.2398 +	{		
  1.2399 +		QStringList filters;
  1.2400 +		filters <<"VYM map (*.vym)";
  1.2401 +		QFileDialog *fd=new QFileDialog( NULL,vymName+" - " +tr("Link to another map"));
  1.2402 +		fd->setFilters (filters);
  1.2403 +		fd->setCaption(vymName+" - " +tr("Link to another map"));
  1.2404 +		fd->setDirectory (lastFileDir);
  1.2405 +		if (! bo->getVymLink().isEmpty() )
  1.2406 +			fd->selectFile( bo->getVymLink() );
  1.2407 +		fd->show();
  1.2408 +
  1.2409 +		QString fn;
  1.2410 +		if ( fd->exec() == QDialog::Accepted )
  1.2411 +		{
  1.2412 +			lastFileDir=QDir (fd->directory().path());
  1.2413 +			saveState(
  1.2414 +				bo,
  1.2415 +				"setVymLink (\""+bo->getVymLink()+"\")",
  1.2416 +				bo,
  1.2417 +				"setVymLink (\""+fd->selectedFile()+"\")",
  1.2418 +				QString("Set vymlink of %1 to %2").arg(getObjectName(bo)).arg(fd->selectedFile())
  1.2419 +			);	
  1.2420 +			setVymLink (fd->selectedFile() );	// FIXME ok?
  1.2421 +		}
  1.2422 +	}
  1.2423 +}
  1.2424 +
  1.2425 +void VymModel::setVymLink (const QString &s)
  1.2426 +{
  1.2427 +	// Internal function, no saveState needed
  1.2428 +	BranchObj *bo=selection.getBranch();
  1.2429 +	if (bo)
  1.2430 +	{
  1.2431 +		bo->setVymLink(s);
  1.2432 +		reposition();
  1.2433 +		updateActions();
  1.2434 +		selection.update();
  1.2435 +		ensureSelectionVisible();
  1.2436 +	}
  1.2437 +}
  1.2438 +
  1.2439 +void VymModel::deleteVymLink()
  1.2440 +{
  1.2441 +	BranchObj *bo=selection.getBranch();
  1.2442 +	if (bo)
  1.2443 +	{		
  1.2444 +		saveState(
  1.2445 +			bo,
  1.2446 +			"setVymLink (\""+bo->getVymLink()+"\")",
  1.2447 +			bo,
  1.2448 +			"setVymLink (\"\")",
  1.2449 +			QString("Unset vymlink of %1").arg(getObjectName(bo))
  1.2450 +		);	
  1.2451 +		bo->setVymLink ("" );
  1.2452 +		updateActions();
  1.2453 +		reposition();
  1.2454 +		// FIXME needed? scene()->update();
  1.2455 +	}
  1.2456 +}
  1.2457 +
  1.2458 +QString VymModel::getVymLink()
  1.2459 +{
  1.2460 +	BranchObj *bo=selection.getBranch();
  1.2461 +	if (bo)
  1.2462 +		return bo->getVymLink();
  1.2463 +	else	
  1.2464 +		return "";
  1.2465 +	
  1.2466 +}
  1.2467 +
  1.2468 +QStringList VymModel::getVymLinks()
  1.2469 +{
  1.2470 +	QStringList links;
  1.2471 +	BranchObj *bo=selection.getBranch();
  1.2472 +	if (bo)
  1.2473 +	{		
  1.2474 +		bo=bo->first();	
  1.2475 +		while (bo) 
  1.2476 +		{
  1.2477 +			if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
  1.2478 +			bo=bo->next();
  1.2479 +		}	
  1.2480 +	}	
  1.2481 +	return links;
  1.2482 +}
  1.2483 +
  1.2484 +
  1.2485 +void VymModel::followXLink(int i)
  1.2486 +{
  1.2487 +	BranchObj *bo=selection.getBranch();
  1.2488 +	if (bo)
  1.2489 +	{
  1.2490 +		bo=bo->XLinkTargetAt(i);
  1.2491 +		if (bo) 
  1.2492 +		{
  1.2493 +			selection.select(bo);
  1.2494 +			ensureSelectionVisible();
  1.2495 +		}
  1.2496 +	}
  1.2497 +}
  1.2498 +
  1.2499 +void VymModel::editXLink(int i)	// FIXME missing saveState
  1.2500 +{
  1.2501 +	BranchObj *bo=selection.getBranch();
  1.2502 +	if (bo)
  1.2503 +	{
  1.2504 +		XLinkObj *xlo=bo->XLinkAt(i);
  1.2505 +		if (xlo) 
  1.2506 +		{
  1.2507 +			EditXLinkDialog dia;
  1.2508 +			dia.setXLink (xlo);
  1.2509 +			dia.setSelection(bo);
  1.2510 +			if (dia.exec() == QDialog::Accepted)
  1.2511 +			{
  1.2512 +				if (dia.useSettingsGlobal() )
  1.2513 +				{
  1.2514 +					setMapDefXLinkColor (xlo->getColor() );
  1.2515 +					setMapDefXLinkWidth (xlo->getWidth() );
  1.2516 +				}
  1.2517 +				if (dia.deleteXLink())
  1.2518 +					bo->deleteXLinkAt(i);
  1.2519 +			}
  1.2520 +		}	
  1.2521 +	}
  1.2522 +}
  1.2523 +
  1.2524 +
  1.2525 +
  1.2526 +
  1.2527 +
  1.2528 +//////////////////////////////////////////////
  1.2529 +// Scripting
  1.2530 +//////////////////////////////////////////////
  1.2531 +
  1.2532 +void VymModel::parseAtom(const QString &atom)
  1.2533 +{
  1.2534 +	BranchObj *selb=selection.getBranch();
  1.2535 +	QString s,t;
  1.2536 +	double x,y;
  1.2537 +	int n;
  1.2538 +	bool b,ok;
  1.2539 +
  1.2540 +	// Split string s into command and parameters
  1.2541 +	parser.parseAtom (atom);
  1.2542 +	QString com=parser.getCommand();
  1.2543 +	
  1.2544 +	// External commands
  1.2545 +	/////////////////////////////////////////////////////////////////////
  1.2546 +	if (com=="addBranch")
  1.2547 +	{
  1.2548 +		if (selection.isEmpty())
  1.2549 +		{
  1.2550 +			parser.setError (Aborted,"Nothing selected");
  1.2551 +		} else if (! selb )
  1.2552 +		{				  
  1.2553 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2554 +		} else 
  1.2555 +		{	
  1.2556 +			QList <int> pl;
  1.2557 +			pl << 0 <<1;
  1.2558 +			if (parser.checkParCount(pl))
  1.2559 +			{
  1.2560 +				if (parser.parCount()==0)
  1.2561 +					addNewBranch (0);
  1.2562 +				else
  1.2563 +				{
  1.2564 +					n=parser.parInt (ok,0);
  1.2565 +					if (ok ) addNewBranch (n);
  1.2566 +				}
  1.2567 +			}
  1.2568 +		}
  1.2569 +	/////////////////////////////////////////////////////////////////////
  1.2570 +	} else if (com=="addBranchBefore")
  1.2571 +	{
  1.2572 +		if (selection.isEmpty())
  1.2573 +		{
  1.2574 +			parser.setError (Aborted,"Nothing selected");
  1.2575 +		} else if (! selb )
  1.2576 +		{				  
  1.2577 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2578 +		} else 
  1.2579 +		{	
  1.2580 +			if (parser.parCount()==0)
  1.2581 +			{
  1.2582 +				addNewBranchBefore ();
  1.2583 +			}	
  1.2584 +		}
  1.2585 +	/////////////////////////////////////////////////////////////////////
  1.2586 +	} else if (com==QString("addMapCenter"))
  1.2587 +	{
  1.2588 +		if (parser.checkParCount(2))
  1.2589 +		{
  1.2590 +			x=parser.parDouble (ok,0);
  1.2591 +			if (ok)
  1.2592 +			{
  1.2593 +				y=parser.parDouble (ok,1);
  1.2594 +				if (ok) addMapCenter (QPointF(x,y));
  1.2595 +			}
  1.2596 +		}	
  1.2597 +	/////////////////////////////////////////////////////////////////////
  1.2598 +	} else if (com==QString("addMapReplace"))
  1.2599 +	{
  1.2600 +		if (selection.isEmpty())
  1.2601 +		{
  1.2602 +			parser.setError (Aborted,"Nothing selected");
  1.2603 +		} else if (! selb )
  1.2604 +		{				  
  1.2605 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2606 +		} else if (parser.checkParCount(1))
  1.2607 +		{
  1.2608 +			//s=parser.parString (ok,0);	// selection
  1.2609 +			t=parser.parString (ok,0);	// path to map
  1.2610 +			if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
  1.2611 +			addMapReplaceInt(getSelectString(selb),t);	
  1.2612 +		}
  1.2613 +	/////////////////////////////////////////////////////////////////////
  1.2614 +	} else if (com==QString("addMapInsert"))
  1.2615 +	{
  1.2616 +		if (selection.isEmpty())
  1.2617 +		{
  1.2618 +			parser.setError (Aborted,"Nothing selected");
  1.2619 +		} else if (! selb )
  1.2620 +		{				  
  1.2621 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2622 +		} else 
  1.2623 +		{	
  1.2624 +			if (parser.checkParCount(2))
  1.2625 +			{
  1.2626 +				t=parser.parString (ok,0);	// path to map
  1.2627 +				n=parser.parInt(ok,1);		// position
  1.2628 +				if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
  1.2629 +				addMapInsertInt(t,n);	
  1.2630 +			}
  1.2631 +		}
  1.2632 +	/////////////////////////////////////////////////////////////////////
  1.2633 +	} else if (com=="clearFlags")
  1.2634 +	{
  1.2635 +		if (selection.isEmpty() )
  1.2636 +		{
  1.2637 +			parser.setError (Aborted,"Nothing selected");
  1.2638 +		} else if (! selb )
  1.2639 +		{				  
  1.2640 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2641 +		} else if (parser.checkParCount(0))
  1.2642 +		{
  1.2643 +			selb->clearStandardFlags();	
  1.2644 +			selb->updateFlagsToolbar();
  1.2645 +		}
  1.2646 +	/////////////////////////////////////////////////////////////////////
  1.2647 +	} else if (com=="colorBranch")
  1.2648 +	{
  1.2649 +		if (selection.isEmpty())
  1.2650 +		{
  1.2651 +			parser.setError (Aborted,"Nothing selected");
  1.2652 +		} else if (! selb )
  1.2653 +		{				  
  1.2654 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2655 +		} else if (parser.checkParCount(1))
  1.2656 +		{	
  1.2657 +			QColor c=parser.parColor (ok,0);
  1.2658 +			if (ok) colorBranch (c);
  1.2659 +		}	
  1.2660 +	/////////////////////////////////////////////////////////////////////
  1.2661 +	} else if (com=="colorSubtree")
  1.2662 +	{
  1.2663 +		if (selection.isEmpty())
  1.2664 +		{
  1.2665 +			parser.setError (Aborted,"Nothing selected");
  1.2666 +		} else if (! selb )
  1.2667 +		{				  
  1.2668 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2669 +		} else if (parser.checkParCount(1))
  1.2670 +		{	
  1.2671 +			QColor c=parser.parColor (ok,0);
  1.2672 +			if (ok) colorSubtree (c);
  1.2673 +		}	
  1.2674 +	/////////////////////////////////////////////////////////////////////
  1.2675 +	} else if (com=="copy")
  1.2676 +	{
  1.2677 +		if (selection.isEmpty())
  1.2678 +		{
  1.2679 +			parser.setError (Aborted,"Nothing selected");
  1.2680 +		} else if (! selb )
  1.2681 +		{				  
  1.2682 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2683 +		} else if (parser.checkParCount(0))
  1.2684 +		{	
  1.2685 +			//FIXME missing action for copy
  1.2686 +		}	
  1.2687 +	/////////////////////////////////////////////////////////////////////
  1.2688 +	} else if (com=="cut")
  1.2689 +	{
  1.2690 +		if (selection.isEmpty())
  1.2691 +		{
  1.2692 +			parser.setError (Aborted,"Nothing selected");
  1.2693 +		} else if ( selection.type()!=Selection::Branch  && 
  1.2694 +					selection.type()!=Selection::MapCenter  &&
  1.2695 +					selection.type()!=Selection::FloatImage )
  1.2696 +		{				  
  1.2697 +			parser.setError (Aborted,"Type of selection is not a branch or floatimage");
  1.2698 +		} else if (parser.checkParCount(0))
  1.2699 +		{	
  1.2700 +			cut();
  1.2701 +		}	
  1.2702 +	/////////////////////////////////////////////////////////////////////
  1.2703 +	} else if (com=="delete")
  1.2704 +	{
  1.2705 +		if (selection.isEmpty())
  1.2706 +		{
  1.2707 +			parser.setError (Aborted,"Nothing selected");
  1.2708 +		} 
  1.2709 +		/*else if (selection.type() != Selection::Branch && selection.type() != Selection::FloatImage )
  1.2710 +		{
  1.2711 +			parser.setError (Aborted,"Type of selection is wrong.");
  1.2712 +		} 
  1.2713 +		*/
  1.2714 +		else if (parser.checkParCount(0))
  1.2715 +		{	
  1.2716 +			deleteSelection();
  1.2717 +		}	
  1.2718 +	/////////////////////////////////////////////////////////////////////
  1.2719 +	} else if (com=="deleteKeepChildren")
  1.2720 +	{
  1.2721 +		if (selection.isEmpty())
  1.2722 +		{
  1.2723 +			parser.setError (Aborted,"Nothing selected");
  1.2724 +		} else if (! selb )
  1.2725 +		{
  1.2726 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2727 +		} else if (parser.checkParCount(0))
  1.2728 +		{	
  1.2729 +			deleteKeepChildren();
  1.2730 +		}	
  1.2731 +	/////////////////////////////////////////////////////////////////////
  1.2732 +	} else if (com=="deleteChildren")
  1.2733 +	{
  1.2734 +		if (selection.isEmpty())
  1.2735 +		{
  1.2736 +			parser.setError (Aborted,"Nothing selected");
  1.2737 +		} else if (! selb)
  1.2738 +		{
  1.2739 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2740 +		} else if (parser.checkParCount(0))
  1.2741 +		{	
  1.2742 +			deleteChildren();
  1.2743 +		}	
  1.2744 +	/////////////////////////////////////////////////////////////////////
  1.2745 +	} else if (com=="exportASCII")
  1.2746 +	{
  1.2747 +		QString fname="";
  1.2748 +		ok=true;
  1.2749 +		if (parser.parCount()>=1)
  1.2750 +			// Hey, we even have a filename
  1.2751 +			fname=parser.parString(ok,0); 
  1.2752 +		if (!ok)
  1.2753 +		{
  1.2754 +			parser.setError (Aborted,"Could not read filename");
  1.2755 +		} else
  1.2756 +		{
  1.2757 +				exportASCII (fname,false);
  1.2758 +		}
  1.2759 +	/////////////////////////////////////////////////////////////////////
  1.2760 +	} else if (com=="exportImage")
  1.2761 +	{
  1.2762 +		QString fname="";
  1.2763 +		ok=true;
  1.2764 +		if (parser.parCount()>=2)
  1.2765 +			// Hey, we even have a filename
  1.2766 +			fname=parser.parString(ok,0); 
  1.2767 +		if (!ok)
  1.2768 +		{
  1.2769 +			parser.setError (Aborted,"Could not read filename");
  1.2770 +		} else
  1.2771 +		{
  1.2772 +			QString format="PNG";
  1.2773 +			if (parser.parCount()>=2)
  1.2774 +			{
  1.2775 +				format=parser.parString(ok,1);
  1.2776 +			}
  1.2777 +			exportImage (fname,false,format);
  1.2778 +		}
  1.2779 +	/////////////////////////////////////////////////////////////////////
  1.2780 +	} else if (com=="exportXHTML")
  1.2781 +	{
  1.2782 +		QString fname="";
  1.2783 +		ok=true;
  1.2784 +		if (parser.parCount()>=2)
  1.2785 +			// Hey, we even have a filename
  1.2786 +			fname=parser.parString(ok,1); 
  1.2787 +		if (!ok)
  1.2788 +		{
  1.2789 +			parser.setError (Aborted,"Could not read filename");
  1.2790 +		} else
  1.2791 +		{
  1.2792 +			exportXHTML (fname,false);
  1.2793 +		}
  1.2794 +	/////////////////////////////////////////////////////////////////////
  1.2795 +	} else if (com=="exportXML")
  1.2796 +	{
  1.2797 +		QString fname="";
  1.2798 +		ok=true;
  1.2799 +		if (parser.parCount()>=2)
  1.2800 +			// Hey, we even have a filename
  1.2801 +			fname=parser.parString(ok,1); 
  1.2802 +		if (!ok)
  1.2803 +		{
  1.2804 +			parser.setError (Aborted,"Could not read filename");
  1.2805 +		} else
  1.2806 +		{
  1.2807 +			exportXML (fname,false);
  1.2808 +		}
  1.2809 +	/////////////////////////////////////////////////////////////////////
  1.2810 +	} else if (com=="importDir")
  1.2811 +	{
  1.2812 +		if (selection.isEmpty())
  1.2813 +		{
  1.2814 +			parser.setError (Aborted,"Nothing selected");
  1.2815 +		} else if (! selb )
  1.2816 +		{				  
  1.2817 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2818 +		} else if (parser.checkParCount(1))
  1.2819 +		{
  1.2820 +			s=parser.parString(ok,0);
  1.2821 +			if (ok) importDirInt(s);
  1.2822 +		}	
  1.2823 +	/////////////////////////////////////////////////////////////////////
  1.2824 +	} else if (com=="linkTo")
  1.2825 +	{
  1.2826 +		if (selection.isEmpty())
  1.2827 +		{
  1.2828 +			parser.setError (Aborted,"Nothing selected");
  1.2829 +		} else if ( selb)
  1.2830 +		{
  1.2831 +			if (parser.checkParCount(4))
  1.2832 +			{
  1.2833 +				// 0	selectstring of parent
  1.2834 +				// 1	num in parent (for branches)
  1.2835 +				// 2,3	x,y of mainbranch or mapcenter
  1.2836 +				s=parser.parString(ok,0);
  1.2837 +				LinkableMapObj *dst=findObjBySelect (s);
  1.2838 +				if (dst)
  1.2839 +				{	
  1.2840 +					if (typeid(*dst) == typeid(BranchObj) ) 
  1.2841 +					{
  1.2842 +						// Get number in parent
  1.2843 +						n=parser.parInt (ok,1);
  1.2844 +						if (ok)
  1.2845 +						{
  1.2846 +							selb->linkTo ((BranchObj*)(dst),n);
  1.2847 +							selection.update();
  1.2848 +						}	
  1.2849 +					} else if (typeid(*dst) == typeid(MapCenterObj) ) 
  1.2850 +					{
  1.2851 +						selb->linkTo ((BranchObj*)(dst),-1);
  1.2852 +						// Get coordinates of mainbranch
  1.2853 +						x=parser.parDouble(ok,2);
  1.2854 +						if (ok)
  1.2855 +						{
  1.2856 +							y=parser.parDouble(ok,3);
  1.2857 +							if (ok) 
  1.2858 +							{
  1.2859 +								selb->move (x,y);
  1.2860 +								selection.update();
  1.2861 +							}
  1.2862 +						}
  1.2863 +					}	
  1.2864 +				}	
  1.2865 +			}	
  1.2866 +		} else if ( selection.type() == Selection::FloatImage) 
  1.2867 +		{
  1.2868 +			if (parser.checkParCount(1))
  1.2869 +			{
  1.2870 +				// 0	selectstring of parent
  1.2871 +				s=parser.parString(ok,0);
  1.2872 +				LinkableMapObj *dst=findObjBySelect (s);
  1.2873 +				if (dst)
  1.2874 +				{	
  1.2875 +					if (typeid(*dst) == typeid(BranchObj) ||
  1.2876 +						typeid(*dst) == typeid(MapCenterObj)) 
  1.2877 +						linkFloatImageTo (getSelectString(dst));
  1.2878 +				} else	
  1.2879 +					parser.setError (Aborted,"Destination is not a branch");
  1.2880 +			}		
  1.2881 +		} else
  1.2882 +			parser.setError (Aborted,"Type of selection is not a floatimage or branch");
  1.2883 +	/////////////////////////////////////////////////////////////////////
  1.2884 +	} else if (com=="loadImage")
  1.2885 +	{
  1.2886 +		if (selection.isEmpty())
  1.2887 +		{
  1.2888 +			parser.setError (Aborted,"Nothing selected");
  1.2889 +		} else if (! selb )
  1.2890 +		{				  
  1.2891 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2892 +		} else if (parser.checkParCount(1))
  1.2893 +		{
  1.2894 +			s=parser.parString(ok,0);
  1.2895 +			if (ok) loadFloatImageInt (s);
  1.2896 +		}	
  1.2897 +	/////////////////////////////////////////////////////////////////////
  1.2898 +	} else if (com=="moveBranchUp")
  1.2899 +	{
  1.2900 +		if (selection.isEmpty() )
  1.2901 +		{
  1.2902 +			parser.setError (Aborted,"Nothing selected");
  1.2903 +		} else if (! selb )
  1.2904 +		{				  
  1.2905 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2906 +		} else if (parser.checkParCount(0))
  1.2907 +		{
  1.2908 +			moveBranchUp();
  1.2909 +		}	
  1.2910 +	/////////////////////////////////////////////////////////////////////
  1.2911 +	} else if (com=="moveBranchDown")
  1.2912 +	{
  1.2913 +		if (selection.isEmpty() )
  1.2914 +		{
  1.2915 +			parser.setError (Aborted,"Nothing selected");
  1.2916 +		} else if (! selb )
  1.2917 +		{				  
  1.2918 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2919 +		} else if (parser.checkParCount(0))
  1.2920 +		{
  1.2921 +			moveBranchDown();
  1.2922 +		}	
  1.2923 +	/////////////////////////////////////////////////////////////////////
  1.2924 +	} else if (com=="move")
  1.2925 +	{
  1.2926 +		if (selection.isEmpty() )
  1.2927 +		{
  1.2928 +			parser.setError (Aborted,"Nothing selected");
  1.2929 +		} else if ( selection.type()!=Selection::Branch  && 
  1.2930 +					selection.type()!=Selection::MapCenter  &&
  1.2931 +					selection.type()!=Selection::FloatImage )
  1.2932 +		{				  
  1.2933 +			parser.setError (Aborted,"Type of selection is not a branch or floatimage");
  1.2934 +		} else if (parser.checkParCount(2))
  1.2935 +		{	
  1.2936 +			x=parser.parDouble (ok,0);
  1.2937 +			if (ok)
  1.2938 +			{
  1.2939 +				y=parser.parDouble (ok,1);
  1.2940 +				if (ok) move (x,y);
  1.2941 +			}
  1.2942 +		}	
  1.2943 +	/////////////////////////////////////////////////////////////////////
  1.2944 +	} else if (com=="moveRel")
  1.2945 +	{
  1.2946 +		if (selection.isEmpty() )
  1.2947 +		{
  1.2948 +			parser.setError (Aborted,"Nothing selected");
  1.2949 +		} else if ( selection.type()!=Selection::Branch  && 
  1.2950 +					selection.type()!=Selection::MapCenter  &&
  1.2951 +					selection.type()!=Selection::FloatImage )
  1.2952 +		{				  
  1.2953 +			parser.setError (Aborted,"Type of selection is not a branch or floatimage");
  1.2954 +		} else if (parser.checkParCount(2))
  1.2955 +		{	
  1.2956 +			x=parser.parDouble (ok,0);
  1.2957 +			if (ok)
  1.2958 +			{
  1.2959 +				y=parser.parDouble (ok,1);
  1.2960 +				if (ok) moveRel (x,y);
  1.2961 +			}
  1.2962 +		}	
  1.2963 +	/////////////////////////////////////////////////////////////////////
  1.2964 +	} else if (com=="nop")
  1.2965 +	{
  1.2966 +	/////////////////////////////////////////////////////////////////////
  1.2967 +	} else if (com=="paste")
  1.2968 +	{
  1.2969 +		if (selection.isEmpty() )
  1.2970 +		{
  1.2971 +			parser.setError (Aborted,"Nothing selected");
  1.2972 +		} else if (! selb )
  1.2973 +		{				  
  1.2974 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2975 +		} else if (parser.checkParCount(1))
  1.2976 +		{	
  1.2977 +			n=parser.parInt (ok,0);
  1.2978 +			if (ok) pasteNoSave(n);
  1.2979 +		}	
  1.2980 +	/////////////////////////////////////////////////////////////////////
  1.2981 +	} else if (com=="qa")
  1.2982 +	{
  1.2983 +		if (selection.isEmpty() )
  1.2984 +		{
  1.2985 +			parser.setError (Aborted,"Nothing selected");
  1.2986 +		} else if (! selb )
  1.2987 +		{				  
  1.2988 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.2989 +		} else if (parser.checkParCount(4))
  1.2990 +		{	
  1.2991 +			QString c,u;
  1.2992 +			c=parser.parString (ok,0);
  1.2993 +			if (!ok)
  1.2994 +			{
  1.2995 +				parser.setError (Aborted,"No comment given");
  1.2996 +			} else
  1.2997 +			{
  1.2998 +				s=parser.parString (ok,1);
  1.2999 +				if (!ok)
  1.3000 +				{
  1.3001 +					parser.setError (Aborted,"First parameter is not a string");
  1.3002 +				} else
  1.3003 +				{
  1.3004 +					t=parser.parString (ok,2);
  1.3005 +					if (!ok)
  1.3006 +					{
  1.3007 +						parser.setError (Aborted,"Condition is not a string");
  1.3008 +					} else
  1.3009 +					{
  1.3010 +						u=parser.parString (ok,3);
  1.3011 +						if (!ok)
  1.3012 +						{
  1.3013 +							parser.setError (Aborted,"Third parameter is not a string");
  1.3014 +						} else
  1.3015 +						{
  1.3016 +							if (s!="heading")
  1.3017 +							{
  1.3018 +								parser.setError (Aborted,"Unknown type: "+s);
  1.3019 +							} else
  1.3020 +							{
  1.3021 +								if (! (t=="eq") ) 
  1.3022 +								{
  1.3023 +									parser.setError (Aborted,"Unknown operator: "+t);
  1.3024 +								} else
  1.3025 +								{
  1.3026 +									if (! selb    )
  1.3027 +									{
  1.3028 +										parser.setError (Aborted,"Type of selection is not a branch");
  1.3029 +									} else
  1.3030 +									{
  1.3031 +										if (selb->getHeading() == u)
  1.3032 +										{
  1.3033 +											cout << "PASSED: " << qPrintable (c)  << endl;
  1.3034 +										} else
  1.3035 +										{
  1.3036 +											cout << "FAILED: " << qPrintable (c)  << endl;
  1.3037 +										}
  1.3038 +									}
  1.3039 +								}
  1.3040 +							}
  1.3041 +						} 
  1.3042 +					} 
  1.3043 +				} 
  1.3044 +			}
  1.3045 +		}	
  1.3046 +	/////////////////////////////////////////////////////////////////////
  1.3047 +	} else if (com=="saveImage")
  1.3048 +	{
  1.3049 +		FloatImageObj *fio=selection.getFloatImage();
  1.3050 +		if (!fio)
  1.3051 +		{
  1.3052 +			parser.setError (Aborted,"Type of selection is not an image");
  1.3053 +		} else if (parser.checkParCount(2))
  1.3054 +		{
  1.3055 +			s=parser.parString(ok,0);
  1.3056 +			if (ok)
  1.3057 +			{
  1.3058 +				t=parser.parString(ok,1);
  1.3059 +				if (ok) saveFloatImageInt (fio,t,s);
  1.3060 +			}
  1.3061 +		}	
  1.3062 +	/////////////////////////////////////////////////////////////////////
  1.3063 +	} else if (com=="scroll")
  1.3064 +	{
  1.3065 +		if (selection.isEmpty() )
  1.3066 +		{
  1.3067 +			parser.setError (Aborted,"Nothing selected");
  1.3068 +		} else if (! selb )
  1.3069 +		{				  
  1.3070 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3071 +		} else if (parser.checkParCount(0))
  1.3072 +		{	
  1.3073 +			if (!scrollBranch (selb))	
  1.3074 +				parser.setError (Aborted,"Could not scroll branch");
  1.3075 +		}	
  1.3076 +	/////////////////////////////////////////////////////////////////////
  1.3077 +	} else if (com=="select")
  1.3078 +	{
  1.3079 +		if (parser.checkParCount(1))
  1.3080 +		{
  1.3081 +			s=parser.parString(ok,0);
  1.3082 +			if (ok) select (s);
  1.3083 +		}	
  1.3084 +	/////////////////////////////////////////////////////////////////////
  1.3085 +	} else if (com=="selectLastBranch")
  1.3086 +	{
  1.3087 +		if (selection.isEmpty() )
  1.3088 +		{
  1.3089 +			parser.setError (Aborted,"Nothing selected");
  1.3090 +		} else if (! selb )
  1.3091 +		{				  
  1.3092 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3093 +		} else if (parser.checkParCount(0))
  1.3094 +		{	
  1.3095 +			BranchObj *bo=selb->getLastBranch();
  1.3096 +			if (!bo)
  1.3097 +				parser.setError (Aborted,"Could not select last branch");
  1.3098 +			selectInt (bo);	
  1.3099 +				
  1.3100 +		}	
  1.3101 +	/////////////////////////////////////////////////////////////////////
  1.3102 +	} else if (com=="selectLastImage")
  1.3103 +	{
  1.3104 +		if (selection.isEmpty() )
  1.3105 +		{
  1.3106 +			parser.setError (Aborted,"Nothing selected");
  1.3107 +		} else if (! selb )
  1.3108 +		{				  
  1.3109 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3110 +		} else if (parser.checkParCount(0))
  1.3111 +		{	
  1.3112 +			FloatImageObj *fio=selb->getLastFloatImage();
  1.3113 +			if (!fio)
  1.3114 +				parser.setError (Aborted,"Could not select last image");
  1.3115 +			selectInt (fio);	
  1.3116 +				
  1.3117 +		}	
  1.3118 +	/////////////////////////////////////////////////////////////////////
  1.3119 +	} else if (com=="selectLatestAdded")
  1.3120 +	{
  1.3121 +		if (latestSelectionString.isEmpty() )
  1.3122 +		{
  1.3123 +			parser.setError (Aborted,"No latest added object");
  1.3124 +		} else
  1.3125 +		{	
  1.3126 +			if (!select (latestSelectionString))
  1.3127 +				parser.setError (Aborted,"Could not select latest added object "+latestSelectionString);
  1.3128 +		}	
  1.3129 +	/////////////////////////////////////////////////////////////////////
  1.3130 +	} else if (com=="setFrameType")
  1.3131 +	{
  1.3132 +		if ( selection.type()!=Selection::Branch && selection.type()!= Selection::MapCenter && selection.type()!=Selection::FloatImage)
  1.3133 +		{
  1.3134 +			parser.setError (Aborted,"Type of selection does not allow setting frame type");
  1.3135 +		}
  1.3136 +		else if (parser.checkParCount(1))
  1.3137 +		{
  1.3138 +			s=parser.parString(ok,0);
  1.3139 +			if (ok) setFrameType (s);
  1.3140 +		}	
  1.3141 +	/////////////////////////////////////////////////////////////////////
  1.3142 +	} else if (com=="setFramePenColor")
  1.3143 +	{
  1.3144 +		if ( selection.type()!=Selection::Branch && selection.type()!= Selection::MapCenter && selection.type()!=Selection::FloatImage)
  1.3145 +		{
  1.3146 +			parser.setError (Aborted,"Type of selection does not allow setting of pen color");
  1.3147 +		}
  1.3148 +		else if (parser.checkParCount(1))
  1.3149 +		{
  1.3150 +			QColor c=parser.parColor(ok,0);
  1.3151 +			if (ok) setFramePenColor (c);
  1.3152 +		}	
  1.3153 +	/////////////////////////////////////////////////////////////////////
  1.3154 +	} else if (com=="setFrameBrushColor")
  1.3155 +	{
  1.3156 +		if ( selection.type()!=Selection::Branch && selection.type()!= Selection::MapCenter && selection.type()!=Selection::FloatImage)
  1.3157 +		{
  1.3158 +			parser.setError (Aborted,"Type of selection does not allow setting brush color");
  1.3159 +		}
  1.3160 +		else if (parser.checkParCount(1))
  1.3161 +		{
  1.3162 +			QColor c=parser.parColor(ok,0);
  1.3163 +			if (ok) setFrameBrushColor (c);
  1.3164 +		}	
  1.3165 +	/////////////////////////////////////////////////////////////////////
  1.3166 +	} else if (com=="setFramePadding")
  1.3167 +	{
  1.3168 +		if ( selection.type()!=Selection::Branch && selection.type()!= Selection::MapCenter && selection.type()!=Selection::FloatImage)
  1.3169 +		{
  1.3170 +			parser.setError (Aborted,"Type of selection does not allow setting frame padding");
  1.3171 +		}
  1.3172 +		else if (parser.checkParCount(1))
  1.3173 +		{
  1.3174 +			n=parser.parInt(ok,0);
  1.3175 +			if (ok) setFramePadding(n);
  1.3176 +		}	
  1.3177 +	/////////////////////////////////////////////////////////////////////
  1.3178 +	} else if (com=="setFrameBorderWidth")
  1.3179 +	{
  1.3180 +		if ( selection.type()!=Selection::Branch && selection.type()!= Selection::MapCenter && selection.type()!=Selection::FloatImage)
  1.3181 +		{
  1.3182 +			parser.setError (Aborted,"Type of selection does not allow setting frame border width");
  1.3183 +		}
  1.3184 +		else if (parser.checkParCount(1))
  1.3185 +		{
  1.3186 +			n=parser.parInt(ok,0);
  1.3187 +			if (ok) setFrameBorderWidth (n);
  1.3188 +		}	
  1.3189 +	/////////////////////////////////////////////////////////////////////
  1.3190 +	} else if (com=="setMapAuthor")
  1.3191 +	{
  1.3192 +		if (parser.checkParCount(1))
  1.3193 +		{
  1.3194 +			s=parser.parString(ok,0);
  1.3195 +			if (ok) setAuthor (s);
  1.3196 +		}	
  1.3197 +	/////////////////////////////////////////////////////////////////////
  1.3198 +	} else if (com=="setMapComment")
  1.3199 +	{
  1.3200 +		if (parser.checkParCount(1))
  1.3201 +		{
  1.3202 +			s=parser.parString(ok,0);
  1.3203 +			if (ok) setComment(s);
  1.3204 +		}	
  1.3205 +	/////////////////////////////////////////////////////////////////////
  1.3206 +	} else if (com=="setMapBackgroundColor")
  1.3207 +	{
  1.3208 +		if (selection.isEmpty() )
  1.3209 +		{
  1.3210 +			parser.setError (Aborted,"Nothing selected");
  1.3211 +		} else if (! selection.getBranch() )
  1.3212 +		{				  
  1.3213 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3214 +		} else if (parser.checkParCount(1))
  1.3215 +		{
  1.3216 +			QColor c=parser.parColor (ok,0);
  1.3217 +			if (ok) setMapBackgroundColor (c);
  1.3218 +		}	
  1.3219 +	/////////////////////////////////////////////////////////////////////
  1.3220 +	} else if (com=="setMapDefLinkColor")
  1.3221 +	{
  1.3222 +		if (selection.isEmpty() )
  1.3223 +		{
  1.3224 +			parser.setError (Aborted,"Nothing selected");
  1.3225 +		} else if (! selb )
  1.3226 +		{				  
  1.3227 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3228 +		} else if (parser.checkParCount(1))
  1.3229 +		{
  1.3230 +			QColor c=parser.parColor (ok,0);
  1.3231 +			if (ok) setMapDefLinkColor (c);
  1.3232 +		}	
  1.3233 +	/////////////////////////////////////////////////////////////////////
  1.3234 +	} else if (com=="setMapLinkStyle")
  1.3235 +	{
  1.3236 +		if (parser.checkParCount(1))
  1.3237 +		{
  1.3238 +			s=parser.parString (ok,0);
  1.3239 +			if (ok) setMapLinkStyle(s);
  1.3240 +		}	
  1.3241 +	/////////////////////////////////////////////////////////////////////
  1.3242 +	} else if (com=="setHeading")
  1.3243 +	{
  1.3244 +		if (selection.isEmpty() )
  1.3245 +		{
  1.3246 +			parser.setError (Aborted,"Nothing selected");
  1.3247 +		} else if (! selb )
  1.3248 +		{				  
  1.3249 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3250 +		} else if (parser.checkParCount(1))
  1.3251 +		{
  1.3252 +			s=parser.parString (ok,0);
  1.3253 +			if (ok) 
  1.3254 +				setHeading (s);
  1.3255 +		}	
  1.3256 +	/////////////////////////////////////////////////////////////////////
  1.3257 +	} else if (com=="setHideExport")
  1.3258 +	{
  1.3259 +		if (selection.isEmpty() )
  1.3260 +		{
  1.3261 +			parser.setError (Aborted,"Nothing selected");
  1.3262 +		} else if (selection.type()!=Selection::Branch && selection.type() != Selection::MapCenter &&selection.type()!=Selection::FloatImage)
  1.3263 +		{				  
  1.3264 +			parser.setError (Aborted,"Type of selection is not a branch or floatimage");
  1.3265 +		} else if (parser.checkParCount(1))
  1.3266 +		{
  1.3267 +			b=parser.parBool(ok,0);
  1.3268 +			if (ok) setHideExport (b);
  1.3269 +		}
  1.3270 +	/////////////////////////////////////////////////////////////////////
  1.3271 +	} else if (com=="setIncludeImagesHorizontally")
  1.3272 +	{ 
  1.3273 +		if (selection.isEmpty() )
  1.3274 +		{
  1.3275 +			parser.setError (Aborted,"Nothing selected");
  1.3276 +		} else if (! selb)
  1.3277 +		{				  
  1.3278 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3279 +		} else if (parser.checkParCount(1))
  1.3280 +		{
  1.3281 +			b=parser.parBool(ok,0);
  1.3282 +			if (ok) setIncludeImagesHor(b);
  1.3283 +		}
  1.3284 +	/////////////////////////////////////////////////////////////////////
  1.3285 +	} else if (com=="setIncludeImagesVertically")
  1.3286 +	{
  1.3287 +		if (selection.isEmpty() )
  1.3288 +		{
  1.3289 +			parser.setError (Aborted,"Nothing selected");
  1.3290 +		} else if (! selb)
  1.3291 +		{				  
  1.3292 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3293 +		} else if (parser.checkParCount(1))
  1.3294 +		{
  1.3295 +			b=parser.parBool(ok,0);
  1.3296 +			if (ok) setIncludeImagesVer(b);
  1.3297 +		}
  1.3298 +	/////////////////////////////////////////////////////////////////////
  1.3299 +	} else if (com=="setHideLinkUnselected")
  1.3300 +	{
  1.3301 +		if (selection.isEmpty() )
  1.3302 +		{
  1.3303 +			parser.setError (Aborted,"Nothing selected");
  1.3304 +		} else if ( selection.type()!=Selection::Branch && selection.type()!= Selection::MapCenter && selection.type()!=Selection::FloatImage)
  1.3305 +		{				  
  1.3306 +			parser.setError (Aborted,"Type of selection does not allow hiding the link");
  1.3307 +		} else if (parser.checkParCount(1))
  1.3308 +		{
  1.3309 +			b=parser.parBool(ok,0);
  1.3310 +			if (ok) setHideLinkUnselected(b);
  1.3311 +		}
  1.3312 +	/////////////////////////////////////////////////////////////////////
  1.3313 +	} else if (com=="setSelectionColor")
  1.3314 +	{
  1.3315 +		if (parser.checkParCount(1))
  1.3316 +		{
  1.3317 +			QColor c=parser.parColor (ok,0);
  1.3318 +			if (ok) setSelectionColorInt (c);
  1.3319 +		}	
  1.3320 +	/////////////////////////////////////////////////////////////////////
  1.3321 +	} else if (com=="setURL")
  1.3322 +	{
  1.3323 +		if (selection.isEmpty() )
  1.3324 +		{
  1.3325 +			parser.setError (Aborted,"Nothing selected");
  1.3326 +		} else if (! selb )
  1.3327 +		{				  
  1.3328 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3329 +		} else if (parser.checkParCount(1))
  1.3330 +		{
  1.3331 +			s=parser.parString (ok,0);
  1.3332 +			if (ok) setURL(s);
  1.3333 +		}	
  1.3334 +	/////////////////////////////////////////////////////////////////////
  1.3335 +	} else if (com=="setVymLink")
  1.3336 +	{
  1.3337 +		if (selection.isEmpty() )
  1.3338 +		{
  1.3339 +			parser.setError (Aborted,"Nothing selected");
  1.3340 +		} else if (! selb )
  1.3341 +		{				  
  1.3342 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3343 +		} else if (parser.checkParCount(1))
  1.3344 +		{
  1.3345 +			s=parser.parString (ok,0);
  1.3346 +			if (ok) setVymLink(s);
  1.3347 +		}	
  1.3348 +	}
  1.3349 +	/////////////////////////////////////////////////////////////////////
  1.3350 +	else if (com=="setFlag")
  1.3351 +	{
  1.3352 +		if (selection.isEmpty() )
  1.3353 +		{
  1.3354 +			parser.setError (Aborted,"Nothing selected");
  1.3355 +		} else if (! selb )
  1.3356 +		{				  
  1.3357 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3358 +		} else if (parser.checkParCount(1))
  1.3359 +		{
  1.3360 +			s=parser.parString(ok,0);
  1.3361 +			if (ok) 
  1.3362 +			{
  1.3363 +				selb->activateStandardFlag(s);
  1.3364 +				selb->updateFlagsToolbar();
  1.3365 +			}	
  1.3366 +		}
  1.3367 +	/////////////////////////////////////////////////////////////////////
  1.3368 +	} else if (com=="setFrameType")
  1.3369 +	{
  1.3370 +		if (selection.isEmpty() )
  1.3371 +		{
  1.3372 +			parser.setError (Aborted,"Nothing selected");
  1.3373 +		} else if (! selb )
  1.3374 +		{				  
  1.3375 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3376 +		} else if (parser.checkParCount(1))
  1.3377 +		{
  1.3378 +			s=parser.parString(ok,0);
  1.3379 +			if (ok) 
  1.3380 +				setFrameType (s);
  1.3381 +		}
  1.3382 +	/////////////////////////////////////////////////////////////////////
  1.3383 +	} else if (com=="sortChildren")
  1.3384 +	{
  1.3385 +		if (selection.isEmpty() )
  1.3386 +		{
  1.3387 +			parser.setError (Aborted,"Nothing selected");
  1.3388 +		} else if (! selb )
  1.3389 +		{				  
  1.3390 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3391 +		} else if (parser.checkParCount(0))
  1.3392 +		{
  1.3393 +			sortChildren();
  1.3394 +		}
  1.3395 +	/////////////////////////////////////////////////////////////////////
  1.3396 +	} else if (com=="toggleFlag")
  1.3397 +	{
  1.3398 +		if (selection.isEmpty() )
  1.3399 +		{
  1.3400 +			parser.setError (Aborted,"Nothing selected");
  1.3401 +		} else if (! selb )
  1.3402 +		{				  
  1.3403 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3404 +		} else if (parser.checkParCount(1))
  1.3405 +		{
  1.3406 +			s=parser.parString(ok,0);
  1.3407 +			if (ok) 
  1.3408 +			{
  1.3409 +				selb->toggleStandardFlag(s);	
  1.3410 +				selb->updateFlagsToolbar();
  1.3411 +			}	
  1.3412 +		}
  1.3413 +	/////////////////////////////////////////////////////////////////////
  1.3414 +	} else if (com=="unscroll")
  1.3415 +	{
  1.3416 +		if (selection.isEmpty() )
  1.3417 +		{
  1.3418 +			parser.setError (Aborted,"Nothing selected");
  1.3419 +		} else if (! selb )
  1.3420 +		{				  
  1.3421 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3422 +		} else if (parser.checkParCount(0))
  1.3423 +		{	
  1.3424 +			if (!unscrollBranch (selb))	
  1.3425 +				parser.setError (Aborted,"Could not unscroll branch");
  1.3426 +		}	
  1.3427 +	/////////////////////////////////////////////////////////////////////
  1.3428 +	} else if (com=="unscrollChildren")
  1.3429 +	{
  1.3430 +		if (selection.isEmpty() )
  1.3431 +		{
  1.3432 +			parser.setError (Aborted,"Nothing selected");
  1.3433 +		} else if (! selb )
  1.3434 +		{				  
  1.3435 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3436 +		} else if (parser.checkParCount(0))
  1.3437 +		{	
  1.3438 +			unscrollChildren ();
  1.3439 +		}	
  1.3440 +	/////////////////////////////////////////////////////////////////////
  1.3441 +	} else if (com=="unsetFlag")
  1.3442 +	{
  1.3443 +		if (selection.isEmpty() )
  1.3444 +		{
  1.3445 +			parser.setError (Aborted,"Nothing selected");
  1.3446 +		} else if (! selb )
  1.3447 +		{				  
  1.3448 +			parser.setError (Aborted,"Type of selection is not a branch");
  1.3449 +		} else if (parser.checkParCount(1))
  1.3450 +		{
  1.3451 +			s=parser.parString(ok,0);
  1.3452 +			if (ok) 
  1.3453 +			{
  1.3454 +				selb->deactivateStandardFlag(s);
  1.3455 +				selb->updateFlagsToolbar();
  1.3456 +			}	
  1.3457 +		}
  1.3458 +	} else
  1.3459 +		parser.setError (Aborted,"Unknown command");
  1.3460 +
  1.3461 +	// Any errors?
  1.3462 +	if (parser.errorLevel()==NoError)
  1.3463 +	{
  1.3464 +		// setChanged();  FIXME should not be called e.g. for export?!
  1.3465 +		reposition();
  1.3466 +	}	
  1.3467 +	else	
  1.3468 +	{
  1.3469 +		// TODO Error handling
  1.3470 +		qWarning("VymModel::parseAtom: Error!");
  1.3471 +		qWarning(parser.errorMessage());
  1.3472 +	} 
  1.3473 +}
  1.3474 +
  1.3475 +void VymModel::runScript (QString script)
  1.3476 +{
  1.3477 +	parser.setScript (script);
  1.3478 +	parser.runScript();
  1.3479 +	while (parser.next() ) 
  1.3480 +		parseAtom(parser.getAtom());
  1.3481 +}
  1.3482 +
  1.3483 +void VymModel::setExportMode (bool b)
  1.3484 +{
  1.3485 +	// should be called before and after exports
  1.3486 +	// depending on the settings
  1.3487 +	if (b && settings.value("/export/useHideExport","true")=="true")
  1.3488 +		setHideTmpMode (HideExport);
  1.3489 +	else	
  1.3490 +		setHideTmpMode (HideNone);
  1.3491 +}
  1.3492 +
  1.3493 +void VymModel::exportImage(QString fname, bool askName, QString format)
  1.3494 +{
  1.3495 +	if (fname=="")
  1.3496 +	{
  1.3497 +		fname=getMapName()+".png";
  1.3498 +		format="PNG";
  1.3499 +	} 	
  1.3500 +
  1.3501 +	if (askName)
  1.3502 +	{
  1.3503 +		QStringList fl;
  1.3504 +		QFileDialog *fd=new QFileDialog (NULL);
  1.3505 +		fd->setCaption (tr("Export map as image"));
  1.3506 +		fd->setDirectory (lastImageDir);
  1.3507 +		fd->setFileMode(QFileDialog::AnyFile);
  1.3508 +		fd->setFilters  (imageIO.getFilters() );
  1.3509 +		if (fd->exec())
  1.3510 +		{
  1.3511 +			fl=fd->selectedFiles();
  1.3512 +			fname=fl.first();
  1.3513 +			format=imageIO.getType(fd->selectedFilter());
  1.3514 +		} 
  1.3515 +	}
  1.3516 +
  1.3517 +	setExportMode (true);
  1.3518 +	QPixmap pix (getPixmap());
  1.3519 +	pix.save(fname, format);
  1.3520 +	setExportMode (false);
  1.3521 +}
  1.3522 +
  1.3523 +
  1.3524 +void VymModel::exportXML(QString dir, bool askForName)
  1.3525 +{
  1.3526 +	if (askForName)
  1.3527 +	{
  1.3528 +		dir=browseDirectory(NULL,tr("Export XML to directory"));
  1.3529 +		if (dir =="" && !reallyWriteDirectory(dir) )
  1.3530 +		return;
  1.3531 +	}
  1.3532 +
  1.3533 +	// Hide stuff during export, if settings want this
  1.3534 +	setExportMode (true);
  1.3535 +
  1.3536 +	// Create subdirectories
  1.3537 +	makeSubDirs (dir);
  1.3538 +
  1.3539 +	// write to directory
  1.3540 +	QString saveFile=saveToDir (dir,mapName+"-",true,getTotalBBox().topLeft() ,NULL);
  1.3541 +	QFile file;
  1.3542 +
  1.3543 +	file.setName ( dir + "/"+mapName+".xml");
  1.3544 +	if ( !file.open( QIODevice::WriteOnly ) )
  1.3545 +	{
  1.3546 +		// This should neverever happen
  1.3547 +		QMessageBox::critical (0,tr("Critical Export Error"),tr("VymModel::exportXML couldn't open %1").arg(file.name()));
  1.3548 +		return;
  1.3549 +	}	
  1.3550 +
  1.3551 +	// Write it finally, and write in UTF8, no matter what 
  1.3552 +	QTextStream ts( &file );
  1.3553 +	ts.setEncoding (QTextStream::UnicodeUTF8);
  1.3554 +	ts << saveFile;
  1.3555 +	file.close();
  1.3556 +
  1.3557 +	// Now write image, too
  1.3558 +	exportImage (dir+"/images/"+mapName+".png",false,"PNG");
  1.3559 +
  1.3560 +	setExportMode (false);
  1.3561 +}
  1.3562 +
  1.3563 +void VymModel::exportASCII(QString fname,bool askName)
  1.3564 +{
  1.3565 +	ExportASCII ex;
  1.3566 +	ex.setModel (this);
  1.3567 +	if (fname=="") 
  1.3568 +		ex.setFile (mapName+".txt");	
  1.3569 +	else
  1.3570 +		ex.setFile (fname);
  1.3571 +
  1.3572 +	if (askName)
  1.3573 +	{
  1.3574 +		//ex.addFilter ("TXT (*.txt)");
  1.3575 +		ex.setDir(lastImageDir);
  1.3576 +		//ex.setCaption(vymName+ " -" +tr("Export as ASCII")+" "+tr("(still experimental)"));
  1.3577 +		ex.execDialog() ; 
  1.3578 +	} 
  1.3579 +	if (!ex.canceled())
  1.3580 +	{
  1.3581 +		setExportMode(true);
  1.3582 +		ex.doExport();
  1.3583 +		setExportMode(false);
  1.3584 +	}
  1.3585 +}
  1.3586 +
  1.3587 +void VymModel::exportXHTML (const QString &dir, bool askForName)
  1.3588 +{
  1.3589 +			ExportXHTMLDialog dia(NULL);
  1.3590 +			dia.setFilePath (filePath );
  1.3591 +			dia.setMapName (mapName );
  1.3592 +			dia.readSettings();
  1.3593 +			if (dir!="") dia.setDir (dir);
  1.3594 +
  1.3595 +			bool ok=true;
  1.3596 +			
  1.3597 +			if (askForName)
  1.3598 +			{
  1.3599 +				if (dia.exec()!=QDialog::Accepted) 
  1.3600 +					ok=false;
  1.3601 +				else	
  1.3602 +				{
  1.3603 +					QDir d (dia.getDir());
  1.3604 +					// Check, if warnings should be used before overwriting
  1.3605 +					// the output directory
  1.3606 +					if (d.exists() && d.count()>0)
  1.3607 +					{
  1.3608 +						WarningDialog warn;
  1.3609 +						warn.showCancelButton (true);
  1.3610 +						warn.setText(QString(
  1.3611 +							"The directory %1 is not empty.\n"
  1.3612 +							"Do you risk to overwrite some of its contents?").arg(d.path() ));
  1.3613 +						warn.setCaption("Warning: Directory not empty");
  1.3614 +						warn.setShowAgainName("mainwindow/overwrite-dir-xhtml");
  1.3615 +
  1.3616 +						if (warn.exec()!=QDialog::Accepted) ok=false;
  1.3617 +					}
  1.3618 +				}	
  1.3619 +			}
  1.3620 +
  1.3621 +			if (ok)
  1.3622 +			{
  1.3623 +				exportXML (dia.getDir(),false );
  1.3624 +				dia.doExport(mapName );
  1.3625 +				//if (dia.hasChanged()) setChanged();
  1.3626 +			}
  1.3627 +}
  1.3628 +
  1.3629 +void VymModel::exportOOPresentation(const QString &fn, const QString &cf)
  1.3630 +{
  1.3631 +	ExportOO ex;
  1.3632 +	ex.setFile (fn);
  1.3633 +	ex.setModel (this);
  1.3634 +	if (ex.setConfigFile(cf)) 
  1.3635 +	{
  1.3636 +		setExportMode (true);
  1.3637 +		ex.exportPresentation();
  1.3638 +		setExportMode (false);
  1.3639 +	}
  1.3640 +}
  1.3641 +
  1.3642 +
  1.3643 +
  1.3644  
  1.3645  //////////////////////////////////////////////
  1.3646  // View related
  1.3647  //////////////////////////////////////////////
  1.3648  
  1.3649 +void VymModel::registerEditor(QWidget *)
  1.3650 +{
  1.3651 +}
  1.3652 +
  1.3653 +void VymModel::unregisterEditor(QWidget *)
  1.3654 +{
  1.3655 +}
  1.3656 +
  1.3657 +void VymModel::updateNoteFlag()
  1.3658 +{
  1.3659 +	setChanged();
  1.3660 +	BranchObj *bo=selection.getBranch();
  1.3661 +	if (bo) 
  1.3662 +	{
  1.3663 +		bo->updateNoteFlag();
  1.3664 +		mainWindow->updateActions();
  1.3665 +	}	
  1.3666 +}
  1.3667 +
  1.3668  void VymModel::updateRelPositions()
  1.3669  {
  1.3670  	for (int i=0; i<mapCenters.count(); i++)
  1.3671 @@ -284,6 +3766,261 @@
  1.3672  	}
  1.3673  }
  1.3674  
  1.3675 +QPixmap VymModel::getPixmap()
  1.3676 +{
  1.3677 +	QRectF mapRect=getTotalBBox();
  1.3678 +	QPixmap pix((int)mapRect.width()+2,(int)mapRect.height()+1);
  1.3679 +	QPainter pp (&pix);
  1.3680 +	
  1.3681 +	pp.setRenderHints(mapEditor->renderHints());
  1.3682 +
  1.3683 +	// Don't print the visualisation of selection
  1.3684 +	selection.unselect();
  1.3685 +
  1.3686 +	mapScene->render (	&pp, 
  1.3687 +		QRectF(0,0,mapRect.width()+2,mapRect.height()+2),
  1.3688 +		QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height() ));
  1.3689 +
  1.3690 +	// Restore selection
  1.3691 +	selection.reselect();
  1.3692 +	
  1.3693 +	return pix;
  1.3694 +}
  1.3695 +
  1.3696 +
  1.3697 +void VymModel::setMapLinkStyle (const QString & s)
  1.3698 +{
  1.3699 +	QString snow;
  1.3700 +	if (linkstyle==LinkableMapObj::Line)
  1.3701 +		snow="StyleLine";
  1.3702 +	else if (linkstyle==LinkableMapObj::Parabel)
  1.3703 +		snow="StyleParabel";
  1.3704 +	else if (linkstyle==LinkableMapObj::PolyLine)
  1.3705 +		snow="StylePolyLine";
  1.3706 +	else if (linkstyle==LinkableMapObj::PolyParabel)
  1.3707 +		snow="StyleParabel";
  1.3708 +
  1.3709 +	saveState (
  1.3710 +		QString("setMapLinkStyle (\"%1\")").arg(s),
  1.3711 +		QString("setMapLinkStyle (\"%1\")").arg(snow),
  1.3712 +		QString("Set map link style (\"%1\")").arg(s)
  1.3713 +	);	
  1.3714 +
  1.3715 +	if (s=="StyleLine")
  1.3716 +		linkstyle=LinkableMapObj::Line;
  1.3717 +	else if (s=="StyleParabel")
  1.3718 +		linkstyle=LinkableMapObj::Parabel;
  1.3719 +	else if (s=="StylePolyLine")
  1.3720 +		linkstyle=LinkableMapObj::PolyLine;
  1.3721 +	else	
  1.3722 +		linkstyle=LinkableMapObj::PolyParabel;
  1.3723 +
  1.3724 +	BranchObj *bo;
  1.3725 +	bo=first();
  1.3726 +	bo=next(bo);
  1.3727 +	while (bo) 
  1.3728 +	{
  1.3729 +		bo->setLinkStyle(bo->getDefLinkStyle());
  1.3730 +		bo=next(bo);
  1.3731 +	}
  1.3732 +	reposition();
  1.3733 +}
  1.3734 +
  1.3735 +LinkableMapObj::Style VymModel::getMapLinkStyle ()
  1.3736 +{
  1.3737 +	return linkstyle;
  1.3738 +}	
  1.3739 +
  1.3740 +void VymModel::setMapDefLinkColor(QColor col)
  1.3741 +{
  1.3742 +	if ( !col.isValid() ) return;
  1.3743 +	saveState (
  1.3744 +		QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
  1.3745 +		QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
  1.3746 +		QString("Set map link color to %1").arg(col.name())
  1.3747 +	);
  1.3748 +
  1.3749 +	defLinkColor=col;
  1.3750 +	BranchObj *bo;
  1.3751 +	bo=first();
  1.3752 +	while (bo) 
  1.3753 +	{
  1.3754 +		bo->setLinkColor();
  1.3755 +		bo=next(bo);
  1.3756 +	}
  1.3757 +	updateActions();
  1.3758 +}
  1.3759 +
  1.3760 +void VymModel::setMapLinkColorHintInt()
  1.3761 +{
  1.3762 +	// called from setMapLinkColorHint(lch) or at end of parse
  1.3763 +	BranchObj *bo;
  1.3764 +	bo=first();
  1.3765 +	while (bo) 
  1.3766 +	{
  1.3767 +		bo->setLinkColor();
  1.3768 +		bo=next(bo);
  1.3769 +	}
  1.3770 +}
  1.3771 +
  1.3772 +void VymModel::setMapLinkColorHint(LinkableMapObj::ColorHint lch)
  1.3773 +{
  1.3774 +	linkcolorhint=lch;
  1.3775 +	setMapLinkColorHintInt();
  1.3776 +}
  1.3777 +
  1.3778 +void VymModel::toggleMapLinkColorHint()
  1.3779 +{
  1.3780 +	if (linkcolorhint==LinkableMapObj::HeadingColor)
  1.3781 +		linkcolorhint=LinkableMapObj::DefaultColor;
  1.3782 +	else	
  1.3783 +		linkcolorhint=LinkableMapObj::HeadingColor;
  1.3784 +	BranchObj *bo;
  1.3785 +	bo=first();
  1.3786 +	while (bo) 
  1.3787 +	{
  1.3788 +		bo->setLinkColor();
  1.3789 +		bo=next(bo);
  1.3790 +	}
  1.3791 +}
  1.3792 +
  1.3793 +void VymModel::selectMapBackgroundImage ()
  1.3794 +{
  1.3795 +	Q3FileDialog *fd=new Q3FileDialog( NULL);
  1.3796 +	fd->setMode (Q3FileDialog::ExistingFile);
  1.3797 +	fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
  1.3798 +	ImagePreview *p =new ImagePreview (fd);
  1.3799 +	fd->setContentsPreviewEnabled( TRUE );
  1.3800 +	fd->setContentsPreview( p, p );
  1.3801 +	fd->setPreviewMode( Q3FileDialog::Contents );
  1.3802 +	fd->setCaption(vymName+" - " +tr("Load background image"));
  1.3803 +	fd->setDir (lastImageDir);
  1.3804 +	fd->show();
  1.3805 +
  1.3806 +	if ( fd->exec() == QDialog::Accepted )
  1.3807 +	{
  1.3808 +		// TODO selectMapBackgroundImg in QT4 use:	lastImageDir=fd->directory();
  1.3809 +		lastImageDir=QDir (fd->dirPath());
  1.3810 +		setMapBackgroundImage (fd->selectedFile());
  1.3811 +	}
  1.3812 +}	
  1.3813 +
  1.3814 +void VymModel::setMapBackgroundImage (const QString &fn)	//FIXME missing savestate
  1.3815 +{
  1.3816 +	QColor oldcol=mapScene->backgroundBrush().color();
  1.3817 +	/*
  1.3818 +	saveState(
  1.3819 +		selection,
  1.3820 +		QString ("setMapBackgroundImage (%1)").arg(oldcol.name()),
  1.3821 +		selection,
  1.3822 +		QString ("setMapBackgroundImage (%1)").arg(col.name()),
  1.3823 +		QString("Set background color of map to %1").arg(col.name()));
  1.3824 +	*/	
  1.3825 +	QBrush brush;
  1.3826 +	brush.setTextureImage (QPixmap (fn));
  1.3827 +	mapScene->setBackgroundBrush(brush);
  1.3828 +}
  1.3829 +
  1.3830 +void VymModel::selectMapBackgroundColor()
  1.3831 +{
  1.3832 +	QColor col = QColorDialog::getColor( mapScene->backgroundBrush().color(), NULL);
  1.3833 +	if ( !col.isValid() ) return;
  1.3834 +	setMapBackgroundColor( col );
  1.3835 +}
  1.3836 +
  1.3837 +
  1.3838 +void VymModel::setMapBackgroundColor(QColor col)
  1.3839 +{
  1.3840 +	QColor oldcol=mapScene->backgroundBrush().color();
  1.3841 +	saveState(
  1.3842 +		QString ("setMapBackgroundColor (\"%1\")").arg(oldcol.name()),
  1.3843 +		QString ("setMapBackgroundColor (\"%1\")").arg(col.name()),
  1.3844 +		QString("Set background color of map to %1").arg(col.name()));
  1.3845 +	mapScene->setBackgroundBrush(col);
  1.3846 +}
  1.3847 +
  1.3848 +QColor VymModel::getMapBackgroundColor()
  1.3849 +{
  1.3850 +    return mapScene->backgroundBrush().color();
  1.3851 +}
  1.3852 +
  1.3853 +
  1.3854 +LinkableMapObj::ColorHint VymModel::getMapLinkColorHint()
  1.3855 +{
  1.3856 +	return linkcolorhint;
  1.3857 +}
  1.3858 +
  1.3859 +QColor VymModel::getMapDefLinkColor()
  1.3860 +{
  1.3861 +	return defLinkColor;
  1.3862 +}
  1.3863 +
  1.3864 +void VymModel::setMapDefXLinkColor(QColor col)
  1.3865 +{
  1.3866 +	defXLinkColor=col;
  1.3867 +}
  1.3868 +
  1.3869 +QColor VymModel::getMapDefXLinkColor()
  1.3870 +{
  1.3871 +	return defXLinkColor;
  1.3872 +}
  1.3873 +
  1.3874 +void VymModel::setMapDefXLinkWidth (int w)
  1.3875 +{
  1.3876 +	defXLinkWidth=w;
  1.3877 +}
  1.3878 +
  1.3879 +int VymModel::getMapDefXLinkWidth()
  1.3880 +{
  1.3881 +	return defXLinkWidth;
  1.3882 +}
  1.3883 +
  1.3884 +void VymModel::move(const double &x, const double &y)
  1.3885 +{
  1.3886 +	LinkableMapObj *sel=selection.single();
  1.3887 +	if (sel)
  1.3888 +	{
  1.3889 +        QPointF ap(sel->getAbsPos());
  1.3890 +        QPointF to(x, y);
  1.3891 +        if (ap != to)
  1.3892 +        {
  1.3893 +            QString ps=qpointfToString(ap);
  1.3894 +            QString s=selection.getSelectString();
  1.3895 +            saveState(
  1.3896 +                s, "move "+ps, 
  1.3897 +                s, "move "+qpointfToString(to), 
  1.3898 +                QString("Move %1 to %2").arg(getObjectName(sel)).arg(ps));
  1.3899 +            sel->move(x,y);
  1.3900 +            reposition();
  1.3901 +            selection.update();
  1.3902 +        }
  1.3903 +	}
  1.3904 +}
  1.3905 +
  1.3906 +void VymModel::moveRel (const double &x, const double &y)
  1.3907 +{
  1.3908 +	LinkableMapObj *sel=selection.single();
  1.3909 +	if (sel)
  1.3910 +	{
  1.3911 +        QPointF rp(sel->getRelPos());
  1.3912 +        QPointF to(x, y);
  1.3913 +        if (rp != to)
  1.3914 +        {
  1.3915 +            QString ps=qpointfToString (sel->getRelPos());
  1.3916 +            QString s=getSelectString(sel);
  1.3917 +            saveState(
  1.3918 +                s, "moveRel "+ps, 
  1.3919 +                s, "moveRel "+qpointfToString(to), 
  1.3920 +                QString("Move %1 to relative position %2").arg(getObjectName(sel)).arg(ps));
  1.3921 +            ((OrnamentedObj*)sel)->move2RelPos (x,y);
  1.3922 +            reposition();
  1.3923 +            sel->updateLink();
  1.3924 +            selection.update();
  1.3925 +        }
  1.3926 +	}
  1.3927 +}
  1.3928 +
  1.3929 +
  1.3930  void VymModel::animate()
  1.3931  {
  1.3932  	animationTimer->stop();
  1.3933 @@ -294,7 +4031,11 @@
  1.3934  		bo=(BranchObj*)animObjList.at(i);
  1.3935  		if (!bo->animate())
  1.3936  		{
  1.3937 -			if (i>=0) animObjList.removeAt(i);
  1.3938 +			if (i>=0) 
  1.3939 +			{	
  1.3940 +				animObjList.removeAt(i);
  1.3941 +				i--;
  1.3942 +			}
  1.3943  		}
  1.3944  		bo->reposition();
  1.3945  		i++;
  1.3946 @@ -322,26 +4063,640 @@
  1.3947  	}
  1.3948  }
  1.3949  
  1.3950 +void VymModel::sendSelection()
  1.3951 +{
  1.3952 +	if (netstate!=Server) return;
  1.3953 +	sendData (QString("select (\"%1\")").arg(selection.getSelectString()) );
  1.3954 +}
  1.3955 +
  1.3956 +void VymModel::newServer()
  1.3957 +{
  1.3958 +	port=54321;
  1.3959 +	sendCounter=0;
  1.3960 +    tcpServer = new QTcpServer(this);
  1.3961 +    if (!tcpServer->listen(QHostAddress::Any,port)) {
  1.3962 +        QMessageBox::critical(NULL, "vym server",
  1.3963 +                              QString("Unable to start the server: %1.").arg(tcpServer->errorString()));
  1.3964 +        //FIXME needed? we are no widget any longer... close();
  1.3965 +        return;
  1.3966 +    }
  1.3967 +	connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newClient()));
  1.3968 +	netstate=Server;
  1.3969 +	cout<<"Server is running on port "<<tcpServer->serverPort()<<endl;
  1.3970 +}
  1.3971 +
  1.3972 +void VymModel::connectToServer()
  1.3973 +{
  1.3974 +	port=54321;
  1.3975 +	server="salam.suse.de";
  1.3976 +	server="localhost";
  1.3977 +	clientSocket = new QTcpSocket (this);
  1.3978 +	clientSocket->abort();
  1.3979 +    clientSocket->connectToHost(server ,port);
  1.3980 +	connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readData()));
  1.3981 +    connect(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
  1.3982 +            this, SLOT(displayNetworkError(QAbstractSocket::SocketError)));
  1.3983 +	netstate=Client;		
  1.3984 +	cout<<"connected to "<<qPrintable (server)<<" port "<<port<<endl;
  1.3985 +
  1.3986 +	
  1.3987 +}
  1.3988 +
  1.3989 +void VymModel::newClient()
  1.3990 +{
  1.3991 +    QTcpSocket *newClient = tcpServer->nextPendingConnection();
  1.3992 +    connect(newClient, SIGNAL(disconnected()),
  1.3993 +            newClient, SLOT(deleteLater()));
  1.3994 +
  1.3995 +	cout <<"ME::newClient  at "<<qPrintable( newClient->peerAddress().toString() )<<endl;
  1.3996 +
  1.3997 +	clientList.append (newClient);
  1.3998 +}
  1.3999 +
  1.4000 +
  1.4001 +void VymModel::sendData(const QString &s)
  1.4002 +{
  1.4003 +	if (clientList.size()==0) return;
  1.4004 +
  1.4005 +	// Create bytearray to send
  1.4006 +	QByteArray block;
  1.4007 +    QDataStream out(&block, QIODevice::WriteOnly);
  1.4008 +    out.setVersion(QDataStream::Qt_4_0);
  1.4009 +
  1.4010 +	// Reserve some space for blocksize
  1.4011 +    out << (quint16)0;
  1.4012 +
  1.4013 +	// Write sendCounter
  1.4014 +    out << sendCounter++;
  1.4015 +
  1.4016 +	// Write data
  1.4017 +    out << s;
  1.4018 +
  1.4019 +	// Go back and write blocksize so far
  1.4020 +    out.device()->seek(0);
  1.4021 +    quint16 bs=(quint16)(block.size() - 2*sizeof(quint16));
  1.4022 +	out << bs;
  1.4023 +
  1.4024 +	if (debug)
  1.4025 +		cout << "ME::sendData  bs="<<bs<<"  counter="<<sendCounter<<"  s="<<qPrintable(s)<<endl;
  1.4026 +
  1.4027 +	for (int i=0; i<clientList.size(); ++i)
  1.4028 +	{
  1.4029 +		//cout << "Sending \""<<qPrintable (s)<<"\" to "<<qPrintable (clientList.at(i)->peerAddress().toString())<<endl;
  1.4030 +		clientList.at(i)->write (block);
  1.4031 +	}
  1.4032 +}
  1.4033 +
  1.4034 +void VymModel::readData ()
  1.4035 +{
  1.4036 +	while (clientSocket->bytesAvailable() >=(int)sizeof(quint16) )
  1.4037 +	{
  1.4038 +		if (debug)
  1.4039 +			cout <<"readData  bytesAvail="<<clientSocket->bytesAvailable();
  1.4040 +		quint16 recCounter;
  1.4041 +		quint16 blockSize;
  1.4042 +
  1.4043 +		QDataStream in(clientSocket);
  1.4044 +		in.setVersion(QDataStream::Qt_4_0);
  1.4045 +
  1.4046 +		in >> blockSize;
  1.4047 +		in >> recCounter;
  1.4048 +		
  1.4049 +		QString t;
  1.4050 +		in >>t;
  1.4051 +		if (debug)
  1.4052 +			cout << "  t="<<qPrintable (t)<<endl;
  1.4053 +		parseAtom (t);
  1.4054 +	}
  1.4055 +	return;
  1.4056 +}
  1.4057 +
  1.4058 +void VymModel::displayNetworkError(QAbstractSocket::SocketError socketError)
  1.4059 +{
  1.4060 +    switch (socketError) {
  1.4061 +    case QAbstractSocket::RemoteHostClosedError:
  1.4062 +        break;
  1.4063 +    case QAbstractSocket::HostNotFoundError:
  1.4064 +        QMessageBox::information(NULL, vymName +" Network client",
  1.4065 +                                 "The host was not found. Please check the "
  1.4066 +                                    "host name and port settings.");
  1.4067 +        break;
  1.4068 +    case QAbstractSocket::ConnectionRefusedError:
  1.4069 +        QMessageBox::information(NULL, vymName + " Network client",
  1.4070 +                                 "The connection was refused by the peer. "
  1.4071 +                                    "Make sure the fortune server is running, "
  1.4072 +                                    "and check that the host name and port "
  1.4073 +                                    "settings are correct.");
  1.4074 +        break;
  1.4075 +    default:
  1.4076 +        QMessageBox::information(NULL, vymName + " Network client",
  1.4077 +                                 QString("The following error occurred: %1.")
  1.4078 +                                 .arg(clientSocket->errorString()));
  1.4079 +    }
  1.4080 +}
  1.4081 +
  1.4082 +
  1.4083 +
  1.4084 +
  1.4085 +void VymModel::selectMapSelectionColor()
  1.4086 +{
  1.4087 +	QColor col = QColorDialog::getColor( defLinkColor, NULL);
  1.4088 +	setSelectionColor (col);
  1.4089 +}
  1.4090 +
  1.4091 +void VymModel::setSelectionColorInt (QColor col)
  1.4092 +{
  1.4093 +	if ( !col.isValid() ) return;
  1.4094 +	saveState (
  1.4095 +		QString("setSelectionColor (%1)").arg(selection.getColor().name()),
  1.4096 +		QString("setSelectionColor (%1)").arg(col.name()),
  1.4097 +		QString("Set color of selection box to %1").arg(col.name())
  1.4098 +	);
  1.4099 +
  1.4100 +	selection.setColor (col);
  1.4101 +}
  1.4102 +
  1.4103 +void VymModel::updateSelection()
  1.4104 +{
  1.4105 +	selection.update();
  1.4106 +}
  1.4107 +
  1.4108 +void VymModel::setSelectionColor(QColor col)
  1.4109 +{
  1.4110 +	if ( !col.isValid() ) return;
  1.4111 +	saveState (
  1.4112 +		QString("setSelectionColor (%1)").arg(selection.getColor().name()),
  1.4113 +		QString("setSelectionColor (%1)").arg(col.name()),
  1.4114 +		QString("Set color of selection box to %1").arg(col.name())
  1.4115 +	);
  1.4116 +	setSelectionColorInt (col);
  1.4117 +}
  1.4118 +
  1.4119 +QColor VymModel::getSelectionColor()
  1.4120 +{
  1.4121 +	return selection.getColor();
  1.4122 +}
  1.4123 +
  1.4124 +void VymModel::setHideTmpMode (HideTmpMode mode)
  1.4125 +{
  1.4126 +	hidemode=mode;
  1.4127 +	for (int i=0;i<mapCenters.count(); i++)
  1.4128 +		mapCenters.at(i)->setHideTmp (mode);	
  1.4129 +	reposition();
  1.4130 +	// FIXME needed? scene()->update();
  1.4131 +}
  1.4132 +
  1.4133 +
  1.4134 +QRectF VymModel::getTotalBBox()
  1.4135 +{
  1.4136 +	QRectF r;
  1.4137 +	for (int i=0;i<mapCenters.count(); i++)
  1.4138 +		r=addBBox (mapCenters.at(i)->getTotalBBox(), r);
  1.4139 +	return r;	
  1.4140 +}
  1.4141  
  1.4142  //////////////////////////////////////////////
  1.4143  // Selection related
  1.4144  //////////////////////////////////////////////
  1.4145  
  1.4146 -
  1.4147 -// Only as long as we dont have Model/View yet
  1.4148 +void VymModel::setSelectionBlocked (bool b)
  1.4149 +{
  1.4150 +	if (b)
  1.4151 +		selection.block();
  1.4152 +	else	
  1.4153 +		selection.unblock();
  1.4154 +}
  1.4155 +
  1.4156 +bool VymModel::isSelectionBlocked()
  1.4157 +{
  1.4158 +	return selection.isBlocked();
  1.4159 +}
  1.4160 +
  1.4161 +bool VymModel::select (const QString &s)
  1.4162 +{
  1.4163 +	if (selection.select(s))
  1.4164 +	{
  1.4165 +		selection.update();
  1.4166 +		ensureSelectionVisible();
  1.4167 +		sendSelection ();
  1.4168 +		return true;
  1.4169 +	}
  1.4170 +	return false;
  1.4171 +
  1.4172 +}
  1.4173 +
  1.4174 +bool VymModel::select (LinkableMapObj *lmo)
  1.4175 +{
  1.4176 +	if (selection.select(lmo))
  1.4177 +	{
  1.4178 +		selection.update();
  1.4179 +		ensureSelectionVisible();
  1.4180 +		sendSelection ();
  1.4181 +		return true;
  1.4182 +	}
  1.4183 +	return false;
  1.4184 +}
  1.4185 +
  1.4186 +void VymModel::unselect()
  1.4187 +{
  1.4188 +	selection.unselect();
  1.4189 +}	
  1.4190 +
  1.4191 +void VymModel::reselect()
  1.4192 +{
  1.4193 +	selection.reselect();
  1.4194 +}	
  1.4195 +
  1.4196 +void VymModel::ensureSelectionVisible()
  1.4197 +{
  1.4198 +	LinkableMapObj *lmo=selection.single();
  1.4199 +	if (lmo &&mapEditor) mapEditor->ensureVisible (lmo->getBBox() );
  1.4200 +	
  1.4201 +}
  1.4202 +
  1.4203 +void VymModel::selectInt (LinkableMapObj *lmo)
  1.4204 +{
  1.4205 +	if (selection.select(lmo))
  1.4206 +	{
  1.4207 +		selection.update();
  1.4208 +		sendSelection ();
  1.4209 +	}
  1.4210 +}
  1.4211 +
  1.4212 +
  1.4213 +void VymModel::selectNextBranchInt()
  1.4214 +{
  1.4215 +	// Increase number of branch
  1.4216 +	LinkableMapObj *sel=selection.single();
  1.4217 +	if (sel)
  1.4218 +	{
  1.4219 +		QString s=selection.getSelectString();
  1.4220 +		QString part;
  1.4221 +		QString typ;
  1.4222 +		QString num;
  1.4223 +
  1.4224 +		// Where am I? 
  1.4225 +		part=s.section(",",-1);
  1.4226 +		typ=part.left (3);
  1.4227 +		num=part.right(part.length() - 3);
  1.4228 +
  1.4229 +		s=s.left (s.length() -num.length());
  1.4230 +
  1.4231 +		// Go to next lmo
  1.4232 +		num=QString ("%1").arg(num.toUInt()+1);
  1.4233 +
  1.4234 +		s=s+num;
  1.4235 +		
  1.4236 +		// Try to select this one
  1.4237 +		if (select (s)) return;
  1.4238 +
  1.4239 +		// We have no direct successor, 
  1.4240 +		// try to increase the parental number in order to
  1.4241 +		// find a successor with same depth
  1.4242 +
  1.4243 +		int d=selection.single()->getDepth();
  1.4244 +		int oldDepth=d;
  1.4245 +		int i;
  1.4246 +		bool found=false;
  1.4247 +		bool b;
  1.4248 +		while (!found && d>0)
  1.4249 +		{
  1.4250 +			s=s.section (",",0,d-1);
  1.4251 +			// replace substring of current depth in s with "1"
  1.4252 +			part=s.section(",",-1);
  1.4253 +			typ=part.left (3);
  1.4254 +			num=part.right(part.length() - 3);
  1.4255 +
  1.4256 +			if (d>1)
  1.4257 +			{	
  1.4258 +				// increase number of parent
  1.4259 +				num=QString ("%1").arg(num.toUInt()+1);
  1.4260 +				s=s.section (",",0,d-2) + ","+ typ+num;
  1.4261 +			} else
  1.4262 +			{
  1.4263 +				// Special case, look at orientation
  1.4264 +				if (selection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
  1.4265 +					num=QString ("%1").arg(num.toUInt()+1);
  1.4266 +				else	
  1.4267 +					num=QString ("%1").arg(num.toUInt()-1);
  1.4268 +				s=typ+num;
  1.4269 +			}	
  1.4270 +
  1.4271 +			if (select (s))
  1.4272 +				// pad to oldDepth, select the first branch for each depth
  1.4273 +				for (i=d;i<oldDepth;i++)
  1.4274 +				{
  1.4275 +					b=select (s);
  1.4276 +					if (b)
  1.4277 +					{	
  1.4278 +						if ( selection.getBranch()->countBranches()>0)
  1.4279 +							s+=",bo:0";
  1.4280 +						else	
  1.4281 +							break;
  1.4282 +					} else
  1.4283 +						break;
  1.4284 +				}	
  1.4285 +
  1.4286 +			// try to select the freshly built string
  1.4287 +			found=select(s);
  1.4288 +			d--;
  1.4289 +		}
  1.4290 +		return;
  1.4291 +	}	
  1.4292 +}
  1.4293 +
  1.4294 +void VymModel::selectPrevBranchInt()
  1.4295 +{
  1.4296 +	// Decrease number of branch
  1.4297 +	BranchObj *bo=selection.getBranch();
  1.4298 +	if (bo)
  1.4299 +	{
  1.4300 +		QString s=selection.getSelectString();
  1.4301 +		QString part;
  1.4302 +		QString typ;
  1.4303 +		QString num;
  1.4304 +
  1.4305 +		// Where am I? 
  1.4306 +		part=s.section(",",-1);
  1.4307 +		typ=part.left (3);
  1.4308 +		num=part.right(part.length() - 3);
  1.4309 +
  1.4310 +		s=s.left (s.length() -num.length());
  1.4311 +
  1.4312 +		int n=num.toInt()-1;
  1.4313 +		
  1.4314 +		// Go to next lmo
  1.4315 +		num=QString ("%1").arg(n);
  1.4316 +		s=s+num;
  1.4317 +		
  1.4318 +		// Try to select this one
  1.4319 +		if (n>=0 && select (s)) return;
  1.4320 +
  1.4321 +		// We have no direct precessor, 
  1.4322 +		// try to decrease the parental number in order to
  1.4323 +		// find a precessor with same depth
  1.4324 +
  1.4325 +		int d=selection.single()->getDepth();
  1.4326 +		int oldDepth=d;
  1.4327 +		int i;
  1.4328 +		bool found=false;
  1.4329 +		bool b;
  1.4330 +		while (!found && d>0)
  1.4331 +		{
  1.4332 +			s=s.section (",",0,d-1);
  1.4333 +			// replace substring of current depth in s with "1"
  1.4334 +			part=s.section(",",-1);
  1.4335 +			typ=part.left (3);
  1.4336 +			num=part.right(part.length() - 3);
  1.4337 +
  1.4338 +			if (d>1)
  1.4339 +			{
  1.4340 +				// decrease number of parent
  1.4341 +				num=QString ("%1").arg(num.toInt()-1);
  1.4342 +				s=s.section (",",0,d-2) + ","+ typ+num;
  1.4343 +			} else
  1.4344 +			{
  1.4345 +				// Special case, look at orientation
  1.4346 +				if (selection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
  1.4347 +					num=QString ("%1").arg(num.toInt()-1);
  1.4348 +				else	
  1.4349 +					num=QString ("%1").arg(num.toInt()+1);
  1.4350 +				s=typ+num;
  1.4351 +			}	
  1.4352 +
  1.4353 +			if (select(s))
  1.4354 +				// pad to oldDepth, select the last branch for each depth
  1.4355 +				for (i=d;i<oldDepth;i++)
  1.4356 +				{
  1.4357 +					b=select (s);
  1.4358 +					if (b)
  1.4359 +						if ( selection.getBranch()->countBranches()>0)
  1.4360 +							s+=",bo:"+ QString ("%1").arg( selection.getBranch()->countBranches()-1 );
  1.4361 +						else	
  1.4362 +							break;
  1.4363 +					else
  1.4364 +						break;
  1.4365 +				}	
  1.4366 +			
  1.4367 +			// try to select the freshly built string
  1.4368 +			found=select(s);
  1.4369 +			d--;
  1.4370 +		}
  1.4371 +		return;
  1.4372 +	}	
  1.4373 +}
  1.4374 +
  1.4375 +void VymModel::selectUpperBranch()
  1.4376 +{
  1.4377 +	if (selection.isBlocked() ) return;
  1.4378 +
  1.4379 +	BranchObj *bo=selection.getBranch();
  1.4380 +	if (bo && selection.type()==Selection::Branch)
  1.4381 +	{
  1.4382 +		if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
  1.4383 +			selectPrevBranchInt();
  1.4384 +		else
  1.4385 +			if (bo->getDepth()==1)
  1.4386 +				selectNextBranchInt();
  1.4387 +			else
  1.4388 +				selectPrevBranchInt();
  1.4389 +	}
  1.4390 +}
  1.4391 +
  1.4392 +void VymModel::selectLowerBranch()
  1.4393 +{
  1.4394 +	if (selection.isBlocked() ) return;
  1.4395 +
  1.4396 +	BranchObj *bo=selection.getBranch();
  1.4397 +	if (bo && selection.type()==Selection::Branch)
  1.4398 +	{
  1.4399 +		if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
  1.4400 +			selectNextBranchInt();
  1.4401 +		else
  1.4402 +			if (bo->getDepth()==1)
  1.4403 +				selectPrevBranchInt();
  1.4404 +			else
  1.4405 +				selectNextBranchInt();
  1.4406 +	}			
  1.4407 +}
  1.4408 +
  1.4409 +
  1.4410 +void VymModel::selectLeftBranch()
  1.4411 +{
  1.4412 +	if (selection.isBlocked() ) return;
  1.4413 +
  1.4414 +	BranchObj* bo;
  1.4415 +	BranchObj* par;
  1.4416 +	LinkableMapObj *sel=selection.single();
  1.4417 +	if (sel)
  1.4418 +	{
  1.4419 +		if (selection.type()== Selection::MapCenter)
  1.4420 +		{
  1.4421 +			par=selection.getBranch();
  1.4422 +			bo=par->getLastSelectedBranch();
  1.4423 +			if (bo)
  1.4424 +			{
  1.4425 +				// Workaround for reselecting on left and right side
  1.4426 +				if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
  1.4427 +					bo=par->getLastBranch();
  1.4428 +				if (bo)
  1.4429 +				{
  1.4430 +					bo=par->getLastBranch();
  1.4431 +					selection.select(bo);
  1.4432 +					selection.update();
  1.4433 +					ensureSelectionVisible();
  1.4434 +					sendSelection();
  1.4435 +				}
  1.4436 +			}	
  1.4437 +		} else
  1.4438 +		{
  1.4439 +			par=(BranchObj*)(sel->getParObj());
  1.4440 +			if (sel->getOrientation()==LinkableMapObj::RightOfCenter)
  1.4441 +			{
  1.4442 +				if (selection.type() == Selection::Branch ||
  1.4443 +					selection.type() == Selection::FloatImage)
  1.4444 +				{
  1.4445 +					selection.select(par);
  1.4446 +					selection.update();
  1.4447 +					ensureSelectionVisible();
  1.4448 +					sendSelection();
  1.4449 +				}
  1.4450 +			} else
  1.4451 +			{
  1.4452 +				if (selection.type() == Selection::Branch )
  1.4453 +				{
  1.4454 +					bo=selection.getBranch()->getLastSelectedBranch();
  1.4455 +					if (bo) 
  1.4456 +					{
  1.4457 +						selection.select(bo);
  1.4458 +						selection.update();
  1.4459 +						ensureSelectionVisible();
  1.4460 +					sendSelection();
  1.4461 +					}
  1.4462 +				}
  1.4463 +			}
  1.4464 +		}	
  1.4465 +	}
  1.4466 +}
  1.4467 +
  1.4468 +void VymModel::selectRightBranch()
  1.4469 +{
  1.4470 +	if (selection.isBlocked() ) return;
  1.4471 +
  1.4472 +	BranchObj* bo;
  1.4473 +	BranchObj* par;
  1.4474 +	LinkableMapObj *sel=selection.single();
  1.4475 +	if (sel)
  1.4476 +	{
  1.4477 +		if (selection.type()==Selection::MapCenter) 
  1.4478 +		{
  1.4479 +			par=selection.getBranch();
  1.4480 +			bo=par->getLastSelectedBranch();
  1.4481 +			if (bo)
  1.4482 +			{
  1.4483 +				// Workaround for reselecting on left and right side
  1.4484 +				if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
  1.4485 +					bo=par->getFirstBranch();
  1.4486 +				if (bo)
  1.4487 +				{
  1.4488 +					selection.select(bo);
  1.4489 +					selection.update();
  1.4490 +					ensureSelectionVisible();
  1.4491 +					sendSelection();
  1.4492 +				}
  1.4493 +			}
  1.4494 +		} else
  1.4495 +		{
  1.4496 +			par=(BranchObj*)(selection.single()->getParObj());
  1.4497 +			if (selection.single()->getOrientation()==LinkableMapObj::LeftOfCenter)
  1.4498 +			{
  1.4499 +				if (selection.type() == Selection::Branch ||
  1.4500 +					selection.type() == Selection::FloatImage)
  1.4501 +				{
  1.4502 +					selection.select(par);
  1.4503 +					selection.update();
  1.4504 +					ensureSelectionVisible();
  1.4505 +					sendSelection();
  1.4506 +				}
  1.4507 +			} else
  1.4508 +			{
  1.4509 +				if (selection.type()  == Selection::Branch) 
  1.4510 +				{
  1.4511 +					bo=selection.getBranch()->getLastSelectedBranch();
  1.4512 +					if (bo) 
  1.4513 +					{
  1.4514 +						selection.select(bo);
  1.4515 +						selection.update();
  1.4516 +						ensureSelectionVisible();
  1.4517 +					sendSelection();
  1.4518 +					}
  1.4519 +				}
  1.4520 +			}
  1.4521 +		}
  1.4522 +	}
  1.4523 +}
  1.4524 +
  1.4525 +void VymModel::selectFirstBranch()
  1.4526 +{
  1.4527 +	BranchObj *bo1=selection.getBranch();
  1.4528 +	BranchObj *bo2;
  1.4529 +	BranchObj* par;
  1.4530 +	if (bo1)
  1.4531 +	{
  1.4532 +		par=(BranchObj*)(bo1->getParObj());
  1.4533 +		if (!par) return;
  1.4534 +		bo2=par->getFirstBranch();
  1.4535 +		if (bo2) {
  1.4536 +			selection.select(bo2);
  1.4537 +			selection.update();
  1.4538 +			ensureSelectionVisible();
  1.4539 +			sendSelection();
  1.4540 +		}
  1.4541 +	}		
  1.4542 +}
  1.4543 +
  1.4544 +void VymModel::selectLastBranch()
  1.4545 +{
  1.4546 +	BranchObj *bo1=selection.getBranch();
  1.4547 +	BranchObj *bo2;
  1.4548 +	BranchObj* par;
  1.4549 +	if (bo1)
  1.4550 +	{
  1.4551 +		par=(BranchObj*)(bo1->getParObj());
  1.4552 +		if (!par) return;
  1.4553 +		bo2=par->getLastBranch();
  1.4554 +		if (bo2) 
  1.4555 +		{
  1.4556 +			selection.select(bo2);
  1.4557 +			selection.update();
  1.4558 +			ensureSelectionVisible();
  1.4559 +			sendSelection();
  1.4560 +		}
  1.4561 +	}		
  1.4562 +}
  1.4563 +
  1.4564 +Selection::Type VymModel::selectionType()
  1.4565 +{
  1.4566 +	return selection.type();
  1.4567 +}
  1.4568 +
  1.4569  LinkableMapObj* VymModel::getSelection()
  1.4570  {
  1.4571 -	return mapEditor->getSelection();
  1.4572 +	return selection.single();	
  1.4573  }
  1.4574  BranchObj* VymModel::getSelectedBranch()
  1.4575  {
  1.4576 -	return mapEditor->getSelectedBranch();
  1.4577 +	return selection.getBranch();	
  1.4578  }
  1.4579  
  1.4580 -
  1.4581 -bool VymModel::select (const QString &s)
  1.4582 +FloatImageObj* VymModel::getSelectedFloatImage()
  1.4583  {
  1.4584 -	return mapEditor->select (s);
  1.4585 +	return selection.getFloatImage();	
  1.4586 +}
  1.4587 +
  1.4588 +QString VymModel::getSelectString ()
  1.4589 +{
  1.4590 +	return selection.getSelectString();
  1.4591  }
  1.4592  
  1.4593  QString VymModel::getSelectString (LinkableMapObj *lmo)
  1.4594 @@ -368,21 +4723,5 @@
  1.4595  		}	
  1.4596  	}	
  1.4597  	return s;
  1.4598 -
  1.4599  }
  1.4600  
  1.4601 -	
  1.4602 -void VymModel::setHideTmp (HideTmpMode mode)
  1.4603 -{
  1.4604 -	for (int i=0;i<mapCenters.count(); i++)
  1.4605 -		mapCenters.at(i)->setHideTmp (mode);	
  1.4606 -}
  1.4607 -
  1.4608 -QRectF VymModel::getTotalBBox()
  1.4609 -{
  1.4610 -	QRectF r;
  1.4611 -	for (int i=0;i<mapCenters.count(); i++)
  1.4612 -		r=addBBox (mapCenters.at(i)->getTotalBBox(), r);
  1.4613 -	return r;	
  1.4614 -}
  1.4615 -