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 "AnnotHighlightWidget.h"
23 #include <limits.h>
24 
25 #include <QPushButton>
26 
27 #include <U2Core/AnnotationSelection.h>
28 #include <U2Core/AnnotationSettings.h>
29 #include <U2Core/AnnotationTableObject.h>
30 #include <U2Core/AppContext.h>
31 #include <U2Core/Counter.h>
32 #include <U2Core/DNAAlphabet.h>
33 #include <U2Core/U1AnnotationUtils.h>
34 #include <U2Core/U2SafePoints.h>
35 
36 #include <U2View/ADVSequenceObjectContext.h>
37 #include <U2View/ADVSingleSequenceWidget.h>
38 #include <U2View/AnnotatedDNAView.h>
39 #include <U2View/PanView.h>
40 
41 namespace U2 {
42 
ShowAllAnnotTypesLabel()43 ShowAllAnnotTypesLabel::ShowAllAnnotTypesLabel() {
44     // By default, show only types for the sequence
45     showAllIsSelected = false;
46     setText(QObject::tr("Show all annotation names"));
47 
48     setStyleSheet(
49         "text-decoration: underline;"
50         "color: gray;"
51         "margin-left: 2px;"
52         "margin-top: 1px;");
53 }
54 
mousePressEvent(QMouseEvent * event)55 void ShowAllAnnotTypesLabel::mousePressEvent(QMouseEvent *event) {
56     Q_UNUSED(event);
57     if (showAllIsSelected) {
58         showAllIsSelected = false;
59         setText(QObject::tr("Show all annotation names"));
60     } else {
61         showAllIsSelected = true;
62         setText(QObject::tr("Show names for the sequence only"));
63     }
64 
65     emit si_showAllStateChanged();
66 }
67 
AnnotHighlightWidget(AnnotatedDNAView * _annotatedDnaView)68 AnnotHighlightWidget::AnnotHighlightWidget(AnnotatedDNAView *_annotatedDnaView)
69     : annotatedDnaView(_annotatedDnaView) {
70     SAFE_POINT(0 != annotatedDnaView, "AnnotatedDNAView is NULL!", );
71     initLayout();
72     connectSlots();
73     loadAnnotTypes();
74 }
75 
initLayout()76 void AnnotHighlightWidget::initLayout() {
77     QVBoxLayout *mainLayout = new QVBoxLayout();
78     mainLayout->setContentsMargins(0, 0, 0, 0);
79     mainLayout->setSpacing(10);
80     mainLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
81 
82     noAnnotTypesLabel = new QLabel("");
83     noAnnotTypesLabel->setWordWrap(true);
84     setNoAnnotTypesLabelValue();
85     noAnnotTypesLabel->setStyleSheet("margin-left: 2px;");
86     noAnnotTypesLabel->setObjectName("noAnnotTypesLabel");
87 
88     annotTreeTitle = new QLabel(tr("Select an annotation name:"));
89 
90     // Tree
91     QVBoxLayout *treeLayout = new QVBoxLayout();
92     treeLayout->setContentsMargins(0, 0, 0, 10);
93     treeLayout->setSpacing(0);
94 
95     annotTree = new AnnotHighlightTree();
96 
97     showAllLabel = new ShowAllAnnotTypesLabel();
98     showAllLabel->setObjectName("show_all_annotation_types");
99 
100     treeLayout->addWidget(annotTree);
101     treeLayout->addWidget(showAllLabel);
102 
103     // Configure settings
104     QVBoxLayout *settingsLayout = new QVBoxLayout();
105     settingsLayout->setContentsMargins(0, 0, 0, 0);
106     settingsLayout->setSpacing(0);
107     settingsLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
108 
109     settingsTitle = new QLabel(tr("Configure the annotations:"));
110     annotSettingsWidget = new AnnotHighlightSettingsWidget();
111 
112     settingsLayout->addWidget(settingsTitle);
113     settingsLayout->addWidget(annotSettingsWidget);
114 
115     QHBoxLayout *buttonsLayout = new QHBoxLayout();
116     buttonsLayout->setContentsMargins(0, 0, 0, 0);
117     buttonsLayout->setSpacing(0);
118 
119     prevAnnotationButton = new QPushButton(QIcon(":core/images/backward.png"), "");
120     prevAnnotationButton->setFixedSize(32, 32);
121     prevAnnotationButton->setToolTip(AnnotHighlightWidget::tr("Previous annotation"));
122     prevAnnotationButton->setDisabled(true);
123     prevAnnotationButton->setObjectName("prevAnnotationButton");
124     buttonsLayout->addWidget(prevAnnotationButton);
125     buttonsLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
126 
127     nextAnnotationButton = new QPushButton(QIcon(":core/images/forward.png"), "");
128     nextAnnotationButton->setFixedSize(32, 32);
129     nextAnnotationButton->setToolTip(AnnotHighlightWidget::tr("Next annotation"));
130     nextAnnotationButton->setObjectName("nextAnnotationButton");
131     buttonsLayout->addWidget(nextAnnotationButton);
132     if (noAnnotatedRegions()) {
133         nextAnnotationButton->setDisabled(true);
134     } else {
135         sl_onAnnotationSelectionChanged();
136     }
137 
138     // Init main layout
139     mainLayout->addWidget(noAnnotTypesLabel);
140     mainLayout->addWidget(annotTreeTitle);
141     mainLayout->addLayout(treeLayout);
142     mainLayout->addLayout(settingsLayout);
143     mainLayout->addLayout(buttonsLayout);
144 
145     setLayout(mainLayout);
146 }
147 
isFirstAnnotatedRegion(Annotation * annotation,const U2Region & region,bool fromTheBeginning) const148 bool AnnotHighlightWidget::isFirstAnnotatedRegion(Annotation *annotation, const U2Region &region, bool fromTheBeginning) const {
149     AnnotatedRegion annRegion;
150     if (findFirstAnnotatedRegion(annRegion, fromTheBeginning)) {
151         if (annRegion.annotation == annotation) {
152             SAFE_POINT(annRegion.annotation->getRegions().size() > annRegion.regionIdx, "Invalid annotation region", false);
153             if (annRegion.annotation->getRegions()[annRegion.regionIdx] == region) {
154                 return true;
155             }
156         }
157     }
158     return false;
159 }
160 
noAnnotatedRegions() const161 bool AnnotHighlightWidget::noAnnotatedRegions() const {
162     const QList<AnnotationTableObject *> items = annotatedDnaView->getAnnotationObjects(true);
163     foreach (AnnotationTableObject *object, items) {
164         SAFE_POINT(object != nullptr, "Annotation table object is NULL", true);
165         if (object->hasAnnotations()) {
166             return false;
167         }
168     }
169     return true;
170 }
171 
selectNextAnnotation(bool isForward) const172 void AnnotHighlightWidget::selectNextAnnotation(bool isForward) const {
173     AnnotationSelection *as = annotatedDnaView->getAnnotationsSelection();
174     CHECK(as != nullptr, );
175 
176     bool isAnnRegionValid = false;
177     AnnotatedRegion annRegion;
178 
179     if (as->isEmpty() && isForward) {
180         // no selected annotation regions - choose first one
181         isAnnRegionValid = findFirstAnnotatedRegion(annRegion);
182     } else {
183         // choose next acoording to selection
184         isAnnRegionValid = findNextUnselectedAnnotatedRegion(annRegion, isForward);
185     }
186 
187     if (isAnnRegionValid) {
188         as->clear();
189         as->add(annRegion.annotation);
190     }
191     return;
192 }
193 
findFirstAnnotatedRegion(AnnotatedRegion & annRegion,bool fromTheBeginging) const194 bool AnnotHighlightWidget::findFirstAnnotatedRegion(AnnotatedRegion &annRegion, bool fromTheBeginging) const {
195     return findFirstAnnotatedRegionAfterPos(annRegion,
196                                             fromTheBeginging ? -1 : LLONG_MAX,
197                                             fromTheBeginging);
198 }
199 
findFirstAnnotatedRegionAfterPos(AnnotatedRegion & annRegion,qint64 startPos,bool isForward) const200 bool AnnotHighlightWidget::findFirstAnnotatedRegionAfterPos(AnnotatedRegion &annRegion, qint64 startPos, bool isForward) const {
201     qint64 boundary = isForward ? LLONG_MAX : -1;
202     qint64 sign = isForward ? 1 : -1;
203     qint64 pos = boundary;
204 
205     const QList<AnnotationTableObject *> annObjects = annotatedDnaView->getAnnotationObjects(true);
206     foreach (AnnotationTableObject *annObject, annObjects) {
207         SAFE_POINT(annotatedDnaView->getSequenceContext(annObject) != nullptr, tr("Sequence context is NULL"), false);
208         qint64 seqLen = annotatedDnaView->getSequenceContext(annObject)->getSequenceLength();
209         QList<Annotation *> annots = annObject->getAnnotationsByRegion(U2Region(isForward ? startPos : 0, isForward ? seqLen - startPos : startPos));
210         foreach (Annotation *a, annots) {
211             QVector<U2Region> regions = a->getRegions();
212             for (int i = 0; i < regions.size(); i++) {
213                 if (sign * regions[i].startPos > sign * startPos && sign * regions[i].startPos < sign * pos) {
214                     pos = regions[i].startPos;
215                     annRegion.annotation = a;
216                     annRegion.regionIdx = i;
217                 }
218             }
219         }
220     }
221 
222     if (pos == boundary) {
223         return false;
224     }
225 
226     QList<AnnotatedRegion> regionsAtTheSamePosition = getAllAnnotatedRegionsByStartPos(pos);
227     if (!regionsAtTheSamePosition.isEmpty()) {
228         annRegion = regionsAtTheSamePosition[isForward ? 0 : (regionsAtTheSamePosition.size() - 1)];
229         return true;
230     }
231 
232     return false;
233 }
234 
findNextUnselectedAnnotatedRegion(AnnotatedRegion & annRegion,bool fromTheBeginning) const235 bool AnnotHighlightWidget::findNextUnselectedAnnotatedRegion(AnnotatedRegion &annRegion, bool fromTheBeginning) const {
236     AnnotationSelection *as = annotatedDnaView->getAnnotationsSelection();
237     CHECK(as != nullptr, false);
238     CHECK(!as->isEmpty(), false);
239 
240     // detect the most right/left start position in selection
241     const QList<Annotation *> selectionData = as->getAnnotations();
242     int start = -1;
243     foreach (Annotation *selectionItem, selectionData) {
244         foreach (U2Region region, selectionItem->getRegions()) {
245             if (start == -1) {
246                 start = region.startPos;
247             } else {
248                 if ((region.startPos - start) * (fromTheBeginning ? 1 : -1) > 0) {
249                     start = region.startPos;
250                 }
251             }
252         }
253     }
254 
255     QList<AnnotatedRegion> regionsAtTheSamePosition = getAllAnnotatedRegionsByStartPos(start);
256     // find the next unselected
257     for (int i = 0; i < regionsAtTheSamePosition.size(); i++) {
258         int idx = fromTheBeginning ? regionsAtTheSamePosition.size() - 1 - i : i;
259         if (as->contains(regionsAtTheSamePosition[idx].annotation)) {
260             idx += (fromTheBeginning ? 1 : -1);
261             if (idx < 0 || idx == regionsAtTheSamePosition.size()) {
262                 break;
263             }
264             annRegion = regionsAtTheSamePosition[idx];
265             return true;
266         }
267     }
268 
269     return findFirstAnnotatedRegionAfterPos(annRegion, start, fromTheBeginning);
270 }
271 
getAllAnnotatedRegionsByStartPos(qint64 startPos) const272 QList<AnnotatedRegion> AnnotHighlightWidget::getAllAnnotatedRegionsByStartPos(qint64 startPos) const {
273     const QList<AnnotationTableObject *> annObjects = annotatedDnaView->getAnnotationObjects(true);
274     return U1AnnotationUtils::getAnnotatedRegionsByStartPos(annObjects, startPos);
275 }
276 
sl_onNextAnnotationClick()277 void AnnotHighlightWidget::sl_onNextAnnotationClick() {
278     GCOUNTER(cvar, "Annotations navigation: next annotation");
279     selectNextAnnotation(true);
280 }
281 
sl_onPrevAnnotationClick()282 void AnnotHighlightWidget::sl_onPrevAnnotationClick() {
283     GCOUNTER(cvar, "Annotations navigation: previous annotation");
284     selectNextAnnotation(false);
285 }
286 
sl_onAnnotationSelectionChanged()287 void AnnotHighlightWidget::sl_onAnnotationSelectionChanged() {
288     AnnotationSelection *as = annotatedDnaView->getAnnotationsSelection();
289     CHECK(as != nullptr, );
290 
291     if (as->isEmpty()) {
292         nextAnnotationButton->setDisabled(noAnnotatedRegions());
293         prevAnnotationButton->setDisabled(true);
294     } else {
295         nextAnnotationButton->setDisabled(false);
296         prevAnnotationButton->setDisabled(false);
297 
298         // find first or last annotation region
299         foreach (Annotation *a, as->getAnnotations()) {
300             foreach (U2Region region, a->getRegions()) {
301                 if (isFirstAnnotatedRegion(a, region, false)) {
302                     nextAnnotationButton->setDisabled(true);
303                 }
304                 if (isFirstAnnotatedRegion(a, region)) {
305                     prevAnnotationButton->setDisabled(true);
306                 }
307             }
308         }
309     }
310 }
311 
setNoAnnotTypesLabelValue()312 void AnnotHighlightWidget::setNoAnnotTypesLabelValue() {
313     QList<ADVSequenceObjectContext *> seqContexts = annotatedDnaView->getSequenceContexts();
314 
315     if (1 == seqContexts.count()) {
316         noAnnotTypesLabel->setText(tr("The sequence doesn't have any annotations."));
317     } else {
318         noAnnotTypesLabel->setText(tr("The sequences do not have any annotations."));
319     }
320 }
321 
setNoAnnotsLayout()322 void AnnotHighlightWidget::setNoAnnotsLayout() {
323     noAnnotTypesLabel->show();
324     annotTreeTitle->hide();
325     annotTree->hide();
326     settingsTitle->hide();
327     annotSettingsWidget->hide();
328 }
329 
setLayoutWithAnnotsSelection()330 void AnnotHighlightWidget::setLayoutWithAnnotsSelection() {
331     noAnnotTypesLabel->hide();
332     annotTreeTitle->show();
333     annotTree->show();
334     settingsTitle->show();
335     annotSettingsWidget->show();
336 }
337 
connectSlots()338 void AnnotHighlightWidget::connectSlots() {
339     // Show annotation types for the sequence or all annotation types
340     connect(showAllLabel, SIGNAL(si_showAllStateChanged()), this, SLOT(sl_onShowAllStateChanged()));
341 
342     // Selected annotation type has changed
343     connect(annotTree, SIGNAL(si_selectedItemChanged(QString)), SLOT(sl_onSelectedItemChanged(QString)));
344 
345     // Another color or a setting has been selected for an annotation type
346     connect(annotTree, SIGNAL(si_colorChanged(QString, QColor)), SLOT(sl_storeNewColor(QString, QColor)));
347     connect(annotSettingsWidget, SIGNAL(si_annotSettingsChanged(AnnotationSettings *)), SLOT(sl_storeNewSettings(AnnotationSettings *)));
348 
349     // A sequence has been modified (a subsequence added, removed, etc.)
350     connect(annotatedDnaView, SIGNAL(si_sequenceModified(ADVSequenceObjectContext *)), this, SLOT(sl_onSequenceModified(ADVSequenceObjectContext *)));
351 
352     // An annotation object has been added/removed - connect/disconnect slots
353     connect(annotatedDnaView, SIGNAL(si_annotationObjectAdded(AnnotationTableObject *)), SLOT(sl_onAnnotationObjectAdded(AnnotationTableObject *)));
354     connect(annotatedDnaView, SIGNAL(si_annotationObjectRemoved(AnnotationTableObject *)), SLOT(sl_onAnnotationObjectRemoved(AnnotationTableObject *)));
355 
356     // An annotation has been added/removed/modified
357     QList<AnnotationTableObject *> seqAnnotTableObjs = annotatedDnaView->getAnnotationObjects(true);  // "true" to include auto-annotations
358     foreach (const AnnotationTableObject *annotTableObj, seqAnnotTableObjs) {
359         connectSlotsForAnnotTableObj(annotTableObj);
360     }
361 
362     connect(prevAnnotationButton, SIGNAL(clicked()), this, SLOT(sl_onPrevAnnotationClick()));
363 
364     connect(nextAnnotationButton, SIGNAL(clicked()), this, SLOT(sl_onNextAnnotationClick()));
365 
366     AnnotationSelection *as = annotatedDnaView->getAnnotationsSelection();
367     CHECK(as != nullptr, );
368     connect(as, SIGNAL(si_selectionChanged(AnnotationSelection *, const QList<Annotation *> &, const QList<Annotation *> &)), SLOT(sl_onAnnotationSelectionChanged()));
369 }
370 
connectSlotsForAnnotTableObj(const AnnotationTableObject * annotTableObj)371 void AnnotHighlightWidget::connectSlotsForAnnotTableObj(const AnnotationTableObject *annotTableObj) {
372     connect(annotTableObj, SIGNAL(si_onAnnotationsAdded(const QList<Annotation *> &)), SLOT(sl_onAnnotationsAdded(const QList<Annotation *> &)));
373     connect(annotTableObj, SIGNAL(si_onAnnotationsRemoved(const QList<Annotation *> &)), SLOT(sl_onAnnotationsRemoved(const QList<Annotation *> &)));
374     connect(annotTableObj, SIGNAL(si_onAnnotationsModified(const QList<AnnotationModification> &)), SLOT(sl_onAnnotationsModified()));
375 }
376 
disconnectSlotsForAnnotTableObj(const AnnotationTableObject * annotTableObj)377 void AnnotHighlightWidget::disconnectSlotsForAnnotTableObj(const AnnotationTableObject *annotTableObj) {
378     disconnect(annotTableObj, SIGNAL(si_onAnnotationsAdded(const QList<Annotation *> &)), this, SLOT(sl_onAnnotationsAdded(const QList<Annotation *> &)));
379     disconnect(annotTableObj, SIGNAL(si_onAnnotationsRemoved(const QList<Annotation *> &)), this, SLOT(sl_onAnnotationsRemoved(const QList<Annotation *> &)));
380     disconnect(annotTableObj, SIGNAL(si_onAnnotationsModified(const QList<AnnotationModification> &)), this, SLOT(sl_onAnnotationsModified()));
381 }
382 
sl_onShowAllStateChanged()383 void AnnotHighlightWidget::sl_onShowAllStateChanged() {
384     loadAnnotTypes();
385 }
386 
sl_onSelectedItemChanged(const QString & annotName)387 void AnnotHighlightWidget::sl_onSelectedItemChanged(const QString &annotName) {
388     AnnotationSettingsRegistry *annotRegistry = AppContext::getAnnotationsSettingsRegistry();
389 
390     AnnotationSettings *selectedAnnotSettings = annotRegistry->getAnnotationSettings(annotName);
391     annotSettingsWidget->setSettings(selectedAnnotSettings, annotNamesWithAminoInfo.value(annotName));
392 }
393 
findAllAnnotationsNamesForSequence()394 void AnnotHighlightWidget::findAllAnnotationsNamesForSequence() {
395     annotNamesWithAminoInfo.clear();
396 
397     QList<ADVSequenceObjectContext *> seqObjContexts = annotatedDnaView->getSequenceContexts();
398 
399     foreach (ADVSequenceObjectContext *seqContext, seqObjContexts) {
400         const DNAAlphabet *seqAlphabet = seqContext->getAlphabet();
401         bool isAminoSeq = seqAlphabet->isAmino();
402 
403         QSet<AnnotationTableObject *> seqAnnotTableObjects = seqContext->getAnnotationObjects(true);
404 
405         foreach (AnnotationTableObject *annotTableObj, seqAnnotTableObjects) {
406             const QList<Annotation *> annotations = annotTableObj->getAnnotations();
407 
408             foreach (Annotation *annot, annotations) {
409                 const QString annotName = annot->getName();
410 
411                 // If the annotation was found on a nucleotide sequence
412                 if (!isAminoSeq) {
413                     // The "Show on translation" option should be enabled for this annotation type
414                     annotNamesWithAminoInfo.insert(annotName, false);
415                 }
416                 // The annotation was found on an amino acid sequence
417                 else {
418                     if (annotNamesWithAminoInfo.contains(annotName)) {
419                         // Do nothing:
420                         // if the value is "true", then it doesn't make sense to rewrite the same value
421                         // if the value is "false", then the annotation was previously found on a nucleotide
422                         // sequence and therefore the "Show on translation" option should be enabled
423                     } else {
424                         // Disable the option
425                         annotNamesWithAminoInfo.insert(annotName, true);
426                     }
427                 }
428             }
429         }
430     }
431 }
432 
findAllAnnotationsNamesInSettings()433 void AnnotHighlightWidget::findAllAnnotationsNamesInSettings() {
434     annotNamesWithAminoInfo.clear();
435 
436     AnnotationSettingsRegistry *registry = AppContext::getAnnotationsSettingsRegistry();
437     SAFE_POINT(0 != registry, "AnnotationSettingsRegistry is NULL!", );
438 
439     QStringList annotSettings = registry->getAllSettings();
440     foreach (QString setting, annotSettings) {
441         annotNamesWithAminoInfo.insert(setting, false);
442     }
443 }
444 
updateAnnotationNames()445 void AnnotHighlightWidget::updateAnnotationNames() {
446     if (showAllLabel->isShowAllSelected()) {
447         findAllAnnotationsNamesInSettings();
448     } else {
449         findAllAnnotationsNamesForSequence();
450     }
451 }
452 
loadAnnotTypes()453 void AnnotHighlightWidget::loadAnnotTypes() {
454     // Get the annotation names
455     updateAnnotationNames();
456 
457     QList<QString> annotNames = annotNamesWithAminoInfo.keys();
458     std::sort(annotNames.begin(), annotNames.end());
459 
460     // Get the currently selected annotation name
461     QString currentAnnotName = annotTree->getCurrentItemAnnotName();
462 
463     // Clear the old items and restore the initial height
464     annotTree->clear();
465 
466     // If there types to show
467     if (!annotNames.isEmpty()) {
468         setLayoutWithAnnotsSelection();
469 
470         // Add the tree items
471         AnnotationSettingsRegistry *annotRegistry = AppContext::getAnnotationsSettingsRegistry();
472         foreach (const QString &name, annotNames) {
473             AnnotationSettings *annotSettings = annotRegistry->getAnnotationSettings(name);
474             annotTree->addItem(name, annotSettings->color);
475         }
476 
477         // By default, select either previously selected item (if it is present) or the first item
478         if (annotNames.contains(currentAnnotName)) {
479             annotTree->setItemSelectedWithAnnotName(currentAnnotName);
480         } else {
481             annotTree->setFirstItemSelected();
482             currentAnnotName = annotTree->getFirstItemAnnotName();
483             SAFE_POINT(currentAnnotName != QString(), "Failed to get first annotation name!", );
484         }
485 
486         // Set the configuration settings for the item
487         AnnotationSettings *currentAnnotSettings = annotRegistry->getAnnotationSettings(currentAnnotName);
488         annotSettingsWidget->setSettings(currentAnnotSettings, annotNamesWithAminoInfo.value(currentAnnotName));
489     } else {
490         setNoAnnotsLayout();
491     }
492 
493     if (noAnnotatedRegions()) {
494         nextAnnotationButton->setDisabled(true);
495     }
496 }
497 
sl_storeNewColor(const QString & annotName,const QColor & newColor)498 void AnnotHighlightWidget::sl_storeNewColor(const QString &annotName, const QColor &newColor) {
499     QList<AnnotationSettings *> annotToWrite;
500     AnnotationSettingsRegistry *annotRegistry = AppContext::getAnnotationsSettingsRegistry();
501     AnnotationSettings *annotSettings = annotRegistry->getAnnotationSettings(annotName);
502     if (annotSettings->color != newColor) {
503         annotSettings->color = newColor;
504         annotToWrite.append(annotSettings);
505         annotRegistry->changeSettings(annotToWrite, true);
506     }
507 }
508 
sl_storeNewSettings(AnnotationSettings * annotSettings)509 void AnnotHighlightWidget::sl_storeNewSettings(AnnotationSettings *annotSettings) {
510     QList<AnnotationSettings *> annotToWrite;
511     AnnotationSettingsRegistry *annotRegistry = AppContext::getAnnotationsSettingsRegistry();
512     annotToWrite.append(annotSettings);
513     annotRegistry->changeSettings(annotToWrite, true);
514 }
515 
sl_onSequenceModified(ADVSequenceObjectContext *)516 void AnnotHighlightWidget::sl_onSequenceModified(ADVSequenceObjectContext * /* seqContext */) {
517     loadAnnotTypes();
518 }
519 
sl_onAnnotationsAdded(const QList<Annotation * > &)520 void AnnotHighlightWidget::sl_onAnnotationsAdded(const QList<Annotation *> & /* annotations */) {
521     loadAnnotTypes();
522 }
523 
sl_onAnnotationsRemoved(const QList<Annotation * > & annotations)524 void AnnotHighlightWidget::sl_onAnnotationsRemoved(const QList<Annotation *> &annotations) {
525     CHECK(!showAllLabel->isShowAllSelected(), );
526 
527     const QString selectedAnnotName = annotTree->getCurrentItemAnnotName();
528 
529     QMap<QString, int> observedAnnNames;
530     foreach (Annotation *a, annotations) {
531         const QString annotName = a->getName();
532         if (observedAnnNames.contains(annotName)) {
533             observedAnnNames[annotName]++;
534             continue;
535         }
536         observedAnnNames.insert(annotName, 1);
537     }
538 
539     bool isSelectedItemRemoved = false;
540     QList<AnnotationTableObject *> annTables = annotatedDnaView->getAnnotationObjects(true);
541     foreach (const QString &annotName, observedAnnNames.keys()) {
542         int count = 0;
543         foreach (AnnotationTableObject *t, annTables) {
544             count += t->getAnnotationsByName(annotName).size();
545         }
546         if (count == observedAnnNames[annotName]) {
547             QList<QTreeWidgetItem *> itemList = annotTree->findItems(annotName, Qt::MatchExactly);
548             SAFE_POINT(itemList.size() == 1, "Annotation Highlight tree should contain only one item per annotation type", );
549             QTreeWidgetItem *item = itemList.first();
550             delete annotTree->takeTopLevelItem(annotTree->indexOfTopLevelItem(item));
551             annotNamesWithAminoInfo.remove(annotName);
552             if (selectedAnnotName == annotName) {
553                 isSelectedItemRemoved = true;
554             }
555         }
556     }
557 
558     if (annotNamesWithAminoInfo.count() == 0) {
559         annotTree->clear();
560         setNoAnnotsLayout();
561         nextAnnotationButton->setDisabled(true);
562     } else {
563         setLayoutWithAnnotsSelection();
564         if (isSelectedItemRemoved || selectedAnnotName.isEmpty()) {
565             annotTree->setFirstItemSelected();
566         } else {
567             annotTree->setItemSelectedWithAnnotName(selectedAnnotName);
568         }
569     }
570 }
571 
sl_onAnnotationsModified()572 void AnnotHighlightWidget::sl_onAnnotationsModified() {
573     loadAnnotTypes();
574 }
575 
sl_onAnnotationObjectAdded(AnnotationTableObject * annotTableObj)576 void AnnotHighlightWidget::sl_onAnnotationObjectAdded(AnnotationTableObject *annotTableObj) {
577     connectSlotsForAnnotTableObj(annotTableObj);
578     loadAnnotTypes();
579 }
580 
sl_onAnnotationObjectRemoved(AnnotationTableObject * annotTableObj)581 void AnnotHighlightWidget::sl_onAnnotationObjectRemoved(AnnotationTableObject *annotTableObj) {
582     disconnectSlotsForAnnotTableObj(annotTableObj);
583     loadAnnotTypes();
584 }
585 
586 }  // namespace U2
587