/*
* Copyright (C) 2011, 2012, 2013 Nicolas Bonnefon and other contributors
*
* This file is part of glogg.
*
* glogg is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* glogg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with glogg. If not, see .
*/
// This file implements OverviewWidget. This class is responsable for
// managing and painting the matches overview widget.
#include
#include
#include
#include "log.h"
#include "overviewwidget.h"
#include "overview.h"
// Graphic parameters
const int OverviewWidget::LINE_MARGIN = 4;
const int OverviewWidget::STEP_DURATION_MS = 30;
const int OverviewWidget::INITIAL_TTL_VALUE = 5;
#define HIGHLIGHT_XPM_WIDTH 27
#define HIGHLIGHT_XPM_HEIGHT 9
#define S(x) #x
#define SX(x) S(x)
// width height colours char/pixel
// Colours
#define HIGHLIGHT_XPM_LEAD_LINE SX(HIGHLIGHT_XPM_WIDTH) " " SX(HIGHLIGHT_XPM_HEIGHT) " 2 1",\
" s mask c none",\
"x c #572F80"
const char* const highlight_xpm[][14] = {
{
HIGHLIGHT_XPM_LEAD_LINE,
" ",
" ",
" xxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxx ",
" xx xx ",
" xx xx ",
" xx xx ",
" xxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxx ",
" ",
" ",
},
{
HIGHLIGHT_XPM_LEAD_LINE,
" ",
" xxxxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxxxx ",
" xxx xxx ",
" xxx xxx ",
" xxx xxx ",
" xxxxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxxxx ",
" ",
},
{
HIGHLIGHT_XPM_LEAD_LINE,
" xxxxxxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxxxxxx ",
" xxxx xxxx ",
" xxxx xxxx ",
" xxxx xxxx ",
" xxxxxxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxxxxxx ",
},
{
HIGHLIGHT_XPM_LEAD_LINE,
" ",
" xxxxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxxxx ",
" xxx xxx ",
" xxx xxx ",
" xxx xxx ",
" xxxxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxxxx ",
" ",
},
{
HIGHLIGHT_XPM_LEAD_LINE,
" ",
" ",
" xxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxx ",
" xx xx ",
" xx xx ",
" xx xx ",
" xxxxxxxxxxxxxxxxxxxxx ",
" xxxxxxxxxxxxxxxxxxxxx ",
" ",
" ",
},
{
HIGHLIGHT_XPM_LEAD_LINE,
" ",
" ",
" ",
" xxxxxxxxxxxxxxxxxxx ",
" x x ",
" x x ",
" x x ",
" xxxxxxxxxxxxxxxxxxx ",
" ",
" ",
" ",
},
};
OverviewWidget::OverviewWidget( QWidget* parent ) :
QWidget( parent ), highlightTimer_()
{
overview_ = NULL;
setBackgroundRole( QPalette::Window );
// Highlight
highlightedLine_ = -1;
highlightedTTL_ = 0;
// We should be hidden by default (e.g. for the FilteredView)
hide();
}
void OverviewWidget::paintEvent( QPaintEvent* /* paintEvent */ )
{
static const QColor match_color("red");
static const QColor mark_color("dodgerblue");
static const QPixmap highlight_pixmap[] = {
QPixmap( highlight_xpm[0] ),
QPixmap( highlight_xpm[1] ),
QPixmap( highlight_xpm[2] ),
QPixmap( highlight_xpm[3] ),
QPixmap( highlight_xpm[4] ),
QPixmap( highlight_xpm[5] ), };
// We must be hidden until we have an Overview
assert( overview_ != NULL );
overview_->updateView( height() );
{
QPainter painter( this );
painter.fillRect( painter.viewport(), painter.background() );
// The line separating from the main view
painter.setPen( palette().color(QPalette::Text) );
painter.drawLine( 0, 0, 0, height() );
// The 'match' lines
painter.setPen( match_color );
foreach (Overview::WeightedLine line, *(overview_->getMatchLines()) ) {
painter.setOpacity( ( 1.0 / Overview::WeightedLine::WEIGHT_STEPS )
* ( line.weight() + 1 ) );
// (allow multiple matches to look 'darker' than a single one.)
painter.drawLine( 1 + LINE_MARGIN,
line.position(), width() - LINE_MARGIN - 1, line.position() );
}
// The 'mark' lines
painter.setPen( mark_color );
foreach (Overview::WeightedLine line, *(overview_->getMarkLines()) ) {
painter.setOpacity( ( 1.0 / Overview::WeightedLine::WEIGHT_STEPS )
* ( line.weight() + 1 ) );
// (allow multiple matches to look 'darker' than a single one.)
painter.drawLine( 1 + LINE_MARGIN,
line.position(), width() - LINE_MARGIN - 1, line.position() );
}
// The 'view' lines
painter.setOpacity( 1 );
painter.setPen( palette().color(QPalette::Text) );
std::pair view_lines = overview_->getViewLines();
painter.drawLine( 1, view_lines.first, width(), view_lines.first );
painter.drawLine( 1, view_lines.second, width(), view_lines.second );
// The highlight
if ( highlightedLine_ >= 0 ) {
/*
QPen highlight_pen( palette().color(QPalette::Text) );
highlight_pen.setWidth( 4 - highlightedTTL_ );
painter.setOpacity( 1 );
painter.setPen( highlight_pen );
painter.drawRect( 2, position - 2, width() - 2 - 2, 4 );
*/
int position = overview_->yFromFileLine( highlightedLine_ );
painter.drawPixmap(
( width() - HIGHLIGHT_XPM_WIDTH ) / 2,
position - ( HIGHLIGHT_XPM_HEIGHT / 2 ),
highlight_pixmap[ INITIAL_TTL_VALUE - highlightedTTL_ ] );
}
}
}
void OverviewWidget::mousePressEvent( QMouseEvent* mouseEvent )
{
if ( mouseEvent->button() == Qt::LeftButton )
handleMousePress( mouseEvent->y() );
}
void OverviewWidget::mouseMoveEvent( QMouseEvent* mouseEvent )
{
if ( mouseEvent->buttons() |= Qt::LeftButton )
handleMousePress( mouseEvent->y() );
}
void OverviewWidget::handleMousePress( int position )
{
int line = overview_->fileLineFromY( position );
LOG(logDEBUG) << "OverviewWidget::handleMousePress y=" << position << " line=" << line;
emit lineClicked( line );
}
void OverviewWidget::highlightLine( qint64 line )
{
highlightTimer_.stop();
highlightedLine_ = line;
highlightedTTL_ = INITIAL_TTL_VALUE;
update();
highlightTimer_.start( STEP_DURATION_MS, this );
}
void OverviewWidget::removeHighlight()
{
highlightTimer_.stop();
highlightedLine_ = -1;
update();
}
void OverviewWidget::timerEvent( QTimerEvent* event )
{
if ( event->timerId() == highlightTimer_.timerId() ) {
LOG(logDEBUG) << "OverviewWidget::timerEvent";
if ( highlightedTTL_ > 0 ) {
--highlightedTTL_;
update();
}
else {
highlightTimer_.stop();
}
}
else {
QObject::timerEvent( event );
}
}