1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2002-2011 Werner Schweer
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License version 2
9 //  as published by the Free Software Foundation and appearing in
10 //  the file LICENCE.GPL
11 //=============================================================================
12 
13 #include "box.h"
14 #include "textframe.h"
15 #include "text.h"
16 #include "score.h"
17 #include "barline.h"
18 #include "repeat.h"
19 #include "symbol.h"
20 #include "system.h"
21 #include "image.h"
22 #include "layoutbreak.h"
23 #include "fret.h"
24 #include "mscore.h"
25 #include "stafftext.h"
26 #include "icon.h"
27 #include "xml.h"
28 #include "measure.h"
29 #include "undo.h"
30 
31 namespace Ms {
32 
33 static const ElementStyle boxStyle {
34       { Sid::systemFrameDistance,                Pid::TOP_GAP                 },
35       { Sid::frameSystemDistance,                Pid::BOTTOM_GAP              },
36       };
37 
38 static const ElementStyle hBoxStyle {
39       };
40 
41 //---------------------------------------------------------
42 //   Box
43 //---------------------------------------------------------
44 
Box(Score * score)45 Box::Box(Score* score)
46    : MeasureBase(score)
47       {
48       }
49 
50 //---------------------------------------------------------
51 //   layout
52 //---------------------------------------------------------
53 
layout()54 void Box::layout()
55       {
56       MeasureBase::layout();
57       for (Element* e : el()) {
58             if (!e->isLayoutBreak())
59                   e->layout();
60             }
61       }
62 
63 //---------------------------------------------------------
64 //   computeMinWidth
65 //---------------------------------------------------------
66 
computeMinWidth()67 void HBox::computeMinWidth()
68       {
69       setWidth(point(boxWidth()) + topGap() + bottomGap());  // top/bottom is really left/right
70       }
71 
72 //---------------------------------------------------------
73 //   draw
74 //---------------------------------------------------------
75 
draw(QPainter * painter) const76 void Box::draw(QPainter* painter) const
77       {
78       if (score() && score()->printing())
79             return;
80       if (selected() || editMode || dropTarget() || score()->showFrames()) {
81             qreal w = spatium() * .15;
82             QPainterPathStroker stroker;
83             stroker.setWidth(w);
84             stroker.setJoinStyle(Qt::MiterJoin);
85             stroker.setCapStyle(Qt::SquareCap);
86 
87             QVector<qreal> dashes ;
88             dashes.append(1);
89             dashes.append(3);
90             stroker.setDashPattern(dashes);
91             QPainterPath path;
92             w *= .5;
93             path.addRect(bbox().adjusted(w, w, -w, -w));
94             QPainterPath stroke = stroker.createStroke(path);
95             painter->setBrush(Qt::NoBrush);
96             painter->fillPath(stroke, (selected() || editMode || dropTarget()) ? MScore::selectColor[0] : MScore::frameMarginColor);
97             }
98       }
99 
100 //---------------------------------------------------------
101 //   startEdit
102 //---------------------------------------------------------
103 
startEdit(EditData & ed)104 void Box::startEdit(EditData& ed)
105       {
106       Element::startEdit(ed);
107       editMode   = true;
108       }
109 
110 //---------------------------------------------------------
111 //   edit
112 //---------------------------------------------------------
113 
edit(EditData &)114 bool Box::edit(EditData&)
115       {
116       return false;
117       }
118 
119 //---------------------------------------------------------
120 //   startEditDrag
121 //---------------------------------------------------------
122 
startEditDrag(EditData & ed)123 void Box::startEditDrag(EditData& ed)
124       {
125       ElementEditData* eed = ed.getData(this);
126       if (isHBox())
127             eed->pushProperty(Pid::BOX_WIDTH);
128       else
129             eed->pushProperty(Pid::BOX_HEIGHT);
130       }
131 
132 //---------------------------------------------------------
133 //   editDrag
134 //---------------------------------------------------------
135 
editDrag(EditData & ed)136 void Box::editDrag(EditData& ed)
137       {
138       if (isVBox()) {
139             _boxHeight += Spatium(ed.delta.y() / spatium());
140             if (ed.vRaster) {
141                   qreal vRaster = 1.0 / MScore::vRaster();
142                   int n = lrint(_boxHeight.val() / vRaster);
143                   _boxHeight = Spatium(vRaster * n);
144                   }
145             bbox().setRect(0.0, 0.0, system()->width(), point(boxHeight()));
146             system()->setHeight(height());
147             triggerLayout();
148             }
149       else {
150             _boxWidth += Spatium(ed.delta.x() / spatium());
151             if (ed.hRaster) {
152                   qreal hRaster = 1.0 / MScore::hRaster();
153                   int n = lrint(_boxWidth.val() / hRaster);
154                   _boxWidth = Spatium(hRaster * n);
155                   }
156             triggerLayout();
157             }
158       layout();
159       }
160 
161 //---------------------------------------------------------
162 //   endEdit
163 //---------------------------------------------------------
164 
endEdit(EditData &)165 void Box::endEdit(EditData&)
166       {
167       editMode = false;
168       layout();
169       }
170 
171 //---------------------------------------------------------
172 //   gripsPositions
173 //---------------------------------------------------------
174 
gripsPositions(const EditData &) const175 std::vector<QPointF> HBox::gripsPositions(const EditData&) const
176       {
177       QRectF r(abbox());
178       return { QPointF(r.right(), r.top() + r.height() * .5) };
179       }
180 
gripsPositions(const EditData &) const181 std::vector<QPointF> VBox::gripsPositions(const EditData&) const
182       {
183       QRectF r(abbox());
184       return { QPointF(r.x() + r.width() * .5, r.bottom()) };
185       }
186 
187 //---------------------------------------------------------
188 //   write
189 //---------------------------------------------------------
190 
write(XmlWriter & xml) const191 void Box::write(XmlWriter& xml) const
192       {
193       xml.stag(this);
194       writeProperties(xml);
195       xml.etag();
196       }
197 
198 //---------------------------------------------------------
199 //   writeProperties
200 //---------------------------------------------------------
201 
writeProperties(XmlWriter & xml) const202 void Box::writeProperties(XmlWriter& xml) const
203       {
204       for (Pid id : {
205          Pid::BOX_HEIGHT, Pid::BOX_WIDTH, Pid::TOP_GAP, Pid::BOTTOM_GAP,
206          Pid::LEFT_MARGIN, Pid::RIGHT_MARGIN, Pid::TOP_MARGIN, Pid::BOTTOM_MARGIN, Pid::BOX_AUTOSIZE }) {
207             writeProperty(xml, id);
208             }
209       Element::writeProperties(xml);
210       for (const Element* e : el())
211             e->write(xml);
212       }
213 
214 //---------------------------------------------------------
215 //   read
216 //---------------------------------------------------------
217 
read(XmlReader & e)218 void Box::read(XmlReader& e)
219       {
220       _leftMargin      = 0.0;
221       _rightMargin     = 0.0;
222       _topMargin       = 0.0;
223       _bottomMargin    = 0.0;
224       _boxHeight       = Spatium(0);     // override default set in constructor
225       _boxWidth        = Spatium(0);
226       MeasureBase::read(e);
227       if (score()->mscVersion() < 302)
228             _isAutoSizeEnabled = false; // disable auto-size for older scores by default.
229       }
230 
231 //---------------------------------------------------------
232 //   readProperties
233 //---------------------------------------------------------
234 
readProperties(XmlReader & e)235 bool Box::readProperties(XmlReader& e)
236       {
237       const QStringRef& tag(e.name());
238       if (tag == "height")
239             _boxHeight = Spatium(e.readDouble());
240       else if (tag == "width")
241             _boxWidth = Spatium(e.readDouble());
242       else if (tag == "topGap") {
243             _topGap = e.readDouble();
244             if (score()->mscVersion() >= 206)
245                   _topGap *= score()->spatium();
246             setPropertyFlags(Pid::TOP_GAP, PropertyFlags::UNSTYLED);
247             }
248       else if (tag == "bottomGap") {
249             _bottomGap = e.readDouble();
250              if (score()->mscVersion() >= 206)
251                   _bottomGap *= score()->spatium();
252             setPropertyFlags(Pid::BOTTOM_GAP, PropertyFlags::UNSTYLED);
253             }
254       else if (tag == "leftMargin")
255             _leftMargin = e.readDouble();
256       else if (tag == "rightMargin")
257             _rightMargin = e.readDouble();
258       else if (tag == "topMargin")
259             _topMargin = e.readDouble();
260       else if (tag == "bottomMargin")
261             _bottomMargin = e.readDouble();
262       else if (tag == "boxAutoSize")
263             _isAutoSizeEnabled = e.readBool();
264       else if (tag == "Text") {
265             Text* t;
266             if (isTBox()) {
267                   t = toTBox(this)->text();
268                   t->read(e);
269                   }
270             else {
271                   t = new Text(score());
272                   t->read(e);
273                   if (t->empty())
274                         qDebug("read empty text");
275                   else
276                         add(t);
277                   }
278             }
279       else if (tag == "Symbol") {
280             Symbol* s = new Symbol(score());
281             s->read(e);
282             add(s);
283             }
284       else if (tag == "Image") {
285             if (MScore::noImages)
286                   e.skipCurrentElement();
287             else {
288                   Image* image = new Image(score());
289                   image->setTrack(e.track());
290                   image->read(e);
291                   add(image);
292                   }
293             }
294       else if (tag == "FretDiagram") {
295             FretDiagram* f = new FretDiagram(score());
296             f->read(e);
297             add(f);
298             }
299       else if (tag == "HBox") {
300             HBox* hb = new HBox(score());
301             hb->read(e);
302             add(hb);
303             }
304       else if (tag == "VBox") {
305             VBox* vb = new VBox(score());
306             vb->read(e);
307             add(vb);
308             }
309       else if (MeasureBase::readProperties(e))
310             ;
311       else
312             return false;
313       return true;
314       }
315 
316 //---------------------------------------------------------
317 //   add
318 ///   Add new Element \a el to Box
319 //---------------------------------------------------------
320 
add(Element * e)321 void Box::add(Element* e)
322       {
323       if (e->isText())
324             toText(e)->setLayoutToParentWidth(true);
325       MeasureBase::add(e);
326       }
327 
contentRect() const328 QRectF Box::contentRect() const
329       {
330       QRectF result;
331 
332       for (const Element* element : el())
333             result = result.united(element->bbox());
334 
335       return result;
336       }
337 
338 //---------------------------------------------------------
339 //   getProperty
340 //---------------------------------------------------------
341 
getProperty(Pid propertyId) const342 QVariant Box::getProperty(Pid propertyId) const
343       {
344       switch(propertyId) {
345             case Pid::BOX_HEIGHT:
346                   return _boxHeight;
347             case Pid::BOX_WIDTH:
348                   return _boxWidth;
349             case Pid::TOP_GAP:
350                   return _topGap;
351             case Pid::BOTTOM_GAP:
352                   return _bottomGap;
353             case Pid::LEFT_MARGIN:
354                   return _leftMargin;
355             case Pid::RIGHT_MARGIN:
356                   return _rightMargin;
357             case Pid::TOP_MARGIN:
358                   return _topMargin;
359             case Pid::BOTTOM_MARGIN:
360                   return _bottomMargin;
361             case Pid::BOX_AUTOSIZE:
362                   return (score()->mscVersion() >= 302) ? _isAutoSizeEnabled : false;
363             default:
364                   return MeasureBase::getProperty(propertyId);
365             }
366       }
367 
368 //---------------------------------------------------------
369 //   setProperty
370 //---------------------------------------------------------
371 
setProperty(Pid propertyId,const QVariant & v)372 bool Box::setProperty(Pid propertyId, const QVariant& v)
373       {
374       score()->addRefresh(canvasBoundingRect());
375       switch (propertyId) {
376             case Pid::BOX_HEIGHT:
377                   _boxHeight = v.value<Spatium>();
378                   break;
379             case Pid::BOX_WIDTH:
380                   _boxWidth = v.value<Spatium>();
381                   break;
382             case Pid::TOP_GAP:
383                   _topGap = v.toDouble();
384                   break;
385             case Pid::BOTTOM_GAP:
386                   _bottomGap = v.toDouble();
387                   break;
388             case Pid::LEFT_MARGIN:
389                   _leftMargin = v.toDouble();
390                   break;
391             case Pid::RIGHT_MARGIN:
392                   _rightMargin = v.toDouble();
393                   break;
394             case Pid::TOP_MARGIN:
395                   _topMargin = v.toDouble();
396                   break;
397             case Pid::BOTTOM_MARGIN:
398                   _bottomMargin = v.toDouble();
399                   break;
400             case Pid::BOX_AUTOSIZE:
401                   _isAutoSizeEnabled = v.toBool();
402                   break;
403             default:
404                   return MeasureBase::setProperty(propertyId, v);
405             }
406       triggerLayout();
407       return true;
408       }
409 
410 //---------------------------------------------------------
411 //   propertyDefault
412 //---------------------------------------------------------
413 
propertyDefault(Pid id) const414 QVariant Box::propertyDefault(Pid id) const
415       {
416       switch(id) {
417             case Pid::BOX_HEIGHT:
418             case Pid::BOX_WIDTH:
419                   return Spatium(0.0);
420 
421             case Pid::TOP_GAP:
422                   return isHBox() ? 0.0 : score()->styleP(Sid::systemFrameDistance);
423             case Pid::BOTTOM_GAP:
424                   return isHBox() ? 0.0 : score()->styleP(Sid::frameSystemDistance);
425 
426             case Pid::LEFT_MARGIN:
427             case Pid::RIGHT_MARGIN:
428             case Pid::TOP_MARGIN:
429             case Pid::BOTTOM_MARGIN:
430                   return 0.0;
431             case Pid::BOX_AUTOSIZE:
432                   return true;
433             default:
434                   return MeasureBase::propertyDefault(id);
435             }
436       }
437 
438 //---------------------------------------------------------
439 //   copyValues
440 //---------------------------------------------------------
441 
copyValues(Box * origin)442 void Box::copyValues(Box* origin)
443       {
444       _boxHeight    = origin->boxHeight();
445       _boxWidth     = origin->boxWidth();
446 
447       qreal factor  = magS() / origin->magS();
448       _bottomGap    = origin->bottomGap() * factor;
449       _topGap       = origin->topGap() * factor;
450       _bottomMargin = origin->bottomMargin() * factor;
451       _topMargin    = origin->topMargin() * factor;
452       _leftMargin   = origin->leftMargin() * factor;
453       _rightMargin  = origin->rightMargin() * factor;
454       }
455 
456 //---------------------------------------------------------
457 //   HBox
458 //---------------------------------------------------------
459 
HBox(Score * score)460 HBox::HBox(Score* score)
461    : Box(score)
462       {
463       initElementStyle(&hBoxStyle);
464       setBoxWidth(Spatium(5.0));
465       }
466 
467 //---------------------------------------------------------
468 //   layout
469 //---------------------------------------------------------
470 
layout()471 void HBox::layout()
472       {
473       if (parent() && parent()->isVBox()) {
474             VBox* vb = toVBox(parent());
475             qreal x = vb->leftMargin() * DPMM;
476             qreal y = vb->topMargin() * DPMM;
477             qreal w = point(boxWidth());
478             qreal h = vb->height() - (vb->topMargin() + vb->bottomMargin()) * DPMM;
479             setPos(x, y);
480             bbox().setRect(0.0, 0.0, w, h);
481             }
482       else if (system()) {
483             bbox().setRect(0.0, 0.0, point(boxWidth()), system()->height());
484             }
485       else {
486             bbox().setRect(0.0, 0.0, 50, 50);
487             }
488       Box::layout();
489       }
490 
491 //---------------------------------------------------------
492 //   layout2
493 //    height (bbox) is defined now
494 //---------------------------------------------------------
495 
layout2()496 void HBox::layout2()
497       {
498       Box::layout();
499       }
500 
501 //---------------------------------------------------------
502 //   acceptDrop
503 //---------------------------------------------------------
504 
acceptDrop(EditData & data) const505 bool Box::acceptDrop(EditData& data) const
506       {
507       if (data.dropElement->flag(ElementFlag::ON_STAFF))
508             return false;
509       if (MScore::debugMode)
510             qDebug("<%s>", data.dropElement->name());
511       ElementType t = data.dropElement->type();
512       switch (t) {
513             case ElementType::LAYOUT_BREAK:
514             case ElementType::TEXT:
515             case ElementType::STAFF_TEXT:
516             case ElementType::IMAGE:
517             case ElementType::SYMBOL:
518                   return true;
519             case ElementType::ICON:
520                   switch (toIcon(data.dropElement)->iconType()) {
521                         case IconType::VFRAME:
522                         case IconType::TFRAME:
523                         case IconType::FFRAME:
524                         case IconType::HFRAME:
525                         case IconType::MEASURE:
526                               return true;
527                         default:
528                               break;
529                         }
530                   break;
531             case ElementType::BAR_LINE:
532                   return isHBox();
533             default:
534                   break;
535             }
536       return false;
537       }
538 
539 //---------------------------------------------------------
540 //   drop
541 //---------------------------------------------------------
542 
drop(EditData & data)543 Element* Box::drop(EditData& data)
544       {
545       Element* e = data.dropElement;
546       if (e->flag(ElementFlag::ON_STAFF))
547             return 0;
548       if (MScore::debugMode)
549             qDebug("<%s>", e->name());
550       switch (e->type()) {
551             case ElementType::LAYOUT_BREAK:
552                   {
553                   LayoutBreak* lb = toLayoutBreak(e);
554                   if (pageBreak() || lineBreak()) {
555                         if (
556                            (lb->isPageBreak() && pageBreak())
557                            || (lb->isLineBreak() && lineBreak())
558                            || (lb->isSectionBreak() && sectionBreak())
559                            ) {
560                               //
561                               // if break already set
562                               //
563                               delete lb;
564                               break;
565                               }
566                         for (Element* elem : el()) {
567                               if (elem->type() == ElementType::LAYOUT_BREAK) {
568                                     score()->undoChangeElement(elem, e);
569                                     break;
570                                     }
571                               }
572                         break;
573                         }
574                   lb->setTrack(-1);       // these are system elements
575                   lb->setParent(this);
576                   score()->undoAddElement(lb);
577                   return lb;
578                   }
579 
580             case ElementType::STAFF_TEXT:
581                   {
582                   Text* text = new Text(score(), Tid::FRAME);
583                   text->setParent(this);
584                   text->setXmlText(toStaffText(e)->xmlText());
585                   score()->undoAddElement(text);
586                   delete e;
587                   return text;
588                   }
589 
590             case ElementType::ICON:
591                   switch (toIcon(e)->iconType()) {
592                         case IconType::VFRAME:
593                               score()->insertMeasure(ElementType::VBOX, this);
594                               break;
595                         case IconType::TFRAME:
596                               score()->insertMeasure(ElementType::TBOX, this);
597                               break;
598                         case IconType::FFRAME:
599                               score()->insertMeasure(ElementType::FBOX, this);
600                               break;
601                         case IconType::HFRAME:
602                               score()->insertMeasure(ElementType::HBOX, this);
603                               break;
604                         case IconType::MEASURE:
605                               score()->insertMeasure(ElementType::MEASURE, this);
606                               break;
607                         default:
608                               break;
609                         }
610                   break;
611 
612             case ElementType::TEXT:
613             case ElementType::IMAGE:
614             case ElementType::SYMBOL:
615                   e->setParent(this);
616                   score()->undoAddElement(e);
617                   return e;
618             default:
619                   return 0;
620             }
621       return 0;
622       }
623 
624 //---------------------------------------------------------
625 //   drag
626 //---------------------------------------------------------
627 
drag(EditData & data)628 QRectF HBox::drag(EditData& data)
629       {
630       QRectF r(canvasBoundingRect());
631       qreal diff = data.evtDelta.x();
632       qreal x1   = offset().x() + diff;
633       if (parent()->type() == ElementType::VBOX) {
634             VBox* vb = toVBox(parent());
635             qreal x2 = parent()->width() - width() - (vb->leftMargin() + vb->rightMargin()) * DPMM;
636             if (x1 < 0.0)
637                   x1 = 0.0;
638             else if (x1 > x2)
639                   x1 = x2;
640             }
641       setOffset(QPointF(x1, 0.0));
642 //      setStartDragPosition(data.delta);
643       return canvasBoundingRect() | r;
644       }
645 
646 //---------------------------------------------------------
647 //   endEditDrag
648 //---------------------------------------------------------
649 
endEditDrag(EditData &)650 void HBox::endEditDrag(EditData&)
651       {
652       triggerLayout();
653       score()->update();
654       }
655 
656 //---------------------------------------------------------
657 //   isMovable
658 //---------------------------------------------------------
659 
isMovable() const660 bool HBox::isMovable() const
661       {
662       return parent() && (parent()->isHBox() || parent()->isVBox());
663       }
664 
665 //---------------------------------------------------------
666 //   writeProperties
667 //---------------------------------------------------------
668 
writeProperties(XmlWriter & xml) const669 void HBox::writeProperties(XmlWriter& xml) const
670       {
671       writeProperty(xml, Pid::CREATE_SYSTEM_HEADER);
672       Box::writeProperties(xml);
673       }
674 
675 //---------------------------------------------------------
676 //   readProperties
677 //---------------------------------------------------------
678 
readProperties(XmlReader & e)679 bool HBox::readProperties(XmlReader& e)
680       {
681       const QStringRef& tag(e.name());
682       if (readProperty(tag, e, Pid::CREATE_SYSTEM_HEADER))
683             ;
684       else if (Box::readProperties(e))
685             ;
686       else
687             return false;
688       return true;
689       }
690 
691 //---------------------------------------------------------
692 //   getProperty
693 //---------------------------------------------------------
694 
getProperty(Pid propertyId) const695 QVariant HBox::getProperty(Pid propertyId) const
696       {
697       switch (propertyId) {
698             case Pid::CREATE_SYSTEM_HEADER:
699                   return createSystemHeader();
700             default:
701                   return Box::getProperty(propertyId);
702             }
703       }
704 
705 //---------------------------------------------------------
706 //   setProperty
707 //---------------------------------------------------------
708 
setProperty(Pid propertyId,const QVariant & v)709 bool HBox::setProperty(Pid propertyId, const QVariant& v)
710       {
711       switch (propertyId) {
712             case Pid::CREATE_SYSTEM_HEADER:
713                   setCreateSystemHeader(v.toBool());
714                   triggerLayout();
715                   break;
716             default:
717                   return Box::setProperty(propertyId, v);
718             }
719       return true;
720       }
721 
722 //---------------------------------------------------------
723 //   propertyDefault
724 //---------------------------------------------------------
725 
propertyDefault(Pid id) const726 QVariant HBox::propertyDefault(Pid id) const
727       {
728       switch(id) {
729             case Pid::CREATE_SYSTEM_HEADER:
730                   return true;
731             default:
732                   return Box::propertyDefault(id);
733             }
734       }
735 
736 //---------------------------------------------------------
737 //   VBox
738 //---------------------------------------------------------
739 
VBox(Score * score)740 VBox::VBox(Score* score)
741    : Box(score)
742       {
743       initElementStyle(&boxStyle);
744       setBoxHeight(Spatium(10.0));
745       setLineBreak(true);
746       }
747 
minHeight() const748 qreal VBox::minHeight() const
749       {
750       return point(Spatium(10));
751       }
752 
maxHeight() const753 qreal VBox::maxHeight() const
754       {
755       return point(Spatium(30));
756       }
757 
getProperty(Pid propertyId) const758 QVariant VBox::getProperty(Pid propertyId) const
759       {
760       switch (propertyId) {
761             case Pid::BOX_AUTOSIZE:
762                   return isAutoSizeEnabled();
763             default:
764                   return Box::getProperty(propertyId);
765       }
766       }
767 
768 //---------------------------------------------------------
769 //   layout
770 //---------------------------------------------------------
771 
layout()772 void VBox::layout()
773       {
774       setPos(QPointF());
775 
776       if (system())
777             bbox().setRect(0.0, 0.0, system()->width(), point(boxHeight()));
778       else
779             bbox().setRect(0.0, 0.0, 50, 50);
780 
781       for (Element* e : el()) {
782             if (!e->isLayoutBreak())
783                   e->layout();
784             }
785 
786       if (getProperty(Pid::BOX_AUTOSIZE).toBool()) {
787             qreal contentHeight = contentRect().height();
788 
789             if (contentHeight < minHeight())
790                   contentHeight = minHeight();
791 
792             setHeight(contentHeight);
793             }
794 
795       MeasureBase::layout();
796       }
797 
798 //---------------------------------------------------------
799 //   layout
800 //---------------------------------------------------------
801 
layout()802 void FBox::layout()
803       {
804 //      setPos(QPointF());      // !?
805       bbox().setRect(0.0, 0.0, system()->width(), point(boxHeight()));
806       Box::layout();
807       }
808 
809 //---------------------------------------------------------
810 //   add
811 ///   Add new Element \a e to fret diagram box
812 //---------------------------------------------------------
813 
add(Element * e)814 void FBox::add(Element* e)
815       {
816       e->setParent(this);
817       if (e->isFretDiagram()) {
818 //            FretDiagram* fd = toFretDiagram(e);
819 //            fd->setFlag(ElementFlag::MOVABLE, false);
820             }
821       else {
822             qDebug("FBox::add: element not allowed");
823             return;
824             }
825       el().push_back(e);
826       }
827 
828 //---------------------------------------------------------
829 //   accessibleExtraInfo
830 //---------------------------------------------------------
831 
accessibleExtraInfo() const832 QString Box::accessibleExtraInfo() const
833       {
834       QString rez = "";
835       for (Element* e : el())
836             rez += " " + e->screenReaderInfo();
837       return rez;
838       }
839 
840 //---------------------------------------------------------
841 //   accessibleExtraInfo
842 //---------------------------------------------------------
843 
accessibleExtraInfo() const844 QString TBox::accessibleExtraInfo() const
845       {
846       QString rez = _text->screenReaderInfo();
847       return rez;
848       }
849 
850 }
851 
852