vymmodel.cpp
author insilmaril
Mon Nov 16 09:07:17 2009 +0000 (2009-11-16)
branchrelease-1-12-maintained
changeset 77 bdfc1079a723
parent 59 1c550f80c43b
permissions -rw-r--r--
1.12.5 Fixed crash related to reselecting deleted mapcenter
insilmaril@40
     1
#include <QApplication>
insilmaril@40
     2
#include <typeinfo>
insilmaril@40
     3
insilmaril@40
     4
#include "geometry.h"		// for addBBox
insilmaril@40
     5
#include "vymmodel.h"
insilmaril@40
     6
insilmaril@40
     7
insilmaril@40
     8
extern Settings settings;
insilmaril@40
     9
insilmaril@40
    10
VymModel::VymModel() 
insilmaril@40
    11
{
insilmaril@40
    12
//    cout << "Const VymModel\n";
insilmaril@40
    13
}
insilmaril@40
    14
insilmaril@40
    15
insilmaril@40
    16
VymModel::~VymModel() 
insilmaril@40
    17
{
insilmaril@59
    18
    //cout << "Destr VymModel\n";
insilmaril@59
    19
	clear();
insilmaril@40
    20
}	
insilmaril@40
    21
insilmaril@40
    22
void VymModel::clear() 
insilmaril@40
    23
{
insilmaril@40
    24
	while (!mapCenters.isEmpty())
insilmaril@40
    25
		delete mapCenters.takeFirst();
insilmaril@40
    26
}
insilmaril@40
    27
insilmaril@40
    28
void VymModel::init () 
insilmaril@40
    29
{
insilmaril@40
    30
	addMapCenter();
insilmaril@40
    31
insilmaril@40
    32
	// animations
insilmaril@40
    33
	animationUse=settings.readBoolEntry("/animation/use",false);
insilmaril@40
    34
	animationTicks=settings.readNumEntry("/animation/ticks",10);
insilmaril@40
    35
	animationInterval=settings.readNumEntry("/animation/interval",50);
insilmaril@40
    36
	animObjList.clear();
insilmaril@40
    37
	animationTimer=new QTimer (this);
insilmaril@40
    38
	connect(animationTimer, SIGNAL(timeout()), this, SLOT(animate()));
insilmaril@40
    39
insilmaril@40
    40
}
insilmaril@40
    41
insilmaril@40
    42
void VymModel::setMapEditor(MapEditor *me)
insilmaril@40
    43
{
insilmaril@40
    44
	mapEditor=me;
insilmaril@40
    45
	for (int i=0; i<mapCenters.count(); i++)
insilmaril@40
    46
		mapCenters.at(i)->setMapEditor(mapEditor);
insilmaril@40
    47
}
insilmaril@40
    48
insilmaril@40
    49
MapEditor* VymModel::getMapEditor()
insilmaril@40
    50
{
insilmaril@40
    51
	return mapEditor;
insilmaril@40
    52
}
insilmaril@40
    53
insilmaril@40
    54
void VymModel::setVersion (const QString &s)
insilmaril@40
    55
{
insilmaril@40
    56
	version=s;
insilmaril@40
    57
}
insilmaril@40
    58
insilmaril@40
    59
void VymModel::setAuthor (const QString &s)
insilmaril@40
    60
{
insilmaril@40
    61
	author=s;
insilmaril@40
    62
}
insilmaril@40
    63
insilmaril@40
    64
QString VymModel::getAuthor()
insilmaril@40
    65
{
insilmaril@40
    66
	return author;
insilmaril@40
    67
}
insilmaril@40
    68
insilmaril@40
    69
void VymModel::setComment (const QString &s)
insilmaril@40
    70
{
insilmaril@40
    71
	comment=s;
insilmaril@40
    72
}
insilmaril@40
    73
insilmaril@40
    74
QString VymModel::getComment ()
insilmaril@40
    75
{
insilmaril@40
    76
	return comment;
insilmaril@40
    77
}
insilmaril@40
    78
insilmaril@40
    79
QString VymModel::getDate ()
insilmaril@40
    80
{
insilmaril@40
    81
	return QDate::currentDate().toString ("yyyy-MM-dd");
insilmaril@40
    82
}
insilmaril@40
    83
insilmaril@40
    84
void VymModel::setScene (QGraphicsScene *s)
insilmaril@40
    85
{
insilmaril@40
    86
	mapScene=s;
insilmaril@40
    87
    init();	// Here we have a mapScene set, 
insilmaril@40
    88
			// which is (still) needed to create MapCenters
insilmaril@40
    89
}
insilmaril@40
    90
