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