mapeditor.cpp
author insilmaril
Thu, 02 Apr 2009 09:46:29 +0000
changeset 750 ff3b01ce0960
parent 749 9ff332964015
child 753 25a77484ec72
permissions -rw-r--r--
More moving from BranchObj to BranchItem
     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 "mainwindow.h"
    11 #include "misc.h"
    12 #include "warningdialog.h"
    13 
    14 
    15 extern int statusbarTime;
    16 extern Main *mainWindow;
    17 extern QString tmpVymDir;
    18 extern QString clipboardDir;
    19 extern QString clipboardFile;
    20 extern bool clipboardEmpty;
    21 extern bool debug;
    22 extern FlagRowObj *standardFlagsDefault;
    23 
    24 extern QMenu* branchContextMenu;
    25 extern QMenu* branchAddContextMenu;
    26 extern QMenu* branchRemoveContextMenu;
    27 extern QMenu* branchLinksContextMenu;
    28 extern QMenu* branchXLinksContextMenuEdit;
    29 extern QMenu* branchXLinksContextMenuFollow;
    30 extern QMenu* floatimageContextMenu;
    31 extern QMenu* canvasContextMenu;
    32 
    33 extern Settings settings;
    34 extern QString iconPath;
    35 
    36 ///////////////////////////////////////////////////////////////////////
    37 ///////////////////////////////////////////////////////////////////////
    38 MapEditor::MapEditor( VymModel *vm) 
    39 {
    40 	//cout << "Constructor ME "<<this<<endl;
    41 	mapScene= new QGraphicsScene(NULL);
    42 	mapScene->setBackgroundBrush (QBrush(Qt::white, Qt::SolidPattern));
    43 
    44 	model=vm;
    45 	model->setScene (mapScene);
    46 	model->registerEditor(this);
    47 //	model->addMapCenter();	//  FIXME-3 create this in MapEditor until BO and MCO are independent of scene
    48 	model->makeDefault();	// No changes in model so far
    49 
    50     setScene (mapScene);
    51 
    52     printer=NULL;
    53 
    54 	// Create bitmap cursors, platform dependant
    55 	HandOpenCursor=QCursor (QPixmap(iconPath+"cursorhandopen.png"),1,1);		
    56 	PickColorCursor=QCursor ( QPixmap(iconPath+"cursorcolorpicker.png"), 5,27 ); 
    57 	CopyCursor=QCursor ( QPixmap(iconPath+"cursorcopy.png"), 1,1 ); 
    58 	XLinkCursor=QCursor ( QPixmap(iconPath+"cursorxlink.png"), 1,7 ); 
    59 
    60 	setFocusPolicy (Qt::StrongFocus);
    61 
    62 	pickingColor=false;
    63 	drawingLink=false;
    64 	copyingObj=false;
    65 
    66     editingBO=NULL;
    67     movingObj=NULL;
    68 
    69 	printFrame=true;
    70 	printFooter=true;
    71 
    72 	setAcceptDrops (true);	
    73 
    74 	//model->reposition();	//FIXME-3 really still needed?
    75 
    76 
    77 	// Action to embed LineEdit for heading in Scene
    78 	editingHeading=false;
    79 	lineEdit=new QLineEdit;
    80 	lineEdit->hide();
    81 	QGraphicsProxyWidget *pw=scene()->addWidget (lineEdit);
    82 	pw->setZValue (100);
    83 
    84 	QAction *a = new QAction( tr( "Edit heading","MapEditor" ), this);
    85 	a->setShortcut ( Qt::Key_Return );					//Edit heading
    86 	addAction (a);
    87     connect( a, SIGNAL( triggered() ), this, SLOT( editHeading() ) );
    88 	a = new QAction( tr( "Edit heading","MapEditor" ), this);
    89 	a->setShortcut ( Qt::Key_Enter);					//Edit heading
    90 	addAction (a);
    91     connect( a, SIGNAL( triggered() ), this, SLOT( editHeading() ) );
    92 
    93 	// Selections
    94 	selectionColor =QColor (255,255,0);
    95 	
    96 
    97 	// Attributes	//FIXME-2 testing only...
    98 	QString k;
    99 	AttributeDef *ad;
   100 	attrTable= new AttributeTable();
   101 	k="A - StringList";
   102 	ad=attrTable->addKey (k,StringList);
   103 	if (ad)
   104 	{
   105 		QStringList sl;
   106 		sl <<"val 1"<<"val 2"<< "val 3";
   107 		ad->setValue (QVariant (sl));
   108 	}
   109 	//attrTable->addValue ("Key A","P 1");
   110 	//attrTable->addValue ("Key A","P 2");
   111 	//attrTable->addValue ("Key A","P 3");
   112 	//attrTable->addValue ("Key A","P 4");
   113 	k="B - FreeString";
   114 	ad=attrTable->addKey (k,FreeString);
   115 	if (ad)
   116 	{
   117 		//attrTable->addValue ("Key B","w1");
   118 		//attrTable->addValue ("Key B","w2");
   119 	}
   120 	k="C - UniqueString";
   121 	ad=attrTable->addKey (k,UniqueString);
   122 	if (ad)
   123 	{
   124 	//attrTable->addKey ("Key Prio");
   125 	//attrTable->addValue ("Key Prio","Prio 1");
   126 	//attrTable->addValue ("Key Prio","Prio 2");
   127 	}
   128 }
   129 
   130 MapEditor::~MapEditor()
   131 {
   132 	//cout <<"Destructor MapEditor for "<<model->getMapName().toStdString()<<endl;
   133 	// No need to remove tmp files:
   134 	// tmpMapDir is in tmpVymDir, 
   135 	// so it gets removed automagically when vym closes
   136 	
   137 	model->unregisterEditor(this);
   138 }
   139 
   140 VymModel* MapEditor::getModel()
   141 {
   142     return model;
   143 }
   144 
   145 QGraphicsScene * MapEditor::getScene()
   146 {
   147     return mapScene;
   148 }
   149 
   150 void MapEditor::print()
   151 {
   152 	if ( !printer ) 
   153 	{
   154 		printer = new QPrinter;
   155 		printer->setColorMode (QPrinter::Color);
   156 		printer->setPrinterName (settings.value("/mainwindow/printerName",printer->printerName()).toString());
   157 		printer->setOutputFormat((QPrinter::OutputFormat)settings.value("/mainwindow/printerFormat",printer->outputFormat()).toInt());
   158 		printer->setOutputFileName(settings.value("/mainwindow/printerFileName",printer->outputFileName()).toString());
   159 	}
   160 
   161 	QRectF totalBBox=model->getTotalBBox();
   162 
   163 	// Try to set orientation automagically
   164 	// Note: Interpretation of generated postscript is amibiguous, if 
   165 	// there are problems with landscape mode, see
   166 	// http://sdb.suse.de/de/sdb/html/jsmeix_print-cups-landscape-81.html
   167 
   168 	if (totalBBox.width()>totalBBox.height())
   169 		// recommend landscape
   170 		printer->setOrientation (QPrinter::Landscape);
   171 	else	
   172 		// recommend portrait
   173 		printer->setOrientation (QPrinter::Portrait);
   174 
   175 	if ( printer->setup(this) ) 
   176 	// returns false, if printing is canceled
   177 	{
   178 		QPainter pp(printer);
   179 
   180 		pp.setRenderHint(QPainter::Antialiasing,true);
   181 
   182 		// Don't print the visualisation of selection
   183 		model->unselect();
   184 
   185 		QRectF mapRect=totalBBox;
   186 		QGraphicsRectItem *frame=NULL;
   187 
   188 		if (printFrame) 
   189 		{
   190 			// Print frame around map
   191 			mapRect.setRect (totalBBox.x()-10, totalBBox.y()-10, 
   192 				totalBBox.width()+20, totalBBox.height()+20);
   193 			frame=mapScene->addRect (mapRect, QPen(Qt::black),QBrush(Qt::NoBrush));
   194 			frame->setZValue(0);
   195 			frame->show();    
   196 		}		
   197 
   198 
   199 		double paperAspect = (double)printer->width()   / (double)printer->height();
   200 		double   mapAspect = (double)mapRect.width() / (double)mapRect.height();
   201 		int viewBottom;
   202 		if (mapAspect>=paperAspect)
   203 		{
   204 			// Fit horizontally to paper width
   205 			//pp.setViewport(0,0, printer->width(),(int)(printer->width()/mapAspect) );	
   206 			viewBottom=(int)(printer->width()/mapAspect);	
   207 		}	else
   208 		{
   209 			// Fit vertically to paper height
   210 			//pp.setViewport(0,0,(int)(printer->height()*mapAspect),printer->height());	
   211 			viewBottom=printer->height();	
   212 		}	
   213 		
   214 		if (printFooter) 
   215 		{
   216 			// Print footer below map
   217 			QFont font;		
   218 			font.setPointSize(10);
   219 			pp.setFont (font);
   220 			QRectF footerBox(0,viewBottom,printer->width(),15);
   221 			// FIXME-3 fileName not any longer available here: pp.drawText ( footerBox,Qt::AlignLeft,"VYM - " +fileName);
   222 			pp.drawText ( footerBox, Qt::AlignRight, QDate::currentDate().toString(Qt::TextDate));
   223 		}
   224 		mapScene->render (
   225 			&pp, 
   226 			QRectF (0,0,printer->width(),printer->height()-15),
   227 			QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height())
   228 		);
   229 		
   230 		// Viewport has paper dimension
   231 		if (frame)  delete (frame);
   232 
   233 		// Restore selection
   234 		model->reselect();
   235 
   236 		// Save settings in vymrc
   237 		settings.writeEntry("/mainwindow/printerName",printer->printerName());
   238 		settings.writeEntry("/mainwindow/printerFormat",printer->outputFormat());
   239 		settings.writeEntry("/mainwindow/printerFileName",printer->outputFileName());
   240 	}
   241 }
   242 
   243 void MapEditor::setAntiAlias (bool b)
   244 {
   245 	setRenderHint(QPainter::Antialiasing,b);
   246 }
   247 
   248 void MapEditor::setSmoothPixmap(bool b)
   249 {
   250 	setRenderHint(QPainter::SmoothPixmapTransform,b);
   251 }
   252 
   253 void MapEditor::toggleStandardFlag(QString f)
   254 {
   255 	BranchObj *bo=model->getSelectedBranch();
   256 	if (bo) 
   257 	{
   258 		QString u,r;
   259 		if (bo->isSetStandardFlag(f))
   260 		{
   261 			r="unsetFlag";
   262 			u="setFlag";
   263 		}	
   264 		else
   265 		{
   266 			u="unsetFlag";
   267 			r="setFlag";
   268 		}	
   269 		model->saveState(
   270 			bo,
   271 			QString("%1 (\"%2\")").arg(u).arg(f), 
   272 			bo,
   273 			QString("%1 (\"%2\")").arg(r).arg(f),
   274 			QString("Toggling standard flag \"%1\" of %2").arg(f).arg(model->getObjectName(bo)));
   275 		bo->toggleStandardFlag (f,mainWindow->useFlagGroups());
   276 		model->updateSelection();	// geometry has changed
   277 	}
   278 }
   279 
   280 AttributeTable* MapEditor::attributeTable()
   281 {
   282 	return attrTable;
   283 }
   284 
   285 void MapEditor::testFunction1()
   286 {
   287 	BranchItem *cur=NULL;
   288 	BranchItem *prev=NULL;
   289 	int d;
   290 	cout << "ME::testFunction1  starting to walk the map...\n";
   291 	while (model->next (cur,prev,d) )
   292 		cout << "*** " <<cur->getHeading().toStdString()<<endl;
   293 
   294 
   295 	//BranchObj *bo=model->getSelectedBranch();
   296 	//if (bo) model->moveAway (bo);
   297 	//if (bo) bo->setLinkStyle (LinkableMapObj::Line);
   298 	
   299 
   300 /*
   301 	// Displacement and animation of all non-mainbranches
   302 	QPointF p;
   303 	QPointF q;
   304 	BranchObj *bo;
   305 	TreeItem *cur=NULL;
   306 	TreeItem *prev=NULL;
   307 	int d;
   308 	while (cur) 
   309 	{
   310 		bo=(BranchObj*)(cur->getLMO());
   311 
   312 		if (cur->depth() >0 && !bo->hasScrolledParent(bo) )
   313 		{
   314 			p=QPointF (qrand() %600-300, qrand () %600-300);
   315 			bo->setRelPos();
   316 			q=bo->getRelPos();
   317 			model->startAnimation (bo,p, q);
   318 		}
   319 		model->next(cur,prev,d);
   320 	}
   321 */
   322 
   323 
   324 /* TODO Hide hidden stuff temporary, maybe add this as regular function somewhere
   325 	if (hidemode==HideNone)
   326 	{
   327 		setHideTmpMode (HideExport);
   328 		mapCenter->calcBBoxSizeWithChilds();
   329 		QRectF totalBBox=mapCenter->getTotalBBox();
   330 		QRectF mapRect=totalBBox;
   331 		QCanvasRectangle *frame=NULL;
   332 
   333 		cout << "  map has =("<<totalBBox.x()<<","<<totalBBox.y()<<","<<totalBBox.width()<<","<<totalBBox.height()<<")\n";
   334 	
   335 		mapRect.setRect (totalBBox.x(), totalBBox.y(), 
   336 			totalBBox.width(), totalBBox.height());
   337 		frame=new QCanvasRectangle (mapRect,mapScene);
   338 		frame->setBrush (QColor(white));
   339 		frame->setPen (QColor(black));
   340 		frame->setZValue(0);
   341 		frame->show();    
   342 	}	
   343 	else	
   344 	{
   345 		setHideTmpMode (HideNone);
   346 	}	
   347 	cout <<"  hidemode="<<hidemode<<endl;
   348 	*/
   349 }	
   350 	
   351 void MapEditor::testFunction2()
   352 {
   353 
   354 /*
   355 	// Toggle hidemode
   356 	if (hidemode==HideExport)
   357 		setHideTmpMode (HideNone);
   358 	else	
   359 		setHideTmpMode (HideExport);
   360 */		
   361 }
   362 
   363 void MapEditor::editHeading()
   364 {
   365 	if (editingHeading)
   366 	{
   367 		editHeadingFinished();
   368 		return;
   369 	}
   370 	BranchObj *bo=model->getSelectedBranch();
   371 	if (bo)
   372 	{
   373 		model->setSelectionBlocked(true);
   374 
   375 		lineEdit->setText (bo->getHeading());
   376 		QPoint p = mapTo (this,bo->getAbsPos().toPoint() );
   377 		lineEdit->setGeometry(p.x(),p.y(),230,25);
   378 		lineEdit->selectAll();
   379 		lineEdit->show();
   380 		lineEdit->setFocus();
   381 		lineEdit->grabKeyboard();
   382 		editingHeading=true;
   383 	}
   384 
   385 }
   386 void MapEditor::editHeadingFinished()
   387 {
   388 	editingHeading=false;
   389 	lineEdit->releaseKeyboard();
   390 	model->setHeading (lineEdit->text() );
   391 	model->setSelectionBlocked(false);
   392 	lineEdit->hide();
   393 
   394 	// Maybe reselect previous branch 
   395 	mainWindow->editHeadingFinished (model);
   396 }
   397 
   398 
   399 void MapEditor::contextMenuEvent ( QContextMenuEvent * e )
   400 {
   401 	// Lineedits are already closed by preceding
   402 	// mouseEvent, we don't need to close here.
   403 
   404     QPointF p = mapToScene(e->pos());
   405     LinkableMapObj* lmo=model->findMapObj(p, NULL);
   406 	
   407     if (lmo) 
   408 	{	// MapObj was found
   409 		if (model->getSelectedLMO() != lmo)
   410 		{
   411 			// select the MapObj
   412 			model->select(lmo);
   413 		}
   414 		// Context Menu 
   415 		if (model->getSelectedBranch() ) 
   416 		{
   417 			// Context Menu on branch or mapcenter
   418 			//FIXME-3 model->updateActions(); needed?
   419 			branchContextMenu->popup(e->globalPos() );
   420 		} else
   421 		{
   422 			if (model->getSelectedFloatImage() )
   423 			{
   424 				// Context Menu on floatimage
   425 				// model->updateActions(); FIXME-3 needed?
   426 				floatimageContextMenu->popup(e->globalPos() );
   427 			}	
   428 		}	
   429 	} else 
   430 	{ // No MapObj found, we are on the Canvas itself
   431 		// Context Menu on scene
   432 		// model->updateActions(); FIXME-3 needed?
   433 		
   434 		// Open context menu synchronously to position new mapcenter
   435 		model->setContextPos (p);
   436 		canvasContextMenu->exec(e->globalPos() );
   437 		model->unsetContextPos ();
   438     } 
   439 	e->accept();
   440 }
   441 
   442 void MapEditor::keyPressEvent(QKeyEvent* e)
   443 {
   444 	if (e->modifiers() & Qt::ControlModifier)
   445 	{
   446 		switch (mainWindow->getModMode())
   447 		{
   448 			case Main::ModModeColor: 
   449 				setCursor (PickColorCursor);
   450 				break;
   451 			case Main::ModModeCopy: 
   452 				setCursor (CopyCursor);
   453 				break;
   454 			case Main::ModModeXLink: 
   455 				setCursor (XLinkCursor);
   456 				break;
   457 			default :
   458 				setCursor (Qt::ArrowCursor);
   459 				break;
   460 		} 
   461 	}	
   462 }
   463 
   464 void MapEditor::keyReleaseEvent(QKeyEvent* e)
   465 {
   466 	if (!(e->modifiers() & Qt::ControlModifier))
   467 		setCursor (Qt::ArrowCursor);
   468 }
   469 
   470 void MapEditor::mousePressEvent(QMouseEvent* e)
   471 {
   472 	// Ignore right clicks, these will go to context menus
   473 	if (e->button() == Qt::RightButton )
   474 	{
   475 		e->ignore();
   476 		return;
   477 	}
   478 
   479 	//Ignore clicks while editing heading
   480 	if (model->isSelectionBlocked() ) 
   481 	{
   482 		e->ignore();
   483 		return;
   484 	}
   485 
   486     QPointF p = mapToScene(e->pos());
   487     LinkableMapObj* lmo=model->findMapObj(p, NULL);
   488 	
   489 	e->accept();
   490 
   491 	//Take care of  system flags _or_ modifier modes
   492 	//
   493 	if (lmo && (typeid(*lmo)==typeid(BranchObj) ||
   494 		typeid(*lmo)==typeid(MapCenterObj) ))
   495 	{
   496 		QString foname=((BranchObj*)lmo)->getSystemFlagName(p);
   497 		if (!foname.isEmpty())
   498 		{
   499 			// systemFlag clicked
   500 			model->select (lmo);	// FIXME-3 was selectInt
   501 			if (foname=="url") 
   502 			{
   503 				if (e->state() & Qt::ControlModifier)
   504 					mainWindow->editOpenURLTab();
   505 				else	
   506 					mainWindow->editOpenURL();
   507 			}	
   508 			else if (foname=="vymLink")
   509 			{
   510 				mainWindow->editOpenVymLink();
   511 				// tabWidget may change, better return now
   512 				// before segfaulting...
   513 			} else if (foname=="note")
   514 				mainWindow->windowToggleNoteEditor();
   515 			else if (foname=="hideInExport")		
   516 				model->toggleHideExport();
   517 			// FIXME-3 needed? xelection.update();	
   518 			return;	
   519 		} 
   520 	}	
   521 	// No system flag clicked, take care of modmodes (CTRL-Click)
   522 	if (e->state() & Qt::ControlModifier)
   523 	{
   524 		if (mainWindow->getModMode()==Main::ModModeColor)
   525 		{
   526 				pickingColor=true;
   527 				setCursor (PickColorCursor);
   528 				return;
   529 		} 
   530 		if (mainWindow->getModMode()==Main::ModModeXLink)
   531 		{	
   532 			BranchObj *bo_begin=NULL;
   533 			if (lmo)
   534 				bo_begin=(BranchObj*)(lmo);
   535 			else	
   536 				bo_begin=model->getSelectedBranch();
   537 			if (bo_begin)	
   538 			{
   539 				drawingLink=true;
   540 				linkingObj_src=bo_begin;
   541 				tmpXLink=new XLinkObj (mapScene);
   542 				tmpXLink->setBegin (bo_begin);
   543 				tmpXLink->setEnd   (p);
   544 				tmpXLink->setColor(model->getMapDefXLinkColor());
   545 				tmpXLink->setWidth(model->getMapDefXLinkWidth());
   546 				tmpXLink->updateXLink();
   547 				tmpXLink->setVisibility (true);
   548 				return;
   549 			} 
   550 		}
   551 	}	// End of modmodes
   552 
   553     if (lmo) 
   554 	{	
   555 	/*
   556 		cout << "ME::mouse pressed\n";
   557 		cout << "  lmo="<<lmo<<endl;
   558 		cout << "  h="<<((BranchObj*)lmo)->getHeading().toStdString()<<endl;
   559 	*/
   560 		// Select the clicked object
   561 
   562 		// FIXME-2 VM better let "find" return an index instead of lmo...
   563 		// Get index of clicked LMO
   564 		TreeItem *ti=lmo->getTreeItem();
   565 		/*
   566 		cout << "  lmo="<<lmo<<"    lmo(ti)="<<ti->getLMO()<<endl;
   567 		cout << "  ti ("<<ti->row()<<","<<ti->column()<<") = "<<ti<<endl;
   568 		*/
   569 		//QModelIndex ix=model->index( ti->row(), ti->column(), model->index (0,0,QModelIndex()) );
   570 		model->select (ti);
   571 
   572 		// Left Button	    Move Branches
   573 		if (e->button() == Qt::LeftButton )
   574 		{
   575 			//movingObj_start.setX( p.x() - selection->x() );// TODO replaced selection->lmo here	
   576 			//movingObj_start.setY( p.y() - selection->y() );	
   577 			movingObj_start.setX( p.x() - lmo->x() );	
   578 			movingObj_start.setY( p.y() - lmo->y() );	
   579 			movingObj_orgPos.setX (lmo->x() );
   580 			movingObj_orgPos.setY (lmo->y() );
   581 			lmo->setRelPos();
   582 			movingObj_orgRelPos=lmo->getRelPos();
   583 
   584 			// If modMode==copy, then we want to "move" the _new_ object around
   585 			// then we need the offset from p to the _old_ selection, because of tmp
   586 			if (mainWindow->getModMode()==Main::ModModeCopy &&
   587 				e->state() & Qt::ControlModifier)
   588 			{
   589 				BranchItem *bi=model->getSelectedBranchItem();
   590 				if (bi)
   591 				{
   592 					copyingObj=true;
   593 					//FIXME-2   TreeItem::addBranch (BranchItem still missing) 
   594 					//bi->addBranch (model->getSelectedBranchItem());
   595 					model->unselect();
   596 					model->select(bi->getLastBranch());
   597 					model->reposition();
   598 				}
   599 			} 
   600 
   601 			movingObj=model->getSelectedLMO();	
   602 		} else
   603 			// Middle Button    Toggle Scroll
   604 			// (On Mac OS X this won't work, but we still have 
   605 			// a button in the toolbar)
   606 			if (e->button() == Qt::MidButton )
   607 				model->toggleScroll();
   608 		// model->updateActions(); FIXME-3 needed?
   609 		// FIXME-3 needed? xelection.update();
   610 	} else 
   611 	{ // No MapObj found, we are on the scene itself
   612 		// Left Button	    move Pos of sceneView
   613 		if (e->button() == Qt::LeftButton )
   614 		{
   615 			movingObj=NULL;	// move Content not Obj
   616 			movingObj_start=e->globalPos();
   617 			movingCont_start=QPointF (
   618 				horizontalScrollBar()->value(),
   619 				verticalScrollBar()->value());
   620 			movingVec=QPointF(0,0);
   621 			setCursor(HandOpenCursor);
   622 		} 
   623     } 
   624 }
   625 
   626 void MapEditor::mouseMoveEvent(QMouseEvent* e)
   627 {
   628     QPointF p = mapToScene(e->pos());
   629 	LinkableMapObj *lmosel=model->getSelectedLMO();
   630 
   631     // Move the selected MapObj
   632     if ( lmosel && movingObj) 
   633     {	
   634 		// reset cursor if we are moving and don't copy
   635 		if (mainWindow->getModMode()!=Main::ModModeCopy)
   636 			setCursor (Qt::ArrowCursor);
   637 
   638 		// To avoid jumping of the sceneView, only 
   639 		// ensureSelectionVisible, if not tmp linked
   640 		if (!lmosel->hasParObjTmp())
   641 			model->ensureSelectionVisible ();
   642 		
   643 		// Now move the selection, but add relative position 
   644 		// (movingObj_start) where selection was chosen with 
   645 		// mousepointer. (This avoids flickering resp. jumping 
   646 		// of selection back to absPos)
   647 		
   648 		// Check if we could link 
   649 		LinkableMapObj* lmo=model->findMapObj(p, lmosel);
   650 		
   651 
   652 		FloatObj *fio=model->getSelectedFloatImage();
   653 		if (fio)
   654 		{
   655 			fio->move   (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );		
   656 			fio->setRelPos();
   657 			fio->updateLink(); //no need for reposition, if we update link here
   658 			model->updateSelection();	// position has changed
   659 
   660 			// Relink float to new mapcenter or branch, if shift is pressed	
   661 			// Only relink, if selection really has a new parent
   662 			if ( (e->modifiers()==Qt::ShiftModifier) && lmo &&
   663 				( (typeid(*lmo)==typeid(BranchObj)) ||
   664 				  (typeid(*lmo)==typeid(MapCenterObj)) ) &&
   665 				( lmo != fio->getParObj())  
   666 				)
   667 			{
   668 				if (typeid(*fio) == typeid(FloatImageObj) && 
   669 				( (typeid(*lmo)==typeid(BranchObj) ||
   670 				  typeid(*lmo)==typeid(MapCenterObj)) ))  
   671 				{
   672 
   673 					// Also save the move which was done so far
   674 					QString pold=qpointfToString(movingObj_orgRelPos);
   675 					QString pnow=qpointfToString(fio->getRelPos());
   676 					model->saveState(
   677 						fio,
   678 						"moveRel "+pold,
   679 						fio,
   680 						"moveRel "+pnow,
   681 						QString("Move %1 to relative position %2").arg(model->getObjectName(fio)).arg(pnow));
   682 					fio->getParObj()->requestReposition();
   683 					model->reposition();
   684 
   685 					model->linkFloatImageTo (model->getSelectString(lmo));
   686 					//movingObj=lmosel;
   687 					//movingObj_orgRelPos=lmosel->getRelPos();	
   688 
   689 					model->reposition();
   690 				}	
   691 			}
   692 		} else	
   693 		{	// selection != a FloatObj
   694 			if (lmosel->getDepth()==0)
   695 			{
   696 				// Move MapCenter
   697 				if (e->buttons()== Qt::LeftButton && e->modifiers()==Qt::ShiftModifier) 
   698 					((MapCenterObj*)lmosel)->moveAll(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );		
   699 				else	
   700 					lmosel->move   (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );		
   701 				model->updateRelPositions();
   702 			} else
   703 			{	
   704 				if (lmosel->getDepth()==1)
   705 				{
   706 					// Move mainbranch
   707 					lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );		
   708 					lmosel->setRelPos();
   709 				} else
   710 				{
   711 					// Move ordinary branch
   712 					if (lmosel->getOrientation() == LinkableMapObj::LeftOfCenter)
   713 						// Add width of bbox here, otherwise alignRelTo will cause jumping around
   714 						lmosel->move(p.x() -movingObj_start.x() , //lmosel->getBBox().width(), 
   715 							p.y()-movingObj_start.y() +lmosel->getTopPad() );		
   716 					else	
   717 						lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() -lmosel->getTopPad());
   718 					lmosel->setRelPos();	
   719 				} 
   720 
   721 				// Maybe we can relink temporary?
   722 				if (lmo && (lmo!=lmosel) && model->getSelectedBranch() && 
   723 					 (typeid(*lmo)==typeid(BranchObj) ||
   724 					  typeid(*lmo)==typeid(MapCenterObj)) ) 
   725 
   726 				{
   727 					if (e->modifiers()==Qt::ControlModifier)
   728 					{
   729 						// Special case: CTRL to link below lmo
   730 						lmosel->setParObjTmp (lmo,p,+1);
   731 					}
   732 					else if (e->modifiers()==Qt::ShiftModifier)
   733 						lmosel->setParObjTmp (lmo,p,-1);
   734 					else
   735 						lmosel->setParObjTmp (lmo,p,0);
   736 				} else	
   737 				{
   738 					lmosel->unsetParObjTmp();
   739 				}		
   740 				// reposition subbranch
   741 				lmosel->reposition();	
   742 			} // depth>0
   743 
   744 			QItemSelection sel=model->getSelectionModel()->selection();
   745 			updateSelection(sel,sel);	// position has changed
   746 
   747 		} // no FloatImageObj
   748 
   749 		scene()->update();
   750 		return;
   751 	} // selection && moving_obj
   752 		
   753 	// Draw a link from one branch to another
   754 	if (drawingLink)
   755 	{
   756 		 tmpXLink->setEnd (p);
   757 		 tmpXLink->updateXLink();
   758 	}	 
   759 	
   760     // Move sceneView 
   761     if (!movingObj && !pickingColor &&!drawingLink && e->buttons() == Qt::LeftButton ) 
   762 	{
   763 		QPointF p=e->globalPos();
   764 		movingVec.setX(-p.x() + movingObj_start.x() );
   765 		movingVec.setY(-p.y() + movingObj_start.y() );
   766 		horizontalScrollBar()->setSliderPosition((int)( movingCont_start.x()+movingVec.x() ));
   767 		verticalScrollBar()->setSliderPosition((int)( movingCont_start.y()+movingVec.y() ) );
   768     }
   769 }
   770 
   771 
   772 void MapEditor::mouseReleaseEvent(QMouseEvent* e)
   773 {
   774     QPointF p = mapToScene(e->pos());
   775 	LinkableMapObj *dst;
   776 	LinkableMapObj *lmosel=model->getSelectedLMO();
   777 	// Have we been picking color?
   778 	if (pickingColor)
   779 	{
   780 		pickingColor=false;
   781 		setCursor (Qt::ArrowCursor);
   782 		// Check if we are over another branch
   783 		dst=model->findMapObj(p, NULL);
   784 		if (dst && lmosel) 
   785 		{	
   786 			if (e->state() & Qt::ShiftModifier)
   787 				model->colorBranch (((BranchObj*)dst)->getColor());
   788 			else	
   789 				model->colorSubtree (((BranchObj*)dst)->getColor());
   790 		} 
   791 		return;
   792 	}
   793 
   794 	// Have we been drawing a link?
   795 	if (drawingLink)	
   796 	{
   797 		drawingLink=false;
   798 		// Check if we are over another branch
   799 		dst=model->findMapObj(p, NULL);
   800 		if (dst && lmosel) 
   801 		{	
   802 			tmpXLink->setEnd ( ((BranchObj*)(dst)) );
   803 			tmpXLink->updateXLink();
   804 			tmpXLink->activate(); //FIXME-2 savestate missing
   805 			//model->saveStateComplete(QString("Activate xLink from %1 to %2").arg(model->getObjectName(tmpXLink->getBegin())).arg(model->getObjectName(tmpXLink->getEnd())) );	
   806 		} else
   807 		{
   808 			delete(tmpXLink);
   809 			tmpXLink=NULL;
   810 		}
   811 		return;
   812 	}
   813 	
   814     // Have we been moving something?
   815     if ( lmosel && movingObj ) 
   816     {	
   817 		FloatImageObj *fo=model->getSelectedFloatImage();
   818 		if(fo)
   819 		{
   820 			// Moved FloatObj. Maybe we need to reposition
   821 		    QString pold=qpointfToString(movingObj_orgRelPos);
   822 		    QString pnow=qpointfToString(fo->getRelPos());
   823 			model->saveState(
   824 				fo,
   825 				"moveRel "+pold,
   826 				fo,
   827 				"moveRel "+pnow,
   828 				QString("Move %1 to relative position %2").arg(model->getObjectName(fo)).arg(pnow));
   829 
   830 			fo->getParObj()->requestReposition();
   831 			model->reposition();
   832 		}	
   833 
   834 		// Check if we are over another branch, but ignore 
   835 		// any found LMOs, which are FloatObjs
   836 		dst=model->findMapObj(mapToScene(e->pos() ), lmosel);
   837 
   838 		if (dst && (typeid(*dst)!=typeid(BranchObj) && typeid(*dst)!=typeid(MapCenterObj))) 
   839 			dst=NULL;
   840 		
   841 		BranchObj *bo=model->getSelectedBranch();
   842 		if (bo && bo->getDepth()==0)
   843 		{	
   844             if (movingObj_orgPos != bo->getAbsPos())
   845             {
   846                 QString pold=qpointfToString(movingObj_orgPos);
   847                 QString pnow=qpointfToString(bo->getAbsPos());
   848                 model->saveState(
   849                     bo,
   850                     "move "+pold,
   851                     bo,
   852                     "move "+pnow,
   853                     QString("Move mapcenter %1 to position %2").arg(model->getObjectName(bo)).arg(pnow));
   854             }
   855 		}
   856 	
   857 		if (model->selectionType() == TreeItem::Branch )
   858 		{	// A branch was moved
   859 			
   860 			// save the position in case we link to mapcenter
   861 			QPointF savePos=QPointF (lmosel->getAbsPos()  );
   862 
   863 			// Reset the temporary drawn link to the original one
   864 			lmosel->unsetParObjTmp();
   865 
   866 			// For Redo we may need to save original selection
   867 			QString preSelStr=model->getSelectString(lmosel);
   868 
   869 			copyingObj=false;	
   870 			if (dst ) 
   871 			{
   872 				// We have a destination, relink to that
   873 
   874 				BranchObj* bsel=model->getSelectedBranch();
   875 				TreeItem * tisel=model->getSelectedItem();
   876 				BranchObj* bdst=(BranchObj*)dst;
   877 				TreeItem* tidst=dst->getTreeItem();
   878 
   879 				QString preParStr=model->getSelectString (bsel->getParObj());
   880 				QString preNum=QString::number (tisel->num(),10);
   881 				QString preDstParStr;
   882 
   883 				if (e->state() & Qt::ShiftModifier && dst->getParObj())
   884 				{	// Link above dst
   885 					preDstParStr=model->getSelectString (dst->getParObj());
   886 					bsel->linkTo ( (BranchObj*)(bdst->getParObj()), tidst->num());
   887 				} else 
   888 				if (e->state() & Qt::ControlModifier && dst->getParObj())
   889 				{
   890 					// Link below dst
   891 					preDstParStr=model->getSelectString (dst->getParObj());
   892 					bsel->linkTo ( (BranchObj*)(bdst->getParObj()), tidst->num()+1);
   893 				} else	
   894 				{	// Append to dst
   895 					preDstParStr=model->getSelectString(dst);
   896 					bsel->linkTo (bdst,-1);
   897 					if (dst->getDepth()==0) bsel->move (savePos);
   898 				} 
   899 				QString postSelStr=model->getSelectString(lmosel);
   900 				QString postNum=QString::number (tisel->num(),10);
   901 
   902 				QString undoCom="linkTo (\""+ 
   903 					preParStr+ "\"," + preNum  +"," + 
   904 					QString ("%1,%2").arg(movingObj_orgPos.x()).arg(movingObj_orgPos.y())+ ")";
   905 
   906 				QString redoCom="linkTo (\""+ 
   907 					preDstParStr + "\"," + postNum + "," +
   908 					QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
   909 
   910 				model->saveState (
   911 					postSelStr,undoCom,
   912 					preSelStr, redoCom,
   913 					QString("Relink %1 to %2").arg(model->getObjectName(bsel)).arg(model->getObjectName(dst)) );
   914 
   915 				model->reposition();	// not necessary if we undo temporary move  below
   916 			} else
   917 			{
   918 				// No destination, undo  temporary move
   919 
   920 				if (lmosel->getDepth()==1)
   921 				{
   922 					// The select string might be different _after_ moving around.
   923 					// Therefor reposition and then use string of old selection, too
   924 					model->reposition();
   925 
   926                     QPointF rp(lmosel->getRelPos());
   927                     if (rp != movingObj_orgRelPos)
   928                     {
   929                         QString ps=qpointfToString(rp);
   930                         model->saveState(
   931                             model->getSelectString(lmosel), "moveRel "+qpointfToString(movingObj_orgRelPos), 
   932                             preSelStr, "moveRel "+ps, 
   933                             QString("Move %1 to relative position %2").arg(model->getObjectName(lmosel)).arg(ps));
   934                     }
   935 				}
   936 
   937 				// Draw the original link, before selection was moved around
   938 				if (settings.value("/animation/use",false).toBool() && lmosel->getDepth()>1) 
   939 				{
   940 					lmosel->setRelPos();	// calc relPos first for starting point
   941 					QPointF dst=bo->getParObj()->getChildPos();
   942 			//		if (lmosel->getOrientation()==LinkableMapObj::LeftOfCenter) dst.setX (dst.x()+lmosel->width() );
   943 					
   944 					model->startAnimation(
   945 						(BranchObj*)lmosel,
   946 						lmosel->getRelPos(),
   947 						movingObj_orgRelPos
   948 //						QPointF (movingObj_orgPos.x() - dst.x(), movingObj_orgPos.y() - dst.y() )
   949 					);	
   950 				} else	
   951 					model->reposition();
   952 			}
   953 		}
   954 		model->updateSelection();  //FIXME-3 needed? at least not after pos of selection has changed...
   955 		// Finally resize scene, if needed
   956 		scene()->update();
   957 		movingObj=NULL;		
   958 
   959 		// Just make sure, that actions are still ok,e.g. the move branch up/down buttons...
   960 		// model->updateActions(); FIXME-3 neeeded? 
   961 	} else 
   962 		// maybe we moved View: set old cursor
   963 		setCursor (Qt::ArrowCursor);
   964     
   965 }
   966 
   967 void MapEditor::mouseDoubleClickEvent(QMouseEvent* e)
   968 {
   969 	if (model->isSelectionBlocked() ) 
   970 	{
   971 		e->ignore();
   972 		return;
   973 	}
   974 
   975 	if (e->button() == Qt::LeftButton )
   976 	{
   977 		QPointF p = mapToScene(e->pos());
   978 		LinkableMapObj *lmo=model->findMapObj(p, NULL);
   979 		if (lmo) {	// MapObj was found
   980 			// First select the MapObj than edit heading
   981 			model->select (lmo);
   982 			editHeading();
   983 		}
   984 	}
   985 }
   986 
   987 void MapEditor::resizeEvent (QResizeEvent* e)
   988 {
   989 	QGraphicsView::resizeEvent( e );
   990 }
   991 
   992 void MapEditor::dragEnterEvent(QDragEnterEvent *event)
   993 {
   994 	//for (unsigned int i=0;event->format(i);i++) // Debug mime type
   995 	//	cerr << event->format(i) << endl;
   996 
   997 	if (event->mimeData()->hasImage())
   998 		event->acceptProposedAction();
   999 	else	
  1000 		if (event->mimeData()->hasUrls())
  1001 			event->acceptProposedAction();
  1002 }
  1003 
  1004 void MapEditor::dragMoveEvent(QDragMoveEvent *)
  1005 {
  1006 }
  1007 
  1008 void MapEditor::dragLeaveEvent(QDragLeaveEvent *event)
  1009 {
  1010 	event->accept();
  1011 }
  1012 
  1013 void MapEditor::dropEvent(QDropEvent *event)
  1014 {
  1015 	BranchObj *sel=model->getSelectedBranch();
  1016 	if (sel)
  1017 	{
  1018 		if (debug)
  1019 			foreach (QString format,event->mimeData()->formats()) 
  1020 				cout << "MapEditor: Dropped format: "<<qPrintable (format)<<endl;
  1021 
  1022 
  1023 		QList <QUrl> uris;
  1024 		if (event->mimeData()->hasImage()) 
  1025 		{
  1026 			 QVariant imageData = event->mimeData()->imageData();
  1027 			 model->addFloatImage (qvariant_cast<QPixmap>(imageData));
  1028 		} else
  1029 		if (event->mimeData()->hasUrls())
  1030 			uris=event->mimeData()->urls();
  1031 
  1032 		if (uris.count()>0)
  1033 		{
  1034 			QStringList files;
  1035 			QString s;
  1036 			QString heading;
  1037 			BranchObj *bo;
  1038 			for (int i=0; i<uris.count();i++)
  1039 			{
  1040 				// Workaround to avoid adding empty branches
  1041 				if (!uris.at(i).toString().isEmpty())
  1042 				{
  1043 					bo=sel->addBranch();
  1044 					if (bo)
  1045 					{
  1046 						s=uris.at(i).toLocalFile();
  1047 						if (!s.isEmpty()) 
  1048 						{
  1049 						   QString file = QDir::fromNativeSeparators(s);
  1050 						   heading = QFileInfo(file).baseName();
  1051 						   files.append(file);
  1052 						   if (file.endsWith(".vym", false))
  1053 							   bo->setVymLink(file);
  1054 						   else
  1055 							   bo->setURL(uris.at(i).toString());
  1056 					   } else 
  1057 					   {
  1058 						   bo->setURL(uris.at(i).toString());
  1059 					   }
  1060 
  1061 					   if (!heading.isEmpty())
  1062 						   bo->setHeading(heading);
  1063 					   else
  1064 						   bo->setHeading(uris.at(i).toString());
  1065 					}
  1066 				}
  1067 			}
  1068 			model->reposition();
  1069 		}
  1070 	}	
  1071 	event->acceptProposedAction();
  1072 }
  1073 
  1074 void MapEditor::updateSelection(const QItemSelection &newsel,const QItemSelection &)
  1075 {
  1076 	// Reduce rectangles
  1077 	while (newsel.indexes().count() < selboxList.count() )
  1078 		delete selboxList.takeFirst();
  1079 
  1080 	// Add additonal rectangles
  1081 	QGraphicsRectItem *sb;
  1082 	while (newsel.indexes().count() > selboxList.count() )
  1083 	{
  1084 		sb = mapScene->addRect(
  1085 			QRectF(0,0,0,0), 
  1086 			QPen(selectionColor),
  1087 			selectionColor);
  1088 		sb->setZValue(Z_SELBOX);
  1089 		sb->show();
  1090 		selboxList.append (sb);
  1091 	}
  1092 
  1093 	// Reposition rectangles
  1094 	int i=0;
  1095 	QRectF bbox;
  1096 	QModelIndex index;
  1097 
  1098 	TreeItem *ti;
  1099 	LinkableMapObj *lmo;
  1100 	foreach (sb,selboxList)
  1101 	{
  1102 		index=newsel.indexes().at(i);
  1103 		ti= static_cast<TreeItem*>(index.internalPointer());
  1104 		lmo=ti->getLMO();
  1105 		bbox=lmo->getBBox();
  1106 		sb->setRect (
  1107 			bbox.x(),bbox.y(), 
  1108 			bbox.width(), bbox.height());
  1109 		sb->setPen (selectionColor);	
  1110 		sb->setBrush (selectionColor);	
  1111 		i++;
  1112 	}
  1113 }
  1114 
  1115 void MapEditor::updateCurrent (const QModelIndex &,const QModelIndex &)	//FIXME-3 not used?
  1116 {
  1117 
  1118 /* testing
  1119 
  1120 	cout << "ME::updateCurrent\n";
  1121 
  1122 	TreeItem *item = static_cast<TreeItem*>(newsel.internalPointer());
  1123 	LinkableMapObj *lmo=item->getLMO();
  1124 	cout << "  lmo="<<lmo<<endl;
  1125 	cout << "  h="<<((BranchObj*)lmo)->getHeading().toStdString()<<endl;
  1126 	*/
  1127 
  1128 }
  1129 
  1130 void MapEditor::setSelectionColor (QColor col)
  1131 {
  1132 	selectionColor=col;
  1133 	QItemSelection sel=model->getSelectionModel()->selection();
  1134 	updateSelection(sel,sel);
  1135 }
  1136 
  1137 QColor MapEditor::getSelectionColor ()
  1138 {
  1139 	return selectionColor;
  1140 }
  1141 
  1142