xref: /glogg/src/overviewwidget.cpp (revision f01b5ae6e52a8353648b89082babdce6d22dd832)
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 
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 
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 
173*f01b5ae6SNicolas Bonnefon         painter.fillRect( painter.viewport(), painter.background() );
174*f01b5ae6SNicolas 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 
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 
230bb02e0acSNicolas Bonnefon void OverviewWidget::mouseMoveEvent( QMouseEvent* mouseEvent )
231bb02e0acSNicolas Bonnefon {
232bb02e0acSNicolas Bonnefon     if ( mouseEvent->buttons() |= Qt::LeftButton )
233bb02e0acSNicolas Bonnefon         handleMousePress( mouseEvent->y() );
234bb02e0acSNicolas Bonnefon }
235bb02e0acSNicolas Bonnefon 
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 
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 
254bb02e0acSNicolas Bonnefon void OverviewWidget::removeHighlight()
255bb02e0acSNicolas Bonnefon {
256bb02e0acSNicolas Bonnefon     highlightTimer_.stop();
257bb02e0acSNicolas Bonnefon 
258bb02e0acSNicolas Bonnefon     highlightedLine_ = -1;
259bb02e0acSNicolas Bonnefon     update();
260bb02e0acSNicolas Bonnefon }
261bb02e0acSNicolas Bonnefon 
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