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