]> git.sven.stormbind.net Git - sven/vym.git/blob - branchitem.cpp
ed97e5db505c8432de6b405c765ae5ecab259755
[sven/vym.git] / branchitem.cpp
1 #include "branchitem.h"
2
3 #include "attributeitem.h"
4 #include "branchobj.h"
5 #include "task.h"
6 #include "taskmodel.h"
7 #include "vymmodel.h"
8 #include "xlink.h"
9 #include "xlinkitem.h"
10
11 extern TaskModel *taskModel;
12
13 //#include <QDir>
14
15 BranchItem::BranchItem(const QList<QVariant> &data, TreeItem *parent):MapItem (data,parent)
16 {
17     //qDebug()<< "Constr. BranchItem this="<<this;
18
19     // Set type if parent is known yet 
20     // if not, type is set in insertBranch or TreeItem::appendChild
21     if (parent==rootItem)
22         setType (MapCenter);
23     else
24         setType (Branch);
25
26     scrolled=false;
27     tmpUnscrolled=false;
28
29     includeImagesVer=false;
30     includeImagesHor=false;
31     includeChildren=false;
32     childrenLayout = BranchItem::AutoPositioning;
33      
34     lastSelectedBranchNum=-1;
35     lastSelectedBranchNumAlt=-1;
36
37     task=NULL;
38 }
39
40 BranchItem::~BranchItem()
41 {
42     //qDebug()<< "Destr. BranchItem  this="<<this<<"  "<<getHeading();
43     if (mo) 
44     {
45         delete mo;
46         mo=NULL;
47     }
48     clear();
49 }
50
51 void BranchItem::clear()
52 {
53     if (task) taskModel->deleteTask (task);
54 }
55
56 void BranchItem::copy (BranchItem *other)  // TODO lacks most of data...
57 {
58     scrolled=other->scrolled;
59     tmpUnscrolled=other->tmpUnscrolled;
60 }
61
62 BranchItem* BranchItem::parentBranch ()
63 {
64     return (BranchItem*) parentItem;
65 }
66
67 void BranchItem::insertBranch (int pos, BranchItem *branch)
68 {
69     if (pos<0) pos=0;
70     if (pos>branchCounter) pos=branchCounter;
71     childItems.insert(pos+branchOffset,branch);
72     branch->parentItem=this;
73     branch->rootItem=rootItem;
74     branch->setModel (model);
75     if (parentItem==rootItem)
76         setType (MapCenter);
77     else
78         setType (Branch);
79
80
81     if (branchCounter==0)
82         branchOffset=childItems.count()-1;
83     branchCounter++;
84 }
85
86 QString BranchItem::saveToDir (const QString &tmpdir,const QString &prefix, const QPointF& offset, QList <Link*> &tmpLinks ) 
87 {
88     // Cloudy stuff can be hidden during exports
89     if (hidden) return QString();
90
91     // Save uuid 
92     QString idAttr=attribut("uuid",uuid.toString());
93
94     QString s,a;
95
96     // Update of note is usually done while unselecting a branch
97     
98     QString scrolledAttr;
99     if (scrolled) 
100         scrolledAttr=attribut ("scrolled","yes");
101     else
102         scrolledAttr="";
103
104     // save area, if not scrolled   // not needed if HTML is rewritten...
105                                     // also we could check if _any_ of parents is scrolled
106     QString areaAttr;
107     if (mo && parentItem->isBranchLikeType() && !((BranchItem*)parentItem)->isScrolled() )
108     {
109         qreal x=mo->getAbsPos().x();
110         qreal y=mo->getAbsPos().y();
111         areaAttr=
112             attribut("x1",QString().setNum(x-offset.x())) +
113             attribut("y1",QString().setNum(y-offset.y())) +
114             attribut("x2",QString().setNum(x+mo->width()-offset.x())) +
115             attribut("y2",QString().setNum(y+mo->height()-offset.y()));
116
117     } else
118         areaAttr="";
119     
120     QString elementName;
121     if (parentItem==rootItem)
122         elementName="mapcenter";
123     else
124         elementName="branch";
125
126     // Free positioning of children
127     QString layoutAttr;
128     if (childrenLayout == BranchItem::FreePositioning)
129         layoutAttr += attribut ("childrenFreePos","true");
130
131     // Save rotation
132     QString rotAttr;
133     if (mo && mo->getRotation() !=0 )
134         rotAttr=attribut ("rotation",QString().setNum (mo->getRotation() ) );
135
136     s=beginElement (elementName
137         + getMapAttr()
138         + getGeneralAttr()
139         + scrolledAttr 
140         + getIncludeImageAttr() 
141     + rotAttr
142     + layoutAttr
143         + idAttr
144         );
145     incIndent();
146
147     // save heading
148     s += heading.saveToDir();
149
150     // Save frame  // not saved if there is no MO
151     if (mo)
152     {
153         // Avoid saving NoFrame for objects other than MapCenter
154         if (depth() == 0  || ((OrnamentedObj*)mo)->getFrame()->getFrameType()!=FrameObj::NoFrame)
155             s+=((OrnamentedObj*)mo)->getFrame()->saveToDir ();
156     }
157
158     // save names of flags set
159     s+=standardFlags.saveToDir(tmpdir,prefix,0);
160     
161     // Save Images
162     for (int i=0; i<imageCount(); ++i)
163         s+=getImageNum(i)->saveToDir (tmpdir,prefix);
164
165     // save attributes
166     for (int i=0; i<attributeCount(); ++i)
167         s+=getAttributeNum(i)->getDataXML();
168
169     // save note
170     if (!note.isEmpty() )
171         s+=note.saveToDir();
172     
173     // save task
174     if (task)
175         s+=task->saveToDir();
176
177     // Save branches
178     int i=0;
179     TreeItem *ti=getBranchNum(i);
180     while (ti)
181     {
182         s+=getBranchNum(i)->saveToDir(tmpdir,prefix,offset,tmpLinks);
183         i++;
184         ti=getBranchNum(i);
185     }   
186
187     // Mark Links for save
188     for (int i=0; i<xlinkCount(); ++i)
189     {
190         Link *l=getXLinkItemNum (i)->getLink();
191         if (l && !tmpLinks.contains (l)) tmpLinks.append (l);
192     }
193     decIndent();
194     s += endElement (elementName);
195     return s;
196 }
197
198 void BranchItem::updateVisibility()
199 {
200     // Needed to hide relinked branch, if parent is scrolled
201     if (mo)
202     {
203         if (hasScrolledParent(this) || hidden)
204             mo->setVisibility (false);
205         else    
206             mo->setVisibility (true);
207     }
208 }
209
210 void BranchItem::setHeadingColor (QColor color)
211 {
212     TreeItem::setHeadingColor (color);
213     if (mo) ((BranchObj*)mo)->setColor (color);
214 }
215
216 void BranchItem::updateTaskFlag()
217 {
218     systemFlags.deactivateGroup ("system-tasks");
219     if (task)
220     {
221         QString s="system-" + task->getIconString();
222         systemFlags.activate (s);
223         model->emitDataChanged(this);
224     } 
225 }
226
227 void BranchItem::setTask(Task *t) 
228 {
229     task=t;
230     updateTaskFlag();
231 }
232
233 Task* BranchItem::getTask()
234 {
235     return task;
236 }
237
238 void BranchItem::unScroll()
239 {
240     if (tmpUnscrolled) resetTmpUnscroll();
241     if (scrolled) toggleScroll();
242 }
243
244 bool BranchItem::toggleScroll() 
245 {
246     // MapCenters are not scrollable
247     if (depth()==0) return false;
248
249     BranchObj *bo;
250     if (scrolled)
251     {
252         scrolled=false;
253         systemFlags.deactivate("system-scrolledright");
254         if (branchCounter>0)
255             for (int i=0;i<branchCounter;++i)
256             {
257                 bo=(BranchObj*)(getBranchNum(i)->getMO());
258                 if (bo) bo->setVisibility(true);
259             }
260     } else
261     {
262         scrolled=true;
263         systemFlags.activate("system-scrolledright");
264         if (branchCounter>0)
265             for (int i=0;i<branchCounter;++i)
266             {
267                 bo=(BranchObj*)(getBranchNum(i)->getMO());
268                 if (bo) bo->setVisibility(false);
269             }
270     }
271     return true;
272 }
273
274 bool BranchItem::isScrolled()
275 {
276     return scrolled;
277 }
278
279 bool BranchItem::hasScrolledParent(BranchItem *start)
280 {
281     // Calls parents recursivly to
282     // find out, if we are scrolled at all.
283     // But ignore myself, just look at parents.
284
285     if (!start) start=this;
286
287     if (this !=start && scrolled) return true;
288
289     BranchItem* bi=(BranchItem*)parentItem;
290     if (bi && bi!=rootItem ) 
291         return bi->hasScrolledParent(start);
292     else
293         return false;
294 }
295
296 bool BranchItem::tmpUnscroll(BranchItem *start)
297 {
298     bool result=false;
299
300     if (!start) start=this;
301
302     // Unscroll parent (recursivly)
303     BranchItem * pi=(BranchItem*)parentItem;
304     if (pi && pi->isBranchLikeType() ) result=pi->tmpUnscroll(start);
305         
306     // Unscroll myself
307     if (start !=this && scrolled)
308     {
309         tmpUnscrolled=true;
310         systemFlags.activate("system-tmpUnscrolledRight");
311         toggleScroll();
312         model->emitDataChanged (this); 
313         result=true;
314     }   
315     return result;
316 }
317
318 bool BranchItem::resetTmpUnscroll()
319 {
320     bool result=false;
321
322     // Unscroll parent (recursivly)
323     BranchItem * pi=(BranchItem*)parentItem;
324     if (pi && pi->isBranchLikeType() ) result=pi->resetTmpUnscroll();
325         
326     // Unscroll myself
327     if (tmpUnscrolled)
328     {
329         tmpUnscrolled=false;
330         systemFlags.deactivate("system-tmpUnscrolledRight");
331         toggleScroll();
332         model->emitDataChanged (this);
333         result=true;
334     }   
335     return result;
336 }
337
338 void BranchItem::sortChildren(bool inverse) //FIXME-4 optimize by not using moveUp/Down
339 {
340     int childCount=branchCounter; 
341     int curChildIndex;
342     bool madeChanges=false;
343     do
344     {
345         madeChanges=false;
346         for(curChildIndex=1;curChildIndex<childCount;curChildIndex++)
347         {
348             BranchItem* curChild =getBranchNum(curChildIndex);
349             BranchItem* prevChild=getBranchNum(curChildIndex-1);
350             if (inverse)
351             {
352         if (prevChild->getHeadingPlain().compare(curChild->getHeadingPlain())<0)
353                 {
354                     model->moveUp (curChild);
355                     madeChanges=true;
356                 }   
357             } else  
358         if (prevChild->getHeadingPlain().compare(curChild->getHeadingPlain())>0)
359                 {
360                     model->moveUp (curChild);
361                     madeChanges=true;
362                 }   
363         } 
364     }while(madeChanges);
365 }
366
367 void BranchItem::setChildrenLayout(BranchItem::LayoutHint layoutHint)
368 {
369     childrenLayout = layoutHint;
370 }
371
372 BranchItem::LayoutHint BranchItem::getChildrenLayout()
373 {
374     return childrenLayout;
375 }
376
377 void BranchItem::setIncludeImagesVer(bool b)
378 {
379     includeImagesVer=b;
380 }
381
382 bool BranchItem::getIncludeImagesVer()
383 {
384     return includeImagesVer;
385 }
386
387 void BranchItem::setIncludeImagesHor(bool b)
388 {
389     includeImagesHor=b;
390 }
391
392 bool BranchItem::getIncludeImagesHor()
393 {
394     return includeImagesHor;
395 }
396
397 QString BranchItem::getIncludeImageAttr()
398 {
399     QString a;
400     if (includeImagesVer)
401         a=attribut ("incImgV","true");
402     if (includeImagesHor)
403         a+=attribut ("incImgH","true");
404     return a;   
405 }
406
407 BranchItem* BranchItem::getFramedParentBranch(BranchItem *start)
408 {
409     BranchObj *bo=getBranchObj();
410     if (bo && bo->getFrameType() != FrameObj::NoFrame)
411     {
412         if (bo->getFrame()->getFrameIncludeChildren() ) return this;
413         if (this == start) return this;
414     } 
415     BranchItem* bi=(BranchItem*)parentItem;
416     if (bi && bi!=rootItem ) 
417         return bi->getFramedParentBranch(start);
418     else
419         return NULL;
420 }
421
422 void BranchItem::setFrameIncludeChildren(bool b)
423 {
424     includeChildren=b;  // FIXME-4 ugly: same information stored in FrameObj
425     BranchObj *bo=getBranchObj();
426     if (bo) bo->getFrame()->setFrameIncludeChildren(b);
427 }
428
429 bool BranchItem::getFrameIncludeChildren()
430 {
431     BranchObj *bo=getBranchObj();
432     if (bo) 
433         return bo->getFrame()->getFrameIncludeChildren();
434     else        
435         return includeChildren;
436 }
437
438 void BranchItem::setLastSelectedBranch()
439 {
440     int d=depth();
441     if (d>=0)
442     {
443         if (d==1)
444             // Hack to save an additional lastSelected for mapcenters in MapEditor
445             // depending on orientation
446             // this allows to go both left and right from there
447             if (mo && ((BranchObj*)mo)->getOrientation()==LinkableMapObj::LeftOfCenter)
448             {
449                 ((BranchItem*)parentItem)->lastSelectedBranchNumAlt=parentItem->num(this);
450                 return;
451             }
452         ((BranchItem*)parentItem)->lastSelectedBranchNum=parentItem->num(this);
453     }
454 }
455
456 void BranchItem::setLastSelectedBranch(int i)
457 {
458         lastSelectedBranchNum=i;
459 }
460
461 BranchItem* BranchItem::getLastSelectedBranch()
462 {
463     if (lastSelectedBranchNum>=branchCounter)
464         return getBranchNum (branchCounter-1);
465     else    
466         return getBranchNum (lastSelectedBranchNum);
467 }
468
469 BranchItem* BranchItem::getLastSelectedBranchAlt()
470 {
471     return getBranchNum (lastSelectedBranchNumAlt);
472 }
473
474
475
476
477 TreeItem* BranchItem::findMapItem (QPointF p, TreeItem* excludeTI)
478 {
479     // Search branches
480     TreeItem *ti;
481     for (int i=0; i<branchCount(); ++i)
482     {   
483         ti=getBranchNum(i)->findMapItem(p, excludeTI);
484         if (ti != NULL) return ti;
485     }
486     
487     // Search images
488     ImageItem *ii;
489     for (int i=0; i<imageCount(); ++i )
490     {
491         ii=getImageNum (i);
492         MapObj *mo=ii->getMO();
493         if (mo && mo->isInClickBox(p) && 
494             (ii != excludeTI) && 
495             this!= excludeTI &&
496             mo->isVisibleObj() 
497         ) return ii;
498     }
499
500     // Search myself
501     if (getBranchObj()->isInClickBox (p) && (this != excludeTI) && getBranchObj()->isVisibleObj() ) 
502         return this;
503
504
505     // Search attributes
506     AttributeItem *ai;
507     for (int i=0; i<attributeCount(); ++i )
508     {
509         ai=getAttributeNum (i);
510         MapObj *mo=ai->getMO();
511         if (mo && mo->isInClickBox(p) && 
512             (ai != excludeTI) && 
513             this!= excludeTI &&
514             mo->isVisibleObj() 
515         ) return ai;
516     }
517     return NULL;
518 }
519
520 void BranchItem::updateStyles(const bool &keepFrame)
521 {
522     // Update styles when relinking branches
523     if (mo)
524     { 
525         BranchObj *bo=getBranchObj();
526         if ( parentItem != rootItem)
527             bo->setParObj ( (LinkableMapObj*) ( ((MapItem*)parentItem)->getMO() ) );
528         else
529             bo->setParObj (NULL);
530         bo->setDefAttr(BranchObj::MovedBranch,keepFrame);
531     }
532 }
533
534 BranchObj* BranchItem::getBranchObj()   
535 {
536     return (BranchObj*)mo;
537 }
538
539 BranchObj* BranchItem::createMapObj(QGraphicsScene *scene)  
540 {
541     BranchObj *newbo;
542
543     if (parentItem==rootItem)
544     {
545         newbo=new BranchObj(NULL,this);
546         mo=newbo;
547         scene->addItem (newbo);
548     } else
549     {
550         newbo=new BranchObj( ((MapItem*)parentItem)->getMO(),this);
551         mo=newbo;
552         // Set visibility depending on parents
553         if (parentItem!=rootItem && 
554             ( ((BranchItem*)parentItem)->scrolled || !((MapItem*)parentItem)->getLMO()->isVisibleObj() ) )
555             newbo->setVisibility (false);
556         if (depth()==1) 
557         {
558            qreal r=190;
559            qreal a= -M_PI_4 + M_PI_2 * (num()) + (M_PI_4/2)*(num()/4 % 4);
560            QPointF p (r*cos (a), r*sin (a));
561            newbo->setRelPos (p);
562         }
563     }
564     newbo->setDefAttr(BranchObj::NewBranch);
565     initLMO();
566
567     if (!getHeading().isEmpty() ) 
568     {
569         newbo->updateData();    
570         newbo->setColor (heading.getColor());
571     }   
572         
573     return newbo;
574 }
575