]> sigrok.org Git - pulseview.git/blame - pv/view/header.cpp
Paint decoder traces
[pulseview.git] / pv / view / header.cpp
CommitLineData
1d8dca91 1/*
b3f22de0 2 * This file is part of the PulseView project.
1d8dca91
JH
3 *
4 * Copyright (C) 2012 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, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "header.h"
22#include "view.h"
23
8d634081 24#include "signal.h"
51e77110 25#include "../sigsession.h"
1d8dca91
JH
26
27#include <assert.h>
28
29#include <boost/foreach.hpp>
30
e3374498 31#include <QApplication>
b3b57abc 32#include <QColorDialog>
49f8ff3f
JH
33#include <QInputDialog>
34#include <QMenu>
a29bb7fb 35#include <QMouseEvent>
1d8dca91
JH
36#include <QPainter>
37#include <QRect>
38
39using namespace boost;
40using namespace std;
41
42namespace pv {
43namespace view {
44
45Header::Header(View &parent) :
c23b29d6 46 MarginWidget(parent),
b3b57abc
JH
47 _action_set_name(new QAction(tr("Set &Name..."), this)),
48 _action_set_colour(new QAction(tr("Set &Colour..."), this))
1d8dca91 49{
a29bb7fb 50 setMouseTracking(true);
49f8ff3f
JH
51
52 connect(_action_set_name, SIGNAL(triggered()),
53 this, SLOT(on_action_set_name_triggered()));
b3b57abc
JH
54 connect(_action_set_colour, SIGNAL(triggered()),
55 this, SLOT(on_action_set_colour_triggered()));
07204819 56
9e40e83d
JH
57 connect(&_view.session(), SIGNAL(signals_changed()),
58 this, SLOT(on_signals_changed()));
59
07204819
JH
60 connect(&_view, SIGNAL(signals_moved()),
61 this, SLOT(on_signals_moved()));
1d8dca91
JH
62}
63
38eeddea 64shared_ptr<Trace> Header::get_mouse_over_trace(const QPoint &pt)
e3374498
JH
65{
66 const int w = width();
38eeddea 67 const vector< shared_ptr<Trace> > traces(_view.get_traces());
e3374498
JH
68
69 const int v_offset = _view.v_offset();
38eeddea 70 BOOST_FOREACH(const shared_ptr<Trace> t, traces)
e3374498 71 {
38eeddea 72 assert(t);
e3374498 73
38eeddea 74 if (t->pt_in_label_rect(t->get_v_offset() - v_offset,
2658961b 75 0, w, pt))
38eeddea 76 return t;
e3374498
JH
77 }
78
38eeddea 79 return shared_ptr<Trace>();
e3374498
JH
80}
81
a2ae0205
JH
82void Header::clear_selection()
83{
38eeddea
JH
84 const vector< shared_ptr<Trace> > traces(_view.get_traces());
85 BOOST_FOREACH(const shared_ptr<Trace> t, traces) {
86 assert(t);
87 t->select(false);
a2ae0205
JH
88 }
89
90 update();
91}
92
e314eca4 93void Header::paintEvent(QPaintEvent*)
1d8dca91
JH
94{
95 const int w = width();
38eeddea 96 const vector< shared_ptr<Trace> > traces(_view.get_traces());
1d8dca91
JH
97
98 QPainter painter(this);
99 painter.setRenderHint(QPainter::Antialiasing);
100
2e575351 101 const int v_offset = _view.v_offset();
38eeddea
JH
102 const bool dragging = !_drag_traces.empty();
103 BOOST_FOREACH(const shared_ptr<Trace> t, traces)
1d8dca91 104 {
38eeddea 105 assert(t);
1d8dca91 106
38eeddea
JH
107 const int y = t->get_v_offset() - v_offset;
108 const bool highlight = !dragging && t->pt_in_label_rect(
2658961b 109 y, 0, w, _mouse_point);
38eeddea 110 t->paint_label(painter, y, w, highlight);
1d8dca91
JH
111 }
112
113 painter.end();
114}
115
e3374498
JH
116void Header::mousePressEvent(QMouseEvent *event)
117{
118 assert(event);
119
38eeddea 120 const vector< shared_ptr<Trace> > traces(_view.get_traces());
e3374498 121
333d5bbc 122 if (event->button() & Qt::LeftButton) {
54401bbb
JH
123 _mouse_down_point = event->pos();
124
da2bebfb 125 // Save the offsets of any signals which will be dragged
38eeddea
JH
126 BOOST_FOREACH(const shared_ptr<Trace> t, traces)
127 if (t->selected())
128 _drag_traces.push_back(
129 make_pair(t, t->get_v_offset()));
da2bebfb
JH
130 }
131
132 // Select the signal if it has been clicked
38eeddea
JH
133 const shared_ptr<Trace> mouse_over_trace =
134 get_mouse_over_trace(event->pos());
135 if (mouse_over_trace) {
136 if (mouse_over_trace->selected())
137 mouse_over_trace->select(false);
da2bebfb 138 else {
38eeddea 139 mouse_over_trace->select(true);
da2bebfb 140
333d5bbc 141 if (~QApplication::keyboardModifiers() &
07204819 142 Qt::ControlModifier)
38eeddea 143 _drag_traces.clear();
07204819 144
da2bebfb 145 // Add the signal to the drag list
333d5bbc 146 if (event->button() & Qt::LeftButton)
38eeddea
JH
147 _drag_traces.push_back(
148 make_pair(mouse_over_trace,
149 mouse_over_trace->get_v_offset()));
da2bebfb 150 }
54401bbb
JH
151 }
152
333d5bbc 153 if (~QApplication::keyboardModifiers() & Qt::ControlModifier) {
07204819
JH
154 // Unselect all other signals because the Ctrl is not
155 // pressed
38eeddea
JH
156 BOOST_FOREACH(const shared_ptr<Trace> t, traces)
157 if (t != mouse_over_trace)
158 t->select(false);
07204819
JH
159 }
160
b2a53645 161 selection_changed();
e3374498
JH
162 update();
163}
164
54401bbb
JH
165void Header::mouseReleaseEvent(QMouseEvent *event)
166{
167 assert(event);
333d5bbc 168 if (event->button() == Qt::LeftButton) {
38eeddea 169 _drag_traces.clear();
4b192962
JH
170 _view.normalize_layout();
171 }
54401bbb
JH
172}
173
a29bb7fb
JH
174void Header::mouseMoveEvent(QMouseEvent *event)
175{
176 assert(event);
177 _mouse_point = event->pos();
54401bbb
JH
178
179 // Move the signals if we are dragging
38eeddea 180 if (!_drag_traces.empty()) {
54401bbb
JH
181 const int delta = event->pos().y() - _mouse_down_point.y();
182
38eeddea
JH
183 for (std::list<std::pair<boost::weak_ptr<Trace>,
184 int> >::iterator i = _drag_traces.begin();
185 i != _drag_traces.end(); i++) {
186 const boost::shared_ptr<Trace> trace((*i).first);
187 if (trace) {
da2bebfb 188 const int y = (*i).second + delta;
49153683
JH
189 const int y_snap =
190 ((y + View::SignalSnapGridSize / 2) /
191 View::SignalSnapGridSize) *
192 View::SignalSnapGridSize;
38eeddea 193 trace->set_v_offset(y_snap);
da2bebfb 194
38eeddea
JH
195 // Ensure the trace is selected
196 trace->select();
49153683 197 }
da2bebfb
JH
198
199 }
54401bbb
JH
200
201 signals_moved();
202 }
203
a29bb7fb
JH
204 update();
205}
206
e314eca4 207void Header::leaveEvent(QEvent*)
a29bb7fb
JH
208{
209 _mouse_point = QPoint(-1, -1);
210 update();
211}
212
49f8ff3f
JH
213void Header::contextMenuEvent(QContextMenuEvent *event)
214{
38eeddea 215 const shared_ptr<Trace> t = get_mouse_over_trace(_mouse_point);
49f8ff3f 216
38eeddea 217 if (!t)
e3374498 218 return;
49f8ff3f 219
e3374498
JH
220 QMenu menu(this);
221 menu.addAction(_action_set_name);
222 menu.addAction(_action_set_colour);
49f8ff3f 223
38eeddea 224 _context_trace = t;
e3374498 225 menu.exec(event->globalPos());
38eeddea 226 _context_trace.reset();
49f8ff3f
JH
227}
228
229void Header::on_action_set_name_triggered()
230{
2c982fc3
JH
231 bool ok = false;
232
38eeddea
JH
233 shared_ptr<view::Trace> context_trace = _context_trace;
234 if (!context_trace)
49f8ff3f
JH
235 return;
236
237 const QString new_label = QInputDialog::getText(this, tr("Set Name"),
38eeddea 238 tr("Name"), QLineEdit::Normal, context_trace->get_name(), &ok);
49f8ff3f 239
2c982fc3 240 if (ok)
38eeddea 241 context_trace->set_name(new_label);
49f8ff3f
JH
242}
243
b3b57abc
JH
244void Header::on_action_set_colour_triggered()
245{
38eeddea
JH
246 shared_ptr<view::Trace> context_trace = _context_trace;
247 if (!context_trace)
b3b57abc
JH
248 return;
249
250 const QColor new_colour = QColorDialog::getColor(
38eeddea 251 context_trace->get_colour(), this, tr("Set Colour"));
b3b57abc 252
333d5bbc 253 if (new_colour.isValid())
38eeddea 254 context_trace->set_colour(new_colour);
b3b57abc
JH
255}
256
9e40e83d
JH
257void Header::on_signals_changed()
258{
38eeddea
JH
259 const vector< shared_ptr<Trace> > traces(_view.get_traces());
260 BOOST_FOREACH(shared_ptr<Trace> t, traces) {
261 assert(t);
262 connect(t.get(), SIGNAL(text_changed()), this, SLOT(update()));
9e40e83d
JH
263 }
264}
265
07204819
JH
266void Header::on_signals_moved()
267{
268 update();
269}
270
271
1d8dca91
JH
272} // namespace view
273} // namespace pv