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 <drivers/GTKeyboardDriver.h>
23 #include <drivers/GTMouseDriver.h>
24 #include <primitives/GTScrollBar.h>
25 #include <primitives/GTToolbar.h>
26 #include <primitives/GTWidget.h>
27 #include <utils/GTThread.h>
28 
29 #include <QLabel>
30 #include <QTextDocument>
31 
32 #include <U2Core/AppContext.h>
33 #include <U2Core/U2SafePoints.h>
34 
35 #include <U2View/MSAEditorOffsetsView.h>
36 #include <U2View/MaEditorFactory.h>
37 #include <U2View/McaEditor.h>
38 #include <U2View/McaEditorConsensusArea.h>
39 #include <U2View/McaEditorNameList.h>
40 #include <U2View/McaEditorReferenceArea.h>
41 #include <U2View/McaEditorSequenceArea.h>
42 #include <U2View/RowHeightController.h>
43 #include <U2View/ScrollController.h>
44 
45 #include "GTUtilsMcaEditor.h"
46 #include "GTUtilsMcaEditorSequenceArea.h"
47 #include "GTUtilsMdi.h"
48 
49 namespace U2 {
50 using namespace HI;
51 
52 #define GT_CLASS_NAME "GTUtilsMcaEditor"
53 
54 #define GT_METHOD_NAME "getActiveMcaEditorWindow"
getActiveMcaEditorWindow(GUITestOpStatus & os)55 QWidget *GTUtilsMcaEditor::getActiveMcaEditorWindow(GUITestOpStatus &os) {
56     QWidget *widget = GTUtilsMdi::getActiveObjectViewWindow(os, McaEditorFactory::ID);
57     GTThread::waitForMainThread();
58     return widget;
59 }
60 #undef GT_METHOD_NAME
61 
62 #define GT_METHOD_NAME "checkMcaEditorWindowIsActive"
checkMcaEditorWindowIsActive(GUITestOpStatus & os)63 void GTUtilsMcaEditor::checkMcaEditorWindowIsActive(GUITestOpStatus &os) {
64     getActiveMcaEditorWindow(os);
65 }
66 #undef GT_METHOD_NAME
67 
68 #define GT_METHOD_NAME "getEditor"
getEditor(GUITestOpStatus & os)69 McaEditor *GTUtilsMcaEditor::getEditor(GUITestOpStatus &os) {
70     McaEditorWgt *editorUi = getEditorUi(os);
71     McaEditor *editor = editorUi->getEditor();
72     GT_CHECK_RESULT(editor != nullptr, "MCA Editor is NULL", nullptr);
73     return editor;
74 }
75 #undef GT_METHOD_NAME
76 
77 #define GT_METHOD_NAME "getEditorUi"
getEditorUi(GUITestOpStatus & os)78 McaEditorWgt *GTUtilsMcaEditor::getEditorUi(GUITestOpStatus &os) {
79     checkMcaEditorWindowIsActive(os);
80     McaEditorWgt *mcaEditorWgt = nullptr;
81     // For some reason McaEditorWgt is not within normal widgets hierarchy (wrong parent?), so can't use GTWidget::findWidget here.
82     for (int time = 0; time < GT_OP_WAIT_MILLIS && mcaEditorWgt == nullptr; time += GT_OP_CHECK_MILLIS) {
83         GTGlobals::sleep(time > 0 ? GT_OP_CHECK_MILLIS : 0);
84         MainWindow *mainWindow = AppContext::getMainWindow();
85         QWidget *activeWindow = mainWindow == nullptr ? nullptr : mainWindow->getMDIManager()->getActiveWindow();
86         if (activeWindow == nullptr) {
87             continue;
88         }
89         mcaEditorWgt = activeWindow->findChild<McaEditorWgt *>();
90     }
91     GT_CHECK_RESULT(mcaEditorWgt != nullptr, "MCA Editor widget is NULL", nullptr);
92     return mcaEditorWgt;
93 }
94 #undef GT_METHOD_NAME
95 
96 #define GT_METHOD_NAME "getReferenceLabel"
getReferenceLabel(GUITestOpStatus & os)97 QLabel *GTUtilsMcaEditor::getReferenceLabel(GUITestOpStatus &os) {
98     QWidget *referenceLabelContainerWidget = GTWidget::findExactWidget<QWidget *>(os, "reference label container widget", getEditorUi(os));
99     GT_CHECK_RESULT(nullptr != referenceLabelContainerWidget, "Reference label not found", nullptr);
100     return GTWidget::findExactWidget<QLabel *>(os, "", referenceLabelContainerWidget);
101 }
102 #undef GT_METHOD_NAME
103 
104 #define GT_METHOD_NAME "getNameListArea"
getNameListArea(GUITestOpStatus & os)105 McaEditorNameList *GTUtilsMcaEditor::getNameListArea(GUITestOpStatus &os) {
106     return GTWidget::findExactWidget<McaEditorNameList *>(os, "mca_editor_name_list", getEditorUi(os));
107 }
108 #undef GT_METHOD_NAME
109 
110 #define GT_METHOD_NAME "getSequenceArea"
getSequenceArea(GUITestOpStatus & os)111 McaEditorSequenceArea *GTUtilsMcaEditor::getSequenceArea(GUITestOpStatus &os) {
112     return GTWidget::findExactWidget<McaEditorSequenceArea *>(os, "mca_editor_sequence_area", getEditorUi(os));
113 }
114 #undef GT_METHOD_NAME
115 
116 #define GT_METHOD_NAME "getConsensusArea"
getConsensusArea(GUITestOpStatus & os)117 McaEditorConsensusArea *GTUtilsMcaEditor::getConsensusArea(GUITestOpStatus &os) {
118     QWidget *activeWindow = getActiveMcaEditorWindow(os);
119     return GTWidget::findExactWidget<McaEditorConsensusArea *>(os, "consArea", activeWindow);
120 }
121 #undef GT_METHOD_NAME
122 
123 #define GT_METHOD_NAME "getReferenceArea"
getReferenceArea(GUITestOpStatus & os)124 McaEditorReferenceArea *GTUtilsMcaEditor::getReferenceArea(GUITestOpStatus &os) {
125     QWidget *activeWindow = getActiveMcaEditorWindow(os);
126     return GTWidget::findExactWidget<McaEditorReferenceArea *>(os, "mca_editor_reference_area", activeWindow);
127 }
128 #undef GT_METHOD_NAME
129 
130 #define GT_METHOD_NAME "getHorizontalScrollBar"
getHorizontalScrollBar(GUITestOpStatus & os)131 QScrollBar *GTUtilsMcaEditor::getHorizontalScrollBar(GUITestOpStatus &os) {
132     return GTWidget::findExactWidget<QScrollBar *>(os, "horizontal_sequence_scroll", getEditorUi(os));
133 }
134 #undef GT_METHOD_NAME
135 
136 #define GT_METHOD_NAME "getVerticalScrollBar"
getVerticalScrollBar(GUITestOpStatus & os)137 QScrollBar *GTUtilsMcaEditor::getVerticalScrollBar(GUITestOpStatus &os) {
138     return GTWidget::findExactWidget<QScrollBar *>(os, "vertical_sequence_scroll", getEditorUi(os));
139 }
140 #undef GT_METHOD_NAME
141 
142 #define GT_METHOD_NAME "getMcaRow"
getMcaRow(GUITestOpStatus & os,int rowNum)143 MultipleAlignmentRowData *GTUtilsMcaEditor::getMcaRow(GUITestOpStatus &os, int rowNum) {
144     McaEditor *mcaEditor = GTUtilsMcaEditor::getEditor(os);
145     MultipleChromatogramAlignmentObject *maObj = mcaEditor->getMaObject();
146     GT_CHECK_RESULT(maObj != nullptr, "MultipleChromatogramAlignmentObject not found", nullptr);
147 
148     MultipleAlignmentRow row = maObj->getRow(rowNum);
149     return row.data();
150 }
151 #undef GT_METHOD_NAME
152 
153 #define GT_METHOD_NAME "getOffsetAction"
getOffsetAction(GUITestOpStatus & os)154 QAction *GTUtilsMcaEditor::getOffsetAction(GUITestOpStatus &os) {
155     McaEditorWgt *editorWgt = GTUtilsMcaEditor::getEditorUi(os);
156     GT_CHECK_RESULT(editorWgt != nullptr, "McaEditorWgt not found", nullptr);
157 
158     MSAEditorOffsetsViewController *offsetController = editorWgt->getOffsetsViewController();
159     GT_CHECK_RESULT(offsetController != nullptr, "MSAEditorOffsetsViewController is NULL", nullptr);
160     return offsetController->toggleColumnsViewAction;
161 }
162 
163 #undef GT_METHOD_NAME
164 
165 #define GT_METHOD_NAME "getReferenceLabelText"
getReferenceLabelText(GUITestOpStatus & os)166 QString GTUtilsMcaEditor::getReferenceLabelText(GUITestOpStatus &os) {
167     QLabel *referenceLabel = getReferenceLabel(os);
168     GT_CHECK_RESULT(nullptr != referenceLabel, "Reference label is NULL", "");
169     if (referenceLabel->textFormat() != Qt::PlainText) {
170         QTextDocument textDocument;
171         textDocument.setHtml(referenceLabel->text());
172         return textDocument.toPlainText();
173     } else {
174         return referenceLabel->text();
175     }
176 }
177 #undef GT_METHOD_NAME
178 
179 #define GT_METHOD_NAME "getReadsCount"
getReadsCount(GUITestOpStatus & os)180 int GTUtilsMcaEditor::getReadsCount(GUITestOpStatus &os) {
181     QWidget *statusBar = GTWidget::findWidget(os, "mca_editor_status_bar", getEditorUi(os));
182     QLabel *readsCountLabel = GTWidget::findExactWidget<QLabel *>(os, "Line", statusBar);
183 
184     QRegExp readsCounRegExp("Ln \\d+|\\- / (\\d+)");
185     readsCounRegExp.indexIn(readsCountLabel->text());
186     const QString totalReadsCountString = readsCounRegExp.cap(1);
187 
188     bool isNumber = false;
189     const int totalReadsCount = totalReadsCountString.toInt(&isNumber);
190     GT_CHECK_RESULT(isNumber, QString("Can't convert the reads count string to number: %1").arg(totalReadsCountString), -1);
191 
192     return totalReadsCount;
193 }
194 #undef GT_METHOD_NAME
195 
196 #define GT_METHOD_NAME "getReadsNames"
getReadsNames(GUITestOpStatus & os)197 const QStringList GTUtilsMcaEditor::getReadsNames(GUITestOpStatus &os) {
198     return getEditor(os)->getMaObject()->getMultipleAlignment()->getRowNames();
199 }
200 #undef GT_METHOD_NAME
201 
202 #define GT_METHOD_NAME "getDirectReadsNames"
getDirectReadsNames(GUITestOpStatus & os)203 const QStringList GTUtilsMcaEditor::getDirectReadsNames(GUITestOpStatus &os) {
204     QStringList directReadsNames;
205     MultipleChromatogramAlignmentObject *mcaObject = getEditor(os)->getMaObject();
206     const int rowsCount = mcaObject->getNumRows();
207     for (int i = 0; i < rowsCount; i++) {
208         if (!mcaObject->getMcaRow(i)->isReversed()) {
209             directReadsNames << mcaObject->getMcaRow(i)->getName();
210         }
211     }
212     return directReadsNames;
213 }
214 #undef GT_METHOD_NAME
215 
216 #define GT_METHOD_NAME "getReverseComplementReadsNames"
getReverseComplementReadsNames(GUITestOpStatus & os)217 const QStringList GTUtilsMcaEditor::getReverseComplementReadsNames(GUITestOpStatus &os) {
218     QStringList reverseComplementedReadsNames;
219     MultipleChromatogramAlignmentObject *mcaObject = getEditor(os)->getMaObject();
220     const int rowsCount = mcaObject->getNumRows();
221     for (int i = 0; i < rowsCount; i++) {
222         if (mcaObject->getMcaRow(i)->isReversed()) {
223             reverseComplementedReadsNames << mcaObject->getMcaRow(i)->getName();
224         }
225     }
226     return reverseComplementedReadsNames;
227 }
228 #undef GT_METHOD_NAME
229 
230 #define GT_METHOD_NAME "getReadNameRect"
getReadNameRect(GUITestOpStatus & os,const QString & readName)231 QRect GTUtilsMcaEditor::getReadNameRect(GUITestOpStatus &os, const QString &readName) {
232     McaEditorNameList *nameList = getNameListArea(os);
233     GT_CHECK_RESULT(nullptr != nameList, "McaEditorNameList not found", QRect());
234 
235     const QStringList names = GTUtilsMcaEditorSequenceArea::getVisibleNames(os);
236     const int rowNumber = names.indexOf(readName);
237     GT_CHECK_RESULT(0 <= rowNumber, QString("Read '%1' not found").arg(readName), QRect());
238     return getReadNameRect(os, rowNumber);
239 }
240 #undef GT_METHOD_NAME
241 
242 #define GT_METHOD_NAME "getReadNameRect"
getReadNameRect(GUITestOpStatus & os,int rowNumber)243 QRect GTUtilsMcaEditor::getReadNameRect(GUITestOpStatus &os, int rowNumber) {
244     Q_UNUSED(os);
245     GT_CHECK_RESULT(0 <= rowNumber, QString("Read '%1' not found").arg(rowNumber), QRect());
246 
247     McaEditorNameList *nameList = getNameListArea(os);
248     GT_CHECK_RESULT(nullptr != nameList, "McaEditorNameList not found", QRect());
249 
250     const U2Region rowScreenRange = getEditorUi(os)->getRowHeightController()->getScreenYRegionByViewRowIndex(rowNumber);
251     return QRect(nameList->mapToGlobal(QPoint(0, rowScreenRange.startPos)), nameList->mapToGlobal(QPoint(nameList->width(), rowScreenRange.endPos())));
252 }
253 #undef GT_METHOD_NAME
254 
255 #define GT_METHOD_NAME "scrollToRead"
scrollToRead(GUITestOpStatus & os,const QString & readName)256 void GTUtilsMcaEditor::scrollToRead(GUITestOpStatus &os, const QString &readName) {
257     scrollToRead(os, readName2readNumber(os, readName));
258 }
259 #undef GT_METHOD_NAME
260 
261 #define GT_METHOD_NAME "scrollToRead"
scrollToRead(GUITestOpStatus & os,int readNumber)262 void GTUtilsMcaEditor::scrollToRead(GUITestOpStatus &os, int readNumber) {
263     McaEditorWgt *mcaEditorWgt = getEditorUi(os);
264     const U2Region rowRange = mcaEditorWgt->getRowHeightController()->getGlobalYRegionByViewRowIndex(readNumber);
265     CHECK(!U2Region(mcaEditorWgt->getScrollController()->getScreenPosition().y(), getNameListArea(os)->height()).contains(rowRange), );
266     GTScrollBar::moveSliderWithMouseToValue(os, getVerticalScrollBar(os), rowRange.center() - mcaEditorWgt->getSequenceArea()->height() / 2);
267 }
268 #undef GT_METHOD_NAME
269 
270 #define GT_METHOD_NAME "moveToReadName"
moveToReadName(GUITestOpStatus & os,const QString & readName)271 void GTUtilsMcaEditor::moveToReadName(GUITestOpStatus &os, const QString &readName) {
272     moveToReadName(os, readName2readNumber(os, readName));
273 }
274 #undef GT_METHOD_NAME
275 
276 #define GT_METHOD_NAME "moveToReadName"
moveToReadName(GUITestOpStatus & os,int readNumber)277 void GTUtilsMcaEditor::moveToReadName(GUITestOpStatus &os, int readNumber) {
278     scrollToRead(os, readNumber);
279     const QRect readNameRect = getReadNameRect(os, readNumber);
280     GTMouseDriver::moveTo(readNameRect.center());
281 }
282 #undef GT_METHOD_NAME
283 
284 #define GT_METHOD_NAME "clickReadName"
clickReadName(GUITestOpStatus & os,const QString & readName,Qt::MouseButton mouseButton)285 void GTUtilsMcaEditor::clickReadName(GUITestOpStatus &os, const QString &readName, Qt::MouseButton mouseButton) {
286     clickReadName(os, readName2readNumber(os, readName), mouseButton);
287 }
288 #undef GT_METHOD_NAME
289 
290 #define GT_METHOD_NAME "clickReadName"
clickReadName(GUITestOpStatus & os,int readNumber,Qt::MouseButton mouseButton)291 void GTUtilsMcaEditor::clickReadName(GUITestOpStatus &os, int readNumber, Qt::MouseButton mouseButton) {
292     moveToReadName(os, readNumber);
293     GTMouseDriver::click(mouseButton);
294 }
295 #undef GT_METHOD_NAME
296 
297 #define GT_METHOD_NAME "doubleClickReadName"
doubleClickReadName(GUITestOpStatus & os,int readIndex)298 void GTUtilsMcaEditor::doubleClickReadName(GUITestOpStatus &os, int readIndex) {
299     moveToReadName(os, readIndex);
300     GTMouseDriver::doubleClick();
301 }
302 #undef GT_METHOD_NAME
303 
304 #define GT_METHOD_NAME "undo"
removeRead(GUITestOpStatus & os,const QString & readName)305 void GTUtilsMcaEditor::removeRead(GUITestOpStatus &os, const QString &readName) {
306     clickReadName(os, readName);
307     GTKeyboardDriver::keyClick(Qt::Key_Delete);
308     GTGlobals::sleep(500);
309 }
310 #undef GT_METHOD_NAME
311 
312 #define GT_METHOD_NAME "undo"
undo(GUITestOpStatus & os)313 void GTUtilsMcaEditor::undo(GUITestOpStatus &os) {
314     GTWidget::click(os, GTToolbar::getWidgetForActionObjectName(os, GTToolbar::getToolbar(os, MWTOOLBAR_ACTIVEMDI), "msa_action_undo"));
315 }
316 #undef GT_METHOD_NAME
317 
318 #define GT_METHOD_NAME "redo"
redo(GUITestOpStatus & os)319 void GTUtilsMcaEditor::redo(GUITestOpStatus &os) {
320     GTWidget::click(os, GTToolbar::getWidgetForActionObjectName(os, GTToolbar::getToolbar(os, MWTOOLBAR_ACTIVEMDI), "msa_action_redo"));
321 }
322 #undef GT_METHOD_NAME
323 
324 #define GT_METHOD_NAME "zoomIn"
zoomIn(HI::GUITestOpStatus & os)325 void GTUtilsMcaEditor::zoomIn(HI::GUITestOpStatus &os) {
326     GTWidget::click(os, GTToolbar::getWidgetForActionObjectName(os, GTToolbar::getToolbar(os, MWTOOLBAR_ACTIVEMDI), "Zoom In"));
327 }
328 #undef GT_METHOD_NAME
329 
330 #define GT_METHOD_NAME "zoomOut"
zoomOut(HI::GUITestOpStatus & os)331 void GTUtilsMcaEditor::zoomOut(HI::GUITestOpStatus &os) {
332     GTWidget::click(os, GTToolbar::getWidgetForActionObjectName(os, GTToolbar::getToolbar(os, MWTOOLBAR_ACTIVEMDI), "Zoom Out"));
333 }
334 #undef GT_METHOD_NAME
335 
336 #define GT_METHOD_NAME "resetZoom"
resetZoom(HI::GUITestOpStatus & os)337 void GTUtilsMcaEditor::resetZoom(HI::GUITestOpStatus &os) {
338     GTWidget::click(os, GTToolbar::getWidgetForActionObjectName(os, GTToolbar::getToolbar(os, MWTOOLBAR_ACTIVEMDI), "Reset Zoom"));
339 }
340 #undef GT_METHOD_NAME
341 
342 #define GT_METHOD_NAME "isUndoEnabled"
isUndoEnabled(GUITestOpStatus & os)343 bool GTUtilsMcaEditor::isUndoEnabled(GUITestOpStatus &os) {
344     return GTToolbar::getWidgetForActionObjectName(os, GTToolbar::getToolbar(os, MWTOOLBAR_ACTIVEMDI), "msa_action_undo")->isEnabled();
345 }
346 #undef GT_METHOD_NAME
347 
348 #define GT_METHOD_NAME "isRedoEnabled"
isRedoEnabled(GUITestOpStatus & os)349 bool GTUtilsMcaEditor::isRedoEnabled(GUITestOpStatus &os) {
350     return GTToolbar::getWidgetForActionObjectName(os, GTToolbar::getToolbar(os, MWTOOLBAR_ACTIVEMDI), "msa_action_redo")->isEnabled();
351 }
352 #undef GT_METHOD_NAME
353 
354 #define GT_METHOD_NAME "toggleShowChromatogramsMode"
toggleShowChromatogramsMode(GUITestOpStatus & os)355 void GTUtilsMcaEditor::toggleShowChromatogramsMode(GUITestOpStatus &os) {
356     GTWidget::click(os, GTToolbar::getWidgetForActionTooltip(os, GTToolbar::getToolbar(os, MWTOOLBAR_ACTIVEMDI), "Show chromatograms"));
357 }
358 #undef GT_METHOD_NAME
359 
360 #define GT_METHOD_NAME "readName2readNumber"
readName2readNumber(GUITestOpStatus & os,const QString & readName)361 int GTUtilsMcaEditor::readName2readNumber(GUITestOpStatus &os, const QString &readName) {
362     const QStringList names = GTUtilsMcaEditorSequenceArea::getVisibleNames(os);
363     const int rowNumber = names.indexOf(readName);
364     GT_CHECK_RESULT(0 <= rowNumber, QString("Read '%1' not found").arg(readName), -1);
365     return rowNumber;
366 }
367 #undef GT_METHOD_NAME
368 
369 #undef GT_CLASS_NAME
370 
371 }  // namespace U2
372