# HG changeset patch
# User insilmaril
# Date 1269345270 0
# Node ID 876eed30ba3b967371054b38b37e135676773c78
# Parent  5c5b4464b24fe43c2198375afb7908126325756b
Patch from Xavier Oswald to compile with older compilers

diff -r 5c5b4464b24f -r 876eed30ba3b exports.cpp
--- a/exports.cpp	Fri Mar 05 20:16:46 2010 +0000
+++ b/exports.cpp	Tue Mar 23 11:54:30 2010 +0000
@@ -5,6 +5,7 @@
 #include "mainwindow.h"
 #include "warningdialog.h"
 #include "xsltproc.h"
+#include <cstdlib>
 
 extern Main *mainWindow;
 extern QDir vymBaseDir;
diff -r 5c5b4464b24f -r 876eed30ba3b file.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/file.cpp	Tue Mar 23 11:54:30 2010 +0000
@@ -0,0 +1,500 @@
+#include <QDir>
+#include <QMessageBox>
+#include <QPixmap>
+#include <QLabel>
+#include <QTextStream>
+#include <iostream>
+#include <cstdlib>
+
+#include "file.h"
+#include "process.h"
+
+#if defined(Q_OS_WIN32)
+#include "mkdtemp.h"
+#include <windows.h>
+#endif
+
+QString maskPath(QString p)
+{
+	// Change " " to "\ " to enable blanks in filenames
+	p=p.replace(QChar('&'),"\\&");
+	return p.replace(QChar(' '),"\\ ");
+}
+
+QString convertToRel (const QString &src, const QString &dst)
+{
+	QString s=src;
+	QString d=dst;
+	int i;
+
+	if (s==d) 
+	{
+		// Special case, we just need the name of the file,
+		// not the complete path
+		i=d.findRev ("/");
+		d=d.right (d.length()-i-1);
+	} else
+	{
+		// Find relative path from src to dst
+
+		// Remove the first "/"
+		if (s.section ("/",0,0).isEmpty()) 
+		{
+			s=s.right (s.length()-1);
+			d=d.right (d.length()-1);
+		}
+		
+		// remove identical left parts
+		while (s.section("/",0,0) == d.section("/",0,0) ) 
+		{
+			i=s.find ("/");
+			s=s.right (s.length()-i-1);
+			d=d.right (d.length()-i-1);
+		}
+
+		// Now take care of paths where we have to go back first
+		int srcsep=s.count("/");
+		int dstsep=d.count("/");
+		if (srcsep <=  dstsep )
+		{
+			// find path to go up first and then back to dst
+			i=1;
+			while (i<=srcsep) 
+			{
+				d="../"+d;
+				i++;
+			}	
+		}
+	}	
+	return d;
+}
+
+#include <QFileDialog>
+extern QString vymName;
+extern QDir lastFileDir;
+
+QString browseDirectory (QWidget *parent,const QString &caption)
+{
+	QFileDialog fd(parent,caption);
+	fd.setMode (QFileDialog::DirectoryOnly);
+	fd.setCaption(vymName+ " - "+caption);
+	fd.setDir (lastFileDir);
+	fd.show();
+	
+	if ( fd.exec() == QDialog::Accepted )
+		return fd.selectedFile();
+	else
+		return "";
+}
+
+
+
+bool reallyWriteDirectory(const QString &dir)
+{
+	QStringList eList = QDir(dir).entryList();
+	if (eList.first() ==".")  eList.pop_front();	// remove "."
+	if (eList.first() =="..") eList.pop_front();	// remove "."
+	if (!eList.isEmpty())
+	{
+		QMessageBox mb( vymName,
+			QObject::tr("The directory %1 is not empty.\nDo you risk to overwrite its contents?","write directory").arg(dir),
+		QMessageBox::Warning,
+		QMessageBox::Yes ,
+		QMessageBox::Cancel | QMessageBox::Default,
+		QMessageBox::NoButton );
+
+		mb.setButtonText( QMessageBox::Yes, QObject::tr("Overwrite") );
+		mb.setButtonText( QMessageBox::No, QObject::tr("Cancel"));
+		switch( mb.exec() ) 
+		{
+			case QMessageBox::Yes:
+				// save 
+				return true;
+			case QMessageBox::Cancel:
+				// do nothing
+				return false;
+		}
+	}
+	return true;
+}
+
+QString makeTmpDir (bool &ok, QString prefix)
+{
+	bool b;
+	QString path=makeUniqueDir (b,QDir::tempPath()+"/"+prefix+"-XXXXXX");
+	ok=b;
+	return path;
+}
+
+bool isInTmpDir(QString fn)
+{
+	QString temp=QDir::tempPath();
+	int l=temp.length();
+	return fn.left(l)==temp;
+}
+
+QString makeUniqueDir (bool &ok,QString s)
+{
+	// Create unique directory e.g. for s="/tmp/vym-XXXXXX"
+
+	// Convert Separators
+	s=QDir::convertSeparators(s);
+
+	// Convert QString to string 
+	ok=true;
+	char *p;
+	int bytes=s.length();
+	p=(char*) malloc (bytes+1);
+	int i;
+	for (i=0;i<bytes;i++)
+		p[i]=s.at(i).latin1();
+	p[bytes]=0;	
+
+	QString r=mkdtemp (p);
+	if (r.isEmpty()) ok=false;
+	free (p);
+	return r;
+}
+
+void removeDir(QDir d)
+{
+	// This check should_ not be necessary, but proved to be useful ;-)
+	if (!isInTmpDir(d.path()))
+	{
+		qWarning ("file.cpp::removeDir should remove "+d.path()+" - aborted.");
+		return;
+	}
+
+	// Traverse directories
+	d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
+	QFileInfoList list = d.entryInfoList();
+	QFileInfo fi;
+
+	for (int i = 0; i < list.size(); ++i) 
+	{
+		fi=list.at(i);
+		if (fi.fileName() != "." && fi.fileName() != ".." )
+		{
+			if ( !d.cd(fi.fileName()) ) 
+				qWarning ("removeDir() cannot find the directory "+fi.fileName());
+			else 
+			{
+				// Recursively remove subdirs
+				removeDir (d);
+				d.cdUp();
+			}
+		}	
+	}
+
+	// Traverse files
+	d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
+	list = d.entryInfoList();
+
+	for (int i = 0; i < list.size(); ++i) 
+	{
+		fi=list.at(i);
+		QFile (fi.filePath()).remove(); 
+	}	
+
+	if (!d.rmdir(d.path()))
+		qWarning ("removeDir("+d.path()+") failed!");
+}		
+
+void copyDir (QDir src, QDir dst)
+{
+	system ("cp -r "+src.path()+"/* "+dst.path());
+
+	/*
+	ErrorCode err=success;
+
+	Process *cpProc=new Process ();
+	QStringList args;
+	cpProc->setWorkingDirectory (src.path());
+	args <<"-r";
+	args <<src.path();
+	args <<dst.path();
+
+	cpProc->start ("cp",args);
+	if (!cpProc->waitForStarted() )
+	{	
+		// zip could not be started
+		QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+					   QObject::tr("Couldn't start zip to compress data."));
+		err=aborted;
+	} else
+	{
+		// zip could be started
+		cpProc->waitForFinished();
+		if (cpProc->exitStatus()!=QProcess::NormalExit )
+		{
+			QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+						   QObject::tr("cp didn't exit normally")+
+						   "\n" + cpProc->getErrout());
+			err=aborted;
+		} else
+		{
+			if (cpProc->exitCode()>0)
+			{
+				QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+						   QString("cp exit code:  %1").arg(cpProc->exitCode() )+
+						   "\n" + cpProc->getErrout() );
+				err=aborted;
+			}
+		}
+	}	// cp could be started
+	*/
+}
+
+void makeSubDirs (const QString &s)
+{
+	QDir d(s);
+	d.mkdir(s);
+	d.mkdir ("images");	
+	d.mkdir ("flags");	
+}
+
+ErrorCode zipDir (const QDir &zipDir, const QString &zipName)
+{
+	ErrorCode err=success;
+	
+	// zip the temporary directory
+	QStringList args;
+	Process *zipProc=new Process ();
+	zipProc->setWorkingDirectory (zipDir.path());
+	args <<"-r";
+	args <<zipName;
+	args <<".";
+
+	zipProc->start ("zip",args);
+	if (!zipProc->waitForStarted() )
+	{	
+		// zip could not be started
+		QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+					   QObject::tr("Couldn't start zip to compress data."));
+		err=aborted;
+	} else
+	{
+		// zip could be started
+		zipProc->waitForFinished();
+		if (zipProc->exitStatus()!=QProcess::NormalExit )
+		{
+			QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+						   QObject::tr("zip didn't exit normally")+
+						   "\n" + zipProc->getErrout());
+			err=aborted;
+		} else
+		{
+			if (zipProc->exitCode()>0)
+			{
+				QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+						   QString("zip exit code:  %1").arg(zipProc->exitCode() )+
+						   "\n" + zipProc->getErrout() );
+				err=aborted;
+			}
+		}
+	}	// zip could be started
+	return err;	
+}
+
+ErrorCode unzipDir (const QDir &zipDir, const QString &zipName)
+{
+	ErrorCode err=success;
+
+	// Try to unzip file
+#if !defined(Q_OS_WIN32)
+	QStringList args;
+	Process *zipProc=new Process ();
+	zipProc->setWorkingDirectory (zipDir.path());
+	args << "-o";	// overwrite existing files!
+	args << zipName ;
+	args << "-d";
+	args << zipDir.path();
+
+	zipProc->start ("unzip",args);
+	if (!zipProc->waitForStarted() )
+	{
+		QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+					   QObject::tr("Couldn't start unzip to decompress data."));
+		err=aborted;
+		
+	} else
+	{
+		zipProc->waitForFinished();
+		if (zipProc->exitStatus()!=QProcess::NormalExit )
+		{
+			QMessageBox::critical( 0,QObject::tr( "Critical Error" ),
+						   QObject::tr("unzip didn't exit normally") +
+						   zipProc->getErrout() );
+			err=aborted;
+		} else
+		{
+			if (zipProc->exitCode()>0)
+			{
+				if (zipProc->exitCode()==9)
+					// no zipped file, but maybe .xml or old version? Try again.
+					err=nozip;
+				else	
+				{
+					QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+								   QString("unzip exit code:  %1").arg(zipProc->exitCode() ) +
+								   zipProc->getErrout() );
+					err=aborted;
+				}
+			} 
+		}
+	}
+#else
+    // Do this process creation using Win32 API.
+    //! Create process.
+    PROCESS_INFORMATION piProcInfo;
+    STARTUPINFO siStartInfo;
+
+    // Initialize members of the PROCESS_INFORMATION structure.
+    ::ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
+
+    // Set up members of the STARTUPINFO structure.
+    ::ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
+    siStartInfo.cb = sizeof(STARTUPINFO);
+
+    // Create command line.
+    QString argv("unzip -o ");
+    argv.append(QDir::convertSeparators(zipName));
+    argv.append(" -d ");
+    argv.append(QDir::convertSeparators(zipDir.path()));
+
+    // Create the child process.
+    if( !::CreateProcess(NULL, 
+        (LPWSTR)argv.unicode(), // command line
+        NULL, // process security attributes
+        NULL, // primary thread security attributes
+        TRUE, // handles are inherited
+        0, // creation flags
+        NULL, // use parent's environment
+        NULL, // use parent's current directory
+        &siStartInfo, // STARTUPINFO pointer
+        &piProcInfo) ) // receives PROCESS_INFORMATION
+    {
+        err = aborted;
+    }
+    else
+    {
+        // Wait for it to finish.
+        ::WaitForSingleObject( piProcInfo.hProcess, 10000 );
+    }
+#endif
+	return err;	
+}
+
+bool loadStringFromDisk (const QString &fname, QString &s)
+{
+	s="";
+	QFile file ( fname);
+	if ( !file.open( QIODevice::ReadOnly ) ) return false;
+
+	QTextStream ts( &file );
+	ts.setEncoding (QTextStream::UnicodeUTF8);
+	while ( !ts.atEnd() ) 
+		s+=ts.readLine()+"\n"; 
+	file.close();
+	return true;
+}
+
+bool saveStringToDisk (const QString &fname, const QString &s)
+{
+	QFile file( fname);
+
+	file.setName ( fname);
+	if ( !file.open( QIODevice::WriteOnly ) ) 
+	{
+		file.close();
+		return false;
+	}	
+
+	// Write it finally, and write in UTF8, no matter what 
+	QTextStream ts( &file );
+	ts.setEncoding (QTextStream::UnicodeUTF8);
+	ts << s;
+	file.close();
+	return true;
+}
+
+
+ImagePreview::ImagePreview (QWidget *par=0): QLabel (par)
+{
+	fdia=(Q3FileDialog*)par;
+}
+
+void ImagePreview::previewUrl( const Q3Url &u )
+{
+    QString path = u.path();
+    QPixmap pix( path );
+    if ( pix.isNull() )
+	{
+		// Strange: If we have fd->setMode (QFileDialog::ExistingFiles)
+		// in the filedialog, then there are 3 calls to previewURL 
+		// for each selection. And only the first is the actual selected file
+		// while the following 2 point to the directory above the current one.
+		// So here's my workaround:
+		
+		if (fdia && fdia->selectedFiles().count()==0)
+			setText( QObject::tr("This is not an image.") );
+		if (fdia &&fdia->selectedFiles().count()>1)
+			setText( QObject::tr("Sorry, no preview for\nmultiple selected files.") );
+	}	
+    else
+	{
+		float max_w=300;
+		float max_h=300;
+		float r;
+		if (pix.width()>max_w)
+		{
+			r=max_w / pix.width();
+			pix.resize(qRound(pix.width()*r), qRound(pix.height()*r));
+			// TODO not a resize, but a shrink/enlarge is needed here...
+		}
+		if (pix.height()>max_h)
+		{
+			r=max_h / pix.height();
+			pix.resize(qRound(pix.width()*r), qRound(pix.height()*r));
+			// TODO not a resize, but a shrink/enlarge is needed here...
+		}
+        setPixmap( pix );
+	}	
+}
+
+ImageIO::ImageIO ()
+{
+	// Create list with supported image types
+	// foreach (QByteArray format, QImageWriter::supportedImageFormats()) 
+	// imageTypes.append( tr("%1...").arg(QString(format).toUpper()));
+	imageFilters.append ("Images (*.png *.jpg *.jpeg *.bmp *.bmp *.ppm *.xpm *.xbm)");
+	imageTypes.append ("PNG");
+	imageFilters.append ("Portable Network Graphics (*.png)");
+	imageTypes.append ("PNG");
+	imageFilters.append ("Joint Photographic Experts Group (*.jpg)");
+	imageTypes.append ("JPG");
+	imageFilters.append ("Joint Photographic Experts Group (*.jpeg)");
+	imageTypes.append ("JPG");
+	imageFilters.append ("Windows Bitmap (*.bmp)");
+	imageTypes.append ("BMP");
+	imageFilters.append ("Portable Pixmap (*.ppm)");
+	imageTypes.append ("PPM");
+	imageFilters.append ("X11 Bitmap (*.xpm)");
+	imageTypes.append ("XPM");
+	imageFilters.append ("X11 Bitmap (*.xbm)");
+	imageTypes.append ("XBM");
+}
+
+QStringList ImageIO::getFilters()
+{
+	return imageFilters;
+}
+
+QString ImageIO::getType(QString filter)
+{
+	for (int i=0;i<imageFilters.count()+1;i++)
+		if (imageFilters.at(i)==filter) return imageTypes.at(i);
+	return QString();	
+}
+
+
diff -r 5c5b4464b24f -r 876eed30ba3b linkablemapobj.cpp
--- a/linkablemapobj.cpp	Fri Mar 05 20:16:46 2010 +0000
+++ b/linkablemapobj.cpp	Tue Mar 23 11:54:30 2010 +0000
@@ -1,12 +1,10 @@
-//#include <math.h>
+#include <math.h>
+#include <cstdlib>
 
 #include "linkablemapobj.h"
 #include "branchobj.h"
 #include "mapeditor.h"
 
