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