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 #include "PanView.h"
23 
24 #include <QDialog>
25 #include <QGridLayout>
26 #include <QPainter>
27 #include <QTextEdit>
28 
29 #include <U2Core/AnnotationModification.h>
30 #include <U2Core/AnnotationSettings.h>
31 #include <U2Core/AnnotationTableObject.h>
32 #include <U2Core/AppContext.h>
33 #include <U2Core/DNAAlphabet.h>
34 #include <U2Core/DNASequenceObject.h>
35 #include <U2Core/DNASequenceSelection.h>
36 #include <U2Core/Log.h>
37 #include <U2Core/SelectionModel.h>
38 #include <U2Core/Timer.h>
39 #include <U2Core/U2SafePoints.h>
40 
41 #include <U2Gui/GScrollBar.h>
42 
43 #include "ADVSequenceObjectContext.h"
44 #include "ADVSingleSequenceWidget.h"
45 #include "PanViewRows.h"
46 
47 namespace U2 {
48 
PanViewLinesSettings()49 PanViewLinesSettings::PanViewLinesSettings()
50     : numLines(0),
51       rowLinesOffset(0),
52       showMainRuler(true),
53       showCustomRulers(true) {
54 }
55 
getRowLine(int i) const56 int PanViewLinesSettings::getRowLine(int i) const {
57     int line = getFirstRowLine() - i + rowLinesOffset;
58     if (line < 0 || line > getFirstRowLine()) {
59         return -1;
60     }
61     return line;
62 }
63 
getSelectionLine() const64 int PanViewLinesSettings::getSelectionLine() const {
65     return numLines - 1;
66 }
67 
getRulerLine() const68 int PanViewLinesSettings::getRulerLine() const {
69     SAFE_POINT(showMainRuler, "Trying to get ruler line, but it's not visible", -1);
70     return numLines - 2;
71 }
72 
getCustomRulerLine(int n) const73 int PanViewLinesSettings::getCustomRulerLine(int n) const {
74     SAFE_POINT(showCustomRulers, "Trying to get custom ruler line, but it's not visible", -1);
75     SAFE_POINT(n >= 0 && n < customRulers.count(), "Invalid number of custom ruler", -1);
76 
77     return numLines - (showMainRuler ? 3 : 2) - n;
78 }
79 
getFirstRowLine() const80 int PanViewLinesSettings::getFirstRowLine() const {
81     return numLines - 2 - (showMainRuler ? 1 : 0) - (showCustomRulers ? customRulers.count() : 0);
82 }
83 
getAdditionalLines() const84 int PanViewLinesSettings::getAdditionalLines() const {
85     return 1 + (showMainRuler ? 1 : 0) + (showCustomRulers ? customRulers.size() : 0);
86 }
87 
getNumVisibleRows() const88 int PanViewLinesSettings::getNumVisibleRows() const {
89     return getFirstRowLine() + 1;
90 }
91 
isRowVisible(int row) const92 bool PanViewLinesSettings::isRowVisible(int row) const {
93     return getRowLine(row) >= 0;
94 }
95 
ZoomUseObject()96 PanView::ZoomUseObject::ZoomUseObject()
97     : usingZoom(false), panView(nullptr) {
98 }
99 
ZoomUseObject(PanView * pv)100 PanView::ZoomUseObject::ZoomUseObject(PanView *pv)
101     : usingZoom(false) {
102     setPanView(pv);
103 }
104 
~ZoomUseObject()105 PanView::ZoomUseObject::~ZoomUseObject() {
106     releaseZoom();
107 }
108 
setPanView(PanView * pv)109 void PanView::ZoomUseObject::setPanView(PanView *pv) {
110     releaseZoom();
111 
112     Q_ASSERT(pv);
113     panView = pv;
114 
115     useZoom();
116 }
117 
useZoom()118 void PanView::ZoomUseObject::useZoom() {
119     if (usingZoom || !panView) {
120         return;
121     }
122     usingZoom = true;
123     panView->useZoom();
124 }
125 
releaseZoom()126 void PanView::ZoomUseObject::releaseZoom() {
127     if (!usingZoom || !panView) {
128         return;
129     }
130     usingZoom = false;
131     panView->releaseZoom();
132 }
133 
134 #define MAX_VISIBLE_ROWS_ON_START 10
PanView(QWidget * p,SequenceObjectContext * ctx,const PanViewRenderAreaFactory & renderFactory)135 PanView::PanView(QWidget *p, SequenceObjectContext *ctx, const PanViewRenderAreaFactory &renderFactory)
136     : GSequenceLineViewAnnotated(p, ctx) {
137     rowBar = new QScrollBar(this);
138     setObjectName("pan_view");
139     settings = new PanViewLinesSettings();
140     rowsManager = new PVRowsManager();
141     renderArea = renderFactory.createRenderArea(this);
142     renderArea->setMouseTracking(true);
143 
144     updateNumVisibleRows();
145 
146     visibleRange.length = seqLen;
147     minNuclsPerScreen = qMin(seqLen, qint64(0));
148 
149     zoomUsing = 0;
150 
151     zoomInAction = new QAction(QIcon(":/core/images/zoom_in.png"), tr("Zoom In"), this);
152     zoomInAction->setObjectName("action_zoom_in_" + ctx->getSequenceObject()->getGObjectName());
153     connect(zoomInAction, SIGNAL(triggered()), SLOT(sl_zoomInAction()));
154 
155     zoomOutAction = new QAction(QIcon(":/core/images/zoom_out.png"), tr("Zoom Out"), this);
156     zoomOutAction->setObjectName("action_zoom_out_" + ctx->getSequenceObject()->getGObjectName());
157     connect(zoomOutAction, SIGNAL(triggered()), SLOT(sl_zoomOutAction()));
158 
159     zoomToSelectionAction = new QAction(QIcon(":/core/images/zoom_sel.png"), tr("Zoom to Selection"), this);
160     zoomToSelectionAction->setObjectName("action_zoom_to_selection_" + ctx->getSequenceObject()->getGObjectName());
161     connect(zoomToSelectionAction, SIGNAL(triggered()), SLOT(sl_zoomToSelection()));
162 
163     zoomToSequenceAction = new QAction(QIcon(":/core/images/zoom_whole.png"), tr("Zoom to Whole Sequence"), this);
164     zoomToSequenceAction->setObjectName("action_zoom_to_sequence_" + ctx->getSequenceObject()->getGObjectName());
165     connect(zoomToSequenceAction, SIGNAL(triggered()), SLOT(sl_zoomToSequence()));
166 
167     toggleMainRulerAction = new QAction(tr("Show Main Ruler"), this);
168     toggleMainRulerAction->setObjectName("Show Main Ruler");
169     toggleMainRulerAction->setCheckable(true);
170     toggleMainRulerAction->setChecked(settings->showMainRuler);
171     connect(toggleMainRulerAction, SIGNAL(triggered(bool)), SLOT(sl_toggleMainRulerVisibility(bool)));
172 
173     toggleCustomRulersAction = new QAction(tr("Show Custom Rulers"), this);
174     toggleCustomRulersAction->setObjectName("Show Custom Rulers");
175     toggleCustomRulersAction->setCheckable(true);
176     toggleCustomRulersAction->setChecked(settings->showCustomRulers);
177     toggleCustomRulersAction->setEnabled(!settings->customRulers.isEmpty());
178     connect(toggleCustomRulersAction, SIGNAL(triggered(bool)), SLOT(sl_toggleCustomRulersVisibility(bool)));
179 
180     addActionToLocalToolbar(zoomInAction);
181     addActionToLocalToolbar(zoomOutAction);
182     addActionToLocalToolbar(zoomToSelectionAction);
183     addActionToLocalToolbar(zoomToSequenceAction);
184 
185     syncOffset = 0;
186 
187     // can't move to the GSequenceLineViewAnnotated -> virtual calls does not work in  constructor
188     foreach (AnnotationTableObject *obj, ctx->getAnnotationObjects(true)) {
189         registerAnnotations(obj->getAnnotations());
190     }
191 
192     connect(this, SIGNAL(si_updateRows()), SLOT(sl_updateRows()));
193 
194     updateActions();
195     updateRowBar();
196 
197     settings->numLines = qMin(MAX_VISIBLE_ROWS_ON_START, rowsManager->getNumRows() + settings->getAdditionalLines());
198 
199     resize(width(), getRenderArea()->getRowLineHeight() * settings->numLines);
200 
201     pack();
202 }
203 
pack()204 void PanView::pack() {
205     QGridLayout *layout = new QGridLayout();
206     layout->setMargin(0);
207     layout->setSpacing(0);
208     layout->addWidget(renderArea, 0, 0, 1, 1);
209     layout->addWidget(rowBar, 0, 1, 1, 1);
210     layout->addWidget(scrollBar, 1, 0, 1, 1);
211     setContentLayout(layout);
212 }
213 
~PanView()214 PanView::~PanView() {
215     delete rowsManager;
216 }
217 
registerAnnotations(const QList<Annotation * > & l)218 void PanView::registerAnnotations(const QList<Annotation *> &l) {
219     GTIMER(c1, t1, "PanView::registerAnnotations");
220     AnnotationSettingsRegistry *asr = AppContext::getAnnotationsSettingsRegistry();
221     foreach (Annotation *a, l) {
222         AnnotationSettings *as = asr->getAnnotationSettings(a->getData());
223         if (as->visible) {
224             rowsManager->addAnnotation(a);
225         }
226     }
227     updateRows();
228 }
229 
unregisterAnnotations(const QList<Annotation * > & l)230 void PanView::unregisterAnnotations(const QList<Annotation *> &l) {
231     AnnotationSettingsRegistry *asr = AppContext::getAnnotationsSettingsRegistry();
232     foreach (Annotation *a, l) {
233         AnnotationSettings *as = asr->getAnnotationSettings(a->getData());
234         if (as->visible) {
235             rowsManager->removeAnnotation(a);
236         }
237     }
238     emit si_updateRows();
239 }
240 
updateRows()241 void PanView::updateRows() {
242     PanViewRenderArea *ra = getRenderArea();
243     SAFE_POINT(ra != nullptr, "PanViewRenderArea is NULL", );
244     /*ra->*/ updateNumVisibleRows();
245     int maxSteps = calculateNumRowBarSteps();
246     if (qAbs(rowBar->maximum() - rowBar->minimum()) != maxSteps) {
247         updateRowBar();
248     }
249     updateActions();
250 }
251 
calculateNumRowBarSteps() const252 int PanView::calculateNumRowBarSteps() const {
253     int visibleRows = settings->getNumVisibleRows();
254     int numRows = rowsManager->getNumRows();
255     int res = qMax(0, numRows - visibleRows);
256     return res;
257 }
258 
setNumVisibleRows(int rowNum)259 void PanView::setNumVisibleRows(int rowNum) {
260     settings->numLines = qMin(rowNum, rowsManager->getNumRows() + settings->getAdditionalLines());
261 
262     addUpdateFlags(GSLV_UF_ViewResized);
263     update();
264 }
265 
updateNumVisibleRows()266 void PanView::updateNumVisibleRows() {
267     setNumVisibleRows(renderArea->height() / getRenderArea()->getRowLineHeight());
268 }
269 
updateRowBar()270 void PanView::updateRowBar() {
271     rowBar->disconnect(this);
272 
273     int visibleRows = settings->getNumVisibleRows();
274     int maxSteps = calculateNumRowBarSteps();
275 
276     rowBar->setMinimum(-maxSteps);  // inverted appearance
277     rowBar->setMaximum(0);
278     rowBar->setSingleStep(1);
279     rowBar->setPageStep(visibleRows - 1);
280     int rowsOffset = qMin(maxSteps, settings->rowLinesOffset);
281     settings->rowLinesOffset = rowsOffset;
282     rowBar->setSliderPosition(-rowsOffset);
283     rowBar->setEnabled(maxSteps > 0);
284 
285     connect(rowBar, SIGNAL(valueChanged(int)), SLOT(sl_onRowBarMoved(int)));
286 }
287 
sl_onRowBarMoved(int v)288 void PanView::sl_onRowBarMoved(int v) {
289     settings->rowLinesOffset = -v;  // '-' because of inverted appearance
290     addUpdateFlags(GSLV_UF_NeedCompleteRedraw);
291     update();
292 }
293 
sl_onAnnotationsModified(const QList<AnnotationModification> & annotationModifications)294 void PanView::sl_onAnnotationsModified(const QList<AnnotationModification> &annotationModifications) {
295     QList<Annotation *> modified;
296     foreach (const AnnotationModification &annotationModification, annotationModifications) {
297         modified << annotationModification.annotation;
298     }
299     unregisterAnnotations(modified);
300     registerAnnotations(modified);
301 
302     addUpdateFlags(GSLV_UF_AnnotationsChanged);
303     update();
304     GSequenceLineViewAnnotated::sl_onAnnotationsModified(annotationModifications);
305 }
306 
sl_onAnnotationSettingsChanged(const QStringList & changedSettings)307 void PanView::sl_onAnnotationSettingsChanged(const QStringList &changedSettings) {
308     AnnotationSettingsRegistry *asr = AppContext::getAnnotationsSettingsRegistry();
309     foreach (const QString &name, changedSettings) {
310         AnnotationSettings *as = asr->getAnnotationSettings(name);
311         bool hasRow = rowsManager->contains(name);
312         if (as->visible == hasRow) {
313             continue;
314         }
315         QList<Annotation *> changed;
316         foreach (AnnotationTableObject *ao, ctx->getAnnotationObjects(true)) {
317             changed << ao->getAnnotationsByName(name);
318         }
319         if (changed.isEmpty()) {
320             continue;
321         }
322         foreach (Annotation *a, changed) {
323             if (as->visible) {
324                 rowsManager->addAnnotation(a);
325             } else {
326                 rowsManager->removeAnnotation(a);
327             }
328         }
329     }
330     updateRows();
331     GSequenceLineViewAnnotated::sl_onAnnotationSettingsChanged(changedSettings);
332 }
333 
setSelection(const U2Region & r)334 void PanView::setSelection(const U2Region &r) {
335     ctx->getSequenceSelection()->setRegion(r);
336 }
337 
onVisibleRangeChanged(bool signal)338 void PanView::onVisibleRangeChanged(bool signal) {
339     updateActions();
340     GSequenceLineView::onVisibleRangeChanged(signal);
341 }
342 
useZoom()343 void PanView::useZoom() {
344     zoomUsing++;
345     updateActions();
346 }
347 
releaseZoom()348 void PanView::releaseZoom() {
349     if (zoomUsing) {
350         zoomUsing--;
351         updateActions();
352     }
353 
354     Q_ASSERT(zoomUsing >= 0);
355 }
356 
updateActions()357 void PanView::updateActions() {
358     if (!zoomUsing) {
359         zoomInAction->setDisabled(true);
360         zoomOutAction->setDisabled(true);
361 
362         zoomToSelectionAction->setDisabled(true);
363         zoomToSequenceAction->setDisabled(true);
364 
365         return;
366     }
367 
368     zoomInAction->setEnabled(visibleRange.length > minNuclsPerScreen);
369     zoomOutAction->setEnabled(visibleRange.length < seqLen);
370 
371     const QVector<U2Region> &sel = ctx->getSequenceSelection()->getSelectedRegions();
372     if (!sel.isEmpty() && sel.first().length >= minNuclsPerScreen) {
373         zoomToSelectionAction->setEnabled(true);
374     } else {
375         zoomToSelectionAction->setEnabled(false);
376     }
377     zoomToSequenceAction->setEnabled(visibleRange.startPos != 0 || visibleRange.endPos() != seqLen);
378 }
379 
sl_zoomInAction()380 void PanView::sl_zoomInAction() {
381     assert(visibleRange.length >= minNuclsPerScreen);
382     const U2Region selRange = getRegionToZoom();
383     if (!selRange.isEmpty() && selRange.length >= minNuclsPerScreen && visibleRange.contains(selRange) && visibleRange != selRange) {
384         sl_zoomToSelection();
385         return;
386     }
387     U2Region newVisibleRange = visibleRange;
388     newVisibleRange.length = qMax((visibleRange.length + 1) / 2, (qint64)minNuclsPerScreen);
389     if (newVisibleRange.length != visibleRange.length) {
390         newVisibleRange.startPos = visibleRange.startPos + (visibleRange.length - newVisibleRange.length) / 2;
391         setVisibleRange(newVisibleRange);
392     }
393 }
394 
sl_zoomOutAction()395 void PanView::sl_zoomOutAction() {
396     assert(visibleRange.length <= seqLen);
397     U2Region newVisibleRange = visibleRange;
398     newVisibleRange.length = qMin(visibleRange.length * 2, seqLen);
399     if (newVisibleRange.length != visibleRange.length) {
400         newVisibleRange.startPos = qBound(qint64(0), visibleRange.startPos - (newVisibleRange.length - visibleRange.length) / 2, seqLen - newVisibleRange.length);
401         assert(newVisibleRange.startPos >= 0 && newVisibleRange.endPos() <= seqLen);  // todo: move to setVisibleRange
402         setVisibleRange(newVisibleRange);
403     }
404 }
405 
sl_onDNASelectionChanged(LRegionsSelection * s,const QVector<U2Region> & added,const QVector<U2Region> & removed)406 void PanView::sl_onDNASelectionChanged(LRegionsSelection *s, const QVector<U2Region> &added, const QVector<U2Region> &removed) {
407     GSequenceLineView::sl_onDNASelectionChanged(s, added, removed);
408     updateActions();
409 }
410 
sl_zoomToSelection()411 void PanView::sl_zoomToSelection() {
412     const U2Region selRegion = getRegionToZoom();
413     if (selRegion.isEmpty()) {
414         return;
415     }
416     if (selRegion.length < minNuclsPerScreen) {
417         return;
418     }
419     if (visibleRange == selRegion) {
420         return;
421     }
422     SAFE_POINT(U2Region(0, ctx->getSequenceObject()->getSequenceLength()).contains(selRegion), "Invalid selection region", );
423     visibleRange = selRegion;
424     onVisibleRangeChanged();
425 }
426 
sl_zoomToSequence()427 void PanView::sl_zoomToSequence() {
428     U2Region wholeRange(0, seqLen);
429     assert(visibleRange != wholeRange);
430     visibleRange = wholeRange;
431     onVisibleRangeChanged();
432 }
433 
setVisibleRange(const U2Region & newRange,bool signal)434 void PanView::setVisibleRange(const U2Region &newRange, bool signal) {
435     assert(newRange.startPos >= 0 && newRange.endPos() <= seqLen);
436 
437     if (newRange.length < minNuclsPerScreen) {
438         minNuclsPerScreen = newRange.length;
439     }
440     GSequenceLineView::setVisibleRange(newRange, signal);
441 }
442 
ensureVisible(Annotation * a,int locationIdx)443 void PanView::ensureVisible(Annotation *a, int locationIdx) {
444     AnnotationSettingsRegistry *asr = AppContext::getAnnotationsSettingsRegistry();
445     const AnnotationSettings *as = asr->getAnnotationSettings(a->getData());
446     if (as->visible) {
447         const int row = rowsManager->getAnnotationRowIdx(a);
448         if (!settings->isRowVisible(row)) {
449             centerRow(row);
450         }
451     }
452     GSequenceLineViewAnnotated::ensureVisible(a, locationIdx);
453 }
454 
centerRow(int row)455 void PanView::centerRow(int row) {
456     int targetFirstRowLine = qMax(0, row - settings->getNumVisibleRows() / 2);
457     int rowOnTheFirstLine = settings->rowLinesOffset;
458     if (targetFirstRowLine == rowOnTheFirstLine) {
459         return;
460     }
461     int dPos = targetFirstRowLine - rowOnTheFirstLine;
462     int sliderPos = qBound(rowBar->minimum(), rowBar->value() - dPos, rowBar->maximum());
463     rowBar->setSliderPosition(sliderPos);
464 }
465 
sl_onRangeChangeRequest(qint64 start,qint64 end)466 void PanView::sl_onRangeChangeRequest(qint64 start, qint64 end) {
467     uiLog.trace(tr("range change request: [%1, %2]").arg(start).arg(end));
468     setVisibleRange(U2Region(start - 1, end));
469 }
470 
setNumBasesVisible(qint64 n)471 void PanView::setNumBasesVisible(qint64 n) {
472     qint64 nBases = qBound((qint64)minNuclsPerScreen, n, seqLen);
473     qint64 center = visibleRange.startPos + visibleRange.length / 2;
474     qint64 newStart = qMax(qint64(0), center - nBases / 2);
475     assert(newStart + nBases <= seqLen);
476     setVisibleRange(U2Region(newStart, nBases));
477 }
478 
getRenderArea() const479 PanViewRenderArea *PanView::getRenderArea() const {
480     return qobject_cast<PanViewRenderArea *>(renderArea);
481 }
482 
getCustomRulers() const483 QList<RulerInfo> PanView::getCustomRulers() const {
484     return settings->customRulers;
485 }
486 
addCustomRuler(const RulerInfo & r)487 void PanView::addCustomRuler(const RulerInfo &r) {
488     settings->customRulers.append(r);
489     if (settings->showCustomRulers) {
490         addUpdateFlags(GSLV_UF_NeedCompleteRedraw);
491         update();
492     }
493     toggleCustomRulersAction->setEnabled(true);
494 }
495 
removeCustomRuler(const QString & name)496 void PanView::removeCustomRuler(const QString &name) {
497     for (int i = 0, n = settings->customRulers.count(); i < n; i++) {
498         if (settings->customRulers[i].name == name) {
499             settings->customRulers.removeAt(i);
500             break;
501         }
502     }
503     toggleCustomRulersAction->setEnabled(!settings->customRulers.isEmpty());
504     if (settings->showCustomRulers) {
505         addUpdateFlags(GSLV_UF_NeedCompleteRedraw);
506         update();
507     }
508 }
509 
removeAllCustomRulers()510 void PanView::removeAllCustomRulers() {
511     toggleCustomRulersAction->setEnabled(false);
512     if (!settings->customRulers.isEmpty()) {
513         settings->customRulers.clear();
514 
515         addUpdateFlags(GSLV_UF_NeedCompleteRedraw);
516         update();
517     }
518 }
519 
sl_toggleMainRulerVisibility(bool visible)520 void PanView::sl_toggleMainRulerVisibility(bool visible) {
521     settings->showMainRuler = visible;
522 
523     addUpdateFlags(GSLV_UF_NeedCompleteRedraw);
524     update();
525 }
526 
sl_toggleCustomRulersVisibility(bool visible)527 void PanView::sl_toggleCustomRulersVisibility(bool visible) {
528     settings->showCustomRulers = visible;
529 
530     addUpdateFlags(GSLV_UF_NeedCompleteRedraw);
531     update();
532 }
533 
setSyncOffset(int o)534 void PanView::setSyncOffset(int o) {
535     if (o == syncOffset) {
536         return;
537     }
538     syncOffset = o;
539     addUpdateFlags(GSLV_UF_NeedCompleteRedraw);
540     update();
541 }
542 
getSyncOffset() const543 int PanView::getSyncOffset() const {
544     return syncOffset;
545 }
546 
sl_sequenceChanged()547 void PanView::sl_sequenceChanged() {
548     seqLen = ctx->getSequenceLength();
549     U2Region curSource(0, ctx->getSequenceLength()), newRange(0, 0);
550     if (!curSource.contains(visibleRange)) {
551         if (curSource.length > visibleRange.length) {
552             newRange.startPos = visibleRange.startPos - (visibleRange.endPos() - curSource.endPos());
553             newRange.length = visibleRange.length;
554         } else {
555             newRange = curSource;
556         }
557         setVisibleRange(newRange);
558     }
559     GSequenceLineView::sl_sequenceChanged();
560     updateActions();
561 }
562 
hideEvent(QHideEvent * ev)563 void PanView::hideEvent(QHideEvent *ev) {
564     zoomInAction->setDisabled(true);
565     zoomOutAction->setDisabled(true);
566     zoomToSelectionAction->setDisabled(true);
567     zoomToSequenceAction->setDisabled(true);
568     QWidget::hideEvent(ev);
569 }
570 
showEvent(QShowEvent * ev)571 void PanView::showEvent(QShowEvent *ev) {
572     QWidget::showEvent(ev);
573     updateActions();
574 }
575 
sl_updateRows()576 void PanView::sl_updateRows() {
577     updateRows();
578 }
579 
getRegionToZoom() const580 U2Region PanView::getRegionToZoom() const {
581     const QVector<U2Region> &sel = ctx->getSequenceSelection()->getSelectedRegions();
582     const QList<Annotation *> annotationSel = getSequenceContext()->getAnnotationsSelection()->getAnnotations();
583     U2Region selRegion;
584     if (!sel.isEmpty()) {
585         selRegion = sel.first();
586     } else if (!annotationSel.isEmpty()) {
587         selRegion = U2Region::containingRegion(annotationSel.first()->getRegions());
588     }
589 
590     return selRegion;
591 }
592 
getZoomInAction() const593 QAction *PanView::getZoomInAction() const {
594     return zoomInAction;
595 }
596 
getZoomOutAction() const597 QAction *PanView::getZoomOutAction() const {
598     return zoomOutAction;
599 }
600 
getZoomToSelectionAction() const601 QAction *PanView::getZoomToSelectionAction() const {
602     return zoomToSelectionAction;
603 }
604 
getZoomToSequenceAction() const605 QAction *PanView::getZoomToSequenceAction() const {
606     return zoomToSequenceAction;
607 }
608 
getRowsManager() const609 PVRowsManager *PanView::getRowsManager() const {
610     return rowsManager;
611 }
612 
getToggleMainRulerAction() const613 QAction *PanView::getToggleMainRulerAction() const {
614     return toggleMainRulerAction;
615 }
616 
getToggleCustomRulersAction() const617 QAction *PanView::getToggleCustomRulersAction() const {
618     return toggleCustomRulersAction;
619 }
620 
getLinesSettings() const621 PanViewLinesSettings *PanView::getLinesSettings() const {
622     return settings;
623 }
624 
getSingleStep() const625 qint64 PanView::getSingleStep() const {
626     return qMax((qint64)1, visibleRange.length / 10);
627 }
628 
getPageStep() const629 qint64 PanView::getPageStep() const {
630     return qMax((qint64)1, visibleRange.length / 5);
631 }
632 
633 //////////////////////////////////////////////////////////////////////////
634 /// PanViewRenderArea
PanViewRenderArea(PanView * d,PanViewRenderer * renderer)635 PanViewRenderArea::PanViewRenderArea(PanView *d, PanViewRenderer *renderer)
636     : GSequenceLineViewGridAnnotationRenderArea(d),
637       panView(d),
638       renderer(renderer) {
639     SAFE_POINT(nullptr != renderer, "Renderer is NULL", );
640 }
641 
drawAll(QPaintDevice * pd)642 void PanViewRenderArea::drawAll(QPaintDevice *pd) {
643     GTIMER(c2, t2, "PanViewRenderArea::drawAll");
644     GSLV_UpdateFlags uf = view->getUpdateFlags();
645     bool completeRedraw = uf.testFlag(GSLV_UF_NeedCompleteRedraw) || uf.testFlag(GSLV_UF_ViewResized) ||
646                           uf.testFlag(GSLV_UF_VisibleRangeChanged) || uf.testFlag(GSLV_UF_AnnotationsChanged);
647 
648     QPainter p(pd);
649     if (completeRedraw) {
650         QPainter pCached(getCachedPixmap());
651         renderer->drawAll(pCached, QSize(pd->width(), pd->height()), view->getVisibleRange());
652         pCached.end();
653     }
654 
655     p.drawPixmap(0, 0, *cachedView);
656 
657     // SANGER_TODO: should not be this kind of connection
658     //    ADVSingleSequenceWidget* ssw = panView->seqWidget;
659     //    SAFE_POINT(ssw != NULL, "ADVSingleSequenceWidget is NULL", );
660     //    if (!ssw->isOverviewCollapsed()) {
661     //        //! VIEW_RENDERER_REFACTORING: consider to move frame drawing to renderer
662     //        drawFrame(p);
663     //    }
664 
665     renderer->drawSelection(p, QSize(pd->width(), pd->height()), view->getVisibleRange());
666 
667     if (view->hasFocus()) {
668         drawFocus(p);
669     }
670 }
671 
getAnnotationYRange(Annotation * annotation,int locationRegionIndex,const AnnotationSettings * annotationSettings) const672 U2Region PanViewRenderArea::getAnnotationYRange(Annotation *annotation, int locationRegionIndex, const AnnotationSettings *annotationSettings) const {
673     U2Region region = renderer->getAnnotationYRange(annotation, locationRegionIndex, annotationSettings, height());
674     region.startPos += renderer->getContentIndentY(height());
675     return region;
676 }
677 
getAnnotationYRegions(Annotation * annotation,int locationRegionIndex,const AnnotationSettings * annotationSettings) const678 QList<U2Region> PanViewRenderArea::getAnnotationYRegions(Annotation *annotation, int locationRegionIndex, const AnnotationSettings *annotationSettings) const {
679     // Each annotation region has only 1 y-region in PanView.
680     return QList<U2Region>() << getAnnotationYRange(annotation, locationRegionIndex, annotationSettings);
681 }
682 
getRowLineHeight() const683 int PanViewRenderArea::getRowLineHeight() const {
684     return renderer->getRowLineHeight();
685 }
686 
isSequenceCharsVisible() const687 bool PanViewRenderArea::isSequenceCharsVisible() const {
688     return getCurrentScale() >= smallCharWidth;
689 }
690 
resizeEvent(QResizeEvent * e)691 void PanViewRenderArea::resizeEvent(QResizeEvent *e) {
692     view->addUpdateFlags(GSLV_UF_ViewResized);
693 
694     PanView *pv = getPanView();
695     SAFE_POINT(pv != nullptr, "Panview is NULL", );
696     pv->updateNumVisibleRows();
697     pv->updateRowBar();
698 
699     QWidget::resizeEvent(e);
700 }
701 
702 }  // namespace U2
703