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 <GTGlobals.h>
23 #include <drivers/GTKeyboardDriver.h>
24 #include <drivers/GTMouseDriver.h>
25 #include <primitives/GTAction.h>
26 #include <primitives/GTLineEdit.h>
27 #include <primitives/GTMenu.h>
28 #include <primitives/GTToolbar.h>
29 #include <primitives/PopupChooser.h>
30 #include <system/GTClipboard.h>
31 #include <utils/GTKeyboardUtils.h>
32 #include <utils/GTThread.h>
33
34 #include <QApplication>
35 #include <QClipboard>
36 #include <QDialogButtonBox>
37 #include <QPlainTextEdit>
38 #include <QPushButton>
39
40 #include <U2Core/AnnotationSettings.h>
41 #include <U2Core/AppContext.h>
42 #include <U2Core/DNASequenceSelection.h>
43 #include <U2Core/U1AnnotationUtils.h>
44
45 #include <U2Gui/MainWindow.h>
46
47 #include <U2View/ADVConstants.h>
48 #include <U2View/ADVSequenceObjectContext.h>
49 #include <U2View/ADVSingleSequenceWidget.h>
50 #include <U2View/AnnotatedDNAViewFactory.h>
51 #include <U2View/DetView.h>
52 #include <U2View/DetViewRenderer.h>
53 #include <U2View/DetViewSequenceEditor.h>
54 #include <U2View/GSequenceGraphView.h>
55 #include <U2View/Overview.h>
56
57 #include "GTUtilsMdi.h"
58 #include "GTUtilsProjectTreeView.h"
59 #include "GTUtilsSequenceView.h"
60 #include "runnables/ugene/corelibs/U2Gui/RangeSelectionDialogFiller.h"
61 #include "utils/GTUtilsDialog.h"
62
63 namespace U2 {
64 using namespace HI;
65
66 #define GT_CLASS_NAME "GTSequenceReader"
67 #define GT_METHOD_NAME "commonScenario"
68 class GTSequenceReader : public Filler {
69 public:
GTSequenceReader(HI::GUITestOpStatus & _os,QString * _str)70 GTSequenceReader(HI::GUITestOpStatus &_os, QString *_str)
71 : Filler(_os, "EditSequenceDialog"), str(_str) {
72 }
commonScenario()73 void commonScenario() {
74 QWidget *widget = QApplication::activeModalWidget();
75 GT_CHECK(widget != nullptr, "active widget not found");
76
77 QPlainTextEdit *textEdit = widget->findChild<QPlainTextEdit *>();
78 GT_CHECK(textEdit != nullptr, "PlainTextEdit not found");
79
80 *str = textEdit->toPlainText();
81
82 QDialogButtonBox *box = qobject_cast<QDialogButtonBox *>(GTWidget::findWidget(os, "buttonBox", widget));
83 GT_CHECK(box != nullptr, "buttonBox is NULL");
84 QPushButton *button = box->button(QDialogButtonBox::Cancel);
85 GT_CHECK(button != nullptr, "cancel button is NULL");
86 GTWidget::click(os, button);
87 }
88
89 private:
90 QString *str;
91 };
92 #undef GT_METHOD_NAME
93 #undef GT_CLASS_NAME
94
95 #define GT_CLASS_NAME "GTUtilsSequenceView"
96
97 #define GT_METHOD_NAME "getActiveSequenceViewWindow"
getActiveSequenceViewWindow(GUITestOpStatus & os)98 QWidget *GTUtilsSequenceView::getActiveSequenceViewWindow(GUITestOpStatus &os) {
99 QWidget *widget = GTUtilsMdi::getActiveObjectViewWindow(os, AnnotatedDNAViewFactory::ID);
100 GTThread::waitForMainThread();
101 return widget;
102 }
103 #undef GT_METHOD_NAME
104
105 #define GT_METHOD_NAME "checkSequenceViewWindowIsActive"
checkSequenceViewWindowIsActive(GUITestOpStatus & os)106 void GTUtilsSequenceView::checkSequenceViewWindowIsActive(GUITestOpStatus &os) {
107 getActiveSequenceViewWindow(os);
108 }
109 #undef GT_METHOD_NAME
110
111 #define GT_METHOD_NAME "checkNoSequenceViewWindowIsOpened"
checkNoSequenceViewWindowIsOpened(GUITestOpStatus & os)112 void GTUtilsSequenceView::checkNoSequenceViewWindowIsOpened(GUITestOpStatus &os) {
113 GTUtilsMdi::checkNoObjectViewWindowIsOpened(os, AnnotatedDNAViewFactory::ID);
114 }
115 #undef GT_METHOD_NAME
116
117 #define GT_METHOD_NAME "getSequenceAsString"
getSequenceAsString(HI::GUITestOpStatus & os,QString & sequence)118 void GTUtilsSequenceView::getSequenceAsString(HI::GUITestOpStatus &os, QString &sequence) {
119 QWidget *sequenceWidget = getPanOrDetView(os);
120 GTWidget::click(os, sequenceWidget);
121
122 GTUtilsDialog::waitForDialog(os, new SelectSequenceRegionDialogFiller(os));
123 GTKeyboardUtils::selectAll();
124 GTUtilsDialog::waitAllFinished(os);
125
126 GTUtilsDialog::waitForDialog(os, new PopupChooser(os, QStringList() << ADV_MENU_EDIT << ACTION_EDIT_REPLACE_SUBSEQUENCE, GTGlobals::UseKey));
127 GTUtilsDialog::waitForDialog(os, new GTSequenceReader(os, &sequence));
128 GTMenu::showContextMenu(os, sequenceWidget);
129 GTUtilsDialog::waitAllFinished(os);
130 }
131 #undef GT_METHOD_NAME
132
133 #define GT_METHOD_NAME "getSequenceAsString"
getSequenceAsString(HI::GUITestOpStatus & os,int number)134 QString GTUtilsSequenceView::getSequenceAsString(HI::GUITestOpStatus &os, int number) {
135 getActiveSequenceViewWindow(os);
136 GTWidget::click(os, getSeqWidgetByNumber(os, number));
137
138 GTUtilsDialog::waitForDialog(os, new SelectSequenceRegionDialogFiller(os));
139 GTKeyboardUtils::selectAll();
140 GTGlobals::sleep(500);
141 GTUtilsDialog::waitForDialog(os, new PopupChooser(os, QStringList() << ADV_MENU_COPY << "Copy sequence"));
142 // Use PanView or DetView but not the sequence widget itself: there are internal scrollbars in the SequenceWidget that may affect popup menu content.
143 QWidget *panOrDetView = getDetViewByNumber(os, number, GTGlobals::FindOptions(false));
144 if (panOrDetView == nullptr) {
145 panOrDetView = getPanViewByNumber(os, number);
146 }
147 GTWidget::click(os, panOrDetView, Qt::RightButton);
148 QString result = GTClipboard::text(os);
149 return result;
150 }
151 #undef GT_METHOD_NAME
152
153 #define GT_METHOD_NAME "getBeginOfSequenceAsString"
154
getBeginOfSequenceAsString(HI::GUITestOpStatus & os,int length)155 QString GTUtilsSequenceView::getBeginOfSequenceAsString(HI::GUITestOpStatus &os, int length) {
156 checkSequenceViewWindowIsActive(os);
157 GTUtilsDialog::waitForDialog(os, new SelectSequenceRegionDialogFiller(os, length));
158 GTKeyboardUtils::selectAll();
159 GTThread::waitForMainThread();
160
161 QString sequence;
162 GTUtilsDialog::waitForDialog(os, new PopupChooser(os, QStringList() << ADV_MENU_EDIT << ACTION_EDIT_REPLACE_SUBSEQUENCE, GTGlobals::UseKey));
163 GTUtilsDialog::waitForDialog(os, new GTSequenceReader(os, &sequence));
164 openPopupMenuOnSequenceViewArea(os);
165 GTUtilsDialog::waitAllFinished(os);
166
167 return sequence;
168 }
169 #undef GT_METHOD_NAME
170
171 #define GT_METHOD_NAME "getEndOfSequenceAsString"
getEndOfSequenceAsString(HI::GUITestOpStatus & os,int length)172 QString GTUtilsSequenceView::getEndOfSequenceAsString(HI::GUITestOpStatus &os, int length) {
173 QWidget *mdiWindow = getActiveSequenceViewWindow(os);
174 GTMouseDriver::moveTo(mdiWindow->mapToGlobal(mdiWindow->rect().center()));
175 GTMouseDriver::click();
176
177 Runnable *filler = new SelectSequenceRegionDialogFiller(os, length, false);
178 GTUtilsDialog::waitForDialog(os, filler);
179
180 GTKeyboardUtils::selectAll();
181 GTGlobals::sleep(1000);
182 GTGlobals::sleep(1000); // don't touch
183
184 QString sequence;
185 Runnable *chooser = new PopupChooser(os, QStringList() << ADV_MENU_EDIT << ACTION_EDIT_REPLACE_SUBSEQUENCE, GTGlobals::UseKey);
186 GTUtilsDialog::waitForDialog(os, chooser);
187 Runnable *reader = new GTSequenceReader(os, &sequence);
188 GTUtilsDialog::waitForDialog(os, reader);
189
190 GTMenu::showContextMenu(os, mdiWindow);
191 GTGlobals::sleep(1000);
192
193 return sequence;
194 }
195 #undef GT_METHOD_NAME
196
197 #define GT_METHOD_NAME "getLengthOfSequence"
getLengthOfSequence(HI::GUITestOpStatus & os)198 int GTUtilsSequenceView::getLengthOfSequence(HI::GUITestOpStatus &os) {
199 MainWindow *mw = AppContext::getMainWindow();
200 GT_CHECK_RESULT(mw != nullptr, "MainWindow == NULL", 0);
201
202 MWMDIWindow *mdiWindow = mw->getMDIManager()->getActiveWindow();
203 GT_CHECK_RESULT(mdiWindow != nullptr, "MDI window == NULL", 0);
204
205 GTGlobals::sleep();
206
207 GTMouseDriver::moveTo(mdiWindow->mapToGlobal(mdiWindow->rect().center()));
208 GTMouseDriver::click();
209
210 int length = -1;
211 GTUtilsDialog::waitForDialog(os, new SelectSequenceRegionDialogFiller(os, &length));
212 GTKeyboardUtils::selectAll();
213 GTGlobals::sleep(1000);
214
215 return length;
216 }
217 #undef GT_METHOD_NAME
218
getVisibleStart(HI::GUITestOpStatus & os,int widgetNumber)219 int GTUtilsSequenceView::getVisibleStart(HI::GUITestOpStatus &os, int widgetNumber) {
220 return getSeqWidgetByNumber(os, widgetNumber)->getDetView()->getVisibleRange().startPos;
221 }
222
223 #define GT_METHOD_NAME "getVisibleRange"
getVisibleRange(HI::GUITestOpStatus & os,int widgetNumber)224 U2Region GTUtilsSequenceView::getVisibleRange(HI::GUITestOpStatus &os, int widgetNumber) {
225 ADVSingleSequenceWidget *seqWgt = getSeqWidgetByNumber(os, widgetNumber);
226 GT_CHECK_RESULT(seqWgt != nullptr, "Cannot find sequence view", U2Region());
227 return seqWgt->getDetView()->getVisibleRange();
228 }
229 #undef GT_METHOD_NAME
230
231 #define GT_METHOD_NAME "checkSequence"
checkSequence(HI::GUITestOpStatus & os,const QString & expectedSequence)232 void GTUtilsSequenceView::checkSequence(HI::GUITestOpStatus &os, const QString &expectedSequence) {
233 QString actualSequence;
234 getSequenceAsString(os, actualSequence);
235
236 GT_CHECK(expectedSequence == actualSequence, "Actual sequence does not match with expected sequence");
237 }
238 #undef GT_METHOD_NAME
239
240 #define GT_METHOD_NAME "selectSequenceRegion"
selectSequenceRegion(HI::GUITestOpStatus & os,int from,int to)241 void GTUtilsSequenceView::selectSequenceRegion(HI::GUITestOpStatus &os, int from, int to) {
242 GTUtilsDialog::waitForDialog(os, new SelectSequenceRegionDialogFiller(os, from, to));
243 clickMouseOnTheSafeSequenceViewArea(os);
244 GTKeyboardUtils::selectAll();
245 }
246 #undef GT_METHOD_NAME
247
248 #define GT_METHOD_NAME "selectSeveralRegionsByDialog"
selectSeveralRegionsByDialog(HI::GUITestOpStatus & os,const QString & multipleRangeString)249 void GTUtilsSequenceView::selectSeveralRegionsByDialog(HI::GUITestOpStatus &os, const QString &multipleRangeString) {
250 GTUtilsDialog::waitForDialog(os, new SelectSequenceRegionDialogFiller(os, multipleRangeString));
251 clickMouseOnTheSafeSequenceViewArea(os);
252 GTKeyboardUtils::selectAll();
253 }
254 #undef GT_METHOD_NAME
255
256 #define GT_METHOD_NAME "openSequenceView"
openSequenceView(HI::GUITestOpStatus & os,const QString & sequenceName)257 void GTUtilsSequenceView::openSequenceView(HI::GUITestOpStatus &os, const QString &sequenceName) {
258 GTUtilsDialog::waitForDialog(os, new PopupChooser(os, QStringList() << "Open View"
259 << "action_open_view",
260 GTGlobals::UseMouse));
261
262 QPoint itemPos = GTUtilsProjectTreeView::getItemCenter(os, sequenceName);
263 GTMouseDriver::moveTo(itemPos);
264 GTMouseDriver::click(Qt::RightButton);
265 }
266 #undef GT_METHOD_NAME
267
268 #define GT_METHOD_NAME "addSequenceView"
addSequenceView(HI::GUITestOpStatus & os,const QString & sequenceName)269 void GTUtilsSequenceView::addSequenceView(HI::GUITestOpStatus &os, const QString &sequenceName) {
270 GTUtilsDialog::waitForDialog(os, new PopupChooser(os, QStringList() << "submenu_add_view"
271 << "action_add_view",
272 GTGlobals::UseMouse));
273
274 QPoint itemPos = GTUtilsProjectTreeView::getItemCenter(os, sequenceName);
275 GTMouseDriver::moveTo(itemPos);
276 GTMouseDriver::click(Qt::RightButton);
277 }
278 #undef GT_METHOD_NAME
279
280 #define GT_METHOD_NAME "goToPosition"
goToPosition(HI::GUITestOpStatus & os,qint64 position)281 void GTUtilsSequenceView::goToPosition(HI::GUITestOpStatus &os, qint64 position) {
282 QToolBar *toolbar = GTToolbar::getToolbar(os, MWTOOLBAR_ACTIVEMDI);
283 GT_CHECK(nullptr != toolbar, "Can't find the toolbar");
284
285 QLineEdit *positionLineEdit = GTWidget::findExactWidget<QLineEdit *>(os, "go_to_pos_line_edit", toolbar);
286 GT_CHECK(nullptr != positionLineEdit, "Can't find the position line edit");
287
288 GTLineEdit::setText(os, positionLineEdit, QString::number(position));
289 GTKeyboardDriver::keyClick(Qt::Key_Enter);
290 }
291 #undef GT_METHOD_NAME
292
293 #define GT_METHOD_NAME "clickMouseOnTheSafeSequenceViewArea"
clickMouseOnTheSafeSequenceViewArea(HI::GUITestOpStatus & os)294 void GTUtilsSequenceView::clickMouseOnTheSafeSequenceViewArea(HI::GUITestOpStatus &os) {
295 QWidget *panOrDetView = getPanOrDetView(os);
296 GT_CHECK(panOrDetView != nullptr, "No pan or det-view found!");
297 GTMouseDriver::moveTo(panOrDetView->mapToGlobal(panOrDetView->rect().center()));
298 GTMouseDriver::click();
299 }
300 #undef GT_METHOD_NAME
301
302 #define GT_METHOD_NAME "clickMouseOnTheSafeSequenceViewArea"
openPopupMenuOnSequenceViewArea(HI::GUITestOpStatus & os,int number)303 void GTUtilsSequenceView::openPopupMenuOnSequenceViewArea(HI::GUITestOpStatus &os, int number) {
304 QWidget *panOrDetView = getPanOrDetView(os, number);
305 GT_CHECK(panOrDetView != nullptr, "No pan or det-view found!");
306 GTWidget::click(os, panOrDetView, Qt::RightButton);
307 }
308 #undef GT_METHOD_NAME
309
310 #define GT_METHOD_NAME "getPanOrDetView"
getPanOrDetView(HI::GUITestOpStatus & os,int number)311 QWidget *GTUtilsSequenceView::getPanOrDetView(HI::GUITestOpStatus &os, int number) {
312 QWidget *panOrDetView = getDetViewByNumber(os, number, GTGlobals::FindOptions(false));
313 if (panOrDetView == nullptr) {
314 panOrDetView = getPanViewByNumber(os, number);
315 }
316 return panOrDetView;
317 }
318 #undef GT_METHOD_NAME
319
320 #define GT_METHOD_NAME "getSeqWidgetByNumber"
getSeqWidgetByNumber(HI::GUITestOpStatus & os,int number,const GTGlobals::FindOptions & options)321 ADVSingleSequenceWidget *GTUtilsSequenceView::getSeqWidgetByNumber(HI::GUITestOpStatus &os, int number, const GTGlobals::FindOptions &options) {
322 QWidget *widget = GTWidget::findWidget(os,
323 QString("ADV_single_sequence_widget_%1").arg(number),
324 getActiveSequenceViewWindow(os),
325 options);
326
327 ADVSingleSequenceWidget *seqWidget = qobject_cast<ADVSingleSequenceWidget *>(widget);
328
329 if (options.failIfNotFound) {
330 GT_CHECK_RESULT(widget != nullptr, QString("Sequence widget %1 was not found!").arg(number), nullptr);
331 }
332
333 return seqWidget;
334 }
335 #undef GT_METHOD_NAME
336
337 #define GT_METHOD_NAME "getDetViewByNumber"
getDetViewByNumber(HI::GUITestOpStatus & os,int number,const GTGlobals::FindOptions & options)338 DetView *GTUtilsSequenceView::getDetViewByNumber(HI::GUITestOpStatus &os, int number, const GTGlobals::FindOptions &options) {
339 ADVSingleSequenceWidget *seq = getSeqWidgetByNumber(os, number, options);
340 if (options.failIfNotFound) {
341 GT_CHECK_RESULT(seq != nullptr, QString("sequence view with num %1 not found").arg(number), nullptr);
342 } else {
343 return nullptr;
344 }
345
346 DetView *result = seq->findChild<DetView *>();
347 if (options.failIfNotFound) {
348 GT_CHECK_RESULT(result != nullptr, QString("det view with number %1 not found").arg(number), nullptr);
349 }
350 return result;
351 }
352 #undef GT_METHOD_NAME
353
354 #define GT_METHOD_NAME "getPanViewByNumber"
getPanViewByNumber(HI::GUITestOpStatus & os,int number,const GTGlobals::FindOptions & options)355 PanView *GTUtilsSequenceView::getPanViewByNumber(HI::GUITestOpStatus &os, int number, const GTGlobals::FindOptions &options) {
356 ADVSingleSequenceWidget *seq = getSeqWidgetByNumber(os, number, options);
357 if (options.failIfNotFound) {
358 GT_CHECK_RESULT(seq != nullptr, QString("sequence view with num %1 not found").arg(number), nullptr);
359 } else {
360 return nullptr;
361 }
362
363 PanView *result = seq->findChild<PanView *>();
364 if (options.failIfNotFound) {
365 GT_CHECK_RESULT(seq != nullptr, QString("pan view with number %1 not found").arg(number), nullptr)
366 }
367
368 return result;
369 }
370 #undef GT_METHOD_NAME
371
372 #define GT_METHOD_NAME "getOverViewByNumber"
getOverviewByNumber(HI::GUITestOpStatus & os,int number,const GTGlobals::FindOptions & options)373 Overview *GTUtilsSequenceView::getOverviewByNumber(HI::GUITestOpStatus &os, int number, const GTGlobals::FindOptions &options) {
374 ADVSingleSequenceWidget *seq = getSeqWidgetByNumber(os, number, options);
375 if (options.failIfNotFound) {
376 GT_CHECK_RESULT(seq != nullptr, QString("sequence view with num %1 not found").arg(number), nullptr);
377 } else {
378 return nullptr;
379 }
380
381 Overview *result = seq->findChild<Overview *>();
382 if (options.failIfNotFound) {
383 GT_CHECK_RESULT(seq != nullptr, QString("pan view with number %1 not found").arg(number), nullptr)
384 }
385
386 return result;
387 }
388 #undef GT_METHOD_NAME
389
390 #define GT_METHOD_NAME "getSeqWidgetsNumber"
getSeqWidgetsNumber(HI::GUITestOpStatus & os)391 int GTUtilsSequenceView::getSeqWidgetsNumber(HI::GUITestOpStatus &os) {
392 QList<ADVSingleSequenceWidget *> seqWidgets = getActiveSequenceViewWindow(os)->findChildren<ADVSingleSequenceWidget *>();
393 return seqWidgets.size();
394 }
395 #undef GT_METHOD_NAME
396
getSelection(HI::GUITestOpStatus & os,int number)397 QVector<U2Region> GTUtilsSequenceView::getSelection(HI::GUITestOpStatus &os, int number) {
398 PanView *panView = getPanViewByNumber(os, number);
399 QVector<U2Region> result = panView->getSequenceContext()->getSequenceSelection()->getSelectedRegions();
400 return result;
401 }
402
403 #define GT_METHOD_NAME "getSeqName"
getSeqName(HI::GUITestOpStatus & os,int number)404 QString GTUtilsSequenceView::getSeqName(HI::GUITestOpStatus &os, int number) {
405 return getSeqName(os, getSeqWidgetByNumber(os, number));
406 }
407 #undef GT_METHOD_NAME
408
409 #define GT_METHOD_NAME "getSeqName"
getSeqName(HI::GUITestOpStatus & os,ADVSingleSequenceWidget * seqWidget)410 QString GTUtilsSequenceView::getSeqName(HI::GUITestOpStatus &os, ADVSingleSequenceWidget *seqWidget) {
411 GT_CHECK_RESULT(nullptr != seqWidget, "Sequence widget is NULL!", "");
412 QLabel *nameLabel = qobject_cast<QLabel *>(GTWidget::findWidget(os, "nameLabel", seqWidget));
413 GT_CHECK_RESULT(nullptr != nameLabel, "Name label is NULL!", "");
414
415 QString labelText = nameLabel->text();
416 QString result = labelText.left(labelText.indexOf("[") - 1); // detachment of name from label text
417 return result;
418 }
419 #undef GT_METHOD_NAME
420
421 #define MIN_ANNOTATION_WIDTH 5
422
423 #define GT_METHOD_NAME "clickAnnotationDet"
clickAnnotationDet(HI::GUITestOpStatus & os,const QString & annotationName,int annotationRegionStartPos,int sequenceWidgetIndex,const bool isDoubleClick,Qt::MouseButton button)424 void GTUtilsSequenceView::clickAnnotationDet(HI::GUITestOpStatus &os, const QString &annotationName, int annotationRegionStartPos, int sequenceWidgetIndex, const bool isDoubleClick, Qt::MouseButton button) {
425 ADVSingleSequenceWidget *sequenceView = getSeqWidgetByNumber(os, sequenceWidgetIndex);
426 DetView *detView = sequenceView->getDetView();
427 GT_CHECK(detView != nullptr, "detView not found");
428 auto renderArea = qobject_cast<DetViewRenderArea *>(detView->getRenderArea());
429 GT_CHECK(renderArea != nullptr, "detView render area not found");
430
431 QList<Annotation *> selectedAnnotationList;
432 const QSet<AnnotationTableObject *> annotationObjectSet = sequenceView->getSequenceContext()->getAnnotationObjects(true);
433 for (const AnnotationTableObject *ao : qAsConst(annotationObjectSet)) {
434 for (Annotation *a : ao->getAnnotations()) {
435 QVector<U2Region> regions = a->getLocation()->regions;
436 for (const U2Region &r : qAsConst(regions)) {
437 if (a->getName() == annotationName && r.startPos == annotationRegionStartPos - 1) {
438 selectedAnnotationList << a;
439 }
440 }
441 }
442 }
443 GT_CHECK(selectedAnnotationList.size() != 0, QString("Annotation with annotationName %1 and startPos %2").arg(annotationName).arg(annotationRegionStartPos));
444 GT_CHECK(selectedAnnotationList.size() == 1, QString("Several annotation with annotationName %1 and startPos %2. Number is: %3").arg(annotationName).arg(annotationRegionStartPos).arg(selectedAnnotationList.size()));
445
446 Annotation *annotation = selectedAnnotationList.first();
447
448 const SharedAnnotationData &aData = annotation->getData();
449 AnnotationSettingsRegistry *asr = AppContext::getAnnotationsSettingsRegistry();
450 AnnotationSettings *as = asr->getAnnotationSettings(aData);
451
452 U2Region annotationRegion;
453 int annotationRegionIndex = 0;
454 const QVector<U2Region> regionList = annotation->getRegions();
455 for (const U2Region ® : qAsConst(regionList)) {
456 if (reg.startPos == annotationRegionStartPos - 1) {
457 annotationRegion = reg;
458 break;
459 }
460 annotationRegionIndex++;
461 }
462 GT_CHECK(!annotationRegion.isEmpty(), "Region not found");
463
464 if (!annotationRegion.intersects(detView->getVisibleRange())) {
465 int center = annotationRegion.center();
466 goToPosition(os, center);
467 }
468
469 QList<U2Region> yRegionList = renderArea->getAnnotationYRegions(annotation, annotationRegionIndex, as);
470 GT_CHECK(!yRegionList.isEmpty(), "yRegionList is empty!");
471
472 U2Region yRegion = yRegionList.first();
473 U2Region visibleRegion = detView->getVisibleRange();
474 U2Region annotationVisibleRegion = annotationRegion.intersect(visibleRegion);
475 int x1 = renderArea->posToCoord(annotationVisibleRegion.startPos, true);
476 int x2 = renderArea->posToCoord(annotationVisibleRegion.endPos() - 1, true) + renderArea->getCharWidth();
477 if (x2 <= x1) { // In the wrap mode x2 may be on a different line. In this case use [x1...line-end] as the click region.
478 x2 = renderArea->width();
479 }
480
481 const QRect clickRect(x1, yRegion.startPos, x2 - x1, yRegion.length);
482 GTMouseDriver::moveTo(renderArea->mapToGlobal(clickRect.center()));
483 if (isDoubleClick) {
484 GTMouseDriver::doubleClick();
485 } else {
486 GTMouseDriver::click(button);
487 }
488 }
489 #undef GT_METHOD_NAME
490
491 #define GT_METHOD_NAME "clickAnnotationPan"
clickAnnotationPan(HI::GUITestOpStatus & os,QString name,int startPos,int number,const bool isDoubleClick,Qt::MouseButton button)492 void GTUtilsSequenceView::clickAnnotationPan(HI::GUITestOpStatus &os, QString name, int startPos, int number, const bool isDoubleClick, Qt::MouseButton button) {
493 ADVSingleSequenceWidget *seq = getSeqWidgetByNumber(os, number);
494 GSequenceLineViewRenderArea *area = seq->getPanView()->getRenderArea();
495 PanViewRenderArea *pan = dynamic_cast<PanViewRenderArea *>(area);
496 GT_CHECK(pan != nullptr, "pan view render area not found");
497
498 ADVSequenceObjectContext *context = seq->getSequenceContext();
499 context->getAnnotationObjects(true);
500
501 QList<Annotation *> anns;
502 foreach (const AnnotationTableObject *ao, context->getAnnotationObjects(true)) {
503 foreach (Annotation *a, ao->getAnnotations()) {
504 const int sp = a->getLocation().data()->regions.first().startPos;
505 const QString annName = a->getName();
506 if (sp == startPos - 1 && annName == name) {
507 anns << a;
508 }
509 }
510 }
511 GT_CHECK(anns.size() != 0, QString("Annotation with name %1 and startPos %2").arg(name).arg(startPos));
512 GT_CHECK(anns.size() == 1, QString("Several annotation with name %1 and startPos %2. Number is: %3").arg(name).arg(startPos).arg(anns.size()));
513
514 Annotation *a = anns.first();
515
516 const SharedAnnotationData &aData = a->getData();
517 AnnotationSettingsRegistry *asr = AppContext::getAnnotationsSettingsRegistry();
518 AnnotationSettings *as = asr->getAnnotationSettings(aData);
519
520 const U2Region &vr = seq->getPanView()->getVisibleRange();
521 QVector<U2Region> regions = a->getLocation().data()->regions;
522 const U2Region &r = regions.first();
523
524 if (!r.intersects(vr)) {
525 int center = r.center();
526 goToPosition(os, center);
527 GTGlobals::sleep();
528 }
529
530 const U2Region visibleLocation = r.intersect(vr);
531
532 U2Region y = pan->getAnnotationYRange(a, 0, as);
533
534 float start = visibleLocation.startPos;
535 float end = visibleLocation.endPos();
536 float x1f = (float)(start - vr.startPos) * pan->getCurrentScale();
537 float x2f = (float)(end - vr.startPos) * pan->getCurrentScale();
538
539 int rw = qMax(MIN_ANNOTATION_WIDTH, qRound(x2f - x1f));
540 int x1 = qRound(x1f);
541
542 const QRect annotationRect(x1, y.startPos, rw, y.length);
543 GTMouseDriver::moveTo(pan->mapToGlobal(annotationRect.center()));
544 if (isDoubleClick) {
545 GTMouseDriver::doubleClick();
546 } else {
547 GTMouseDriver::click(button);
548 }
549 }
550 #undef GT_METHOD_NAME
551
552 #define GT_METHOD_NAME "getGraphView"
getGraphView(HI::GUITestOpStatus & os)553 GSequenceGraphView *GTUtilsSequenceView::getGraphView(HI::GUITestOpStatus &os) {
554 GSequenceGraphView *graph = getSeqWidgetByNumber(os)->findChild<GSequenceGraphView *>();
555 GT_CHECK_RESULT(graph != nullptr, "Graph view is NULL", nullptr);
556 return graph;
557 }
558 #undef GT_METHOD_NAME
559
getLabelPositions(HI::GUITestOpStatus & os,GSequenceGraphView * graph)560 QList<QVariant> GTUtilsSequenceView::getLabelPositions(HI::GUITestOpStatus &os, GSequenceGraphView *graph) {
561 Q_UNUSED(os);
562 QList<QVariant> list;
563 graph->getSavedLabelsState(list);
564 return list;
565 }
566
getGraphLabels(HI::GUITestOpStatus & os,GSequenceGraphView * graph)567 QList<GraphLabelTextBox *> GTUtilsSequenceView::getGraphLabels(HI::GUITestOpStatus &os, GSequenceGraphView *graph) {
568 Q_UNUSED(os);
569 QList<GraphLabelTextBox *> result = graph->findChildren<GraphLabelTextBox *>();
570 return result;
571 }
572
getGraphColor(HI::GUITestOpStatus &,GSequenceGraphView * graph)573 QColor GTUtilsSequenceView::getGraphColor(HI::GUITestOpStatus & /*os*/, GSequenceGraphView *graph) {
574 ColorMap map = graph->getGraphDrawer()->getColors();
575 QColor result = map.value("Default color");
576 return result;
577 }
578
579 #define GT_METHOD_NAME "toggleGraphByName"
toggleGraphByName(HI::GUITestOpStatus & os,const QString & graphName,int sequenceViewIndex)580 void GTUtilsSequenceView::toggleGraphByName(HI::GUITestOpStatus &os, const QString &graphName, int sequenceViewIndex) {
581 QWidget *sequenceWidget = getSeqWidgetByNumber(os, sequenceViewIndex);
582 QWidget *graphAction = GTWidget::findWidget(os, "GraphMenuAction", sequenceWidget, false);
583 GTUtilsDialog::waitForDialog(os, new PopupChooser(os, {graphName}));
584 GTWidget::click(os, graphAction);
585 }
586 #undef GT_METHOD_NAME
587
588 #define GT_METHOD_NAME "zoomIn"
zoomIn(HI::GUITestOpStatus & os,int sequenceViewIndex)589 void GTUtilsSequenceView::zoomIn(HI::GUITestOpStatus &os, int sequenceViewIndex) {
590 QWidget *sequenceWidget = getSeqWidgetByNumber(os, sequenceViewIndex);
591 QAction *zoomInAction = GTAction::findActionByText(os, "Zoom In", sequenceWidget);
592 GTWidget::click(os, GTAction::button(os, zoomInAction));
593 }
594 #undef GT_METHOD_NAME
595
596 #define GT_METHOD_NAME "enableEditingMode"
enableEditingMode(GUITestOpStatus & os,bool enable,int sequenceNumber)597 void GTUtilsSequenceView::enableEditingMode(GUITestOpStatus &os, bool enable, int sequenceNumber) {
598 DetView *detView = getDetViewByNumber(os, sequenceNumber);
599 CHECK_SET_ERR(detView != nullptr, "DetView is NULL");
600
601 QToolBar *toolbar = GTWidget::findExactWidget<QToolBar *>(os, "", detView);
602 QToolButton *editButton = qobject_cast<QToolButton *>(GTToolbar::getWidgetForActionObjectName(os, toolbar, "edit_sequence_action"));
603 CHECK_SET_ERR(nullptr != editButton, "'edit_sequence_action' button is NULL");
604 if (editButton->isChecked() != enable) {
605 if (editButton->isVisible()) {
606 GTWidget::click(os, editButton);
607 } else {
608 const QPoint gp = detView->mapToGlobal(QPoint(10, detView->rect().height() - 5));
609 GTMouseDriver::moveTo(gp);
610 GTMouseDriver::click();
611 GTGlobals::sleep(500);
612 GTKeyboardDriver::keyClick(Qt::Key_Up);
613 GTGlobals::sleep(200);
614 GTKeyboardDriver::keyClick(Qt::Key_Enter);
615 GTGlobals::sleep(200);
616 }
617 }
618 }
619 #undef GT_METHOD_NAME
620
621 #define GT_METHOD_NAME "insertSubsequence"
insertSubsequence(HI::GUITestOpStatus & os,qint64 offset,const QString & subsequence,bool isDirectStrand)622 void GTUtilsSequenceView::insertSubsequence(HI::GUITestOpStatus &os, qint64 offset, const QString &subsequence, bool isDirectStrand) {
623 makeDetViewVisible(os);
624 enableEditingMode(os, true);
625 setCursor(os, offset, isDirectStrand);
626 GTKeyboardDriver::keySequence(subsequence);
627 enableEditingMode(os, false);
628 }
629 #undef GT_METHOD_NAME
630
631 #define GT_METHOD_NAME "setCursor"
setCursor(GUITestOpStatus & os,qint64 position,bool clickOnDirectLine,bool doubleClick)632 void GTUtilsSequenceView::setCursor(GUITestOpStatus &os, qint64 position, bool clickOnDirectLine, bool doubleClick) {
633 // Multiline view is no supported correctly
634
635 DetView *detView = getDetViewByNumber(os, 0);
636 CHECK_SET_ERR(nullptr != detView, "DetView is NULL");
637
638 DetViewRenderArea *renderArea = detView->getDetViewRenderArea();
639 CHECK_SET_ERR(nullptr != renderArea, "DetViewRenderArea is NULL");
640
641 DetViewRenderer *renderer = renderArea->getRenderer();
642 CHECK_SET_ERR(nullptr != renderer, "DetViewRenderer is NULL");
643
644 U2Region visibleRange = detView->getVisibleRange();
645 if (!visibleRange.contains(position)) {
646 GTUtilsSequenceView::goToPosition(os, position);
647 GTGlobals::sleep();
648 visibleRange = detView->getVisibleRange();
649 }
650 SAFE_POINT_EXT(visibleRange.contains(position), os.setError("Position is out of visible range"), );
651
652 const double scale = renderer->getCurrentScale();
653 const int coord = renderer->posToXCoord(position, renderArea->size(), visibleRange) + (int)(scale / 2);
654
655 const bool wrapMode = detView->isWrapMode();
656 if (!wrapMode) {
657 GTMouseDriver::moveTo(renderArea->mapToGlobal(QPoint(coord, 40))); // TODO: replace the hardcoded value with method in renderer
658 } else {
659 GTUtilsSequenceView::goToPosition(os, position);
660 GTGlobals::sleep();
661
662 const int symbolsPerLine = renderArea->getSymbolsPerLine();
663 const int linesCount = renderArea->getLinesCount();
664 visibleRange = GTUtilsSequenceView::getVisibleRange(os);
665 int linesBeforePos = -1;
666 for (int i = 0; i < linesCount; i++) {
667 const U2Region line(visibleRange.startPos + i * symbolsPerLine, symbolsPerLine);
668 if (line.contains(position)) {
669 linesBeforePos = i;
670 break;
671 }
672 }
673 SAFE_POINT_EXT(linesBeforePos != -1, os.setError("Position not found"), );
674
675 const int shiftsCount = renderArea->getShiftsCount();
676 int middleShift = (int)(shiftsCount / 2) + 1; // TODO: this calculation might consider the case then complementary is turned off or translations are drawn
677 if (clickOnDirectLine) {
678 middleShift--;
679 }
680
681 const int shiftHeight = renderArea->getShiftHeight();
682 const int lineToClick = linesBeforePos * shiftsCount + middleShift;
683
684 const int yPos = (lineToClick * shiftHeight) - (shiftHeight / 2);
685
686 GTMouseDriver::moveTo(renderArea->mapToGlobal(QPoint(coord, yPos)));
687 }
688 if (doubleClick) {
689 GTMouseDriver::doubleClick();
690 } else {
691 GTMouseDriver::click();
692 }
693 }
694 #undef GT_METHOD_NAME
695
696 #define GT_METHOD_NAME "getCursor"
getCursor(HI::GUITestOpStatus & os)697 qint64 GTUtilsSequenceView::getCursor(HI::GUITestOpStatus &os) {
698 DetView *detView = getDetViewByNumber(os, 0);
699 GT_CHECK_RESULT(nullptr != detView, "DetView is NULL", -1);
700
701 DetViewSequenceEditor *dwSequenceEditor = detView->getEditor();
702 GT_CHECK_RESULT(dwSequenceEditor != nullptr, "DetViewSequenceEditor is NULL", -1);
703
704 const bool isEditMode = detView->isEditMode();
705 GT_CHECK_RESULT(isEditMode, "Edit mode is disabled", -1);
706
707 const qint64 result = dwSequenceEditor->getCursorPosition();
708
709 return result;
710 }
711 #undef GT_METHOD_NAME
712
713 #define GT_METHOD_NAME "getRegionAsString"
getRegionAsString(HI::GUITestOpStatus & os,const U2Region & region)714 QString GTUtilsSequenceView::getRegionAsString(HI::GUITestOpStatus &os, const U2Region ®ion) {
715 GTUtilsSequenceView::selectSequenceRegion(os, region.startPos, region.endPos() - 1);
716 GTGlobals::sleep();
717
718 GTKeyboardUtils::copy();
719
720 const QString result = GTClipboard::text(os);
721
722 return result;
723 }
724 #undef GT_METHOD_NAME
725
726 #define GT_METHOD_NAME "clickOnDetView"
clickOnDetView(HI::GUITestOpStatus & os)727 void GTUtilsSequenceView::clickOnDetView(HI::GUITestOpStatus &os) {
728 MainWindow *mw = AppContext::getMainWindow();
729 GT_CHECK(mw != nullptr, "MainWindow == NULL");
730
731 MWMDIWindow *mdiWindow = mw->getMDIManager()->getActiveWindow();
732 GT_CHECK(mdiWindow != nullptr, "MDI window == NULL");
733
734 GTMouseDriver::moveTo(mdiWindow->mapToGlobal(mdiWindow->rect().center()));
735 GTMouseDriver::click();
736
737 GTGlobals::sleep(500);
738 }
739 #undef GT_METHOD_NAME
740
741 #define GT_METHOD_NAME "makeDetViewVisible"
makeDetViewVisible(HI::GUITestOpStatus & os)742 void GTUtilsSequenceView::makeDetViewVisible(HI::GUITestOpStatus &os) {
743 QToolButton *toggleDetViewButton = GTWidget::findToolButton(os, "show_hide_details_view");
744 if (!toggleDetViewButton->isChecked()) {
745 GTWidget::click(os, toggleDetViewButton);
746 }
747 }
748 #undef GT_METHOD_NAME
749
750 #undef GT_CLASS_NAME
751
752 } // namespace U2
753