1bb02e0acSNicolas Bonnefon /*
2bb02e0acSNicolas Bonnefon * Copyright (C) 2011, 2012, 2013 Nicolas Bonnefon and other contributors
3bb02e0acSNicolas Bonnefon *
4bb02e0acSNicolas Bonnefon * This file is part of glogg.
5bb02e0acSNicolas Bonnefon *
6bb02e0acSNicolas Bonnefon * glogg is free software: you can redistribute it and/or modify
7bb02e0acSNicolas Bonnefon * it under the terms of the GNU General Public License as published by
8bb02e0acSNicolas Bonnefon * the Free Software Foundation, either version 3 of the License, or
9bb02e0acSNicolas Bonnefon * (at your option) any later version.
10bb02e0acSNicolas Bonnefon *
11bb02e0acSNicolas Bonnefon * glogg is distributed in the hope that it will be useful,
12bb02e0acSNicolas Bonnefon * but WITHOUT ANY WARRANTY; without even the implied warranty of
13bb02e0acSNicolas Bonnefon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14bb02e0acSNicolas Bonnefon * GNU General Public License for more details.
15bb02e0acSNicolas Bonnefon *
16bb02e0acSNicolas Bonnefon * You should have received a copy of the GNU General Public License
17bb02e0acSNicolas Bonnefon * along with glogg. If not, see <http://www.gnu.org/licenses/>.
18bb02e0acSNicolas Bonnefon */
19bb02e0acSNicolas Bonnefon
20bb02e0acSNicolas Bonnefon // This file implements OverviewWidget. This class is responsable for
21bb02e0acSNicolas Bonnefon // managing and painting the matches overview widget.
22bb02e0acSNicolas Bonnefon
23bb02e0acSNicolas Bonnefon #include <QPainter>
24bb02e0acSNicolas Bonnefon #include <QMouseEvent>
25bb02e0acSNicolas Bonnefon #include <cassert>
26bb02e0acSNicolas Bonnefon
27bb02e0acSNicolas Bonnefon #include "log.h"
28bb02e0acSNicolas Bonnefon
29bb02e0acSNicolas Bonnefon #include "overviewwidget.h"
30bb02e0acSNicolas Bonnefon
31bb02e0acSNicolas Bonnefon #include "overview.h"
32bb02e0acSNicolas Bonnefon
33bb02e0acSNicolas Bonnefon // Graphic parameters
34bb02e0acSNicolas Bonnefon const int OverviewWidget::LINE_MARGIN = 4;
35bb02e0acSNicolas Bonnefon const int OverviewWidget::STEP_DURATION_MS = 30;
36bb02e0acSNicolas Bonnefon const int OverviewWidget::INITIAL_TTL_VALUE = 5;
37bb02e0acSNicolas Bonnefon
38bb02e0acSNicolas Bonnefon #define HIGHLIGHT_XPM_WIDTH 27
39bb02e0acSNicolas Bonnefon #define HIGHLIGHT_XPM_HEIGHT 9
40bb02e0acSNicolas Bonnefon
41bb02e0acSNicolas Bonnefon #define S(x) #x
42bb02e0acSNicolas Bonnefon #define SX(x) S(x)
43bb02e0acSNicolas Bonnefon
44bb02e0acSNicolas Bonnefon // width height colours char/pixel
45bb02e0acSNicolas Bonnefon // Colours
46bb02e0acSNicolas Bonnefon #define HIGHLIGHT_XPM_LEAD_LINE SX(HIGHLIGHT_XPM_WIDTH) " " SX(HIGHLIGHT_XPM_HEIGHT) " 2 1",\
47bb02e0acSNicolas Bonnefon " s mask c none",\
48bb02e0acSNicolas Bonnefon "x c #572F80"
49bb02e0acSNicolas Bonnefon
50bb02e0acSNicolas Bonnefon const char* const highlight_xpm[][14] = {
51bb02e0acSNicolas Bonnefon {
52bb02e0acSNicolas Bonnefon HIGHLIGHT_XPM_LEAD_LINE,
53bb02e0acSNicolas Bonnefon " ",
54bb02e0acSNicolas Bonnefon " ",
55bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxx ",
56bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxx ",
57bb02e0acSNicolas Bonnefon " xx xx ",
58bb02e0acSNicolas Bonnefon " xx xx ",
59bb02e0acSNicolas Bonnefon " xx xx ",
60bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxx ",
61bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxx ",
62bb02e0acSNicolas Bonnefon " ",
63bb02e0acSNicolas Bonnefon " ",
64bb02e0acSNicolas Bonnefon },
65bb02e0acSNicolas Bonnefon {
66bb02e0acSNicolas Bonnefon HIGHLIGHT_XPM_LEAD_LINE,
67bb02e0acSNicolas Bonnefon " ",
68bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxx ",
69bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxx ",
70bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxx ",
71bb02e0acSNicolas Bonnefon " xxx xxx ",
72bb02e0acSNicolas Bonnefon " xxx xxx ",
73bb02e0acSNicolas Bonnefon " xxx xxx ",
74bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxx ",
75bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxx ",
76bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxx ",
77bb02e0acSNicolas Bonnefon " ",
78bb02e0acSNicolas Bonnefon },
79bb02e0acSNicolas Bonnefon {
80bb02e0acSNicolas Bonnefon HIGHLIGHT_XPM_LEAD_LINE,
81bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxxxx ",
82bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxxxx ",
83bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxxxx ",
84bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxxxx ",
85bb02e0acSNicolas Bonnefon " xxxx xxxx ",
86bb02e0acSNicolas Bonnefon " xxxx xxxx ",
87bb02e0acSNicolas Bonnefon " xxxx xxxx ",
88bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxxxx ",
89bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxxxx ",
90bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxxxx ",
91bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxxxx ",
92bb02e0acSNicolas Bonnefon },
93bb02e0acSNicolas Bonnefon {
94bb02e0acSNicolas Bonnefon HIGHLIGHT_XPM_LEAD_LINE,
95bb02e0acSNicolas Bonnefon " ",
96bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxx ",
97bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxx ",
98bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxx ",
99bb02e0acSNicolas Bonnefon " xxx xxx ",
100bb02e0acSNicolas Bonnefon " xxx xxx ",
101bb02e0acSNicolas Bonnefon " xxx xxx ",
102bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxx ",
103bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxx ",
104bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxxxx ",
105bb02e0acSNicolas Bonnefon " ",
106bb02e0acSNicolas Bonnefon },
107bb02e0acSNicolas Bonnefon {
108bb02e0acSNicolas Bonnefon HIGHLIGHT_XPM_LEAD_LINE,
109bb02e0acSNicolas Bonnefon " ",
110bb02e0acSNicolas Bonnefon " ",
111bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxx ",
112bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxx ",
113bb02e0acSNicolas Bonnefon " xx xx ",
114bb02e0acSNicolas Bonnefon " xx xx ",
115bb02e0acSNicolas Bonnefon " xx xx ",
116bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxx ",
117bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxxxx ",
118bb02e0acSNicolas Bonnefon " ",
119bb02e0acSNicolas Bonnefon " ",
120bb02e0acSNicolas Bonnefon },
121bb02e0acSNicolas Bonnefon {
122bb02e0acSNicolas Bonnefon HIGHLIGHT_XPM_LEAD_LINE,
123bb02e0acSNicolas Bonnefon " ",
124bb02e0acSNicolas Bonnefon " ",
125bb02e0acSNicolas Bonnefon " ",
126bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxx ",
127bb02e0acSNicolas Bonnefon " x x ",
128bb02e0acSNicolas Bonnefon " x x ",
129bb02e0acSNicolas Bonnefon " x x ",
130bb02e0acSNicolas Bonnefon " xxxxxxxxxxxxxxxxxxx ",
131bb02e0acSNicolas Bonnefon " ",
132bb02e0acSNicolas Bonnefon " ",
133bb02e0acSNicolas Bonnefon " ",
134bb02e0acSNicolas Bonnefon },
135bb02e0acSNicolas Bonnefon };
136bb02e0acSNicolas Bonnefon
OverviewWidget(QWidget * parent)137bb02e0acSNicolas Bonnefon OverviewWidget::OverviewWidget( QWidget* parent ) :
138bb02e0acSNicolas Bonnefon QWidget( parent ), highlightTimer_()
139bb02e0acSNicolas Bonnefon {
140bb02e0acSNicolas Bonnefon overview_ = NULL;
141bb02e0acSNicolas Bonnefon
142bb02e0acSNicolas Bonnefon setBackgroundRole( QPalette::Window );
143bb02e0acSNicolas Bonnefon
144bb02e0acSNicolas Bonnefon // Highlight
145bb02e0acSNicolas Bonnefon highlightedLine_ = -1;
146bb02e0acSNicolas Bonnefon highlightedTTL_ = 0;
147bb02e0acSNicolas Bonnefon
148bb02e0acSNicolas Bonnefon // We should be hidden by default (e.g. for the FilteredView)
149bb02e0acSNicolas Bonnefon hide();
150bb02e0acSNicolas Bonnefon }
151bb02e0acSNicolas Bonnefon
paintEvent(QPaintEvent *)152721a2433SNicolas Bonnefon void OverviewWidget::paintEvent( QPaintEvent* /* paintEvent */ )
153bb02e0acSNicolas Bonnefon {
154bb02e0acSNicolas Bonnefon static const QColor match_color("red");
155bb02e0acSNicolas Bonnefon static const QColor mark_color("dodgerblue");
156bb02e0acSNicolas Bonnefon
157bb02e0acSNicolas Bonnefon static const QPixmap highlight_pixmap[] = {
158bb02e0acSNicolas Bonnefon QPixmap( highlight_xpm[0] ),
159bb02e0acSNicolas Bonnefon QPixmap( highlight_xpm[1] ),
160bb02e0acSNicolas Bonnefon QPixmap( highlight_xpm[2] ),
161bb02e0acSNicolas Bonnefon QPixmap( highlight_xpm[3] ),
162bb02e0acSNicolas Bonnefon QPixmap( highlight_xpm[4] ),
163bb02e0acSNicolas Bonnefon QPixmap( highlight_xpm[5] ), };
164bb02e0acSNicolas Bonnefon
165bb02e0acSNicolas Bonnefon // We must be hidden until we have an Overview
166bb02e0acSNicolas Bonnefon assert( overview_ != NULL );
167bb02e0acSNicolas Bonnefon
168bb02e0acSNicolas Bonnefon overview_->updateView( height() );
169bb02e0acSNicolas Bonnefon
170bb02e0acSNicolas Bonnefon {
171bb02e0acSNicolas Bonnefon QPainter painter( this );
172bb02e0acSNicolas Bonnefon
173f01b5ae6SNicolas Bonnefon painter.fillRect( painter.viewport(), painter.background() );
174f01b5ae6SNicolas Bonnefon
175bb02e0acSNicolas Bonnefon // The line separating from the main view
176bb02e0acSNicolas Bonnefon painter.setPen( palette().color(QPalette::Text) );
177bb02e0acSNicolas Bonnefon painter.drawLine( 0, 0, 0, height() );
178bb02e0acSNicolas Bonnefon
179bb02e0acSNicolas Bonnefon // The 'match' lines
180bb02e0acSNicolas Bonnefon painter.setPen( match_color );
181bb02e0acSNicolas Bonnefon foreach (Overview::WeightedLine line, *(overview_->getMatchLines()) ) {
182bb02e0acSNicolas Bonnefon painter.setOpacity( ( 1.0 / Overview::WeightedLine::WEIGHT_STEPS )
183bb02e0acSNicolas Bonnefon * ( line.weight() + 1 ) );
184bb02e0acSNicolas Bonnefon // (allow multiple matches to look 'darker' than a single one.)
185bb02e0acSNicolas Bonnefon painter.drawLine( 1 + LINE_MARGIN,
186bb02e0acSNicolas Bonnefon line.position(), width() - LINE_MARGIN - 1, line.position() );
187bb02e0acSNicolas Bonnefon }
188bb02e0acSNicolas Bonnefon
189bb02e0acSNicolas Bonnefon // The 'mark' lines
190bb02e0acSNicolas Bonnefon painter.setPen( mark_color );
191bb02e0acSNicolas Bonnefon foreach (Overview::WeightedLine line, *(overview_->getMarkLines()) ) {
192bb02e0acSNicolas Bonnefon painter.setOpacity( ( 1.0 / Overview::WeightedLine::WEIGHT_STEPS )
193bb02e0acSNicolas Bonnefon * ( line.weight() + 1 ) );
194bb02e0acSNicolas Bonnefon // (allow multiple matches to look 'darker' than a single one.)
195bb02e0acSNicolas Bonnefon painter.drawLine( 1 + LINE_MARGIN,
196bb02e0acSNicolas Bonnefon line.position(), width() - LINE_MARGIN - 1, line.position() );
197bb02e0acSNicolas Bonnefon }
198bb02e0acSNicolas Bonnefon
199bb02e0acSNicolas Bonnefon // The 'view' lines
200bb02e0acSNicolas Bonnefon painter.setOpacity( 1 );
201bb02e0acSNicolas Bonnefon painter.setPen( palette().color(QPalette::Text) );
202bb02e0acSNicolas Bonnefon std::pair<int,int> view_lines = overview_->getViewLines();
203bb02e0acSNicolas Bonnefon painter.drawLine( 1, view_lines.first, width(), view_lines.first );
204bb02e0acSNicolas Bonnefon painter.drawLine( 1, view_lines.second, width(), view_lines.second );
205bb02e0acSNicolas Bonnefon
206bb02e0acSNicolas Bonnefon // The highlight
207bb02e0acSNicolas Bonnefon if ( highlightedLine_ >= 0 ) {
208bb02e0acSNicolas Bonnefon /*
209bb02e0acSNicolas Bonnefon QPen highlight_pen( palette().color(QPalette::Text) );
210bb02e0acSNicolas Bonnefon highlight_pen.setWidth( 4 - highlightedTTL_ );
211bb02e0acSNicolas Bonnefon painter.setOpacity( 1 );
212bb02e0acSNicolas Bonnefon painter.setPen( highlight_pen );
213bb02e0acSNicolas Bonnefon painter.drawRect( 2, position - 2, width() - 2 - 2, 4 );
214bb02e0acSNicolas Bonnefon */
215bb02e0acSNicolas Bonnefon int position = overview_->yFromFileLine( highlightedLine_ );
216bb02e0acSNicolas Bonnefon painter.drawPixmap(
217bb02e0acSNicolas Bonnefon ( width() - HIGHLIGHT_XPM_WIDTH ) / 2,
218bb02e0acSNicolas Bonnefon position - ( HIGHLIGHT_XPM_HEIGHT / 2 ),
219bb02e0acSNicolas Bonnefon highlight_pixmap[ INITIAL_TTL_VALUE - highlightedTTL_ ] );
220bb02e0acSNicolas Bonnefon }
221bb02e0acSNicolas Bonnefon }
222bb02e0acSNicolas Bonnefon }
223bb02e0acSNicolas Bonnefon
mousePressEvent(QMouseEvent * mouseEvent)224bb02e0acSNicolas Bonnefon void OverviewWidget::mousePressEvent( QMouseEvent* mouseEvent )
225bb02e0acSNicolas Bonnefon {
226bb02e0acSNicolas Bonnefon if ( mouseEvent->button() == Qt::LeftButton )
227bb02e0acSNicolas Bonnefon handleMousePress( mouseEvent->y() );
228bb02e0acSNicolas Bonnefon }
229bb02e0acSNicolas Bonnefon
mouseMoveEvent(QMouseEvent * mouseEvent)230bb02e0acSNicolas Bonnefon void OverviewWidget::mouseMoveEvent( QMouseEvent* mouseEvent )
231bb02e0acSNicolas Bonnefon {
232*2f6e624bSAnton Filimonov if ( mouseEvent->buttons().testFlag( Qt::LeftButton ) )
233bb02e0acSNicolas Bonnefon handleMousePress( mouseEvent->y() );
234bb02e0acSNicolas Bonnefon }
235bb02e0acSNicolas Bonnefon
handleMousePress(int position)236bb02e0acSNicolas Bonnefon void OverviewWidget::handleMousePress( int position )
237bb02e0acSNicolas Bonnefon {
238bb02e0acSNicolas Bonnefon int line = overview_->fileLineFromY( position );
239bb02e0acSNicolas Bonnefon LOG(logDEBUG) << "OverviewWidget::handleMousePress y=" << position << " line=" << line;
240bb02e0acSNicolas Bonnefon emit lineClicked( line );
241bb02e0acSNicolas Bonnefon }
242bb02e0acSNicolas Bonnefon
highlightLine(qint64 line)243bb02e0acSNicolas Bonnefon void OverviewWidget::highlightLine( qint64 line )
244bb02e0acSNicolas Bonnefon {
245bb02e0acSNicolas Bonnefon highlightTimer_.stop();
246bb02e0acSNicolas Bonnefon
247bb02e0acSNicolas Bonnefon highlightedLine_ = line;
248bb02e0acSNicolas Bonnefon highlightedTTL_ = INITIAL_TTL_VALUE;
249bb02e0acSNicolas Bonnefon
250bb02e0acSNicolas Bonnefon update();
251bb02e0acSNicolas Bonnefon highlightTimer_.start( STEP_DURATION_MS, this );
252bb02e0acSNicolas Bonnefon }
253bb02e0acSNicolas Bonnefon
removeHighlight()254bb02e0acSNicolas Bonnefon void OverviewWidget::removeHighlight()
255bb02e0acSNicolas Bonnefon {
256bb02e0acSNicolas Bonnefon highlightTimer_.stop();
257bb02e0acSNicolas Bonnefon
258bb02e0acSNicolas Bonnefon highlightedLine_ = -1;
259bb02e0acSNicolas Bonnefon update();
260bb02e0acSNicolas Bonnefon }
261bb02e0acSNicolas Bonnefon
timerEvent(QTimerEvent * event)262bb02e0acSNicolas Bonnefon void OverviewWidget::timerEvent( QTimerEvent* event )
263bb02e0acSNicolas Bonnefon {
264bb02e0acSNicolas Bonnefon if ( event->timerId() == highlightTimer_.timerId() ) {
265bb02e0acSNicolas Bonnefon LOG(logDEBUG) << "OverviewWidget::timerEvent";
266bb02e0acSNicolas Bonnefon if ( highlightedTTL_ > 0 ) {
267bb02e0acSNicolas Bonnefon --highlightedTTL_;
268bb02e0acSNicolas Bonnefon update();
269bb02e0acSNicolas Bonnefon }
270bb02e0acSNicolas Bonnefon else {
271bb02e0acSNicolas Bonnefon highlightTimer_.stop();
272bb02e0acSNicolas Bonnefon }
273bb02e0acSNicolas Bonnefon }
274bb02e0acSNicolas Bonnefon else {
275bb02e0acSNicolas Bonnefon QObject::timerEvent( event );
276bb02e0acSNicolas Bonnefon }
277bb02e0acSNicolas Bonnefon }
278