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