AnalogSignal: Draw analog thresholds differently
[pulseview.git] / pv / views / trace / tracegroup.cpp
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2013 Joel Holdsworth <joel@airwebreathe.org.uk>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <extdef.h>
21
22 #include <algorithm>
23 #include <cassert>
24
25 #include <QMenu>
26 #include <QPainter>
27
28 #include "tracegroup.hpp"
29
30 using std::any_of;
31 using std::pair;
32 using std::shared_ptr;
33 using std::vector;
34
35 namespace pv {
36 namespace views {
37 namespace trace {
38
39 const int TraceGroup::Padding = 8;
40 const int TraceGroup::Width = 12;
41 const int TraceGroup::LineThickness = 5;
42 const QColor TraceGroup::LineColour(QColor(0x55, 0x57, 0x53));
43
44 TraceGroup::~TraceGroup()
45 {
46         owner_ = nullptr;
47         clear_child_items();
48 }
49
50 bool TraceGroup::enabled() const
51 {
52         return any_of(child_items().begin(), child_items().end(),
53                 [](const shared_ptr<ViewItem> &r) { return r->enabled(); });
54 }
55
56 pv::Session& TraceGroup::session()
57 {
58         assert(owner_);
59         return owner_->session();
60 }
61
62 const pv::Session& TraceGroup::session() const
63 {
64         assert(owner_);
65         return owner_->session();
66 }
67
68 View* TraceGroup::view()
69 {
70         assert(owner_);
71         return owner_->view();
72 }
73
74 const View* TraceGroup::view() const
75 {
76         assert(owner_);
77         return owner_->view();
78 }
79
80 pair<int, int> TraceGroup::v_extents() const
81 {
82         return TraceTreeItemOwner::v_extents();
83 }
84
85 void TraceGroup::paint_label(QPainter &p, const QRect &rect, bool hover)
86 {
87         const QRectF r = label_rect(rect).adjusted(
88                 LineThickness / 2, LineThickness / 2,
89                 -LineThickness / 2, -LineThickness / 2);
90
91         // Paint the label
92         const QPointF points[] = {
93                 r.topRight(),
94                 r.topLeft(),
95                 r.bottomLeft(),
96                 r.bottomRight()
97         };
98
99         if (selected()) {
100                 const QPen pen(highlight_pen());
101                 p.setPen(QPen(pen.brush(), pen.width() + LineThickness,
102                         Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin));
103                 p.setBrush(Qt::transparent);
104                 p.drawPolyline(points, countof(points));
105         }
106
107         p.setPen(QPen(QBrush(LineColour.darker()), LineThickness,
108                 Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin));
109         p.drawPolyline(points, countof(points));
110         p.setPen(QPen(QBrush(hover ? LineColour.lighter() : LineColour),
111                 LineThickness - 2, Qt::SolidLine, Qt::SquareCap,
112                 Qt::RoundJoin));
113         p.drawPolyline(points, countof(points));
114 }
115
116 QRectF TraceGroup::label_rect(const QRectF &rect) const
117 {
118         QRectF child_rect;
119         for (const shared_ptr<ViewItem> r : child_items())
120                 if (r && r->enabled())
121                         child_rect = child_rect.united(r->label_rect(rect));
122
123         return QRectF(child_rect.x() - Width - Padding, child_rect.y(),
124                 Width, child_rect.height());
125 }
126
127 bool TraceGroup::pt_in_label_rect(int left, int right, const QPoint &point)
128 {
129         (void)left;
130         (void)right;
131         (void)point;
132
133         return false;
134 }
135
136 QMenu* TraceGroup::create_context_menu(QWidget *parent)
137 {
138         QMenu *const menu = new QMenu(parent);
139
140         QAction *const ungroup = new QAction(tr("Ungroup"), this);
141         ungroup->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U));
142         connect(ungroup, SIGNAL(triggered()), this, SLOT(on_ungroup()));
143         menu->addAction(ungroup);
144
145         return menu;
146 }
147
148 pv::widgets::Popup* TraceGroup::create_popup(QWidget *parent)
149 {
150         (void)parent;
151         return nullptr;
152 }
153
154 int TraceGroup::owner_visual_v_offset() const
155 {
156         return owner_ ? visual_v_offset() + owner_->owner_visual_v_offset() : 0;
157 }
158
159 unsigned int TraceGroup::depth() const
160 {
161         return owner_ ? owner_->depth() + 1 : 0;
162 }
163
164 void TraceGroup::ungroup()
165 {
166         const vector<shared_ptr<TraceTreeItem>> items(trace_tree_child_items());
167         clear_child_items();
168
169         for (shared_ptr<TraceTreeItem> r : items)
170                 owner_->add_child_item(r);
171
172         owner_->remove_child_item(shared_from_this());
173 }
174
175 void TraceGroup::on_ungroup()
176 {
177         ungroup();
178 }
179
180 void TraceGroup::row_item_appearance_changed(bool label, bool content)
181 {
182         if (owner_)
183                 owner_->row_item_appearance_changed(label, content);
184 }
185
186 void TraceGroup::extents_changed(bool horz, bool vert)
187 {
188         if (owner_)
189                 owner_->extents_changed(horz, vert);
190 }
191
192 } // namespace trace
193 } // namespace views
194 } // namespace pv