insilmaril@40
    91
QGraphicsScene* VymModel::getScene ()
insilmaril@40
    92
{
insilmaril@40
    93
	return mapScene;
insilmaril@40
    94
}
insilmaril@40
    95
insilmaril@40
    96
MapCenterObj* VymModel::addMapCenter()
insilmaril@40
    97
{
insilmaril@40
    98
	return addMapCenter (QPointF(0,0));
insilmaril@40
    99
}
insilmaril@40
   100
insilmaril@40
   101
MapCenterObj* VymModel::addMapCenter(QPointF absPos)
insilmaril@40
   102
{
insilmaril@40
   103
	MapCenterObj *mapCenter = new MapCenterObj(mapScene);
insilmaril@40
   104
	mapCenter->move (absPos);
insilmaril@40
   105
    mapCenter->setVisibility (true);
insilmaril@40
   106
	mapCenter->setHeading (QApplication::translate("Heading of mapcenter in new map", "New map"));
insilmaril@40
   107
	mapCenter->setMapEditor(mapEditor);		//FIXME needed to get defLinkStyle, mapLinkColorHint ... for later added objects
insilmaril@40
   108
	mapCenters.append(mapCenter);
insilmaril@40
   109
	return mapCenter;
insilmaril@40
   110
}
insilmaril@40
   111
insilmaril@40
   112
MapCenterObj *VymModel::removeMapCenter(MapCenterObj* mco)
insilmaril@40
   113
{
insilmaril@40
   114
	int i=mapCenters.indexOf (mco);
insilmaril@40
   115
	if (i>=0)
insilmaril@40
   116
	{
insilmaril@40
   117
		mapCenters.removeAt (i);
insilmaril@40
   118
		delete (mco);
insilmaril@40
   119
		if (i>0) return mapCenters.at(i-1);	// Return previous MCO
insilmaril@40
   120
	}
insilmaril@40
   121
	return NULL;
insilmaril@40
   122
}
insilmaril@40
   123
insilmaril@57
   124
MapCenterObj *VymModel::getMapCenterNum (int i)
insilmaril@57
   125
{
insilmaril@57
   126
	if (i>mapCenters.count()-1 || i<0)
insilmaril@57
   127
		return NULL;
insilmaril@57
   128
	else
insilmaril@57
   129
		return mapCenters.at(i);
insilmaril@57
   130
}
insilmaril@57
   131
insilmaril@57
   132
int VymModel::countMapCenters()
insilmaril@57
   133
{
insilmaril@57
   134
	return mapCenters.count();
insilmaril@57
   135
}
insilmaril@57
   136
insilmaril@62
   137
int VymModel::countBranches()
insilmaril@62
   138
{
insilmaril@62
   139
	uint b=0;
insilmaril@62
   140
	BranchObj *bo=first();
insilmaril@62
   141
	while (bo) 
insilmaril@62
   142
	{
insilmaril@62
   143
		b++;
insilmaril@62
   144
		bo=next(bo);
insilmaril@62
   145
	}
insilmaril@62
   146
	return b;
insilmaril@62
   147
}
insilmaril@62
   148
insilmaril@40
   149
BranchObj* VymModel::first()
insilmaril@40
   150
{
insilmaril@40
   151
	if (mapCenters.count()>0) 
insilmaril@40
   152
		return mapCenters.first();
insilmaril@40
   153
	else	
insilmaril@40
   154
		return NULL;
insilmaril@40
   155
}
insilmaril@40
   156
	
insilmaril@40
   157
BranchObj* VymModel::next(BranchObj *bo_start)
insilmaril@40
   158
{
insilmaril@40
   159
	BranchObj *rbo;
insilmaril@40
   160
	BranchObj *bo=bo_start;
insilmaril@40
   161
	if (bo)
insilmaril@40
   162
	{
insilmaril@40
   163
		// Try to find next branch in current MapCenter
insilmaril@40
   164
		rbo=bo->next();
insilmaril@40
   165
		if (rbo) return rbo;
insilmaril@40
   166
insilmaril@40
   167
		// Try to find MapCenter of bo
insilmaril@40
   168
		while (bo->getDepth()>0) bo=(BranchObj*)bo->getParObj();
insilmaril@40
   169
insilmaril@40
   170
		// Try to find next MapCenter
insilmaril@40
   171
		int i=mapCenters.indexOf ((MapCenterObj*)bo);
insilmaril@40
   172
		if (i+2 > mapCenters.count() || i<0) return NULL;
insilmaril@40
   173
		if (mapCenters.at(i+1)!=bo_start)
insilmaril@40
   174
			return mapCenters.at(i+1);
insilmaril@40
   175
	} 
insilmaril@40
   176
	return NULL;
insilmaril@40
   177
}
insilmaril@40
   178
