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_MA_EDITOR_SEQUENCE_AREA_ 23 #define _U2_MA_EDITOR_SEQUENCE_AREA_ 24 25 #include <QColor> 26 #include <QPainter> 27 #include <QTimer> 28 #include <QWidget> 29 30 #include <U2Core/MultipleAlignment.h> 31 #include <U2Core/U2Region.h> 32 33 #include <U2Gui/GScrollBar.h> 34 #include <U2Gui/SelectionModificationHelper.h> 35 36 #include "../MsaEditorUserModStepController.h" 37 38 class QRubberBand; 39 40 namespace U2 { 41 42 #define SETTINGS_ROOT QString("msaeditor/") 43 #define SETTINGS_COLOR_NUCL "color_nucl" 44 #define SETTINGS_COLOR_AMINO "color_amino" 45 #define SETTINGS_COLOR_RAW "color_raw" 46 #define SETTINGS_HIGHLIGHT_NUCL "highlight_nucl" 47 #define SETTINGS_HIGHLIGHT_AMINO "highlight_amino" 48 #define SETTINGS_HIGHLIGHT_RAW "highlight_raw" 49 #define SETTINGS_COPY_FORMATTED "copyformatted" 50 51 class GScrollBar; 52 class MaEditor; 53 class MaEditorWgt; 54 class SequenceAreaRenderer; 55 56 class MaModificationInfo; 57 class MsaColorScheme; 58 class MaEditorSelection; 59 class MsaColorSchemeFactory; 60 class MsaHighlightingScheme; 61 class MsaHighlightingSchemeFactory; 62 63 class U2VIEW_EXPORT MaEditorSequenceArea : public QWidget { 64 Q_OBJECT 65 friend class SequenceAreaRenderer; 66 67 public: 68 MaEditorSequenceArea(MaEditorWgt *ui, GScrollBar *hb, GScrollBar *vb); 69 virtual ~MaEditorSequenceArea(); 70 71 MaEditor *getEditor() const; 72 73 QSize getCanvasSize(const QList<int> &seqIdx, const U2Region ®ion) const; 74 75 int getFirstVisibleBase() const; 76 int getLastVisibleBase(bool countClipped) const; 77 int getNumVisibleBases() const; 78 79 /* 80 * Returns count of sequences that are drawn on the widget by taking into account 81 * collapsed rows. 82 */ 83 int getViewRowCount() const; 84 85 int getRowIndex(const int num) const; 86 87 bool isAlignmentEmpty() const; 88 89 bool isPosInRange(int position) const; 90 bool isSeqInRange(int rowNumber) const; 91 bool isInRange(const QPoint &point) const; 92 93 /** Returns true if the given rectangle within visible [rows x columns] grid range. */ 94 bool isInRange(const QRect &rect) const; 95 96 QPoint boundWithVisibleRange(const QPoint &point) const; 97 98 /** Returns rectangle bounded with the visible width/height range. */ 99 QRect boundWithVisibleRange(const QRect &rect) const; 100 101 bool isVisible(const QPoint &p, bool countClipped) const; 102 bool isPositionVisible(int pos, bool countClipped) const; 103 bool isRowVisible(int rowNumber, bool countClipped) const; 104 105 /** 106 * Sets new selection from the given rect. 107 * Bounds the rect with the visible area to ensure rect is within view bounds. 108 * This method does not update selection directly but calls 'setSelection()' with a new selection instance. 109 */ 110 void setSelectionRect(const QRect &newSelectionRect); 111 112 virtual void moveSelection(int dx, int dy, bool allowSelectionResize = false); 113 adjustReferenceLength(U2OpStatus & os)114 virtual void adjustReferenceLength(U2OpStatus &os) { 115 Q_UNUSED(os); 116 } 117 118 /** Returns list of selected MA row indexes. */ 119 QList<int> getSelectedMaRowIndexes() const; 120 121 /** Returns MA row index of the top-most selected view row or -1 if selection is empty. */ 122 int getTopSelectedMaRow() const; 123 124 QString getCopyFormattedAlgorithmId() const; 125 126 virtual void deleteCurrentSelection(); 127 128 /** 129 * Shifts currently selected region to @shift. 130 * If @shift > 0, the region is moved to the right and "true" is returned. 131 * If @shift <= 0, the region is moved to the left only for the available number 132 * of columns (i.e. the columns with gaps). The returned value specifies 133 * whether the region was actually moved in this case. 134 */ 135 bool shiftSelectedRegion(int shift); 136 137 void centerPos(const QPoint &point); 138 void centerPos(int pos); 139 140 QFont getFont() const; 141 142 void onVisibleRangeChanged(); 143 144 bool isAlignmentLocked() const; 145 146 void drawVisibleContent(QPainter &painter); 147 148 bool drawContent(QPainter &painter, const U2Region &columns, const QList<int> &maRows, int xStart, int yStart); 149 150 MsaColorScheme *getCurrentColorScheme() const; 151 MsaHighlightingScheme *getCurrentHighlightingScheme() const; 152 bool getUseDotsCheckedState() const; 153 154 QAction *getReplaceCharacterAction() const; 155 156 public slots: 157 void sl_changeColorSchemeOutside(const QString &id); 158 void sl_delCurrentSelection(); 159 void sl_changeCopyFormat(const QString &formatId); 160 161 protected slots: 162 void sl_changeColorScheme(); 163 void sl_fillCurrentSelectionWithGaps(); 164 165 void sl_alignmentChanged(const MultipleAlignment &ma, const MaModificationInfo &modInfo); 166 167 void sl_completeUpdate(); 168 void sl_completeRedraw(); 169 170 virtual void sl_updateActions() = 0; 171 172 void sl_triggerUseDots(); 173 void sl_useDots(); 174 175 void sl_registerCustomColorSchemes(); 176 void sl_colorSchemeFactoryUpdated(); 177 void sl_setDefaultColorScheme(); 178 void sl_changeHighlightScheme(); 179 180 void sl_replaceSelectedCharacter(); 181 void sl_changeSelectionColor(); 182 virtual void sl_modelChanged(); 183 184 private slots: 185 void sl_hScrollBarActionPerformed(); 186 void sl_onSelectionChanged(const MaEditorSelection &newSelection, const MaEditorSelection &oldSelection); 187 188 private: 189 void setBorderCursor(const QPoint &p); 190 void moveBorder(const QPoint &p); 191 192 int shiftRegion(int shift); 193 QList<U2MsaGap> findRemovableGapColumns(int &shift); 194 QList<U2MsaGap> findCommonGapColumns(int &numOfColumns); 195 U2MsaGap addTrailingGapColumns(int count); 196 QList<U2MsaGap> findRestorableGapColumns(const int shift); 197 198 /** 199 * Restores view selection using cached MA selection. 200 * If the original selection can't be restored moves the selection to the top-left corner of the original. 201 */ 202 void restoreViewSelectionFromMaSelection(); 203 204 signals: 205 void si_selectionChanged(const QStringList &selectedRows); 206 void si_highlightingChanged(); 207 void si_visibleRangeChanged(QStringList visibleSequences, int reqHeight); 208 void si_visibleRangeChanged(); 209 void si_startMaChanging(); 210 void si_stopMaChanging(bool msaUpdated); 211 void si_copyFormattedChanging(bool enabled); 212 void si_collapsingModeChanged(); 213 214 protected: 215 void resizeEvent(QResizeEvent *event); 216 void paintEvent(QPaintEvent *event); 217 void wheelEvent(QWheelEvent *event); 218 void mousePressEvent(QMouseEvent *event); 219 void mouseReleaseEvent(QMouseEvent *event); 220 void mouseMoveEvent(QMouseEvent *event); 221 222 void keyPressEvent(QKeyEvent *); 223 void keyReleaseEvent(QKeyEvent *); 224 225 virtual void initRenderer() = 0; 226 virtual void drawBackground(QPainter &p); 227 228 /** 229 * Inserts a region consisting of gaps only before the selection. The inserted region width 230 * is specified by @countOfGaps parameter if 0 < @countOfGaps, its height is equal to the 231 * current selection's height. 232 * 233 * If there is no selection in MSA then the method does nothing. 234 * 235 * If -1 == @countOfGaps then the inserting region width is equal to 236 * the selection's width. If 1 > @countOfGaps and -1 != @countOfGaps then nothing happens. 237 */ 238 void insertGapsBeforeSelection(int countOfGaps = -1); 239 240 /** 241 * Reverse operation for @insertGapsBeforeSelection( ), 242 * removes the region preceding the selection if it consists of gaps only. 243 * 244 * If there is no selection in MSA then the method does nothing. 245 * 246 * @countOfGaps specifies maximum width of the removed region. 247 * If -1 == @countOfGaps then count of removed gap columns is equal to 248 * the selection width. If 1 > @countOfGaps and -1 != @countOfGaps then nothing happens. 249 */ 250 void removeGapsPrecedingSelection(int countOfGaps = -1); 251 252 /* 253 * Interrupts the tracking of MSA modifications caused by a region shifting, 254 * also stops shifting. The method is used to keep consistence of undo/redo stack. 255 */ 256 void cancelShiftTracking(); 257 258 void drawAll(); 259 260 void updateColorAndHighlightSchemes(); 261 262 void initColorSchemes(MsaColorSchemeFactory *defaultColorSchemeFactory); 263 264 void registerCommonColorSchemes(); 265 266 void initHighlightSchemes(MsaHighlightingSchemeFactory *hsf); 267 268 MsaColorSchemeFactory *getDefaultColorSchemeFactory() const; 269 MsaHighlightingSchemeFactory *getDefaultHighlightingSchemeFactory() const; 270 271 virtual void getColorAndHighlightingIds(QString &csid, QString &hsid); 272 void applyColorScheme(const QString &id); 273 274 void processCharacterInEditMode(QKeyEvent *e); 275 void processCharacterInEditMode(char newCharacter); 276 void replaceChar(char newCharacter); insertChar(char)277 virtual void insertChar(char) { 278 } 279 virtual bool isCharacterAcceptable(const QString &text) const; 280 virtual const QString &getInacceptableCharacterErrorMessage() const; 281 282 void deleteOldCustomSchemes(); 283 284 /* 285 * Update collapse model on alignment modification. 286 * Note, that we have collapse model regardless if collapsing mode is enabled or not. 287 * In the disabled collapsing mode the collapse model is 'flat': 1 view row = 1 MA row. 288 */ 289 virtual void updateCollapseModel(const MaModificationInfo &maModificationInfo); 290 291 public: 292 enum MaMode { 293 ViewMode, 294 ReplaceCharMode, 295 InsertCharMode 296 }; 297 298 /** Returns current mode of the sequence area: viewing or editing. */ 299 MaMode getMode() const; 300 301 /** Swithes sequence area into the ViewMode. */ 302 void exitFromEditCharacterMode(); 303 304 protected: 305 MaEditor *const editor; 306 MaEditorWgt *const ui; 307 308 MsaColorScheme *colorScheme; 309 MsaHighlightingScheme *highlightingScheme; 310 311 GScrollBar *shBar; 312 GScrollBar *svBar; 313 QRubberBand *rubberBand; 314 bool showRubberBandOnSelection; 315 316 SequenceAreaRenderer *renderer; 317 318 QPixmap *cachedView; 319 bool completeRedraw; 320 321 MaMode maMode; 322 QTimer editModeAnimationTimer; 323 QColor selectionColor; 324 325 bool editingEnabled; 326 bool shifting; 327 bool selecting; 328 Qt::MouseButton prevPressedButton; 329 330 /* Last mouse press point. Global window coordinates. */ 331 QPoint mousePressEventPoint; 332 /* 333 * Last mouse press point in view rows/columns coordinates. 334 * May be out of range if clicked out of the view/rows range. 335 */ 336 QPoint mousePressViewPos; 337 338 /** Selected MA row ids within the current view selection. */ 339 QList<qint64> selectedMaRowIds; 340 341 /** Selected MA row columns within the current view selection. */ 342 U2Region selectedColumns; 343 344 int maVersionBeforeShifting; 345 SelectionModificationHelper::MovableSide movableBorder; 346 347 QList<U2MsaGap> ctrlModeGapModel; 348 qint64 lengthOnMousePress; 349 350 QAction *replaceCharacterAction; 351 QAction *fillWithGapsinsSymAction; 352 353 public: 354 QAction *useDotsAction; 355 356 QList<QAction *> colorSchemeMenuActions; 357 QList<QAction *> customColorSchemeMenuActions; 358 QList<QAction *> highlightingSchemeMenuActions; 359 360 protected: 361 // The member is intended for tracking MSA changes (handling U2UseCommonUserModStep objects) 362 // that does not fit into one method, e.g. shifting MSA region with mouse. 363 // If the changing action fits within one method it's recommended using 364 // the U2UseCommonUserModStep object explicitly. 365 MsaEditorUserModStepController changeTracker; 366 367 static const QChar emDash; 368 }; 369 370 } // namespace U2 371 372 #endif // _U2_MA_EDITOR_SEQUENCE_AREA_ 373