-#include "version.h"
-
-
 /////////////////////////////////////////////////////////////////
 // LinkableMapObj
 /////////////////////////////////////////////////////////////////
@@ -17,13 +15,13 @@
     init ();
 }
 
-LinkableMapObj::LinkableMapObj(QCanvas* c) :MapObj(c)
+LinkableMapObj::LinkableMapObj(QGraphicsScene* s) :MapObj(s)
 {
-//    cout << "Const LinkableMapObj\n";
+//    cout << "Const LinkableMapObj (s)\n";
     init ();
 }
 
-LinkableMapObj::LinkableMapObj (LinkableMapObj* lmo) : MapObj (lmo->canvas)
+LinkableMapObj::LinkableMapObj (LinkableMapObj* lmo) : MapObj (lmo->scene)
 {
     copy (lmo);
 }
@@ -31,8 +29,6 @@
 LinkableMapObj::~LinkableMapObj()
 {
     delete (bottomline);
-    delete (selbox);
-	delete (frame);
 	delLink();
 }
 
@@ -40,19 +36,17 @@
 {
 	switch (style)
 	{
-		case StyleLine:
+		case Line:
 			delete (l);
 			break;
-		case StyleParabel:
-			segment.clear();
+		case Parabel:
+			while (!segment.isEmpty()) delete segment.takeFirst();
 			break;
-		case StylePolyLine:
+		case PolyLine:
 			delete (p);
-			delete (l);
 			break;
-		case StylePolyParabel:
+		case PolyParabel:
 			delete (p);
-			segment.clear();
 			break;
 		default:
 			break;
@@ -62,49 +56,56 @@
 void LinkableMapObj::init ()
 {
     depth=-1;	
+	mapEditor=NULL;
     childObj=NULL;
     parObj=NULL;
     parObjTmpBuf=NULL;
-    parPos=QPoint(0,0);
-    childPos=QPoint(0,0);
+    parPos=QPointF(0,0);
+    childPos=QPointF(0,0);
 	link2ParPos=false;
     l=NULL;
-    orientation=OrientUndef;
+    orientation=UndefinedOrientation;
     linkwidth=20;		
 	thickness_start=8;
-    style=StyleUndef;
-	linkpos=LinkBottom;
-    segment.setAutoDelete (TRUE);
+    style=UndefinedStyle;
+	linkpos=Bottom;
     arcsegs=13;
-	QPointArray pa(arcsegs*2+2);
     
-    bottomline=new QCanvasLine(canvas);
-    bottomline->setPen( QPen(linkcolor, 1) );
-    bottomline->setZ(Z_LINK);
+// TODO instead of linkcolor pen.color() could be used	all around
+	pen.setWidth (1);
+	pen.setColor (linkcolor);
+	pen.setCapStyle ( Qt::RoundCap );
+	bottomline=scene->addLine(QLineF(1,1,1,1),pen);
+    bottomline->setZValue(Z_LINK);
     bottomline->show();
 
     // Prepare showing the selection of a MapObj
-    selbox = new QCanvasRectangle (canvas);
-    selbox->setZ(Z_SELBOX);
-    selbox->setBrush( QColor(255,255,0) );
-    selbox->setPen( QPen(QColor(255,255,0) ));
-    selbox->hide();
     selected=false;
 
-	// initialize frame
-	frame = new FrameObj (canvas);
-	
+	hideLinkUnselected=false;
+
+	topPad=botPad=leftPad=rightPad=0;
+
 	repositionRequest=false;
+
+	// Rel Positions
+	relPos=QPointF(0,0);
+	useRelPos=false;
+	useOrientation=true;
+
+	// Reset ID
+	objID="";
 }
 
 void LinkableMapObj::copy (LinkableMapObj* other)
 {
     MapObj::copy(other);
 	bboxTotal=other->bboxTotal;
-//    linkwidth=other->linkwidth;		
-
     setLinkStyle(other->style);
     setLinkColor (other->linkcolor);
+	relPos=other->relPos;
+	useOrientation=other->useOrientation;
+	objID=other->objID;
 }
 
 void LinkableMapObj::setChildObj(LinkableMapObj* o)
@@ -118,7 +119,7 @@
 	mapEditor=parObj->getMapEditor();
 }
 
-void LinkableMapObj::setParObjTmp(LinkableMapObj*,QPoint,int)
+void LinkableMapObj::setParObjTmp(LinkableMapObj*,QPointF,int)
 {
 }
 
@@ -126,66 +127,116 @@
 {
 }
 
-LinkStyle LinkableMapObj::getDefLinkStyle ()
+bool LinkableMapObj::hasParObjTmp()
 {
-	LinkStyle ls=mapEditor->getLinkStyle();
+	if (parObjTmpBuf) return true;
+	return false;
+}
+
+void LinkableMapObj::setUseRelPos (const bool &b)
+{
+	useRelPos=b;
+}
+
+void LinkableMapObj::setRelPos()
+{
+	if (parObj)
+	{	
+		relPos.setX (absPos.x() - parObj->getChildPos().x() );
+		relPos.setY (absPos.y() - parObj->getChildPos().y() );
+		parObj->calcBBoxSize();
+	}	
+}
+
+void LinkableMapObj::setRelPos(const QPointF &p)
+{
+	relPos=p;
+	if (parObj)
+	{		
+		parObj->calcBBoxSize();
+		requestReposition();
+	}
+}
+
+QPointF LinkableMapObj::getRelPos()
+{
+	if (!parObj) return QPointF();
+	return relPos;
+}
+
+qreal LinkableMapObj::getTopPad()
+{
+	return topPad;
+}
+
+qreal LinkableMapObj::getLeftPad()
+{
+	return leftPad;
+}
+
+qreal LinkableMapObj::getRightPad()
+{
+	return rightPad;
+}
+
+LinkableMapObj::Style LinkableMapObj::getDefLinkStyle ()
+{
+	if (!mapEditor) return UndefinedStyle;
+	Style ls=mapEditor->getMapLinkStyle();
 	switch (ls)
 	{
-		case StyleLine: 
+		case Line: 
 			return ls;
 			break;
-		case StyleParabel:
+		case Parabel:
 			return ls;
 			break;
-		case StylePolyLine:	
+		case PolyLine:	
 			if (depth>1)
-				return StyleLine;
+				return Line;
 			else	
 				return ls;
 			break;
-		case StylePolyParabel:	
+		case PolyParabel:	
 			if (depth>1)
-				return StyleParabel;
+				return Parabel;
 			else	
 				return ls;
 			break;
 		default: 
 			break;	
 	}	
-	return StyleUndef;
+	return UndefinedStyle;
 }
 
-void LinkableMapObj::setLinkStyle(LinkStyle newstyle)
+void LinkableMapObj::setLinkStyle(Style newstyle)
 {
+	//if (newstyle=style) return;
 	delLink();
 		
 	style=newstyle;
 
     if (childObj!=NULL && parObj != NULL)
     {
-		int i;
-		QCanvasLine* cl;
+		QGraphicsLineItem *cl;
 		switch (style)
 		{
-			case StyleUndef:
+			case UndefinedStyle:
 				bottomline->hide();
 				break;
-			case StyleLine: 
-				l = new QCanvasLine(canvas);
-				l->setPen( QPen(linkcolor, 1) );
-				l->setZ(Z_LINK);
+			case Line: 
+				l = scene->addLine(QLineF(1,1,1,1),pen);
+				l->setZValue(Z_LINK);
 				if (visible)
 					l->show();
 				else
 					l->hide();
 				break;
-			case StyleParabel:
-				for (i=0;i<arcsegs;i++)
+			case Parabel:
+				for (int i=0;i<arcsegs;i++)
 				{
-					cl = new QCanvasLine(canvas);
-					cl->setPen( QPen(linkcolor, 1) );
-					cl->setPoints( 0,0,i*10,100);
-					cl->setZ(Z_LINK);
+					cl = scene->addLine(QLineF(i*5,0,i*10,100),pen);
+					cl->setZValue(Z_LINK);
 					if (visible)
 						cl->show();
 					else
@@ -194,30 +245,18 @@
 				}
 				pa0.resize (arcsegs+1);
 				break;
-			case StylePolyLine:	
-				p = new QCanvasPolygon(canvas);
-				p->setBrush( linkcolor );
-				p->setZ(Z_LINK);
+			case PolyLine:	
+				p =scene->addPolygon(QPolygonF(),pen,linkcolor);
+				p->setZValue(Z_LINK);
 				if (visible)
 					p->show();
 				else
 					p->hide();
 				pa0.resize (3);
-				// TODO
-				// a bit awkward: draw the lines additionally to polygon, to avoid
-				// missing pixels, when polygon is extremly flat
-				l = new QCanvasLine(canvas);
-				l->setPen( QPen(linkcolor, 1) );
-				l->setZ(Z_LINK);
-				if (visible)
-					l->show();
-				else
-					l->hide();
 				break;
-			case StylePolyParabel:	
-				p = new QCanvasPolygon(canvas);
-				p->setBrush( linkcolor );
-				p->setZ(Z_LINK);
+			case PolyParabel:	
+				p = scene->addPolygon(QPolygonF(),pen,linkcolor);
+				p->setZValue(Z_LINK);
 				if (visible)
 					p->show();
 				else
@@ -225,83 +264,83 @@
 				pa0.resize (arcsegs*2+2);
 				pa1.resize (arcsegs+1);
 				pa2.resize (arcsegs+1);
-
-				// TODO
-				// a bit awkward: draw the lines additionally 
-				// to polygon, to avoid missing pixels, 
-				// if polygon is extremly flat
-				for (i=0;i<arcsegs;i++)
-				{
-					cl = new QCanvasLine(canvas);
-					cl->setPen( QPen(linkcolor, 1) );
-					cl->setPoints( 0,0,i*10,100);
-					cl->setZ(Z_LINK);
-					if (visible)
-						cl->show();
-					else
-						cl->hide();
-					segment.append(cl);
-				}
 				break;
 			default: 
 				break;	
 		}	
-	} else
-	{
-		cout << "Error: ChildObj or parObj == NULL in LinkableMapObj::setLinkStyle\n";
-	}
+	} 
 }
 
