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