xref: /glogg/src/abstractlogview.h (revision 45ef183cd93d6c0b14e535ca8e31874f61b2ffa4)
1 /*
2  * Copyright (C) 2009, 2010, 2011, 2012, 2013 Nicolas Bonnefon
3  * and other contributors
4  *
5  * This file is part of glogg.
6  *
7  * glogg is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * glogg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with glogg.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #ifndef ABSTRACTLOGVIEW_H
22 #define ABSTRACTLOGVIEW_H
23 
24 #include <QAbstractScrollArea>
25 #include <QBasicTimer>
26 
27 #ifdef GLOGG_PERF_MEASURE_FPS
28 #  include "perfcounter.h"
29 #endif
30 
31 #include "selection.h"
32 #include "quickfind.h"
33 #include "overviewwidget.h"
34 #include "quickfindmux.h"
35 
36 class QMenu;
37 class QAction;
38 class AbstractLogData;
39 
40 class LineChunk
41 {
42   public:
43     enum ChunkType {
44         Normal,
45         Highlighted,
46         Selected,
47     };
48 
49     LineChunk( int first_col, int end_col, ChunkType type );
50 
51     int start() const { return start_; }
52     int end() const { return end_; }
53     ChunkType type() const { return type_; }
54 
55     // Returns 'true' if the selection is part of this chunk
56     // (at least partially), if so, it should be replaced by the list returned
57     QList<LineChunk> select( int selection_start, int selection_end ) const;
58 
59   private:
60     int start_;
61     int end_;
62     ChunkType type_;
63 };
64 
65 // Utility class for syntax colouring.
66 // It stores the chunks of line to draw
67 // each chunk having a different colour
68 class LineDrawer
69 {
70   public:
71     LineDrawer( const QColor& back_color) :
72         list(), backColor_( back_color ) { };
73 
74     // Add a chunk of line using the given colours.
75     // Both first_col and last_col are included
76     // An empty chunk will be ignored.
77     // the first column will be set to 0 if negative
78     // The column are relative to the screen
79     void addChunk( int first_col, int last_col, QColor fore, QColor back );
80     void addChunk( const LineChunk& chunk, QColor fore, QColor back );
81 
82     // Draw the current line of text using the given painter,
83     // in the passed block (in pixels)
84     // The line must be cut to fit on the screen.
85     // leftExtraBackgroundPx is the an extra margin to start drawing
86     // the coloured // background, going all the way to the element
87     // left of the line looks better.
88     void draw( QPainter& painter, int xPos, int yPos,
89                int line_width, const QString& line,
90                int leftExtraBackgroundPx );
91 
92   private:
93     class Chunk {
94       public:
95         // Create a new chunk
96         Chunk( int start, int length, QColor fore, QColor back )
97             : start_( start ), length_( length ),
98             foreColor_ ( fore ), backColor_ ( back ) { };
99 
100         // Accessors
101         int start() const { return start_; }
102         int length() const { return length_; }
103         const QColor& foreColor() const { return foreColor_; }
104         const QColor& backColor() const { return backColor_; }
105 
106       private:
107         int start_;
108         int length_;
109         QColor foreColor_;
110         QColor backColor_;
111     };
112     QList<Chunk> list;
113     QColor backColor_;
114 };
115 
116 
117 // Utility class representing a buffer for number entered on the keyboard
118 // The buffer keep at most 7 digits, and reset itself after a timeout.
119 class DigitsBuffer : public QObject
120 {
121   Q_OBJECT
122 
123   public:
124     DigitsBuffer();
125 
126     // Reset the buffer.
127     void reset();
128     // Add a single digit to the buffer (discarded if it's not a digit),
129     // the timeout timer is reset.
130     void add( char character );
131     // Get the content of the buffer (0 if empty) and reset it.
132     int content();
133 
134   protected:
135     void timerEvent( QTimerEvent* event );
136 
137   private:
138     // Duration of the timeout in milliseconds.
139     static const int timeout_;
140 
141     QString digits_;
142 
143     QBasicTimer timer_;
144 };
145 
146 class Overview;
147 
148 // Base class representing the log view widget.
149 // It can be either the top (full) or bottom (filtered) view.
150 class AbstractLogView :
151     public QAbstractScrollArea, public SearchableWidgetInterface
152 {
153   Q_OBJECT
154 
155   public:
156     // Constructor of the widget, the data set is passed.
157     // The caller retains ownership of the data set.
158     // The pointer to the QFP is used for colouring and QuickFind searches
159     AbstractLogView( const AbstractLogData* newLogData,
160             const QuickFindPattern* const quickFind, QWidget* parent=0 );
161     ~AbstractLogView();
162 
163     // Refresh the widget when the data set has changed.
164     void updateData();
165     // Instructs the widget to update it's content geometry,
166     // used when the font is changed.
167     void updateDisplaySize();
168     // Return the line number of the top line of the view
169     int getTopLine() const;
170     // Return the text of the current selection.
171     QString getSelection() const;
172     // Instructs the widget to select the whole text.
173     void selectAll();
174 
175   protected:
176     void mousePressEvent( QMouseEvent* mouseEvent );
177     void mouseMoveEvent( QMouseEvent* mouseEvent );
178     void mouseReleaseEvent( QMouseEvent* );
179     void mouseDoubleClickEvent( QMouseEvent* mouseEvent );
180     void timerEvent( QTimerEvent* timerEvent );
181     void changeEvent( QEvent* changeEvent );
182     void paintEvent( QPaintEvent* paintEvent );
183     void resizeEvent( QResizeEvent* resizeEvent );
184     void scrollContentsBy( int dx, int dy );
185     void keyPressEvent( QKeyEvent* keyEvent );
186     void wheelEvent( QWheelEvent* wheelEvent );
187 
188     // Must be implemented to return wether the line number is
189     // a match, a mark or just a normal line (used for coloured bullets)
190     enum LineType { Normal, Marked, Match };
191     virtual LineType lineType( int lineNumber ) const = 0;
192 
193     // Line number to display for line at the given index
194     virtual qint64 displayLineNumber( int lineNumber ) const;
195     virtual qint64 maxDisplayLineNumber() const;
196 
197     // Get the overview associated with this view, or NULL if there is none
198     Overview* getOverview() const { return overview_; }
199     // Set the Overview and OverviewWidget
200     void setOverview( Overview* overview, OverviewWidget* overview_widget );
201 
202   signals:
203     // Sent when a new line has been selected by the user.
204     void newSelection(int line);
205     // Sent up to the MainWindow to disable the follow mode
206     void followDisabled();
207     // Sent when the view wants the QuickFind widget pattern to change.
208     void changeQuickFind( const QString& newPattern,
209             QuickFindMux::QFDirection newDirection );
210     // Sent up when the current line number is updated
211     void updateLineNumber( int line );
212     // Sent up when quickFind wants to show a message to the user.
213     void notifyQuickFind( const QFNotification& message );
214     // Sent up when quickFind wants to clear the notification.
215     void clearQuickFindNotification();
216     // Sent when the view ask for a line to be marked
217     // (click in the left margin).
218     void markLine( qint64 line );
219     // Sent up when the user wants to add the selection to the search
220     void addToSearch( const QString& selection );
221     // Sent up when the mouse is hovered over a line's margin
222     void mouseHoveredOverLine( qint64 line );
223     // Sent up when the mouse leaves a line's margin
224     void mouseLeftHoveringZone();
225     // Sent up for view initiated quickfind searches
226     void searchNext();
227     void searchPrevious();
228     // Sent up when the user has moved within the view
229     void activity();
230 
231   public slots:
232     // Makes the widget select and display the passed line.
233     // Scrolling as necessary
234     void selectAndDisplayLine( int line );
235 
236     // Use the current QFP to go and select the next match.
237     virtual void searchForward();
238     // Use the current QFP to go and select the previous match.
239     virtual void searchBackward();
240 
241     // Use the current QFP to go and select the next match (incremental)
242     virtual void incrementallySearchForward();
243     // Use the current QFP to go and select the previous match (incremental)
244     virtual void incrementallySearchBackward();
245     // Stop the current incremental search (typically when user press return)
246     virtual void incrementalSearchStop();
247     // Abort the current incremental search (typically when user press esc)
248     virtual void incrementalSearchAbort();
249 
250     // Signals the follow mode has been enabled.
251     void followSet( bool checked );
252 
253     // Signal the on/off status of the overview has been changed.
254     void refreshOverview();
255 
256     // Make the view jump to the specified line, regardless of weither it
257     // is on the screen or not.
258     // (does NOT emit followDisabled() )
259     void jumpToLine( int line );
260 
261     // Configure the setting of whether to show line number margin
262     void setLineNumbersVisible( bool lineNumbersVisible );
263 
264   private slots:
265     void handlePatternUpdated();
266     void addToSearch();
267     void findNextSelected();
268     void findPreviousSelected();
269     void copy();
270 
271   private:
272     // Constants
273     static const int OVERVIEW_WIDTH;
274 
275     // Width of the bullet zone, including decoration
276     int bulletZoneWidthPx_;
277 
278     // Total size of all margins and decorations in pixels
279     int leftMarginPx_;
280 
281     // Number of digits to display in line numbers
282     int nbDigitsInLineNumber_;
283 
284     // Digits buffer (for numeric keyboard entry)
285     DigitsBuffer digitsBuffer_;
286 
287     // Follow mode
288     bool followMode_;
289 
290     // Whether to show line numbers or not
291     bool lineNumbersVisible_;
292 
293     // Pointer to the CrawlerWidget's data set
294     const AbstractLogData* logData;
295 
296     // Pointer to the Overview object
297     Overview* overview_;
298 
299     // Pointer to the OverviewWidget, this class doesn't own it,
300     // but is responsible for displaying it (for purely aesthetic
301     // reasons).
302     OverviewWidget* overviewWidget_;
303 
304     bool selectionStarted_;
305     // Start of the selection (characters)
306     QPoint selectionStartPos_;
307     // Current end of the selection (characters)
308     QPoint selectionCurrentEndPos_;
309     QBasicTimer autoScrollTimer_;
310 
311     // Hovering state
312     // Last line that has been hoovered on, -1 if none
313     qint64 lastHoveredLine_;
314 
315     // Marks (left margin click)
316     bool markingClickInitiated_;
317     qint64 markingClickLine_;
318 
319     Selection selection_;
320     qint64 firstLine;
321     qint64 lastLine;
322     int firstCol;
323 
324     // Text handling
325     int charWidth_;
326     int charHeight_;
327 
328     // Popup menu
329     QMenu* popupMenu_;
330     QAction* copyAction_;
331     QAction* findNextAction_;
332     QAction* findPreviousAction_;
333     QAction* addToSearchAction_;
334 
335     // Pointer to the CrawlerWidget's QFP object
336     const QuickFindPattern* const quickFindPattern_;
337     // Our own QuickFind object
338     QuickFind quickFind_;
339 
340 #ifdef GLOGG_PERF_MEASURE_FPS
341     // Performance measurement
342     PerfCounter perfCounter_;
343 #endif
344 
345     int getNbVisibleLines() const;
346     int getNbVisibleCols() const;
347     QPoint convertCoordToFilePos( const QPoint& pos ) const;
348     int convertCoordToLine( int yPos ) const;
349     int convertCoordToColumn( int xPos ) const;
350     void displayLine( int line );
351     void moveSelection( int y );
352     void jumpToStartOfLine();
353     void jumpToEndOfLine();
354     void jumpToRightOfScreen();
355     void jumpToTop();
356     void jumpToBottom();
357     void selectWordAtPosition( const QPoint& pos );
358 
359     void createMenu();
360 
361     void considerMouseHovering( int x_pos, int y_pos );
362 
363     // Search functions (for n/N)
364     void searchUsingFunction ( qint64 (QuickFind::*search_function)() );
365 
366     // Utils functions
367     bool isCharWord( char c );
368     void updateGlobalSelection();
369 };
370 
371 #endif
372