-LinkStyle LinkableMapObj::getLinkStyle()
+LinkableMapObj::Style LinkableMapObj::getLinkStyle()
 {
 	return style;
 }
 
-void LinkableMapObj::setLinkPos(LinkPos lp)
+void LinkableMapObj::setHideLinkUnselected(bool b)
+{
+	hideLinkUnselected=b;
+	setVisibility (visible);
+	updateLink();
+}
+
+bool LinkableMapObj::getHideLinkUnselected()
+{
+	return hideLinkUnselected;
+}
+
+void LinkableMapObj::setLinkPos(Position lp)
 {
 	linkpos=lp;
 }
 
-LinkPos LinkableMapObj::getLinkPos()
+LinkableMapObj::Position LinkableMapObj::getLinkPos()
 {
 	return linkpos;
 }
 
+void LinkableMapObj::setID (const QString &s)
+{
+	objID=s;
+}
+
+QString LinkableMapObj::getID()
+{
+	return objID;
+}
 
 void LinkableMapObj::setLinkColor()
 {
 	// Overloaded in BranchObj and childs
 	// here only set default color
-	setLinkColor (mapEditor->getDefLinkColor());
+	if (mapEditor)
+		setLinkColor (mapEditor->getMapDefLinkColor());
 }
 
 void LinkableMapObj::setLinkColor(QColor col)
 {
 	linkcolor=col;
-    bottomline->setPen( QPen(linkcolor, 1) );
-	QCanvasLine *cl;
+	pen.setColor(col);
+    bottomline->setPen( pen );
 	switch (style)
 	{
-		case StyleLine:
-			l->setPen( QPen(col,1));
+		case Line:
+			l->setPen( pen);
 			break;	
-		case StyleParabel:	
-			for (cl=segment.first(); cl; cl=segment.next() )
-				cl->setPen( QPen(col,1));
+		case Parabel:	
+			for (int i=0; i<segment.size(); ++i)
+				segment.at(i)->setPen( pen);
 			break;
-		case StylePolyLine:
+		case PolyLine:
 			p->setBrush( QBrush(col));
-			l->setPen( QPen(col,1));
+			p->setPen( pen);
 			break;
-		case StylePolyParabel:	
+		case PolyParabel:	
 			p->setBrush( QBrush(col));
-			for (cl=segment.first(); cl; cl=segment.next() )
-				cl->setPen( QPen(col,1));
+			p->setPen( pen);
 			break;
 		default:
 			break;
 	} // switch (style)	
-	updateLink();
 }
 
 QColor LinkableMapObj::getLinkColor()
