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 229 public slots: 230 // Makes the widget select and display the passed line. 231 // Scrolling as necessary 232 void selectAndDisplayLine( int line ); 233 234 // Use the current QFP to go and select the next match. 235 virtual void searchForward(); 236 // Use the current QFP to go and select the previous match. 237 virtual void searchBackward(); 238 239 // Use the current QFP to go and select the next match (incremental) 240 virtual void incrementallySearchForward(); 241 // Use the current QFP to go and select the previous match (incremental) 242 virtual void incrementallySearchBackward(); 243 // Stop the current incremental search (typically when user press return) 244 virtual void incrementalSearchStop(); 245 // Abort the current incremental search (typically when user press esc) 246 virtual void incrementalSearchAbort(); 247 248 // Signals the follow mode has been enabled. 249 void followSet( bool checked ); 250 251 // Signal the on/off status of the overview has been changed. 252 void refreshOverview(); 253 254 // Make the view jump to the specified line, regardless of weither it 255 // is on the screen or not. 256 // (does NOT emit followDisabled() ) 257 void jumpToLine( int line ); 258 259 // Configure the setting of whether to show line number margin 260 void setLineNumbersVisible( bool lineNumbersVisible ); 261 262 private slots: 263 void handlePatternUpdated(); 264 void addToSearch(); 265 void findNextSelected(); 266 void findPreviousSelected(); 267 void copy(); 268 269 private: 270 // Constants 271 static const int OVERVIEW_WIDTH; 272 273 // Width of the bullet zone, including decoration 274 int bulletZoneWidthPx_; 275 276 // Total size of all margins and decorations in pixels 277 int leftMarginPx_; 278 279 // Number of digits to display in line numbers 280 int nbDigitsInLineNumber_; 281 282 // Digits buffer (for numeric keyboard entry) 283 DigitsBuffer digitsBuffer_; 284 285 // Follow mode 286 bool followMode_; 287 288 // Whether to show line numbers or not 289 bool lineNumbersVisible_; 290 291 // Pointer to the CrawlerWidget's data set 292 const AbstractLogData* logData; 293 294 // Pointer to the Overview object 295 Overview* overview_; 296 297 // Pointer to the OverviewWidget, this class doesn't own it, 298 // but is responsible for displaying it (for purely aesthetic 299 // reasons). 300 OverviewWidget* overviewWidget_; 301 302 bool selectionStarted_; 303 // Start of the selection (characters) 304 QPoint selectionStartPos_; 305 // Current end of the selection (characters) 306 QPoint selectionCurrentEndPos_; 307 QBasicTimer autoScrollTimer_; 308 309 // Hovering state 310 // Last line that has been hoovered on, -1 if none 311 qint64 lastHoveredLine_; 312 313 // Marks (left margin click) 314 bool markingClickInitiated_; 315 qint64 markingClickLine_; 316 317 Selection selection_; 318 qint64 firstLine; 319 qint64 lastLine; 320 int firstCol; 321 322 // Text handling 323 int charWidth_; 324 int charHeight_; 325 326 // Popup menu 327 QMenu* popupMenu_; 328 QAction* copyAction_; 329 QAction* findNextAction_; 330 QAction* findPreviousAction_; 331 QAction* addToSearchAction_; 332 333 // Pointer to the CrawlerWidget's QFP object 334 const QuickFindPattern* const quickFindPattern_; 335 // Our own QuickFind object 336 QuickFind quickFind_; 337 338 #ifdef GLOGG_PERF_MEASURE_FPS 339 // Performance measurement 340 PerfCounter perfCounter_; 341 #endif 342 343 int getNbVisibleLines() const; 344 int getNbVisibleCols() const; 345 QPoint convertCoordToFilePos( const QPoint& pos ) const; 346 int convertCoordToLine( int yPos ) const; 347 int convertCoordToColumn( int xPos ) const; 348 void displayLine( int line ); 349 void moveSelection( int y ); 350 void jumpToStartOfLine(); 351 void jumpToEndOfLine(); 352 void jumpToRightOfScreen(); 353 void jumpToTop(); 354 void jumpToBottom(); 355 void selectWordAtPosition( const QPoint& pos ); 356 357 void createMenu(); 358 359 void considerMouseHovering( int x_pos, int y_pos ); 360 361 // Search functions (for n/N) 362 void searchUsingFunction ( qint64 (QuickFind::*search_function)() ); 363 364 // Utils functions 365 bool isCharWord( char c ); 366 void updateGlobalSelection(); 367 }; 368 369 #endif 370