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