mapeditor.cpp
author insilmaril
Tue, 15 Dec 2009 09:14:59 +0000
changeset 818 25ee6b988b73
parent 817 b486ffd0fa11
child 819 8f987e376035
permissions -rw-r--r--
Fixed A&O report to show subitems
     1 #include "mapeditor.h"
     2 
     3 #include <iostream>
     4 #include <cstdlib>
     5 #include <typeinfo>
     6 
     7 #include <QObject>
     8 
     9 #include "branchitem.h"
    10 #include "geometry.h"
    11 #include "mainwindow.h"
    12 #include "misc.h"
    13 #include "warningdialog.h"
    14 #include "xlinkitem.h"
    15 
    16 
    17 extern int statusbarTime;
    18 extern Main *mainWindow;
    19 extern QString tmpVymDir;
    20 extern QString clipboardDir;
    21 extern QString clipboardFile;
    22 extern bool clipboardEmpty;
    23 extern bool debug;
    24 
    25 extern QMenu* branchContextMenu;
    26 extern QMenu* floatimageContextMenu;
    27 extern QMenu* canvasContextMenu;
    28 
    29 extern Settings settings;
    30 extern QString iconPath;
    31 
    32 ///////////////////////////////////////////////////////////////////////
    33 ///////////////////////////////////////////////////////////////////////
    34 MapEditor::MapEditor( VymModel *vm) 
    35 {
    36 	//cout << "Constructor ME "<<this<<endl;
    37 	mapScene= new QGraphicsScene(NULL);
    38 	mapScene->setBackgroundBrush (QBrush(Qt::white, Qt::SolidPattern));
    39 
    40 	zoomFactor=zoomFactorTarget=1;
    41 
    42 	model=vm;
    43 	model->setScene (mapScene);
    44 	model->registerEditor(this);
    45 	model->makeDefault();	// No changes in model so far
    46 
    47     setScene (mapScene);
    48 
    49     printer=NULL;
    50 
    51 	// Create bitmap cursors, platform dependant
    52 	HandOpenCursor=QCursor (QPixmap(iconPath+"cursorhandopen.png"),1,1);		
    53 	PickColorCursor=QCursor ( QPixmap(iconPath+"cursorcolorpicker.png"), 5,27 ); 
    54 	CopyCursor=QCursor ( QPixmap(iconPath+"cursorcopy.png"), 1,1 ); 
    55 	XLinkCursor=QCursor ( QPixmap(iconPath+"cursorxlink.png"), 1,7 ); 
    56 
    57 	//setFocusPolicy (Qt::StrongFocus);	//FIXME-3
    58 
    59 	pickingColor=false;
    60 	drawingLink=false;
    61 	copyingObj=false;
    62 	objectMoved=false;
    63 
    64     editingBO=NULL;
    65     movingObj=NULL;
    66 
    67 	printFrame=true;
    68 	printFooter=true;
    69 
    70 	setAcceptDrops (true);	
    71 
    72 	//model->reposition();	//FIXME-3 really still needed?
    73 
    74 
    75 	// Shortcuts and actions
    76 	QAction *a;
    77     a = new QAction("Select upper branch", this);
    78 	a->setShortcut (Qt::Key_Up );
    79 	a->setShortcutContext (Qt::WidgetShortcut);
    80 	addAction (a);
    81     connect( a, SIGNAL( triggered() ), this, SLOT( cursorUp() ) );
    82 
    83     a = new QAction( "Select lower branch",this);
    84 	a->setShortcut ( Qt::Key_Down );
    85 	a->setShortcutContext (Qt::WidgetShortcut);
    86 	addAction (a);
    87     connect( a, SIGNAL( triggered() ), this, SLOT( cursorDown() ) );
    88 
    89     a = new QAction( "Select left branch", this);
    90 	a->setShortcut (Qt::Key_Left );
    91 //	a->setShortcutContext (Qt::WindowShortcut);
    92 	a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
    93 	addAction (a);
    94     connect( a, SIGNAL( triggered() ), this, SLOT( cursorLeft() ) );
    95 
    96     a = new QAction( "Select child branch", this);
    97 	a->setShortcut (Qt::Key_Right);
    98 	a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
    99 	addAction (a);
   100     connect( a, SIGNAL( triggered() ), this, SLOT( cursorRight() ) );
   101 
   102     a = new QAction(  "Select first branch", this);
   103 	a->setShortcut (Qt::Key_Home );
   104 	a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
   105 	addAction (a);
   106     connect( a, SIGNAL( triggered() ), this, SLOT( cursorFirst() ) );
   107 
   108     a = new QAction( "Select last branch",this);
   109 	a->setShortcut ( Qt::Key_End );
   110 	a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
   111 	addAction (a);
   112     connect( a, SIGNAL( triggered() ), this, SLOT( cursorLast() ) );
   113 
   114 	// Action to embed LineEdit for heading in Scene
   115 	editingHeading=false;
   116 	lineEdit=new QLineEdit;
   117 	lineEdit->hide();
   118 	QGraphicsProxyWidget *pw=scene()->addWidget (lineEdit);
   119 	pw->setZValue (Z_LINEEDIT);
   120 
   121 	a = new QAction( tr( "Edit heading","MapEditor" ), this);
   122 	a->setShortcut ( Qt::Key_Return );					//Edit heading
   123 	a->setShortcutContext (Qt::WidgetShortcut);
   124 	addAction (a);
   125     connect( a, SIGNAL( triggered() ), this, SLOT( editHeading() ) );
   126 	a = new QAction( tr( "Edit heading","MapEditor" ), this);
   127 	a->setShortcut ( Qt::Key_Enter);					//Edit heading
   128 	addAction (a);
   129     connect( a, SIGNAL( triggered() ), this, SLOT( editHeading() ) );
   130 
   131 	// Selections
   132 	selectionColor =QColor (255,255,0);
   133 	
   134 
   135 	// Attributes	//FIXME-2 testing only...
   136 	QString k;
   137 	AttributeDef *ad;
   138 	attrTable= new AttributeTable();
   139 	k="A - StringList";
   140 	ad=attrTable->addKey (k,StringList);
   141 	if (ad)
   142 	{
   143 		QStringList sl;
   144 		sl <<"val 1"<<"val 2"<< "val 3";
   145 		ad->setValue (QVariant (sl));
   146 	}
   147 	//attrTable->addValue ("Key A","P 1");
   148 	//attrTable->addValue ("Key A","P 2");
   149 	//attrTable->addValue ("Key A","P 3");
   150 	//attrTable->addValue ("Key A","P 4");
   151 	k="B - FreeString";
   152 	ad=attrTable->addKey (k,FreeString);
   153 	if (ad)
   154 	{
   155 		//attrTable->addValue ("Key B","w1");
   156 		//attrTable->addValue ("Key B","w2");
   157 	}
   158 	k="C - UniqueString";
   159 	ad=attrTable->addKey (k,UniqueString);
   160 	if (ad)
   161 	{
   162 	//attrTable->addKey ("Key Prio");
   163 	//attrTable->addValue ("Key Prio","Prio 1");
   164 	//attrTable->addValue ("Key Prio","Prio 2");
   165 	}
   166 }
   167 
   168 MapEditor::~MapEditor()
   169 {
   170 	//cout <<"Destructor MapEditor for "<<model->getMapName().toStdString()<<endl;
   171 	model->unregisterEditor(this);
   172 }
   173 
   174 VymModel* MapEditor::getModel()
   175 {
   176     return model;
   177 }
   178 
   179 QGraphicsScene * MapEditor::getScene()
   180 {
   181     return mapScene;
   182 }
   183 
   184 void MapEditor::scrollTo (const QModelIndex &index)	
   185 {
   186 	if (index.isValid())
   187 	{
   188 		LinkableMapObj* lmo=NULL;
   189 		TreeItem *ti= static_cast<TreeItem*>(index.internalPointer());
   190 		if (ti->getType()==TreeItem::Image ||ti->isBranchLikeType() )
   191 			lmo=((MapItem*)ti)->getLMO();
   192 		if (lmo) 
   193 		{
   194 			QRectF r=lmo->getBBox();
   195 			setScrollBarPosTarget (r);
   196 		}	
   197 	}
   198 }
   199 
   200 void MapEditor::setScrollBarPosTarget (const QRectF &rect)
   201 {
   202 	// Code copied from Qt sources
   203 	int xmargin=50;
   204 	int ymargin=50;
   205 
   206     qreal width = viewport()->width();
   207     qreal height = viewport()->height();
   208     QRectF viewRect = matrix().mapRect(rect);
   209 
   210     qreal left = horizontalScrollBar()->value();
   211     qreal right = left + width;
   212     qreal top = verticalScrollBar()->value();
   213     qreal bottom = top + height;
   214 
   215 	scrollBarPosTarget=getScrollBarPos();
   216 
   217     if (viewRect.left() <= left + xmargin) {
   218         // need to scroll from the left
   219   //      if (!d->leftIndent)
   220             scrollBarPosTarget.setX(int(viewRect.left() - xmargin - 0.5));
   221     }
   222     if (viewRect.right() >= right - xmargin) {
   223         // need to scroll from the right
   224 //        if (!d->leftIndent)
   225             scrollBarPosTarget.setX(int(viewRect.right() - width + xmargin + 0.5));
   226     }
   227     if (viewRect.top() <= top + ymargin) {
   228         // need to scroll from the top
   229    //     if (!d->topIndent)
   230             scrollBarPosTarget.setY(int(viewRect.top() - ymargin - 0.5));
   231     }
   232     if (viewRect.bottom() >= bottom - ymargin) {
   233         // need to scroll from the bottom
   234 //        if (!d->topIndent)
   235             scrollBarPosTarget.setY(int(viewRect.bottom() - height + ymargin + 0.5));
   236     }
   237 
   238 	if (scrollBarPosTarget==getScrollBarPos()) return;
   239 
   240 	if (scrollBarPosAnimation.state()==QtAbstractAnimation::Running)
   241 		scrollBarPosAnimation.stop();
   242 	
   243 	if (settings.value ("/animation/use/",true).toBool() )
   244 	{
   245 		scrollBarPosAnimation.setTargetObject (this);
   246 		scrollBarPosAnimation.setPropertyName ("scrollBarPos");
   247 		scrollBarPosAnimation.setDuration(1000);
   248 		scrollBarPosAnimation.setEasingCurve ( QtEasingCurve::OutQuint);
   249 		scrollBarPosAnimation.setStartValue(
   250 			QPointF (horizontalScrollBar()->value() ,
   251 					 verticalScrollBar()->value() ) );
   252 		scrollBarPosAnimation.setEndValue(scrollBarPosTarget);
   253 		scrollBarPosAnimation.start();
   254 	} else
   255 		setScrollBarPos (scrollBarPosTarget);
   256 }
   257 
   258 QPointF MapEditor::getScrollBarPosTarget()
   259 {
   260     return scrollBarPosTarget;
   261 }
   262 
   263 
   264 void MapEditor::setScrollBarPos(const QPointF &p)
   265 {
   266     scrollBarPos=p;
   267 	horizontalScrollBar()->setValue(int(p.x()));
   268 	verticalScrollBar()->setValue(int(p.y()));
   269 }
   270 
   271 QPointF MapEditor::getScrollBarPos()
   272 {
   273 	return QPointF (horizontalScrollBar()->value(),verticalScrollBar()->value());
   274     //return scrollBarPos;
   275 }
   276 
   277 void MapEditor::setZoomFactorTarget (const qreal &zft)
   278 {
   279 	zoomFactorTarget=zft;
   280 	if (zoomAnimation.state()==QtAbstractAnimation::Running)
   281 		zoomAnimation.stop();
   282 	if (settings.value ("/animation/use/",true).toBool() )
   283 	{
   284 		//zoomAnimation=QPropertyAnimation(this, "zoomFactor");
   285 		zoomAnimation.setTargetObject (this);
   286 		zoomAnimation.setPropertyName ("zoomFactor");
   287 		zoomAnimation.setDuration(1000);
   288 		zoomAnimation.setEasingCurve ( QtEasingCurve::OutQuint);
   289 		zoomAnimation.setStartValue(zoomFactor);
   290 		zoomAnimation.setEndValue(zft);
   291 		zoomAnimation.start();
   292 	} else
   293 		setZoomFactor (zft);
   294 }
   295 
   296 qreal MapEditor::getZoomFactorTarget()
   297 {
   298     return zoomFactorTarget;
   299 }
   300 
   301 
   302 void MapEditor::setZoomFactor(const qreal &zf)
   303 {
   304     zoomFactor=zf;
   305 	setMatrix (QMatrix(zf, 0, 0, zf, 0, 0),false );
   306 }
   307 
   308 qreal MapEditor::getZoomFactor()
   309 {
   310     return zoomFactor;
   311 }
   312 
   313 void MapEditor::print()
   314 {
   315 	if ( !printer ) 
   316 	{
   317 		printer = new QPrinter;
   318 		printer->setColorMode (QPrinter::Color);
   319 		printer->setPrinterName (settings.value("/mainwindow/printerName",printer->printerName()).toString());
   320 		printer->setOutputFormat((QPrinter::OutputFormat)settings.value("/mainwindow/printerFormat",printer->outputFormat()).toInt());
   321 		printer->setOutputFileName(settings.value("/mainwindow/printerFileName",printer->outputFileName()).toString());
   322 	}
   323 
   324 	QRectF totalBBox=getTotalBBox();
   325 
   326 	// Try to set orientation automagically
   327 	// Note: Interpretation of generated postscript is amibiguous, if 
   328 	// there are problems with landscape mode, see
   329 	// http://sdb.suse.de/de/sdb/html/jsmeix_print-cups-landscape-81.html
   330 
   331 	if (totalBBox.width()>totalBBox.height())
   332 		// recommend landscape
   333 		printer->setOrientation (QPrinter::Landscape);
   334 	else	
   335 		// recommend portrait
   336 		printer->setOrientation (QPrinter::Portrait);
   337 
   338 	if ( printer->setup(this) ) 
   339 	// returns false, if printing is canceled
   340 	{
   341 		QPainter pp(printer);
   342 
   343 		pp.setRenderHint(QPainter::Antialiasing,true);
   344 
   345 		// Don't print the visualisation of selection
   346 		model->unselect();
   347 
   348 		QRectF mapRect=totalBBox;
   349 		QGraphicsRectItem *frame=NULL;
   350 
   351 		if (printFrame) 
   352 		{
   353 			// Print frame around map
   354 			mapRect.setRect (totalBBox.x()-10, totalBBox.y()-10, 
   355 				totalBBox.width()+20, totalBBox.height()+20);
   356 			frame=mapScene->addRect (mapRect, QPen(Qt::black),QBrush(Qt::NoBrush));
   357 			frame->setZValue(0);
   358 			frame->show();    
   359 		}		
   360 
   361 
   362 		double paperAspect = (double)printer->width()   / (double)printer->height();
   363 		double   mapAspect = (double)mapRect.width() / (double)mapRect.height();
   364 		int viewBottom;
   365 		if (mapAspect>=paperAspect)
   366 		{
   367 			// Fit horizontally to paper width
   368 			//pp.setViewport(0,0, printer->width(),(int)(printer->width()/mapAspect) );	
   369 			viewBottom=(int)(printer->width()/mapAspect);	
   370 		}	else
   371 		{
   372 			// Fit vertically to paper height
   373 			//pp.setViewport(0,0,(int)(printer->height()*mapAspect),printer->height());	
   374 			viewBottom=printer->height();	
   375 		}	
   376 		
   377 		if (printFooter) 
   378 		{
   379 			// Print footer below map
   380 			QFont font;		
   381 			font.setPointSize(10);
   382 			pp.setFont (font);
   383 			QRectF footerBox(0,viewBottom,printer->width(),15);
   384 			// FIXME-3 fileName not any longer available here: pp.drawText ( footerBox,Qt::AlignLeft,"VYM - " +fileName);
   385 			pp.drawText ( footerBox, Qt::AlignRight, QDate::currentDate().toString(Qt::TextDate));
   386 		}
   387 		mapScene->render (
   388 			&pp, 
   389 			QRectF (0,0,printer->width(),printer->height()-15),
   390 			QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height())
   391 		);
   392 		
   393 		// Viewport has paper dimension
   394 		if (frame)  delete (frame);
   395 
   396 		// Restore selection
   397 		model->reselect();
   398 
   399 		// Save settings in vymrc
   400 		settings.writeEntry("/mainwindow/printerName",printer->printerName());
   401 		settings.writeEntry("/mainwindow/printerFormat",printer->outputFormat());
   402 		settings.writeEntry("/mainwindow/printerFileName",printer->outputFileName());
   403 	}
   404 }
   405 
   406 QRectF MapEditor::getTotalBBox()	
   407 {
   408 	QRectF r;
   409 	BranchObj *bo;
   410 	for (int i=0;i<model->getRootItem()->branchCount(); i++)
   411 	{
   412 		bo=(BranchObj*)(model->getRootItem()->getBranchNum(i)->getLMO());
   413 		if (bo) r=addBBox (bo->getTotalBBox(), r);
   414 	}
   415 	return r;	
   416 }
   417 
   418 
   419 QPixmap MapEditor::getPixmap()
   420 {
   421 	QRectF mapRect=getTotalBBox();
   422 	QPixmap pix((int)mapRect.width()+2,(int)mapRect.height()+2);
   423 	QPainter pp (&pix);
   424 	
   425 	pp.setRenderHints(renderHints());
   426 
   427 	// Don't print the visualisation of selection
   428 	model->unselect();
   429 
   430 	mapScene->render (	&pp, 
   431 		QRectF(0,0,mapRect.width()+2,mapRect.height()+2),
   432 		QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height() ));
   433 
   434 	// Restore selection
   435 	model->reselect();
   436 	
   437 	return pix;
   438 }
   439 
   440 
   441 void MapEditor::setAntiAlias (bool b)
   442 {
   443 	setRenderHint(QPainter::Antialiasing,b);
   444 }
   445 
   446 void MapEditor::setSmoothPixmap(bool b)
   447 {
   448 	setRenderHint(QPainter::SmoothPixmapTransform,b);
   449 }
   450 
   451 TreeItem* MapEditor::findMapItem (QPointF p,TreeItem *exclude)
   452 {
   453 	// Start with mapcenter, no images allowed at rootItem
   454 	int i=0;
   455 	BranchItem *bi=model->getRootItem()->getFirstBranch();
   456 	TreeItem *found=NULL;
   457 	while (bi)
   458 	{
   459 		found=bi->findMapItem (p, exclude);
   460 		if (found) return found;
   461 		i++;
   462 		bi=model->getRootItem()->getBranchNum(i);
   463 	}
   464 	return NULL;
   465 }
   466 
   467 AttributeTable* MapEditor::attributeTable()
   468 {
   469 	return attrTable;
   470 }
   471 
   472 void MapEditor::testFunction1()
   473 {
   474 	cout << "ME::test1  selected TI="<<model->getSelectedItem()<<endl;
   475 
   476 	for (int i=0; i<200;i++)
   477 		model->addNewBranch();
   478 
   479 	/*
   480 	// Code copied from Qt sources
   481 	QRectF rect=model->getSelectedBranchObj()->getBBox();
   482 	int xmargin=50;
   483 	int ymargin=50;
   484 
   485     qreal width = viewport()->width();
   486     qreal height = viewport()->height();
   487     QRectF viewRect = matrix().mapRect(rect);
   488 
   489     qreal left = horizontalScrollBar()->value();
   490     qreal right = left + width;
   491     qreal top = verticalScrollBar()->value();
   492     qreal bottom = top + height;
   493 
   494     if (viewRect.left() <= left + xmargin) {
   495         // need to scroll from the left
   496   //      if (!d->leftIndent)
   497             horizontalScrollBar()->setValue(int(viewRect.left() - xmargin - 0.5));
   498     }
   499     if (viewRect.right() >= right - xmargin) {
   500         // need to scroll from the right
   501 //        if (!d->leftIndent)
   502             horizontalScrollBar()->setValue(int(viewRect.right() - width + xmargin + 0.5));
   503     }
   504     if (viewRect.top() <= top + ymargin) {
   505         // need to scroll from the top
   506    //     if (!d->topIndent)
   507             verticalScrollBar()->setValue(int(viewRect.top() - ymargin - 0.5));
   508     }
   509     if (viewRect.bottom() >= bottom - ymargin) {
   510         // need to scroll from the bottom
   511 //        if (!d->topIndent)
   512             verticalScrollBar()->setValue(int(viewRect.bottom() - height + ymargin + 0.5));
   513     }
   514 	cout << "test1:  hor="<<horizontalScrollBar()->value()<<endl;
   515 	cout << "test1:  ver="<<verticalScrollBar()->value()<<endl;
   516 }
   517 
   518 */
   519 /*
   520 	 QtPropertyAnimation *animation=new QtPropertyAnimation(this, "sceneRect");
   521 	 animation->setDuration(5000);
   522 	 //animation->setEasingCurve ( QtEasingCurve::OutElastic);
   523 	 animation->setEasingCurve ( QtEasingCurve::OutQuint);
   524 	 animation->setStartValue(sceneRect() );
   525 	 animation->setEndValue(QRectF(50, 50, 1000, 1000));
   526 
   527 	 animation->start();
   528 */	 
   529 /*
   530 	QDialog *dia= new QDialog (this);
   531 	dia->setGeometry (50,50,10,10);
   532 
   533      dia->show();
   534      dia ->raise();
   535 
   536 	 QtPropertyAnimation *animation=new QtPropertyAnimation(dia, "geometry");
   537 	 animation->setDuration(1000);
   538 	 //animation->setEasingCurve ( QtEasingCurve::OutElastic);
   539 	 animation->setEasingCurve ( QtEasingCurve::OutQuint);
   540 	 animation->setStartValue(QRect(50, 50, 10, 10));
   541 	 animation->setEndValue(QRect(250, 250, 100, 100));
   542 
   543 	 animation->start();
   544  */
   545 
   546 /* FIXME-4 Hide hidden stuff temporary, maybe add this as regular function somewhere
   547 	if (hidemode==HideNone)
   548 	{
   549 		setHideTmpMode (HideExport);
   550 		mapCenter->calcBBoxSizeWithChilds();
   551 		QRectF totalBBox=mapCenter->getTotalBBox();
   552 		QRectF mapRect=totalBBox;
   553 		QCanvasRectangle *frame=NULL;
   554 
   555 		cout << "  map has =("<<totalBBox.x()<<","<<totalBBox.y()<<","<<totalBBox.width()<<","<<totalBBox.height()<<")\n";
   556 	
   557 		mapRect.setRect (totalBBox.x(), totalBBox.y(), 
   558 			totalBBox.width(), totalBBox.height());
   559 		frame=new QCanvasRectangle (mapRect,mapScene);
   560 		frame->setBrush (QColor(white));
   561 		frame->setPen (QColor(black));
   562 		frame->setZValue(0);
   563 		frame->show();    
   564 	}	
   565 	else	
   566 	{
   567 		setHideTmpMode (HideNone);
   568 	}	
   569 	cout <<"  hidemode="<<hidemode<<endl;
   570 	*/
   571 
   572 /*
   573 	// Toggle hidemode
   574 	if (hidemode==HideExport)
   575 		setHideTmpMode (HideNone);
   576 	else	
   577 		setHideTmpMode (HideExport);
   578 */		
   579 
   580 }
   581 	
   582 void MapEditor::testFunction2()
   583 {
   584 	// Create list with all bounding polygons
   585 	QList <LinkableMapObj*> mapobjects;
   586 	QList <ConvexPolygon> polys; 
   587 	ConvexPolygon p;
   588 	QList <Vector> vectors;
   589 	QList <Vector> orgpos;
   590 	QStringList headings;	//FIXME-3 testing only
   591 	Vector v;
   592 	BranchItem *bi;
   593 	BranchItem *bi2;
   594 	BranchObj *bo;
   595 
   596 	// Outer loop: Iterate until we no more changes in orientation 
   597 	bool orientationChanged=true;
   598 	while (orientationChanged)
   599 	{
   600 		BranchItem *ri=model->getRootItem();
   601 		for (int i=0;i<ri->branchCount();++i)
   602 		{
   603 			bi=ri->getBranchNum (i);
   604 			bo=(BranchObj*)bi->getLMO();
   605 			if (bo)
   606 			{
   607 				mapobjects.append (bo);
   608 				p=bo->getBoundingPolygon();
   609 				p.calcCentroid();
   610 				polys.append(p);
   611 				vectors.append (QPointF(0,0));
   612 				orgpos.append (p.at(0));
   613 				headings.append (bi->getHeading());
   614 			}
   615 			for (int j=0;j<bi->branchCount();++j)
   616 			{
   617 				bi2=bi->getBranchNum (j);
   618 				bo=(BranchObj*)bi2->getLMO();
   619 				if (bo)
   620 				{
   621 					mapobjects.append (bo);
   622 					p=bo->getBoundingPolygon();
   623 					p.calcCentroid();
   624 					polys.append(p);
   625 					vectors.append (QPointF(0,0));
   626 					orgpos.append (p.at(0));
   627 					headings.append (bi2->getHeading());
   628 				}	
   629 			}
   630 		}
   631 
   632 		// Iterate moving bounding polygons until we have no more collisions
   633 		int collisions=1;
   634 		while (collisions>0)
   635 		{
   636 			collisions=0;
   637 			for (int i=0; i<polys.size()-1; ++i)
   638 			{
   639 				for (int j=i+1; j<polys.size();++j)
   640 				{
   641 					if (polygonCollision (polys.at(i),polys.at(j), QPointF(0,0)).intersect )
   642 					{
   643 						collisions++;
   644 						//cout << "Collision: "<<headings[i].toStdString()<<" - "<<headings[j].toStdString()<<endl;
   645 						v=polys.at(j).centroid()-polys.at(i).centroid();
   646 						// Move also away if centroids are identical
   647 						if (v.isNull()) 
   648 						{
   649 							//cout << "v==0="<<polys[i].centroid()<<polys[j].centroid()<<" "<<v<<endl;
   650 							v.setX (rand()%200 -100);
   651 							v.setY (rand()%200 -100);
   652 							//cout << v;
   653 						}
   654 						v.normalize();
   655 						v.scale (2);
   656 						//cout <<  "  v="<<v<<endl;
   657 						vectors[j]=v;
   658 						vectors[i]=v;
   659 						vectors[i].invert();
   660 					}  
   661 				}
   662 			}
   663 			for (int i=0;i<vectors.size();i++)
   664 			{
   665 				//cout << " v="<<vectors[i]<<" "<<headings[i].toStdString()<<endl;
   666 				polys[i].translate (vectors[i]);
   667 			}
   668 			cout << "Collisions: "<<collisions<<endl;
   669 			//collisions=0;
   670 		}	
   671 
   672 		// Finally move the real objects and update 
   673 		QList <LinkableMapObj::Orientation> orients;
   674 		for (int i=0;i<polys.size();i++)
   675 		{
   676 			Vector v=polys[i].at(0)-orgpos[i];
   677 			orients.append (mapobjects[i]->getOrientation());
   678 			mapobjects[i]->moveBy(v.x(),v.y() );
   679 			mapobjects[i]->setRelPos();
   680 		}	
   681 		model->reposition();	
   682 		orientationChanged=false;
   683 		for (int i=0;i<polys.size();i++)
   684 			if (orients[i]!=mapobjects[i]->getOrientation())
   685 			{
   686 				orientationChanged=true;
   687 				break;
   688 			}
   689 		cout << "Final: orientChanged="<<orientationChanged<<endl;
   690 		break;
   691 		//orientationChanged=false;
   692 	} // loop if orientation has changed
   693 
   694 	model->emitSelectionChanged();
   695 }
   696 
   697 BranchItem* MapEditor::getBranchDirectAbove (BranchItem *bi)
   698 {
   699 	if (bi)
   700 	{
   701 		int i=bi->num();
   702 		if (i>0) return bi->parent()->getBranchNum(i-1);
   703 	}
   704 	return NULL;
   705 }
   706 
   707 BranchItem* MapEditor::getBranchAbove (BranchItem *selbi)
   708 {
   709 	if (selbi)
   710 	{
   711 		int dz=selbi->depth();	// original depth
   712 		bool invert=false;
   713 		if (selbi->getLMO()->getOrientation()==LinkableMapObj::LeftOfCenter)
   714 			invert=true;
   715 
   716 		BranchItem *bi;
   717 
   718 		// Look for branch with same parent but directly above
   719 		if (dz==1 && invert)
   720 			bi=getBranchDirectBelow(selbi);
   721 		else
   722 			bi=getBranchDirectAbove (selbi);
   723 
   724 		if (bi) 
   725 			// direct predecessor
   726 			return bi;
   727 
   728 		// Go towards center and look for predecessor
   729 		while (selbi->depth()>0)
   730 		{
   731 			selbi=(BranchItem*)(selbi->parent());
   732 			if (selbi->depth()==1 && invert)
   733 				bi=getBranchDirectBelow (selbi);
   734 			else
   735 				bi=getBranchDirectAbove (selbi);
   736 			if (bi)
   737 			{
   738 				// turn 
   739 				selbi=bi;
   740 				while (selbi->depth()<dz)
   741 				{
   742 					// try to get back to original depth dz
   743 					bi=selbi->getLastBranch();
   744 					if (!bi) 
   745 					{
   746 						return selbi;
   747 					}
   748 					selbi=bi;
   749 				}
   750 				return selbi;
   751 			}
   752 		}
   753 	}
   754 	return NULL;
   755 }
   756 
   757 BranchItem* MapEditor::getBranchDirectBelow(BranchItem *bi)
   758 {
   759 	if (bi)
   760 	{
   761 		int i=bi->num();
   762 		if (i+1<bi->parent()->branchCount()) return bi->parent()->getBranchNum(i+1);
   763 	}
   764 	return NULL;
   765 }
   766 
   767 BranchItem* MapEditor::getBranchBelow (BranchItem *selbi)
   768 {
   769 	if (selbi)
   770 	{
   771 		BranchItem *bi;
   772 		int dz=selbi->depth();	// original depth
   773 		bool invert=false;
   774 		if (selbi->getLMO()->getOrientation()==LinkableMapObj::LeftOfCenter)
   775 			invert=true;
   776 
   777 
   778 		// Look for branch with same parent but directly below
   779 		if (dz==1 && invert)
   780 			bi=getBranchDirectAbove (selbi);
   781 		else
   782 			bi=getBranchDirectBelow (selbi);
   783 		if (bi) 
   784 			// direct successor
   785 			return bi;
   786 
   787 
   788 		// Go towards center and look for neighbour
   789 		while (selbi->depth()>0)
   790 		{
   791 			selbi=(BranchItem*)(selbi->parent());
   792 			if (selbi->depth()==1 && invert)
   793 				bi=getBranchDirectAbove (selbi);
   794 			else
   795 				bi=getBranchDirectBelow (selbi);
   796 			if (bi)
   797 			{
   798 				// turn 
   799 				selbi=bi;
   800 				while (selbi->depth()<dz)
   801 				{
   802 					// try to get back to original depth dz
   803 					bi=selbi->getFirstBranch();
   804 					if (!bi) 
   805 					{
   806 						return selbi;
   807 					}
   808 					selbi=bi;
   809 				}
   810 				return selbi;
   811 			}
   812 		}
   813 	}
   814 	return NULL;
   815 }
   816 
   817 BranchItem* MapEditor::getLeftBranch (BranchItem *bi)
   818 {
   819 	if (bi)
   820 	{
   821 		if (bi->depth()==0)
   822 			// Special case: use alternative selection index
   823 			return bi->getLastSelectedBranchAlt();	
   824 		if (bi->getBranchObj()->getOrientation()==LinkableMapObj::RightOfCenter)	
   825 			// right of center
   826 			return (BranchItem*)(bi->parent());
   827 		else
   828 			// left of center
   829 			if (bi->getType()== TreeItem::Branch )
   830 				return bi->getLastSelectedBranch();
   831 	}
   832 	return NULL;
   833 }
   834 
   835 BranchItem* MapEditor::getRightBranch(BranchItem *bi)
   836 {
   837 	if (bi)
   838 	{
   839 		if (bi->depth()==0) return bi->getLastSelectedBranch();	
   840 		if (bi->getBranchObj()->getOrientation()==LinkableMapObj::LeftOfCenter)	
   841 			// left of center
   842 			return (BranchItem*)(bi->parent());
   843 		else
   844 			// right of center
   845 			if (bi->getType()== TreeItem::Branch )
   846 				return (BranchItem*)bi->getLastSelectedBranch();
   847 	}
   848 	return NULL;
   849 }
   850 
   851 
   852 
   853 void MapEditor::cursorUp()
   854 {
   855 	BranchItem *bi=model->getSelectedBranch();
   856 	if (bi) model->select (getBranchAbove(bi));
   857 }
   858 
   859 void MapEditor::cursorDown()	
   860 
   861 {
   862 	BranchItem *bi=model->getSelectedBranch();
   863 	if (bi) model->select (getBranchBelow(bi));
   864 }
   865 
   866 void MapEditor::cursorLeft()
   867 {
   868 	BranchItem *bi=getLeftBranch (model->getSelectedBranch());
   869 	if (bi) model->select (bi);
   870 }
   871 
   872 void MapEditor::cursorRight()	
   873 {
   874 	BranchItem *bi=getRightBranch (model->getSelectedBranch());
   875 	if (bi) model->select (bi);
   876 }
   877 
   878 void MapEditor::cursorFirst()	
   879 {
   880 	model->selectFirstBranch();
   881 }
   882 
   883 void MapEditor::cursorLast()	
   884 {
   885 	model->selectLastBranch();
   886 }
   887 
   888 
   889 void MapEditor::editHeading()
   890 {
   891 	if (editingHeading)
   892 	{
   893 		editHeadingFinished();
   894 		return;
   895 	}
   896 	BranchObj *bo=model->getSelectedBranchObj();
   897 	BranchItem *bi=model->getSelectedBranch();
   898 	if (bo)	
   899 	{
   900 		model->setSelectionBlocked(true);
   901 
   902 		lineEdit->setText (bi->getHeading());
   903 		QPoint p = mapTo (this,bo->getAbsPos().toPoint() );
   904 		lineEdit->setGeometry(p.x(),p.y(),230,25);
   905 		//lineEdit->selectAll();
   906 		//lineEdit->setCursorPosition (1);
   907 		lineEdit->show();
   908 		lineEdit->setFocus();
   909 		lineEdit->grabKeyboard();
   910 		editingHeading=true;
   911 	}
   912 
   913 }
   914 void MapEditor::editHeadingFinished()
   915 {
   916 	editingHeading=false;
   917 	lineEdit->releaseKeyboard();
   918 	model->setHeading (lineEdit->text() );
   919 	model->setSelectionBlocked(false);
   920 	lineEdit->hide();
   921 
   922 	// Maybe reselect previous branch 
   923 	mainWindow->editHeadingFinished (model);
   924 }
   925 
   926 
   927 void MapEditor::contextMenuEvent ( QContextMenuEvent * e )
   928 {
   929 	// Lineedits are already closed by preceding
   930 	// mouseEvent, we don't need to close here.
   931 
   932     QPointF p = mapToScene(e->pos());
   933     TreeItem *ti=findMapItem (p, NULL);
   934     LinkableMapObj* lmo=NULL;
   935 	if (ti) lmo=((MapItem*)ti)->getLMO();
   936 	
   937     if (lmo) 
   938 	{	// MapObj was found
   939 		if (model->getSelectedLMO() != lmo)
   940 		{
   941 			// select the MapObj
   942 			model->select(lmo);
   943 		}
   944 		// Context Menu 
   945 		if (model->getSelectedBranchObj() ) 
   946 		{
   947 			// Context Menu on branch or mapcenter
   948 			branchContextMenu->popup(e->globalPos() );
   949 		} else
   950 		{
   951 			if (model->getSelectedImage() )
   952 			{
   953 				// Context Menu on floatimage
   954 				floatimageContextMenu->popup(e->globalPos() );
   955 			}	
   956 		}	
   957 	} else 
   958 	{ // No MapObj found, we are on the Canvas itself
   959 		// Context Menu on scene
   960 		
   961 		// Open context menu synchronously to position new mapcenter
   962 		model->setContextPos (p);
   963 		canvasContextMenu->exec(e->globalPos() );
   964 		model->unsetContextPos ();
   965     } 
   966 	e->accept();
   967 }
   968 
   969 void MapEditor::keyPressEvent(QKeyEvent* e)
   970 {
   971 	if (e->modifiers() & Qt::ControlModifier)
   972 	{
   973 		switch (mainWindow->getModMode())
   974 		{
   975 			case Main::ModModeColor: 
   976 				setCursor (PickColorCursor);
   977 				break;
   978 			case Main::ModModeCopy: 
   979 				setCursor (CopyCursor);
   980 				break;
   981 			case Main::ModModeXLink: 
   982 				setCursor (XLinkCursor);
   983 				break;
   984 			default :
   985 				setCursor (Qt::ArrowCursor);
   986 				break;
   987 		} 
   988 	}	
   989 }
   990 
   991 void MapEditor::keyReleaseEvent(QKeyEvent* e)
   992 {
   993 	if (!(e->modifiers() & Qt::ControlModifier))
   994 		setCursor (Qt::ArrowCursor);
   995 }
   996 
   997 void MapEditor::mousePressEvent(QMouseEvent* e)
   998 {
   999 //cout << "ME::mousePressed\n"; //FIXME-3
  1000 	// Ignore right clicks, these will go to context menus
  1001 	if (e->button() == Qt::RightButton )
  1002 	{
  1003 		//cout << "  ME::ignoring right mouse event...\n";
  1004 		e->ignore();
  1005 		return;
  1006 	}
  1007 
  1008 	//Ignore clicks while editing heading
  1009 	if (model->isSelectionBlocked() ) 
  1010 	{
  1011 		//cout << "  ME::ignoring other mouse event...\n";
  1012 		e->ignore();
  1013 		return;
  1014 	}
  1015 
  1016     QPointF p = mapToScene(e->pos());
  1017     TreeItem *ti=findMapItem (p, NULL);
  1018     LinkableMapObj* lmo=NULL;
  1019 	if (ti) lmo=((MapItem*)ti)->getLMO();
  1020 	
  1021 	
  1022 	e->accept();
  1023 
  1024 	//Take care of  system flags _or_ modifier modes
  1025 	//
  1026 	if (lmo && ti->isBranchLikeType() )
  1027 	{
  1028 		QString foname=((BranchObj*)lmo)->getSystemFlagName(p);
  1029 		if (!foname.isEmpty())
  1030 		{
  1031 			// systemFlag clicked
  1032 			model->select (lmo);	
  1033 			if (foname=="system-url") 
  1034 			{
  1035 				if (e->state() & Qt::ControlModifier)
  1036 					mainWindow->editOpenURLTab();
  1037 				else	
  1038 					mainWindow->editOpenURL();
  1039 			}	
  1040 			else if (foname=="system-vymLink")
  1041 			{
  1042 				mainWindow->editOpenVymLink();
  1043 				// tabWidget may change, better return now
  1044 				// before segfaulting...
  1045 			} else if (foname=="system-note")
  1046 				mainWindow->windowToggleNoteEditor();
  1047 			else if (foname=="hideInExport")		
  1048 				model->toggleHideExport();
  1049 			// FIXME-3 needed? xelection.update();	
  1050 			return;	
  1051 		} else
  1052 		{
  1053 			// Take care of xLink
  1054 			if (ti->xlinkCount()>0 && lmo->getBBox().width()>30)
  1055 			{
  1056 				if ((lmo->getOrientation()!=LinkableMapObj::RightOfCenter && p.x() < lmo->getBBox().left()+20)  ||
  1057 				    (lmo->getOrientation()!=LinkableMapObj::LeftOfCenter && p.x() > lmo->getBBox().right()-20) ) 
  1058 				{
  1059 					// FIXME-4 if (ti->xlinkCount()>1)
  1060 					if (true)
  1061 					{
  1062 						QMenu menu;
  1063 						QList <QAction*> alist;
  1064 						for (int i=0;i<ti->xlinkCount();i++)
  1065 							alist.append (new QAction(ti->getXLinkNum(i)->getOtherBranch(ti)->getHeading(),&menu));
  1066 						menu.addActions (alist);	
  1067 						QAction *ra=menu.exec (e->globalPos() );
  1068 						if (ra)
  1069 							model->select (ti->getXLinkNum(alist.indexOf(ra))->getOtherBranch (ti));
  1070 						while (!alist.isEmpty())
  1071 						{
  1072 							QAction *a=alist.takeFirst();
  1073 							delete a;
  1074 						}	
  1075 						return;
  1076 					} else
  1077 					{
  1078 						model->select (ti->getXLinkNum(0)->getOtherBranch (ti));
  1079 						return;
  1080 					}
  1081 				}	
  1082 			}
  1083 		}
  1084 	}	
  1085 
  1086 	// No system flag clicked, take care of modmodes (CTRL-Click)
  1087 	if (e->state() & Qt::ControlModifier)
  1088 	{
  1089 		if (mainWindow->getModMode()==Main::ModModeColor)
  1090 		{
  1091 				pickingColor=true;
  1092 				setCursor (PickColorCursor);
  1093 				return;
  1094 		} 
  1095 		if (mainWindow->getModMode()==Main::ModModeXLink)
  1096 		{	
  1097 			BranchItem *bi_begin=model->getSelectedBranch();
  1098 			if (bi_begin)	
  1099 			{
  1100 				drawingLink=true;
  1101 				tmpXLink=model->createXLink(bi_begin,true);
  1102 				tmpXLink->setColor(model->getMapDefXLinkColor());
  1103 				tmpXLink->setWidth(model->getMapDefXLinkWidth());
  1104 				tmpXLink->setEnd   (p);
  1105 				tmpXLink->updateXLink();
  1106 				return;
  1107 			} 
  1108 		}
  1109 	}	// End of modmodes
  1110 
  1111     if (lmo) 
  1112 	{	
  1113 	/*
  1114 		cout << "ME::mouse pressed\n";
  1115 		cout << "  lmo="<<lmo<<endl;
  1116 		cout << "   ti="<<ti->getHeadingStd()<<endl;
  1117 	*/
  1118 		// Select the clicked object
  1119 
  1120 		// Get clicked LMO
  1121 		model->select (ti);
  1122 
  1123 		// Left Button	    Move Branches
  1124 		if (e->button() == Qt::LeftButton )
  1125 		{
  1126 			movingObj_start.setX( p.x() - lmo->x() );	
  1127 			movingObj_start.setY( p.y() - lmo->y() );	
  1128 			movingObj_orgPos.setX (lmo->x() );
  1129 			movingObj_orgPos.setY (lmo->y() );
  1130 			lmo->setRelPos();
  1131 			movingObj_orgRelPos=lmo->getRelPos();
  1132 
  1133 			// If modMode==copy, then we want to "move" the _new_ object around
  1134 			// then we need the offset from p to the _old_ selection, because of tmp
  1135 			if (mainWindow->getModMode()==Main::ModModeCopy &&
  1136 				e->state() & Qt::ControlModifier)
  1137 			{
  1138 				BranchItem *bi=model->getSelectedBranch();
  1139 				if (bi)
  1140 				{
  1141 					copyingObj=true;
  1142 					//FIXME-2   TreeItem::addBranch (BranchItem still missing) 
  1143 					//bi->addBranch (model->getSelectedBranch());
  1144 					model->unselect();
  1145 					model->select(bi->getLastBranch());
  1146 					model->reposition();
  1147 				}
  1148 			} 
  1149 
  1150 			movingObj=model->getSelectedLMO();	
  1151 		} else
  1152 			// Middle Button    Toggle Scroll
  1153 			// (On Mac OS X this won't work, but we still have 
  1154 			// a button in the toolbar)
  1155 			if (e->button() == Qt::MidButton )
  1156 				model->toggleScroll();
  1157 		// model->updateActions(); FIXME-3 needed?
  1158 		// FIXME-3 needed? xelection.update();
  1159 	} else 
  1160 	{ // No MapObj found, we are on the scene itself
  1161 		// Left Button	    move Pos of sceneView
  1162 		if (e->button() == Qt::LeftButton )
  1163 		{
  1164 			movingObj=NULL;	// move Content not Obj
  1165 			movingObj_start=e->globalPos();
  1166 			movingCont_start=QPointF (
  1167 				horizontalScrollBar()->value(),
  1168 				verticalScrollBar()->value());
  1169 			movingVec=QPointF(0,0);
  1170 			setCursor(HandOpenCursor);
  1171 		} 
  1172     } 
  1173 }
  1174 
  1175 void MapEditor::mouseMoveEvent(QMouseEvent* e)
  1176 {
  1177     QPointF p = mapToScene(e->pos());
  1178 	TreeItem *seli=model->getSelectedItem();
  1179 	LinkableMapObj* lmosel=NULL;	
  1180 	if (seli && (seli->isBranchLikeType() ||seli->getType()==TreeItem::Image))
  1181 		lmosel=((MapItem*)seli)->getLMO();
  1182 
  1183     // Move the selected MapObj
  1184     if ( lmosel && movingObj) 
  1185     {	
  1186 		objectMoved=true;
  1187 		// reset cursor if we are moving and don't copy
  1188 		if (mainWindow->getModMode()!=Main::ModModeCopy)
  1189 			setCursor (Qt::ArrowCursor);
  1190 
  1191 		// To avoid jumping of the sceneView, only 
  1192 		// show selection, if not tmp linked
  1193 		/* FIXME-2 if (!lmosel->hasParObjTmp())
  1194 			model->emitShowSelection();
  1195 			*/
  1196 		
  1197 		// Now move the selection, but add relative position 
  1198 		// (movingObj_start) where selection was chosen with 
  1199 		// mousepointer. (This avoids flickering resp. jumping 
  1200 		// of selection back to absPos)
  1201 		
  1202 		// Check if we could link 
  1203 		TreeItem *ti=findMapItem (p, seli);
  1204 		BranchItem *dsti=NULL;
  1205 		LinkableMapObj* dst=NULL;
  1206 		if (ti && ti!=seli && ti->isBranchLikeType())
  1207 		{
  1208 			dsti=(BranchItem*)ti;
  1209 			dst=dsti->getLMO(); 
  1210 		} else
  1211 			dsti=NULL;
  1212 		
  1213 
  1214 		if (lmosel && seli->getType()==TreeItem::Image)	
  1215 		{
  1216 			FloatObj *fio=(FloatImageObj*)lmosel;
  1217 			fio->move   (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );		
  1218 			fio->setRelPos();
  1219 			fio->updateLinkGeometry(); //no need for reposition, if we update link here
  1220 			model->emitSelectionChanged();	// position has changed
  1221 
  1222 			// Relink float to new mapcenter or branch, if shift is pressed	
  1223 			// Only relink, if selection really has a new parent
  1224 			if ( e->modifiers()==Qt::ShiftModifier && dsti &&  dsti != seli->parent()  )
  1225 			{
  1226 				// Also save the move which was done so far
  1227 				QString pold=qpointFToString(movingObj_orgRelPos);
  1228 				QString pnow=qpointFToString(fio->getRelPos());
  1229 				model->saveState(
  1230 					seli,
  1231 					"moveRel "+pold,
  1232 					seli,
  1233 					"moveRel "+pnow,
  1234 					QString("Move %1 to relative position %2").arg(model->getObjectName(fio)).arg(pnow));
  1235 				fio->getParObj()->requestReposition();
  1236 				model->reposition();
  1237 
  1238 				model->relinkImage ((ImageItem*) seli,dsti);
  1239 				model->select (seli);
  1240 				//movingObj=lmosel;	//FIXME-3
  1241 				//movingObj_orgRelPos=lmosel->getRelPos();	
  1242 
  1243 				model->reposition();
  1244 			}
  1245 		} else	
  1246 		{	// selection != a FloatObj
  1247 			if (seli->depth()==0)		
  1248 			{
  1249 				// Move mapcenter
  1250 				lmosel->move   (p-movingObj_start);		
  1251 				if (e->buttons()== Qt::LeftButton && e->modifiers()==Qt::ShiftModifier) 
  1252 				{
  1253 					// Move only mapcenter, leave its children where they are
  1254 					QPointF v;
  1255 					v=lmosel->getAbsPos();
  1256 					for (int i=0; i<seli->branchCount(); ++i)
  1257 					{
  1258 						seli->getBranchObjNum(i)->setRelPos();
  1259 						seli->getBranchObjNum(i)->setOrientation();
  1260 					}
  1261 				}	
  1262 			} else
  1263 			{	
  1264 				if (seli->depth()==1)
  1265 				{
  1266 					// Move mainbranch
  1267 					if (!lmosel->hasParObjTmp())
  1268 						lmosel->move(p-movingObj_start);		
  1269 					lmosel->setRelPos();
  1270 				} else
  1271 				{
  1272 					// Move ordinary branch
  1273 					if (lmosel->getOrientation() == LinkableMapObj::LeftOfCenter)
  1274 						// Add width of bbox here, otherwise alignRelTo will cause jumping around
  1275 						lmosel->move(p.x() -movingObj_start.x() , //lmosel->getBBox().width(), 
  1276 							p.y()-movingObj_start.y() +lmosel->getTopPad() );		
  1277 					else	
  1278 						lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() -lmosel->getTopPad());
  1279 					lmosel->setRelPos();	
  1280 				} 
  1281 
  1282 			} // depth>0
  1283 				// Maybe we can relink temporary?
  1284 				if (dsti)	// FIXME-1 check if dsti is ancestor of myself!
  1285 				{
  1286 					if (e->modifiers()==Qt::ControlModifier)
  1287 					{
  1288 						// Special case: CTRL to link below dst
  1289 						lmosel->setParObjTmp (dst,p,+1);
  1290 					} else if (e->modifiers()==Qt::ShiftModifier)
  1291 						lmosel->setParObjTmp (dst,p,-1);
  1292 					else
  1293 						lmosel->setParObjTmp (dst,p,0);
  1294 				} else	
  1295 				{
  1296 					lmosel->unsetParObjTmp();
  1297 				}		
  1298 				// reposition subbranch
  1299 				lmosel->reposition();	
  1300 
  1301 			QItemSelection sel=model->getSelectionModel()->selection();
  1302 			updateSelection(sel,sel);	// position has changed
  1303 
  1304 		} // no FloatImageObj
  1305 
  1306 		scene()->update();
  1307 		return;
  1308 	} // selection && moving_obj
  1309 		
  1310 	// Draw a link from one branch to another
  1311 	if (drawingLink)
  1312 	{
  1313 		 tmpXLink->setEnd (p);
  1314 		 tmpXLink->updateXLink();
  1315 	}	 
  1316 	
  1317     // Move sceneView 
  1318     if (!movingObj && !pickingColor &&!drawingLink && e->buttons() == Qt::LeftButton ) 
  1319 	{
  1320 		QPointF p=e->globalPos();
  1321 		movingVec.setX(-p.x() + movingObj_start.x() );
  1322 		movingVec.setY(-p.y() + movingObj_start.y() );
  1323 		horizontalScrollBar()->setSliderPosition((int)( movingCont_start.x()+movingVec.x() ));
  1324 		verticalScrollBar()->setSliderPosition((int)( movingCont_start.y()+movingVec.y() ) );
  1325     }
  1326 }
  1327 
  1328 
  1329 void MapEditor::mouseReleaseEvent(QMouseEvent* e)
  1330 {
  1331     QPointF p = mapToScene(e->pos());
  1332 	TreeItem *seli=model->getSelectedItem();
  1333 
  1334 	TreeItem *dsti=NULL;
  1335 	if (seli) dsti=findMapItem(p, seli);
  1336 	LinkableMapObj* dst=NULL;
  1337 	if (dsti && dsti->isBranchLikeType ()) 
  1338 		dst=((MapItem*)dsti)->getLMO();	
  1339 	else
  1340 		dsti=NULL;
  1341 
  1342 
  1343 	// Have we been picking color?
  1344 	if (pickingColor)
  1345 	{
  1346 		pickingColor=false;
  1347 		setCursor (Qt::ArrowCursor);
  1348 		// Check if we are over another branch
  1349 		if (dst) 
  1350 		{	
  1351 			if (e->state() & Qt::ShiftModifier)
  1352 				model->colorBranch (((BranchObj*)dst)->getColor());
  1353 			else	
  1354 				model->colorSubtree (((BranchObj*)dst)->getColor());
  1355 		} 
  1356 		return;
  1357 	}
  1358 
  1359 	// Have we been drawing a link?
  1360 	if (drawingLink)	
  1361 	{
  1362 		drawingLink=false;
  1363 		// Check if we are over another branch
  1364 		if (dsti)
  1365 		{	
  1366 			tmpXLink->setEnd ( ((BranchItem*)dsti) );
  1367 			tmpXLink->updateXLink();
  1368 			tmpXLink->activate(); 
  1369 			model->saveState(
  1370 				tmpXLink,QString("delete ()"),
  1371 				dsti,QString("addXLink (\"%1\",\"%2\")").arg(model->getSelectString(tmpXLink->getBegin())).arg(model->getSelectString(dsti)),
  1372 				QString("Add xLink from %1 to %2").arg(model->getObjectName(tmpXLink->getBegin())).arg(model->getObjectName(dsti)) 
  1373 			);	
  1374 		} else
  1375 		{
  1376 			model->deleteItem(tmpXLink);
  1377 			tmpXLink=NULL;
  1378 		}
  1379 		return;
  1380 	}
  1381 	
  1382     // Have we been moving something?
  1383     if ( seli && movingObj ) 
  1384     {	
  1385 		if (seli->getType()==TreeItem::Image)
  1386 		{
  1387 			FloatImageObj *fio=(FloatImageObj*)( ((MapItem*)seli)->getLMO());
  1388 			if(fio)
  1389 			{
  1390 				// Moved FloatObj. Maybe we need to reposition
  1391 				QString pold=qpointFToString(movingObj_orgRelPos);
  1392 				QString pnow=qpointFToString(fio->getRelPos());
  1393 				model->saveState(
  1394 					seli,
  1395 					"moveRel "+pold,
  1396 					seli,
  1397 					"moveRel "+pnow,
  1398 					QString("Move %1 to relative position %2").arg(model->getObjectName(seli)).arg(pnow));
  1399 
  1400 				cout << "ME::release mouse\n";
  1401 				fio->getParObj()->requestReposition();
  1402 				model->reposition();
  1403 			}	
  1404 		}
  1405 
  1406 		BranchItem *bi=model->getSelectedBranch();
  1407 		if (bi && bi->depth()==0)
  1408 		{	
  1409             if (movingObj_orgPos != bi->getBranchObj()->getAbsPos())	// FIXME-3 check getBO here...
  1410             {
  1411                 QString pold=qpointFToString(movingObj_orgPos);
  1412                 QString pnow=qpointFToString(bi->getBranchObj()->getAbsPos());		// FIXME-3 check getBO here...
  1413 
  1414                 model->saveState(
  1415                     bi,
  1416                     "move "+pold,
  1417                     bi,
  1418                     "move "+pnow,
  1419                     QString("Move mapcenter %1 to position %2").arg(model->getObjectName(bi)).arg(pnow));
  1420             }
  1421 		}
  1422 	
  1423 		if (seli->isBranchLikeType() ) //(seli->getType() == TreeItem::Branch )
  1424 		{	// A branch was moved
  1425 			LinkableMapObj* lmosel=NULL;		
  1426 			lmosel=((MapItem*)seli)->getLMO();
  1427 				
  1428 			// save the position in case we link to mapcenter
  1429 			QPointF savePos=QPointF (lmosel->getAbsPos()  );
  1430 
  1431 			// Reset the temporary drawn link to the original one
  1432 			lmosel->unsetParObjTmp();
  1433 
  1434 			// For Redo we may need to save original selection
  1435 			QString preSelStr=model->getSelectString(seli);
  1436 
  1437 			copyingObj=false;	
  1438 			if (dsti && objectMoved)
  1439 			{
  1440 				// We have a destination, relink to that
  1441 
  1442 				BranchObj* bsel=model->getSelectedBranchObj();
  1443 
  1444 				QString preParStr=model->getSelectString (bsel->getParObj());
  1445 				QString preNum=QString::number (seli->num(),10);
  1446 				QString preDstParStr;
  1447 				bool relinked;
  1448 
  1449 				if (e->state() & Qt::ShiftModifier && dst->getParObj())
  1450 				{	// Link above dst
  1451 					preDstParStr=model->getSelectString (dst->getParObj());
  1452 					relinked=model->relinkBranch ((BranchItem*)seli,(BranchItem*)dsti->parent(),((BranchItem*)dsti)->num());
  1453 				} else 
  1454 				if (e->state() & Qt::ControlModifier && dst->getParObj())
  1455 				{
  1456 					// Link below dst
  1457 					preDstParStr=model->getSelectString (dst->getParObj());
  1458 					relinked=model->relinkBranch ((BranchItem*)seli,(BranchItem*)dsti->parent(),((BranchItem*)dsti)->num()+1);
  1459 				} else	
  1460 				{	// Append to dst
  1461 					preDstParStr=model->getSelectString(dst);
  1462 					relinked=model->relinkBranch ((BranchItem*)seli,(BranchItem*)dsti);
  1463 					if (dsti->depth()==0) bsel->move (savePos);
  1464 				} 
  1465 				if (relinked)
  1466 				{
  1467 					QString postSelStr=model->getSelectString(lmosel);
  1468 					QString postNum=QString::number (seli->num(),10);
  1469 
  1470 					QString undoCom="relinkTo (\""+ 
  1471 						preParStr+ "\"," + preNum  +"," + 
  1472 						QString ("%1,%2").arg(movingObj_orgPos.x()).arg(movingObj_orgPos.y())+ ")";
  1473 
  1474 					QString redoCom="relinkTo (\""+ 
  1475 						preDstParStr + "\"," + postNum + "," +
  1476 						QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
  1477 
  1478 					model->saveState (
  1479 						postSelStr,undoCom,
  1480 						preSelStr, redoCom,
  1481 						QString("Relink %1 to %2").arg(model->getObjectName(bsel)).arg(model->getObjectName(dst)) );
  1482 
  1483 				}
  1484 			} else
  1485 			{
  1486 				// No destination, undo  temporary move	
  1487 
  1488 				if (seli->depth()==1)
  1489 				{
  1490 					// The select string might be different _after_ moving around.
  1491 					// Therefor reposition and then use string of old selection, too
  1492 					model->reposition();
  1493 
  1494                     QPointF rp(lmosel->getRelPos());
  1495                     if (rp != movingObj_orgRelPos)
  1496                     {
  1497                         QString ps=qpointFToString(rp);
  1498                         model->saveState(
  1499                             model->getSelectString(lmosel), "moveRel "+qpointFToString(movingObj_orgRelPos), 
  1500                             preSelStr, "moveRel "+ps, 
  1501                             QString("Move %1 to relative position %2").arg(model->getObjectName(lmosel)).arg(ps));
  1502                     }
  1503 				}
  1504 
  1505 				// Draw the original link, before selection was moved around
  1506 				if (settings.value("/animation/use",true).toBool() && seli->depth()>1) 
  1507 				{
  1508 					lmosel->setRelPos();	// calc relPos first for starting point
  1509 					
  1510 					model->startAnimation(
  1511 						(BranchObj*)lmosel,
  1512 						lmosel->getRelPos(),
  1513 						movingObj_orgRelPos
  1514 					);	
  1515 				} else	
  1516 					model->reposition();
  1517 			}
  1518 		}
  1519 		model->emitSelectionChanged();  //FIXME-3 needed? at least not after pos of selection has changed...
  1520 		// Finally resize scene, if needed
  1521 		scene()->update();
  1522 		movingObj=NULL;		
  1523 		objectMoved=false;
  1524 
  1525 	} else 
  1526 		// maybe we moved View: set old cursor
  1527 		setCursor (Qt::ArrowCursor);
  1528     
  1529 }
  1530 
  1531 void MapEditor::mouseDoubleClickEvent(QMouseEvent* e)
  1532 {
  1533 	if (debug) 
  1534 	{
  1535 		cout << "ME p="<<mapToScene (e->pos())<<"  scrollBarPos="<<getScrollBarPos();
  1536 		cout << "  min="<<QPointF(horizontalScrollBar()->minimum(),verticalScrollBar()->minimum());
  1537 		cout << endl;
  1538 	}
  1539 
  1540 
  1541 	if (model->isSelectionBlocked() ) 
  1542 	{
  1543 		e->ignore();
  1544 		return;
  1545 	}
  1546 
  1547 	if (e->button() == Qt::LeftButton )
  1548 	{
  1549 		QPointF p = mapToScene(e->pos());
  1550 		TreeItem *ti=findMapItem (p, NULL);
  1551 		if (ti) {	// MapObj was found
  1552 			// First select the MapObj than edit heading
  1553 			model->select (ti);
  1554 			editHeading();
  1555 		}
  1556 	}
  1557 }
  1558 
  1559 void MapEditor::resizeEvent (QResizeEvent* e)
  1560 {
  1561 	QGraphicsView::resizeEvent( e );
  1562 }
  1563 
  1564 void MapEditor::dragEnterEvent(QDragEnterEvent *event)
  1565 {
  1566 	//for (unsigned int i=0;event->format(i);i++) // Debug mime type
  1567 	//	cerr << event->format(i) << endl;
  1568 
  1569 	if (event->mimeData()->hasImage())
  1570 		event->acceptProposedAction();
  1571 	else	
  1572 		if (event->mimeData()->hasUrls())
  1573 			event->acceptProposedAction();
  1574 }
  1575 
  1576 void MapEditor::dragMoveEvent(QDragMoveEvent *)
  1577 {
  1578 }
  1579 
  1580 void MapEditor::dragLeaveEvent(QDragLeaveEvent *event)
  1581 {
  1582 	event->accept();
  1583 }
  1584 
  1585 void MapEditor::dropEvent(QDropEvent *event)
  1586 {
  1587 	BranchItem *selbi=model->getSelectedBranch();
  1588 	if (selbi)
  1589 	{
  1590 		if (debug)
  1591 			foreach (QString format,event->mimeData()->formats()) 
  1592 				cout << "MapEditor: Dropped format: "<<qPrintable (format)<<endl;
  1593 
  1594 
  1595 		QList <QUrl> uris;
  1596 		if (event->mimeData()->hasImage()) 
  1597 		{
  1598 			 QVariant imageData = event->mimeData()->imageData();
  1599 			 model->addFloatImage (qvariant_cast<QPixmap>(imageData));
  1600 		} else
  1601 		if (event->mimeData()->hasUrls())
  1602 			uris=event->mimeData()->urls();
  1603 
  1604 		if (uris.count()>0)
  1605 		{
  1606 			QStringList files;
  1607 			QString s;
  1608 			QString heading;
  1609 			BranchItem *bi;
  1610 			for (int i=0; i<uris.count();i++)
  1611 			{
  1612 				// Workaround to avoid adding empty branches
  1613 				if (!uris.at(i).toString().isEmpty())
  1614 				{
  1615 					bi=model->addNewBranch();
  1616 					if (bi)
  1617 					{
  1618 						   /* FIXME-2 
  1619 						s=uris.at(i).toLocalFile();
  1620 						if (!s.isEmpty()) 
  1621 						{
  1622 						   QString file = QDir::fromNativeSeparators(s);
  1623 						   heading = QFileInfo(file).baseName();
  1624 						   files.append(file);
  1625 						   if (file.endsWith(".vym", false))
  1626 							   bi->setVymLink(file);
  1627 						   else
  1628 							   bi->setURL(uris.at(i).toString());
  1629 					   } else 
  1630 					   {
  1631 						   bo->setURL(uris.at(i).toString());
  1632 					   }
  1633 							 */  
  1634 
  1635 					   if (!heading.isEmpty())
  1636 						   bi->setHeading(heading);
  1637 					   else
  1638 						   bi->setHeading(uris.at(i).toString());
  1639 						   
  1640 					}
  1641 				}
  1642 			}
  1643 			model->reposition();
  1644 		}
  1645 	}	
  1646 	event->acceptProposedAction();
  1647 }
  1648 
  1649 void MapEditor::updateSelection(QItemSelection newsel,QItemSelection oldsel)
  1650 {
  1651 	// Note: Here we are prepared for multiple selections, though this 
  1652 	// is not yet implemented elsewhere
  1653 
  1654 	// Here in MapEditor we can only select Branches and Images
  1655 	QList <TreeItem*> treeItemsNew;
  1656 	QList <TreeItem*> treeItemsOld;
  1657 
  1658 	QModelIndex newIndex;
  1659 
  1660 	bool do_reposition=false;
  1661 
  1662 	QModelIndex ix;
  1663 	foreach (ix,newsel.indexes() )
  1664 	{
  1665 		TreeItem *ti= static_cast<TreeItem*>(ix.internalPointer());
  1666 		if (ti->isBranchLikeType() || ti->getType()==TreeItem::Image )
  1667 			if (!treeItemsNew.contains(ti)) treeItemsNew.append (ti);
  1668 	}
  1669 	foreach (ix,oldsel.indexes() )
  1670 	{
  1671 		TreeItem *ti= static_cast<TreeItem*>(ix.internalPointer());
  1672 		if (ti->isBranchLikeType() || ti->getType()==TreeItem::Image )
  1673 			if (!treeItemsOld.contains(ti)) treeItemsOld.append (ti);
  1674 	}
  1675 
  1676 	// Trim list of selection rectangles 
  1677 	while (treeItemsNew.count() < selboxList.count() )
  1678 		delete selboxList.takeFirst();
  1679 
  1680 	// Take care to tmp scroll/unscroll
  1681 	if (!oldsel.isEmpty())
  1682 	{
  1683 		QModelIndex ix=oldsel.indexes().first(); 
  1684 		if (ix.isValid() )
  1685 		{
  1686 			TreeItem *ti= static_cast<TreeItem*>(ix.internalPointer());
  1687 			if (ti)
  1688 			{
  1689 				if (ti->isBranchLikeType() )
  1690 				{
  1691 					// reset tmp scrolled branches
  1692 					BranchItem *bi=(BranchItem*)ti;
  1693 					if (bi->resetTmpUnscroll() )
  1694 						do_reposition=true;
  1695 				}
  1696 				if (ti->isBranchLikeType() || ti->getType()==TreeItem::Image)
  1697 					// Hide link if not needed
  1698 					((MapItem*)ti)->getLMO()->updateVisibility();
  1699 			}
  1700 		}
  1701 	}
  1702 
  1703 	if (!treeItemsNew.isEmpty())
  1704 	{
  1705 		QModelIndex ix=newsel.indexes().first(); 
  1706 		if (ix.isValid() )
  1707 		{
  1708 			newIndex=ix;
  1709 
  1710 			// Temporary unscroll if necessary
  1711 			TreeItem *ti= static_cast<TreeItem*>(ix.internalPointer());
  1712 			if (ti->isBranchLikeType() )
  1713 			{
  1714 				BranchItem *bi=(BranchItem*)ti;
  1715 				if (bi->hasScrolledParent(bi) )
  1716 				{
  1717 					if (bi->parentBranch()->tmpUnscroll() )
  1718 						do_reposition=true;
  1719 				}	
  1720 			}
  1721 			if (ti->isBranchLikeType() || ti->getType()==TreeItem::Image)
  1722 				// Show link if needed
  1723 				((MapItem*)ti)->getLMO()->updateVisibility();
  1724 		}
  1725 	}
  1726 	if (do_reposition) model->reposition();
  1727 
  1728 	// Reduce rectangles
  1729 	while (treeItemsNew.count() < selboxList.count() )
  1730 		delete selboxList.takeFirst();
  1731 
  1732 	// Add additonal rectangles
  1733 	QGraphicsRectItem *sb;
  1734 	while (treeItemsNew.count() > selboxList.count() )
  1735 	{
  1736 		sb = mapScene->addRect(
  1737 			QRectF(0,0,0,0), 
  1738 			QPen(selectionColor),
  1739 			selectionColor);
  1740 		sb->setZValue(Z_SELBOX);
  1741 		sb->show();
  1742 		selboxList.append (sb);
  1743 	}
  1744 
  1745 	// Reposition rectangles
  1746 	QRectF bbox;
  1747 	QModelIndex index;
  1748 
  1749 	LinkableMapObj *lmo;
  1750 	for (int i=0; i<treeItemsNew.count();++i)
  1751 	{
  1752 		lmo=((MapItem*)treeItemsNew.at(i) )->getLMO();
  1753 		bbox=lmo->getBBox();
  1754 		sb=selboxList.at(i);
  1755 		sb->setRect (
  1756 			bbox.x(),bbox.y(), 
  1757 			bbox.width(), bbox.height());
  1758 		sb->setPen (selectionColor);	
  1759 		sb->setBrush (selectionColor);	
  1760 		i++;
  1761 	}
  1762 
  1763 	scene()->update();  
  1764 }
  1765 
  1766 void MapEditor::updateData (const QModelIndex &sel)
  1767 {
  1768 	TreeItem *ti= static_cast<TreeItem*>(sel.internalPointer());
  1769 
  1770 /* testing
  1771 	cout << "ME::updateData\n";
  1772 
  1773 	cout << "  ti="<<ti<<endl;
  1774 	cout << "  h="<<ti->getHeading().toStdString()<<endl;
  1775 	*/
  1776 	
  1777 	if (ti->isBranchLikeType())
  1778 	{
  1779 	//	cout << "  ->updating...\n";
  1780 		BranchObj *bo=(BranchObj*) ( ((MapItem*)ti)->getLMO());
  1781 		bo->updateData();
  1782 	}
  1783 }
  1784 
  1785 void MapEditor::setSelectionColor (QColor col)
  1786 {
  1787 	selectionColor=col;
  1788 	QItemSelection sel=model->getSelectionModel()->selection();
  1789 	updateSelection(sel,sel);
  1790 }
  1791 
  1792 
  1793 QColor MapEditor::getSelectionColor ()
  1794 {
  1795 	return selectionColor;
  1796 }
  1797 
  1798