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 "GSequenceLineViewAnnotated.h"
23
24 #include <QApplication>
25 #include <QMenu>
26 #include <QPainterPath>
27 #include <QToolTip>
28
29 #include <U2Core/AnnotationData.h>
30 #include <U2Core/AnnotationModification.h>
31 #include <U2Core/AnnotationSettings.h>
32 #include <U2Core/AnnotationTableObject.h>
33 #include <U2Core/AppContext.h>
34 #include <U2Core/DNASequenceObject.h>
35 #include <U2Core/DNASequenceSelection.h>
36 #include <U2Core/GenbankFeatures.h>
37 #include <U2Core/Timer.h>
38 #include <U2Core/U1AnnotationUtils.h>
39 #include <U2Core/U2SafePoints.h>
40
41 #include <U2Formats/GenbankLocationParser.h>
42
43 #include <U2Gui/GUIUtils.h>
44
45 #include "ADVSequenceObjectContext.h"
46
47 namespace U2 {
48
GSequenceLineViewAnnotated(QWidget * p,SequenceObjectContext * ctx)49 GSequenceLineViewAnnotated::GSequenceLineViewAnnotated(QWidget *p, SequenceObjectContext *ctx)
50 : GSequenceLineView(p, ctx) {
51 const QSet<AnnotationTableObject *> aObjs = ctx->getAnnotationObjects(true);
52 foreach (const AnnotationTableObject *ao, aObjs) {
53 connectAnnotationObject(ao);
54 }
55 connect(ctx->getAnnotationsSelection(),
56 SIGNAL(si_selectionChanged(AnnotationSelection *, const QList<Annotation *> &, const QList<Annotation *> &)),
57 SLOT(sl_onAnnotationSelectionChanged(AnnotationSelection *, const QList<Annotation *> &, const QList<Annotation *> &)));
58
59 connect(ctx, SIGNAL(si_annotationObjectAdded(AnnotationTableObject *)), SLOT(sl_onAnnotationObjectAdded(AnnotationTableObject *)));
60 connect(ctx, SIGNAL(si_annotationObjectRemoved(AnnotationTableObject *)), SLOT(sl_onAnnotationObjectRemoved(AnnotationTableObject *)));
61 connect(ctx, SIGNAL(si_annotationActivated(Annotation *, int)), SLOT(sl_onAnnotationActivated(Annotation *, int)));
62
63 connect(AppContext::getAnnotationsSettingsRegistry(), SIGNAL(si_annotationSettingsChanged(const QStringList &)), SLOT(sl_onAnnotationSettingsChanged(const QStringList &)));
64 }
65
connectAnnotationObject(const AnnotationTableObject * ao)66 void GSequenceLineViewAnnotated::connectAnnotationObject(const AnnotationTableObject *ao) {
67 connect(ao, SIGNAL(si_onAnnotationsAdded(const QList<Annotation *> &)), SLOT(sl_onAnnotationsAdded(const QList<Annotation *> &)));
68 connect(ao, SIGNAL(si_onAnnotationsRemoved(const QList<Annotation *> &)), SLOT(sl_onAnnotationsRemoved(const QList<Annotation *> &)));
69 connect(ao, SIGNAL(si_onAnnotationsInGroupRemoved(const QList<Annotation *> &, AnnotationGroup *)), SLOT(sl_onAnnotationsInGroupRemoved(const QList<Annotation *> &, AnnotationGroup *)));
70 connect(ao, SIGNAL(si_onAnnotationsModified(const QList<AnnotationModification> &)), SLOT(sl_onAnnotationsModified(const QList<AnnotationModification> &)));
71 }
72
sl_onAnnotationSettingsChanged(const QStringList &)73 void GSequenceLineViewAnnotated::sl_onAnnotationSettingsChanged(const QStringList &) {
74 addUpdateFlags(GSLV_UF_AnnotationsChanged);
75 update();
76 }
77
sl_onAnnotationObjectAdded(AnnotationTableObject * o)78 void GSequenceLineViewAnnotated::sl_onAnnotationObjectAdded(AnnotationTableObject *o) {
79 connectAnnotationObject(o);
80 sl_onAnnotationsAdded(o->getAnnotations());
81 }
82
sl_onAnnotationObjectRemoved(AnnotationTableObject * o)83 void GSequenceLineViewAnnotated::sl_onAnnotationObjectRemoved(AnnotationTableObject *o) {
84 o->disconnect(this);
85 sl_onAnnotationsRemoved(o->getAnnotations());
86 }
87
sl_onAnnotationsAdded(const QList<Annotation * > & l)88 void GSequenceLineViewAnnotated::sl_onAnnotationsAdded(const QList<Annotation *> &l) {
89 GTIMER(c2, t2, "GSequenceLineViewAnnotated::sl_onAnnotationsAdded");
90 registerAnnotations(l);
91 addUpdateFlags(GSLV_UF_AnnotationsChanged);
92 update();
93 }
94
sl_onAnnotationsRemoved(const QList<Annotation * > & l)95 void GSequenceLineViewAnnotated::sl_onAnnotationsRemoved(const QList<Annotation *> &l) {
96 unregisterAnnotations(l);
97 addUpdateFlags(GSLV_UF_AnnotationsChanged);
98 update();
99 }
100
sl_onAnnotationsInGroupRemoved(const QList<Annotation * > & l,AnnotationGroup *)101 void GSequenceLineViewAnnotated::sl_onAnnotationsInGroupRemoved(const QList<Annotation *> &l, AnnotationGroup *) {
102 ClearAnnotationsTask *task = new ClearAnnotationsTask(l, this);
103 AppContext::getTaskScheduler()->registerTopLevelTask(task);
104 }
105
ClearAnnotationsTask(const QList<Annotation * > & list,GSequenceLineViewAnnotated * view)106 ClearAnnotationsTask::ClearAnnotationsTask(const QList<Annotation *> &list, GSequenceLineViewAnnotated *view)
107 : Task("Clear annotations", TaskFlag_None), l(list), view(view) {
108 }
109
run()110 void ClearAnnotationsTask::run() {
111 view->unregisterAnnotations(l);
112 }
113
report()114 Task::ReportResult ClearAnnotationsTask::report() {
115 view->addUpdateFlags(GSLV_UF_AnnotationsChanged);
116 view->update();
117 return ReportResult_Finished;
118 }
119
sl_onAnnotationActivated(U2::Annotation * annotation,int regionIndex)120 void GSequenceLineViewAnnotated::sl_onAnnotationActivated(U2::Annotation *annotation, int regionIndex) {
121 const QSet<AnnotationTableObject *> aos = ctx->getAnnotationObjects(true);
122 if (aos.contains(annotation->getGObject())) {
123 ensureVisible(annotation, regionIndex);
124 }
125 }
126
sl_onAnnotationSelectionChanged(AnnotationSelection *,const QList<Annotation * > & _added,const QList<Annotation * > & _removed)127 void GSequenceLineViewAnnotated::sl_onAnnotationSelectionChanged(AnnotationSelection * /*as*/, const QList<Annotation *> &_added, const QList<Annotation *> &_removed) {
128 const QSet<AnnotationTableObject *> aos = ctx->getAnnotationObjects(true);
129
130 bool changed = false;
131 const QList<Annotation *> added = ctx->selectRelatedAnnotations(_added);
132 const QList<Annotation *> removed = ctx->selectRelatedAnnotations(_removed);
133
134 if (!changed) {
135 foreach (Annotation *a, added) {
136 if (aos.contains(a->getGObject()) && isAnnotationVisible(a)) {
137 changed = true;
138 break;
139 }
140 }
141 if (!changed) {
142 foreach (Annotation *a, removed) {
143 if (aos.contains(a->getGObject()) && isAnnotationVisible(a)) {
144 changed = true;
145 break;
146 }
147 }
148 }
149 }
150
151 if (changed) {
152 addUpdateFlags(GSLV_UF_SelectionChanged);
153 update();
154 }
155 }
156
isAnnotationVisible(const Annotation * a) const157 bool GSequenceLineViewAnnotated::isAnnotationVisible(const Annotation *a) const {
158 foreach (const U2Region &r, a->getRegions()) {
159 if (visibleRange.intersects(r)) {
160 return true;
161 }
162 }
163 return false;
164 }
165
findAnnotationsByCoord(const QPoint & coord) const166 QList<Annotation *> GSequenceLineViewAnnotated::findAnnotationsByCoord(const QPoint &coord) const {
167 auto renderAreaAnnotated = qobject_cast<GSequenceLineViewAnnotatedRenderArea *>(renderArea);
168 SAFE_POINT(renderAreaAnnotated != nullptr, "GSequenceLineViewAnnotated must have GSequenceLineViewAnnotatedRenderArea!", QList<Annotation *>());
169 return renderAreaAnnotated->findAnnotationsByCoord(coord);
170 }
171
mousePressEvent(QMouseEvent * me)172 void GSequenceLineViewAnnotated::mousePressEvent(QMouseEvent *me) {
173 setFocus();
174 const QPoint renderAreaPoint = toRenderAreaPoint(me->pos());
175 const QPoint p = toRenderAreaPoint(me->pos());
176 const Qt::KeyboardModifiers km = QApplication::keyboardModifiers();
177 const bool singleBaseSelectionMode = km.testFlag(Qt::AltModifier);
178 bool annotationEvent = false; // true if mouse pressed in some annotation area
179 if (renderArea->rect().contains(p) && me->button() == Qt::LeftButton && !singleBaseSelectionMode) {
180 const Qt::KeyboardModifiers mouseEventModifiers = me->modifiers();
181 const bool controlOrShiftPressed = mouseEventModifiers.testFlag(Qt::ControlModifier) || mouseEventModifiers.testFlag(Qt::ShiftModifier);
182 QList<Annotation *> annotations = findAnnotationsByCoord(p);
183 annotationEvent = !annotations.isEmpty();
184 if ((!controlOrShiftPressed || !annotationEvent) && cursor().shape() == Qt::ArrowCursor) {
185 ctx->getAnnotationsSelection()->clear();
186 ctx->getSequenceSelection()->clear();
187 ctx->emitClearSelectedAnnotationRegions();
188 }
189 if (annotationEvent && cursor().shape() == Qt::ArrowCursor) {
190 Annotation *annotation = annotations.first();
191 if (annotations.size() > 1) {
192 AnnotationSettingsRegistry *asr = AppContext::getAnnotationsSettingsRegistry();
193 QMenu popup;
194 foreach (const Annotation *as, annotations) {
195 const SharedAnnotationData &aData = as->getData();
196 const U2Region r = as->getRegions().first();
197 const QString text = aData->name + QString(" [%1, %2]").arg(r.startPos + 1).arg(r.endPos());
198 AnnotationSettings *asettings = asr->getAnnotationSettings(aData);
199 const QIcon icon = GUIUtils::createSquareIcon(asettings->color, 10);
200 popup.addAction(icon, text);
201 }
202 QAction *a = popup.exec(QCursor::pos());
203 if (nullptr == a) {
204 annotation = nullptr;
205 } else {
206 int idx = popup.actions().indexOf(a);
207 annotation = annotations[idx];
208 }
209 }
210 if (nullptr != annotation) {
211 QVector<U2Region> annotationRegions = annotation->getRegions();
212 bool processAllRegions = U1AnnotationUtils::isAnnotationContainsJunctionPoint(annotation, seqLen);
213 if (processAllRegions) {
214 ctx->emitAnnotationActivated(annotation, -1);
215 } else {
216 qint64 mousePressPos = renderArea->coordToPos(renderAreaPoint);
217 for (int i = 0; i < annotationRegions.size(); i++) {
218 const U2Region ®ion = annotationRegions[i];
219 if (region.contains(mousePressPos)) {
220 ctx->emitAnnotationActivated(annotation, i);
221 }
222 }
223 }
224 }
225 }
226 }
227 // a hint to parent class: if mouse action leads to annotation selection -> skip selection handling for mouse press
228 ignoreMouseSelectionEvents = annotationEvent;
229 GSequenceLineView::mousePressEvent(me);
230 ignoreMouseSelectionEvents = false;
231 }
232
mouseDoubleClickEvent(QMouseEvent * me)233 void GSequenceLineViewAnnotated::mouseDoubleClickEvent(QMouseEvent *me) {
234 const QPoint renderAreaPoint = toRenderAreaPoint(me->pos());
235 lastPressPos = renderArea->coordToPos(renderAreaPoint);
236 QList<Annotation *> selection = findAnnotationsByCoord(renderAreaPoint);
237 if (selection.isEmpty()) {
238 GSequenceLineView::mouseDoubleClickEvent(me);
239 return;
240 }
241 Annotation *annotation = selection.first();
242 // Using any of modifiers (compatibility with older UGENE behavior).
243 bool expandSelection = me->modifiers() == Qt::ControlModifier || me->modifiers() == Qt::ShiftModifier;
244 if (!expandSelection) {
245 ctx->emitClearSelectedAnnotationRegions();
246 }
247 const QVector<U2Region> annotationRegions = annotation->getRegions();
248 foreach (const U2Region ®ion, annotationRegions) {
249 CHECK_CONTINUE(region.contains(lastPressPos));
250
251 ctx->emitAnnotationDoubleClicked(annotation, annotationRegions.indexOf(region));
252 break;
253 }
254 }
255
256 //! VIEW_RENDERER_REFACTORING: used only in CV, doubled in SequenceViewAnnotetedRenderer.
257 //! Apply renederer logic to CV and remove this method.
prepareAnnotationText(const SharedAnnotationData & a,const AnnotationSettings * as)258 QString GSequenceLineViewAnnotated::prepareAnnotationText(const SharedAnnotationData &a, const AnnotationSettings *as) {
259 if (!as->showNameQuals || as->nameQuals.isEmpty()) {
260 return a->name;
261 }
262 QVector<U2Qualifier> qs;
263 foreach (const QString &qn, as->nameQuals) {
264 qs.clear();
265 a->findQualifiers(qn, qs);
266 if (!qs.isEmpty()) {
267 QString res = qs[0].value;
268 return res;
269 }
270 }
271 return a->name;
272 }
273
findAnnotationsInRange(const U2Region & range) const274 QList<Annotation *> GSequenceLineViewAnnotated::findAnnotationsInRange(const U2Region &range) const {
275 QList<Annotation *> result;
276 const QSet<AnnotationTableObject *> aObjs = ctx->getAnnotationObjects(true);
277 foreach (AnnotationTableObject *ao, aObjs) {
278 result << ao->getAnnotationsByRegion(range);
279 }
280 return result;
281 }
282
283 //////////////////////////////////////////////////////////////////////////
284 /// Renderer
285
GSequenceLineViewAnnotatedRenderArea(GSequenceLineViewAnnotated * sequenceLineView)286 GSequenceLineViewAnnotatedRenderArea::GSequenceLineViewAnnotatedRenderArea(GSequenceLineViewAnnotated *sequenceLineView)
287 : GSequenceLineViewRenderArea(sequenceLineView), sequenceLineViewAnnotated(sequenceLineView) {
288 afNormal = new QFont("Courier", 10);
289 afSmall = new QFont("Arial", 8);
290
291 afmNormal = new QFontMetrics(*afNormal, this);
292 afmSmall = new QFontMetrics(*afSmall, this);
293
294 afNormalCharWidth = afmNormal->width('w');
295 afSmallCharWidth = afmSmall->width('w');
296
297 QLinearGradient gradient(0, 0, 0, 1); // vertical
298 gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
299 gradient.setColorAt(0.00, QColor(255, 255, 255, 120));
300 gradient.setColorAt(0.50, QColor(0, 0, 0, 0));
301 gradient.setColorAt(0.70, QColor(0, 0, 0, 0));
302 gradient.setColorAt(1.00, QColor(0, 0, 0, 70));
303 gradientMaskBrush = QBrush(gradient);
304 }
305
~GSequenceLineViewAnnotatedRenderArea()306 GSequenceLineViewAnnotatedRenderArea::~GSequenceLineViewAnnotatedRenderArea() {
307 delete afmNormal;
308 delete afNormal;
309 delete afmSmall;
310 delete afSmall;
311 }
312
registerAnnotations(const QList<Annotation * > &)313 void GSequenceLineViewAnnotated::registerAnnotations(const QList<Annotation *> &) {
314 }
315
unregisterAnnotations(const QList<Annotation * > &)316 void GSequenceLineViewAnnotated::unregisterAnnotations(const QList<Annotation *> &) {
317 }
318
ensureVisible(Annotation * a,int locationIdx)319 void GSequenceLineViewAnnotated::ensureVisible(Annotation *a, int locationIdx) {
320 QVector<U2Region> location = a->getRegions();
321 SAFE_POINT(locationIdx < location.size(), "Invalid annotation location on the widget!", );
322 if (-1 == locationIdx) {
323 foreach (const U2Region &r, location) {
324 if (visibleRange.intersects(r)) {
325 return;
326 }
327 }
328 }
329 const U2Region ®ion = location[qMax(0, locationIdx)];
330 if (!visibleRange.intersects(region)) {
331 const qint64 pos = a->getStrand().isCompementary() ? region.endPos() : region.startPos;
332 setCenterPos(qBound(qint64(0), pos, seqLen - 1));
333 }
334 }
335
event(QEvent * e)336 bool GSequenceLineViewAnnotated::event(QEvent *e) {
337 if (e->type() == QEvent::ToolTip) {
338 QHelpEvent *he = static_cast<QHelpEvent *>(e);
339 QString tip = createToolTip(he);
340 if (!tip.isEmpty()) {
341 QToolTip::showText(he->globalPos(), tip);
342 }
343 return true;
344 }
345 return GSequenceLineView::event(e);
346 }
347
createToolTip(QHelpEvent * e)348 QString GSequenceLineViewAnnotated::createToolTip(QHelpEvent *e) {
349 const int ROWS_LIMIT = 25;
350 QList<Annotation *> la = findAnnotationsByCoord(e->pos());
351 QList<SharedAnnotationData> annotationList;
352 if (la.isEmpty()) {
353 return QString();
354 } else {
355 // fetch annotation data before further processing in order to improve performance
356 foreach (const Annotation *annotation, la) {
357 annotationList << annotation->getData();
358 }
359 }
360 QString tip = "<table>";
361 int rows = 0;
362 if (annotationList.size() > 1) {
363 foreach (const SharedAnnotationData &ad, annotationList) {
364 rows += ad->qualifiers.size() + 1;
365 }
366 }
367
368 const bool skipDetails = (rows > ROWS_LIMIT);
369 rows = 0;
370 foreach (const SharedAnnotationData &ad, annotationList) {
371 if (++rows > ROWS_LIMIT) {
372 break;
373 }
374 AnnotationSettingsRegistry *registry = AppContext::getAnnotationsSettingsRegistry();
375 const QColor acl = registry->getAnnotationSettings(ad->name)->color;
376 tip += "<tr><td bgcolor=" + acl.name() + " bordercolor=black width=15></td><td><big>" + ad->name + "</big></td></tr>";
377
378 if (skipDetails) {
379 tip += "<tr><td/><td>...</td>";
380 rows++;
381 } else {
382 tip += "<tr><td></td><td><b>Location</b> = " + U1AnnotationUtils::buildLocationString(ad) + "</td></tr>";
383 tip += "<tr><td/><td>";
384 tip += Annotation::getQualifiersTip(ad, ROWS_LIMIT - rows, getSequenceObject(), ctx->getComplementTT(), ctx->getAminoTT());
385 tip += "</td></tr>";
386 rows += ad->qualifiers.size();
387 }
388 }
389 tip += "</table>";
390 if (rows > ROWS_LIMIT) {
391 tip += "<hr> <div align=center>" + tr("etc ...") + "</div>";
392 }
393 return tip;
394 }
395
sl_onAnnotationsModified(const QList<AnnotationModification> & annotationModifications)396 void GSequenceLineViewAnnotated::sl_onAnnotationsModified(const QList<AnnotationModification> &annotationModifications) {
397 foreach (const AnnotationModification &annotationModification, annotationModifications) {
398 if (annotationModification.type == AnnotationModification_LocationChanged ||
399 annotationModification.type == AnnotationModification_NameChanged ||
400 annotationModification.type == AnnotationModification_TypeChanged) {
401 addUpdateFlags(GSLV_UF_AnnotationsChanged);
402 update();
403 break;
404 }
405 }
406 }
407
isAnnotationSelectionInVisibleRange() const408 bool GSequenceLineViewAnnotated::isAnnotationSelectionInVisibleRange() const {
409 const QSet<AnnotationTableObject *> aos = ctx->getAnnotationObjects(true);
410 AnnotationSelection *as = ctx->getAnnotationsSelection();
411 foreach (const Annotation *annotation, as->getAnnotations()) {
412 if (!aos.contains(annotation->getGObject())) {
413 continue;
414 }
415 if (isAnnotationVisible(annotation)) {
416 return true;
417 }
418 }
419 return false;
420 }
421
GSequenceLineViewGridAnnotationRenderArea(GSequenceLineViewAnnotated * sequenceLineView)422 GSequenceLineViewGridAnnotationRenderArea::GSequenceLineViewGridAnnotationRenderArea(GSequenceLineViewAnnotated *sequenceLineView)
423 : GSequenceLineViewAnnotatedRenderArea(sequenceLineView) {
424 }
425
findAnnotationsByCoord(const QPoint & coord) const426 QList<Annotation *> GSequenceLineViewGridAnnotationRenderArea::findAnnotationsByCoord(const QPoint &coord) const {
427 QList<Annotation *> resultAnnotationList;
428 CHECK(rect().contains(coord), resultAnnotationList);
429
430 AnnotationSettingsRegistry *annotationsSettingsRegistry = AppContext::getAnnotationsSettingsRegistry();
431 const qint64 pos = coordToPos(coord);
432 qint64 uncertaintyLength = 0;
433 SequenceObjectContext *sequenceContext = sequenceLineViewAnnotated->getSequenceContext();
434 qint64 sequenceLength = sequenceContext->getSequenceLength();
435 U2Region visibleRange = view->getVisibleRange();
436 if (visibleRange.length > width()) {
437 double scale = getCurrentScale();
438 uncertaintyLength = static_cast<qint64>(1 / scale);
439 SAFE_POINT(uncertaintyLength < sequenceLength, "Invalid uncertaintyLength for the given seqLen!", resultAnnotationList);
440 }
441 U2Region pointRegion(pos - uncertaintyLength, 1 + 2 * uncertaintyLength); // A region of sequence covered by the 'QPoint& coord'.
442 const QSet<AnnotationTableObject *> annotationObjectSet = sequenceContext->getAnnotationObjects(true);
443 for (const AnnotationTableObject *annotationObject : qAsConst(annotationObjectSet)) {
444 for (Annotation *annotation : annotationObject->getAnnotationsByRegion(pointRegion)) {
445 const SharedAnnotationData &aData = annotation->getData();
446 const QVector<U2Region> locationRegionList = aData->getRegions();
447 for (int i = 0, n = locationRegionList.size(); i < n; i++) {
448 const U2Region &locationRegion = locationRegionList[i];
449 if (locationRegion.intersects(pointRegion) || pointRegion.startPos == locationRegion.endPos()) {
450 // now check pixel precise coords for boundaries.
451 if (pos == locationRegion.startPos) {
452 int posStartX = posToCoord(locationRegion.startPos, true);
453 if (coord.x() < posStartX) {
454 continue;
455 }
456 } else if (pos == locationRegion.endPos()) {
457 // Use endPos() - 1 to avoid moving to the next line in multiline views.
458 int posEndX = posToCoord(locationRegion.endPos() - 1, true) + getCharWidth();
459 if (coord.x() >= posEndX) {
460 continue;
461 }
462 }
463 AnnotationSettings *annotationSettings = annotationsSettingsRegistry->getAnnotationSettings(aData);
464 if (annotationSettings->visible && checkAnnotationRegionContainsYPoint(coord.y(), annotation, i, annotationSettings)) {
465 resultAnnotationList.append(annotation); // select whole annotation (all regions)
466 break;
467 }
468 }
469 }
470 }
471 }
472 return resultAnnotationList;
473 }
474
checkAnnotationRegionContainsYPoint(int y,Annotation * annotation,int locationRegionIndex,const AnnotationSettings * annotationSettings) const475 bool GSequenceLineViewGridAnnotationRenderArea::checkAnnotationRegionContainsYPoint(int y, Annotation *annotation, int locationRegionIndex, const AnnotationSettings *annotationSettings) const {
476 QList<U2Region> yRegionList = getAnnotationYRegions(annotation, locationRegionIndex, annotationSettings);
477 for (const U2Region ®ion : qAsConst(yRegionList)) {
478 if (region.contains(y)) {
479 return true;
480 }
481 }
482 return false;
483 }
484
485 } // namespace U2
486