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