@@ -309,58 +348,85 @@
 	return linkcolor;
 }
 
-FrameType LinkableMapObj::getFrameType()
-{
-	return frame->getFrameType();
-}
-
-void LinkableMapObj::setFrameType(const FrameType &t)
-{
-	frame->setFrameType(t);
-	calcBBoxSize();
-	positionBBox();
-	requestReposition();
-}
-
-void LinkableMapObj::setFrameType(const QString &t)
-{
-	frame->setFrameType(t);
-	calcBBoxSize();
-	positionBBox();
-	requestReposition();
-}
-
 void LinkableMapObj::setVisibility (bool v)
 {
 	MapObj::setVisibility (v);
-	if (visible) 
+	bool visnow=visible;
+
+	// We can hide the link, while object is not selected
+	if (hideLinkUnselected && !selected)
+		visnow=false;
+
+	if (visnow) 
 	{
 		bottomline->show();
-		// FIXME lines and segments should be done in LMO?
-		if (style==StyleLine && l) 
+		switch (style)
 		{
-			l->show();
-		} else
-		{
-			QCanvasLine* cl;
-			for (cl=segment.first(); cl; cl=segment.next() )
-				cl->show();
-		} 
+			case Line:
+				if (l) l->show();
+				break;
+			case Parabel:	
+				for (int i=0; i<segment.size(); ++i)
+					segment.at(i)->show();
+				break;	
+			case PolyLine:
+				if (p) p->show();
+				break;
+			case PolyParabel:	
+				if (p) p->show();
+				break;
+			default:
+				break;
+		}
 	} else 
 	{
 		bottomline->hide();
-		if (style==StyleLine && l) 
+		switch (style)
 		{
-			l->hide();
-		} else
-		{
-			QCanvasLine* cl;
-			for (cl=segment.first(); cl; cl=segment.next() )
-				cl->hide();
-		} 
+			case Line:
+				if (l) l->hide();
+				break;
+			case Parabel:	
+				for (int i=0; i<segment.size(); ++i)
+					segment.at(i)->hide();
+				break;	
+			case PolyLine:
+				if (p) p->hide();
+				break;
+			case PolyParabel:	
+				if (p) p->hide();
+				break;
+			default:
+				break;
+		}
 	}	
 }
 
