1 /**
2  * UGENE - Integrated Bioinformatics Tools.
3  * Copyright (C) 2008-2021 UniPro <ugene@unipro.ru>
4  * http://ugene.net
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  * MA 02110-1301, USA.
20  */
21 
22 #ifndef _U2_FIND_PATTERN_MSA_WIDGET_H_
23 #define _U2_FIND_PATTERN_MSA_WIDGET_H_
24 
25 #include <U2Core/U2Region.h>
26 
27 #include <U2View/MSAEditor.h>
28 
29 #include "FindPatternMsaWidgetSavableTab.h"
30 #include "ov_msa/view_rendering/MaEditorSelection.h"
31 #include "ui_FindPatternMsaForm.h"
32 
33 namespace U2 {
34 class ShowHideSubgroupWidget;
35 class ADVSequenceObjectContext;
36 class ADVSequenceWidget;
37 class AnnotatedDNAView;
38 class CreateAnnotationWidgetController;
39 class DNASequenceSelection;
40 class Task;
41 class U2OpStatus;
42 
43 /** Find algorithm results with view positioning info. */
44 struct FindPatternWidgetResult {
45     FindPatternWidgetResult(qint64 rowId, int viewRowIndex, const U2Region &region);
46 
47     /** MA sequence row id. */
48     qint64 rowId;
49 
50     /** View row index of the result. -1 if the result is not visible: the result is inside of some collapsed group. */
51     int viewRowIndex;
52 
53     /** Region with gaps. */
54     U2Region region;
55 };
56 
57 class FindPatternMsaWidget : public QWidget, private Ui_FindPatternMsaForm {
58     Q_OBJECT
59 public:
60     enum MessageFlag {
61         PatternAlphabetDoNotMatch,
62         PatternsWithBadAlphabetInFile,
63         PatternsWithBadRegionInFile,
64         PleaseInputAtLeastOneSearchPatternTip,
65         AnnotationNotValidName,
66         AnnotationNotValidFastaParsedName,
67         NoPatternToSearch,
68         SearchRegionIncorrect,
69         PatternWrongRegExp,
70         SequenceIsTooBig
71     };
72     /** Creates a new widget. Activates search-in-name mode if isSearchInNamesMode is yes. Uses the last saved state if isSearchInNamesMode is Unknown. */
73     FindPatternMsaWidget(MSAEditor *msaEditor, TriState isSearchInNamesModeTriState = TriState_Unknown);
74 
75     int getTargetMsaLength() const;
76 
77     void setSearchInNamesMode(bool flag);
78 
79 private slots:
80     void sl_onAlgorithmChanged(int);
81     void sl_onRegionOptionChanged(int);
82     void sl_onRegionValueEdited();
83     void sl_onSearchPatternChanged();
84     void sl_onMaxResultChanged(int);
85     void sl_findPatternTaskStateChanged();
86     void sl_searchModeChanged();
87     void sl_groupResultsButtonClicked();
88 
89     /** A sequence part was added, removed or replaced */
90     void sl_onMsaModified();
91     void sl_msaStateChanged();
92 
93     void sl_onSelectedRegionChanged(const MaEditorSelection &currentSelection, const MaEditorSelection &prev);
94     void sl_prevButtonClicked();
95     void sl_nextButtonClicked();
96 
97     void sl_onEnterPressed();
98     void sl_onShiftEnterPressed();
99     void sl_collapseModelChanged();
100 
101     void sl_validateStateAndStartNewSearch(bool activatedByOutsideChanges = false);
102 
103 private:
104     void updateActions();
105     void initLayout();
106     void initAlgorithmLayout();
107     void initRegionSelection();
108     void initResultsLimit();
109     void initMaxResultLenContainer();
110     void updateLayout();
111     void connectSlots();
112     void clearResults();
113 
114     /** Returns true if the alignment alphabet is Amino. */
115     bool isAmino() const;
116 
117     int getMaxError(const QString &pattern) const;
118 
119     /** Assigns valid viewRowIndex value to all results & resorts them based on the view position. */
120     void resortResultsByViewState();
121 
122     /** Returns current visible result equal to the selection. Returns -1 if no such result found. */
123     int findCurrentResultIndexFromSelection() const;
124 
125     /** Returns next or prev result index using current selection top-left position. */
126     int getNextOrPrevResultIndexFromSelection(bool isNext);
127 
128     /** Updates label with current result position. */
129     void updateCurrentResultLabel();
130 
131     /** Selects current search result in the MSA editor . */
132     void selectCurrentResult();
133 
134     /** Returns true if current MSA editor selection region is equal to the current result. */
135     bool isResultSelected() const;
136 
137     void stopCurrentSearchTask();
138     void correctSearchInCombo();
139     void setUpTabOrder() const;
140     void showCurrentResultAndStopProgress();
141     void startProgressAnimation();
142 
143     /** Checks current UI state and update status label. */
144     void checkStateAndUpdateStatus();
145 
146     /**
147      * Checks if currently selected region is valid for the given pattern.
148      * Returns error message to display if the region is not correct or an empty string if the region is correct.
149      */
150     QString checkSearchRegion() const;
151 
152     /**
153      * The "Match" spin is disabled if this is an amino acid sequence or
154      * the search pattern is empty. Otherwise it is enabled.
155      */
156     void enableDisableMatchSpin();
157 
158     /** Toggles error message flag and updates additional error message. Does not trigger re-rendering of the error label. */
159     void setMessageFlag(const MessageFlag &messageFlag, bool show, const QString &additionalMsg = QString());
160 
161     /** Updates visual error label state based on the curent error flags state. */
162     void updateErrorLabelState();
163 
164     /** Checks pattern alphabet and sets error message if needed. Returns false on error or true if no error found */
165     bool verifyPatternAlphabet();
166     bool checkAlphabet(const QString &pattern);
167     void showTooLongSequenceError();
168     void hideAllMessages();
169 
170     void setCorrectPatternsString();
171     void setRegionToWholeSequence();
172 
173     /** Performs in-main thread search in sequence names. */
174     void runSearchInSequenceNames(const QStringList &patterns);
175 
176     /** Checks current UI state and returns either a valid or an empty (invalid) region. */
177     U2Region getSearchRegion() const;
178 
179     void startFindPatternInMsaTask(const QStringList &patterns);
180 
181     /**
182      * Checks if there are several patterns in textPattern which are separated by new line symbol,
183      * parses them out and returns with their names (if they're exist).
184      */
185     QStringList getPatternsFromTextPatternField(U2OpStatus &os) const;
186 
187     void updatePatternText(int previousAlgorithm);
188 
189     /** Post processes allSearchResults list after search task is finished. */
190     void postProcessAllSearchResults();
191 
192     MSAEditor *msaEditor;
193     int selectedAlgorithm;
194     QString patternString;
195     QString patternRegExp;
196 
197     /** Keeps flags of visible messages and optional (may be empty) custom messages as values. */
198     QMap<MessageFlag, QString> messageFlagMap;
199 
200     /** Widgets in the Algorithm group */
201     QHBoxLayout *layoutMismatch;
202     QVBoxLayout *layoutRegExpLen;
203 
204     QLabel *lblMatch;
205     QSpinBox *spinMatch;
206 
207     QWidget *useMaxResultLenContainer;
208     QCheckBox *boxUseMaxResultLen;
209     QSpinBox *boxMaxResultLen;
210 
211     static const int DEFAULT_RESULTS_NUM_LIMIT;
212     static const int DEFAULT_REGEXP_RESULT_LENGTH_LIMIT;
213 
214     static const int REG_EXP_MIN_RESULT_LEN;
215     static const int REG_EXP_MAX_RESULT_LEN;
216     static const int REG_EXP_MAX_RESULT_SINGLE_STEP;
217 
218     /** Visible only search results. */
219     QList<FindPatternWidgetResult> visibleSearchResults;
220 
221     /** All search results: both visible & hidden in collapsed groups. */
222     QList<FindPatternWidgetResult> allSearchResults;
223 
224     /** Index of the currently selected result. */
225     int currentResultIndex;
226 
227     Task *searchTask;
228     int previousMaxResult;
229     QStringList currentSearchPatternList;
230     QMovie *progressMovie;
231     bool setSelectionToTheFirstResult;
232     bool isSearchInNamesMode;
233 
234     FindPatternMsaWidgetSavableTab savableWidget;
235 
236     ShowHideSubgroupWidget *algorithmSubgroup;
237     ShowHideSubgroupWidget *searchInSubgroup;
238     ShowHideSubgroupWidget *otherSettingsSubgroup;
239 };
240 
241 }  // namespace U2
242 
243 #endif  // _U2_FIND_PATTERN_WIDGET_H_
244