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