+void LinkableMapObj::setOrientation()
+{
+	Orientation orientOld=orientation;
+
+	if (!parObj) 
+	{
+		orientation=UndefinedOrientation;
+		return;
+	}
+		
+    // Set orientation, first look for orientation of parent
+    if (parObj->getOrientation() != UndefinedOrientation ) 
+		// use the orientation of the parent:
+		orientation=parObj->getOrientation();
+    else
+    {
+		// calc orientation depending on position rel to parent
+		if (absPos.x() < QPointF(parObj->getChildPos() ).x() )
+			orientation=LeftOfCenter; 
+		else
+			orientation=RightOfCenter;
+    }
+	if (orientOld!=orientation) requestReposition();
+}
+
 void LinkableMapObj::updateLink()
 {
     // needs:
@@ -370,84 +436,38 @@
     // 
     // sets:
     //	orientation
-    //	childPos
-    //	parPos
-	//  offset
+    //	childPos	(by calling setDockPos())
+    //	parPos		(by calling setDockPos())
+	//  bottomlineY
     //	drawing of the link itself
 
-
 	// updateLink is called from move, but called from constructor we don't
 	// have parents yet...
-	if (style==StyleUndef) return;	
+	if (style==UndefinedStyle) return;	
 
-	if (frame->getFrameType() == NoFrame)
-		linkpos=LinkBottom;
-	else	
-		linkpos=LinkMiddle;
 	switch (linkpos)
 	{
-		case LinkMiddle:
-			offset=bbox.height() /2;
+		case Middle:
+			bottomlineY=bbox.top() + bbox.height()/2;	// draw link to middle (of frame)
 			break;
-		default :
-			offset=bbox.height()-1;			// draw link to bottom of bbox
+		case Bottom:
+			bottomlineY=bbox.bottom()-1;	// draw link to bottom of box
 			break;
 	}
 	
     double p2x,p2y;								// Set P2 Before setting
 	if (!link2ParPos)
 	{
-		p2x=QPoint( parObj->getChildPos() ).x();	// P1, we have to look at
-		p2y=QPoint( parObj->getChildPos() ).y();	// orientation
+		p2x=QPointF( parObj->getChildPos() ).x();	// P1, we have to look at
+		p2y=QPointF( parObj->getChildPos() ).y();	// orientation
 	} else	
 	{
-		p2x=QPoint( parObj->getParPos() ).x();	
-		p2y=QPoint( parObj->getParPos() ).y();
+		p2x=QPointF( parObj->getParPos() ).x();	
+		p2y=QPointF( parObj->getParPos() ).y();
 	} 
 
-	LinkOrient orientOld=orientation;
-
-    // Set orientation, first look for orientation of parent
-    if (parObj->getOrientation() != OrientUndef ) 
-		// use the orientation of the parent:
-		orientation=parObj->getOrientation();
-    else
-    {
-		// calc orientation depending on position rel to mapCenter
-		if (absPos.x() < QPoint(parObj->getChildPos() ).x() )
-			orientation=OrientLeftOfCenter; 
-		else
-			orientation=OrientRightOfCenter;
-    }
-
-	if ((orientation!=orientOld) && (orientOld!= OrientUndef))
-	{
-		// Orientation just changed. Reorient this subbranch, because move is called
-		// before updateLink => Position is still the old one, which could lead to 
-		// linking of subranch to itself => segfault
-		//
-		// Also possible: called in BranchObj::init(), then orientOld==OrientUndef,
-		// no need to reposition now
-		reposition();
-	}
-	
-    if (orientation==OrientLeftOfCenter )
-    {
-		childPos=QPoint (absPos.x(),absPos.y()+offset);
-		parPos=QPoint (absPos.x()+ bbox.width(), absPos.y() + offset );
-    } else
-    {
-		childPos=QPoint (absPos.x()+ bbox.width(), absPos.y() + offset ); 
-		parPos=QPoint (absPos.x(),absPos.y()+offset);
-    }
-	/* FIXME
-		cout << "      LMO::updateLink   absPos="<<absPos<<endl;
-		cout << "      LMO::updateLink childPos="<<childPos<<endl;
-		cout << "      LMO::updateLink   parPos="<<parPos<<endl;
-		cout << "      LMO::updateLink   offset="<<offset<<endl;
-		cout << "      LMO::updateLink   bbox.w="<<bbox.width()<<endl;
-		cout << "      LMO::updateLink   bbox.h="<<bbox.height()<<endl;
-	*/	
+	setDockPos(); // Call overloaded method
+	setOrientation();
 
 	double p1x=parPos.x();	// Link is drawn from P1 to P2
 	double p1y=parPos.y();
@@ -456,10 +476,11 @@
 	double vy=p2y - p1y;
 
 	// Draw the horizontal line below heading (from ChildPos to ParPos)
-	bottomline->setPoints (lrint(childPos.x()),
-		lrint(childPos.y()),
-		lrint(p1x),
-		lrint(p1y) );
+	//bottomline->prepareGeometryChange();
+	bottomline->setLine (QLine (qRound(childPos.x()),
+		qRound(childPos.y()),
+		qRound(p1x),
+		qRound(p1y) ));
 
 	double a;	// angle
 	if (vx > -0.000001 && vx < 0.000001)
@@ -467,57 +488,44 @@
 	else
 		a=atan( vy / vx );
 	// "turning point" for drawing polygonal links
-	QPoint tp (-lrint(sin (a)*thickness_start), lrint(cos (a)*thickness_start));	
+	QPointF tp (-qRound(sin (a)*thickness_start), qRound(cos (a)*thickness_start));	
 	
-	QCanvasLine *cl;
-
-	int i;
-
     // Draw the link
 	switch (style)
 	{
-		case StyleLine:
-			l->setPoints( lrint (parPos.x()),
-				lrint(parPos.y()),
-				lrint(p2x),
-				lrint(p2y) );
+		case Line:
+			//l->prepareGeometryChange();
+			l->setLine( QLine(qRound (parPos.x()),
+				qRound(parPos.y()),
+				qRound(p2x),
+				qRound(p2y) ));
 			break;	
-		case StyleParabel:	
+		case Parabel:	
 			parabel (pa0, p1x,p1y,p2x,p2y);
-			i=0;
-			for (cl=segment.first(); cl; cl=segment.next() )
-			{	
-				cl->setPoints( pa0.point(i).x(), pa0.point(i).y(),pa0.point(i+1).x(),pa0.point(i+1).y());
-				i++;
-			}
+			for (int i=0; i<segment.size(); ++i)
+			{
+				//segment.at(i)->prepareGeometryChange();
+				segment.at(i)->setLine(QLineF( pa0.at(i).x(), pa0.at(i).y(),pa0.at(i+1).x(),pa0.at(i+1).y()));
+			}	
 			break;
-		case StylePolyLine:
-			pa0[0]=QPoint (lrint(p2x+tp.x()), lrint(p2y+tp.y()));
-			pa0[1]=QPoint (lrint(p2x-tp.x()), lrint(p2y-tp.y()));
-			pa0[2]=QPoint (lrint (parPos.x()), lrint(parPos.y()) );
-			p->setPoints (pa0);
-			// here too, draw line to avoid missing pixels
-			l->setPoints( lrint (parPos.x()),
-				lrint(parPos.y()),
-				lrint(p2x),
-				lrint(p2y) );
+		case PolyLine:
+			pa0.clear();
+			pa0<<QPointF (qRound(p2x+tp.x()), qRound(p2y+tp.y()));
+			pa0<<QPointF (qRound(p2x-tp.x()), qRound(p2y-tp.y()));
+			pa0<<QPointF (qRound (parPos.x()), qRound(parPos.y()) );
+			//p->prepareGeometryChange();
+			p->setPolygon(QPolygonF (pa0));
 			break;
-		case StylePolyParabel:	
+		case PolyParabel:	
 			parabel (pa1, p1x,p1y,p2x+tp.x(),p2y+tp.y());
 			parabel (pa2, p1x,p1y,p2x-tp.x(),p2y-tp.y());
-			for (i=0;i<=arcsegs;i++)
-			{
-				// Combine the arrays to a single one
-				pa0[i]=pa1[i];
-				pa0[i+arcsegs+1]=pa2[arcsegs-i];
-			}	
-			p->setPoints (pa0);
-			i=0;
-			for (cl=segment.first(); cl; cl=segment.next() )
-			{	
-				cl->setPoints( pa1.point(i).x(), pa1.point(i).y(),pa1.point(i+1).x(),pa1.point(i+1).y());
-				i++;
-			}
+			pa0.clear();
+			for (int i=0;i<=arcsegs;i++)
+				pa0 << QPointF (pa1.at(i));
+			for (int i=0;i<=arcsegs;i++)
+				pa0 << QPointF (pa2.at(arcsegs-i));
+			//p->prepareGeometryChange();
+			p->setPolygon(QPolygonF (pa0));
 			break;
 		default:
 			break;
@@ -534,26 +542,59 @@
     return parObj;
 }
 
-QPoint LinkableMapObj::getChildPos()
+LinkableMapObj* LinkableMapObj::findObjBySelect (QString s)
+{
+	LinkableMapObj *lmo=this;
+	QString part;
+	QString typ;
+	QString num;
+	while (!s.isEmpty() )
+	{
+		part=s.section(",",0,0);
+		typ=part.left (3);
+		num=part.right(part.length() - 3);
+		if (typ=="mc:")
+		{
+			if (depth>0)
+				return false;	// in a subtree there is no center
+			else
+				break;
+		} else
+			if (typ=="bo:")
+				lmo=((BranchObj*)lmo)->getBranchNum (num.toInt());
+			else
+				if (typ=="fi:")
+					lmo=((BranchObj*)lmo)->getFloatImageNum (num.toUInt());
+		if (!lmo) break;
+		
+		if (s.contains(","))
+			s=s.right(s.length() - part.length() -1 );
+		else	
+			break;
+	}
+	return lmo;
+}
+
+QPointF LinkableMapObj::getChildPos()
 {
     return childPos;
 }
 
-QPoint LinkableMapObj::getParPos()
+QPointF LinkableMapObj::getParPos()
 {
     return parPos;
 }
 
-QPoint LinkableMapObj::getRelPos()
-{
-	if (!parObj) return QPoint (0,0);
-    return QPoint(
-		absPos.x() - parObj->x(),
-		absPos.y() - parObj->y()
-	);
+void LinkableMapObj::setUseOrientation (const bool &b)
+{	
+	if (useOrientation!=b)
+	{
+		useOrientation=b;
+		requestReposition();
+	}	
 }
 
-LinkOrient LinkableMapObj::getOrientation()
+LinkableMapObj::Orientation LinkableMapObj::getOrientation()
 {
     return orientation;
 }
@@ -573,36 +614,16 @@
 	return mapEditor;
 }
 
-QPoint LinkableMapObj::getRandPos()
+QPointF LinkableMapObj::getRandPos()
 {
 	// Choose a random position with given distance to parent:
 	double a=rand()%360 * 2 * M_PI / 360;
-    return QPoint ( (int)( + 150*cos (a)),
+    return QPointF ( (int)( + 150*cos (a)),
                     (int)( + 150*sin (a)));
 }
 
-void LinkableMapObj::alignRelativeTo (QPoint ref)
-{
-}
-
 void LinkableMapObj::reposition()
 {
-cout << "LMO::reposition  ???"<<endl;
-	if (depth==0)
-	{
-		// only calculate the sizes once. If the deepest LMO changes its height,
-		// all upper LMOs have to change, too.
-		calcBBoxSizeWithChilds();
-
-	    alignRelativeTo ( QPoint (absPos.x(),
-							absPos.y()-(bboxTotal.height()-bbox.height())/2) );
-	} else
-	{
-		// This is only important for moving branches:
-		// For editing a branch it isn't called...
-	    alignRelativeTo ( QPoint (absPos.x(),
-							absPos.y()-(bboxTotal.height()-bbox.height())/2) );
-	}
 }
 
 void LinkableMapObj::requestReposition()
@@ -626,14 +647,15 @@
 	// we want to block expensive repositioning, but just do it once at
 	// the end, thus check first:
 
-	if (mapEditor->blockReposition()) return;
+	if (mapEditor->isRepositionBlocked()) return;
 	
 	// Pass on the request to parental objects, if this hasn't been done yet
 	
 	if (parObj) 
 		parObj->forceReposition(); 
 	else 
-		reposition(); }
+		reposition(); 
+}
 
 bool LinkableMapObj::repositionRequested()
 {
@@ -641,28 +663,23 @@
 }
 
 