insilmaril@40
   179
LinkableMapObj* VymModel::findMapObj(QPointF p, LinkableMapObj *excludeLMO)
insilmaril@40
   180
{
insilmaril@40
   181
	LinkableMapObj *lmo;
insilmaril@40
   182
insilmaril@40
   183
	for (int i=0;i<mapCenters.count(); i++)
insilmaril@40
   184
	{
insilmaril@40
   185
		lmo=mapCenters.at(i)->findMapObj (p,excludeLMO);
insilmaril@40
   186
		if (lmo) return lmo;
insilmaril@40
   187
	}
insilmaril@40
   188
	return NULL;
insilmaril@40
   189
}
insilmaril@40
   190
insilmaril@40
   191
LinkableMapObj* VymModel::findObjBySelect(const QString &s)
insilmaril@40
   192
{
insilmaril@40
   193
	LinkableMapObj *lmo;
insilmaril@40
   194
	if (!s.isEmpty() )
insilmaril@40
   195
	{
insilmaril@40
   196
		QString part;
insilmaril@40
   197
		QString typ;
insilmaril@40
   198
		QString num;
insilmaril@40
   199
		part=s.section(",",0,0);
insilmaril@40
   200
		typ=part.left (2);
insilmaril@40
   201
		num=part.right(part.length() - 3);
insilmaril@40
   202
		if (typ=="mc" && num.toInt()>=0 && num.toInt() <mapCenters.count() )
insilmaril@40
   203
			return mapCenters.at(num.toInt() );
insilmaril@40
   204
	}		
insilmaril@40
   205
insilmaril@40
   206
	for (int i=0; i<mapCenters.count(); i++)
insilmaril@40
   207
	{
insilmaril@40
   208
		lmo=mapCenters.at(i)->findObjBySelect(s);
insilmaril@40
   209
		if (lmo) return lmo;
insilmaril@40
   210
	}	
insilmaril@40
   211
	return NULL;
insilmaril@40
   212
}
insilmaril@40
   213
insilmaril@40
   214
LinkableMapObj* VymModel::findID (const QString &s)
insilmaril@40
   215
{
insilmaril@40
   216
	LinkableMapObj *lmo;
insilmaril@40
   217
	for (int i=0; i<mapCenters.count(); i++)
insilmaril@40
   218
	{
insilmaril@40
   219
		lmo=mapCenters.at(i)->findID (s);
insilmaril@40
   220
		if (lmo) return lmo;
insilmaril@40
   221
	}	
insilmaril@40
   222
	return NULL;
insilmaril@40
   223
}
insilmaril@40
   224
insilmaril@40
   225
QString VymModel::saveToDir (const QString &tmpdir,const QString &prefix, int verbose, const QPointF &offset)
insilmaril@40
   226
{
insilmaril@40
   227
    QString s;
insilmaril@40
   228
insilmaril@40
   229
	for (int i=0; i<mapCenters.count(); i++)
insilmaril@40
   230
		s+=mapCenters.at(i)->saveToDir (tmpdir,prefix,verbose,offset);
insilmaril@40
   231
    return s;
insilmaril@40
   232
}
insilmaril@40
   233
insilmaril@40
   234
insilmaril@40
   235
//////////////////////////////////////////////
insilmaril@40
   236
// View related
insilmaril@40
   237
//////////////////////////////////////////////
insilmaril@40
   238
insilmaril@40
   239
void VymModel::updateRelPositions()
insilmaril@40
   240
{
insilmaril@40
   241
	for (int i=0; i<mapCenters.count(); i++)
insilmaril@40
   242
		mapCenters.at(i)->updateRelPositions();
insilmaril@40
   243
}
insilmaril@40
   244
insilmaril@40
   245
void VymModel::reposition()
insilmaril@40
   246
{
insilmaril@40
   247
	for (int i=0;i<mapCenters.count(); i++)
insilmaril@40
   248
		mapCenters.at(i)->reposition();	//	for positioning heading
insilmaril@40
   249
}
insilmaril@40
   250
insilmaril@40
   251
