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