]> git.sven.stormbind.net Git - sven/vym.git/blob - treeitem.cpp
fcb32d6ccb9b2e669e0e5a3e29d4678377af242c
[sven/vym.git] / treeitem.cpp
1 #include <iostream>
2 #include <QStringList>
3
4 #include "attributeitem.h"
5 #include "branchobj.h"
6 #include "branchitem.h"
7 #include "misc.h"
8 #include "treeitem.h"
9 #include "vymmodel.h"
10 #include "xlinkitem.h"
11 #include "xlinkobj.h"
12
13 using namespace std;
14
15 extern uint itemLastID;
16 extern FlagRow* standardFlagsMaster;
17 extern FlagRow* systemFlagsMaster;
18
19 extern QTextStream vout;
20
21 TreeItem::TreeItem()
22 {
23     //qDebug() << "Constr. TI  this="<<this;
24     init();
25     itemData.clear();
26     rootItem=this;
27     parentItem=NULL;
28 }
29
30 TreeItem::TreeItem(const QList<QVariant> &data, TreeItem *parent)
31 {
32     //qDebug() << "Constructor TreeItem this="<<this<<"  parent="<<parent;
33     init();
34     parentItem = parent;
35     itemData = data;
36     
37     rootItem=this;
38     if (parentItem )
39         rootItem=parentItem->rootItem;
40 }
41
42 TreeItem::~TreeItem()
43 {
44     //qDebug()<<"Destr TreeItem this="<<this<<"  childcount="<<childItems.count();
45     TreeItem *ti;
46     while (!childItems.isEmpty())
47     {
48         ti = childItems.takeFirst();
49         delete ti;
50     }
51 }
52
53
54 void TreeItem::init()
55 {
56     model=NULL;
57
58     // Assign ID  
59     itemLastID++;
60     id = itemLastID;
61     uuid = QUuid::createUuid();
62
63     branchOffset = 0;
64     branchCounter = 0;
65
66     imageOffset = 0;
67     imageCounter = 0;
68
69     attributeCounter = 0;
70     attributeOffset = 0;
71
72     xlinkCounter = 0;
73     xlinkOffset = 0;
74
75     target = false;
76
77     heading.clear();
78     note.setText("");
79
80     hidden = false;
81     hideExport = false;
82
83     backgroundColor = Qt::transparent;
84
85     standardFlags.setMasterRow (standardFlagsMaster);
86     systemFlags.setMasterRow (systemFlagsMaster);
87 }
88
89 void TreeItem::setModel (VymModel *m)
90 {
91     model = m;
92 }
93
94 VymModel* TreeItem::getModel ()
95 {
96     return model;
97 }
98
99 int TreeItem::getRowNumAppend (TreeItem *item)
100 {   
101     switch (item->type)
102     {
103         case Attribute: return attributeOffset + attributeCounter;
104         case XLink: return xlinkOffset + xlinkCounter;
105         case Image: return imageOffset + imageCounter;
106         case MapCenter: return branchOffset + branchCounter;
107         case Branch: return branchOffset + branchCounter;
108         default: return -1;
109     }
110 }
111
112 void TreeItem::appendChild(TreeItem *item)
113 {
114     item->parentItem=this;
115     item->rootItem=rootItem;
116     item->setModel (model);
117
118     if (item->type == Attribute)
119     {
120         // attribute are on top of list
121         childItems.insert (attributeCounter,item);
122         attributeCounter++;
123         xlinkOffset++;
124         imageOffset++;
125         branchOffset++;
126     }
127
128     if (item->type == XLink)
129     {
130         childItems.insert (xlinkCounter+xlinkOffset,item);
131         xlinkCounter++;
132         imageOffset++;
133         branchOffset++;
134     }
135
136     if (item->type == Image)
137     {
138         childItems.insert (imageCounter+imageOffset,item);
139         imageCounter++;
140         branchOffset++;
141     }
142
143     if (item->isBranchLikeType())
144     {
145         // branches are on bottom of list
146         childItems.append(item);
147         branchCounter++;
148
149         // Set correct type     
150         if (this==rootItem)
151             item->setType(MapCenter);
152         else
153             item->setType (Branch);
154     }
155 }
156
157 void TreeItem::removeChild(int row)
158 {
159     if (row<0 || row > childItems.size()-1)
160         qWarning ("TreeItem::removeChild tried to remove non existing item?!");
161     else
162     {
163         if (childItems.at(row)->type==Attribute)
164         {
165             attributeCounter--;
166             xlinkOffset--;
167             imageOffset--;
168             branchOffset--;
169         }   
170         if (childItems.at(row)->type==XLink)
171         {
172             xlinkCounter--;
173             imageOffset--;
174             branchOffset--;
175         }   
176         if (childItems.at(row)->type==Image)
177         {
178             imageCounter--;
179             branchOffset--;
180         }   
181         if (childItems.at(row)->isBranchLikeType())
182             branchCounter--;
183
184         childItems.removeAt (row);
185     }
186 }
187
188 TreeItem *TreeItem::child(int row)
189 {
190     return childItems.value(row);
191 }
192
193 int TreeItem::childCount() const
194 {
195     return childItems.count();
196 }
197
198 int TreeItem::childNumber() const
199 {
200     if (parentItem)
201         return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));
202
203     return 0;
204 }
205
206 int TreeItem::columnCount() const
207 {
208     return 1;
209 }
210
211 int TreeItem::branchCount() const
212 {
213     return branchCounter;
214 }
215
216 int TreeItem::imageCount() const
217 {
218     return imageCounter; 
219 }
220
221 int TreeItem::xlinkCount() const
222 {
223     return xlinkCounter; 
224 }
225
226 int TreeItem::attributeCount() const 
227 {
228     return attributeCounter; 
229 }
230
231 int TreeItem::row() const
232 {
233     if (parentItem)
234         return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));
235
236     qDebug() << "TI::row() pI=NULL this="<<this<<"  ***************";
237     return 0;
238 }
239
240 int TreeItem::depth() 
241 {
242     // Rootitem d=-1
243     // MapCenter d=0
244     int d=-2;
245     TreeItem *ti=this;
246     while (ti!=NULL)
247     {
248         ti=ti->parent();
249         d++;
250     }
251     return d;
252 }
253
254 TreeItem *TreeItem::parent()
255 {
256     //qDebug() << "TI::parent of "<<getHeadingStd()<<"  is "<<parentItem;
257     return parentItem;
258 }
259
260 bool TreeItem::isChildOf (TreeItem *ti)
261 {
262     if (this==rootItem) return false;
263     if (parentItem==ti) return true;
264     if (parentItem==rootItem) return false;
265     return parentItem->isChildOf (ti);
266 }
267
268 int TreeItem::childNum()
269 {
270     return parentItem->childItems.indexOf (this);
271 }
272
273 int TreeItem::num()
274 {
275     if (!parentItem) return -1;
276     return parentItem->num (this);
277 }
278
279 int TreeItem::num (TreeItem *item)
280 {
281     if (!item) return -1;
282     if (!childItems.contains(item)) return -1;
283     switch (item->getType())
284     {
285         case MapCenter: return childItems.indexOf (item) - branchOffset;
286         case Branch: return childItems.indexOf (item) - branchOffset;
287         case Image: return childItems.indexOf (item) - imageOffset;
288         case Attribute: return childItems.indexOf (item) - attributeOffset;
289         case XLink: return childItems.indexOf (item) - xlinkOffset;
290         default: return -1;
291     }
292 }
293 void TreeItem::setType(const Type t)
294 {
295     type=t;
296     itemData[1]=getTypeName();
297 }
298
299 TreeItem::Type TreeItem::getType()
300 {
301     if (type==Branch && depth()==0) return MapCenter;   // should not be necesssary
302     return type;
303 }
304
305 bool TreeItem::isBranchLikeType() const
306 {
307     if (type==Branch ||type==MapCenter) return true;
308     return false;
309 }
310
311 QString TreeItem::getTypeName()
312 {
313     switch (type)
314     {
315         case Undefined: return QString ("Undefined");
316         case MapCenter: return QString ("MapCenter");
317         case Branch: return QString ("Branch");
318         case Image: return QString ("Image");
319         case Attribute: return QString ("Attribute");
320         case XLink: return QString ("XLink");
321         default: return QString ("TreeItem::getTypeName no typename defined?!");
322     }
323 }
324
325
326 QVariant TreeItem::data(int column) const
327 {
328     return itemData.value(column);
329 }
330
331 void TreeItem::setHeading (const VymText &vt)
332 {
333     heading = vt;
334     itemData[0]= heading.getTextASCII();  // used in TreeEditor
335 }
336
337 void TreeItem::setHeadingPlainText (const QString &s)
338 {
339     VymText vt;
340
341     vt.setPlainText(s);
342     
343     if (!heading.isRichText() )
344         // Keep current color
345         vt.setColor( heading.getColor() );
346     setHeading(vt);
347 }
348
349 Heading TreeItem::getHeading() const
350 {
351     return heading;
352 }
353
354 QString TreeItem::getHeadingText ()
355 {
356     return heading.getText();
357 }
358
359 std::string TreeItem::getHeadingStd () const
360 {
361     return getHeadingPlain().toStdString();
362 }
363
364 QString TreeItem::getHeadingPlain() const
365 {
366     // strip beginning and tailing WS
367     return heading.getTextASCII().trimmed();
368 }
369
370 QString TreeItem::getHeadingPlainWithParents(uint numberOfParents = 0) 
371 {
372     QString s = getHeadingPlain();
373     if (numberOfParents > 0) 
374     {
375         TreeItem *ti = this;
376         int l = numberOfParents;
377         while ( l > 0 && ti->depth() > 0 )
378         {
379             ti = ti->parent();
380             if (ti)
381                 s = ti->getHeadingPlain() + " -> " + s;
382             else
383                 l = 0;
384             l--;
385         }
386     }
387     return s;
388 }
389
390 QString TreeItem::getHeadingDepth () // Indent by depth for debugging
391 {
392     QString ds;
393     for (int i=0; i<depth(); i++) ds += "  ";
394     return ds + getHeadingPlain();
395 }
396
397 void TreeItem::setHeadingColor (QColor color)
398 {
399     heading.setColor(color);
400 }
401
402 QColor TreeItem::getHeadingColor ()
403 {
404     return heading.getColor();
405 }
406
407 void TreeItem::setBackgroundColor (QColor color)
408 {
409     backgroundColor=color;
410 }
411
412 QColor TreeItem::getBackgroundColor() 
413 {
414     return backgroundColor;
415 }
416
417 void TreeItem::setURL (const QString &u)
418 {
419     url=u;
420     if (!url.isEmpty())
421     {
422         if (url.contains ("bugzilla.novell.com"))
423         {
424             systemFlags.activate ("system-url-bugzilla-novell");
425             if (systemFlags.isActive ("system-url"))
426                 systemFlags.deactivate ("system-url");
427         } else
428         {
429             systemFlags.activate ("system-url");
430             if (systemFlags.isActive ("system-url-bugzilla-novell"))
431                 systemFlags.deactivate ("system-url-bugzilla-novell");
432         }
433     }
434     else
435     {
436         if (systemFlags.isActive ("system-url"))
437             systemFlags.deactivate ("system-url");
438         if (systemFlags.isActive ("system-url-bugzilla-novell"))
439             systemFlags.deactivate ("system-url-bugzilla-novell");
440     }
441 }
442
443 QString TreeItem::getURL ()
444 {
445     return url;
446 }
447
448 void TreeItem::setVymLink (const QString &vl)
449 {
450     if (!vl.isEmpty())
451     {
452         // We need the relative (from loading)
453         // or absolute path (from User event)
454         // and build the absolute path.
455
456         QDir d(vl);
457         if (d.isAbsolute())
458             vymLink = vl;
459         else
460         {
461             // If we have relative, use path of
462             // current map to build absolute path
463             // based on path of current map and relative
464             // path to linked map
465             QString p=dirname(model->getDestPath());
466             vymLink = convertToAbs( p, vl);
467         }
468         systemFlags.activate("system-vymLink");
469     }
470     else
471     {
472         vymLink.clear();
473         systemFlags.deactivate("system-vymLink");
474     }
475 }
476
477 QString TreeItem::getVymLink ()
478 {
479     return vymLink;
480 }
481
482 void TreeItem::toggleTarget ()
483 {
484     systemFlags.toggle ("system-target");
485     target= systemFlags.isActive("system-target");
486     model->emitDataChanged(this);       // FIXME-4 better call from VM?
487 }
488
489 bool TreeItem::isTarget ()
490 {
491     return target;
492 }
493
494 bool TreeItem::isNoteEmpty()
495 {
496     return note.isEmpty();
497 }
498
499 void TreeItem::clearNote()
500 {
501     note.clear();
502     systemFlags.deactivate ("system-note");
503 }
504
505 void TreeItem::setNote(const VymText &vt)
506 {
507     note = vt;
508     if (!note.isEmpty() && !systemFlags.isActive ("system-note"))
509         systemFlags.activate ("system-note");
510     if (note.isEmpty() && systemFlags.isActive ("system-note"))
511         systemFlags.deactivate ("system-note");
512 }
513
514 void TreeItem::setNote(const VymNote &vn)
515 {
516     note = vn;
517     if (!note.isEmpty() && !systemFlags.isActive ("system-note"))
518     systemFlags.activate ("system-note");
519     if (note.isEmpty() && systemFlags.isActive ("system-note"))
520     systemFlags.deactivate ("system-note");
521 }
522
523 bool TreeItem::hasEmptyNote()
524 {
525     return note.isEmpty();
526 }
527
528 VymNote TreeItem::getNote()  
529 {
530     return note;
531 }
532
533 QString TreeItem::getNoteASCII(const QString &indent, const int &width)
534 {
535     return note.getTextASCII(indent,width);
536 }
537
538 QString TreeItem::getNoteASCII()
539 {
540     return note.getTextASCII();
541 }
542
543 void TreeItem::activateStandardFlag (const QString &name)
544 {
545     standardFlags.activate (name);
546     model->emitDataChanged(this);
547 }
548
549 void TreeItem::deactivateStandardFlag (const QString &name)
550 {
551     standardFlags.deactivate (name);
552     model->emitDataChanged(this);
553 }
554
555 void TreeItem::deactivateAllStandardFlags ()
556 {
557     standardFlags.deactivateAll ();
558     model->emitDataChanged(this);
559 }
560
561 void TreeItem::toggleStandardFlag(const QString &name, FlagRow *master)
562 {
563     standardFlags.toggle (name,master);
564 }
565
566 void TreeItem::toggleSystemFlag(const QString &name, FlagRow *master)
567 {
568     systemFlags.toggle (name,master);
569     model->emitDataChanged(this);
570 }
571
572 bool TreeItem::hasActiveStandardFlag (const QString &name)
573 {
574     return standardFlags.isActive (name);
575 }
576
577 bool TreeItem::hasActiveSystemFlag (const QString &name)
578 {
579     return systemFlags.isActive (name);
580 }
581
582 QStringList TreeItem::activeStandardFlagNames ()
583 {
584     return standardFlags.activeFlagNames();
585 }
586
587 FlagRow* TreeItem::getStandardFlagRow()
588 {
589     return &standardFlags;
590 }
591
592 QStringList TreeItem::activeSystemFlagNames ()
593 {
594     return systemFlags.activeFlagNames();
595 }
596
597 bool TreeItem::canMoveDown()
598 {
599     switch (type)
600     {
601         case Undefined: return false;
602         case MapCenter: 
603         case Branch: 
604             if (!parentItem) return false;
605             if (parentItem->num (this) < parentItem->branchCount()-1)
606                 return true;
607             else
608                 return false;
609             break;  
610         case Image: return false;
611         default: return false;
612     }
613 }
614
615 bool TreeItem::canMoveUp()
616 {
617     switch (type)
618     {
619         case MapCenter: 
620         case Branch: 
621             if (!parentItem) return false;
622             if (parentItem->num (this) > 0)
623                 return true;
624             else
625                 return false;
626             break;  
627         default: return false;
628     }
629 }
630
631 uint TreeItem::getID()
632 {
633     return id;
634 }
635
636 void TreeItem::setUuid(const QString &id)
637 {
638     uuid=QUuid(id);
639 }
640
641 QUuid TreeItem::getUuid()
642 {
643     return uuid;
644 }
645
646 TreeItem* TreeItem::getChildNum(const int &n)
647 {
648     if (n>=0 && n<childItems.count() )
649         return childItems.at(n);
650     else
651         return NULL;
652 }
653
654 BranchItem* TreeItem::getFirstBranch()
655 {
656     if (branchCounter>0)
657         return getBranchNum (0);
658     else
659         return NULL;
660 }
661
662 BranchItem* TreeItem::getLastBranch()
663 {
664     if (branchCounter>0)
665         return getBranchNum (branchCounter-1);
666     else
667         return NULL;
668 }
669
670 ImageItem* TreeItem::getFirstImage()
671 {
672     if (imageCounter>0)
673         return getImageNum (imageCounter-1);
674     else
675         return NULL;
676 }
677
678 ImageItem* TreeItem::getLastImage()
679 {
680     if (imageCounter>0)
681         return getImageNum (imageCounter-1);
682     else
683         return NULL;
684 }
685
686 BranchItem* TreeItem::getNextBranch(BranchItem *currentBranch)
687 {
688     if (!currentBranch) return NULL;
689     int n=num (currentBranch)+1;
690     if (n<branchCounter)
691         return getBranchNum (branchOffset + n);
692     else
693         return NULL;
694 }
695
696
697 BranchItem* TreeItem::getBranchNum(const int &n)
698 {
699     if (n>=0 && n<branchCounter)
700         return (BranchItem*)getChildNum (branchOffset + n);
701     else
702         return NULL;
703 }
704
705 BranchObj* TreeItem::getBranchObjNum(const int &n)
706 {
707     if (n>=0 && n<branchCounter)
708     {
709         BranchItem *bi=getBranchNum(n);
710         if (bi)
711         {
712             BranchObj *bo=(BranchObj*)(bi->getLMO());
713             if (bo)
714                 return bo;
715             else
716                 qDebug()<<"TI::getBONum bo=NULL";
717         }
718     } 
719     return NULL;
720 }
721
722 ImageItem* TreeItem::getImageNum (const int &n)
723 {
724     if (n>=0 && n<imageCounter)
725         return (ImageItem*)getChildNum (imageOffset + n);
726     else
727         return NULL;
728 }
729
730 FloatImageObj* TreeItem::getImageObjNum (const int &n)  
731 {
732     if (imageCounter>0 )
733         return (FloatImageObj*)(getImageNum(n)->getLMO());
734     else
735         return NULL;
736 }
737
738 AttributeItem* TreeItem::getAttributeNum (const int &n)
739 {
740     if (n>=0 && n<attributeCounter)
741         return (AttributeItem*)getChildNum (attributeOffset + n);
742     else
743         return NULL;
744 }
745
746 XLinkItem* TreeItem::getXLinkItemNum (const int &n) 
747 {
748     if (n>=0 && n<xlinkCounter )
749         return (XLinkItem*)getChildNum (xlinkOffset +n);
750     else
751         return NULL;
752 }
753
754
755 XLinkObj* TreeItem::getXLinkObjNum (const int &n)   
756 {
757     if (xlinkCounter>0 )
758     {
759         XLinkItem *xli=getXLinkItemNum (n);
760         if (xli)
761         {
762             Link *l=xli->getLink();
763             if (l) return l->getXLinkObj();
764         }
765     }
766     return NULL;
767 }
768
769
770 void TreeItem::setHideTmp (HideTmpMode mode) 
771 {
772     if (type==Image || type==Branch || type==MapCenter)
773 //      ((ImageItem*)this)->updateVisibility();
774     {
775         //LinkableMapObj* lmo=((MapItem*)this)->getLMO();
776
777         if (mode==HideExport && (hideExport || hasHiddenExportParent() ) ) // FIXME-4  try to avoid calling hasScrolledParent repeatedly
778
779             // Hide stuff according to hideExport flag and parents
780             hidden=true;
781         else
782             // Do not hide, but still take care of scrolled status
783             hidden=false;
784         updateVisibility();
785         // And take care of my children
786         for (int i=0; i<branchCount(); ++i)
787             getBranchNum(i)->setHideTmp (mode); 
788     }
789 }
790
791 bool TreeItem::hasHiddenExportParent()
792 {
793     // Calls parents recursivly to
794     // find out, if we or parents are temp. hidden
795
796     if (hidden || hideExport) return true;
797
798     if (parentItem) 
799         return parentItem->hasHiddenExportParent();
800     else
801         return false;
802 }
803
804
805 void TreeItem::setHideInExport(bool b) 
806 {
807     if (type==MapCenter ||type==Branch || type==Image)
808     {
809         hideExport=b;
810         if (b)
811             systemFlags.activate("system-hideInExport");
812         else    
813             systemFlags.deactivate("system-hideInExport");
814     }
815 }   
816
817 bool TreeItem::hideInExport()
818 {
819     return hideExport;
820 }   
821
822 void TreeItem::updateVisibility()
823 {
824     // overloaded in derived objects
825 }   
826
827 bool TreeItem::isHidden()
828 {
829     return hidden;
830 }   
831
832 QString TreeItem::getGeneralAttr()  
833 {
834     QString s;
835     if (hideExport)
836          s+=attribut("hideInExport","true");
837     if (!url.isEmpty())
838         s+=attribut ("url",url);
839     if (!vymLink.isEmpty())
840         s+=attribut ("vymLink",convertToRel (model->getDestPath(),vymLink));    
841
842     if (target)
843         s+=attribut ("localTarget","true");
844     return s;   
845 }
846
847