/*
* Copyright (C) 2009, 2010, 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 .
*/
#ifndef ABSTRACTLOGVIEW_H
#define ABSTRACTLOGVIEW_H
#include
#include
#ifdef GLOGG_PERF_MEASURE_FPS
# include "perfcounter.h"
#endif
#include "selection.h"
#include "quickfind.h"
#include "overviewwidget.h"
#include "quickfindmux.h"
#include "viewtools.h"
class QMenu;
class QAction;
class AbstractLogData;
class LineChunk
{
public:
enum ChunkType {
Normal,
Highlighted,
Selected,
};
LineChunk( int first_col, int end_col, ChunkType type );
int start() const { return start_; }
int end() const { return end_; }
ChunkType type() const { return type_; }
// Returns 'true' if the selection is part of this chunk
// (at least partially), if so, it should be replaced by the list returned
QList select( int selection_start, int selection_end ) const;
private:
int start_;
int end_;
ChunkType type_;
};
// Utility class for syntax colouring.
// It stores the chunks of line to draw
// each chunk having a different colour
class LineDrawer
{
public:
LineDrawer( const QColor& back_color) :
list(), backColor_( back_color ) { };
// Add a chunk of line using the given colours.
// Both first_col and last_col are included
// An empty chunk will be ignored.
// the first column will be set to 0 if negative
// The column are relative to the screen
void addChunk( int first_col, int last_col, QColor fore, QColor back );
void addChunk( const LineChunk& chunk, QColor fore, QColor back );
// Draw the current line of text using the given painter,
// in the passed block (in pixels)
// The line must be cut to fit on the screen.
// leftExtraBackgroundPx is the an extra margin to start drawing
// the coloured // background, going all the way to the element
// left of the line looks better.
void draw( QPainter& painter, int xPos, int yPos,
int line_width, const QString& line,
int leftExtraBackgroundPx );
private:
class Chunk {
public:
// Create a new chunk
Chunk( int start, int length, QColor fore, QColor back )
: start_( start ), length_( length ),
foreColor_ ( fore ), backColor_ ( back ) { };
// Accessors
int start() const { return start_; }
int length() const { return length_; }
const QColor& foreColor() const { return foreColor_; }
const QColor& backColor() const { return backColor_; }
private:
int start_;
int length_;
QColor foreColor_;
QColor backColor_;
};
QList list;
QColor backColor_;
};
// Utility class representing a buffer for number entered on the keyboard
// The buffer keep at most 7 digits, and reset itself after a timeout.
class DigitsBuffer : public QObject
{
Q_OBJECT
public:
DigitsBuffer();
// Reset the buffer.
void reset();
// Add a single digit to the buffer (discarded if it's not a digit),
// the timeout timer is reset.
void add( char character );
// Get the content of the buffer (0 if empty) and reset it.
int content();
protected:
void timerEvent( QTimerEvent* event );
private:
// Duration of the timeout in milliseconds.
static const int timeout_;
QString digits_;
QBasicTimer timer_;
};
class Overview;
// Base class representing the log view widget.
// It can be either the top (full) or bottom (filtered) view.
class AbstractLogView :
public QAbstractScrollArea, public SearchableWidgetInterface
{
Q_OBJECT
public:
// Constructor of the widget, the data set is passed.
// The caller retains ownership of the data set.
// The pointer to the QFP is used for colouring and QuickFind searches
AbstractLogView( const AbstractLogData* newLogData,
const QuickFindPattern* const quickFind, QWidget* parent=0 );
~AbstractLogView();
// Refresh the widget when the data set has changed.
void updateData();
// Instructs the widget to update it's content geometry,
// used when the font is changed.
void updateDisplaySize();
// Return the line number of the top line of the view
int getTopLine() const;
// Return the text of the current selection.
QString getSelection() const;
// Instructs the widget to select the whole text.
void selectAll();
bool isFollowEnabled() const { return followMode_; }
protected:
virtual void mousePressEvent( QMouseEvent* mouseEvent );
virtual void mouseMoveEvent( QMouseEvent* mouseEvent );
virtual void mouseReleaseEvent( QMouseEvent* );
virtual void mouseDoubleClickEvent( QMouseEvent* mouseEvent );
virtual void timerEvent( QTimerEvent* timerEvent );
virtual void changeEvent( QEvent* changeEvent );
virtual void paintEvent( QPaintEvent* paintEvent );
virtual void resizeEvent( QResizeEvent* resizeEvent );
virtual void scrollContentsBy( int dx, int dy );
virtual void keyPressEvent( QKeyEvent* keyEvent );
virtual void wheelEvent( QWheelEvent* wheelEvent );
virtual bool event( QEvent * e );
// Must be implemented to return wether the line number is
// a match, a mark or just a normal line (used for coloured bullets)
enum LineType { Normal, Marked, Match };
virtual LineType lineType( int lineNumber ) const = 0;
// Line number to display for line at the given index
virtual qint64 displayLineNumber( int lineNumber ) const;
virtual qint64 maxDisplayLineNumber() const;
// Get the overview associated with this view, or NULL if there is none
Overview* getOverview() const { return overview_; }
// Set the Overview and OverviewWidget
void setOverview( Overview* overview, OverviewWidget* overview_widget );
signals:
// Sent when a new line has been selected by the user.
void newSelection(int line);
// Sent up to the MainWindow to enable/disable the follow mode
void followModeChanged( bool enabled );
// Sent when the view wants the QuickFind widget pattern to change.
void changeQuickFind( const QString& newPattern,
QuickFindMux::QFDirection newDirection );
// Sent up when the current line number is updated
void updateLineNumber( int line );
// Sent up when quickFind wants to show a message to the user.
void notifyQuickFind( const QFNotification& message );
// Sent up when quickFind wants to clear the notification.
void clearQuickFindNotification();
// Sent when the view ask for a line to be marked
// (click in the left margin).
void markLine( qint64 line );
// Sent up when the user wants to add the selection to the search
void addToSearch( const QString& selection );
// Sent up when the mouse is hovered over a line's margin
void mouseHoveredOverLine( qint64 line );
// Sent up when the mouse leaves a line's margin
void mouseLeftHoveringZone();
// Sent up for view initiated quickfind searches
void searchNext();
void searchPrevious();
// Sent up when the user has moved within the view
void activity();
public slots:
// Makes the widget select and display the passed line.
// Scrolling as necessary
void selectAndDisplayLine( int line );
// Use the current QFP to go and select the next match.
virtual void searchForward();
// Use the current QFP to go and select the previous match.
virtual void searchBackward();
// Use the current QFP to go and select the next match (incremental)
virtual void incrementallySearchForward();
// Use the current QFP to go and select the previous match (incremental)
virtual void incrementallySearchBackward();
// Stop the current incremental search (typically when user press return)
virtual void incrementalSearchStop();
// Abort the current incremental search (typically when user press esc)
virtual void incrementalSearchAbort();
// Signals the follow mode has been enabled.
void followSet( bool checked );
// Signal the on/off status of the overview has been changed.
void refreshOverview();
// Make the view jump to the specified line, regardless of weither it
// is on the screen or not.
// (does NOT emit followDisabled() )
void jumpToLine( int line );
// Configure the setting of whether to show line number margin
void setLineNumbersVisible( bool lineNumbersVisible );
// Force the next refresh to fully redraw the view by invalidating the cache.
// To be used if the data might have changed.
void forceRefresh();
private slots:
void handlePatternUpdated();
void addToSearch();
void findNextSelected();
void findPreviousSelected();
void copy();
private:
// Graphic parameters
static constexpr int OVERVIEW_WIDTH = 27;
static constexpr int HOOK_THRESHOLD = 600;
static constexpr int PULL_TO_FOLLOW_HOOKED_HEIGHT = 10;
// Width of the bullet zone, including decoration
int bulletZoneWidthPx_;
// Total size of all margins and decorations in pixels
int leftMarginPx_;
// Digits buffer (for numeric keyboard entry)
DigitsBuffer digitsBuffer_;
// Follow mode
bool followMode_;
// ElasticHook for follow mode
ElasticHook followElasticHook_;
// Whether to show line numbers or not
bool lineNumbersVisible_;
// Pointer to the CrawlerWidget's data set
const AbstractLogData* logData;
// Pointer to the Overview object
Overview* overview_;
// Pointer to the OverviewWidget, this class doesn't own it,
// but is responsible for displaying it (for purely aesthetic
// reasons).
OverviewWidget* overviewWidget_;
bool selectionStarted_;
// Start of the selection (characters)
QPoint selectionStartPos_;
// Current end of the selection (characters)
QPoint selectionCurrentEndPos_;
QBasicTimer autoScrollTimer_;
// Hovering state
// Last line that has been hoovered on, -1 if none
qint64 lastHoveredLine_;
// Marks (left margin click)
bool markingClickInitiated_;
qint64 markingClickLine_;
Selection selection_;
// Position of the view, those are crucial to control drawing
// firstLine gives the position of the view,
// lastLineAligned == true make the bottom of the last line aligned
// rather than the top of the top one.
LineNumber firstLine;
bool lastLineAligned;
int firstCol;
// Text handling
int charWidth_;
int charHeight_;
// Popup menu
QMenu* popupMenu_;
QAction* copyAction_;
QAction* findNextAction_;
QAction* findPreviousAction_;
QAction* addToSearchAction_;
// Pointer to the CrawlerWidget's QFP object
const QuickFindPattern* const quickFindPattern_;
// Our own QuickFind object
QuickFind quickFind_;
#ifdef GLOGG_PERF_MEASURE_FPS
// Performance measurement
PerfCounter perfCounter_;
#endif
// Vertical offset (in pixels) at which the first line of text is written
int drawingTopOffset_ = 0;
// Cache pixmap and associated info
struct TextAreaCache {
QPixmap pixmap_;
bool invalid_;
int first_line_;
int last_line_;
int first_column_;
};
struct PullToFollowCache {
QPixmap pixmap_;
int nb_columns_;
};
TextAreaCache textAreaCache_ = { {}, true, 0, 0, 0 };
PullToFollowCache pullToFollowCache_ = { {}, 0 };
LineNumber getNbVisibleLines() const;
int getNbVisibleCols() const;
QPoint convertCoordToFilePos( const QPoint& pos ) const;
int convertCoordToLine( int yPos ) const;
int convertCoordToColumn( int xPos ) const;
void displayLine( LineNumber line );
void moveSelection( int y );
void jumpToStartOfLine();
void jumpToEndOfLine();
void jumpToRightOfScreen();
void jumpToTop();
void jumpToBottom();
void selectWordAtPosition( const QPoint& pos );
void createMenu();
void considerMouseHovering( int x_pos, int y_pos );
// Search functions (for n/N)
void searchUsingFunction( qint64 (QuickFind::*search_function)() );
void updateScrollBars();
void drawTextArea( QPaintDevice* paint_device, int32_t delta_y );
QPixmap drawPullToFollowBar( int width, float pixel_ratio );
void disableFollow();
// Utils functions
bool isCharWord( char c );
void updateGlobalSelection();
};
#endif