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