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/GTMouseDriver.h>
23 #include <math.h>
24 #include <primitives/GTWidget.h>
25 #include <utils/GTThread.h>
26 
27 #include <QGraphicsItem>
28 
29 #include <U2Core/U2SafePoints.h>
30 
31 #include <U2View/GraphicsButtonItem.h>
32 #include <U2View/GraphicsRectangularBranchItem.h>
33 
34 #include "GTUtilsMdi.h"
35 #include "GTUtilsPhyTree.h"
36 
37 namespace U2 {
38 using namespace HI;
39 
40 #define GT_CLASS_NAME "GTUtilsPhyTree"
41 
42 #define GT_METHOD_NAME "getNodes"
getNodes(HI::GUITestOpStatus & os)43 QList<GraphicsButtonItem *> GTUtilsPhyTree::getNodes(HI::GUITestOpStatus &os) {
44     QList<GraphicsButtonItem *> result;
45     QGraphicsView *treeView = qobject_cast<QGraphicsView *>(GTWidget::findWidget(os, "treeView"));
46     GT_CHECK_RESULT(treeView, "treeView not found", result);
47     const QList<QGraphicsItem *> itemList = treeView->scene()->items();
48     for (QGraphicsItem *item : qAsConst(itemList)) {
49         auto nodeItem = dynamic_cast<GraphicsButtonItem *>(item);
50         if (nodeItem != nullptr) {
51             result.append(nodeItem);
52         }
53     }
54     return result;
55 }
56 #undef GT_METHOD_NAME
57 
58 #define GT_METHOD_NAME "getSelectedNodes"
getSelectedNodes(HI::GUITestOpStatus & os)59 QList<GraphicsButtonItem *> GTUtilsPhyTree::getSelectedNodes(HI::GUITestOpStatus &os) {
60     QList<GraphicsButtonItem *> nodes = getNodes(os);
61     QList<GraphicsButtonItem *> selectedNodes;
62     for (auto node : qAsConst(nodes)) {
63         if (node->isNodeSelected()) {
64             selectedNodes << node;
65         }
66     }
67     return selectedNodes;
68 }
69 #undef GT_METHOD_NAME
70 
71 #define GT_METHOD_NAME "getUnselectedNodes"
getUnselectedNodes(HI::GUITestOpStatus & os)72 QList<GraphicsButtonItem *> GTUtilsPhyTree::getUnselectedNodes(HI::GUITestOpStatus &os) {
73     QList<GraphicsButtonItem *> nodes = getNodes(os);
74     QList<GraphicsButtonItem *> unselectedNodes;
75     for (auto node : qAsConst(nodes)) {
76         if (node->isNodeSelected()) {
77             unselectedNodes << node;
78         }
79     }
80     return unselectedNodes;
81 }
82 #undef GT_METHOD_NAME
83 
84 #define GT_METHOD_NAME "getLabels"
getLabels(HI::GUITestOpStatus & os,QGraphicsView * treeView)85 QList<QGraphicsSimpleTextItem *> GTUtilsPhyTree::getLabels(HI::GUITestOpStatus &os, QGraphicsView *treeView) {
86     QList<QGraphicsSimpleTextItem *> result;
87     if (treeView == nullptr) {
88         treeView = qobject_cast<QGraphicsView *>(GTWidget::findWidget(os, "treeView"));
89     }
90     GT_CHECK_RESULT(treeView, "treeView not found", result);
91     QList<QGraphicsItem *> list = treeView->scene()->items();
92 
93     foreach (QGraphicsItem *item, list) {
94         QGraphicsSimpleTextItem *textItem = qgraphicsitem_cast<QGraphicsSimpleTextItem *>(item);
95         if (textItem) {
96             bool ok;
97             QString s = textItem->text();
98             s.toDouble(&ok);
99             if (!ok) {
100                 result << textItem;
101             }
102         }
103     }
104     return result;
105 }
106 #undef GT_METHOD_NAME
107 
getVisibleLabels(HI::GUITestOpStatus & os,QGraphicsView * treeView)108 QList<QGraphicsSimpleTextItem *> GTUtilsPhyTree::getVisibleLabels(HI::GUITestOpStatus &os, QGraphicsView *treeView) {
109     QList<QGraphicsSimpleTextItem *> result;
110     foreach (QGraphicsSimpleTextItem *item, getLabels(os, treeView)) {
111         if (item->isVisible() && !item->text().isEmpty()) {
112             result << item;
113         }
114     }
115     return result;
116 }
117 
118 #define GT_METHOD_NAME "getDistances"
getDistances(HI::GUITestOpStatus & os,QGraphicsView * treeView)119 QList<QGraphicsSimpleTextItem *> GTUtilsPhyTree::getDistances(HI::GUITestOpStatus &os, QGraphicsView *treeView) {
120     QList<QGraphicsSimpleTextItem *> result;
121     if (treeView == nullptr) {
122         treeView = qobject_cast<QGraphicsView *>(GTWidget::findWidget(os, "treeView"));
123     }
124     GT_CHECK_RESULT(treeView, "treeView not found", result);
125     QList<QGraphicsItem *> list = treeView->scene()->items();
126 
127     foreach (QGraphicsItem *item, list) {
128         QGraphicsSimpleTextItem *textItem = qgraphicsitem_cast<QGraphicsSimpleTextItem *>(item);
129         if (textItem) {
130             bool ok;
131             textItem->text().toDouble(&ok);
132             if (ok) {
133                 result << textItem;
134             }
135         }
136     }
137     return result;
138 }
139 #undef GT_METHOD_NAME
140 
141 #define GT_METHOD_NAME "getVisibleDistances"
getVisibleDistances(HI::GUITestOpStatus & os,QGraphicsView * treeView)142 QList<QGraphicsSimpleTextItem *> GTUtilsPhyTree::getVisibleDistances(HI::GUITestOpStatus &os, QGraphicsView *treeView) {
143     QList<QGraphicsSimpleTextItem *> result;
144     const QList<QGraphicsSimpleTextItem *> textItemList = getDistances(os, treeView);
145     for (QGraphicsSimpleTextItem *item : qAsConst(textItemList)) {
146         if (item->isVisible()) {
147             result << item;
148         }
149     }
150     return result;
151 }
152 #undef GT_METHOD_NAME
153 
154 #define GT_METHOD_NAME "getDistancesValues"
getDistancesValues(HI::GUITestOpStatus & os)155 QList<double> GTUtilsPhyTree::getDistancesValues(HI::GUITestOpStatus &os) {
156     QList<double> result;
157     QList<QGraphicsSimpleTextItem *> distList = getDistances(os);
158 
159     foreach (QGraphicsSimpleTextItem *item, distList) {
160         bool ok;
161         QString s = item->text();
162         double d = s.toDouble(&ok);
163         if (ok) {
164             result << d;
165         }
166     }
167 
168     return result;
169 }
170 #undef GT_METHOD_NAME
171 
172 #define GT_METHOD_NAME "getLabelsText"
getLabelsText(HI::GUITestOpStatus & os)173 QStringList GTUtilsPhyTree::getLabelsText(HI::GUITestOpStatus &os) {
174     QStringList result;
175     QList<QGraphicsSimpleTextItem *> labelList = getLabels(os);
176 
177     foreach (QGraphicsSimpleTextItem *item, labelList) {
178         result << item->text();
179     }
180 
181     return result;
182 }
183 #undef GT_METHOD_NAME
184 
185 #define GT_METHOD_NAME "getGlobalCenterCoord"
getGlobalCenterCoord(HI::GUITestOpStatus & os,QGraphicsItem * item)186 QPoint GTUtilsPhyTree::getGlobalCenterCoord(HI::GUITestOpStatus &os, QGraphicsItem *item) {
187     QGraphicsView *treeView = qobject_cast<QGraphicsView *>(GTWidget::findWidget(os, "treeView"));
188     GT_CHECK_RESULT(treeView, "treeView not found", QPoint());
189 
190     QPointF sceneCoord = item->mapToScene(item->boundingRect().topLeft());
191     QPoint viewCord = treeView->mapFromScene(sceneCoord);
192     QPoint globalCoord = treeView->mapToGlobal(viewCord);
193     globalCoord += QPoint(item->boundingRect().width() / 2, item->boundingRect().height() / 2);
194 
195     return globalCoord;
196 }
197 #undef GT_METHOD_NAME
198 
199 #define GT_METHOD_NAME "clickNode"
clickNode(HI::GUITestOpStatus & os,GraphicsButtonItem * node)200 void GTUtilsPhyTree::clickNode(HI::GUITestOpStatus &os, GraphicsButtonItem *node) {
201     GT_CHECK(node != nullptr, "Node to click is NULL");
202     node->ensureVisible();
203     GTThread::waitForMainThread();
204     GTMouseDriver::moveTo(getGlobalCenterCoord(os, node));
205     GTMouseDriver::click();
206 }
207 #undef GT_METHOD_NAME
208 
209 #define GT_METHOD_NAME "doubleClickNode"
doubleClickNode(HI::GUITestOpStatus & os,GraphicsButtonItem * node)210 void GTUtilsPhyTree::doubleClickNode(HI::GUITestOpStatus &os, GraphicsButtonItem *node) {
211     GT_CHECK(node != nullptr, "Node to doubleClickNode is NULL");
212     node->ensureVisible();
213     GTThread::waitForMainThread();
214     GTMouseDriver::moveTo(getGlobalCenterCoord(os, node));
215     GTMouseDriver::doubleClick();
216     GTThread::waitForMainThread();
217 }
218 #undef GT_METHOD_NAME
219 
220 #define GT_METHOD_NAME "getNodeDistance"
getNodeDistance(HI::GUITestOpStatus & os,GraphicsButtonItem * node)221 qreal GTUtilsPhyTree::getNodeDistance(HI::GUITestOpStatus &os, GraphicsButtonItem *node) {
222     GT_CHECK_RESULT(nullptr != node, "Node is NULL", 0);
223     GraphicsRectangularBranchItem *branch = dynamic_cast<GraphicsRectangularBranchItem *>(node->parentItem());
224     GT_CHECK_RESULT(nullptr != branch, "Node's branch' is NULL", 0);
225     return branch->getDist();
226 }
227 #undef GT_METHOD_NAME
228 
229 #define GT_METHOD_NAME "getTreeViewerUi"
getTreeViewerUi(HI::GUITestOpStatus & os)230 TreeViewerUI *GTUtilsPhyTree::getTreeViewerUi(HI::GUITestOpStatus &os) {
231     return GTWidget::findExactWidget<TreeViewerUI *>(os, "treeView", GTUtilsMdi::activeWindow(os));
232 }
233 #undef GT_METHOD_NAME
234 
235 #define GT_METHOD_NAME "getOrderedRectangularNodes"
getOrderedRectangularNodes(HI::GUITestOpStatus & os)236 QList<GraphicsButtonItem *> GTUtilsPhyTree::getOrderedRectangularNodes(HI::GUITestOpStatus &os) {
237     QList<GraphicsButtonItem *> orderedRectangularNodes;
238     QList<GraphicsRectangularBranchItem *> graphicsRectangularBranchItems = getOrderedRectangularBranches(os);
239     foreach (GraphicsRectangularBranchItem *rectangularBranch, graphicsRectangularBranchItems) {
240         GT_CHECK_RESULT(nullptr != rectangularBranch, "Rectangular branch is NULL", QList<GraphicsButtonItem *>());
241         GraphicsButtonItem *rectangularNode = rectangularBranch->getButton();
242         if (nullptr != rectangularNode) {
243             orderedRectangularNodes << rectangularNode;
244         }
245     }
246     return orderedRectangularNodes;
247 }
248 #undef GT_METHOD_NAME
249 
250 #define GT_METHOD_NAME "getOrderedRectangularBranches"
getOrderedRectangularBranches(HI::GUITestOpStatus & os)251 QList<GraphicsRectangularBranchItem *> GTUtilsPhyTree::getOrderedRectangularBranches(HI::GUITestOpStatus &os) {
252     return getSubtreeOrderedRectangularBranches(os, getRootRectangularBranch(os));
253 }
254 #undef GT_METHOD_NAME
255 
256 #define GT_METHOD_NAME "getRootRectangularNode"
getOrderedRectangularBranchesDistances(HI::GUITestOpStatus & os)257 QList<qreal> GTUtilsPhyTree::getOrderedRectangularBranchesDistances(HI::GUITestOpStatus &os) {
258     QList<GraphicsRectangularBranchItem *> orderedBranches = getOrderedRectangularBranches(os);
259     QList<qreal> orderedDistances;
260     foreach (GraphicsRectangularBranchItem *branch, orderedBranches) {
261         GT_CHECK_RESULT(nullptr != branch, "Branch is NULL", QList<qreal>());
262         orderedDistances << branch->getDist();
263     }
264     return orderedDistances;
265 }
266 #undef GT_METHOD_NAME
267 
268 #define GT_METHOD_NAME "getRootRectangularNode"
getRootRectangularNode(HI::GUITestOpStatus & os)269 GraphicsButtonItem *GTUtilsPhyTree::getRootRectangularNode(HI::GUITestOpStatus &os) {
270     GraphicsRectangularBranchItem *rootBranch = getRootRectangularBranch(os);
271     GT_CHECK_RESULT(nullptr != rootBranch, "Root branch is NULL", nullptr);
272     return rootBranch->getButton();
273 }
274 #undef GT_METHOD_NAME
275 
276 #define GT_METHOD_NAME "getRootRectangularBranch"
getRootRectangularBranch(HI::GUITestOpStatus & os)277 GraphicsRectangularBranchItem *GTUtilsPhyTree::getRootRectangularBranch(HI::GUITestOpStatus &os) {
278     TreeViewerUI *treeViewerUi = getTreeViewerUi(os);
279     GT_CHECK_RESULT(nullptr != treeViewerUi, "TreeViewerUI is NULL", nullptr);
280 
281     QList<QGraphicsItem *> items = treeViewerUi->scene()->items();
282     foreach (QGraphicsItem *item, items) {
283         GraphicsRectangularBranchItem *rectangularBranch = dynamic_cast<GraphicsRectangularBranchItem *>(item);
284         if (nullptr != rectangularBranch && nullptr == rectangularBranch->getParentItem()) {
285             return rectangularBranch;
286         }
287     }
288 
289     return nullptr;
290 }
291 #undef GT_METHOD_NAME
292 
293 #define GT_METHOD_NAME "getSubtreeOrderedRectangularBranches"
getSubtreeOrderedRectangularBranches(HI::GUITestOpStatus & os,GraphicsRectangularBranchItem * rootBranch)294 QList<GraphicsRectangularBranchItem *> GTUtilsPhyTree::getSubtreeOrderedRectangularBranches(HI::GUITestOpStatus &os, GraphicsRectangularBranchItem *rootBranch) {
295     GT_CHECK_RESULT(nullptr != rootBranch, "Subtree root branch is NULL", QList<GraphicsRectangularBranchItem *>());
296 
297     const QList<QGraphicsItem *> childItems = rootBranch->getChildItems();
298     QList<GraphicsRectangularBranchItem *> childRectangularBranches;
299     foreach (QGraphicsItem *childItem, childItems) {
300         GraphicsRectangularBranchItem *childRectangularBranch = dynamic_cast<GraphicsRectangularBranchItem *>(childItem);
301         if (nullptr != childRectangularBranch && nullptr != childRectangularBranch->getDistanceText()) {
302             childRectangularBranches << childRectangularBranch;
303         }
304     }
305 
306     std::sort(childRectangularBranches.begin(), childRectangularBranches.end(), rectangularBranchLessThan);
307 
308     QList<GraphicsRectangularBranchItem *> subtreeOrderedRectangularBranches;
309     foreach (GraphicsRectangularBranchItem *childRectangularBranch, childRectangularBranches) {
310         subtreeOrderedRectangularBranches << getSubtreeOrderedRectangularBranches(os, childRectangularBranch);
311     }
312     subtreeOrderedRectangularBranches << rootBranch;
313 
314     return subtreeOrderedRectangularBranches;
315 }
316 #undef GT_METHOD_NAME
317 
318 #define GT_METHOD_NAME "rectangularBranchLessThan"
rectangularBranchLessThan(GraphicsRectangularBranchItem * first,GraphicsRectangularBranchItem * second)319 bool GTUtilsPhyTree::rectangularBranchLessThan(GraphicsRectangularBranchItem *first, GraphicsRectangularBranchItem *second) {
320     SAFE_POINT(nullptr != first, "First rectangular branch item is NULL", true);
321     SAFE_POINT(nullptr != second, "Second rectangular branch item is NULL", false);
322 
323     if (first->getDirection() == second->getDirection()) {
324         if (first->getDirection() == GraphicsBranchItem::up) {
325             return first->getDist() < second->getDist();
326         } else {
327             return first->getDist() > second->getDist();
328         }
329     }
330 
331     return first->getDirection() > second->getDirection();
332 }
333 #undef GT_METHOD_NAME
334 
335 #undef GT_CLASS_NAME
336 
337 }  // namespace U2
338