Header, Viewport: Don't manually invoke on_signals_changed on construction
[pulseview.git] / pv / view / cursorheader.cpp
1 /*
2  * This file is part of the PulseView project.
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 "cursorheader.h"
22
23 #include "ruler.h"
24 #include "view.h"
25
26 #include <QApplication>
27 #include <QFontMetrics>
28 #include <QMouseEvent>
29
30 #include <pv/widgets/popup.h>
31
32 using std::shared_ptr;
33
34 namespace pv {
35 namespace view {
36
37 const int CursorHeader::Padding = 20;
38 const int CursorHeader::BaselineOffset = 5;
39
40 int CursorHeader::calculateTextHeight()
41 {
42         QFontMetrics fm(font());
43         return fm.boundingRect(0, 0, INT_MAX, INT_MAX,
44                 Qt::AlignLeft | Qt::AlignTop, "8").height();
45 }
46
47 CursorHeader::CursorHeader(View &parent) :
48         MarginWidget(parent),
49         _dragging(false),
50         _textHeight(calculateTextHeight())
51 {
52         setMouseTracking(true);
53 }
54
55 QSize CursorHeader::sizeHint() const
56 {
57         return QSize(0, _textHeight + Padding + BaselineOffset);
58 }
59
60 void CursorHeader::clear_selection()
61 {
62         CursorPair &cursors = _view.cursors();
63         cursors.first()->select(false);
64         cursors.second()->select(false);
65         update();
66 }
67
68 void CursorHeader::paintEvent(QPaintEvent*)
69 {
70         QPainter p(this);
71         p.setRenderHint(QPainter::Antialiasing);
72
73         unsigned int prefix = pv::view::Ruler::calculate_tick_spacing(
74                 p, _view.scale(), _view.offset()).second;
75
76         // Draw the cursors
77         if (_view.cursors_shown()) {
78                 // The cursor labels are not drawn with the arrows exactly on the
79                 // bottom line of the widget, because then the selection shadow
80                 // would be clipped away.
81                 const QRect r = rect().adjusted(0, 0, 0, -BaselineOffset);
82                 _view.cursors().draw_markers(p, r, prefix);
83         }
84 }
85
86 void CursorHeader::mouseMoveEvent(QMouseEvent *e)
87 {
88         if (!(e->buttons() & Qt::LeftButton))
89                 return;
90
91         if ((e->pos() - _mouse_down_point).manhattanLength() <
92                 QApplication::startDragDistance())
93                 return;
94
95         _dragging = true;
96
97         if (shared_ptr<TimeMarker> m = _grabbed_marker.lock())
98                 m->set_time(_view.offset() +
99                         ((double)e->x() + 0.5) * _view.scale());
100 }
101
102 void CursorHeader::mousePressEvent(QMouseEvent *e)
103 {
104         if (e->buttons() & Qt::LeftButton) {
105                 _mouse_down_point = e->pos();
106
107                 _grabbed_marker.reset();
108
109                 clear_selection();
110
111                 if (_view.cursors_shown()) {
112                         CursorPair &cursors = _view.cursors();
113                         if (cursors.first()->get_label_rect(
114                                 rect()).contains(e->pos()))
115                                 _grabbed_marker = cursors.first();
116                         else if (cursors.second()->get_label_rect(
117                                 rect()).contains(e->pos()))
118                                 _grabbed_marker = cursors.second();
119                 }
120
121                 if (shared_ptr<TimeMarker> m = _grabbed_marker.lock())
122                         m->select();
123
124                 selection_changed();
125         }
126 }
127
128 void CursorHeader::mouseReleaseEvent(QMouseEvent *)
129 {
130         using pv::widgets::Popup;
131
132         if (!_dragging)
133                 if (shared_ptr<TimeMarker> m = _grabbed_marker.lock()) {
134                         Popup *const p = m->create_popup(&_view);
135                         const QPoint arrpos(m->get_x(), height() - BaselineOffset);
136                         p->set_position(mapToGlobal(arrpos), Popup::Bottom);
137                         p->show();
138                 }
139
140         _dragging = false;
141         _grabbed_marker.reset();
142 }
143
144 } // namespace view
145 } // namespace pv