-void LinkableMapObj::setSelBox()
-{
-    selbox->setX (bbox.x() );
-    selbox->setY (bbox.y() );
-    selbox->setSize (bbox.width(), bbox.height() );
-}
-
 void LinkableMapObj::select()
 {
-	setSelBox();
+	// select and unselect are still needed to
+	// handle hiding of links
     selected=true;
-    selbox->show();
+	setVisibility (visible);
 }
 
 
 void LinkableMapObj::unselect()
 {
     selected=false;
-    selbox->hide();
+	// Maybe we have to hide the link:
+	setVisibility (visible);
 }
 
-void LinkableMapObj::parabel (QPointArray &ya, double p1x, double p1y, double p2x, double p2y)
+void LinkableMapObj::parabel (QPolygonF &ya, double p1x, double p1y, double p2x, double p2y)
 
 {
 	double vx=p2x - p1x;	// V=P2-P1
@@ -679,15 +696,24 @@
 	else	
 		m=(vy / (vx*vx));
 	dx=vx/(arcsegs);
-	int i;
-	ya.setPoint (0,QPoint (lrint(p1x),lrint(p1y)));
-	for (i=1;i<=arcsegs;i++)
+	ya.clear();
+	ya<<QPointF (p1x,p1y);
+	for (int i=1;i<=arcsegs;i++)
 	{	
 		pnx=p1x+dx;
 		pny=m*(pnx-parPos.x())*(pnx-parPos.x())+parPos.y();
-		ya.setPoint (i,QPoint (lrint(pnx),lrint(pny)));
+		ya<<QPointF (pnx,pny);
 		p1x=pnx;
 		p1y=pny;
 	}	
 }
 
