1 #include <QtDebug>
2
3 #include "skin/legacy/skincontext.h"
4 #include "waveform/renderers/waveformsignalcolors.h"
5 #include "widget/wskincolor.h"
6
7 #include "waveformmark.h"
8
9 namespace {
decodeAlignmentFlags(const QString & alignString,Qt::Alignment defaultFlags)10 Qt::Alignment decodeAlignmentFlags(const QString& alignString, Qt::Alignment defaultFlags) {
11 QStringList stringFlags = alignString.toLower()
12 .split('|',
13 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
14 Qt::SkipEmptyParts);
15 #else
16 QString::SkipEmptyParts);
17 #endif
18
19 Qt::Alignment hflags;
20 Qt::Alignment vflags;
21
22 for (const auto& stringFlag : stringFlags) {
23 if (stringFlag == "center") {
24 hflags |= Qt::AlignHCenter;
25 vflags |= Qt::AlignVCenter;
26 } else if (stringFlag == "left") {
27 hflags |= Qt::AlignLeft;
28 } else if (stringFlag == "hcenter") {
29 hflags |= Qt::AlignHCenter;
30 } else if (stringFlag == "right") {
31 hflags |= Qt::AlignRight;
32 } else if (stringFlag == "top") {
33 vflags |= Qt::AlignTop;
34 } else if (stringFlag == "vcenter") {
35 vflags |= Qt::AlignVCenter;
36 } else if (stringFlag == "bottom") {
37 vflags |= Qt::AlignBottom;
38 }
39 }
40
41 if (hflags != Qt::AlignLeft && hflags != Qt::AlignHCenter && hflags != Qt::AlignRight) {
42 hflags = defaultFlags & Qt::AlignHorizontal_Mask;
43 }
44
45 if (vflags != Qt::AlignTop && vflags != Qt::AlignVCenter && vflags != Qt::AlignBottom) {
46 vflags = defaultFlags & Qt::AlignVertical_Mask;
47 }
48
49 return hflags | vflags;
50 }
51 } // anonymous namespace
52
WaveformMark(const QString & group,const QDomNode & node,const SkinContext & context,const WaveformSignalColors & signalColors,int hotCue)53 WaveformMark::WaveformMark(const QString& group,
54 const QDomNode& node,
55 const SkinContext& context,
56 const WaveformSignalColors& signalColors,
57 int hotCue)
58 : m_iHotCue(hotCue) {
59 QString control;
60 if (hotCue != Cue::kNoHotCue) {
61 control = "hotcue_" + QString::number(hotCue + 1) + "_position";
62 } else {
63 control = context.selectString(node, "Control");
64 }
65 if (!control.isEmpty()) {
66 m_pPointCos = std::make_unique<ControlProxy>(group, control);
67 }
68
69 QString visibilityControl = context.selectString(node, "VisibilityControl");
70 if (!visibilityControl.isEmpty()) {
71 ConfigKey key = ConfigKey::parseCommaSeparated(visibilityControl);
72 m_pVisibleCos = std::make_unique<ControlProxy>(key);
73 }
74
75 QColor color(context.selectString(node, "Color"));
76 if (!color.isValid()) {
77 // As a fallback, grab the color from the parent's AxesColor
78 color = signalColors.getAxesColor();
79 qDebug() << "Didn't get mark <Color>, using parent's <AxesColor>:" << color;
80 } else {
81 color = WSkinColor::getCorrectColor(color);
82 }
83 int dimBrightThreshold = signalColors.getDimBrightThreshold();
84 setBaseColor(color, dimBrightThreshold);
85
86 m_textColor = context.selectString(node, "TextColor");
87 if (!m_textColor.isValid()) {
88 // Read the text color, otherwise use the parent's BgColor.
89 m_textColor = signalColors.getBgColor();
90 qDebug() << "Didn't get mark <TextColor>, using parent's <BgColor>:" << m_textColor;
91 }
92
93 QString markAlign = context.selectString(node, "Align");
94 m_align = decodeAlignmentFlags(markAlign, Qt::AlignBottom | Qt::AlignHCenter);
95
96 // Hotcue text is set by the cue's label in the database, not by the skin.
97 if (hotCue == Cue::kNoHotCue) {
98 m_text = context.selectString(node, "Text");
99 }
100
101 m_pixmapPath = context.selectString(node, "Pixmap");
102 if (!m_pixmapPath.isEmpty()) {
103 m_pixmapPath = context.makeSkinPath(m_pixmapPath);
104 }
105 }
106
setBaseColor(QColor baseColor,int dimBrightThreshold)107 void WaveformMark::setBaseColor(QColor baseColor, int dimBrightThreshold) {
108 m_image = QImage();
109 m_fillColor = baseColor;
110 m_borderColor = Color::chooseContrastColor(baseColor, dimBrightThreshold);
111 m_labelColor = Color::chooseColorByBrightness(baseColor,
112 QColor(255, 255, 255, 255),
113 QColor(0, 0, 0, 255),
114 dimBrightThreshold);
115 };
116
contains(QPoint point,Qt::Orientation orientation) const117 bool WaveformMark::contains(QPoint point, Qt::Orientation orientation) const {
118 // Without some padding, the user would only have a single pixel width that
119 // would count as hovering over the WaveformMark.
120 float lineHoverPadding = 5.0;
121 int position;
122 if (orientation == Qt::Horizontal) {
123 position = point.x();
124 } else {
125 position = point.y();
126 }
127 bool lineHovered = m_linePosition >= position - lineHoverPadding &&
128 m_linePosition <= position + lineHoverPadding;
129
130 return m_label.area().contains(point) || lineHovered;
131 }
132