1 /** 2 * UGENE - Integrated Bioinformatics Tools. 3 * Copyright (C) 2008-2021 UniPro <ugene@unipro.ru> 4 * http://ugene.net 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 * MA 02110-1301, USA. 20 */ 21 22 #ifndef _U2_GSEQUENCE_LINE_VIEW_H_ 23 #define _U2_GSEQUENCE_LINE_VIEW_H_ 24 25 #include <QFlag> 26 #include <QFocusEvent> 27 #include <QHBoxLayout> 28 #include <QMenu> 29 #include <QMouseEvent> 30 #include <QPainter> 31 #include <QPixmap> 32 #include <QScopedPointer> 33 #include <QToolButton> 34 #include <QWheelEvent> 35 #include <QWidget> 36 37 #include <U2Core/U2Region.h> 38 39 #include <U2Gui/SelectionModificationHelper.h> 40 #include <U2Gui/WidgetWithLocalToolbar.h> 41 42 namespace U2 { 43 44 class DNASequenceSelection; 45 class LRegionsSelection; 46 class GScrollBar; 47 class GSequenceLineViewRenderArea; 48 class GObject; 49 class GObjectViewOpConstraints; 50 class SequenceObjectContext; 51 class U2SequenceObject; 52 53 enum GSLV_UpdateFlag { 54 GSLV_UF_NeedCompleteRedraw = 1 << 0, 55 GSLV_UF_ViewResized = 1 << 1, 56 GSLV_UF_VisibleRangeChanged = 1 << 2, 57 GSLV_UF_SelectionChanged = 1 << 3, 58 GSLV_UF_FocusChanged = 1 << 4, 59 GSLV_UF_FrameChanged = 1 << 5, 60 GSLV_UF_AnnotationsChanged = 1 << 6 61 }; 62 63 enum GSLV_FeatureFlag { 64 /** If set the view can show any requested custom range. Same with Zooming. */ 65 GSLV_FF_SupportsCustomRange = 0x1 66 }; 67 68 typedef QFlags<GSLV_UpdateFlag> GSLV_UpdateFlags; 69 typedef QFlags<GSLV_FeatureFlag> GSLV_FeatureFlags; 70 71 // single-line sequence view 72 class U2VIEW_EXPORT GSequenceLineView : public WidgetWithLocalToolbar { 73 Q_OBJECT 74 public: 75 GSequenceLineView(QWidget *p, SequenceObjectContext *ctx); 76 getVisibleRange()77 const U2Region &getVisibleRange() const { 78 return visibleRange; 79 } 80 getSequenceContext()81 SequenceObjectContext *getSequenceContext() const { 82 return ctx; 83 } 84 getRenderArea()85 GSequenceLineViewRenderArea *getRenderArea() const { 86 return renderArea; 87 } 88 getLastPressPos()89 qint64 getLastPressPos() const { 90 return lastPressPos; 91 } 92 93 virtual void setStartPos(qint64 pos); 94 95 virtual void setCenterPos(qint64 pos); 96 getSequenceLength()97 qint64 getSequenceLength() const { 98 return seqLen; 99 } 100 addUpdateFlags(GSLV_UpdateFlags newFlags)101 virtual void addUpdateFlags(GSLV_UpdateFlags newFlags) { 102 lastUpdateFlags |= newFlags; 103 } 104 clearUpdateFlags()105 virtual void clearUpdateFlags() { 106 lastUpdateFlags = 0; 107 } 108 getUpdateFlags()109 GSLV_UpdateFlags getUpdateFlags() const { 110 return lastUpdateFlags; 111 } 112 113 virtual void setFrameView(GSequenceLineView *frameView); 114 getFrameView()115 virtual GSequenceLineView *getFrameView() const { 116 return frameView; 117 } 118 119 virtual void setCoherentRangeView(GSequenceLineView *rangeView); 120 getConherentRangeView()121 virtual GSequenceLineView *getConherentRangeView() const { 122 return coherentRangeView; 123 } 124 125 // [0..seqLen) 126 virtual void setVisibleRange(const U2Region ®, bool signal = true); 127 getZoomInAction()128 virtual QAction *getZoomInAction() const { 129 return coherentRangeView == nullptr ? nullptr : coherentRangeView->getZoomInAction(); 130 } 131 getZoomOutAction()132 virtual QAction *getZoomOutAction() const { 133 return coherentRangeView == nullptr ? nullptr : coherentRangeView->getZoomOutAction(); 134 } 135 getZoomToSelectionAction()136 virtual QAction *getZoomToSelectionAction() const { 137 return coherentRangeView == nullptr ? nullptr : coherentRangeView->getZoomToSelectionAction(); 138 } 139 getZoomToSequenceAction()140 virtual QAction *getZoomToSequenceAction() const { 141 return coherentRangeView == nullptr ? nullptr : coherentRangeView->getZoomToSequenceAction(); 142 } 143 144 virtual U2SequenceObject *getSequenceObject() const; 145 buildPopupMenu(QMenu & m)146 virtual void buildPopupMenu(QMenu &m) { 147 Q_UNUSED(m); 148 } 149 isWidgetOnlyObject(GObject * o)150 virtual bool isWidgetOnlyObject(GObject *o) const { 151 Q_UNUSED(o); 152 return false; 153 } 154 155 virtual bool eventFilter(QObject *watched, QEvent *event); 156 157 signals: 158 void si_visibleRangeChanged(); 159 void si_centerPosition(qint64 pos); 160 161 protected: 162 void resizeEvent(QResizeEvent *e); 163 void mousePressEvent(QMouseEvent *me); 164 void mouseReleaseEvent(QMouseEvent *me); 165 void mouseMoveEvent(QMouseEvent *me); 166 void mouseDoubleClickEvent(QMouseEvent *me); 167 void wheelEvent(QWheelEvent *we); 168 void focusInEvent(QFocusEvent *fe); 169 void focusOutEvent(QFocusEvent *fe); 170 void keyPressEvent(QKeyEvent *e); 171 virtual void onVisibleRangeChanged(bool signal = true); 172 173 public slots: sl_centerPosition(int pos)174 void sl_centerPosition(int pos) { 175 setCenterPos(pos); 176 } 177 178 protected slots: 179 virtual void sl_onScrollBarMoved(int pos); 180 virtual void sl_onDNASelectionChanged(LRegionsSelection *thiz, const QVector<U2Region> &added, const QVector<U2Region> &removed); 181 virtual void sl_sequenceChanged(); 182 void sl_onFrameRangeChanged(); 183 void sl_onCoherentRangeViewRangeChanged(); 184 void sl_onLocalCenteringRequest(qint64 pos); 185 void completeUpdate(); 186 187 protected: 188 QPoint toRenderAreaPoint(const QPoint &p) const; 189 190 /** 191 * Returns a valid Y-range to react to mouse events for the given 'pos'. 192 * Normally this is a whole vertical range of the widget area, but in some widgets, like DetView it may be a limited space. 193 * Reason for this is that DetView is a 'multi-line', while all methods inside GSequenceLineView are 'single-line'. 194 * Uses 'renderArea' local coordinates. 195 */ 196 virtual U2Region getCapturingRenderAreaYRegionForPos(qint64 pos) const; 197 198 virtual void updateScrollBar(); 199 virtual void setSelection(const U2Region &r); 200 void addSelection(const U2Region &r); 201 virtual void updateCursorShapeOnMouseMove(const QPoint &p); 202 virtual void moveBorder(const QPoint &p); 203 virtual void pack(); 204 virtual qint64 getSingleStep() const; 205 virtual qint64 getPageStep() const; 206 void autoScrolling(const QPoint &areaPoint); 207 virtual void resizeSelection(const QPoint &areaPoint); 208 void cancelSelectionResizing(); 209 void changeSelectionOnScrollbarMoving(const U2Region &newSelection); 210 void changeSelection(QVector<U2Region> ®ions, const U2Region &newSelection); 211 212 SequenceObjectContext *ctx; 213 GSequenceLineViewRenderArea *renderArea; 214 U2Region visibleRange; 215 GScrollBar *scrollBar; 216 qint64 lastPressPos; 217 U2Region resizableRegion; 218 QList<U2Region> overlappedRegions; 219 qint64 seqLen; 220 GSLV_UpdateFlags lastUpdateFlags; 221 GSLV_FeatureFlags featureFlags; 222 GSequenceLineView *frameView; 223 GSequenceLineView *coherentRangeView; 224 double coefScrollBarMapping; 225 226 // special flag setup by child classes that tells to this class do or skip 227 // any changes to selection on mouse ops 228 bool ignoreMouseSelectionEvents; 229 bool singleBaseSelection; 230 bool isSelectionResizing; 231 }; 232 233 class U2VIEW_EXPORT GSequenceLineViewRenderArea : public QWidget { 234 Q_OBJECT 235 public: 236 GSequenceLineViewRenderArea(GSequenceLineView *p); 237 238 /** Returns in-sequence base index by the current on-screen coordinate. */ 239 virtual qint64 coordToPos(const QPoint &coord) const; 240 241 /** Returns a minimal on-screen X coordinate of the given sequence position. */ 242 virtual int posToCoord(qint64 pos, bool useVirtualSpace = false) const; 243 244 /** Returns number of pixels per-base. */ 245 virtual double getCurrentScale() const; 246 247 /** Returns width in pixels required to draw a single text character using sequenceFont. */ getCharWidth()248 int getCharWidth() const { 249 return charWidth; 250 } 251 252 protected: 253 void paintEvent(QPaintEvent *e) override; 254 255 virtual void drawAll(QPaintDevice *pd) = 0; 256 void drawFrame(QPainter &p); 257 virtual void drawFocus(QPainter &p); 258 259 void updateFontMetrics(); 260 261 /** Returns a cached pixmap used to render the whole area. */ getCachedPixmap()262 QPixmap *getCachedPixmap() const { 263 return cachedView.data(); 264 } 265 266 GSequenceLineView *view; 267 QScopedPointer<QPixmap> cachedView; 268 269 //! VIEW_RENDERER_REFACTORING: the following parameters should be stored only in renderer (until they cannot be modified in view). 270 //! Currently they are doubled in SequenceViewRenderer class. 271 // per char and per line metrics 272 QFont sequenceFont; 273 QFont smallSequenceFont; 274 QFont rulerFont; 275 276 int charWidth = 0; 277 int smallCharWidth = 0; 278 279 int lineHeight = 0; 280 int yCharOffset = 0; 281 int xCharOffset = 0; 282 }; 283 284 } // namespace U2 285 286 #endif 287