+QString LinkableMapObj::getLinkAttr ()
+{
+	if (hideLinkUnselected)
+		return attribut ("hideLink","true");
+	else
+		return attribut ("hideLink","false");
+	
+}
+
diff -r 5c5b4464b24f -r 876eed30ba3b main.cpp
--- a/main.cpp	Fri Mar 05 20:16:46 2010 +0000
+++ b/main.cpp	Tue Mar 23 11:54:30 2010 +0000
@@ -1,4 +1,5 @@
 #include <QApplication>
+#include <cstdlib>
 
 #include "flagrowobj.h"
 #include "mainwindow.h"
diff -r 5c5b4464b24f -r 876eed30ba3b process.cpp
--- a/process.cpp	Fri Mar 05 20:16:46 2010 +0000
+++ b/process.cpp	Tue Mar 23 11:54:30 2010 +0000
@@ -1,13 +1,14 @@
 #include "process.h"
+#include <cstdlib>
 
 /////////////////////////////////////////////////////////////////
 // Process
 /////////////////////////////////////////////////////////////////
 Process::Process()
 {
-	connect( this, SIGNAL(readyReadStderr()),
+	connect( this, SIGNAL(readyReadStandardError()),
 			 this, SLOT(readProcErrout()) );
-	connect( this, SIGNAL(readyReadStdout()),
+	connect( this, SIGNAL(readyReadStandardOutput()),
 			 this, SLOT(readProcStdout()) );
 	clear();		 
 }
@@ -22,22 +23,14 @@
 	stdOut="";
 }
 
-void Process::waitFinished()
-{
-	while (isRunning())
-	{
-	// FIXME use some kind of sleep here...
-	}
-}
-
 void Process::readProcErrout()
 {
-	errOut+=readStderr();
+	errOut+=readAllStandardError();
 }
 
 void Process::readProcStdout()
 {
-	stdOut+=readStdout();
+	stdOut+=readAllStandardOutput();
 }
 
 QString Process::getErrout()
diff -r 5c5b4464b24f -r 876eed30ba3b xml-base.cpp
--- a/xml-base.cpp	Fri Mar 05 20:16:46 2010 +0000
+++ b/xml-base.cpp	Tue Mar 23 11:54:30 2010 +0000
@@ -4,6 +4,7 @@
 #include <QColor>
 #include <QTextStream>
 #include <iostream>
+#include <cstdlib>
 
 #include "misc.h"
 #include "settings.h"