4 #include <QCoreApplication>
6 #include <QDomDocument>
7 #include <QFontMetrics>
23 m_Justification(Qt::AlignLeft | Qt::AlignTop), m_OrigDisplayRect(),
24 m_AltDisplayRect(), m_Canvas(),
25 m_drawRect(), m_cursorPos(-1, -1),
26 m_Message(
""), m_CutMessage(
""),
27 m_DefaultMessage(
""), m_TemplateText(
""),
28 m_ShrinkNarrow(
true), m_Cutdown(Qt::ElideRight),
29 m_MultiLine(
false), m_Ascent(0),
30 m_Descent(0), m_leftBearing(0),
31 m_rightBearing(0), m_Leading(1),
32 m_extraLeading(0), m_lineHeight(0),
35 m_startColor(), m_endColor(),
36 m_numSteps(0), m_curStep(0),
37 curR(0.0), curG(0.0), curB(0.0),
38 incR(0.0), incG(0.0), incB(0.0),
39 m_scrollStartDelay(ScrollBounceDelay),
40 m_scrollReturnDelay(ScrollBounceDelay), m_scrollPause(0),
43 m_scrollBounce(
false), m_scrollOffset(0),
44 m_scrollPos(0), m_scrollPosWhole(0),
45 m_scrollDirection(ScrollNone), m_scrolling(
false),
46 m_textCase(CaseNormal)
48 #if 0 // Not currently used
58 QRect displayRect, QRect altDisplayRect,
61 m_Justification(Qt::AlignLeft | Qt::AlignTop),
62 m_OrigDisplayRect(displayRect), m_AltDisplayRect(altDisplayRect),
63 m_Canvas(0, 0, displayRect.
width(), displayRect.height()),
64 m_drawRect(displayRect), m_cursorPos(-1, -1),
65 m_Message(text.trimmed()),
66 m_CutMessage(
""), m_DefaultMessage(text),
68 m_colorCycling(
false), m_startColor(),
69 m_endColor(), m_numSteps(0),
71 curR(0.0), curG(0.0), curB(0.0),
72 incR(0.0), incG(0.0), incB(0.0)
74 #if 0 // Not currently used
109 QVector<QTextLayout *>::iterator Ilayout;
130 QString newtext = text;
136 if (newtext.isEmpty())
157 if (map.contains(objectName()))
161 if (newText.isEmpty())
164 QRegExp regexp(
"%(([^\\|%]+)?\\||\\|(.))?(\\w+)(\\|(.+))?%");
165 regexp.setMinimal(
true);
167 if (!newText.isEmpty() && newText.contains(regexp))
171 QString translatedTemplate = qApp->translate(
"ThemeUI",
174 QCoreApplication::UnicodeUTF8);
176 QString tempString = translatedTemplate;
178 while ((pos = regexp.indexIn(translatedTemplate, pos)) != -1)
180 QString key = regexp.cap(4).toLower().trimmed();
183 if (!map.value(key).isEmpty())
185 replacement = QString(
"%1%2%3%4")
192 tempString.replace(regexp.cap(0), replacement);
193 pos += regexp.matchedLength();
196 newText = tempString;
199 newText = map.value(objectName());
252 #if 0 // Not currently used
272 int h = just & Qt::AlignHorizontal_Mask;
273 int v = just & Qt::AlignVertical_Mask;
301 LOG(VB_GENERAL, LOG_ERR, QString(
"'%1' (%2): <scroll> and "
302 "<cutdown> are not combinable.")
350 QPoint newpoint(x, y);
361 if (x == 0 && y == 0)
370 int alphaMod, QRect clipRect)
377 drawrect.translate(xoffset, yoffset);
384 drawrect.setY(drawrect.y() -
m_Ascent);
385 canvas.moveTop(canvas.y() +
m_Ascent);
386 canvas.setHeight(canvas.height() +
m_Ascent);
390 drawrect.setHeight(drawrect.height() +
m_Descent);
391 canvas.setHeight(canvas.height() +
m_Descent);
408 QTextLayout::FormatRange range;
411 int outlineSize, outlineAlpha;
415 outlineColor.setAlpha(outlineAlpha);
417 MythPoint outline(outlineSize, outlineSize);
421 pen.setBrush(outlineColor);
422 pen.setWidth(outline.x());
426 range.format.setTextOutline(pen);
427 formats.push_back(range);
429 drawrect.setX(drawrect.x() - outline.x());
430 drawrect.setWidth(drawrect.width() + outline.x());
431 drawrect.setY(drawrect.y() - outline.y());
432 drawrect.setHeight(drawrect.height() + outline.y());
436 canvas.moveLeft(canvas.x() + outline.x());
437 canvas.setWidth(canvas.width() + outline.x());
438 canvas.moveTop(canvas.y() + outline.y());
439 canvas.setHeight(canvas.height() + outline.y());
453 drawrect.setWidth(drawrect.width() + shadow.x());
454 drawrect.setHeight(drawrect.height() + shadow.y());
456 canvas.setWidth(canvas.width() + shadow.x());
457 canvas.setHeight(canvas.height() + shadow.y());
465 bool & overflow, qreal
width, qreal & height,
466 bool force, qreal & last_line_width,
467 QRectF & min_rect,
int & num_lines)
471 layout->setText(paragraph);
472 layout->beginLayout();
476 QTextLine line = layout->createLine();
481 line.setLineWidth(width);
483 if (!
m_MultiLine && line.textLength() < paragraph.size())
485 if (!force &&
m_Cutdown != Qt::ElideNone)
488 paragraph = fm.elidedText(paragraph,
m_Cutdown,
489 width - fm.averageCharWidth());
493 line.setLineWidth(INT_MAX);
497 line.setPosition(QPointF(0, height));
501 if (height >
m_Area.height())
503 LOG(VB_GUI, num_lines ? LOG_DEBUG : LOG_NOTICE,
504 QString(
"'%1' (%2): height overflow. line height %3 "
505 "paragraph height %4, area height %5")
517 QString cut_line = fm.elidedText
518 (paragraph.mid(last_line),
520 width - fm.averageCharWidth());
521 paragraph = paragraph.left(last_line) + cut_line;
523 min_rect |= line.naturalTextRect();
534 last_line = line.textStart();
535 last_line_width = line.naturalTextWidth();
536 min_rect |= line.naturalTextRect();
539 if (
final && line.textLength())
555 bearing = fm.rightBearing
567 const QTextOption & textoption,
568 qreal
width, qreal & height,
569 QRectF & min_rect, qreal & last_line_width,
570 int & num_lines,
bool final)
572 QStringList::const_iterator Ipara;
573 QVector<QTextLayout *>::iterator Ilayout;
576 bool overflow =
false;
582 (*Ilayout)->clearLayout();
584 for (Ipara = paragraphs.begin(), idx = 0;
585 Ipara != paragraphs.end(); ++Ipara, ++idx)
588 layout->setTextOption(textoption);
592 saved_height = height;
593 saved_rect = min_rect;
594 if (!
Layout(para, layout,
final, overflow, width, height,
false,
595 last_line_width, min_rect, num_lines))
598 min_rect = saved_rect;
599 height = saved_height;
600 Layout(para, layout,
final, overflow, width, height,
true,
601 last_line_width, min_rect, num_lines);
611 const QTextOption & textoption, qreal &
width)
613 qreal height, last_line_width, lines;
614 int best_width, too_narrow, last_width = -1;
622 width =
m_Area.width() / 2.0;
623 best_width =
m_Area.width();
626 for (attempt = 0; attempt < 10; ++attempt)
634 min_rect, last_line_width, num_lines,
false);
641 if (too_narrow < width)
645 lines =
static_cast<int>
646 ((height -
m_drawRect.height()) / line_height);
647 lines -= (1.0 - last_line_width /
width);
648 width += (lines *
width) /
651 if (width > best_width || static_cast<int>(width) == last_width)
660 if (best_width > width)
663 lines =
static_cast<int>
664 (
m_Area.height() - height) / line_height;
669 (lines /
static_cast<qreal
>(num_lines - 1 + lines));
670 if (static_cast<int>(width) == last_width)
676 else if (last_line_width <
m_Area.width())
679 width -= (1.0 - last_line_width /
width) / num_lines;
680 if (width > last_line_width)
681 width = last_line_width;
682 if (static_cast<int>(width) == last_width)
688 if (width < too_narrow)
694 LOG(VB_GENERAL, LOG_ERR, QString(
"'%1' (%2) GetNarrowWidth: Gave up "
695 "while trying to find optimal width "
727 QCoreApplication::UnicodeUTF8,
733 NULL, QCoreApplication::UnicodeUTF8);
748 QVector<QTextLayout *>::iterator Ilayout =
m_Layouts.begin();
750 (*Ilayout)->setTextOption(textoption);
751 (*Ilayout)->setText(
"");
752 (*Ilayout)->beginLayout();
753 line = (*Ilayout)->createLine();
754 line.setLineWidth(
m_Area.width());
755 line.setPosition(QPointF(0, 0));
756 (*Ilayout)->endLayout();
760 for (++Ilayout ; Ilayout !=
m_Layouts.end(); ++Ilayout)
761 (*Ilayout)->clearLayout();
767 QStringList templist;
768 QStringList::iterator it;
782 for (it = templist.begin(); it != templist.end(); ++it)
783 (*it).replace(0, 1, (*it).left(1).toUpper());
791 for (it = templist.begin(); it != templist.end(); ++it)
792 (*it).replace(0, 1, (*it).left(1).toUpper());
801 textoption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
804 qreal last_line_width;
806 QString::KeepEmptyParts);
808 for (idx =
m_Layouts.size(); idx < paragraphs.size(); ++idx)
820 min_rect, last_line_width, num_lines,
true);
833 m_Ascent = -(actual.y() + fm.ascent());
834 m_Descent = actual.height() - fm.height();
865 min_rect.moveCenter(
m_Area.center());
877 fm.averageCharWidth()) / 2)));
883 min_rect.moveLeft(
m_Area.x());
893 fm.averageCharWidth()) / 2)));
910 ((
m_MinSize.y() - min_rect.height()) / 2));
916 min_rect.moveTop(
m_Area.y());
925 ((
m_MinSize.y() - min_rect.height()) / 2));
947 int layoutStartPos = 0;
954 for (
int y = 0;
y < layout->lineCount();
y++)
960 QTextLine line = layout->lineAt(
y);
963 + (line.lineNumber() == layout->lineCount() - 1 ? 1 : 0))
965 lineNo = lineCount - 1;
970 currPos += line.textLength();
974 layoutStartPos = currPos;
978 if (lineNo == 0 && lines < 0)
982 if (lineNo == lineCount - 1 && lines > 0)
987 LOG(VB_GENERAL, LOG_ERR,
988 QString(
"'%1' (%2) MoveCursor offset %3 not found in ANY paragraph!")
993 int newLine = lineNo + lines;
998 if (newLine >= lineCount)
999 newLine = lineCount - 1;
1009 for (
int y = 0;
y < layout->lineCount();
y++)
1012 QTextLine line = layout->lineAt(
y);
1014 if (lineNo == newLine)
1015 return layoutStartPos + line.xToCursor(xPos);
1018 layoutStartPos += layout->text().length() + 1;
1034 QVector<QTextLayout *>::const_iterator Ipara;
1036 int x,
y, mid, line_height;
1037 int offset = text_offset;
1041 QTextLine line = (*Ipara)->lineForTextPosition(offset);
1045 pos.setX(line.cursorToX(&offset));
1049 offset -= ((*Ipara)->text().size() + 1);
1053 LOG(VB_GENERAL, LOG_ERR,
1054 QString(
"'%1' (%2) CursorPosition offset %3 not found in "
1063 else if (pos.x() >=
m_Canvas.width() - mid)
1066 pos.
setX(pos.x() -
x);
1071 pos.setX(pos.x() -
x);
1075 mid =
m_Area.height() / 2;
1076 mid -= (mid % line_height);
1083 int visible_lines = ((
m_Area.height() / line_height) * line_height);
1084 y =
m_Canvas.height() - visible_lines;
1085 pos.
setY(visible_lines - (
m_Canvas.height() - pos.y()));
1090 pos.setY(mid + m_Leading);
1129 QColor newColor = QColor((
int)
curR, (
int)
curG, (
int)
curB);
1156 m_scrollPosWhole = whole;
1275 curR = startColor.red();
1276 curG = startColor.green();
1277 curB = startColor.blue();
1297 const QString &
filename, QDomElement &element,
bool showWarnings)
1299 if (element.tagName() ==
"area")
1306 else if (element.tagName() ==
"font")
1321 QString state = element.attribute(
"state",
"");
1323 if (!state.isEmpty())
1334 else if (element.tagName() ==
"extraleading")
1338 else if (element.tagName() ==
"value")
1340 if (element.attribute(
"lang",
"").isEmpty())
1344 QCoreApplication::UnicodeUTF8);
1346 else if (element.attribute(
"lang",
"").toLower() ==
1351 else if (element.attribute(
"lang",
"").toLower() ==
1360 else if (element.tagName() ==
"template")
1364 else if (element.tagName() ==
"cutdown")
1370 else if (mode ==
"middle")
1372 else if (mode ==
"right" ||
parseBool(element))
1377 else if (element.tagName() ==
"multiline")
1381 else if (element.tagName() ==
"align")
1386 else if (element.tagName() ==
"colorcycle")
1390 QString
tmp = element.attribute(
"start");
1395 tmp = element.attribute(
"end");
1400 tmp = element.attribute(
"steps");
1413 else if (element.tagName() ==
"scroll")
1417 QString
tmp = element.attribute(
"direction");
1421 tmp = tmp.toLower();
1425 else if (tmp ==
"right")
1427 else if (tmp ==
"up")
1429 else if (tmp ==
"down")
1431 else if (tmp ==
"horizontal")
1433 else if (tmp ==
"vertical")
1438 LOG(VB_GENERAL, LOG_ERR,
1439 QString(
"'%1' (%2) Invalid scroll attribute")
1444 tmp = element.attribute(
"startdelay");
1447 float seconds = tmp.toFloat();
1451 tmp = element.attribute(
"returndelay");
1454 float seconds = tmp.toFloat();
1458 tmp = element.attribute(
"rate");
1461 #if 0 // scroll rate as a percentage of 70Hz
1462 float percent = tmp.toFloat() / 100.0;
1465 #else // scroll rate as pixels per second
1466 int pixels = tmp.toInt();
1471 tmp = element.attribute(
"returnrate");
1474 #if 0 // scroll rate as a percentage of 70Hz
1475 float percent = tmp.toFloat() / 100.0;
1478 #else // scroll rate as pixels per second
1479 int pixels = tmp.toInt();
1490 else if (element.tagName() ==
"case")
1494 if (stringCase ==
"lower")
1496 else if (stringCase ==
"upper")
1498 else if (stringCase ==
"capitalisefirst")
1500 else if (stringCase ==
"capitaliseall")
1507 if (element.tagName() ==
"minsize" && element.hasAttribute(
"shrink"))
1510 .toLower() !=
"short");
1525 LOG(VB_GENERAL, LOG_ERR,
1526 QString(
"'%1' (%2) ERROR, bad parsing '%3' (%4)")
1551 QMutableMapIterator<QString, MythFontProperties> it(text->
m_FontStates);
1553 while (it.hasNext())
1597 LOG(VB_GENERAL, LOG_ERR,
1598 QString(
"'%1' (%2): <scroll> and <cutdown> are not combinable.")