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