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 <api/GTMSAEditorStatusWidget.h>
23 #include <drivers/GTKeyboardDriver.h>
24 #include <drivers/GTMouseDriver.h>
25 #include <primitives/GTAction.h>
26 #include <primitives/GTWidget.h>
27 #include <primitives/PopupChooser.h>
28 #include <system/GTClipboard.h>
29 #include <utils/GTKeyboardUtils.h>
30 #include <utils/GTThread.h>
31 
32 #include <QStyle>
33 #include <QStyleOptionSlider>
34 
35 #include <U2Core/U2SafePoints.h>
36 
37 #include <U2View/BaseWidthController.h>
38 #include <U2View/DrawHelper.h>
39 #include <U2View/MSAEditor.h>
40 #include <U2View/MSAEditorConsensusArea.h>
41 #include <U2View/MaEditorSelection.h>
42 #include <U2View/MsaEditorSimilarityColumn.h>
43 #include <U2View/RowHeightController.h>
44 #include <U2View/ScrollController.h>
45 
46 #include "GTUtilsMdi.h"
47 #include "GTUtilsMsaEditor.h"
48 #include "GTUtilsMsaEditorSequenceArea.h"
49 #include "runnables/ugene/corelibs/U2Gui/util/RenameSequenceFiller.h"
50 
51 namespace U2 {
52 using namespace HI;
53 const QString GTUtilsMSAEditorSequenceArea::highlightingColor = "#9999cc";
54 
55 #define GT_CLASS_NAME "GTUtilsMSAEditorSequenceArea"
56 
57 #define GT_METHOD_NAME "getSequenceArea"
getSequenceArea(GUITestOpStatus & os)58 MSAEditorSequenceArea *GTUtilsMSAEditorSequenceArea::getSequenceArea(GUITestOpStatus &os) {
59     QWidget *activeWindow = GTUtilsMsaEditor::getActiveMsaEditorWindow(os);
60     MSAEditorSequenceArea *result = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area", activeWindow));
61     GT_CHECK_RESULT(result != nullptr, "MsaEditorSequenceArea is not found", nullptr);
62     return result;
63 }
64 #undef GT_METHOD_NAME
65 
66 #define GT_METHOD_NAME "callContextMenu"
callContextMenu(GUITestOpStatus & os,const QPoint & innerCoords)67 void GTUtilsMSAEditorSequenceArea::callContextMenu(GUITestOpStatus &os, const QPoint &innerCoords) {
68     if (innerCoords.isNull()) {
69         GTWidget::click(os, getSequenceArea(os), Qt::RightButton);
70     } else {
71         moveTo(os, innerCoords);
72         GTMouseDriver::click(Qt::RightButton);
73     }
74 }
75 #undef GT_METHOD_NAME
76 
77 #define GT_METHOD_NAME "moveTo"
moveTo(GUITestOpStatus & os,const QPoint & p)78 void GTUtilsMSAEditorSequenceArea::moveTo(GUITestOpStatus &os, const QPoint &p) {
79     QPoint convP = convertCoordinates(os, p);
80 
81     GTMouseDriver::moveTo(convP);
82 }
83 #undef GT_METHOD_NAME
84 
85 #define GT_METHOD_NAME "getPositionRect"
getPositionRect(GUITestOpStatus & os,const QPoint & position)86 QRect GTUtilsMSAEditorSequenceArea::getPositionRect(GUITestOpStatus &os, const QPoint &position) {
87     QWidget *activeWindow = GTUtilsMsaEditor::getActiveMsaEditorWindow(os);
88     MSAEditorSequenceArea *msaEditArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area", activeWindow));
89     GT_CHECK_RESULT(msaEditArea != nullptr, "MsaEditorSequenceArea not found", QRect());
90 
91     MsaEditorWgt *msaEditorWidget = msaEditArea->getEditor()->getUI();
92     U2Region regX = msaEditorWidget->getBaseWidthController()->getBaseGlobalRange(position.x());
93     U2Region regY = msaEditorWidget->getRowHeightController()->getGlobalYRegionByViewRowIndex(position.y());
94 
95     QPoint topLeftGlobalPoint = msaEditArea->mapToGlobal(QPoint(regX.startPos, regY.startPos));
96     QPoint bottomRightGlobalPoint = msaEditArea->mapToGlobal(QPoint(regX.endPos(), regY.endPos()));
97 
98     return QRect(topLeftGlobalPoint, bottomRightGlobalPoint);
99 }
100 #undef GT_METHOD_NAME
101 
102 #define GT_METHOD_NAME "convertCoordinates"
convertCoordinates(GUITestOpStatus & os,const QPoint p)103 QPoint GTUtilsMSAEditorSequenceArea::convertCoordinates(GUITestOpStatus &os, const QPoint p) {
104     QWidget *activeWindow = GTUtilsMsaEditor::getActiveMsaEditorWindow(os);
105     MSAEditorSequenceArea *msaEditArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area", activeWindow));
106     GT_CHECK_RESULT(msaEditArea != nullptr, "MsaEditorSequenceArea not found", QPoint());
107 
108     const int posX = static_cast<int>(msaEditArea->getEditor()->getUI()->getBaseWidthController()->getBaseGlobalRange(p.x()).center());
109     const int posY = static_cast<int>(msaEditArea->getEditor()->getUI()->getRowHeightController()->getGlobalYRegionByViewRowIndex(p.y()).center());
110     return msaEditArea->mapToGlobal(QPoint(posX, posY));
111 }
112 #undef GT_METHOD_NAME
113 
114 #define GT_METHOD_NAME "selectArea"
selectArea(GUITestOpStatus & os,QPoint p1,QPoint p2,GTGlobals::UseMethod method)115 void GTUtilsMSAEditorSequenceArea::selectArea(GUITestOpStatus &os, QPoint p1, QPoint p2, GTGlobals::UseMethod method) {
116     QWidget *msaEditor = GTUtilsMsaEditor::getActiveMsaEditorWindow(os);
117     MSAEditorSequenceArea *sequenceArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area", msaEditor));
118     GT_CHECK(sequenceArea != nullptr, "MsaEditorSequenceArea not found");
119 
120     p1.rx() = (p1.x() == -1 ? sequenceArea->getNumVisibleBases() - 1 : p1.x());
121     p1.ry() = (p1.y() == -1 ? sequenceArea->getViewRowCount() - 1 : p1.y());
122 
123     p2.rx() = (p2.x() == -1 ? sequenceArea->getNumVisibleBases() - 1 : p2.x());
124     p2.ry() = (p2.y() == -1 ? sequenceArea->getViewRowCount() - 1 : p2.y());
125 
126     switch (method) {
127         case GTGlobals::UseKey:
128             clickToPosition(os, p1);
129             GTKeyboardDriver::keyPress(Qt::Key_Shift);
130             clickToPosition(os, p2);
131             GTKeyboardDriver::keyRelease(Qt::Key_Shift);
132             break;
133         case GTGlobals::UseMouse:
134             GTMouseDriver::dragAndDrop(convertCoordinates(os, p1), convertCoordinates(os, p2));
135             break;
136         case GTGlobals::UseKeyBoard:
137             GT_CHECK(false, "Not implemented");
138         default:
139             GT_CHECK(false, "An unknown method");
140     }
141 }
142 #undef GT_METHOD_NAME
143 
144 #define GT_METHOD_NAME "cancelSelection"
cancelSelection(GUITestOpStatus &)145 void GTUtilsMSAEditorSequenceArea::cancelSelection(GUITestOpStatus & /*os*/) {
146     GTKeyboardDriver::keyClick(Qt::Key_Escape);
147 }
148 #undef GT_METHOD_NAME
149 
150 #define GT_METHOD_NAME "click"
click(GUITestOpStatus & os,const QPoint & screenMaPoint)151 void GTUtilsMSAEditorSequenceArea::click(GUITestOpStatus &os, const QPoint &screenMaPoint) {
152     GTMouseDriver::moveTo(convertCoordinates(os, screenMaPoint));
153     GTMouseDriver::click();
154 }
155 #undef GT_METHOD_NAME
156 
157 #define GT_METHOD_NAME "copySelectionByContextMenu"
copySelectionByContextMenu(GUITestOpStatus & os)158 void GTUtilsMSAEditorSequenceArea::copySelectionByContextMenu(GUITestOpStatus &os) {
159     GTUtilsDialog::waitForDialog(os, new PopupChooserByText(os, QStringList() << "Copy/Paste"
160                                                                               << "Copy"));
161     GTUtilsMSAEditorSequenceArea::callContextMenu(os);
162 }
163 #undef GT_METHOD_NAME
164 
165 #define GT_METHOD_NAME "scrollToPosition"
scrollToPosition(GUITestOpStatus & os,const QPoint & position)166 void GTUtilsMSAEditorSequenceArea::scrollToPosition(GUITestOpStatus &os, const QPoint &position) {
167     MSAEditorSequenceArea *msaSeqArea = GTWidget::findExactWidget<MSAEditorSequenceArea *>(os, "msa_editor_sequence_area", GTUtilsMsaEditor::getActiveMsaEditorWindow(os));
168     GT_CHECK(msaSeqArea != nullptr, "MSA Editor sequence area is not found");
169     GT_CHECK(msaSeqArea->isInRange(position),
170              QString("Position is out of range: [%1, %2], range: [%3, %4]")
171                  .arg(position.x())
172                  .arg(position.y())
173                  .arg(msaSeqArea->getEditor()->getAlignmentLen())
174                  .arg(msaSeqArea->getViewRowCount()));
175 
176     // scroll down
177     GScrollBar *vBar = GTWidget::findExactWidget<GScrollBar *>(os, "vertical_sequence_scroll", GTUtilsMsaEditor::getActiveMsaEditorWindow(os));
178     GT_CHECK(vBar != nullptr, "Vertical scroll bar is not found");
179 
180     QStyleOptionSlider vScrollBarOptions;
181     vScrollBarOptions.initFrom(vBar);
182 
183     while (!msaSeqArea->isRowVisible(position.y(), false)) {
184         const QRect sliderSpaceRect = vBar->style()->subControlRect(QStyle::CC_ScrollBar, &vScrollBarOptions, QStyle::SC_ScrollBarGroove, vBar);
185         const QPoint bottomEdge(sliderSpaceRect.width() / 2, sliderSpaceRect.y() + sliderSpaceRect.height());
186 
187         GTMouseDriver::moveTo(vBar->mapToGlobal(bottomEdge) - QPoint(0, 1));
188         GTMouseDriver::click();
189     }
190 
191     // scroll right
192     GScrollBar *hBar = GTWidget::findExactWidget<GScrollBar *>(os, "horizontal_sequence_scroll", GTUtilsMsaEditor::getActiveMsaEditorWindow(os));
193     GT_CHECK(hBar != nullptr, "Horizontal scroll bar is not found");
194 
195     QStyleOptionSlider hScrollBarOptions;
196     hScrollBarOptions.initFrom(hBar);
197 
198     while (!msaSeqArea->isPositionVisible(position.x(), false)) {
199         const QRect sliderSpaceRect = hBar->style()->subControlRect(QStyle::CC_ScrollBar, &hScrollBarOptions, QStyle::SC_ScrollBarGroove, hBar);
200         const QPoint rightEdge(sliderSpaceRect.x() + sliderSpaceRect.width(), sliderSpaceRect.height() / 2);
201 
202         int lastBase = msaSeqArea->getLastVisibleBase(true);
203         QPoint p;
204         if (position.x() == lastBase) {
205             p = hBar->mapToGlobal(rightEdge) + QPoint(3, 0);
206         } else {
207             p = hBar->mapToGlobal(rightEdge) - QPoint(1, 0);
208         }
209         GTMouseDriver::moveTo(p);
210         GTMouseDriver::click();
211     }
212 
213     SAFE_POINT(msaSeqArea->isVisible(position, false), "The position is still invisible after scrolling", );
214 }
215 #undef GT_METHOD_NAME
216 
217 #define GT_METHOD_NAME "scrollToBottom"
scrollToBottom(GUITestOpStatus & os)218 void GTUtilsMSAEditorSequenceArea::scrollToBottom(GUITestOpStatus &os) {
219     // scroll down
220     GScrollBar *vBar = GTWidget::findExactWidget<GScrollBar *>(os, "vertical_sequence_scroll", GTUtilsMsaEditor::getActiveMsaEditorWindow(os));
221     GT_CHECK(vBar != nullptr, "Vertical scroll bar is not found");
222 #ifdef Q_OS_DARWIN
223     vBar->setValue(vBar->maximum());
224     return;
225 #endif
226 
227     QStyleOptionSlider vScrollBarOptions;
228     vScrollBarOptions.initFrom(vBar);
229 
230     while (vBar->value() != vBar->maximum()) {
231         const QRect sliderSpaceRect = vBar->style()->subControlRect(QStyle::CC_ScrollBar, &vScrollBarOptions, QStyle::SC_ScrollBarGroove, vBar);
232         const QPoint bottomEdge(sliderSpaceRect.width() / 2 + 10, sliderSpaceRect.y() + sliderSpaceRect.height());
233 
234         GTMouseDriver::moveTo(vBar->mapToGlobal(bottomEdge) - QPoint(0, 1));
235         GTMouseDriver::click();
236     }
237 }
238 #undef GT_METHOD_NAME
239 
240 #define GT_METHOD_NAME "moveMouseToPosition"
moveMouseToPosition(GUITestOpStatus & os,const QPoint & globalMaPosition)241 void GTUtilsMSAEditorSequenceArea::moveMouseToPosition(GUITestOpStatus &os, const QPoint &globalMaPosition) {
242     MSAEditorSequenceArea *msaSeqArea = GTWidget::findExactWidget<MSAEditorSequenceArea *>(os, "msa_editor_sequence_area", GTUtilsMsaEditor::getActiveMsaEditorWindow(os));
243     GT_CHECK(msaSeqArea != nullptr, "MSA Editor sequence area is not found");
244     GT_CHECK(msaSeqArea->isInRange(globalMaPosition),
245              QString("Position is out of range: [%1, %2], range: [%3, %4]")
246                  .arg(globalMaPosition.x())
247                  .arg(globalMaPosition.y())
248                  .arg(msaSeqArea->getEditor()->getAlignmentLen())
249                  .arg(msaSeqArea->getViewRowCount()));
250 
251     scrollToPosition(os, globalMaPosition);
252     const QPoint positionCenter(msaSeqArea->getEditor()->getUI()->getBaseWidthController()->getBaseScreenCenter(globalMaPosition.x()),
253                                 msaSeqArea->getEditor()->getUI()->getRowHeightController()->getScreenYRegionByViewRowIndex(globalMaPosition.y()).center());
254     GT_CHECK(msaSeqArea->rect().contains(positionCenter, false), "Position is not visible");
255 
256     GTMouseDriver::moveTo(msaSeqArea->mapToGlobal(positionCenter));
257 }
258 #undef GT_METHOD_NAME
259 
260 #define GT_METHOD_NAME "clickToPosition"
clickToPosition(GUITestOpStatus & os,const QPoint & globalMaPosition)261 void GTUtilsMSAEditorSequenceArea::clickToPosition(GUITestOpStatus &os, const QPoint &globalMaPosition) {
262     GTUtilsMSAEditorSequenceArea::moveMouseToPosition(os, globalMaPosition);
263     GTMouseDriver::click();
264 }
265 #undef GT_METHOD_NAME
266 
267 #define GT_METHOD_NAME "checkSelectedRect"
checkSelectedRect(GUITestOpStatus & os,const QRect & expectedRect)268 void GTUtilsMSAEditorSequenceArea::checkSelectedRect(GUITestOpStatus &os, const QRect &expectedRect) {
269     auto msaEditArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area"));
270     CHECK_SET_ERR(msaEditArea != nullptr, "MsaEditorSequenceArea not found");
271 
272     QRect msaEditRegion = msaEditArea->getEditor()->getSelection().toRect();
273     CHECK_SET_ERR(expectedRect == msaEditRegion, QString("Unexpected selection region. Expected: [(%1,%2) (%3,%4)]. Actual: [(%5,%6) (%7,%8)]").arg(expectedRect.topLeft().x()).arg(expectedRect.topLeft().y()).arg(expectedRect.bottomRight().x()).arg(expectedRect.bottomRight().y()).arg(msaEditRegion.topLeft().x()).arg(msaEditRegion.topLeft().y()).arg(msaEditRegion.bottomRight().x()).arg(msaEditRegion.bottomRight().y()));
274 }
275 #undef GT_METHOD_NAME
276 
277 #define GT_METHOD_NAME "getNameList"
getNameList(GUITestOpStatus & os)278 QStringList GTUtilsMSAEditorSequenceArea::getNameList(GUITestOpStatus &os) {
279     MSAEditor *editor = GTUtilsMsaEditor::getEditor(os);
280     QStringList result = editor->getMaObject()->getMultipleAlignment()->getRowNames();
281     return result;
282 }
283 #undef GT_METHOD_NAME
284 
285 #define GT_METHOD_NAME "getCurrentRowNames"
getCurrentRowNames(GUITestOpStatus & os)286 QStringList GTUtilsMSAEditorSequenceArea::getCurrentRowNames(GUITestOpStatus &os) {
287     MSAEditor *editor = GTUtilsMsaEditor::getEditor(os);
288     MaCollapseModel *collapseModel = editor->getCollapseModel();
289     int viewRowCount = collapseModel->getViewRowCount();
290     QStringList rowNameList;
291     for (int viewRowIndex = 0; viewRowIndex < viewRowCount; viewRowIndex++) {
292         int maRowIndex = collapseModel->getMaRowIndexByViewRowIndex(viewRowIndex);
293         MultipleAlignmentRow maRow = editor->getMaObject()->getRow(maRowIndex);
294         rowNameList << maRow->getName();
295     }
296     return rowNameList;
297 }
298 #undef GT_METHOD_NAME
299 
300 #define GT_METHOD_NAME "hasSequencesWithNames"
hasSequencesWithNames(GUITestOpStatus & os,const QStringList & names)301 bool GTUtilsMSAEditorSequenceArea::hasSequencesWithNames(GUITestOpStatus &os, const QStringList &names) {
302     QStringList nameList = getNameList(os);
303     QStringList absentNames;
304     foreach (const QString &name, names) {
305         CHECK_CONTINUE(!nameList.contains(name));
306 
307         absentNames << name;
308     }
309     CHECK_SET_ERR_RESULT(absentNames.isEmpty(),
310                          QString("Sequences with the following names are't presented in the alignment: \"%1\".")
311                              .arg(absentNames.join("\", \"")),
312                          false);
313 
314     return true;
315 }
316 #undef GT_METHOD_NAME
317 
318 #define GT_METHOD_NAME "getVisibleNames"
getVisibleNames(GUITestOpStatus & os,bool asShownInNameList)319 QStringList GTUtilsMSAEditorSequenceArea::getVisibleNames(GUITestOpStatus &os, bool asShownInNameList) {
320     MSAEditor *editor = GTUtilsMsaEditor::getEditor(os);
321     MaEditorNameList *nameListArea = GTUtilsMsaEditor::getNameListArea(os);
322     CHECK_SET_ERR_RESULT(nameListArea != nullptr, "MSA Editor name list area is NULL", QStringList());
323 
324     const QList<int> visibleRowsIndexes = editor->getUI()->getDrawHelper()->getVisibleMaRowIndexes(nameListArea->height());
325     const MultipleSequenceAlignmentObject *msaObject = editor->getMaObject();
326 
327     QStringList visibleRowNames;
328     for (int rowIndex : qAsConst(visibleRowsIndexes)) {
329         QString name = asShownInNameList ? nameListArea->getTextForRow(rowIndex) : msaObject->getRow(rowIndex)->getName();
330         visibleRowNames << name;
331     }
332     return visibleRowNames;
333 }
334 #undef GT_METHOD_NAME
335 
336 #define GT_METHOD_NAME "removeSequence"
removeSequence(GUITestOpStatus & os,const QString & sequenceName)337 void GTUtilsMSAEditorSequenceArea::removeSequence(GUITestOpStatus &os, const QString &sequenceName) {
338     selectSequence(os, sequenceName);
339     GTKeyboardDriver::keyClick(Qt::Key_Delete);
340     GTThread::waitForMainThread();
341 }
342 #undef GT_METHOD_NAME
343 
344 #define GT_METHOD_NAME "getSimilarityValue"
getSimilarityValue(GUITestOpStatus & os,int row)345 QString GTUtilsMSAEditorSequenceArea::getSimilarityValue(GUITestOpStatus &os, int row) {
346     // bad solution, but better then nothing
347     MsaEditorSimilarityColumn *simCol = dynamic_cast<MsaEditorSimilarityColumn *>(GTWidget::findWidget(os, "msa_editor_similarity_column"));
348     GT_CHECK_RESULT(simCol != nullptr, "SimilarityColumn is NULL", "");
349 
350     return simCol->getTextForRow(row);
351 }
352 #undef GT_METHOD_NAME
353 
354 #define GT_METHOD_NAME "clickCollapseTriangle"
clickCollapseTriangle(GUITestOpStatus & os,QString seqName)355 void GTUtilsMSAEditorSequenceArea::clickCollapseTriangle(GUITestOpStatus &os, QString seqName) {
356     MSAEditorSequenceArea *msaEditArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area"));
357     GT_CHECK(msaEditArea != nullptr, "MsaEditorSequenceArea not found");
358 
359     int rowNum = getVisibleNames(os).indexOf(seqName);
360     GT_CHECK(rowNum != -1, "sequence not found in nameList");
361     QWidget *nameList = GTWidget::findWidget(os, "msa_editor_name_list");
362     QPoint localCoord = QPoint(15, msaEditArea->getEditor()->getUI()->getRowHeightController()->getScreenYRegionByViewRowIndex(rowNum).startPos + 7);
363     QPoint globalCoord = nameList->mapToGlobal(localCoord);
364     GTMouseDriver::moveTo(globalCoord);
365     GTMouseDriver::click();
366 }
367 #undef GT_METHOD_NAME
368 
369 #define GT_METHOD_NAME "isCollapsed"
isCollapsed(GUITestOpStatus & os,QString seqName)370 bool GTUtilsMSAEditorSequenceArea::isCollapsed(GUITestOpStatus &os, QString seqName) {
371     QStringList names = getNameList(os);
372     QStringList visiable = getVisibleNames(os);
373     GT_CHECK_RESULT(names.contains(seqName), "sequence " + seqName + " not found", false);
374     return !visiable.contains(seqName);
375 }
376 #undef GT_METHOD_NAME
377 
378 #define GT_METHOD_NAME "collapsingMode"
collapsingMode(GUITestOpStatus & os)379 bool GTUtilsMSAEditorSequenceArea::collapsingMode(GUITestOpStatus &os) {
380     QAbstractButton *toggleSequenceOrderButton = GTAction::button(os, "toggle_sequence_row_order_action");
381     bool nameListsAreEqual = getVisibleNames(os) == getNameList(os);
382     if (nameListsAreEqual && !toggleSequenceOrderButton->isChecked()) {
383         return false;
384     } else if (!nameListsAreEqual && toggleSequenceOrderButton->isChecked()) {
385         return true;
386     }
387     GT_CHECK_RESULT(false, "something wrong with collapsing mode", false);
388 }
389 #undef GT_METHOD_NAME
390 
391 #define GT_METHOD_NAME "getFirstVisibleBase"
getFirstVisibleBase(GUITestOpStatus & os)392 int GTUtilsMSAEditorSequenceArea::getFirstVisibleBase(GUITestOpStatus &os) {
393     MSAEditorSequenceArea *msaEditArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area"));
394     CHECK_SET_ERR_RESULT(msaEditArea != nullptr, "MsaEditorSequenceArea not found", -1);
395 
396     ScrollController *scrollController = msaEditArea->getEditor()->getUI()->getScrollController();
397     int clippedIdx = scrollController->getFirstVisibleBase(true);
398     int notClippedIdx = scrollController->getFirstVisibleBase(false);
399     return clippedIdx + (clippedIdx == notClippedIdx ? 0 : 1);
400 }
401 #undef GT_METHOD_NAME
402 
403 #define GT_METHOD_NAME "getLastVisibleBase"
getLastVisibleBase(GUITestOpStatus & os)404 int GTUtilsMSAEditorSequenceArea::getLastVisibleBase(GUITestOpStatus &os) {
405     MSAEditorSequenceArea *msaEditArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area"));
406     CHECK_SET_ERR_RESULT(msaEditArea != nullptr, "MsaEditorSequenceArea not found", -1);
407 
408     ScrollController *scrollController = msaEditArea->getEditor()->getUI()->getScrollController();
409     int clippedIdx = scrollController->getLastVisibleBase(msaEditArea->width(), true);
410     int notClippedIdx = scrollController->getLastVisibleBase(msaEditArea->width(), false);
411     return clippedIdx + (clippedIdx == notClippedIdx ? 0 : 1);
412 }
413 #undef GT_METHOD_NAME
414 
415 #define GT_METHOD_NAME "getLength"
getLength(GUITestOpStatus & os)416 int GTUtilsMSAEditorSequenceArea::getLength(GUITestOpStatus &os) {
417     QWidget *statusWidget = GTWidget::findWidget(os, "msa_editor_status_bar");
418     return GTMSAEditorStatusWidget::length(os, statusWidget);
419 }
420 #undef GT_METHOD_NAME
421 
422 #define GT_METHOD_NAME "getNumVisibleBases"
getNumVisibleBases(GUITestOpStatus & os)423 int GTUtilsMSAEditorSequenceArea::getNumVisibleBases(GUITestOpStatus &os) {
424     MSAEditorSequenceArea *msaEditArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area", GTUtilsMsaEditor::getActiveMsaEditorWindow(os)));
425     GT_CHECK_RESULT(msaEditArea != nullptr, "MsaEditorSequenceArea not found", -1);
426 
427     return msaEditArea->getEditor()->getUI()->getDrawHelper()->getVisibleBasesCount(msaEditArea->width());
428 }
429 #undef GT_METHOD_NAME
430 
431 #define GT_METHOD_NAME "getSelectedRect"
getSelectedRect(GUITestOpStatus & os)432 QRect GTUtilsMSAEditorSequenceArea::getSelectedRect(GUITestOpStatus &os) {
433     auto msaEditArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area"));
434     GT_CHECK_RESULT(msaEditArea != nullptr, "MsaEditorSequenceArea not found", QRect());
435 
436     return msaEditArea->getEditor()->getSelection().toRect();
437 }
438 #undef GT_METHOD_NAME
439 
440 #define GT_METHOD_NAME "dragAndDropSelection"
dragAndDropSelection(GUITestOpStatus & os,const QPoint & fromMaPosition,const QPoint & toMaPosition)441 void GTUtilsMSAEditorSequenceArea::dragAndDropSelection(GUITestOpStatus &os, const QPoint &fromMaPosition, const QPoint &toMaPosition) {
442     const MaEditorSelection &selection = getSequenceArea(os)->getEditor()->getSelection();
443     GT_CHECK(selection.contains(fromMaPosition), QString("Position (%1, %2) is out of selection").arg(fromMaPosition.x()).arg(fromMaPosition.y()));
444 
445     scrollToPosition(os, fromMaPosition);
446 
447     GTMouseDriver::dragAndDrop(convertCoordinates(os, fromMaPosition), convertCoordinates(os, toMaPosition));
448 }
449 #undef GT_METHOD_NAME
450 
451 #define GT_METHOD_NAME "offsetsVisible"
offsetsVisible(GUITestOpStatus & os)452 bool GTUtilsMSAEditorSequenceArea::offsetsVisible(GUITestOpStatus &os) {
453     QWidget *leftOffsetWidget = GTWidget::findWidget(os, "msa_editor_offsets_view_widget_left");
454     QWidget *rightOffsetWidget = GTWidget::findWidget(os, "msa_editor_offsets_view_widget_right");
455 
456     GT_CHECK_RESULT((leftOffsetWidget != nullptr) && (rightOffsetWidget != nullptr), "offset widgets are NULL", false);
457     GT_CHECK_RESULT(leftOffsetWidget->isVisible() == rightOffsetWidget->isVisible(), "offset widget visibility states are not the same", false);
458 
459     return leftOffsetWidget->isVisible();
460 }
461 #undef GT_METHOD_NAME
462 #define GT_METHOD_NAME "checkConsensus"
checkConsensus(GUITestOpStatus & os,QString cons)463 void GTUtilsMSAEditorSequenceArea::checkConsensus(GUITestOpStatus &os, QString cons) {
464     MSAEditorConsensusArea *consArea = qobject_cast<MSAEditorConsensusArea *>(GTWidget::findWidget(os, "consArea"));
465     CHECK_SET_ERR(consArea != nullptr, "consArea is NULL");
466 
467     QSharedPointer<MSAEditorConsensusCache> cache = consArea->getConsensusCache();
468     CHECK_SET_ERR(QString(cache->getConsensusLine(true)) == cons,
469                   "Wrong consensus. Currens consensus is  " + cache->getConsensusLine(true));
470     GTGlobals::sleep(1000);
471 }
472 #undef GT_METHOD_NAME
473 
474 #define GT_METHOD_NAME "selectSequence"
selectSequence(GUITestOpStatus & os,const QString & seqName)475 void GTUtilsMSAEditorSequenceArea::selectSequence(GUITestOpStatus &os, const QString &seqName) {
476     MSAEditorSequenceArea *msaEditArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area"));
477     CHECK_SET_ERR(msaEditArea != nullptr, "MsaEditorSequenceArea not found");
478 
479     QStringList names = getVisibleNames(os);
480     int row = 0;
481     while (names[row] != seqName) {
482         row++;
483     }
484     click(os, QPoint(-5, row));
485 }
486 #undef GT_METHOD_NAME
487 
488 #define GT_METHOD_NAME "selectSequence"
selectSequence(GUITestOpStatus & os,const int row)489 void GTUtilsMSAEditorSequenceArea::selectSequence(GUITestOpStatus &os, const int row) {
490     MSAEditorSequenceArea *msaEditArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area"));
491     CHECK_SET_ERR(msaEditArea != nullptr, "MsaEditorSequenceArea not found");
492 
493     click(os, QPoint(-5, row));
494 }
495 #undef GT_METHOD_NAME
496 
497 #define GT_METHOD_NAME "isSequenceSelected"
isSequenceSelected(GUITestOpStatus & os,const QString & seqName)498 bool GTUtilsMSAEditorSequenceArea::isSequenceSelected(GUITestOpStatus &os, const QString &seqName) {
499     MSAEditor *editor = GTUtilsMsaEditor::getEditor(os);
500     MSAEditorSequenceArea *msaEditArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area"));
501     CHECK_SET_ERR_RESULT(msaEditArea != nullptr, "MsaEditorSequenceArea not found", false);
502 
503     // Seq names are drawn on widget, so this hack is needed
504     QStringList selectedRowNames;
505     QList<int> selectedMaRows = msaEditArea->getSelectedMaRowIndexes();
506     for (int i = 0; i < selectedMaRows.size(); i++) {
507         int maIndex = selectedMaRows[i];
508         QString selectedSequenceName = editor->getMaObject()->getRow(maIndex)->getName();
509         if (selectedSequenceName == seqName) {
510             return true;
511         }
512     }
513     return false;
514 }
515 #undef GT_METHOD_NAME
516 
517 #define GT_METHOD_NAME "getSelectedSequencesNum"
getSelectedSequencesNum(GUITestOpStatus & os)518 int GTUtilsMSAEditorSequenceArea::getSelectedSequencesNum(GUITestOpStatus &os) {
519     MSAEditorSequenceArea *msaEditArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area"));
520     CHECK_SET_ERR_RESULT(msaEditArea != nullptr, "MsaEditorSequenceArea not found", 0);
521 
522     return msaEditArea->getSelectedMaRowIndexes().size();
523 }
524 #undef GT_METHOD_NAME
525 
526 #define GT_METHOD_NAME "isSequenceVisible"
isSequenceVisible(GUITestOpStatus & os,const QString & seqName)527 bool GTUtilsMSAEditorSequenceArea::isSequenceVisible(GUITestOpStatus &os, const QString &seqName) {
528     QStringList visiableRowNames = getVisibleNames(os);
529     return visiableRowNames.contains(seqName);
530 }
531 #undef GT_METHOD_NAME
532 
533 #define GT_METHOD_NAME "getSequenceData"
getSequenceData(GUITestOpStatus & os,const QString & sequenceName)534 QString GTUtilsMSAEditorSequenceArea::getSequenceData(GUITestOpStatus &os, const QString &sequenceName) {
535     MSAEditorSequenceArea *sequenceArea = getSequenceArea(os);
536     GT_CHECK_RESULT(sequenceArea != nullptr, "Sequence area is NULL", "");
537 
538     const QStringList names = getNameList(os);
539     const int rowNumber = names.indexOf(sequenceName);
540     GT_CHECK_RESULT(rowNumber >= 0, QString("Sequence '%1' not found").arg(sequenceName), "");
541 
542     GTUtilsMsaEditor::clickSequenceName(os, sequenceName);
543     GTKeyboardUtils::copy();
544     return GTClipboard::text(os);
545 }
546 #undef GT_METHOD_NAME
547 
548 #define GT_METHOD_NAME "getSequenceData"
getSequenceData(GUITestOpStatus & os,int rowNumber)549 QString GTUtilsMSAEditorSequenceArea::getSequenceData(GUITestOpStatus &os, int rowNumber) {
550     MSAEditorSequenceArea *sequenceArea = getSequenceArea(os);
551     GT_CHECK_RESULT(sequenceArea != nullptr, "Sequence area is NULL", "");
552 
553     const QStringList names = getNameList(os);
554     GT_CHECK_RESULT(rowNumber >= 0 && rowNumber <= names.size(), QString("Row with number %1 is out of boundaries").arg(rowNumber), "");
555 
556     GTUtilsMsaEditor::clickSequenceName(os, names[rowNumber]);
557     GTKeyboardUtils::copy();
558     return GTClipboard::text(os);
559 }
560 #undef GT_METHOD_NAME
561 
562 #define GT_METHOD_NAME "selectColumnInConsensus"
selectColumnInConsensus(GUITestOpStatus & os,int columnNumber)563 void GTUtilsMSAEditorSequenceArea::selectColumnInConsensus(GUITestOpStatus &os, int columnNumber) {
564     QWidget *activeWindow = GTUtilsMsaEditor::getActiveMsaEditorWindow(os);
565     const MSAEditorSequenceArea *msaEditArea = qobject_cast<MSAEditorSequenceArea *>(
566         GTWidget::findWidget(os, "msa_editor_sequence_area", activeWindow));
567     GT_CHECK_RESULT(msaEditArea != nullptr, "MsaEditorSequenceArea not found", );
568 
569     const QWidget *msaOffsetLeft = GTWidget::findWidget(os, "msa_editor_offsets_view_widget_left", activeWindow);
570     GT_CHECK_RESULT(msaOffsetLeft != nullptr, "MsaOffset Left not found", );
571 
572     QPoint shift = msaOffsetLeft->mapToGlobal(QPoint(0, 0));
573     if (msaOffsetLeft->isVisible()) {
574         shift = msaOffsetLeft->mapToGlobal(QPoint(msaOffsetLeft->rect().right(), 0));
575     }
576 
577     const int posX = msaEditArea->getEditor()->getUI()->getBaseWidthController()->getBaseScreenCenter(columnNumber) + shift.x();
578 
579     QWidget *consArea = GTWidget::findWidget(os, "consArea");
580     CHECK_SET_ERR(consArea != nullptr, "consArea is NULL");
581 
582     const int posY = consArea->mapToGlobal(consArea->rect().center()).y();
583     GTMouseDriver::moveTo(QPoint(posX, posY));
584     GTMouseDriver::click();
585 }
586 #undef GT_METHOD_NAME
587 
588 #define GT_METHOD_NAME "hasAminoAlphabet"
hasAminoAlphabet(GUITestOpStatus & os)589 bool GTUtilsMSAEditorSequenceArea::hasAminoAlphabet(GUITestOpStatus &os) {
590     MSAEditorSequenceArea *msaEditArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area"));
591     CHECK_SET_ERR_RESULT(msaEditArea != nullptr, "MsaEditorSequenceArea not found", false);
592 
593     return msaEditArea->hasAminoAlphabet();
594 }
595 #undef GT_METHOD_NAME
596 
597 #define GT_METHOD_NAME "isSequenceHighlighted"
isSequenceHighlighted(GUITestOpStatus & os,const QString & seqName)598 bool GTUtilsMSAEditorSequenceArea::isSequenceHighlighted(GUITestOpStatus &os, const QString &seqName) {
599     QStringList names = getVisibleNames(os);
600     GT_CHECK_RESULT(names.contains(seqName), QString("sequence with name %1 not found").arg(seqName), false);
601 
602     int row = 0;
603     while (names[row] != seqName) {
604         row++;
605     }
606     QPoint center = convertCoordinates(os, QPoint(-5, row));
607     QWidget *nameList = GTWidget::findWidget(os, "msa_editor_name_list");
608     GT_CHECK_RESULT(nameList != nullptr, "name list is NULL", false);
609 
610     int initCoord = center.y() - getRowHeight(os, row) / 2;
611     int finalCoord = center.y() + getRowHeight(os, row) / 2;
612 
613     for (int i = initCoord; i < finalCoord; i++) {
614         QPoint local = nameList->mapFromGlobal(QPoint(center.x(), i));
615         QColor c = GTWidget::getColor(os, nameList, local);
616         QString name = c.name();
617         if (name == highlightingColor) {
618             return true;
619         }
620     }
621 
622     return false;
623 }
624 #undef GT_METHOD_NAME
625 
626 #define GT_METHOD_NAME "getColor"
getColor(GUITestOpStatus & os,QPoint p)627 QString GTUtilsMSAEditorSequenceArea::getColor(GUITestOpStatus &os, QPoint p) {
628     MSAEditorSequenceArea *msaEditArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area", GTUtilsMsaEditor::getActiveMsaEditorWindow(os)));
629     GT_CHECK_RESULT(msaEditArea != nullptr, "MsaEditorSequenceArea not found", "");
630 
631     QPoint global = convertCoordinates(os, p);
632     global.setY(global.y() + (getRowHeight(os, p.y()) / 2 - 2));
633     QPoint local = msaEditArea->mapFromGlobal(global);
634     QColor c = GTWidget::getColor(os, msaEditArea, local);
635     QString name = c.name();
636     return name;
637 }
638 #undef GT_METHOD_NAME
639 
640 #define GT_METHOD_NAME "checkMsaCellColors"
checkMsaCellColors(GUITestOpStatus & os,const QPoint & pos,const QString & fgColor,const QString & bgColor)641 void GTUtilsMSAEditorSequenceArea::checkMsaCellColors(GUITestOpStatus &os, const QPoint &pos, const QString &fgColor, const QString &bgColor) {
642     CHECK_SET_ERR(GTUtilsMSAEditorSequenceArea::hasPixelWithColor(os, pos, fgColor), "Wrong FG color: " + fgColor + ", position: " + QString::number(pos.x()) + "," + QString::number(pos.y()));
643 
644     QString actualBgColor = GTUtilsMSAEditorSequenceArea::getColor(os, pos);
645     CHECK_SET_ERR(actualBgColor == bgColor, QString("Wrong BG color! Expected: %1, got: %2").arg(bgColor).arg(actualBgColor));
646 }
647 #undef GT_METHOD_NAME
648 
649 #define GT_METHOD_NAME "checkMsaCellColor"
checkMsaCellColor(GUITestOpStatus & os,const QPoint & pos,const QString & color)650 void GTUtilsMSAEditorSequenceArea::checkMsaCellColor(GUITestOpStatus &os, const QPoint &pos, const QString &color) {
651     CHECK_SET_ERR(GTUtilsMSAEditorSequenceArea::hasPixelWithColor(os, pos, color), "Wrong color: " + color);
652 }
653 #undef GT_METHOD_NAME
654 
655 #define GT_METHOD_NAME "hasPixelWithColor"
hasPixelWithColor(GUITestOpStatus & os,const QPoint & p,const QColor & color)656 bool GTUtilsMSAEditorSequenceArea::hasPixelWithColor(GUITestOpStatus &os, const QPoint &p, const QColor &color) {
657     MSAEditorSequenceArea *sequenceArea = qobject_cast<MSAEditorSequenceArea *>(GTWidget::findWidget(os, "msa_editor_sequence_area", GTUtilsMsaEditor::getActiveMsaEditorWindow(os)));
658     GT_CHECK_RESULT(sequenceArea != nullptr, "MsaEditorSequenceArea not found", "");
659     QImage img = GTWidget::getImage(os, sequenceArea);
660     QRect rect = getPositionRect(os, p);
661     for (int i = rect.left(); i < rect.right(); i++) {
662         for (int j = rect.top(); j < rect.bottom(); j++) {
663             QPoint local = sequenceArea->mapFromGlobal(QPoint(i, j));
664             QColor pixelColor = img.pixel(local);
665             if (pixelColor == color) {
666                 return true;
667             }
668         }
669     }
670     return false;
671 }
672 #undef GT_METHOD_NAME
673 
674 #define GT_METHOD_NAME "checkColor"
checkColor(GUITestOpStatus & os,const QPoint & p,const QString & expectedColor)675 bool GTUtilsMSAEditorSequenceArea::checkColor(GUITestOpStatus &os, const QPoint &p, const QString &expectedColor) {
676     QColor c = getColor(os, p);
677     bool result = (expectedColor == c.name());
678     GT_CHECK_RESULT(result, QString("wrong color. Expected: %1, actual: %2").arg(expectedColor).arg(c.name()), result);
679     return result;
680 }
681 #undef GT_METHOD_NAME
682 
683 #define GT_METHOD_NAME "getRowHeight"
getRowHeight(GUITestOpStatus & os,int rowNumber)684 int GTUtilsMSAEditorSequenceArea::getRowHeight(GUITestOpStatus &os, int rowNumber) {
685     QWidget *activeWindow = GTUtilsMsaEditor::getActiveMsaEditorWindow(os);
686     MsaEditorWgt *ui = activeWindow->findChild<MsaEditorWgt *>();
687     return ui->getRowHeightController()->getRowHeightByViewRowIndex(rowNumber);
688 }
689 #undef GT_METHOD_NAME
690 
691 #define GT_METHOD_NAME "renameSequence"
renameSequence(GUITestOpStatus & os,const QString & seqToRename,const QString & newName,bool useCopyPaste)692 void GTUtilsMSAEditorSequenceArea::renameSequence(GUITestOpStatus &os, const QString &seqToRename, const QString &newName, bool useCopyPaste) {
693     int num = getVisibleNames(os).indexOf(seqToRename);
694     GT_CHECK(num != -1, "sequence not found");
695 
696     GTUtilsDialog::waitForDialog(os, new RenameSequenceFiller(os, newName, seqToRename, useCopyPaste));
697     moveTo(os, QPoint(-10, num));
698     GTMouseDriver::doubleClick();
699     GTGlobals::sleep(500);
700 }
701 #undef GT_METHOD_NAME
702 
703 #define GT_METHOD_NAME "replaceSymbol"
replaceSymbol(GUITestOpStatus & os,const QPoint & maPoint,char newSymbol)704 void GTUtilsMSAEditorSequenceArea::replaceSymbol(GUITestOpStatus &os, const QPoint &maPoint, char newSymbol) {
705     clickToPosition(os, maPoint);
706     GTKeyboardDriver::keyClick('r', Qt::ShiftModifier);
707     GTKeyboardDriver::keyClick(newSymbol);
708     GTThread::waitForMainThread();
709 }
710 #undef GT_METHOD_NAME
711 
712 #define GT_METHOD_NAME "createColorScheme"
createColorScheme(GUITestOpStatus & os,const QString & colorSchemeName,const NewColorSchemeCreator::alphabet al)713 void GTUtilsMSAEditorSequenceArea::createColorScheme(GUITestOpStatus &os, const QString &colorSchemeName, const NewColorSchemeCreator::alphabet al) {
714     GTUtilsMsaEditor::checkMsaEditorWindowIsActive(os);
715     GTUtilsMSAEditorSequenceArea::moveTo(os, QPoint(1, 1));
716     GTUtilsDialog::waitForDialog(os, new PopupChooser(os, QStringList() << MSAE_MENU_APPEARANCE << "Colors"
717                                                                         << "Custom schemes"
718                                                                         << "Create new color scheme"));
719     GTUtilsDialog::waitForDialog(os, new NewColorSchemeCreator(os, colorSchemeName, al));
720     GTMouseDriver::click(Qt::RightButton);
721     GTUtilsDialog::waitAllFinished(os);
722 }
723 #undef GT_METHOD_NAME
724 
725 #define GT_METHOD_NAME "deleteColorScheme"
deleteColorScheme(GUITestOpStatus & os,const QString & colorSchemeName)726 void GTUtilsMSAEditorSequenceArea::deleteColorScheme(GUITestOpStatus &os, const QString &colorSchemeName) {
727     GTUtilsMSAEditorSequenceArea::moveTo(os, QPoint(1, 1));
728     GTUtilsDialog::waitForDialog(os, new PopupChooser(os, QStringList() << MSAE_MENU_APPEARANCE << "Colors"
729                                                                         << "Custom schemes"
730                                                                         << "Create new color scheme"));
731     GTUtilsDialog::waitForDialog(os, new NewColorSchemeCreator(os, colorSchemeName, NewColorSchemeCreator::nucl, NewColorSchemeCreator::Delete));
732     GTMouseDriver::click(Qt::RightButton);
733 }
734 #undef GT_METHOD_NAME
735 
736 #define GT_METHOD_NAME "checkSelection"
checkSelection(GUITestOpStatus & os,const QPoint & start,const QPoint & end,const QString & expected)737 void GTUtilsMSAEditorSequenceArea::checkSelection(GUITestOpStatus &os, const QPoint &start, const QPoint &end, const QString &expected) {
738     GTWidget::click(os, GTUtilsMsaEditor::getActiveMsaEditorWindow(os));
739     selectArea(os, start, end);
740     GTKeyboardDriver::keyClick('c', Qt::ControlModifier);
741     GTGlobals::sleep(500);
742     QString clipboardText = GTClipboard::text(os);
743     GT_CHECK(clipboardText == expected, QString("unexpected selection:\n%1").arg(clipboardText));
744 }
745 #undef GT_METHOD_NAME
746 
747 #define GT_METHOD_NAME "isAlignmentLocked"
isAlignmentLocked(GUITestOpStatus & os)748 bool GTUtilsMSAEditorSequenceArea::isAlignmentLocked(GUITestOpStatus &os) {
749     MSAEditorSequenceArea *msaSeqArea = GTUtilsMSAEditorSequenceArea::getSequenceArea(os);
750     GT_CHECK_RESULT(msaSeqArea != nullptr, "MsaEditorSequenceArea is not found", false);
751 
752     return msaSeqArea->isAlignmentLocked();
753 }
754 #undef GT_METHOD_NAME
755 
756 #define GT_METHOD_NAME "expandSelectedRegion"
expandSelectedRegion(GUITestOpStatus & os,const int expandedBorder,const int symbolsToExpand)757 void GTUtilsMSAEditorSequenceArea::expandSelectedRegion(GUITestOpStatus &os, const int expandedBorder, const int symbolsToExpand) {
758     MsaEditorWgt *ui = GTUtilsMsaEditor::getEditorUi(os);
759     CHECK_SET_ERR(ui != nullptr, "MsaEditorWgt not found");
760 
761     const int height = ui->getRowHeightController()->getSingleRowHeight();
762     const int width = ui->getBaseWidthController()->getBaseWidth();
763     const QRect selection = GTUtilsMSAEditorSequenceArea::getSelectedRect(os);
764 
765     QPoint startPos;
766     switch (expandedBorder) {
767         case (0):
768             startPos = QPoint(selection.center().x(), selection.top());
769             break;
770         case (1):
771             startPos = QPoint(selection.right(), selection.center().y());
772             break;
773         case (2):
774             startPos = QPoint(selection.center().x(), selection.bottom());
775             break;
776         case (3):
777             startPos = QPoint(selection.left(), selection.center().y());
778             break;
779         case (4):
780             startPos = selection.topRight();
781             break;
782         case (5):
783             startPos = selection.bottomRight();
784             break;
785         case (6):
786             startPos = selection.bottomLeft();
787             break;
788         case (7):
789             startPos = selection.topLeft();
790             break;
791         default:
792             CHECK_SET_ERR(false, QString("Unexpected movable border"));
793     }
794 
795     startPos = convertCoordinates(os, startPos);
796 
797     switch (expandedBorder) {
798         case (0):
799             startPos = QPoint(startPos.x(), startPos.y() - height / 2);
800             break;
801         case (1):
802             startPos = QPoint(startPos.x() + width / 2, startPos.y());
803             break;
804         case (2):
805             startPos = QPoint(startPos.x(), startPos.y() + height / 2);
806             break;
807         case (3):
808             startPos = QPoint(startPos.x() - width / 2, startPos.y());
809             break;
810         case (4):
811             startPos = QPoint(startPos.x() + width / 2, startPos.y() - height / 2);
812             break;
813         case (5):
814             startPos = QPoint(startPos.x() + width / 2, startPos.y() + height / 2);
815             break;
816         case (6):
817             startPos = QPoint(startPos.x() - width / 2, startPos.y() + height / 2);
818             break;
819         case (7):
820             startPos = QPoint(startPos.x() - width / 2, startPos.y() - height / 2);
821             break;
822     }
823 
824     GTMouseDriver::moveTo(startPos);
825     GTGlobals::sleep(500);
826     GTMouseDriver::press();
827 
828     QPoint endPos;
829     switch (expandedBorder) {
830         case (0):
831         case (2):
832             endPos = QPoint(startPos.x(), startPos.y() + symbolsToExpand * height);
833             break;
834         case (1):
835         case (3):
836             endPos = QPoint(startPos.x() + symbolsToExpand * width, startPos.y());
837             break;
838         case (4):
839         case (6):
840             endPos = QPoint(startPos.x() + symbolsToExpand * width, startPos.y() - symbolsToExpand * height);
841             break;
842         case (5):
843         case (7):
844             endPos = QPoint(startPos.x() + symbolsToExpand * width, startPos.y() + symbolsToExpand * height);
845             break;
846     }
847 
848     GTMouseDriver::moveTo(endPos);
849     GTMouseDriver::release();
850     GTGlobals::sleep(500);
851 }
852 #undef GT_METHOD_NAME
853 
zoomIn(GUITestOpStatus & os)854 void GTUtilsMSAEditorSequenceArea::zoomIn(GUITestOpStatus &os) {
855     QWidget *zoomInButton = GTWidget::findButtonByText(os, "Zoom in");
856     CHECK_SET_ERR(nullptr != zoomInButton, "Can't find the 'Zoom in' button");
857 
858     GTWidget::click(os, zoomInButton);
859 }
860 
zoomOut(GUITestOpStatus & os)861 void GTUtilsMSAEditorSequenceArea::zoomOut(GUITestOpStatus &os) {
862     QWidget *zoomOutButton = GTWidget::findButtonByText(os, "Zoom out");
863     CHECK_SET_ERR(nullptr != zoomOutButton, "Can't find the 'Zoom out' button");
864 
865     GTWidget::click(os, zoomOutButton);
866 }
867 
zoomToMax(GUITestOpStatus & os)868 void GTUtilsMSAEditorSequenceArea::zoomToMax(GUITestOpStatus &os) {
869     QWidget *zoomInButton = GTWidget::findButtonByText(os, "Zoom in");
870     CHECK_SET_ERR(nullptr != zoomInButton, "Can't find the 'Zoom in' button");
871 
872     while (zoomInButton->isEnabled()) {
873         GTWidget::click(os, zoomInButton);
874     }
875 }
876 
zoomToMin(GUITestOpStatus & os)877 void GTUtilsMSAEditorSequenceArea::zoomToMin(GUITestOpStatus &os) {
878     QWidget *zoomOutButton = GTWidget::findButtonByText(os, "Zoom out");
879     CHECK_SET_ERR(nullptr != zoomOutButton, "Can't find the 'Zoom out' button");
880 
881     while (zoomOutButton->isEnabled()) {
882         GTWidget::click(os, zoomOutButton);
883     }
884 }
885 
886 #undef GT_CLASS_NAME
887 
888 }  // namespace U2
889