QPolygonF VymModel::shape(BranchObj *bo)
insilmaril@40
   252
{
insilmaril@40
   253
	// Creating (arbitrary) shapes
insilmaril@40
   254
insilmaril@40
   255
	QPolygonF p;
insilmaril@40
   256
	QRectF rb=bo->getBBox();
insilmaril@40
   257
	if (bo->getDepth()==0)
insilmaril@40
   258
	{
insilmaril@40
   259
		// Just take BBox of this mapCenter
insilmaril@40
   260
		p<<rb.topLeft()<<rb.topRight()<<rb.bottomRight()<<rb.bottomLeft();
insilmaril@40
   261
		return p;
insilmaril@40
   262
	}
insilmaril@40
   263
insilmaril@40
   264
	// Take union of BBox and TotalBBox 
insilmaril@40
   265
insilmaril@40
   266
	QRectF ra=bo->getTotalBBox();
insilmaril@40
   267
	if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
insilmaril@40
   268
		p   <<ra.bottomLeft()
insilmaril@40
   269
			<<ra.topLeft()
insilmaril@40
   270
			<<QPointF (rb.topLeft().x(), ra.topLeft().y() )
insilmaril@40
   271
			<<rb.topRight()
insilmaril@40
   272
			<<rb.bottomRight()
insilmaril@40
   273
			<<QPointF (rb.bottomLeft().x(), ra.bottomLeft().y() ) ;
insilmaril@40
   274
	else		
insilmaril@40
   275
		p   <<ra.bottomRight()
insilmaril@40
   276
			<<ra.topRight()
insilmaril@40
   277
			<<QPointF (rb.topRight().x(), ra.topRight().y() )
insilmaril@40
   278
			<<rb.topLeft()
insilmaril@40
   279
			<<rb.bottomLeft()
insilmaril@40
   280
			<<QPointF (rb.bottomRight().x(), ra.bottomRight().y() ) ;
insilmaril@40
   281
	return p;		
insilmaril@40
   282
insilmaril@40
   283
}
insilmaril@40
   284
insilmaril@40
   285
void VymModel::moveAway(LinkableMapObj *lmo)
insilmaril@40
   286
{
insilmaril@40
   287
	// Autolayout:
insilmaril@40
   288
	//
insilmaril@40
   289
	// Move all branches and MapCenters away from lmo 
insilmaril@40
   290
	// to avoid collisions 
insilmaril@40
   291
insilmaril@40
   292
	QPolygonF pA;
insilmaril@40
   293
	QPolygonF pB;
insilmaril@40
   294
insilmaril@40
   295
	BranchObj *boA=(BranchObj*)lmo;
insilmaril@40
   296
	BranchObj *boB;
insilmaril@40
   297
	for (int i=0; i<mapCenters.count(); i++)
insilmaril@40
   298
	{
insilmaril@40
   299
		boB=mapCenters.at(i);
insilmaril@40
   300
		pA=shape (boA);
insilmaril@40
   301
		pB=shape (boB);
insilmaril@40
   302
		PolygonCollisionResult r = PolygonCollision(pA, pB, QPoint(0,0));
insilmaril@40
   303
		cout <<"------->"
insilmaril@40
   304
			<<"="<<r.intersect
insilmaril@40
   305
			<<"  ("<<qPrintable(boA->getHeading() )<<")"
insilmaril@40
   306
			<<"  with ("<< qPrintable (boB->getHeading() )
insilmaril@40
   307
			<<")  willIntersect"
insilmaril@40
   308
			<<r.willIntersect 
insilmaril@40
   309
			<<"  minT="<<r.minTranslation<<endl<<endl;
insilmaril@40
   310
	}
insilmaril@40
   311
}
insilmaril@40
   312
insilmaril@40
   313
void VymModel::animate()
insilmaril@40
   314
{
insilmaril@40
   315
	animationTimer->stop();
insilmaril@40
   316
	BranchObj *bo;
insilmaril@40
   317
	int i=0;
insilmaril@40
   318
	while (i<animObjList.size() )
insilmaril@40
   319
	{
insilmaril@40
   320
		bo=(BranchObj*)animObjList.at(i);
insilmaril@40
   321
		if (!bo->animate())
insilmaril@40
   322
		{
insilmaril@40
   323
			if (i>=0) animObjList.removeAt(i);
insilmaril@40
   324
			i--;
insilmaril@40
   325
		}
insilmaril@40
   326
		bo->reposition();
insilmaril@40
   327
		i++;
insilmaril@40
   328
	} 
insilmaril@40
   329
	mapEditor->updateSelection();
insilmaril@40
   330
	mapScene->update();
insilmaril@43
   331
	if (!animObjList.isEmpty() ) animationTimer->start();
insilmaril@40
   332
}
insilmaril@40
   333
insilmaril@40
   334
insilmaril@40
   335
void VymModel::startAnimation(const QPointF &start, const QPointF &dest)
insilmaril@40
   336
{
insilmaril@40
   337
	BranchObj *bo=getSelectedBranch();
insilmaril@40
   338
	if (bo && bo->getDepth()>0) 
insilmaril@40
   339
	{
insilmaril@40
   340
		AnimPoint ap;
insilmaril@40
   341
		ap.setStart (start);
insilmaril@40
   342
		ap.setDest  (dest);
insilmaril@40
   343
		ap.setTicks (animationTicks);
insilmaril@40
   344
		ap.setAnimated (true);
insilmaril@40
   345
		bo->setAnimation (ap);
insilmaril@40
   346
		animObjList.append( bo );
insilmaril@40
   347
		animationTimer->setSingleShot (true);
insilmaril@40
   348
		animationTimer->start(animationInterval);
insilmaril@40
   349
	}
insilmaril@40
   350
}
insilmaril@40
   351
insilmaril@40
   352
void VymModel::stopAnimation(MapObj *mo)
insilmaril@40
   353
{
insilmaril@40
   354
	int i=animObjList.indexOf(mo);
insilmaril@40
   355
    if (i>=0)
insilmaril@40
   356
		animObjList.removeAt (i);
insilmaril@40
   357
}
insilmaril@40
   358
insilmaril@40
   359
//////////////////////////////////////////////
insilmaril@40
   360
// Selection related
insilmaril@40
   361
//////////////////////////////////////////////
insilmaril@40
   362
insilmaril@40
   363
insilmaril@40
   364
// Only as long as we dont have Model/View yet
insilmaril@40
   365
LinkableMapObj* VymModel::getSelection()
insilmaril@40
   366
{
insilmaril@40
   367
	return mapEditor->getSelection();
insilmaril@40
   368
}
insilmaril@40
   369
BranchObj* VymModel::getSelectedBranch()
insilmaril@40
   370
{
insilmaril@40
   371
	return mapEditor->getSelectedBranch();
insilmaril@40
   372
}
insilmaril@40
   373
insilmaril@40
   374
insilmaril@40
   375
bool VymModel::select (const QString &s)
insilmaril@40
   376
{
insilmaril@40
   377
	return mapEditor->select (s);
insilmaril@40
   378
}
insilmaril@40
   379
insilmaril@40
   380
QString VymModel::getSelectString (LinkableMapObj *lmo)
insilmaril@40
   381
{
insilmaril@40
   382
	QString s;
insilmaril@40
   383
	if (!lmo) return s;
insilmaril@40
   384
	if (typeid(*lmo)==typeid(BranchObj) ||
insilmaril@40
   385
		typeid(*lmo)==typeid(MapCenterObj) )
insilmaril@40
   386
	{	
insilmaril@40
   387
		LinkableMapObj *par=lmo->getParObj();
insilmaril@40
   388
		if (par)
insilmaril@40
   389
		{
insilmaril@40
   390
			if (lmo->getDepth() ==1)
insilmaril@40
   391
				// Mainbranch, return 
insilmaril@40
   392
				s= "bo:" + QString("%1").arg(((BranchObj*)lmo)->getNum());
insilmaril@40
   393
			else	
insilmaril@40
   394
				// Branch, call myself recursively
insilmaril@40
   395
				s= getSelectString(par) + ",bo:" + QString("%1").arg(((BranchObj*)lmo)->getNum());
insilmaril@40
   396
		} else
insilmaril@40
   397
		{
insilmaril@40
   398
			// MapCenter
insilmaril@40
   399
			int i=mapCenters.indexOf ((MapCenterObj*)lmo);
insilmaril@40
   400
			if (i>=0) s=QString("mc:%1").arg(i);
insilmaril@40
   401
		}	
insilmaril@40
   402
	}	
insilmaril@40
   403
	return s;
insilmaril@40
   404
insilmaril@40
   405
}
insilmaril@40
   406
insilmaril@40
   407
	
insilmaril@40
   408
void VymModel::setHideTmp (HideTmpMode mode)
insilmaril@40
   409
{
insilmaril@40
   410
	for (int i=0;i<mapCenters.count(); i++)
insilmaril@40
   411
		mapCenters.at(i)->setHideTmp (mode);	
insilmaril@40
   412
}
insilmaril@40
   413
insilmaril@40
   414
QRectF VymModel::getTotalBBox()
insilmaril@40
   415
{
insilmaril@40
   416
	QRectF r;
insilmaril@40
   417
	for (int i=0;i<mapCenters.count(); i++)
insilmaril@40
   418
		r=addBBox (mapCenters.at(i)->getTotalBBox(), r);
insilmaril@40
   419
	return r;	
insilmaril@40
   420
}
insilmaril@40
   421